Skip to content

Commit

Permalink
vp8enc: add svct encoder
Browse files Browse the repository at this point in the history
the getLayerIds logical is complicate, we can revisit it later

Signed-off-by: wudping <[email protected]>
Signed-off-by: Xu Guangxin <[email protected]>
  • Loading branch information
xuguangxin authored and dongpingx committed Jun 27, 2017
1 parent 4bd50a1 commit 1efcabf
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 2 deletions.
110 changes: 108 additions & 2 deletions encoder/vaapiencoder_vp8.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ namespace YamiMediaCodec{
//golden, alter, last
#define MAX_REFERECNE_FRAME 3
#define VP8_DEFAULT_QP 40
#define VP8_MAX_TEMPORAL_LAYER_NUM 3

#define VP8_MIN_TEMPORAL_GOP 4

static uint32_t VP8TempIds[VP8_MAX_TEMPORAL_LAYER_NUM][VP8_MIN_TEMPORAL_GOP]
= { { 0, 0, 0, 0 },
{ 0, 1, 0, 1 },
{ 0, 2, 1, 2 } };

class VaapiEncPictureVP8 : public VaapiEncPicture
{
Expand Down Expand Up @@ -61,6 +69,8 @@ struct RefFlags
uint32_t no_ref_last : 1;
uint32_t no_ref_gf : 1;
uint32_t no_ref_arf : 1;
uint32_t first_ref : 2;
uint32_t second_ref : 2;

RefFlags()
{
Expand Down Expand Up @@ -96,6 +106,59 @@ void Vp8EncoderNormal::getRefFlags(RefFlags& refFlags, uint8_t temporalLayer) co
refFlags.copy_buffer_to_alternate = 2;

}
class Vp8EncoderSvct : public Vp8Encoder {
public:
Vp8EncoderSvct(uint8_t layerIndex)
: m_layerIndex(layerIndex % VP8_MAX_TEMPORAL_LAYER_NUM)
{
}
void getRefFlags(RefFlags&, uint8_t temporalLayer) const;
void getLayerIds(std::vector<uint32_t>& ids) const;

bool getErrorResilient() const { return true; }
bool getRefreshEntropyProbs() const { return false; }
uint8_t getTemporalLayer(uint32_t frameNum) const;

private:
uint8_t m_layerIndex;
};

uint8_t Vp8EncoderSvct::getTemporalLayer(uint32_t frameNum) const
{
return VP8TempIds[m_layerIndex][frameNum % VP8_MIN_TEMPORAL_GOP];
}

void Vp8EncoderSvct::getLayerIds(std::vector<uint32_t>& ids) const
{
for (uint32_t i = 0; i < VP8_MIN_TEMPORAL_GOP; i++)
ids.push_back(VP8TempIds[m_layerIndex][i]);
}

void Vp8EncoderSvct::getRefFlags(RefFlags& refFlags, uint8_t temporalLayer) const
{
switch (temporalLayer) {
case 2:
refFlags.refresh_alternate_frame = 1;
break;
case 1:
refFlags.refresh_golden_frame = 1;
refFlags.no_ref_arf = 1;
//GoldRef is searched second.
refFlags.second_ref = 0x02;
break;
case 0:
refFlags.refresh_last = 1;
refFlags.no_ref_gf = 1;
refFlags.no_ref_arf = 1;
break;
default:
ERROR("temporal layer %d is out of the range[0, 2].", temporalLayer);
break;
}
//LastRef is searched first.
refFlags.first_ref = 0x01;
}

VaapiEncoderVP8::VaapiEncoderVP8():
m_frameCount(0),
m_qIndex(VP8_DEFAULT_QP)
Expand Down Expand Up @@ -128,7 +191,20 @@ void VaapiEncoderVP8::resetParams()
m_maxCodedbufSize = width() * height() * 3 / 2 + VP8_HEADER_MAX_SIZE;
if (ipPeriod() == 0)
m_videoParamCommon.intraPeriod = 1;
m_encoder.reset(new Vp8EncoderNormal());

uint8_t layerIndex = m_videoParamCommon.temporalLayers.length;
for (uint32_t i = 0; i < layerIndex; i++) {
uint32_t expTemId = (1 << (layerIndex - i));
m_svctFrameRate[i].frameRateDenom = expTemId;
m_svctFrameRate[i].frameRateNum = fps();
}

if (layerIndex > 0) {
m_encoder.reset(new Vp8EncoderSvct(layerIndex));
}
else {
m_encoder.reset(new Vp8EncoderNormal());
}
}

YamiStatus VaapiEncoderVP8::start()
Expand Down Expand Up @@ -192,6 +268,7 @@ YamiStatus VaapiEncoderVP8::doEncode(const SurfacePtr& surface, uint64_t timeSta
else
picture->m_type = VAAPI_PICTURE_P;

picture->m_temporalID = m_encoder->getTemporalLayer(m_frameCount % keyFramePeriod());
m_frameCount++;

m_qIndex = (initQP() > minQP() && initQP() < maxQP()) ? initQP() : VP8_DEFAULT_QP;
Expand Down Expand Up @@ -234,6 +311,8 @@ void VaapiEncoderVP8::fill(VAEncPictureParameterBufferVP8* picParam, const RefFl
picParam->ref_flags.bits.no_ref_last = refFlags.no_ref_last;
picParam->ref_flags.bits.no_ref_gf = refFlags.no_ref_gf;
picParam->ref_flags.bits.no_ref_arf = refFlags.no_ref_arf;
picParam->ref_flags.bits.first_ref = refFlags.first_ref;
picParam->ref_flags.bits.second_ref = refFlags.second_ref;
}
/* Fills in VA picture parameter buffer */
bool VaapiEncoderVP8::fill(VAEncPictureParameterBufferVP8* picParam, const PicturePtr& picture,
Expand All @@ -246,7 +325,7 @@ bool VaapiEncoderVP8::fill(VAEncPictureParameterBufferVP8* picParam, const Pictu
picParam->ref_gf_frame = m_golden->getID();
picParam->ref_last_frame = m_last->getID();

m_encoder->getRefFlags(refFlags, 0);
m_encoder->getRefFlags(refFlags, picture->m_temporalID);
fill(picParam, refFlags);
} else {
picParam->ref_last_frame = VA_INVALID_SURFACE;
Expand All @@ -255,6 +334,7 @@ bool VaapiEncoderVP8::fill(VAEncPictureParameterBufferVP8* picParam, const Pictu
}

picParam->coded_buf = picture->getCodedBufferID();
//picParam->ref_flags.bits.temporal_id = picture->m_temporalID;

picParam->pic_flags.bits.show_frame = 1;
/*TODO: multi partition*/
Expand Down Expand Up @@ -363,6 +443,32 @@ bool VaapiEncoderVP8::referenceListUpdate (const PicturePtr& pic, const SurfaceP
}
return true;
}
/* Generates additional control parameters */
bool VaapiEncoderVP8::ensureMiscParams(VaapiEncPicture* picture)
{
VideoRateControl mode = rateControlMode();
if (mode == RATE_CONTROL_CBR || mode == RATE_CONTROL_VBR) {
if (m_videoParamCommon.temporalLayers.length > 0) {
VAEncMiscParameterTemporalLayerStructure* layerParam = NULL;
if (!picture->newMisc(VAEncMiscParameterTypeTemporalLayerStructure,
layerParam))
return false;

std::vector<uint32_t> ids;
m_encoder->getLayerIds(ids);
if (layerParam) {
layerParam->number_of_layers = m_videoParamCommon.temporalLayers.length + 1;
layerParam->periodicity = ids.size();
std::copy(ids.begin(), ids.end(), layerParam->layer_id);
}
}
}

if (!VaapiEncoderBase::ensureMiscParams(picture))
return false;

return true;
}

YamiStatus VaapiEncoderVP8::encodePicture(const PicturePtr& picture)
{
Expand Down
1 change: 1 addition & 0 deletions encoder/vaapiencoder_vp8.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class VaapiEncoderVP8 : public VaapiEncoderBase {

protected:
virtual YamiStatus doEncode(const SurfacePtr&, uint64_t timeStamp, bool forceKeyFrame = false);
virtual bool ensureMiscParams(VaapiEncPicture*);

private:
friend class FactoryTest<IVideoEncoder, VaapiEncoderVP8>;
Expand Down

0 comments on commit 1efcabf

Please sign in to comment.