Coverage Report

Created: 2025-07-23 08:18

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