Skip to content

Commit

Permalink
vp8enc: remove SVC-T layer framerate setting code
Browse files Browse the repository at this point in the history
Framerate are figured out by the fps of all layers, we no longer support
layer framerate settings now.
3 layer framerates are calculated as followings:
Layer 3 framerate is equal to the total fps.
Layer 2 framerate is the half of layer 3.
Layer 1 framerate is the half of layer 2.

Signed-off-by: wudping <[email protected]>
  • Loading branch information
dongpingx committed Jun 26, 2017
1 parent 6e94de4 commit f277137
Showing 1 changed file with 33 additions and 181 deletions.
214 changes: 33 additions & 181 deletions encoder/vaapiencoder_vp8.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ namespace YamiMediaCodec{
#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
{
public:
Expand Down Expand Up @@ -99,64 +106,30 @@ void Vp8EncoderNormal::getRefFlags(RefFlags& refFlags, uint8_t temporalLayer) co
}
class Vp8EncoderSvct : public Vp8Encoder {
public:
Vp8EncoderSvct(const VideoParamsCommon& common);

Vp8EncoderSvct(uint8_t layerNum)
: m_layerNum(layerNum % (VP8_MAX_TEMPORAL_LAYER_NUM + 1))
{
}
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 { return m_tempLayerIDs[frameNum % m_periodicity]; }
uint8_t getTemporalLayer(uint32_t frameNum) const;

private:
void printRatio();
void printLayerIDs();

bool calculateFramerateRatio();
bool calculatePeriodicity();
bool calculateLayerIDs();
uint32_t calculateGCD(uint32_t* gcdArray, uint32_t num);

VideoFrameRate m_framerates[VP8_MAX_TEMPORAL_LAYER_NUM];
uint32_t m_framerateRatio[VP8_MAX_TEMPORAL_LAYER_NUM];
uint32_t m_layerBitRate[VP8_MAX_TEMPORAL_LAYER_NUM];
uint32_t m_periodicity;
std::vector<uint32_t> m_tempLayerIDs;
uint8_t m_layerNum;
};



Vp8EncoderSvct::Vp8EncoderSvct(const VideoParamsCommon& common)
uint8_t Vp8EncoderSvct::getTemporalLayer(uint32_t frameNum) const
{
uint32_t gcd;
uint32_t i;
uint32_t layers = common.temporalLayers.numLayers;
assert(layers > 0 && layers < VP8_MAX_TEMPORAL_LAYER_NUM);
m_layerNum = layers + 1;
memset(m_layerBitRate, 0, sizeof(m_layerBitRate));
memset(m_framerateRatio, 0, sizeof(m_framerateRatio));
m_layerBitRate[0] = common.rcParams.bitRate;
m_framerates[0] = common.frameRate;
for (i = 1; i < m_layerNum; i++) {
m_framerates[i] = common.temporalLayers.frameRate[i - 1];
m_layerBitRate[i] = common.temporalLayers.bitRate[i - 1];
}
for (i = 0; i < m_layerNum; i++) {
gcd = std::__gcd(m_framerates[i].frameRateNum, m_framerates[i].frameRateDenom);
m_framerates[i].frameRateNum /= gcd;
m_framerates[i].frameRateDenom /= gcd;
}

calculatePeriodicity();
calculateLayerIDs();
printRatio();
printLayerIDs();
return VP8TempIds[m_layerNum - 1][frameNum % VP8_MIN_TEMPORAL_GOP];
}

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

void Vp8EncoderSvct::getRefFlags(RefFlags& refFlags, uint8_t temporalLayer) const
Expand All @@ -180,136 +153,6 @@ void Vp8EncoderSvct::getRefFlags(RefFlags& refFlags, uint8_t temporalLayer) cons
}
}

bool Vp8EncoderSvct::calculateFramerateRatio()
{
int32_t numerator;
//Reduct fractions to a common denominator, then get the numerators
//into m_framerateRatio.
for (uint8_t i = 0; i < m_layerNum; i++) {
numerator = 1;
for (uint8_t j = 0; j < m_layerNum; j++)
if (j != i)
numerator *= m_framerates[j].frameRateDenom;
else
numerator *= m_framerates[j].frameRateNum;
m_framerateRatio[i] = numerator;
}

//Divide m_framerateRatio by Greatest Common Divisor.
uint32_t gcd = calculateGCD(m_framerateRatio, m_layerNum);
if ((gcd != 0) && (gcd != 1))
for (uint8_t i = 0; i < m_layerNum; i++)
m_framerateRatio[i] /= gcd;

return true;
}

bool Vp8EncoderSvct::calculatePeriodicity()
{
if (!m_framerateRatio[0])
calculateFramerateRatio();

m_periodicity = m_framerateRatio[m_layerNum - 1];

return true;
}
bool Vp8EncoderSvct::calculateLayerIDs()
{
uint32_t layer = 0;
uint32_t m_frameNum[VP8_MAX_TEMPORAL_LAYER_NUM];
uint32_t m_frameNumAssigned[VP8_MAX_TEMPORAL_LAYER_NUM];

memset(m_frameNumAssigned, 0, sizeof(m_frameNumAssigned));
m_frameNum[0] = m_framerateRatio[0];
for (uint32_t i = 1; i < m_layerNum; i++)
m_frameNum[i] = m_framerateRatio[i] - m_framerateRatio[i - 1];

for (uint32_t i = 0; i < m_periodicity; i++)
for (layer = 0; layer < m_layerNum; layer++)
if (!(i % (m_periodicity / m_framerateRatio[layer])))
if (m_frameNumAssigned[layer] < m_frameNum[layer]) {
m_tempLayerIDs.push_back(layer);
m_frameNumAssigned[layer]++;
break;
}

return true;
}

//GCD: Greatest Common Divisor;
//return:
// 0: failure;
// else: successful;
uint32_t Vp8EncoderSvct::calculateGCD(uint32_t* gcdArray, uint32_t num)
{
if (!gcdArray || !num)
return 0;
std::vector<uint32_t> gcdVector;
uint32_t gcdNotTheSame = 0;
uint32_t min = 0;

//copy gcdArray, and find out the min of gcdArray.
gcdVector.push_back(gcdArray[0]);
min = gcdVector[0];
for (uint8_t i = 1; i < num; i++) {
gcdVector.push_back(gcdArray[i]);
if (min > gcdVector[i])
min = gcdVector[i];
}
//if gcdArray contains 0, would fail;
if (!min)
return min;

//if the GCDs(greatest common divisor) of min and each element in gcdVector
//are the same, we get the GCD.
while (min != 1) {
gcdNotTheSame = 0;
for (uint8_t i = 0; i < num; i++) {
//calculate the GCD of min and gcdVector[i], and refresh gcdTemp[i]
//with the new GCD.
gcdVector[i] = std::__gcd(min, gcdVector[i]);
if (i > 1)
if (gcdVector[i] != gcdVector[i - 1])
gcdNotTheSame = 1;
if (min > gcdVector[i])
min = gcdVector[i];
}
if (!gcdNotTheSame)
break;
}

return min;
}

void Vp8EncoderSvct::printRatio()
{
DEBUG("ratio: \n");
for (uint8_t i = 0; i < m_layerNum; i++) {
if (i != 0)
DEBUG(" : ");
DEBUG("%d", m_framerateRatio[i]);
}
DEBUG("\n");

return;
}

void Vp8EncoderSvct::printLayerIDs()
{
DEBUG("LayerIDs: \n");
DEBUG(" frame number: ");
for (uint8_t i = 0; i < m_periodicity; i++) {
DEBUG("%2d ", i);
}
DEBUG("\n");
DEBUG("frame layerid: ");
for (uint8_t i = 0; i < m_periodicity; i++) {
DEBUG("%2d ", m_tempLayerIDs[i]);
}
DEBUG("\n");

return;
}
VaapiEncoderVP8::VaapiEncoderVP8():
m_frameCount(0),
m_qIndex(VP8_DEFAULT_QP)
Expand Down Expand Up @@ -339,11 +182,20 @@ YamiStatus VaapiEncoderVP8::getMaxOutSize(uint32_t* maxSize)

void VaapiEncoderVP8::resetParams()
{
uint8_t layerNum;
m_maxCodedbufSize = width() * height() * 3 / 2 + VP8_HEADER_MAX_SIZE;
if (ipPeriod() == 0)
m_videoParamCommon.intraPeriod = 1;
if (m_videoParamCommon.temporalLayers.numLayers > 0) {
m_encoder.reset(new Vp8EncoderSvct(m_videoParamCommon));

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

if (layerNum > 0) {
m_encoder.reset(new Vp8EncoderSvct(layerNum));
} else {
m_encoder.reset(new Vp8EncoderNormal());
}
Expand Down Expand Up @@ -586,12 +438,9 @@ bool VaapiEncoderVP8::referenceListUpdate (const PicturePtr& pic, const SurfaceP
/* Generates additional control parameters */
bool VaapiEncoderVP8::ensureMiscParams(VaapiEncPicture* picture)
{
if (!VaapiEncoderBase::ensureMiscParams(picture))
return false;

VideoRateControl mode = rateControlMode();
if (mode == RATE_CONTROL_CBR || mode == RATE_CONTROL_VBR) {
if (m_videoParamCommon.temporalLayers.numLayers > 0) {
if (m_videoParamCommon.temporalLayers.length > 0) {
VAEncMiscParameterTemporalLayerStructure* layerParam = NULL;
if (!picture->newMisc(VAEncMiscParameterTypeTemporalLayerStructure,
layerParam))
Expand All @@ -600,13 +449,16 @@ bool VaapiEncoderVP8::ensureMiscParams(VaapiEncPicture* picture)
std::vector<uint32_t> ids;
m_encoder->getLayerIds(ids);
if (layerParam) {
layerParam->number_of_layers = m_videoParamCommon.temporalLayers.numLayers + 1;
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;
}

Expand Down

0 comments on commit f277137

Please sign in to comment.