1 /*
2 * Copyright (c) 2019, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file decode_hevc_reference_frames.cpp
24 //! \brief Defines reference list related logic for hevc decode
25 //!
26
27 #include "decode_hevc_basic_feature.h"
28 #include "decode_utils.h"
29 #include "codec_utilities_next.h"
30 #include "decode_hevc_reference_frames.h"
31 #include "codec_def_decode_hevc.h"
32
33 namespace decode
34 {
35
HevcReferenceFrames()36 HevcReferenceFrames::HevcReferenceFrames()
37 {
38 memset(m_refList, 0, sizeof(m_refList));
39 }
40
Init(HevcBasicFeature * basicFeature,DecodeAllocator & allocator)41 MOS_STATUS HevcReferenceFrames::Init(HevcBasicFeature *basicFeature, DecodeAllocator& allocator)
42 {
43 DECODE_FUNC_CALL();
44 DECODE_CHK_NULL(basicFeature);
45
46 m_basicFeature = basicFeature;
47 m_allocator = &allocator;
48 DECODE_CHK_STATUS(CodecUtilities::CodecHalAllocateDataList(m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC));
49
50 m_osInterface = basicFeature->GetOsInterface();
51
52 return MOS_STATUS_SUCCESS;
53 }
54
~HevcReferenceFrames()55 HevcReferenceFrames::~HevcReferenceFrames()
56 {
57 DECODE_FUNC_CALL();
58 CodecUtilities::CodecHalFreeDataList(m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC);
59 m_activeReferenceList.clear();
60 }
61
UpdatePicture(CODEC_HEVC_PIC_PARAMS & picParams,bool isSCCIBCMode)62 MOS_STATUS HevcReferenceFrames::UpdatePicture(CODEC_HEVC_PIC_PARAMS & picParams, bool isSCCIBCMode)
63 {
64 DECODE_FUNC_CALL();
65
66 DECODE_CHK_STATUS(DetectPocDuplication(picParams.PicOrderCntValList, picParams.RefFrameList));
67 DECODE_CHK_STATUS(UpdateCurFrame(picParams, isSCCIBCMode));
68 DECODE_CHK_STATUS(UpdateCurRefList(picParams, isSCCIBCMode));
69 DECODE_CHK_STATUS(UpdateRefIdxMapping(picParams, isSCCIBCMode));
70 DECODE_CHK_STATUS(UpdateRefCachePolicy(picParams));
71
72 return MOS_STATUS_SUCCESS;
73 }
74
GetActiveReferenceList(const CODEC_HEVC_PIC_PARAMS & picParams)75 const std::vector<uint8_t> & HevcReferenceFrames::GetActiveReferenceList(const CODEC_HEVC_PIC_PARAMS & picParams)
76 {
77 DECODE_FUNC_CALL();
78
79 m_activeReferenceList.clear();
80
81 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
82 {
83 if (m_frameUsedAsCurRef[i])
84 {
85 m_activeReferenceList.push_back(picParams.RefFrameList[i].FrameIdx);
86 }
87 }
88
89 return m_activeReferenceList;
90 }
91
GetReferenceByFrameIndex(uint8_t frameIndex)92 PMOS_RESOURCE HevcReferenceFrames::GetReferenceByFrameIndex(uint8_t frameIndex)
93 {
94 DECODE_FUNC_CALL();
95
96 if (frameIndex >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC)
97 {
98 DECODE_ASSERTMESSAGE("Invalid reference frame index");
99 return nullptr;
100 }
101
102 PCODEC_REF_LIST ref = m_refList[frameIndex];
103
104 if (ref == nullptr || m_allocator->ResourceIsNull(&(ref->resRefPic)))
105 {
106 return nullptr;
107 }
108
109 return &(ref->resRefPic);
110 }
111
GetValidReference()112 PMOS_RESOURCE HevcReferenceFrames::GetValidReference()
113 {
114 DECODE_FUNC_CALL();
115
116 if (m_basicFeature->m_hevcPicParams == nullptr)
117 {
118 return nullptr;
119 }
120 auto picParams = m_basicFeature->m_hevcPicParams;
121
122 for(uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
123 {
124 uint8_t frameIdx = picParams->RefFrameList[i].FrameIdx;
125 if (frameIdx >= m_basicFeature->m_maxFrameIndex)
126 {
127 continue;
128 }
129
130 PMOS_RESOURCE buffer = GetReferenceByFrameIndex(frameIdx);
131 if (buffer != nullptr)
132 {
133 return buffer;
134 }
135 }
136
137 return &(m_basicFeature->m_destSurface.OsResource);
138 }
139
UpdateCurResource(const CODEC_HEVC_PIC_PARAMS & picParams,bool isSCCIBCMode)140 MOS_STATUS HevcReferenceFrames::UpdateCurResource(const CODEC_HEVC_PIC_PARAMS &picParams, bool isSCCIBCMode)
141 {
142 DECODE_FUNC_CALL();
143
144 PCODEC_REF_LIST destEntry = m_refList[picParams.CurrPic.FrameIdx];
145
146 if (isSCCIBCMode)
147 {
148 bool twoVersionsOfCurrDecPicFlag = (!picParams.pps_deblocking_filter_disabled_flag) ||
149 picParams.sample_adaptive_offset_enabled_flag ||
150 picParams.deblocking_filter_override_enabled_flag;
151 #ifdef _MMC_SUPPORTED
152 // Due to limitation, IBC reference has to be uncompressed, while recon surface is still compressed.
153 // Always need internal surface for IBC reference while MMC is enabled.
154 if (m_basicFeature->IsMmcEnabled())
155 {
156 twoVersionsOfCurrDecPicFlag = true;
157 }
158 #endif
159 if (twoVersionsOfCurrDecPicFlag)
160 {
161 // In downsampling case, m_referenceBeforeLoopFilter will be allocated by downsampling feature later.
162 if(m_basicFeature->m_referenceBeforeLoopFilter != nullptr)
163 {
164 destEntry->resRefPic = m_basicFeature->m_referenceBeforeLoopFilter->OsResource;
165 }
166 }
167 else
168 {
169 destEntry->resRefPic = m_basicFeature->m_destSurface.OsResource;
170 }
171 }
172 else
173 {
174 destEntry->resRefPic = m_basicFeature->m_destSurface.OsResource;
175 }
176
177 return MOS_STATUS_SUCCESS;
178 }
179
UpdateCurFrame(const CODEC_HEVC_PIC_PARAMS & picParams,bool isSCCIBCMode)180 MOS_STATUS HevcReferenceFrames::UpdateCurFrame(const CODEC_HEVC_PIC_PARAMS & picParams, bool isSCCIBCMode)
181 {
182 DECODE_FUNC_CALL();
183
184 DECODE_CHK_COND(picParams.CurrPic.FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC,
185 "Invalid frame index of current frame");
186 PCODEC_REF_LIST destEntry = m_refList[picParams.CurrPic.FrameIdx];
187 MOS_ZeroMemory(destEntry, sizeof(CODEC_REF_LIST));
188
189 DECODE_CHK_STATUS(UpdateCurResource(picParams, isSCCIBCMode));
190
191 if (isSCCIBCMode)
192 {
193 m_curIsIntra = false;
194 }
195 else
196 {
197 m_curIsIntra = !IsCurFrameUseReference(picParams);
198 }
199
200 destEntry->RefPic = picParams.CurrPic;
201 destEntry->sFrameNumber = int16_t(picParams.CurrPicOrderCntVal);
202 destEntry->iFieldOrderCnt[0] = picParams.CurrPicOrderCntVal;
203 destEntry->bIsIntra = m_curIsIntra;
204
205 for(auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
206 {
207 destEntry->RefList[i] = picParams.RefFrameList[i];
208 }
209
210 return MOS_STATUS_SUCCESS;
211 }
212
UpdateCurRefList(const CODEC_HEVC_PIC_PARAMS & picParams,bool isSCCIBCMode)213 MOS_STATUS HevcReferenceFrames::UpdateCurRefList(const CODEC_HEVC_PIC_PARAMS & picParams, bool isSCCIBCMode)
214 {
215 DECODE_FUNC_CALL();
216
217 // Override reference list with ref surface passed from DDI if needed
218 uint8_t surfCount = 0;
219 uint8_t surfIndex = 0;
220 if (m_osInterface->pfnIsMismatchOrderProgrammingSupported())
221 {
222 while (surfIndex < CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC)
223 {
224 if (!m_allocator->ResourceIsNull(&m_basicFeature->m_refFrameSurface[surfIndex].OsResource))
225 {
226 m_refList[surfIndex]->resRefPic = m_basicFeature->m_refFrameSurface[surfIndex].OsResource;
227 }
228 surfIndex++;
229 }
230 }
231 else
232 {
233 while (surfCount < m_basicFeature->m_refSurfaceNum && surfIndex < CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC)
234 {
235 if (!m_allocator->ResourceIsNull(&m_basicFeature->m_refFrameSurface[surfIndex].OsResource))
236 {
237 m_refList[surfIndex]->resRefPic = m_basicFeature->m_refFrameSurface[surfIndex].OsResource;
238 surfCount++;
239 }
240 surfIndex++;
241 }
242 }
243
244 memset(m_frameUsedAsCurRef, 0, sizeof(m_frameUsedAsCurRef));
245
246 for (auto i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
247 {
248 uint8_t index = picParams.RefPicSetStCurrBefore[i];
249 if (index < CODEC_MAX_NUM_REF_FRAME_HEVC)
250 {
251 m_frameUsedAsCurRef[index] = true;
252 }
253
254 index = picParams.RefPicSetStCurrAfter[i];
255 if (index < CODEC_MAX_NUM_REF_FRAME_HEVC)
256 {
257 m_frameUsedAsCurRef[index] = true;
258 }
259
260 index = picParams.RefPicSetLtCurr[i];
261 if (index < CODEC_MAX_NUM_REF_FRAME_HEVC)
262 {
263 m_frameUsedAsCurRef[index] = true;
264 }
265 }
266
267 if (isSCCIBCMode)
268 {
269 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
270 {
271 if (picParams.PicOrderCntValList[i] == picParams.CurrPicOrderCntVal)
272 {
273 m_frameUsedAsCurRef[i] = !CodecHal_PictureIsInvalid(picParams.RefFrameList[i]);
274 break;
275 }
276 }
277 }
278 else
279 {
280 uint8_t refCurrIndex = -1;
281 uint8_t refBeforeIndex = -1;
282 uint8_t refAfterIndex = -1;
283
284 for (auto i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
285 {
286 uint8_t indexCurr = picParams.RefPicSetLtCurr[i];
287 uint8_t indexBefore = picParams.RefPicSetStCurrBefore[i];
288 uint8_t indexAfter = picParams.RefPicSetStCurrAfter[i];
289
290 if (indexCurr < CODEC_MAX_NUM_REF_FRAME_HEVC)
291 {
292 refCurrIndex = picParams.RefFrameList[indexCurr].FrameIdx;
293 }
294 if (indexBefore < CODEC_MAX_NUM_REF_FRAME_HEVC)
295 {
296 refBeforeIndex = picParams.RefFrameList[indexBefore].FrameIdx;
297 }
298 if (indexAfter < CODEC_MAX_NUM_REF_FRAME_HEVC)
299 {
300 refAfterIndex = picParams.RefFrameList[indexAfter].FrameIdx;
301 }
302
303 if ((refCurrIndex == picParams.CurrPic.FrameIdx) || (refBeforeIndex == picParams.CurrPic.FrameIdx) || (refAfterIndex == picParams.CurrPic.FrameIdx))
304 {
305 return MOS_STATUS_INVALID_PARAMETER;
306 }
307 }
308 }
309
310 return MOS_STATUS_SUCCESS;
311 }
312
UpdateRefIdxMapping(const CODEC_HEVC_PIC_PARAMS & picParams,bool isSCCIBCMode)313 MOS_STATUS HevcReferenceFrames::UpdateRefIdxMapping(const CODEC_HEVC_PIC_PARAMS & picParams, bool isSCCIBCMode)
314 {
315 DECODE_FUNC_CALL();
316
317 memset(m_refIdxMapping, -1, sizeof(m_refIdxMapping));
318 m_IBCRefIdx = 0;
319
320 uint8_t curRefIdx = 0;
321 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
322 {
323 if (m_frameUsedAsCurRef[i])
324 {
325 if (isSCCIBCMode &&
326 picParams.PicOrderCntValList[i] == picParams.CurrPicOrderCntVal)
327 {
328 // pre-dbk reference id for IBC mode
329 m_IBCRefIdx = curRefIdx;
330 }
331 m_refIdxMapping[i] = curRefIdx++;
332 }
333 }
334
335 DECODE_CHK_COND(curRefIdx > 8, "Invalid reference number for current frame");
336
337 return MOS_STATUS_SUCCESS;
338 }
339
UpdateRefCachePolicy(const CODEC_HEVC_PIC_PARAMS & picParams)340 MOS_STATUS HevcReferenceFrames::UpdateRefCachePolicy(const CODEC_HEVC_PIC_PARAMS &picParams)
341 {
342 DECODE_FUNC_CALL();
343 MOS_STATUS sts = MOS_STATUS_SUCCESS;
344
345 HevcReferenceFrames &refFrames = m_basicFeature->m_refFrames;
346 const std::vector<uint8_t> &activeRefList = refFrames.GetActiveReferenceList(picParams);
347 if (!refFrames.m_curIsIntra)
348 {
349 for (uint8_t i = 0; i < activeRefList.size(); i++)
350 {
351 uint8_t frameIdx = activeRefList[i];
352 if (frameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_HEVC)
353 {
354 continue;
355 }
356 sts = m_allocator->UpdateResoreceUsageType(&m_refList[frameIdx]->resRefPic, resourceInputReference);
357 if (sts != MOS_STATUS_SUCCESS)
358 {
359 DECODE_NORMALMESSAGE("GetReferenceByFrameIndex invalid\n");
360 }
361 }
362 }
363
364 return MOS_STATUS_SUCCESS;
365 }
366
IsCurFrameUseReference(const CODEC_HEVC_PIC_PARAMS & picParams)367 bool HevcReferenceFrames::IsCurFrameUseReference(const CODEC_HEVC_PIC_PARAMS & picParams)
368 {
369 DECODE_FUNC_CALL();
370
371 bool useRef = false;
372 if (picParams.IntraPicFlag == 0)
373 {
374 for (uint32_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
375 {
376 uint8_t index = picParams.RefPicSetStCurrBefore[i];
377 if (index < CODEC_MAX_NUM_REF_FRAME_HEVC)
378 {
379 useRef = true;
380 break;
381 }
382
383 index = picParams.RefPicSetStCurrAfter[i];
384 if (index < CODEC_MAX_NUM_REF_FRAME_HEVC)
385 {
386 useRef = true;
387 break;
388 }
389
390 index = picParams.RefPicSetLtCurr[i];
391 if (index < CODEC_MAX_NUM_REF_FRAME_HEVC)
392 {
393 useRef = true;
394 break;
395 }
396 }
397 }
398
399 return useRef;
400 }
401
DetectPocDuplication(const int32_t (& picOrderCntValList)[CODEC_MAX_NUM_REF_FRAME_HEVC],CODEC_PICTURE (& refFrameList)[CODEC_MAX_NUM_REF_FRAME_HEVC])402 MOS_STATUS HevcReferenceFrames::DetectPocDuplication(const int32_t (&picOrderCntValList)[CODEC_MAX_NUM_REF_FRAME_HEVC],
403 CODEC_PICTURE (&refFrameList)[CODEC_MAX_NUM_REF_FRAME_HEVC])
404 {
405 DECODE_FUNC_CALL();
406
407 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
408 {
409 m_duplicationPocMap[i].clear();
410 }
411
412 bool pocListFilter[CODEC_MAX_NUM_REF_FRAME_HEVC]; // Marker to indicate if poc already be filtered
413 memset(pocListFilter, 0, sizeof(pocListFilter));
414
415 for (int8_t m = 0; m < CODEC_MAX_NUM_REF_FRAME_HEVC; m++)
416 {
417 if (pocListFilter[m] || (picOrderCntValList[m] == m_invalidPocValue))
418 {
419 continue;
420 }
421 pocListFilter[m] = true;
422
423 for (int8_t n = m + 1; n < CODEC_MAX_NUM_REF_FRAME_HEVC; n++)
424 {
425 if (picOrderCntValList[m] == picOrderCntValList[n])
426 {
427 pocListFilter[n] = true;
428 m_duplicationPocMap[m].push_back(n);
429
430 refFrameList[n].PicFlags = PICTURE_INVALID;
431 }
432 }
433 }
434
435 return MOS_STATUS_SUCCESS;
436 }
437
FixSliceRefList(const CODEC_HEVC_PIC_PARAMS & picParams,CODEC_HEVC_SLICE_PARAMS & slc)438 MOS_STATUS HevcReferenceFrames::FixSliceRefList(const CODEC_HEVC_PIC_PARAMS & picParams,
439 CODEC_HEVC_SLICE_PARAMS & slc)
440 {
441 DECODE_FUNC_CALL();
442
443 for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
444 {
445 if (m_duplicationPocMap[i].size() == 0)
446 {
447 continue;
448 }
449
450 for (auto dupIdx : m_duplicationPocMap[i])
451 {
452 for (auto k = 0; k < 2; k++)
453 {
454 for (auto j = 0; j < CODEC_MAX_NUM_REF_FRAME_HEVC; j++)
455 {
456 if (slc.RefPicList[k][j].FrameIdx == picParams.RefFrameList[dupIdx].FrameIdx)
457 {
458 slc.RefPicList[k][j].FrameIdx = picParams.RefFrameList[i].FrameIdx;
459 slc.RefPicList[k][j].PicEntry = picParams.RefFrameList[i].PicEntry;
460 slc.RefPicList[k][j].PicFlags = picParams.RefFrameList[i].PicFlags;
461 }
462 }
463 }
464 }
465 }
466
467 return MOS_STATUS_SUCCESS;
468 }
469
470 } // namespace decode
471