Update changelog.
[deb_x265.git] / source / encoder / dpb.cpp
CommitLineData
72b9787e
JB
1/*****************************************************************************
2 * Copyright (C) 2013 x265 project
3 *
4 * Authors: Steve Borho <steve@borho.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
19 *
20 * This program is also available under a commercial proprietary license.
21 * For more information, contact us at license @ x265.com.
22 *****************************************************************************/
23
24#include "common.h"
25#include "frame.h"
26#include "framedata.h"
27#include "picyuv.h"
28#include "slice.h"
29
30#include "dpb.h"
31
32using namespace x265;
33
34DPB::~DPB()
35{
36 while (!m_freeList.empty())
37 {
38 Frame* curFrame = m_freeList.popFront();
39 curFrame->destroy();
40 delete curFrame;
41 }
42
43 while (!m_picList.empty())
44 {
45 Frame* curFrame = m_picList.popFront();
46 curFrame->destroy();
47 delete curFrame;
48 }
49
50 while (m_picSymFreeList)
51 {
52 FrameData* next = m_picSymFreeList->m_freeListNext;
53 m_picSymFreeList->destroy();
54
55 m_picSymFreeList->m_reconPicYuv->destroy();
56 delete m_picSymFreeList->m_reconPicYuv;
57
58 delete m_picSymFreeList;
59 m_picSymFreeList = next;
60 }
61}
62
63// move unreferenced pictures from picList to freeList for recycle
64void DPB::recycleUnreferenced()
65{
66 Frame *iterFrame = m_picList.first();
67
68 while (iterFrame)
69 {
70 Frame *curFrame = iterFrame;
71 iterFrame = iterFrame->m_next;
72 if (!curFrame->m_encData->m_bHasReferences && !curFrame->m_countRefEncoders)
73 {
74 curFrame->m_reconRowCount.set(0);
75 curFrame->m_bChromaExtended = false;
76
77 // iterator is invalidated by remove, restart scan
78 m_picList.remove(*curFrame);
79 iterFrame = m_picList.first();
80
81 m_freeList.pushBack(*curFrame);
82 curFrame->m_encData->m_freeListNext = m_picSymFreeList;
83 m_picSymFreeList = curFrame->m_encData;
84 curFrame->m_encData = NULL;
85 curFrame->m_reconPicYuv = NULL;
86 }
87 }
88}
89
90void DPB::prepareEncode(Frame *newFrame)
91{
92 Slice* slice = newFrame->m_encData->m_slice;
93 slice->m_poc = newFrame->m_poc;
94
95 int pocCurr = slice->m_poc;
96 int type = newFrame->m_lowres.sliceType;
97 bool bIsKeyFrame = newFrame->m_lowres.bKeyframe;
98
99 slice->m_nalUnitType = getNalUnitType(pocCurr, bIsKeyFrame);
100 if (slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL)
101 m_lastIDR = pocCurr;
102 slice->m_lastIDR = m_lastIDR;
103 slice->m_sliceType = IS_X265_TYPE_B(type) ? B_SLICE : (type == X265_TYPE_P) ? P_SLICE : I_SLICE;
104
105 if (type == X265_TYPE_B)
106 {
107 // change from _R "referenced" to _N "non-referenced" NAL unit type
108 switch (slice->m_nalUnitType)
109 {
110 case NAL_UNIT_CODED_SLICE_TRAIL_R:
111 slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_TRAIL_N;
112 break;
113 case NAL_UNIT_CODED_SLICE_RADL_R:
114 slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RADL_N;
115 break;
116 case NAL_UNIT_CODED_SLICE_RASL_R:
117 slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RASL_N;
118 break;
119 default:
120 break;
121 }
122 }
123
124 /* m_bHasReferences starts out as true for non-B pictures, and is set to false
125 * once no more pictures reference it */
126 newFrame->m_encData->m_bHasReferences = IS_REFERENCED(newFrame);
127
128 m_picList.pushFront(*newFrame);
129
130 // Do decoding refresh marking if any
131 decodingRefreshMarking(pocCurr, slice->m_nalUnitType);
132
133 computeRPS(pocCurr, slice->isIRAP(), &slice->m_rps, slice->m_sps->maxDecPicBuffering);
134
135 // Mark pictures in m_piclist as unreferenced if they are not included in RPS
136 applyReferencePictureSet(&slice->m_rps, pocCurr);
137
138 slice->m_numRefIdx[0] = X265_MIN(m_maxRefL0, slice->m_rps.numberOfNegativePictures); // Ensuring L0 contains just the -ve POC
139 slice->m_numRefIdx[1] = X265_MIN(m_maxRefL1, slice->m_rps.numberOfPositivePictures);
140 slice->setRefPicList(m_picList);
141
142 X265_CHECK(slice->m_sliceType != B_SLICE || slice->m_numRefIdx[1], "B slice without L1 references (non-fatal)\n");
143
144 if (slice->m_sliceType == B_SLICE)
145 {
146 /* TODO: the lookahead should be able to tell which reference picture
147 * had the least motion residual. We should be able to use that here to
148 * select a colocation reference list and index */
149 slice->m_colFromL0Flag = false;
150 slice->m_colRefIdx = 0;
151 slice->m_bCheckLDC = false;
152 }
153 else
154 {
155 slice->m_bCheckLDC = true;
156 slice->m_colFromL0Flag = true;
157 slice->m_colRefIdx = 0;
158 }
159 slice->m_sLFaseFlag = (SLFASE_CONSTANT & (1 << (pocCurr % 31))) > 0;
160
161 /* Increment reference count of all motion-referenced frames to prevent them
162 * from being recycled. These counts are decremented at the end of
163 * compressFrame() */
164 int numPredDir = slice->isInterP() ? 1 : slice->isInterB() ? 2 : 0;
165 for (int l = 0; l < numPredDir; l++)
166 {
167 for (int ref = 0; ref < slice->m_numRefIdx[l]; ref++)
168 {
169 Frame *refpic = slice->m_refPicList[l][ref];
170 ATOMIC_INC(&refpic->m_countRefEncoders);
171 }
172 }
173}
174
175void DPB::computeRPS(int curPoc, bool isRAP, RPS * rps, unsigned int maxDecPicBuffer)
176{
177 unsigned int poci = 0, numNeg = 0, numPos = 0;
178
179 Frame* iterPic = m_picList.first();
180
181 while (iterPic && (poci < maxDecPicBuffer - 1))
182 {
183 if ((iterPic->m_poc != curPoc) && iterPic->m_encData->m_bHasReferences)
184 {
185 rps->poc[poci] = iterPic->m_poc;
186 rps->deltaPOC[poci] = rps->poc[poci] - curPoc;
187 (rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++;
188 rps->bUsed[poci] = !isRAP;
189 poci++;
190 }
191 iterPic = iterPic->m_next;
192 }
193
194 rps->numberOfPictures = poci;
195 rps->numberOfPositivePictures = numPos;
196 rps->numberOfNegativePictures = numNeg;
197
198 rps->sortDeltaPOC();
199}
200
201/* Marking reference pictures when an IDR/CRA is encountered. */
202void DPB::decodingRefreshMarking(int pocCurr, NalUnitType nalUnitType)
203{
204 if (nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL)
205 {
206 /* If the nal_unit_type is IDR, all pictures in the reference picture
207 * list are marked as "unused for reference" */
208 Frame* iterFrame = m_picList.first();
209 while (iterFrame)
210 {
211 if (iterFrame->m_poc != pocCurr)
212 iterFrame->m_encData->m_bHasReferences = false;
213 iterFrame = iterFrame->m_next;
214 }
215 }
216 else // CRA or No DR
217 {
218 if (m_bRefreshPending && pocCurr > m_pocCRA)
219 {
220 /* If the bRefreshPending flag is true (a deferred decoding refresh
221 * is pending) and the current temporal reference is greater than
222 * the temporal reference of the latest CRA picture (pocCRA), mark
223 * all reference pictures except the latest CRA picture as "unused
224 * for reference" and set the bRefreshPending flag to false */
225 Frame* iterFrame = m_picList.first();
226 while (iterFrame)
227 {
228 if (iterFrame->m_poc != pocCurr && iterFrame->m_poc != m_pocCRA)
229 iterFrame->m_encData->m_bHasReferences = false;
230 iterFrame = iterFrame->m_next;
231 }
232
233 m_bRefreshPending = false;
234 }
235 if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA)
236 {
237 /* If the nal_unit_type is CRA, set the bRefreshPending flag to true
238 * and pocCRA to the temporal reference of the current picture */
239 m_bRefreshPending = true;
240 m_pocCRA = pocCurr;
241 }
242 }
243
244 /* Note that the current picture is already placed in the reference list and
245 * its marking is not changed. If the current picture has a nal_ref_idc
246 * that is not 0, it will remain marked as "used for reference" */
247}
248
249/** Function for applying picture marking based on the Reference Picture Set */
250void DPB::applyReferencePictureSet(RPS *rps, int curPoc)
251{
252 // loop through all pictures in the reference picture buffer
253 Frame* iterFrame = m_picList.first();
254 while (iterFrame)
255 {
256 if (iterFrame->m_poc != curPoc && iterFrame->m_encData->m_bHasReferences)
257 {
258 // loop through all pictures in the Reference Picture Set
259 // to see if the picture should be kept as reference picture
260 bool referenced = false;
261 for (int i = 0; i < rps->numberOfPositivePictures + rps->numberOfNegativePictures; i++)
262 {
263 if (iterFrame->m_poc == curPoc + rps->deltaPOC[i])
264 {
265 referenced = true;
266 break;
267 }
268 }
269 if (!referenced)
270 iterFrame->m_encData->m_bHasReferences = false;
271 }
272 iterFrame = iterFrame->m_next;
273 }
274}
275
276/* deciding the nal_unit_type */
277NalUnitType DPB::getNalUnitType(int curPOC, bool bIsKeyFrame)
278{
279 if (!curPOC)
280 return NAL_UNIT_CODED_SLICE_IDR_W_RADL;
281
282 if (bIsKeyFrame)
283 return m_bOpenGOP ? NAL_UNIT_CODED_SLICE_CRA : NAL_UNIT_CODED_SLICE_IDR_W_RADL;
284
285 if (m_pocCRA && curPOC < m_pocCRA)
286 // All leading pictures are being marked as TFD pictures here since
287 // current encoder uses all reference pictures while encoding leading
288 // pictures. An encoder can ensure that a leading picture can be still
289 // decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by
290 // controlling the reference pictures used for encoding that leading
291 // picture. Such a leading picture need not be marked as a TFD picture.
292 return NAL_UNIT_CODED_SLICE_RASL_R;
293
294 if (m_lastIDR && curPOC < m_lastIDR)
295 return NAL_UNIT_CODED_SLICE_RADL_R;
296
297 return NAL_UNIT_CODED_SLICE_TRAIL_R;
298}