Newer
Older

Karsten Suehring
committed
const ComponentID ch=ComponentID(chan);
CHECK(!(acPicRecFields[0].get(ch).width==acPicRecFields[1].get(ch).width), "Unspecified error");
CHECK(!(acPicRecFields[0].get(ch).height==acPicRecFields[0].get(ch).height), "Unspecified error");
uint64_t uiSSDtemp=0;
const uint32_t width = acPicRecFields[0].get(ch).width - (m_pcEncLib->getPad(0) >> ::getComponentScaleX(ch, format));
const uint32_t height = acPicRecFields[0].get(ch).height - ((m_pcEncLib->getPad(1) >> 1) >> ::getComponentScaleY(ch, format));
const uint32_t bitDepth = sps.getBitDepth(toChannelType(ch));
for(uint32_t fieldNum=0; fieldNum<2; fieldNum++)
{
CHECK(!(conversion == IPCOLOURSPACE_UNCHANGED), "Unspecified error");
#if ENABLE_QPA
Yang Wang
committed
uiSSDtemp += xFindDistortionPlane( acPicRecFields[fieldNum].get(ch), apcPicOrgFields[fieldNum]->getOrigBuf().get(ch), useWPSNR ? bitDepth : 0, ::getComponentScaleX(ch, format), ::getComponentScaleY(ch, format) );

Karsten Suehring
committed
#else
uiSSDtemp += xFindDistortionPlane( acPicRecFields[fieldNum].get(ch), apcPicOrgFields[fieldNum]->getOrigBuf().get(ch), 0 );
#endif
}
const uint32_t maxval = 255 << (bitDepth - 8);
const uint32_t size = width * height * 2;
const double fRefValue = (double)maxval * maxval * size;
dPSNR[ch] = uiSSDtemp ? 10.0 * log10(fRefValue / (double)uiSSDtemp) : 999.99;
MSEyuvframe[ch] = (double)uiSSDtemp / size;
}
uint32_t uibits = 0; // the number of bits for the pair is not calculated here - instead the overall total is used elsewhere.
//===== add PSNR =====
m_gcAnalyzeAll_in.addResult (dPSNR, (double)uibits, MSEyuvframe
, MSEyuvframe
, isEncodeLtRef
);

Karsten Suehring
committed
*PSNR_Y = dPSNR[COMPONENT_Y];
msg( INFO, "\n Interlaced frame %d: [Y %6.4lf dB U %6.4lf dB V %6.4lf dB]", pcPicOrgSecondField->getPOC()/2, dPSNR[COMPONENT_Y], dPSNR[COMPONENT_Cb], dPSNR[COMPONENT_Cr] );

Karsten Suehring
committed
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
if (printFrameMSE)
{
msg( DETAILS, " [Y MSE %6.4lf U MSE %6.4lf V MSE %6.4lf]", MSEyuvframe[COMPONENT_Y], MSEyuvframe[COMPONENT_Cb], MSEyuvframe[COMPONENT_Cr] );
}
for(uint32_t fieldNum=0; fieldNum<2; fieldNum++)
{
cscd[fieldNum].destroy();
}
}
/** Function for deciding the nal_unit_type.
* \param pocCurr POC of the current picture
* \param lastIDR POC of the last IDR picture
* \param isField true to indicate field coding
* \returns the NAL unit type of the picture
* This function checks the configuration and returns the appropriate nal_unit_type for the picture.
*/
NalUnitType EncGOP::getNalUnitType(int pocCurr, int lastIDR, bool isField)
{
if (pocCurr == 0)
{
return NAL_UNIT_CODED_SLICE_IDR_N_LP;

Karsten Suehring
committed
}
if (m_pcCfg->getEfficientFieldIRAPEnabled() && isField && pocCurr == (m_pcCfg->getUseCompositeRef() ? 2: 1))

Karsten Suehring
committed
{
// to avoid the picture becoming an IRAP

Karsten Suehring
committed
}
if (m_pcCfg->getDecodingRefreshType() != 3 && (pocCurr - isField) % (m_pcCfg->getIntraPeriod() * (m_pcCfg->getUseCompositeRef() ? 2 : 1)) == 0)

Karsten Suehring
committed
{
if (m_pcCfg->getDecodingRefreshType() == 1)
{
return NAL_UNIT_CODED_SLICE_CRA;
}
else if (m_pcCfg->getDecodingRefreshType() == 2)
{
return NAL_UNIT_CODED_SLICE_IDR_W_RADL;
}
}
if(m_pocCRA>0)
{
if(pocCurr<m_pocCRA)
{
// All leading pictures are being marked as TFD pictures here since current encoder uses all
// reference pictures while encoding leading pictures. An encoder can ensure that a leading
// picture can be still decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by
// controlling the reference pictures used for encoding that leading picture. Such a leading
// picture need not be marked as a TFD picture.

Karsten Suehring
committed
}
}
if (lastIDR>0)
{
if (pocCurr < lastIDR)
{

Karsten Suehring
committed
}
}

Karsten Suehring
committed
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
}
void EncGOP::xUpdateRasInit(Slice* slice)
{
slice->setPendingRasInit( false );
if ( slice->getPOC() > m_lastRasPoc )
{
m_lastRasPoc = MAX_INT;
slice->setPendingRasInit( true );
}
if ( slice->isIRAP() )
{
m_lastRasPoc = slice->getPOC();
}
}
double EncGOP::xCalculateRVM()
{
double dRVM = 0;
if( m_pcCfg->getGOPSize() == 1 && m_pcCfg->getIntraPeriod() != 1 && m_pcCfg->getFramesToBeEncoded() > RVM_VCEGAM10_M * 2 )
{
// calculate RVM only for lowdelay configurations
std::vector<double> vRL , vB;
size_t N = m_vRVM_RP.size();
vRL.resize( N );
vB.resize( N );
int i;
double dRavg = 0 , dBavg = 0;
vB[RVM_VCEGAM10_M] = 0;
for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ )
{
vRL[i] = 0;
for( int j = i - RVM_VCEGAM10_M ; j <= i + RVM_VCEGAM10_M - 1 ; j++ )
{
vRL[i] += m_vRVM_RP[j];
}
vRL[i] /= ( 2 * RVM_VCEGAM10_M );
vB[i] = vB[i-1] + m_vRVM_RP[i] - vRL[i];
dRavg += m_vRVM_RP[i];
dBavg += vB[i];
}
dRavg /= ( N - 2 * RVM_VCEGAM10_M );
dBavg /= ( N - 2 * RVM_VCEGAM10_M );
double dSigamB = 0;
for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ )
{
double tmp = vB[i] - dBavg;
dSigamB += tmp * tmp;
}
dSigamB = sqrt( dSigamB / ( N - 2 * RVM_VCEGAM10_M ) );
double f = sqrt( 12.0 * ( RVM_VCEGAM10_M - 1 ) / ( RVM_VCEGAM10_M + 1 ) );
dRVM = dSigamB / dRavg * f;
}
return( dRVM );
}
/** Attaches the input bitstream to the stream in the output NAL unit
Updates rNalu to contain concatenated bitstream. rpcBitstreamRedirect is cleared at the end of this function call.
* \param codedSliceData contains the coded slice data (bitstream) to be concatenated to rNalu
* \param rNalu target NAL unit
*/
void EncGOP::xAttachSliceDataToNalUnit (OutputNALUnit& rNalu, OutputBitstream* codedSliceData)
{
// Byte-align
rNalu.m_Bitstream.writeByteAlignment(); // Slice header byte-alignment
// Perform bitstream concatenation
if (codedSliceData->getNumberOfWrittenBits() > 0)
{
rNalu.m_Bitstream.addSubstream(codedSliceData);
}
codedSliceData->clear();
}
void EncGOP::arrangeCompositeReference(Slice* pcSlice, PicList& rcListPic, int pocCurr)
{
Picture* curPic = NULL;
PicList::iterator iterPic = rcListPic.begin();
const PreCalcValues *pcv = pcSlice->getPPS()->pcv;
m_bgPOC = pocCurr + 1;
if (m_picBg->getSpliceFull())
{
return;
}
while (iterPic != rcListPic.end())
{
curPic = *(iterPic++);
if (curPic->getPOC() == pocCurr)
{
break;
}
}
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
{
return;
}
int width = pcv->lumaWidth;
int height = pcv->lumaHeight;
int stride = curPic->getOrigBuf().get(COMPONENT_Y).stride;
int cStride = curPic->getOrigBuf().get(COMPONENT_Cb).stride;
Pel* curLumaAddr = curPic->getOrigBuf().get(COMPONENT_Y).buf;
Pel* curCbAddr = curPic->getOrigBuf().get(COMPONENT_Cb).buf;
Pel* curCrAddr = curPic->getOrigBuf().get(COMPONENT_Cr).buf;
Pel* bgOrgLumaAddr = m_picOrig->getOrigBuf().get(COMPONENT_Y).buf;
Pel* bgOrgCbAddr = m_picOrig->getOrigBuf().get(COMPONENT_Cb).buf;
Pel* bgOrgCrAddr = m_picOrig->getOrigBuf().get(COMPONENT_Cr).buf;
int cuMaxWidth = pcv->maxCUWidth;
int cuMaxHeight = pcv->maxCUHeight;
int maxReplace = (pcv->sizeInCtus) / 2;
maxReplace = maxReplace < 1 ? 1 : maxReplace;
typedef struct tagCostStr
{
double cost;
int ctuIdx;
}CostStr;
CostStr* minCtuCost = new CostStr[maxReplace];
for (int i = 0; i < maxReplace; i++)
{
minCtuCost[i].cost = 1e10;
minCtuCost[i].ctuIdx = -1;
}
int bitIncrementY = pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 8;
int bitIncrementUV = pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA) - 8;
for (int y = 0; y < height; y += cuMaxHeight)
{
for (int x = 0; x < width; x += cuMaxWidth)
{
double lcuDist = 0.0;
double lcuDistCb = 0.0;
double lcuDistCr = 0.0;
int realPixelCnt = 0;
double lcuCost = 1e10;
int largeDist = 0;
for (int tmpy = 0; tmpy < cuMaxHeight; tmpy++)
{
if (y + tmpy >= height)
{
break;
}
for (int tmpx = 0; tmpx < cuMaxWidth; tmpx++)
{
if (x + tmpx >= width)
{
break;
}
realPixelCnt++;
lcuDist += abs(curLumaAddr[(y + tmpy)*stride + x + tmpx] - bgOrgLumaAddr[(y + tmpy)*stride + x + tmpx]);
if (abs(curLumaAddr[(y + tmpy)*stride + x + tmpx] - bgOrgLumaAddr[(y + tmpy)*stride + x + tmpx]) >(20 << bitIncrementY))
{
largeDist++;
}
if (tmpy % 2 == 0 && tmpx % 2 == 0)
{
lcuDistCb += abs(curCbAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2] - bgOrgCbAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2]);
lcuDistCr += abs(curCrAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2] - bgOrgCrAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2]);
}
}
}
//Test the vertical or horizontal edge for background patches candidates
int yInLCU = y / cuMaxHeight;
int xInLCU = x / cuMaxWidth;
int iLCUIdx = yInLCU * pcv->widthInCtus + xInLCU;
if ((largeDist / (double)realPixelCnt < 0.01 &&lcuDist / realPixelCnt < (3.5 * (1 << bitIncrementY)) && lcuDistCb / realPixelCnt < (0.5 * (1 << bitIncrementUV)) && lcuDistCr / realPixelCnt < (0.5 * (1 << bitIncrementUV)) && m_picBg->getSpliceIdx(iLCUIdx) == 0))
{
lcuCost = lcuDist / realPixelCnt + lcuDistCb / realPixelCnt + lcuDistCr / realPixelCnt;
//obtain the maxReplace smallest cost
//1) find the largest cost in the maxReplace candidates
for (int i = 0; i < maxReplace - 1; i++)
{
if (minCtuCost[i].cost > minCtuCost[i + 1].cost)
{
swap(minCtuCost[i].cost, minCtuCost[i + 1].cost);
swap(minCtuCost[i].ctuIdx, minCtuCost[i + 1].ctuIdx);
}
}
// 2) compare the current cost with the largest cost
if (lcuCost < minCtuCost[maxReplace - 1].cost)
{
minCtuCost[maxReplace - 1].cost = lcuCost;
minCtuCost[maxReplace - 1].ctuIdx = iLCUIdx;
}
}
}
}
// modify QP for background CTU
{
for (int i = 0; i < maxReplace; i++)
{
if (minCtuCost[i].ctuIdx != -1)
{
m_picBg->setSpliceIdx(minCtuCost[i].ctuIdx, pocCurr);
}
}
}
delete[]minCtuCost;
}
void EncGOP::updateCompositeReference(Slice* pcSlice, PicList& rcListPic, int pocCurr)
{
Picture* curPic = NULL;
const PreCalcValues *pcv = pcSlice->getPPS()->pcv;
PicList::iterator iterPic = rcListPic.begin();
iterPic = rcListPic.begin();
while (iterPic != rcListPic.end())
{
curPic = *(iterPic++);
if (curPic->getPOC() == pocCurr)
{
break;
}
}
assert(curPic->getPOC() == pocCurr);
int width = pcv->lumaWidth;
int height = pcv->lumaHeight;
int stride = curPic->getRecoBuf().get(COMPONENT_Y).stride;
int cStride = curPic->getRecoBuf().get(COMPONENT_Cb).stride;
Pel* bgLumaAddr = m_picBg->getRecoBuf().get(COMPONENT_Y).buf;
Pel* bgCbAddr = m_picBg->getRecoBuf().get(COMPONENT_Cb).buf;
Pel* bgCrAddr = m_picBg->getRecoBuf().get(COMPONENT_Cr).buf;
Pel* curLumaAddr = curPic->getRecoBuf().get(COMPONENT_Y).buf;
Pel* curCbAddr = curPic->getRecoBuf().get(COMPONENT_Cb).buf;
Pel* curCrAddr = curPic->getRecoBuf().get(COMPONENT_Cr).buf;
int maxCuWidth = pcv->maxCUWidth;
int maxCuHeight = pcv->maxCUHeight;
// Update background reference
if (pcSlice->isIRAP())//(pocCurr == 0)
curPic->extendPicBorder( pcSlice->getPPS() );
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
curPic->setBorderExtension(true);
m_picBg->getRecoBuf().copyFrom(curPic->getRecoBuf());
m_picOrig->getOrigBuf().copyFrom(curPic->getOrigBuf());
}
else
{
//cout << "update B" << pocCurr << endl;
for (int y = 0; y < height; y += maxCuHeight)
{
for (int x = 0; x < width; x += maxCuWidth)
{
if (m_picBg->getSpliceIdx((y / maxCuHeight)*pcv->widthInCtus + x / maxCuWidth) == pocCurr)
{
for (int tmpy = 0; tmpy < maxCuHeight; tmpy++)
{
if (y + tmpy >= height)
{
break;
}
for (int tmpx = 0; tmpx < maxCuWidth; tmpx++)
{
if (x + tmpx >= width)
{
break;
}
bgLumaAddr[(y + tmpy)*stride + x + tmpx] = curLumaAddr[(y + tmpy)*stride + x + tmpx];
if (tmpy % 2 == 0 && tmpx % 2 == 0)
{
bgCbAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2] = curCbAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2];
bgCrAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2] = curCrAddr[(y + tmpy) / 2 * cStride + (x + tmpx) / 2];
}
}
}
}
}
}
m_picBg->setBorderExtension(false);
m_picBg->extendPicBorder( pcSlice->getPPS() );
m_picBg->setBorderExtension(true);
curPic->extendPicBorder( pcSlice->getPPS() );
curPic->setBorderExtension(true);
m_picOrig->getOrigBuf().copyFrom(curPic->getOrigBuf());
m_picBg->setBorderExtension(false);
m_picBg->extendPicBorder( pcSlice->getPPS() );
m_picBg->setBorderExtension(true);
}
}

Karsten Suehring
committed
void EncGOP::applyDeblockingFilterMetric( Picture* pcPic, uint32_t uiNumSlices )
{
PelBuf cPelBuf = pcPic->getRecoBuf().get( COMPONENT_Y );
Pel* Rec = cPelBuf.buf;
const int stride = cPelBuf.stride;
const uint32_t picWidth = cPelBuf.width;
const uint32_t picHeight = cPelBuf.height;
Pel* tempRec = Rec;
const Slice* pcSlice = pcPic->slices[0];
const uint32_t log2maxTB = pcSlice->getSPS()->getLog2MaxTbSize();
const uint32_t maxTBsize = (1<<log2maxTB);

Karsten Suehring
committed
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
const uint32_t minBlockArtSize = 8;
const uint32_t noCol = (picWidth>>log2maxTB);
const uint32_t noRows = (picHeight>>log2maxTB);
CHECK(!(noCol > 1), "Unspecified error");
CHECK(!(noRows > 1), "Unspecified error");
std::vector<uint64_t> colSAD(noCol, uint64_t(0));
std::vector<uint64_t> rowSAD(noRows, uint64_t(0));
uint32_t colIdx = 0;
uint32_t rowIdx = 0;
Pel p0, p1, p2, q0, q1, q2;
int qp = pcSlice->getSliceQp();
const int bitDepthLuma=pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
int bitdepthScale = 1 << (bitDepthLuma-8);
int beta = LoopFilter::getBeta( qp ) * bitdepthScale;
const int thr2 = (beta>>2);
const int thr1 = 2*bitdepthScale;
uint32_t a = 0;
if (maxTBsize > minBlockArtSize)
{
// Analyze vertical artifact edges
for(int c = maxTBsize; c < picWidth; c += maxTBsize)
{
for(int r = 0; r < picHeight; r++)
{
p2 = Rec[c-3];
p1 = Rec[c-2];
p0 = Rec[c-1];
q0 = Rec[c];
q1 = Rec[c+1];
q2 = Rec[c+2];
a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1);
if ( thr1 < a && a < thr2)
{
colSAD[colIdx] += abs(p0 - q0);
}
Rec += stride;
}
colIdx++;
Rec = tempRec;
}
// Analyze horizontal artifact edges
for(int r = maxTBsize; r < picHeight; r += maxTBsize)
{
for(int c = 0; c < picWidth; c++)
{
p2 = Rec[c + (r-3)*stride];
p1 = Rec[c + (r-2)*stride];
p0 = Rec[c + (r-1)*stride];
q0 = Rec[c + r*stride];
q1 = Rec[c + (r+1)*stride];
q2 = Rec[c + (r+2)*stride];
a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1);
if (thr1 < a && a < thr2)
{
rowSAD[rowIdx] += abs(p0 - q0);
}
}
rowIdx++;
}
}
uint64_t colSADsum = 0;
uint64_t rowSADsum = 0;
for(int c = 0; c < noCol-1; c++)
{
colSADsum += colSAD[c];
}
for(int r = 0; r < noRows-1; r++)
{
rowSADsum += rowSAD[r];
}
colSADsum <<= 10;
rowSADsum <<= 10;
colSADsum /= (noCol-1);
colSADsum /= picHeight;
rowSADsum /= (noRows-1);
rowSADsum /= picWidth;
uint64_t avgSAD = ((colSADsum + rowSADsum)>>1);
avgSAD >>= (bitDepthLuma-8);
if ( avgSAD > 2048 )
{
avgSAD >>= 9;
int offset = Clip3(2,6,(int)avgSAD);
for (int i=0; i<uiNumSlices; i++)
{
Slice* pcLocalSlice = pcPic->slices[i];
pcLocalSlice->setDeblockingFilterOverrideFlag ( true);
pcLocalSlice->setDeblockingFilterDisable ( false);
pcLocalSlice->setDeblockingFilterBetaOffsetDiv2 ( offset );
pcLocalSlice->setDeblockingFilterTcOffsetDiv2 ( offset );
pcLocalSlice->setDeblockingFilterCbBetaOffsetDiv2 ( offset );
pcLocalSlice->setDeblockingFilterCbTcOffsetDiv2 ( offset );
pcLocalSlice->setDeblockingFilterCrBetaOffsetDiv2 ( offset );
pcLocalSlice->setDeblockingFilterCrTcOffsetDiv2 ( offset );

Karsten Suehring
committed
}
}
else
{
for (int i=0; i<uiNumSlices; i++)
{
Slice* pcLocalSlice = pcPic->slices[i];
const PPS* pcPPS = pcSlice->getPPS();
pcLocalSlice->setDeblockingFilterOverrideFlag ( false);
pcLocalSlice->setDeblockingFilterDisable ( pcPPS->getPPSDeblockingFilterDisabledFlag() );
#if DB_PARAM_TID
int betaIdx = Clip3(0, (int)pcPPS->getDeblockingFilterBetaOffsetDiv2().size() - 1, (int)pcLocalSlice->getTLayer() + (pcLocalSlice->isIntra() ? 0 : 1));
int tcIdx = Clip3(0, (int)pcPPS->getDeblockingFilterTcOffsetDiv2().size() - 1, (int)pcLocalSlice->getTLayer() + (pcLocalSlice->isIntra() ? 0 : 1));
pcLocalSlice->setDeblockingFilterBetaOffsetDiv2( pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx] );
pcLocalSlice->setDeblockingFilterTcOffsetDiv2 ( pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx] );
pcLocalSlice->setDeblockingFilterCbBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcLocalSlice->setDeblockingFilterCbTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
pcLocalSlice->setDeblockingFilterCrBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcLocalSlice->setDeblockingFilterCrTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
#else

Karsten Suehring
committed
pcLocalSlice->setDeblockingFilterBetaOffsetDiv2( pcPPS->getDeblockingFilterBetaOffsetDiv2() );
pcLocalSlice->setDeblockingFilterTcOffsetDiv2 ( pcPPS->getDeblockingFilterTcOffsetDiv2() );
pcLocalSlice->setDeblockingFilterCbBetaOffsetDiv2 ( pcPPS->getDeblockingFilterCbBetaOffsetDiv2() );
pcLocalSlice->setDeblockingFilterCbTcOffsetDiv2 ( pcPPS->getDeblockingFilterCbTcOffsetDiv2() );
pcLocalSlice->setDeblockingFilterCrBetaOffsetDiv2 ( pcPPS->getDeblockingFilterCrBetaOffsetDiv2() );
pcLocalSlice->setDeblockingFilterCrTcOffsetDiv2 ( pcPPS->getDeblockingFilterCrTcOffsetDiv2() );

Karsten Suehring
committed
}
}
}
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
#if DB_PARAM_TID
void EncGOP::applyDeblockingFilterParameterSelection( Picture* pcPic, Slice* pcSlice, const uint32_t numSlices, const int gopID )
{
const PPS* pcPPS = pcPic->slices[0]->getPPS();
for (int i = 0; i<numSlices; i++)
{
Slice* pcSlice = pcPic->slices[i];
pcSlice->setDeblockingFilterOverrideFlag(false);
pcSlice->setDeblockingFilterDisable(pcPPS->getPPSDeblockingFilterDisabledFlag());
int betaIdx = Clip3(0, (int)pcPPS->getDeblockingFilterBetaOffsetDiv2().size() - 1, (int)pcSlice->getTLayer() + (pcSlice->isIntra() ? 0 : 1));
int tcIdx = Clip3(0, (int)pcPPS->getDeblockingFilterTcOffsetDiv2().size() - 1, (int)pcSlice->getTLayer() + (pcSlice->isIntra() ? 0 : 1));
pcSlice->setDeblockingFilterBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcSlice->setDeblockingFilterTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
pcSlice->setDeblockingFilterCbBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcSlice->setDeblockingFilterCbTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
pcSlice->setDeblockingFilterCrBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcSlice->setDeblockingFilterCrTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
}
}
#endif

Karsten Suehring
committed
#if W0038_DB_OPT
void EncGOP::applyDeblockingFilterParameterSelection( Picture* pcPic, const uint32_t numSlices, const int gopID )
{
enum DBFltParam
{
DBFLT_PARAM_AVAILABLE = 0,
DBFLT_DISABLE_FLAG,
DBFLT_BETA_OFFSETD2,
DBFLT_TC_OFFSETD2,
//NUM_DBFLT_PARAMS
};
const int MAX_BETA_OFFSET = 3;
const int MIN_BETA_OFFSET = -3;
const int MAX_TC_OFFSET = 3;
const int MIN_TC_OFFSET = -3;
PelUnitBuf reco = pcPic->getRecoBuf();
const int currQualityLayer = (!pcPic->slices[0]->isIRAP()) ? m_pcCfg->getGOPEntry(gopID).m_temporalId+1 : 0;

Karsten Suehring
committed
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
CHECK(!(currQualityLayer <MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS), "Unspecified error");
CodingStructure& cs = *pcPic->cs;
if(!m_pcDeblockingTempPicYuv)
{
m_pcDeblockingTempPicYuv = new PelStorage;
m_pcDeblockingTempPicYuv->create( cs.area );
memset(m_DBParam, 0, sizeof(m_DBParam));
}
//preserve current reconstruction
m_pcDeblockingTempPicYuv->copyFrom ( reco );
const bool bNoFiltering = m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] && m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG]==false /*&& pcPic->getTLayer()==0*/;
const int maxBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]+1) : MAX_BETA_OFFSET;
const int minBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]-1) : MIN_BETA_OFFSET;
const int maxTcOffsetDiv2 = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]+2) : MAX_TC_OFFSET;
const int minTcOffsetDiv2 = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]-2) : MIN_TC_OFFSET;
uint64_t distBetaPrevious = std::numeric_limits<uint64_t>::max();
uint64_t distMin = std::numeric_limits<uint64_t>::max();
bool bDBFilterDisabledBest = true;
int betaOffsetDiv2Best = 0;
int tcOffsetDiv2Best = 0;
for(int betaOffsetDiv2=maxBetaOffsetDiv2; betaOffsetDiv2>=minBetaOffsetDiv2; betaOffsetDiv2--)
{
uint64_t distTcMin = std::numeric_limits<uint64_t>::max();
for(int tcOffsetDiv2=maxTcOffsetDiv2; tcOffsetDiv2 >= minTcOffsetDiv2; tcOffsetDiv2--)
{
for (int i=0; i<numSlices; i++)
{
Slice* pcSlice = pcPic->slices[i];
pcSlice->setDeblockingFilterOverrideFlag ( true);
pcSlice->setDeblockingFilterDisable ( false);
pcSlice->setDeblockingFilterBetaOffsetDiv2( betaOffsetDiv2 );
pcSlice->setDeblockingFilterTcOffsetDiv2 ( tcOffsetDiv2 );
pcSlice->setDeblockingFilterCbBetaOffsetDiv2( betaOffsetDiv2 );
pcSlice->setDeblockingFilterCbTcOffsetDiv2 ( tcOffsetDiv2 );
pcSlice->setDeblockingFilterCrBetaOffsetDiv2( betaOffsetDiv2 );
pcSlice->setDeblockingFilterCrTcOffsetDiv2 ( tcOffsetDiv2 );

Karsten Suehring
committed
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
}
// restore reconstruction
reco.copyFrom( *m_pcDeblockingTempPicYuv );
const uint64_t dist = preLoopFilterPicAndCalcDist( pcPic );
if(dist < distMin)
{
distMin = dist;
bDBFilterDisabledBest = false;
betaOffsetDiv2Best = betaOffsetDiv2;
tcOffsetDiv2Best = tcOffsetDiv2;
}
if(dist < distTcMin)
{
distTcMin = dist;
}
else if(tcOffsetDiv2 <-2)
{
break;
}
}
if(betaOffsetDiv2<-1 && distTcMin >= distBetaPrevious)
{
break;
}
distBetaPrevious = distTcMin;
}
//update:
m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] = 1;
m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG] = bDBFilterDisabledBest;
m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2] = betaOffsetDiv2Best;
m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2] = tcOffsetDiv2Best;
// restore reconstruction
reco.copyFrom( *m_pcDeblockingTempPicYuv );
const PPS* pcPPS = pcPic->slices[0]->getPPS();
#if DB_PARAM_TID
int betaIdx = Clip3(0, (int)pcPPS->getDeblockingFilterBetaOffsetDiv2().size() - 1, (int)pcPic->slices[0]->getTLayer() + (pcPic->slices[0]->isIntra() ? 0 : 1));
int tcIdx = Clip3(0, (int)pcPPS->getDeblockingFilterTcOffsetDiv2().size() - 1, (int)pcPic->slices[0]->getTLayer()) + (pcPic->slices[0]->isIntra() ? 0 : 1);
#endif

Karsten Suehring
committed
if(bDBFilterDisabledBest)
{
for (int i=0; i<numSlices; i++)
{
Slice* pcSlice = pcPic->slices[i];
pcSlice->setDeblockingFilterOverrideFlag( true);
pcSlice->setDeblockingFilterDisable ( true);
}
}
#if DB_PARAM_TID
else if (betaOffsetDiv2Best == pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx] && tcOffsetDiv2Best == pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx])
#else

Karsten Suehring
committed
else if(betaOffsetDiv2Best == pcPPS->getDeblockingFilterBetaOffsetDiv2() && tcOffsetDiv2Best == pcPPS->getDeblockingFilterTcOffsetDiv2())

Karsten Suehring
committed
{
for (int i=0; i<numSlices; i++)
{
Slice* pcSlice = pcPic->slices[i];
pcSlice->setDeblockingFilterOverrideFlag ( false);
pcSlice->setDeblockingFilterDisable ( pcPPS->getPPSDeblockingFilterDisabledFlag() );
#if DB_PARAM_TID
pcSlice->setDeblockingFilterBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcSlice->setDeblockingFilterTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
pcSlice->setDeblockingFilterCbBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcSlice->setDeblockingFilterCbTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
pcSlice->setDeblockingFilterCrBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2()[betaIdx]);
pcSlice->setDeblockingFilterCrTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2()[tcIdx]);
#else

Karsten Suehring
committed
pcSlice->setDeblockingFilterBetaOffsetDiv2 ( pcPPS->getDeblockingFilterBetaOffsetDiv2() );
pcSlice->setDeblockingFilterTcOffsetDiv2 ( pcPPS->getDeblockingFilterTcOffsetDiv2() );
pcSlice->setDeblockingFilterCbBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2());
pcSlice->setDeblockingFilterCbTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2());
pcSlice->setDeblockingFilterCrBetaOffsetDiv2(pcPPS->getDeblockingFilterBetaOffsetDiv2());
pcSlice->setDeblockingFilterCrTcOffsetDiv2(pcPPS->getDeblockingFilterTcOffsetDiv2());
#endif

Karsten Suehring
committed
}
}
else
{
for (int i=0; i<numSlices; i++)
{
Slice* pcSlice = pcPic->slices[i];
pcSlice->setDeblockingFilterOverrideFlag ( true);
pcSlice->setDeblockingFilterDisable ( false );
pcSlice->setDeblockingFilterBetaOffsetDiv2 ( betaOffsetDiv2Best);
pcSlice->setDeblockingFilterTcOffsetDiv2 ( tcOffsetDiv2Best);
pcSlice->setDeblockingFilterCbBetaOffsetDiv2 ( betaOffsetDiv2Best);
pcSlice->setDeblockingFilterCbTcOffsetDiv2 ( tcOffsetDiv2Best);
pcSlice->setDeblockingFilterCrBetaOffsetDiv2 ( betaOffsetDiv2Best);
pcSlice->setDeblockingFilterCrTcOffsetDiv2 ( tcOffsetDiv2Best);

Karsten Suehring
committed
}
}
}
#endif

Karsten Suehring
committed
bool EncGOP::xCheckMaxTidILRefPics(Picture* refPic, bool currentPicIsIRAP)
{
const int maxTidILRefPicsPlus1 = m_pcCfg->getVPSParameters().m_maxTidILRefPicsPlus1;
// -1 means not set
if (maxTidILRefPicsPlus1 < 0)
{
return true;
}
// 0 allows only IRAP pictures to use inter-layer prediction
if (maxTidILRefPicsPlus1 == 0)
{
return currentPicIsIRAP;
}
// all other cases filter by temporalID
return ( refPic->temporalId < maxTidILRefPicsPlus1 );
}
void EncGOP::xCreateExplicitReferencePictureSetFromReference( Slice* slice, PicList& rcListPic, const ReferencePictureList *rpl0, const ReferencePictureList *rpl1 )
{
Picture* rpcPic;
int pocCycle = 0;
Picture* pic = slice->getPic();
const VPS* vps = slice->getPic()->cs->vps;
int layerIdx = vps == nullptr ? 0 : vps->getGeneralLayerIdx( pic->layerId );
bool isIntraLayerPredAllowed = vps->getIndependentLayerFlag(layerIdx) || (vps->getPredDirection(slice->getTLayer()) != 1);
bool isInterLayerPredAllowed = !vps->getIndependentLayerFlag(layerIdx) && (vps->getPredDirection(slice->getTLayer()) != 2);
ReferencePictureList* pLocalRPL0 = slice->getLocalRPL0();
*pLocalRPL0 = ReferencePictureList( slice->getSPS()->getInterLayerPresentFlag() );
uint32_t numOfSTRPL0 = 0;
uint32_t numOfLTRPL0 = 0;
uint32_t numOfILRPL0 = 0;
uint32_t numOfRefPic = rpl0->getNumberOfShorttermPictures() + rpl0->getNumberOfLongtermPictures();
uint32_t refPicIdxL0 = 0;
if (isIntraLayerPredAllowed)
for (int ii = 0; ii < numOfRefPic; ii++)
// loop through all pictures in the reference picture buffer
PicList::iterator iterPic = rcListPic.begin();
bool isAvailable = false;
pocCycle = 1 << (slice->getSPS()->getBitsForPOC());
while (iterPic != rcListPic.end())
rpcPic = *(iterPic++);
if (rpcPic->layerId == pic->layerId)
#if JVET_S0045_SIGN
if (!rpl0->isRefPicLongterm(ii) && rpcPic->referenced
&& rpcPic->getPOC() == slice->getPOC() + rpl0->getRefPicIdentifier(ii)
&& !slice->isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP))
#else
if (!rpl0->isRefPicLongterm(ii) && rpcPic->referenced && rpcPic->getPOC() == slice->getPOC() - rpl0->getRefPicIdentifier(ii) && !slice->isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP))
{
isAvailable = true;
break;
}
else if (rpl0->isRefPicLongterm(ii) && rpcPic->referenced && (rpcPic->getPOC() & (pocCycle - 1)) == rpl0->getRefPicIdentifier(ii) && !slice->isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP))
{
isAvailable = true;
break;
}
if (isAvailable)
{
pLocalRPL0->setRefPicIdentifier(refPicIdxL0, rpl0->getRefPicIdentifier(ii), rpl0->isRefPicLongterm(ii), false, NOT_VALID);
refPicIdxL0++;
numOfSTRPL0 = numOfSTRPL0 + ((rpl0->isRefPicLongterm(ii)) ? 0 : 1);
numOfLTRPL0 += (rpl0->isRefPicLongterm(ii) && !rpl0->isInterLayerRefPic(ii)) ? 1 : 0;
isAvailable = false;
}
}
}
// inter-layer reference pictures are added to the end of the reference picture list
if (layerIdx && vps && !vps->getAllIndependentLayersFlag() && isInterLayerPredAllowed)
{
numOfRefPic = rpl0->getNumberOfInterLayerPictures() ? rpl0->getNumberOfInterLayerPictures() : m_pcEncLib->getNumRefLayers( layerIdx );
for( int ii = 0; ii < numOfRefPic; ii++ )
{
// loop through all pictures in the reference picture buffer
PicList::iterator iterPic = rcListPic.begin();
Vadim Seregin
committed
while( iterPic != rcListPic.end() && ii < numOfRefPic )
{
rpcPic = *( iterPic++ );
int refLayerIdx = vps->getGeneralLayerIdx( rpcPic->layerId );

Karsten Suehring
committed
if (rpcPic->referenced && rpcPic->getPOC() == pic->getPOC() && vps->getDirectRefLayerFlag(layerIdx, refLayerIdx)
&& xCheckMaxTidILRefPics(rpcPic, slice->isIRAP()) )
pLocalRPL0->setRefPicIdentifier( refPicIdxL0, 0, true, true, vps->getInterLayerRefIdc( layerIdx, refLayerIdx ) );
refPicIdxL0++;
numOfILRPL0++;
Vadim Seregin
committed
ii++;
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
}
}
}
}
if( slice->getEnableDRAPSEI() )
{
pLocalRPL0->setNumberOfShorttermPictures( numOfSTRPL0 );
pLocalRPL0->setNumberOfLongtermPictures( numOfLTRPL0 );
pLocalRPL0->setNumberOfInterLayerPictures( numOfILRPL0 );
if( !slice->isIRAP() && !slice->isPOCInRefPicList( pLocalRPL0, slice->getAssociatedIRAPPOC() ) )
{
if( slice->getUseLTforDRAP() && !slice->isPOCInRefPicList( rpl1, slice->getAssociatedIRAPPOC() ) )
{
// Adding associated IRAP as longterm picture
pLocalRPL0->setRefPicIdentifier( refPicIdxL0, slice->getAssociatedIRAPPOC(), true, false, 0 );
refPicIdxL0++;
numOfLTRPL0++;
}
else
{
// Adding associated IRAP as shortterm picture
#if JVET_S0045_SIGN
pLocalRPL0->setRefPicIdentifier(refPicIdxL0, slice->getAssociatedIRAPPOC() - slice->getPOC(), false, false, 0);
#else
pLocalRPL0->setRefPicIdentifier( refPicIdxL0, slice->getPOC() - slice->getAssociatedIRAPPOC(), false, false, 0 );
refPicIdxL0++;
numOfSTRPL0++;
}
}
}
ReferencePictureList* pLocalRPL1 = slice->getLocalRPL1();
*pLocalRPL1 = ReferencePictureList( slice->getSPS()->getInterLayerPresentFlag() );
uint32_t numOfSTRPL1 = 0;
uint32_t numOfLTRPL1 = 0;
uint32_t numOfILRPL1 = 0;
numOfRefPic = rpl1->getNumberOfShorttermPictures() + rpl1->getNumberOfLongtermPictures();
uint32_t refPicIdxL1 = 0;
if (isIntraLayerPredAllowed)
for (int ii = 0; ii < numOfRefPic; ii++)
// loop through all pictures in the reference picture buffer
PicList::iterator iterPic = rcListPic.begin();
bool isAvailable = false;
pocCycle = 1 << (slice->getSPS()->getBitsForPOC());
while (iterPic != rcListPic.end())
rpcPic = *(iterPic++);
if (rpcPic->layerId == pic->layerId)
#if JVET_S0045_SIGN
if (!rpl1->isRefPicLongterm(ii) && rpcPic->referenced
&& rpcPic->getPOC() == slice->getPOC() + rpl1->getRefPicIdentifier(ii)
&& !slice->isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP))
#else
if (!rpl1->isRefPicLongterm(ii) && rpcPic->referenced && rpcPic->getPOC() == slice->getPOC() - rpl1->getRefPicIdentifier(ii) && !slice->isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP))
{
isAvailable = true;
break;
}
else if (rpl1->isRefPicLongterm(ii) && rpcPic->referenced && (rpcPic->getPOC() & (pocCycle - 1)) == rpl1->getRefPicIdentifier(ii) && !slice->isPocRestrictedByDRAP(rpcPic->getPOC(), rpcPic->precedingDRAP))
{
isAvailable = true;
break;
}
if (isAvailable)
{
pLocalRPL1->setRefPicIdentifier(refPicIdxL1, rpl1->getRefPicIdentifier(ii), rpl1->isRefPicLongterm(ii), false, NOT_VALID);
refPicIdxL1++;
numOfSTRPL1 = numOfSTRPL1 + ((rpl1->isRefPicLongterm(ii)) ? 0 : 1);
numOfLTRPL1 += (rpl1->isRefPicLongterm(ii) && !rpl1->isInterLayerRefPic(ii)) ? 1 : 0;
isAvailable = false;
}
// inter-layer reference pictures are added to the end of the reference picture list
if (layerIdx && vps && !vps->getAllIndependentLayersFlag() && isInterLayerPredAllowed)
{
numOfRefPic = rpl1->getNumberOfInterLayerPictures() ? rpl1->getNumberOfInterLayerPictures() : m_pcEncLib->getNumRefLayers( layerIdx );
for( int ii = 0; ii < numOfRefPic; ii++ )
{
// loop through all pictures in the reference picture buffer
PicList::iterator iterPic = rcListPic.begin();
Vadim Seregin
committed
while( iterPic != rcListPic.end() && ii < numOfRefPic )
{
rpcPic = *( iterPic++ );
int refLayerIdx = vps->getGeneralLayerIdx( rpcPic->layerId );

Karsten Suehring
committed
if (rpcPic->referenced && rpcPic->getPOC() == pic->getPOC() && vps->getDirectRefLayerFlag(layerIdx, refLayerIdx)
&& xCheckMaxTidILRefPics( rpcPic, slice->isIRAP() ) )
{
pLocalRPL1->setRefPicIdentifier( refPicIdxL1, 0, true, true, vps->getInterLayerRefIdc( layerIdx, refLayerIdx ) );
refPicIdxL1++;
numOfILRPL1++;
Vadim Seregin
committed
ii++;
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
}
}
}
}
//Copy from L1 if we have less than active ref pic
int numOfNeedToFill = rpl0->getNumberOfActivePictures() - (numOfLTRPL0 + numOfSTRPL0);
bool isDisallowMixedRefPic = ( slice->getSPS()->getAllActiveRplEntriesHasSameSignFlag() ) ? true : false;
int originalL0StrpNum = numOfSTRPL0;
int originalL0LtrpNum = numOfLTRPL0;
int originalL0IlrpNum = numOfILRPL0;
for( int ii = 0; numOfNeedToFill > 0 && ii < ( pLocalRPL1->getNumberOfLongtermPictures() + pLocalRPL1->getNumberOfShorttermPictures() + pLocalRPL1->getNumberOfInterLayerPictures() ); ii++ )
{
if( ii <= ( numOfLTRPL1 + numOfSTRPL1 + numOfILRPL1 - 1 ) )
{
//Make sure this copy is not already in L0
bool canIncludeThis = true;
for( int jj = 0; jj < refPicIdxL0; jj++ )
{
if( ( pLocalRPL1->getRefPicIdentifier( ii ) == pLocalRPL0->getRefPicIdentifier( jj ) ) && ( pLocalRPL1->isRefPicLongterm( ii ) == pLocalRPL0->isRefPicLongterm( jj ) ) && pLocalRPL1->getInterLayerRefPicIdx( ii ) == pLocalRPL0->getInterLayerRefPicIdx( jj ) )
{
canIncludeThis = false;
}
bool sameSign = ( pLocalRPL1->getRefPicIdentifier( ii ) > 0 ) == ( pLocalRPL0->getRefPicIdentifier( 0 ) > 0 );
if( isDisallowMixedRefPic && canIncludeThis && !pLocalRPL1->isRefPicLongterm( ii ) && !sameSign )
{
canIncludeThis = false;
}
}
if( canIncludeThis )
{
pLocalRPL0->setRefPicIdentifier( refPicIdxL0, pLocalRPL1->getRefPicIdentifier( ii ), pLocalRPL1->isRefPicLongterm( ii ), pLocalRPL1->isInterLayerRefPic( ii ), pLocalRPL1->getInterLayerRefPicIdx( ii ) );
refPicIdxL0++;
numOfSTRPL0 = numOfSTRPL0 + ( ( pLocalRPL1->isRefPicLongterm( ii ) ) ? 0 : 1 );
numOfLTRPL0 += ( pLocalRPL1->isRefPicLongterm( ii ) && !pLocalRPL1->isInterLayerRefPic( ii ) ) ? 1 : 0;
numOfILRPL0 += pLocalRPL1->isInterLayerRefPic( ii ) ? 1 : 0;
numOfNeedToFill--;
}
}
}
pLocalRPL0->setNumberOfLongtermPictures( numOfLTRPL0 );
pLocalRPL0->setNumberOfShorttermPictures( numOfSTRPL0 );
pLocalRPL0->setNumberOfInterLayerPictures( numOfILRPL0 );
int numPics = numOfLTRPL0 + numOfSTRPL0;
pLocalRPL0->setNumberOfActivePictures( ( numPics < rpl0->getNumberOfActivePictures() ? numPics : rpl0->getNumberOfActivePictures() ) + numOfILRPL0 );
Zhipin Deng
committed
pLocalRPL0->setLtrpInSliceHeaderFlag( 1 );
slice->setRPL0idx( -1 );
slice->setRPL0( pLocalRPL0 );
//Copy from L0 if we have less than active ref pic
numOfNeedToFill = pLocalRPL0->getNumberOfActivePictures() - ( numOfLTRPL1 + numOfSTRPL1 );
for( int ii = 0; numOfNeedToFill > 0 && ii < ( pLocalRPL0->getNumberOfLongtermPictures() + pLocalRPL0->getNumberOfShorttermPictures() + pLocalRPL0->getNumberOfInterLayerPictures() ); ii++ )
{
if( ii <= ( originalL0StrpNum + originalL0LtrpNum + originalL0IlrpNum - 1 ) )
{
//Make sure this copy is not already in L0
bool canIncludeThis = true;
for( int jj = 0; jj < refPicIdxL1; jj++ )
{
if( ( pLocalRPL0->getRefPicIdentifier( ii ) == pLocalRPL1->getRefPicIdentifier( jj ) ) && ( pLocalRPL0->isRefPicLongterm( ii ) == pLocalRPL1->isRefPicLongterm( jj ) ) && pLocalRPL0->getInterLayerRefPicIdx( ii ) == pLocalRPL1->getInterLayerRefPicIdx( jj ) )
{