1 /*
2 * Copyright (c) 2021-2023, 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_vvc_reference_frames.cpp
24 //! \brief    Defines reference list related logic for vvc decode
25 //!
26 
27 #include "decode_vvc_basic_feature.h"
28 #include "decode_utils.h"
29 #include "codec_utilities_next.h"
30 #include "decode_vvc_reference_frames.h"
31 #include "codec_def_decode_vvc.h"
32 
33 namespace decode
34 {
VvcReferenceFrames()35     VvcReferenceFrames::VvcReferenceFrames()
36     {
37         memset(m_refList, 0, sizeof(m_refList));
38     }
39 
Init(VvcBasicFeature * basicFeature,DecodeAllocator & allocator)40     MOS_STATUS VvcReferenceFrames::Init(VvcBasicFeature *basicFeature, DecodeAllocator& allocator)
41     {
42         DECODE_FUNC_CALL();
43 
44         DECODE_CHK_NULL(basicFeature);
45         m_basicFeature = basicFeature;
46         m_allocator = &allocator;
47         DECODE_CHK_NULL(m_allocator);
48         DECODE_CHK_STATUS(
49             CodecUtilities::CodecHalAllocateDataList((CODEC_REF_LIST_VVC **)m_refList, CODEC_MAX_DPB_NUM_VVC));
50 
51         return MOS_STATUS_SUCCESS;
52     }
53 
~VvcReferenceFrames()54     VvcReferenceFrames::~VvcReferenceFrames()
55     {
56         DECODE_FUNC_CALL();
57 
58         CodecUtilities::CodecHalFreeDataList(m_refList, CODEC_MAX_DPB_NUM_VVC);
59         //m_activeReferenceList.clear();
60     }
61 
UpdatePicture(CodecVvcPicParams & picParams)62     MOS_STATUS VvcReferenceFrames::UpdatePicture(CodecVvcPicParams & picParams)
63     {
64         DECODE_FUNC_CALL();
65 
66         DECODE_CHK_STATUS(UpdateCurFrame(picParams));
67         DECODE_CHK_STATUS(UpdateUnavailableRefFrames(picParams));
68 
69         return MOS_STATUS_SUCCESS;
70     }
71 
GetActiveReferenceList(CodecVvcPicParams & picParams)72     const std::vector<uint8_t> & VvcReferenceFrames::GetActiveReferenceList(CodecVvcPicParams & picParams)
73     {
74         DECODE_FUNC_CALL();
75 
76         m_activeReferenceList.clear();
77         for (auto i = 0; i < vvcMaxNumRefFrame; i++)
78         {
79             uint8_t frameIdx = picParams.m_refFrameList[i].FrameIdx;
80             if (frameIdx >= CODEC_MAX_DPB_NUM_VVC)
81             {
82                 continue;
83             }
84             m_activeReferenceList.push_back(frameIdx);
85         }
86 
87         return m_activeReferenceList;
88     }
89 
GetReferenceByFrameIndex(uint8_t frameIndex)90     PMOS_RESOURCE VvcReferenceFrames::GetReferenceByFrameIndex(uint8_t frameIndex)
91     {
92         DECODE_FUNC_CALL();
93 
94         if (frameIndex >= CODEC_MAX_DPB_NUM_VVC)
95         {
96             DECODE_ASSERTMESSAGE("Invalid reference frame index");
97             return nullptr;
98         }
99 
100         PCODEC_REF_LIST_VVC ref = m_refList[frameIndex];
101 
102         if (ref == nullptr || m_allocator->ResourceIsNull(&(ref->resRefPic)))
103         {
104             return nullptr;
105         }
106 
107         return &(ref->resRefPic);
108     }
109 
GetRefAttrByFrameIndex(uint8_t frameIndex,VvcRefFrameAttributes * attributes)110     MOS_STATUS VvcReferenceFrames::GetRefAttrByFrameIndex(uint8_t frameIndex, VvcRefFrameAttributes* attributes)
111     {
112         DECODE_FUNC_CALL();
113 
114         DECODE_CHK_NULL(attributes);
115 
116         if (frameIndex >= CODEC_MAX_DPB_NUM_VVC)
117         {
118             DECODE_ASSERTMESSAGE("Invalid reference frame index");
119             return MOS_STATUS_INVALID_PARAMETER;
120         }
121 
122         PCODEC_REF_LIST_VVC ref = m_refList[frameIndex];
123 
124         if (ref == nullptr || m_allocator->ResourceIsNull(&(ref->resRefPic)))
125         {
126             return MOS_STATUS_INVALID_PARAMETER;
127         }
128 
129         attributes->m_refscalingwinleftoffset   = ref->m_ppsScalingWinLeftOffset;
130         attributes->m_refscalingwinrightoffset  = ref->m_ppsScalingWinRightOffset;
131         attributes->m_refscalingwintopoffset    = ref->m_ppsScalingWinTopOffset;
132         attributes->m_refscalingwinbottomoffset = ref->m_ppsScalingWinBottomOffset;
133         attributes->m_refpicwidth               = ref->m_ppsPicWidthInLumaSamples;
134         attributes->m_refpicheight              = ref->m_ppsPicHeightInLumaSamples;
135         attributes->m_currPicScalWinWidthL      = ref->m_currPicScalWinWidthL;
136         attributes->m_currPicScalWinHeightL     = ref->m_currPicScalWinHeightL;
137 
138         return MOS_STATUS_SUCCESS;
139     }
140 
GetValidReference()141     PMOS_RESOURCE VvcReferenceFrames::GetValidReference()
142     {
143         DECODE_FUNC_CALL();
144 
145         if (m_basicFeature->m_vvcPicParams == nullptr)
146         {
147             m_validRefFrameIdx = CODEC_MAX_DPB_NUM_VVC;
148             return nullptr;
149         }
150         auto m_picParams = m_basicFeature->m_vvcPicParams;
151 
152         for(auto i = 0; i < vvcMaxNumRefFrame; i++)
153         {
154             uint8_t frameIdx = m_picParams->m_refFrameList[i].FrameIdx;
155             if (frameIdx >= CODEC_MAX_DPB_NUM_VVC)
156             {
157                 continue;
158             }
159             PMOS_RESOURCE buffer = GetReferenceByFrameIndex(frameIdx);
160             if (buffer != nullptr)
161             {
162                 m_validRefFrameIdx = frameIdx;
163                 return buffer;
164             }
165         }
166         m_validRefFrameIdx = m_picParams->m_currPic.FrameIdx;
167 
168         return &(m_basicFeature->m_destSurface.OsResource);
169     }
170 
UpdateCurResource(const PCODEC_REF_LIST_VVC pCurRefList)171     MOS_STATUS VvcReferenceFrames::UpdateCurResource(const PCODEC_REF_LIST_VVC pCurRefList)
172     {
173         DECODE_FUNC_CALL();
174         DECODE_CHK_NULL(pCurRefList);
175         DECODE_CHK_NULL(m_basicFeature->m_vvcPicParams);
176         auto m_picParams = m_basicFeature->m_vvcPicParams;
177 
178         // Overwrite the actual surface height with the coded height and width of the frame
179         // since DPB buffer size may be larger than the YUV data size to put in it
180         m_basicFeature->m_destSurface.dwWidth   = m_picParams->m_ppsPicWidthInLumaSamples;
181         m_basicFeature->m_destSurface.dwHeight  = m_picParams->m_ppsPicHeightInLumaSamples;
182 
183         pCurRefList->resRefPic = m_basicFeature->m_destSurface.OsResource;
184 
185         return MOS_STATUS_SUCCESS;
186     }
187 
UpdateCurFrame(const CodecVvcPicParams & picParams)188     MOS_STATUS VvcReferenceFrames::UpdateCurFrame(const CodecVvcPicParams & picParams)
189     {
190         DECODE_FUNC_CALL();
191 
192         DECODE_CHK_COND(picParams.m_currPic.FrameIdx >= CODEC_MAX_DPB_NUM_VVC, "Invalid frame index of current frame");
193         m_currRefList = m_refList[picParams.m_currPic.FrameIdx];
194         MOS_ZeroMemory(m_currRefList, sizeof(CODEC_REF_LIST_VVC));
195 
196         DECODE_CHK_STATUS(UpdateCurResource(m_currRefList));
197 
198         m_currRefList->m_ppsPicWidthInLumaSamples   = picParams.m_ppsPicWidthInLumaSamples;
199         m_currRefList->m_ppsPicHeightInLumaSamples  = picParams.m_ppsPicHeightInLumaSamples;
200         m_currRefList->m_ppsScalingWinLeftOffset    = picParams.m_ppsScalingWinLeftOffset;
201         m_currRefList->m_ppsScalingWinRightOffset   = picParams.m_ppsScalingWinRightOffset;
202         m_currRefList->m_ppsScalingWinTopOffset     = picParams.m_ppsScalingWinTopOffset;
203         m_currRefList->m_ppsScalingWinBottomOffset  = picParams.m_ppsScalingWinBottomOffset;
204         m_currRefList->m_spsNumSubpicsMinus1        = picParams.m_spsNumSubpicsMinus1;
205         m_currRefList->m_spsHorCollocatedChromaFlag = picParams.m_spsFlags1.m_fields.m_spsChromaHorizontalCollocatedFlag;
206         m_currRefList->m_spsVerCollocatedChromaFlag = picParams.m_spsFlags1.m_fields.m_spsChromaVerticalCollocatedFlag;
207         m_curIsIntra                                = picParams.m_picMiscFlags.m_fields.m_intraPicFlag;
208 
209         //Calc CurrPicScalWinWidthL/CurrPicScalWinHeightL
210         int8_t subWidthC, subHeightC;
211         if (picParams.m_spsChromaFormatIdc == 0 || picParams.m_spsChromaFormatIdc == 3)
212         {
213             subWidthC  = 1;
214             subHeightC = 1;
215         }
216         else
217         {
218             subWidthC  = 2;
219             subHeightC = (picParams.m_spsChromaFormatIdc == 1) ? 2 : 1;
220         }
221         m_currRefList->m_currPicScalWinWidthL = picParams.m_ppsPicWidthInLumaSamples - subWidthC * (picParams.m_ppsScalingWinRightOffset + picParams.m_ppsScalingWinLeftOffset);
222         m_currRefList->m_currPicScalWinHeightL = picParams.m_ppsPicHeightInLumaSamples - subHeightC * (picParams.m_ppsScalingWinBottomOffset + picParams.m_ppsScalingWinTopOffset);
223 
224         return MOS_STATUS_SUCCESS;
225     }
226 
UpdateUnavailableRefFrames(const CodecVvcPicParams & picParams)227     MOS_STATUS VvcReferenceFrames::UpdateUnavailableRefFrames(const CodecVvcPicParams & picParams)
228     {
229         DECODE_FUNC_CALL();
230 
231         for (auto i = 0; i < vvcMaxNumRefFrame; i++)
232         {
233             if (picParams.m_refFrameList[i].PicFlags == PICTURE_UNAVAILABLE_FRAME)
234             {
235 
236                 if (picParams.m_refFrameList[i].FrameIdx >=  CODEC_MAX_DPB_NUM_VVC)
237                 {
238                     continue;
239                 }
240 
241                 PCODEC_REF_LIST_VVC refList = m_refList[picParams.m_refFrameList[i].FrameIdx];
242 
243                 refList->resRefPic                      = m_basicFeature->m_destSurface.OsResource;
244                 refList->m_ppsPicWidthInLumaSamples     = picParams.m_ppsPicWidthInLumaSamples;
245                 refList->m_ppsPicHeightInLumaSamples    = picParams.m_ppsPicHeightInLumaSamples;
246                 refList->m_ppsScalingWinLeftOffset      = picParams.m_ppsScalingWinLeftOffset;
247                 refList->m_ppsScalingWinRightOffset     = picParams.m_ppsScalingWinRightOffset;
248                 refList->m_ppsScalingWinTopOffset       = picParams.m_ppsScalingWinTopOffset;
249                 refList->m_ppsScalingWinBottomOffset    = picParams.m_ppsScalingWinBottomOffset;
250                 refList->m_spsNumSubpicsMinus1          = picParams.m_spsNumSubpicsMinus1;
251                 refList->m_currPicScalWinWidthL         = picParams.m_ppsPicWidthInLumaSamples;
252                 refList->m_currPicScalWinHeightL        = picParams.m_ppsPicHeightInLumaSamples;
253             }
254         }
255 
256         return MOS_STATUS_SUCCESS;
257     }
258 
CalcRprConstraintsActiveFlag(uint8_t refFrameIdx,bool & flag)259     MOS_STATUS VvcReferenceFrames::CalcRprConstraintsActiveFlag(uint8_t refFrameIdx, bool &flag)
260     {
261         DECODE_FUNC_CALL();
262 
263         if (refFrameIdx >= CODEC_MAX_DPB_NUM_VVC)
264         {
265             return MOS_STATUS_INVALID_PARAMETER;
266         }
267 
268         PCODEC_REF_LIST_VVC ref = m_refList[refFrameIdx];
269 
270         if (ref == nullptr || m_allocator->ResourceIsNull(&(ref->resRefPic)))
271         {
272             return MOS_STATUS_INVALID_PARAMETER;
273         }
274 
275         flag = (ref->m_ppsPicHeightInLumaSamples != m_currRefList->m_ppsPicHeightInLumaSamples) ||
276                (ref->m_ppsPicWidthInLumaSamples != m_currRefList->m_ppsPicWidthInLumaSamples)   ||
277                (ref->m_ppsScalingWinTopOffset != m_currRefList->m_ppsScalingWinTopOffset)       ||
278                (ref->m_ppsScalingWinBottomOffset != m_currRefList->m_ppsScalingWinBottomOffset) ||
279                (ref->m_ppsScalingWinLeftOffset != m_currRefList->m_ppsScalingWinLeftOffset)     ||
280                (ref->m_ppsScalingWinRightOffset != m_currRefList->m_ppsScalingWinRightOffset)   ||
281                (ref->m_spsNumSubpicsMinus1 != m_currRefList->m_spsNumSubpicsMinus1);
282 
283         if (flag &&
284             (ref->m_spsHorCollocatedChromaFlag != m_currRefList->m_spsHorCollocatedChromaFlag
285              || ref->m_spsVerCollocatedChromaFlag != m_currRefList->m_spsVerCollocatedChromaFlag))
286         {
287             return MOS_STATUS_INVALID_PARAMETER;
288         }
289 
290         return MOS_STATUS_SUCCESS;
291     }
292 
293 
294 }  // namespace decode
295