1 /*
2 * Copyright (c) 2020, 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_avc_reference_frames.cpp
24 //! \brief    Defines reference list related logic for avc decode
25 //!
26 
27 #include "decode_avc_basic_feature.h"
28 #include "decode_utils.h"
29 #include "codec_utilities_next.h"
30 #include "decode_avc_reference_frames.h"
31 #include "codec_def_decode_avc.h"
32 
33 namespace decode
34 {
35 
AvcReferenceFrames()36     AvcReferenceFrames::AvcReferenceFrames()
37     {
38         MOS_ZeroMemory(m_refList, sizeof(PCODEC_REF_LIST)* CODEC_AVC_NUM_UNCOMPRESSED_SURFACE);
39         MOS_ZeroMemory(&m_prevPic, sizeof(m_prevPic));
40         MOS_ZeroMemory(&m_avcPicIdx, (sizeof(CODEC_PIC_ID) * CODEC_AVC_MAX_NUM_REF_FRAME));
41         MOS_ZeroMemory(&m_avcFrameStoreId, (sizeof(CODEC_AVC_FRAME_STORE_ID) * CODEC_AVC_MAX_NUM_REF_FRAME));
42     }
43 
Init(AvcBasicFeature * basicFeature,DecodeAllocator & allocator)44     MOS_STATUS AvcReferenceFrames::Init(AvcBasicFeature *basicFeature, DecodeAllocator& allocator)
45     {
46         DECODE_FUNC_CALL();
47         DECODE_CHK_NULL(basicFeature);
48 
49         m_basicFeature = basicFeature;
50         m_allocator = &allocator;
51         DECODE_CHK_STATUS(CodecUtilities::CodecHalAllocateDataList(m_refList, CODEC_AVC_NUM_UNCOMPRESSED_SURFACE));
52         m_prevPic.PicFlags = PICTURE_INVALID;
53         m_prevPic.FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE;
54         m_osInterface = basicFeature->GetOsInterface();
55 
56         return MOS_STATUS_SUCCESS;
57     }
58 
~AvcReferenceFrames()59     AvcReferenceFrames::~AvcReferenceFrames()
60     {
61         DECODE_FUNC_CALL();
62         CodecUtilities::CodecHalFreeDataList(m_refList, CODEC_AVC_NUM_UNCOMPRESSED_SURFACE);
63         m_activeReferenceList.clear();
64     }
65 
UpdatePicture(CODEC_AVC_PIC_PARAMS & picParams)66     MOS_STATUS AvcReferenceFrames::UpdatePicture(CODEC_AVC_PIC_PARAMS & picParams)
67     {
68         DECODE_FUNC_CALL();
69 
70         DECODE_CHK_STATUS(UpdateCurFrame(picParams));
71         DECODE_CHK_STATUS(UpdateCurRefList(picParams));
72         DECODE_CHK_STATUS(UpdateRefCachePolicy(picParams));
73 
74         return MOS_STATUS_SUCCESS;
75     }
76 
GetActiveReferenceList(const CODEC_AVC_PIC_PARAMS & picParams)77     const std::vector<uint8_t> & AvcReferenceFrames::GetActiveReferenceList(const CODEC_AVC_PIC_PARAMS & picParams)
78     {
79         DECODE_FUNC_CALL();
80 
81         m_activeReferenceList.clear();
82 
83         for (auto i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
84         {
85             if (!CodecHal_PictureIsInvalid(picParams.RefFrameList[i]))
86             {
87                 if (picParams.RefFrameList[i].FrameIdx >= m_basicFeature->m_maxFrameIndex)
88                 {
89                     continue;
90                 }
91                 m_activeReferenceList.push_back(picParams.RefFrameList[i].FrameIdx);
92             }
93         }
94 
95         return m_activeReferenceList;
96     }
97 
GetReferenceByFrameIndex(uint8_t frameIndex)98     PMOS_RESOURCE AvcReferenceFrames::GetReferenceByFrameIndex(uint8_t frameIndex)
99     {
100         DECODE_FUNC_CALL();
101 
102         if (frameIndex >= CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
103         {
104             DECODE_ASSERTMESSAGE("Invalid reference frame index");
105             return nullptr;
106         }
107 
108         PCODEC_REF_LIST ref = m_refList[frameIndex];
109 
110         if (ref == nullptr || m_allocator->ResourceIsNull(&(ref->resRefPic)))
111         {
112             return nullptr;
113         }
114 
115         return &(ref->resRefPic);
116     }
117 
GetValidReference()118     PMOS_RESOURCE AvcReferenceFrames::GetValidReference()
119     {
120         DECODE_FUNC_CALL();
121 
122         if (m_basicFeature->m_avcPicParams == nullptr)
123         {
124             return nullptr;
125         }
126         auto picParams = m_basicFeature->m_avcPicParams;
127 
128         for (uint32_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
129         {
130             uint8_t frameIdx = picParams->RefFrameList[i].FrameIdx;
131             if (frameIdx >= m_basicFeature->m_maxFrameIndex)
132             {
133                 continue;
134             }
135 
136             PMOS_RESOURCE buffer = GetReferenceByFrameIndex(frameIdx);
137             if (buffer != nullptr)
138             {
139                 return buffer;
140             }
141         }
142 
143         return &(m_basicFeature->m_destSurface.OsResource);
144     }
145 
UpdateCurResource(const CODEC_AVC_PIC_PARAMS & picParams)146      MOS_STATUS AvcReferenceFrames::UpdateCurResource(const CODEC_AVC_PIC_PARAMS &picParams)
147     {
148         DECODE_FUNC_CALL();
149 
150         PCODEC_REF_LIST destEntry = m_refList[picParams.CurrPic.FrameIdx];
151         destEntry->resRefPic = m_basicFeature->m_destSurface.OsResource;
152 
153         return MOS_STATUS_SUCCESS;
154     }
155 
UpdateCurFrame(const CODEC_AVC_PIC_PARAMS & picParams)156     MOS_STATUS AvcReferenceFrames::UpdateCurFrame(const CODEC_AVC_PIC_PARAMS & picParams)
157     {
158         DECODE_FUNC_CALL();
159 
160         CODEC_PICTURE currPic = picParams.CurrPic;
161         DECODE_CHK_COND(currPic.FrameIdx >= CODEC_AVC_NUM_UNCOMPRESSED_SURFACE,
162                         "Invalid frame index of current frame");
163         PCODEC_REF_LIST destEntry = m_refList[currPic.FrameIdx];
164 
165         DECODE_CHK_STATUS(UpdateCurResource(picParams));
166 
167         //MVC related inter-view reference
168         destEntry->bUsedAsInterViewRef = false;
169         if (m_basicFeature->m_mvcExtPicParams)
170         {
171             if (m_basicFeature->m_mvcExtPicParams->inter_view_flag)
172             {
173                 destEntry->bUsedAsInterViewRef = true;
174             }
175         }
176 
177         if (!m_basicFeature->m_isSecondField)
178         {
179             destEntry->ucDMVIdx[0]=0;
180             destEntry->ucDMVIdx[1]=0;
181         }
182 
183         for (auto i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
184         {
185             m_avcFrameStoreId[i].inUse = false;
186         }
187 
188         destEntry->RefPic = currPic;
189 
190         return MOS_STATUS_SUCCESS;
191     }
192 
UpdateCurRefList(const CODEC_AVC_PIC_PARAMS & picParams)193     MOS_STATUS AvcReferenceFrames::UpdateCurRefList(const CODEC_AVC_PIC_PARAMS &picParams)
194     {
195         DECODE_FUNC_CALL();
196 
197         CODEC_PICTURE currPic = picParams.CurrPic;
198 
199         if (currPic.PicFlags != m_prevPic.PicFlags && currPic.FrameIdx == m_prevPic.FrameIdx)
200         {
201             m_basicFeature->m_isSecondField = true;
202         }
203         else
204         {
205             m_basicFeature->m_isSecondField = false;
206         }
207 
208         // Override reference list with ref surface passed from DDI
209         uint8_t surfCount = 0;
210         uint8_t surfIndex = 0;
211         if (m_osInterface->pfnIsMismatchOrderProgrammingSupported())
212         {
213             while (surfIndex < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
214             {
215                 if (!m_allocator->ResourceIsNull(&m_basicFeature->m_refFrameSurface[surfIndex].OsResource))
216                 {
217                     m_refList[surfIndex]->resRefPic = m_basicFeature->m_refFrameSurface[surfIndex].OsResource;
218                 }
219                 surfIndex++;
220             }
221         }
222         else
223         {
224             while (surfCount < m_basicFeature->m_refSurfaceNum && surfIndex < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
225             {
226                 if (!m_allocator->ResourceIsNull(&m_basicFeature->m_refFrameSurface[surfIndex].OsResource))
227                 {
228                     m_refList[surfIndex]->resRefPic = m_basicFeature->m_refFrameSurface[surfIndex].OsResource;
229                     surfCount++;
230                 }
231                 surfIndex++;
232             }
233         }
234 
235 
236         for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
237         {
238             if (!CodecHal_PictureIsInvalid(picParams.RefFrameList[i]))
239             {
240                 auto index = picParams.RefFrameList[i].FrameIdx;
241                 m_refList[index]->sFrameNumber = picParams.FrameNumList[i];
242             }
243         }
244 
245         for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
246         {
247             m_avcPicIdx[i].bValid =false;
248             auto index = picParams.RefFrameList[i].FrameIdx;
249 
250             if (!CodecHal_PictureIsInvalid(picParams.RefFrameList[i]))
251             {
252                 if (m_allocator->ResourceIsNull(&m_refList[index]->resRefPic))
253                 {
254                     if (picParams.pic_fields.IntraPicFlag)
255                     {
256                         m_refList[index]->RefPic = picParams.RefFrameList[i];
257                         m_refList[index]->resRefPic = m_basicFeature->m_dummyReference.OsResource;
258                         m_refList[index]->ucDMVIdx[0] = m_refList[currPic.FrameIdx]->ucDMVIdx[0];
259                     }
260                 }
261 
262                 bool isDuplicateIdx = false;
263                 for (uint8_t j = 0; j < i; j++)
264                 {
265                     if (m_avcPicIdx[j].bValid && index == picParams.RefFrameList[j].FrameIdx)
266                     {
267                         isDuplicateIdx = 1;
268                         break;
269                     }
270                 }
271                 if (isDuplicateIdx)
272                 {
273                     continue;
274                 }
275 
276                 m_refList[index]->RefPic.PicFlags = CodecHal_CombinePictureFlags(m_refList[index]->RefPic,
277                     picParams.RefFrameList[i]);
278                 m_refList[index]->iFieldOrderCnt[0] = picParams.FieldOrderCntList[i][0];
279                 m_refList[index]->iFieldOrderCnt[1] = picParams.FieldOrderCntList[i][1];
280                 m_avcPicIdx[i].bValid = true;
281                 m_avcPicIdx[i].ucPicIdx = index;
282 
283                 // Comparing curPic's DPB and prevPic's DPB, if find same reference frame index, will reuse
284                 //prevPic's ucFrameId, otherwise, need assign a new ucFrameId in SetFrameStoreIds function.
285                 if (!CodecHal_PictureIsInvalid(m_prevPic) && !m_osInterface->pfnIsMismatchOrderProgrammingSupported())
286                 {
287                     uint8_t ii;
288                     for (ii = 0; ii < m_refList[m_prevPic.FrameIdx]->ucNumRef; ii++)
289                     {
290                         if (index == m_refList[m_prevPic.FrameIdx]->RefList[ii].FrameIdx)
291                         {
292                             if (m_refList[index]->ucFrameId == 0x7f)
293                             {
294                                 DECODE_ASSERTMESSAGE("Invaid Ref Frame Id Found");
295                                 m_refList[index]->ucFrameId = 0;
296                             }
297                             m_avcFrameStoreId[m_refList[index]->ucFrameId].inUse = true;
298                             break;
299                         }
300                     }
301                     if (ii == m_refList[m_prevPic.FrameIdx]->ucNumRef)
302                     {
303                         m_refList[index]->ucFrameId = 0x7f;
304                     }
305                 }
306             }
307         }
308 
309         // Save the current RefList and corresponding reference frame flags
310         uint16_t nonExistingFrameFlags = 0;
311         uint32_t usedForReferenceFlags = 0;
312         uint8_t refIdx = 0;
313         for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++)
314         {
315             if (m_avcPicIdx[i].bValid)
316             {
317                 m_refList[currPic.FrameIdx]->RefList[refIdx] = picParams.RefFrameList[i];
318                 nonExistingFrameFlags |= ((picParams.NonExistingFrameFlags >> i) & 1) << refIdx;
319                 usedForReferenceFlags |= ((picParams.UsedForReferenceFlags >> (i * 2)) & 3) << (refIdx * 2);
320                 refIdx++;
321             }
322         }
323 
324         m_refList[currPic.FrameIdx]->ucNumRef = refIdx;
325         m_refList[currPic.FrameIdx]->usNonExistingFrameFlags = nonExistingFrameFlags;
326         m_refList[currPic.FrameIdx]->uiUsedForReferenceFlags = usedForReferenceFlags;
327 
328         if (m_osInterface->pfnIsMismatchOrderProgrammingSupported())
329         {
330             for (uint32_t ii = 0; ii < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE; ii++)
331             {
332                 m_refList[ii]->ucFrameId = 0x7f;
333             }
334         }
335 
336         DECODE_CHK_STATUS(SetFrameStoreIds(currPic.FrameIdx));
337 
338         // Store CurrFieldOrderCnt
339         if (CodecHal_PictureIsBottomField(currPic))
340         {
341             m_refList[currPic.FrameIdx]->iFieldOrderCnt[1] = picParams.CurrFieldOrderCnt[1];
342         }
343         else
344         {
345             m_refList[currPic.FrameIdx]->iFieldOrderCnt[0] = picParams.CurrFieldOrderCnt[0];
346             if (CodecHal_PictureIsFrame(currPic))
347             {
348                 m_refList[currPic.FrameIdx]->iFieldOrderCnt[1] = picParams.CurrFieldOrderCnt[1];
349             }
350         }
351 
352         m_prevPic = currPic;
353 
354         return MOS_STATUS_SUCCESS;
355     }
356 
UpdateRefCachePolicy(const CODEC_AVC_PIC_PARAMS & picParams)357     MOS_STATUS AvcReferenceFrames::UpdateRefCachePolicy(const CODEC_AVC_PIC_PARAMS &picParams)
358     {
359         DECODE_FUNC_CALL();
360         MOS_STATUS sts = MOS_STATUS_SUCCESS;
361 
362         AvcReferenceFrames         &refFrames     = m_basicFeature->m_refFrames;
363         const std::vector<uint8_t> &activeRefList = refFrames.GetActiveReferenceList(picParams);
364         for (uint8_t i = 0; i < activeRefList.size(); i++)
365         {
366             uint8_t frameIdx               = activeRefList[i];
367             if (frameIdx >= CODEC_AVC_NUM_UNCOMPRESSED_SURFACE)
368             {
369                 continue;
370             }
371             sts = m_allocator->UpdateResoreceUsageType(&m_refList[frameIdx]->resRefPic, resourceInputReference);
372             if (sts != MOS_STATUS_SUCCESS)
373             {
374                 DECODE_NORMALMESSAGE("GetReferenceByFrameIndex invalid\n");
375             }
376         }
377 
378         return MOS_STATUS_SUCCESS;
379     }
380 
SetFrameStoreIds(uint8_t frameIdx)381     MOS_STATUS AvcReferenceFrames::SetFrameStoreIds(uint8_t frameIdx)
382     {
383         const uint8_t invalidFrame = 0x7f;
384         for (uint8_t i = 0; i < m_refList[frameIdx]->ucNumRef; i++)
385         {
386             uint8_t index = m_refList[frameIdx]->RefList[i].FrameIdx;
387             if (m_refList[index]->ucFrameId == invalidFrame)
388             {
389                 uint8_t j;
390                 for (j = 0; j < CODEC_AVC_MAX_NUM_REF_FRAME; j++)
391                 {
392                     if (!m_avcFrameStoreId[j].inUse)
393                     {
394                         m_refList[index]->ucFrameId = j;
395                         m_avcFrameStoreId[j].inUse  = true;
396                         break;
397                     }
398                 }
399                 if (j == CODEC_AVC_MAX_NUM_REF_FRAME)
400                 {
401                     // should never happen, something must be wrong
402                     CODECHAL_PUBLIC_ASSERT(false);
403                     m_refList[index]->ucFrameId = 0;
404                     m_avcFrameStoreId[0].inUse  = true;
405                 }
406             }
407         }
408 
409         return MOS_STATUS_SUCCESS;
410     }
411 
412 }  // namespace decode
413