Coverage Report

Created: 2022-08-24 06:17

/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
698
{
37
698
    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.39k
    while (!m_picList.empty())
45
698
    {
46
698
        Frame* curFrame = m_picList.popFront();
47
698
        curFrame->destroy();
48
698
        delete curFrame;
49
698
    }
50
51
698
    while (m_frameDataFreeList)
52
0
    {
53
0
        FrameData* next = m_frameDataFreeList->m_freeListNext;
54
0
        m_frameDataFreeList->destroy();
55
56
0
        m_frameDataFreeList->m_reconPic->destroy();
57
0
        delete m_frameDataFreeList->m_reconPic;
58
59
0
        delete m_frameDataFreeList;
60
0
        m_frameDataFreeList = next;
61
0
    }
62
698
}
63
64
// move unreferenced pictures from picList to freeList for recycle
65
void DPB::recycleUnreferenced()
66
698
{
67
698
    Frame *iterFrame = m_picList.first();
68
69
1.39k
    while (iterFrame)
70
698
    {
71
698
        Frame *curFrame = iterFrame;
72
698
        iterFrame = iterFrame->m_next;
73
698
        if (!curFrame->m_encData->m_bHasReferences && !curFrame->m_countRefEncoders)
74
0
        {
75
0
            curFrame->m_bChromaExtended = false;
76
77
            // Reset column counter
78
0
            X265_CHECK(curFrame->m_reconRowFlag != NULL, "curFrame->m_reconRowFlag check failure");
79
0
            X265_CHECK(curFrame->m_reconColCount != NULL, "curFrame->m_reconColCount check failure");
80
0
            X265_CHECK(curFrame->m_numRows > 0, "curFrame->m_numRows check failure");
81
82
0
            for(int32_t row = 0; row < curFrame->m_numRows; row++)
83
0
            {
84
0
                curFrame->m_reconRowFlag[row].set(0);
85
0
                curFrame->m_reconColCount[row].set(0);
86
0
            }
87
88
            // iterator is invalidated by remove, restart scan
89
0
            m_picList.remove(*curFrame);
90
0
            iterFrame = m_picList.first();
91
92
0
            m_freeList.pushBack(*curFrame);
93
0
            curFrame->m_encData->m_freeListNext = m_frameDataFreeList;
94
0
            m_frameDataFreeList = curFrame->m_encData;
95
0
            for (int i = 0; i < INTEGRAL_PLANE_NUM; i++)
96
0
            {
97
0
                if (curFrame->m_encData->m_meBuffer[i] != NULL)
98
0
                {
99
0
                    X265_FREE(curFrame->m_encData->m_meBuffer[i]);
100
0
                    curFrame->m_encData->m_meBuffer[i] = NULL;
101
0
                }
102
0
            }
103
0
            if (curFrame->m_ctuInfo != NULL)
104
0
            {
105
0
                uint32_t widthInCU = (curFrame->m_param->sourceWidth + curFrame->m_param->maxCUSize - 1) >> curFrame->m_param->maxLog2CUSize;
106
0
                uint32_t heightInCU = (curFrame->m_param->sourceHeight + curFrame->m_param->maxCUSize - 1) >> curFrame->m_param->maxLog2CUSize;
107
0
                uint32_t numCUsInFrame = widthInCU * heightInCU;
108
0
                for (uint32_t i = 0; i < numCUsInFrame; i++)
109
0
                {
110
0
                    X265_FREE((*curFrame->m_ctuInfo + i)->ctuInfo);
111
0
                    (*curFrame->m_ctuInfo + i)->ctuInfo = NULL;
112
0
                }
113
0
                X265_FREE(*curFrame->m_ctuInfo);
114
0
                *(curFrame->m_ctuInfo) = NULL;
115
0
                X265_FREE(curFrame->m_ctuInfo);
116
0
                curFrame->m_ctuInfo = NULL;
117
0
                X265_FREE(curFrame->m_prevCtuInfoChange);
118
0
                curFrame->m_prevCtuInfoChange = NULL;
119
0
            }
120
0
            curFrame->m_encData = NULL;
121
0
            curFrame->m_reconPic = NULL;
122
0
        }
123
698
    }
124
698
}
125
126
void DPB::prepareEncode(Frame *newFrame)
127
698
{
128
698
    Slice* slice = newFrame->m_encData->m_slice;
129
698
    slice->m_poc = newFrame->m_poc;
130
698
    slice->m_fieldNum = newFrame->m_fieldNum;
131
132
698
    int pocCurr = slice->m_poc;
133
698
    int type = newFrame->m_lowres.sliceType;
134
698
    bool bIsKeyFrame = newFrame->m_lowres.bKeyframe;
135
698
    slice->m_nalUnitType = getNalUnitType(pocCurr, bIsKeyFrame);
136
698
    if (slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)
137
698
        m_lastIDR = pocCurr;
138
698
    slice->m_lastIDR = m_lastIDR;
139
698
    slice->m_sliceType = IS_X265_TYPE_B(type) ? B_SLICE : (type == X265_TYPE_P) ? P_SLICE : I_SLICE;
140
141
698
    if (type == X265_TYPE_B)
142
0
    {
143
0
        newFrame->m_encData->m_bHasReferences = false;
144
145
        // Adjust NAL type for unreferenced B frames (change from _R "referenced"
146
        // to _N "non-referenced" NAL unit type)
147
0
        switch (slice->m_nalUnitType)
148
0
        {
149
0
        case NAL_UNIT_CODED_SLICE_TRAIL_R:
150
0
            slice->m_nalUnitType = m_bTemporalSublayer ? NAL_UNIT_CODED_SLICE_TSA_N : NAL_UNIT_CODED_SLICE_TRAIL_N;
151
0
            break;
152
0
        case NAL_UNIT_CODED_SLICE_RADL_R:
153
0
            slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RADL_N;
154
0
            break;
155
0
        case NAL_UNIT_CODED_SLICE_RASL_R:
156
0
            slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RASL_N;
157
0
            break;
158
0
        default:
159
0
            break;
160
0
        }
161
0
    }
162
698
    else
163
698
    {
164
        /* m_bHasReferences starts out as true for non-B pictures, and is set to false
165
         * once no more pictures reference it */
166
698
        newFrame->m_encData->m_bHasReferences = true;
167
698
    }
168
169
698
    m_picList.pushFront(*newFrame);
170
171
    // Do decoding refresh marking if any
172
698
    decodingRefreshMarking(pocCurr, slice->m_nalUnitType);
173
174
698
    computeRPS(pocCurr, slice->isIRAP(), &slice->m_rps, slice->m_sps->maxDecPicBuffering);
175
176
    // Mark pictures in m_piclist as unreferenced if they are not included in RPS
177
698
    applyReferencePictureSet(&slice->m_rps, pocCurr);
178
179
698
    if (slice->m_sliceType != I_SLICE)
180
0
        slice->m_numRefIdx[0] = x265_clip3(1, newFrame->m_param->maxNumReferences, slice->m_rps.numberOfNegativePictures);
181
698
    else
182
698
        slice->m_numRefIdx[0] = X265_MIN(newFrame->m_param->maxNumReferences, slice->m_rps.numberOfNegativePictures); // Ensuring L0 contains just the -ve POC
183
698
    slice->m_numRefIdx[1] = X265_MIN(newFrame->m_param->bBPyramid ? 2 : 1, slice->m_rps.numberOfPositivePictures);
184
698
    slice->setRefPicList(m_picList);
185
186
698
    X265_CHECK(slice->m_sliceType != B_SLICE || slice->m_numRefIdx[1], "B slice without L1 references (non-fatal)\n");
187
188
698
    if (slice->m_sliceType == B_SLICE)
189
0
    {
190
        /* TODO: the lookahead should be able to tell which reference picture
191
         * had the least motion residual.  We should be able to use that here to
192
         * select a colocation reference list and index */
193
0
        slice->m_colFromL0Flag = false;
194
0
        slice->m_colRefIdx = 0;
195
0
        slice->m_bCheckLDC = false;
196
0
    }
197
698
    else
198
698
    {
199
698
        slice->m_bCheckLDC = true;
200
698
        slice->m_colFromL0Flag = true;
201
698
        slice->m_colRefIdx = 0;
202
698
    }
203
204
    // Disable Loopfilter in bound area, because we will do slice-parallelism in future
205
698
    slice->m_sLFaseFlag = (newFrame->m_param->maxSlices > 1) ? false : ((SLFASE_CONSTANT & (1 << (pocCurr % 31))) > 0);
206
207
    /* Increment reference count of all motion-referenced frames to prevent them
208
     * from being recycled. These counts are decremented at the end of
209
     * compressFrame() */
210
698
    int numPredDir = slice->isInterP() ? 1 : slice->isInterB() ? 2 : 0;
211
698
    for (int l = 0; l < numPredDir; l++)
212
0
    {
213
0
        for (int ref = 0; ref < slice->m_numRefIdx[l]; ref++)
214
0
        {
215
0
            Frame *refpic = slice->m_refFrameList[l][ref];
216
0
            ATOMIC_INC(&refpic->m_countRefEncoders);
217
0
        }
218
0
    }
219
698
}
220
221
void DPB::computeRPS(int curPoc, bool isRAP, RPS * rps, unsigned int maxDecPicBuffer)
222
698
{
223
698
    unsigned int poci = 0, numNeg = 0, numPos = 0;
224
225
698
    Frame* iterPic = m_picList.first();
226
227
1.39k
    while (iterPic && (poci < maxDecPicBuffer - 1))
228
698
    {
229
698
        if ((iterPic->m_poc != curPoc) && iterPic->m_encData->m_bHasReferences)
230
0
        {
231
0
            if ((m_lastIDR >= curPoc) || (m_lastIDR <= iterPic->m_poc))
232
0
            {
233
0
                    rps->poc[poci] = iterPic->m_poc;
234
0
                    rps->deltaPOC[poci] = rps->poc[poci] - curPoc;
235
0
                    (rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++;
236
0
                    rps->bUsed[poci] = !isRAP;
237
0
                    poci++;
238
0
            }
239
0
        }
240
698
        iterPic = iterPic->m_next;
241
698
    }
242
243
698
    rps->numberOfPictures = poci;
244
698
    rps->numberOfPositivePictures = numPos;
245
698
    rps->numberOfNegativePictures = numNeg;
246
247
698
    rps->sortDeltaPOC();
248
698
}
249
250
/* Marking reference pictures when an IDR/CRA is encountered. */
251
void DPB::decodingRefreshMarking(int pocCurr, NalUnitType nalUnitType)
252
698
{
253
698
    if (nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP)
254
698
    {
255
        /* If the nal_unit_type is IDR, all pictures in the reference picture
256
         * list are marked as "unused for reference" */
257
698
        Frame* iterFrame = m_picList.first();
258
1.39k
        while (iterFrame)
259
698
        {
260
698
            if (iterFrame->m_poc != pocCurr)
261
0
                iterFrame->m_encData->m_bHasReferences = false;
262
698
            iterFrame = iterFrame->m_next;
263
698
        }
264
698
    }
265
0
    else // CRA or No DR
266
0
    {
267
0
        if (m_bRefreshPending && pocCurr > m_pocCRA)
268
0
        {
269
            /* If the bRefreshPending flag is true (a deferred decoding refresh
270
             * is pending) and the current temporal reference is greater than
271
             * the temporal reference of the latest CRA picture (pocCRA), mark
272
             * all reference pictures except the latest CRA picture as "unused
273
             * for reference" and set the bRefreshPending flag to false */
274
0
            Frame* iterFrame = m_picList.first();
275
0
            while (iterFrame)
276
0
            {
277
0
                if (iterFrame->m_poc != pocCurr && iterFrame->m_poc != m_pocCRA)
278
0
                    iterFrame->m_encData->m_bHasReferences = false;
279
0
                iterFrame = iterFrame->m_next;
280
0
            }
281
282
0
            m_bRefreshPending = false;
283
0
        }
284
0
        if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA)
285
0
        {
286
            /* If the nal_unit_type is CRA, set the bRefreshPending flag to true
287
             * and pocCRA to the temporal reference of the current picture */
288
0
            m_bRefreshPending = true;
289
0
            m_pocCRA = pocCurr;
290
0
        }
291
0
    }
292
293
    /* Note that the current picture is already placed in the reference list and
294
     * its marking is not changed.  If the current picture has a nal_ref_idc
295
     * that is not 0, it will remain marked as "used for reference" */
296
698
}
297
298
/** Function for applying picture marking based on the Reference Picture Set */
299
void DPB::applyReferencePictureSet(RPS *rps, int curPoc)
300
698
{
301
    // loop through all pictures in the reference picture buffer
302
698
    Frame* iterFrame = m_picList.first();
303
1.39k
    while (iterFrame)
304
698
    {
305
698
        if (iterFrame->m_poc != curPoc && iterFrame->m_encData->m_bHasReferences)
306
0
        {
307
            // loop through all pictures in the Reference Picture Set
308
            // to see if the picture should be kept as reference picture
309
0
            bool referenced = false;
310
0
            for (int i = 0; i < rps->numberOfPositivePictures + rps->numberOfNegativePictures; i++)
311
0
            {
312
0
                if (iterFrame->m_poc == curPoc + rps->deltaPOC[i])
313
0
                {
314
0
                    referenced = true;
315
0
                    break;
316
0
                }
317
0
            }
318
0
            if (!referenced)
319
0
                iterFrame->m_encData->m_bHasReferences = false;
320
0
        }
321
698
        iterFrame = iterFrame->m_next;
322
698
    }
323
698
}
324
325
/* deciding the nal_unit_type */
326
NalUnitType DPB::getNalUnitType(int curPOC, bool bIsKeyFrame)
327
698
{
328
698
    if (!curPOC)
329
698
        return NAL_UNIT_CODED_SLICE_IDR_N_LP;
330
0
    if (bIsKeyFrame)
331
0
        return m_bOpenGOP ? NAL_UNIT_CODED_SLICE_CRA : m_bhasLeadingPicture ? NAL_UNIT_CODED_SLICE_IDR_W_RADL : NAL_UNIT_CODED_SLICE_IDR_N_LP;
332
0
    if (m_pocCRA && curPOC < m_pocCRA)
333
        // All leading pictures are being marked as TFD pictures here since
334
        // current encoder uses all reference pictures while encoding leading
335
        // pictures. An encoder can ensure that a leading picture can be still
336
        // decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by
337
        // controlling the reference pictures used for encoding that leading
338
        // picture. Such a leading picture need not be marked as a TFD picture.
339
0
        return NAL_UNIT_CODED_SLICE_RASL_R;
340
341
0
    if (m_lastIDR && curPOC < m_lastIDR)
342
0
        return NAL_UNIT_CODED_SLICE_RADL_R;
343
344
0
    return NAL_UNIT_CODED_SLICE_TRAIL_R;
345
0
}