Coverage Report

Created: 2026-03-08 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/x265/source/encoder/dpb.cpp
Line
Count
Source
1
/*****************************************************************************
2
 * Copyright (C) 2013-2020 MulticoreWare, Inc
3
 *
4
 * Authors: Steve Borho <steve@borho.org>
5
 *          Min Chen <chenm003@163.com>
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
20
 *
21
 * This program is also available under a commercial proprietary license.
22
 * For more information, contact us at license @ x265.com.
23
 *****************************************************************************/
24
25
#include "common.h"
26
#include "frame.h"
27
#include "framedata.h"
28
#include "picyuv.h"
29
#include "slice.h"
30
31
#include "dpb.h"
32
33
using namespace X265_NS;
34
35
DPB::~DPB()
36
654
{
37
654
    while (!m_freeList.empty())
38
0
    {
39
0
        Frame* curFrame = m_freeList.popFront();
40
0
        curFrame->destroy();
41
0
        delete curFrame;
42
0
    }
43
44
1.30k
    while (!m_picList.empty())
45
654
    {
46
654
        Frame* curFrame = m_picList.popFront();
47
654
        curFrame->destroy();
48
654
        delete curFrame;
49
654
    }
50
51
654
    while (m_frameDataFreeList)
52
0
    {
53
0
        FrameData* next = m_frameDataFreeList->m_freeListNext;
54
0
        m_frameDataFreeList->destroy();
55
56
0
        for (int i = 0; i < !!m_frameDataFreeList->m_param->bEnableSCC + 1; i++)
57
0
        {
58
0
            m_frameDataFreeList->m_reconPic[i]->destroy();
59
0
            delete m_frameDataFreeList->m_reconPic[i];
60
0
        }
61
62
0
        delete m_frameDataFreeList;
63
0
        m_frameDataFreeList = next;
64
0
    }
65
654
}
66
67
// move unreferenced pictures from picList to freeList for recycle
68
void DPB::recycleUnreferenced()
69
44
{
70
44
    Frame *iterFrame = m_picList.first();
71
72
88
    while (iterFrame)
73
44
    {
74
44
        Frame *curFrame = iterFrame;
75
44
        iterFrame = iterFrame->m_next;
76
44
        bool isMCSTFReferenced = false;
77
78
44
        if (curFrame->m_param->bEnableTemporalFilter)
79
0
            isMCSTFReferenced =!!(curFrame->m_refPicCnt[1]);
80
81
44
        if (curFrame->m_valid && !curFrame->m_encData->m_bHasReferences && !curFrame->m_countRefEncoders && !isMCSTFReferenced)
82
0
        {
83
0
            curFrame->m_bChromaExtended = false;
84
85
0
            if (curFrame->m_param->bEnableTemporalFilter)
86
0
                *curFrame->m_isSubSampled = false;
87
88
            // Reset column counter
89
0
            X265_CHECK(curFrame->m_reconRowFlag != NULL, "curFrame->m_reconRowFlag check failure");
90
0
            X265_CHECK(curFrame->m_reconColCount != NULL, "curFrame->m_reconColCount check failure");
91
0
            X265_CHECK(curFrame->m_numRows > 0, "curFrame->m_numRows check failure");
92
93
0
            for(int32_t row = 0; row < curFrame->m_numRows; row++)
94
0
            {
95
0
                curFrame->m_reconRowFlag[row].set(0);
96
0
                curFrame->m_reconColCount[row].set(0);
97
98
0
                uint32_t m_numCols = (curFrame->m_fencPic->m_picWidth + curFrame->m_param->maxCUSize - 1) / curFrame->m_param->maxCUSize;
99
0
                for (uint32_t col = 0; col < m_numCols; col++)
100
0
                {
101
0
                    uint32_t ctuAddr = row * m_numCols + col;
102
0
                    curFrame->m_ctuMEFlags[ctuAddr].set(0);
103
0
                }
104
0
            }
105
106
            // iterator is invalidated by remove, restart scan
107
0
            m_picList.remove(*curFrame);
108
#if ENABLE_MULTIVIEW
109
            if (curFrame->m_param->numViews > 1 && !curFrame->m_viewId && m_picList.getPOC(curFrame->m_poc, 1) && curFrame == m_picList.getPOC(curFrame->m_poc, 1)->refPicSetInterLayer0.getPOC(curFrame->m_poc, curFrame->m_viewId))
110
            {
111
                m_picList.getPOC(curFrame->m_poc, 1)->refPicSetInterLayer0.removeSubDPB(*curFrame);
112
            }
113
#endif
114
0
            iterFrame = m_picList.first();
115
116
0
            m_freeList.pushBack(*curFrame);
117
0
            curFrame->m_encData->m_freeListNext = m_frameDataFreeList;
118
0
            m_frameDataFreeList = curFrame->m_encData;
119
0
            for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)
120
0
            {
121
0
                if (curFrame->m_encData->m_meBuffer[i] != NULL)
122
0
                {
123
0
                    X265_FREE(curFrame->m_encData->m_meBuffer[i]);
124
0
                    curFrame->m_encData->m_meBuffer[i] = NULL;
125
0
                }
126
0
            }
127
0
            if (curFrame->m_ctuInfo != NULL)
128
0
            {
129
0
                uint32_t widthInCU = (curFrame->m_param->sourceWidth + curFrame->m_param->maxCUSize - 1) >> curFrame->m_param->maxLog2CUSize;
130
0
                uint32_t heightInCU = (curFrame->m_param->sourceHeight + curFrame->m_param->maxCUSize - 1) >> curFrame->m_param->maxLog2CUSize;
131
0
                uint32_t numCUsInFrame = widthInCU * heightInCU;
132
0
                for (uint32_t i = 0; i < numCUsInFrame; i++)
133
0
                {
134
0
                    X265_FREE((*curFrame->m_ctuInfo + i)->ctuInfo);
135
0
                    (*curFrame->m_ctuInfo + i)->ctuInfo = NULL;
136
0
                }
137
0
                X265_FREE(*curFrame->m_ctuInfo);
138
0
                *(curFrame->m_ctuInfo) = NULL;
139
0
                X265_FREE(curFrame->m_ctuInfo);
140
0
                curFrame->m_ctuInfo = NULL;
141
0
                X265_FREE(curFrame->m_prevCtuInfoChange);
142
0
                curFrame->m_prevCtuInfoChange = NULL;
143
0
            }
144
0
            curFrame->m_encData = NULL;
145
0
            for (int i = 0; i < !!curFrame->m_param->bEnableSCC + 1; i++)
146
0
                curFrame->m_reconPic[i] = NULL;
147
0
        }
148
44
    }
149
44
}
150
151
void DPB::prepareEncode(Frame *newFrame)
152
654
{
153
654
    Slice* slice = newFrame->m_encData->m_slice;
154
654
    slice->m_poc = newFrame->m_poc;
155
654
    slice->m_fieldNum = newFrame->m_fieldNum;
156
157
654
    int pocCurr = slice->m_poc;
158
654
    int type = newFrame->m_lowres.sliceType;
159
654
    bool bIsKeyFrame = newFrame->m_lowres.bKeyframe;
160
654
    slice->m_nalUnitType = getNalUnitType(pocCurr, bIsKeyFrame);
161
654
    if (slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)
162
654
        m_lastIDR = pocCurr;
163
654
    slice->m_lastIDR = m_lastIDR;
164
654
    slice->m_sliceType = IS_X265_TYPE_B(type) ? B_SLICE : (type == X265_TYPE_P) ? P_SLICE : I_SLICE;
165
#if ENABLE_SCC_EXT
166
    if (slice->m_param->bEnableSCC)        slice->m_origSliceType = slice->m_sliceType;
167
    if (slice->m_param->bEnableSCC && IS_X265_TYPE_I(type))
168
        slice->m_sliceType = P_SLICE;
169
#endif
170
171
654
    if (type == X265_TYPE_B)
172
0
    {
173
0
        newFrame->m_encData->m_bHasReferences = false;
174
175
0
        newFrame->m_tempLayer = (newFrame->m_param->bEnableTemporalSubLayers && !m_bTemporalSublayer) ? 1 : newFrame->m_tempLayer;
176
        // Adjust NAL type for unreferenced B frames (change from _R "referenced"
177
        // to _N "non-referenced" NAL unit type)
178
0
        switch (slice->m_nalUnitType)
179
0
        {
180
0
        case NAL_UNIT_CODED_SLICE_TRAIL_R:
181
0
            slice->m_nalUnitType = newFrame->m_param->bEnableTemporalSubLayers ? NAL_UNIT_CODED_SLICE_TSA_N : NAL_UNIT_CODED_SLICE_TRAIL_N;
182
0
            break;
183
0
        case NAL_UNIT_CODED_SLICE_RADL_R:
184
0
            slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RADL_N;
185
0
            break;
186
0
        case NAL_UNIT_CODED_SLICE_RASL_R:
187
0
            slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RASL_N;
188
0
            break;
189
0
        default:
190
0
            break;
191
0
        }
192
0
    }
193
654
    else
194
654
    {
195
        /* m_bHasReferences starts out as true for non-B pictures, and is set to false
196
         * once no more pictures reference it */
197
654
        newFrame->m_encData->m_bHasReferences = true;
198
654
    }
199
200
654
    m_picList.pushFront(*newFrame);
201
202
654
    int layer = slice->m_param->numViews > 1 ? newFrame->m_viewId : (slice->m_param->numScalableLayers > 1) ? newFrame->m_sLayerId : 0;
203
654
    if (m_bTemporalSublayer && getTemporalLayerNonReferenceFlag(layer))
204
0
    {
205
0
        switch (slice->m_nalUnitType)
206
0
        {
207
0
        case NAL_UNIT_CODED_SLICE_TRAIL_R:
208
0
            slice->m_nalUnitType =  NAL_UNIT_CODED_SLICE_TRAIL_N;
209
0
            break;
210
0
        case NAL_UNIT_CODED_SLICE_RADL_R:
211
0
            slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RADL_N;
212
0
            break;
213
0
        case NAL_UNIT_CODED_SLICE_RASL_R:
214
0
            slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RASL_N;
215
0
            break;
216
0
        default:
217
0
            break;
218
0
        }
219
0
    }
220
    // Do decoding refresh marking if any
221
654
    decodingRefreshMarking(pocCurr, slice->m_nalUnitType, layer);
222
223
654
    uint32_t maxDecBuffer = (slice->m_sps->maxDecPicBuffering[newFrame->m_tempLayer] >= 8 && slice->m_param->bEnableSCC) ? 7 : slice->m_sps->maxDecPicBuffering[newFrame->m_tempLayer];
224
654
    computeRPS(pocCurr, newFrame->m_tempLayer, slice->isIRAP(), &slice->m_rps, maxDecBuffer, layer);
225
654
    bool isTSAPic = ((slice->m_nalUnitType == 2) || (slice->m_nalUnitType == 3)) ? true : false;
226
    // Mark pictures in m_piclist as unreferenced if they are not included in RPS
227
654
    applyReferencePictureSet(&slice->m_rps, pocCurr, newFrame->m_tempLayer, isTSAPic, layer);
228
229
230
654
    if (m_bTemporalSublayer && newFrame->m_tempLayer > 0
231
0
        && !(slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N     // Check if not a leading picture
232
0
            || slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R
233
0
            || slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N
234
0
            || slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R)
235
654
        )
236
0
    {
237
0
        if (isTemporalLayerSwitchingPoint(pocCurr, newFrame->m_tempLayer, layer) || (slice->m_sps->maxTempSubLayers == 1))
238
0
        {
239
0
            if (getTemporalLayerNonReferenceFlag(layer))
240
0
            {
241
0
                slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_TSA_N;
242
0
            }
243
0
            else
244
0
            {
245
0
                slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_TSA_R;
246
0
            }
247
0
        }
248
0
        else if (isStepwiseTemporalLayerSwitchingPoint(&slice->m_rps, pocCurr, newFrame->m_tempLayer, layer))
249
0
        {
250
0
            bool isSTSA = true;
251
0
            int id = newFrame->m_gopOffset % x265_gop_ra_length[newFrame->m_gopId];
252
0
            for (int ii = id; (ii < x265_gop_ra_length[newFrame->m_gopId] && isSTSA == true); ii++)
253
0
            {
254
0
                int tempIdRef = x265_gop_ra[newFrame->m_gopId][ii].layer;
255
0
                if (tempIdRef == newFrame->m_tempLayer)
256
0
                {
257
0
                    for (int jj = 0; jj < slice->m_rps.numberOfPositivePictures + slice->m_rps.numberOfNegativePictures; jj++)
258
0
                    {
259
0
                        if (slice->m_rps.bUsed[jj])
260
0
                        {
261
0
                            int refPoc = x265_gop_ra[newFrame->m_gopId][ii].poc_offset + slice->m_rps.deltaPOC[jj];
262
0
                            int kk = 0;
263
0
                            for (kk = 0; kk < x265_gop_ra_length[newFrame->m_gopId]; kk++)
264
0
                            {
265
0
                                if (x265_gop_ra[newFrame->m_gopId][kk].poc_offset == refPoc)
266
0
                                {
267
0
                                    break;
268
0
                                }
269
0
                            }
270
0
                            if (x265_gop_ra[newFrame->m_gopId][kk].layer >= newFrame->m_tempLayer)
271
0
                            {
272
0
                                isSTSA = false;
273
0
                                break;
274
0
                            }
275
0
                        }
276
0
                    }
277
0
                }
278
0
            }
279
0
            if (isSTSA == true)
280
0
            {
281
0
                if (getTemporalLayerNonReferenceFlag(layer))
282
0
                {
283
0
                    slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_STSA_N;
284
0
                }
285
0
                else
286
0
                {
287
0
                    slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_STSA_R;
288
0
                }
289
0
            }
290
0
        }
291
0
    }
292
293
#if ENABLE_MULTIVIEW
294
    if (newFrame->m_viewId)
295
        slice->createInterLayerReferencePictureSet(m_picList, newFrame->refPicSetInterLayer0, newFrame->refPicSetInterLayer1);
296
#endif
297
654
    int numRef = slice->m_param->bEnableSCC ? slice->m_rps.numberOfNegativePictures + 1 : slice->m_rps.numberOfNegativePictures;
298
654
    if (slice->m_sliceType != I_SLICE)
299
0
        slice->m_numRefIdx[0] = x265_clip3(1, newFrame->m_param->maxNumReferences, numRef + newFrame->refPicSetInterLayer0.size() + newFrame->refPicSetInterLayer1.size());
300
654
    else
301
654
        slice->m_numRefIdx[0] = X265_MIN(newFrame->m_param->maxNumReferences, numRef); // Ensuring L0 contains just the -ve POC
302
#if ENABLE_MULTIVIEW || ENABLE_SCC_EXT
303
    if(slice->m_param->numViews > 1 || !!slice->m_param->bEnableSCC)
304
        slice->m_numRefIdx[1] = X265_MIN(newFrame->m_param->bBPyramid ? 3 : 2, slice->m_rps.numberOfPositivePictures + newFrame->refPicSetInterLayer0.size() + newFrame->refPicSetInterLayer1.size());
305
    else
306
#endif
307
654
        slice->m_numRefIdx[1] = X265_MIN(newFrame->m_param->bBPyramid ? 2 : 1, slice->m_rps.numberOfPositivePictures);
308
#if ENABLE_MULTIVIEW
309
    slice->setRefPicList(m_picList, layer, newFrame->refPicSetInterLayer0, newFrame->refPicSetInterLayer1);
310
#else
311
654
    slice->setRefPicList(m_picList, layer);
312
654
#endif
313
314
654
    X265_CHECK(slice->m_sliceType != B_SLICE || slice->m_numRefIdx[1], "B slice without L1 references (non-fatal)\n");
315
316
654
    if (slice->m_sliceType == B_SLICE)
317
0
    {
318
        /* TODO: the lookahead should be able to tell which reference picture
319
         * had the least motion residual.  We should be able to use that here to
320
         * select a colocation reference list and index */
321
322
0
        bool bLowDelay = true;
323
0
        int  iCurrPOC = slice->m_poc;
324
0
        int iRefIdx = 0;
325
326
0
        for (iRefIdx = 0; iRefIdx < slice->m_numRefIdx[0] && bLowDelay; iRefIdx++)
327
0
        {
328
0
            if (slice->m_refPOCList[0][iRefIdx] > iCurrPOC)
329
0
            {
330
0
                bLowDelay = false;
331
0
            }
332
0
        }
333
0
        for (iRefIdx = 0; iRefIdx < slice->m_numRefIdx[1] && bLowDelay; iRefIdx++)
334
0
        {
335
0
            if (slice->m_refPOCList[1][iRefIdx] > iCurrPOC)
336
0
            {
337
0
                bLowDelay = false;
338
0
            }
339
0
        }
340
341
0
        slice->m_bCheckLDC = bLowDelay;
342
0
        slice->m_colFromL0Flag = bLowDelay;
343
0
        slice->m_colRefIdx = 0;
344
0
    }
345
654
    else
346
654
    {
347
654
        slice->m_bCheckLDC = true;
348
654
        slice->m_colFromL0Flag = true;
349
654
        slice->m_colRefIdx = 0;
350
654
    }
351
352
654
    slice->m_bTemporalMvp = slice->m_sps->bTemporalMVPEnabled;
353
#if ENABLE_SCC_EXT
354
    if (!slice->isIntra() && slice->m_param->bEnableTemporalMvp)
355
    {
356
        const Frame* colPic = slice->m_refFrameList[slice->isInterB() && !slice->m_colFromL0Flag][slice->m_colRefIdx];
357
        if (colPic->m_poc == slice->m_poc)
358
            slice->m_bTemporalMvp = false;
359
        else
360
            slice->m_bTemporalMvp = true;
361
    }
362
#endif
363
364
    // Disable Loopfilter in bound area, because we will do slice-parallelism in future
365
654
    slice->m_sLFaseFlag = (newFrame->m_param->maxSlices > 1) ? false : ((SLFASE_CONSTANT & (1 << (pocCurr % 31))) > 0);
366
367
    /* Increment reference count of all motion-referenced frames to prevent them
368
     * from being recycled. These counts are decremented at the end of
369
     * compressFrame() */
370
654
    int numPredDir = slice->isInterP() ? 1 : slice->isInterB() ? 2 : 0;
371
654
    for (int l = 0; l < numPredDir; l++)
372
0
    {
373
0
        for (int ref = 0; ref < slice->m_numRefIdx[l]; ref++)
374
0
        {
375
0
            Frame *refpic = slice->m_refFrameList[l][ref];
376
0
            ATOMIC_INC(&refpic->m_countRefEncoders);
377
0
        }
378
0
    }
379
654
}
380
381
void DPB::computeRPS(int curPoc, int tempId, bool isRAP, RPS * rps, unsigned int maxDecPicBuffer, int scalableLayerId)
382
654
{
383
654
    unsigned int poci = 0, numNeg = 0, numPos = 0;
384
385
654
    Frame* iterPic = m_picList.first();
386
387
1.30k
    while (iterPic && (poci < maxDecPicBuffer - 1))
388
654
    {
389
654
        int layer = iterPic->m_param->numViews > 1 ? iterPic->m_viewId : (iterPic->m_param->numScalableLayers > 1) ? iterPic->m_sLayerId : 0;
390
654
        if (iterPic->m_valid && (iterPic->m_poc != curPoc) && iterPic->m_encData->m_bHasReferences && layer == scalableLayerId)
391
0
        {
392
0
            if ((!m_bTemporalSublayer || (iterPic->m_tempLayer <= tempId)) && ((m_lastIDR >= curPoc) || (m_lastIDR <= iterPic->m_poc)))
393
0
            {
394
#if ENABLE_MULTIVIEW
395
                    if (iterPic->m_param->numViews > 1 && layer && numNeg == (uint8_t)(iterPic->m_param->maxNumReferences - 1) && (iterPic->m_poc - curPoc) < 0)
396
                    {
397
                        iterPic = iterPic->m_next;
398
                        continue;
399
                    }
400
#endif
401
0
                    rps->poc[poci] = iterPic->m_poc;
402
0
                    rps->deltaPOC[poci] = rps->poc[poci] - curPoc;
403
0
                    (rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++;
404
0
                    rps->bUsed[poci] = !isRAP;
405
0
                    poci++;
406
0
            }
407
0
        }
408
654
        iterPic = iterPic->m_next;
409
654
    }
410
411
654
    rps->numberOfPictures = poci;
412
654
    rps->numberOfPositivePictures = numPos;
413
654
    rps->numberOfNegativePictures = numNeg;
414
415
654
    rps->sortDeltaPOC();
416
654
}
417
418
bool DPB::getTemporalLayerNonReferenceFlag(int scalableLayerId)
419
0
{
420
0
    Frame* curFrame = m_picList.first();
421
0
    int layer = curFrame->m_param->numViews > 1 ? curFrame->m_viewId : (curFrame->m_param->numScalableLayers > 1) ? curFrame->m_sLayerId : 0;
422
0
    if (curFrame->m_valid && curFrame->m_encData->m_bHasReferences && layer == scalableLayerId)
423
0
    {
424
0
        curFrame->m_sameLayerRefPic = true;
425
0
        return false;
426
0
    }
427
0
    else
428
0
        return true;
429
0
}
430
431
/* Marking reference pictures when an IDR/CRA is encountered. */
432
void DPB::decodingRefreshMarking(int pocCurr, NalUnitType nalUnitType, int scalableLayerId)
433
654
{
434
654
    if (nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)
435
654
    {
436
        /* If the nal_unit_type is IDR, all pictures in the reference picture
437
         * list are marked as "unused for reference" */
438
654
        Frame* iterFrame = m_picList.first();
439
1.30k
        while (iterFrame)
440
654
        {
441
654
            int layer = iterFrame->m_param->numViews > 1 ? iterFrame->m_viewId : (iterFrame->m_param->numScalableLayers > 1) ? iterFrame->m_sLayerId : 0;
442
654
            if (iterFrame->m_valid && iterFrame->m_poc != pocCurr && layer == scalableLayerId)
443
0
                iterFrame->m_encData->m_bHasReferences = false;
444
654
            iterFrame = iterFrame->m_next;
445
654
        }
446
654
    }
447
0
    else // CRA or No DR
448
0
    {
449
0
        if (m_bRefreshPending && pocCurr > m_pocCRA)
450
0
        {
451
            /* If the bRefreshPending flag is true (a deferred decoding refresh
452
             * is pending) and the current temporal reference is greater than
453
             * the temporal reference of the latest CRA picture (pocCRA), mark
454
             * all reference pictures except the latest CRA picture as "unused
455
             * for reference" and set the bRefreshPending flag to false */
456
0
            Frame* iterFrame = m_picList.first();
457
0
            while (iterFrame)
458
0
            {
459
0
                int layer = iterFrame->m_param->numViews > 1 ? iterFrame->m_viewId : (iterFrame->m_param->numScalableLayers > 1) ? iterFrame->m_sLayerId : 0;
460
0
                if (iterFrame->m_valid && iterFrame->m_poc != pocCurr && iterFrame->m_poc != m_pocCRA && layer == scalableLayerId)
461
0
                    iterFrame->m_encData->m_bHasReferences = false;
462
0
                iterFrame = iterFrame->m_next;
463
0
            }
464
465
0
            if (scalableLayerId == m_picList.first()->m_param->numLayers - 1)
466
0
                m_bRefreshPending = false;
467
0
        }
468
0
        if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA)
469
0
        {
470
            /* If the nal_unit_type is CRA, set the bRefreshPending flag to true
471
             * and pocCRA to the temporal reference of the current picture */
472
0
            m_bRefreshPending = true;
473
0
            m_pocCRA = pocCurr;
474
0
        }
475
0
    }
476
477
    /* Note that the current picture is already placed in the reference list and
478
     * its marking is not changed.  If the current picture has a nal_ref_idc
479
     * that is not 0, it will remain marked as "used for reference" */
480
654
}
481
482
/** Function for applying picture marking based on the Reference Picture Set */
483
void DPB::applyReferencePictureSet(RPS *rps, int curPoc, int tempId, bool isTSAPicture, int scalableLayerId)
484
654
{
485
    // loop through all pictures in the reference picture buffer
486
654
    Frame* iterFrame = m_picList.first();
487
1.30k
    while (iterFrame)
488
654
    {
489
654
        int layer = iterFrame->m_param->numViews > 1 ? iterFrame->m_viewId : (iterFrame->m_param->numScalableLayers > 1) ? iterFrame->m_sLayerId : 0;
490
654
        if (iterFrame->m_valid && iterFrame->m_poc != curPoc && iterFrame->m_encData->m_bHasReferences && layer == scalableLayerId)
491
0
        {
492
            // loop through all pictures in the Reference Picture Set
493
            // to see if the picture should be kept as reference picture
494
0
            bool referenced = false;
495
0
            for (int i = 0; i < rps->numberOfPositivePictures + rps->numberOfNegativePictures; i++)
496
0
            {
497
0
                if (iterFrame->m_poc == curPoc + rps->deltaPOC[i])
498
0
                {
499
0
                    referenced = true;
500
0
                    break;
501
0
                }
502
0
            }
503
0
            if (!referenced)
504
0
                iterFrame->m_encData->m_bHasReferences = false;
505
506
0
            if (m_bTemporalSublayer)
507
0
            {
508
                //check that pictures of higher temporal layers are not used
509
0
                assert(referenced == 0 || iterFrame->m_encData->m_bHasReferences == false || iterFrame->m_tempLayer <= tempId);
510
511
                //check that pictures of higher or equal temporal layer are not in the RPS if the current picture is a TSA picture
512
0
                if (isTSAPicture)
513
0
                {
514
0
                    assert(referenced == 0 || iterFrame->m_tempLayer < tempId);
515
0
                }
516
                //check that pictures marked as temporal layer non-reference pictures are not used for reference
517
0
                if (iterFrame->m_tempLayer == tempId)
518
0
                {
519
0
                    assert(referenced == 0 || iterFrame->m_sameLayerRefPic == true);
520
0
                }
521
0
            }
522
0
        }
523
654
        iterFrame = iterFrame->m_next;
524
654
    }
525
654
}
526
527
bool DPB::isTemporalLayerSwitchingPoint(int curPoc, int tempId, int scalableLayerId)
528
0
{
529
    // loop through all pictures in the reference picture buffer
530
0
    Frame* iterFrame = m_picList.first();
531
0
    while (iterFrame)
532
0
    {
533
0
        int layer = iterFrame->m_param->numViews > 1 ? iterFrame->m_viewId : (iterFrame->m_param->numScalableLayers > 1) ? iterFrame->m_sLayerId : 0;
534
0
        if (iterFrame->m_valid && iterFrame->m_poc != curPoc && iterFrame->m_encData->m_bHasReferences && layer == scalableLayerId)
535
0
        {
536
0
            if (iterFrame->m_tempLayer >= tempId)
537
0
            {
538
0
                return false;
539
0
            }
540
0
        }
541
0
        iterFrame = iterFrame->m_next;
542
0
    }
543
0
    return true;
544
0
}
545
546
bool DPB::isStepwiseTemporalLayerSwitchingPoint(RPS *rps, int curPoc, int tempId, int scalableLayerId)
547
0
{
548
    // loop through all pictures in the reference picture buffer
549
0
    Frame* iterFrame = m_picList.first();
550
0
    while (iterFrame)
551
0
    {
552
0
        int layer = iterFrame->m_param->numViews > 1 ? iterFrame->m_viewId : (iterFrame->m_param->numScalableLayers > 1) ? iterFrame->m_sLayerId : 0;
553
0
        if (iterFrame->m_valid && iterFrame->m_poc != curPoc && iterFrame->m_encData->m_bHasReferences && layer == scalableLayerId)
554
0
        {
555
0
            for (int i = 0; i < rps->numberOfPositivePictures + rps->numberOfNegativePictures; i++)
556
0
            {
557
0
                if ((iterFrame->m_poc == curPoc + rps->deltaPOC[i]) && rps->bUsed[i])
558
0
                {
559
0
                    if (iterFrame->m_tempLayer >= tempId)
560
0
                    {
561
0
                        return false;
562
0
                    }
563
0
                }
564
0
            }
565
0
        }
566
0
        iterFrame = iterFrame->m_next;
567
0
    }
568
0
    return true;
569
0
}
570
571
/* deciding the nal_unit_type */
572
NalUnitType DPB::getNalUnitType(int curPOC, bool bIsKeyFrame)
573
654
{
574
654
    if (!curPOC)
575
654
        return NAL_UNIT_CODED_SLICE_IDR_N_LP;
576
0
    if (bIsKeyFrame)
577
0
        return (m_bOpenGOP || m_craNal) ? NAL_UNIT_CODED_SLICE_CRA : m_bhasLeadingPicture ? NAL_UNIT_CODED_SLICE_IDR_W_RADL : NAL_UNIT_CODED_SLICE_IDR_N_LP;
578
0
    if (m_pocCRA && curPOC < m_pocCRA)
579
        // All leading pictures are being marked as TFD pictures here since
580
        // current encoder uses all reference pictures while encoding leading
581
        // pictures. An encoder can ensure that a leading picture can be still
582
        // decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by
583
        // controlling the reference pictures used for encoding that leading
584
        // picture. Such a leading picture need not be marked as a TFD picture.
585
0
        return NAL_UNIT_CODED_SLICE_RASL_R;
586
587
0
    if (m_lastIDR && curPOC < m_lastIDR)
588
0
        return NAL_UNIT_CODED_SLICE_RADL_R;
589
590
0
    return NAL_UNIT_CODED_SLICE_TRAIL_R;
591
0
}