1 /*
2 * Copyright (c) 2020-2021, 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_vp9_reference_frames.cpp
24 //! \brief    Defines reference list related logic for vp9 decode
25 //!
26 
27 #include "decode_vp9_basic_feature.h"
28 #include "decode_utils.h"
29 #include "codec_utilities_next.h"
30 #include "decode_vp9_reference_frames.h"
31 #include "codec_def_decode_vp9.h"
32 
33 namespace decode
34 {
Vp9ReferenceFrames()35     Vp9ReferenceFrames::Vp9ReferenceFrames()
36     {
37         memset(m_vp9RefList, 0, sizeof(m_vp9RefList));
38     }
39 
Init(Vp9BasicFeature * basicFeature,DecodeAllocator & allocator)40     MOS_STATUS Vp9ReferenceFrames::Init(Vp9BasicFeature *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(CodecUtilities::CodecHalAllocateDataList(m_vp9RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9));
49 
50         return MOS_STATUS_SUCCESS;
51     }
52 
~Vp9ReferenceFrames()53     Vp9ReferenceFrames::~Vp9ReferenceFrames()
54     {
55         DECODE_FUNC_CALL();
56 
57         CodecUtilities::CodecHalFreeDataList(m_vp9RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9);  // CODECHAL_MAX_DPB_NUM_AV1 VP9 WHAT?
58         m_activeReferenceList.clear();
59     }
60 
UpdatePicture(CODEC_VP9_PIC_PARAMS & picParams)61     MOS_STATUS Vp9ReferenceFrames::UpdatePicture(CODEC_VP9_PIC_PARAMS &picParams)
62     {
63         DECODE_FUNC_CALL();
64 
65         DECODE_CHK_STATUS(UpdateCurFrame(picParams));
66 
67         // Override reference list with ref surface passed from DDI if needed
68         uint8_t surfCount = 0;
69         uint8_t surfIndex = 0;
70         while (surfCount < m_basicFeature->m_refSurfaceNum && surfIndex < CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9)
71         {
72             if (!m_allocator->ResourceIsNull(&m_basicFeature->m_refFrameSurface[surfIndex].OsResource))
73             {
74                 m_vp9RefList[surfIndex]->resRefPic = m_basicFeature->m_refFrameSurface[surfIndex].OsResource;
75                 surfCount++;
76             }
77             surfIndex++;
78         }
79 
80         PCODEC_PICTURE refFrameList      = &(m_basicFeature->m_vp9PicParams->RefFrameList[0]);
81         uint8_t        lastRefPicIndex   = m_basicFeature->m_vp9PicParams->PicFlags.fields.LastRefIdx;
82         uint8_t        goldenRefPicIndex = m_basicFeature->m_vp9PicParams->PicFlags.fields.GoldenRefIdx;
83         uint8_t        altRefPicIndex    = m_basicFeature->m_vp9PicParams->PicFlags.fields.AltRefIdx;
84 
85         if (m_basicFeature->m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_KEY_FRAME ||
86             m_basicFeature->m_vp9PicParams->PicFlags.fields.intra_only)
87         {
88             // reference surface should be nullptr when key_frame == true or intra only frame
89             m_basicFeature->m_presLastRefSurface   = nullptr;
90             m_basicFeature->m_presGoldenRefSurface = nullptr;
91             m_basicFeature->m_presAltRefSurface    = nullptr;
92         }
93         else
94         {
95             if (lastRefPicIndex > 7 || goldenRefPicIndex > 7 || altRefPicIndex > 7)
96             {
97                 DECODE_ASSERTMESSAGE("invalid ref index (should be in [0,7]) in pic parameter!");
98                 return MOS_STATUS_INVALID_PARAMETER;
99             }
100 
101             if (refFrameList[lastRefPicIndex].FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9)
102             {
103                 refFrameList[lastRefPicIndex].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1;
104             }
105             if (refFrameList[goldenRefPicIndex].FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9)
106             {
107                 refFrameList[goldenRefPicIndex].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1;
108             }
109             if (refFrameList[altRefPicIndex].FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9)
110             {
111                 refFrameList[altRefPicIndex].FrameIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9 - 1;
112             }
113             PCODEC_REF_LIST *vp9RefList            = &(m_vp9RefList[0]);
114             m_basicFeature->m_presLastRefSurface   = &(vp9RefList[refFrameList[lastRefPicIndex].FrameIdx]->resRefPic);
115             m_basicFeature->m_presGoldenRefSurface = &(vp9RefList[refFrameList[goldenRefPicIndex].FrameIdx]->resRefPic);
116             m_basicFeature->m_presAltRefSurface    = &(vp9RefList[refFrameList[altRefPicIndex].FrameIdx]->resRefPic);
117         }
118 
119         PMOS_RESOURCE dummyRef = &(m_basicFeature->m_dummyReference.OsResource);
120         PMOS_RESOURCE usedDummyReference = nullptr;
121         if(m_basicFeature->m_dummyReferenceStatus &&
122                 !m_allocator->ResourceIsNull(dummyRef))
123         {
124             usedDummyReference = &(m_basicFeature->m_dummyReference.OsResource);
125         }
126         else
127         {
128             usedDummyReference = &(m_basicFeature->m_destSurface.OsResource);
129         }
130 
131         // Populate surface param for reference pictures
132         if (m_basicFeature->m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_INTER_FRAME &&
133             !m_basicFeature->m_vp9PicParams->PicFlags.fields.intra_only &&
134             m_basicFeature->m_presLastRefSurface != nullptr &&
135             m_basicFeature->m_presGoldenRefSurface != nullptr &&
136             m_basicFeature->m_presAltRefSurface != nullptr)
137         {
138             if (Mos_ResourceIsNull(m_basicFeature->m_presLastRefSurface))
139             {
140                 m_basicFeature->m_presLastRefSurface = usedDummyReference;
141             }
142             if (Mos_ResourceIsNull(m_basicFeature->m_presGoldenRefSurface))
143             {
144                 m_basicFeature->m_presGoldenRefSurface = usedDummyReference;
145             }
146             if (Mos_ResourceIsNull(m_basicFeature->m_presAltRefSurface))
147             {
148                 m_basicFeature->m_presAltRefSurface = usedDummyReference;
149             }
150 
151             //MOS_SURFACE lastRefSurface;
152             DECODE_CHK_STATUS(MOS_SecureMemcpy(
153                 &(m_basicFeature->m_lastRefSurface.OsResource),
154                 sizeof(MOS_RESOURCE),
155                 m_basicFeature->m_presLastRefSurface,
156                 sizeof(MOS_RESOURCE)));
157             DECODE_CHK_STATUS(CodecUtilities::CodecHalGetResourceInfo(
158                 m_basicFeature->m_osInterface,
159                 &m_basicFeature->m_lastRefSurface));
160 
161             //MOS_SURFACE goldenRefSurface;
162             DECODE_CHK_STATUS(MOS_SecureMemcpy(
163                 &m_basicFeature->m_goldenRefSurface.OsResource,
164                 sizeof(MOS_RESOURCE),
165                 m_basicFeature->m_presGoldenRefSurface,
166                 sizeof(MOS_RESOURCE)));
167             DECODE_CHK_STATUS(CodecUtilities::CodecHalGetResourceInfo(
168                 m_basicFeature->m_osInterface,
169                 &m_basicFeature->m_goldenRefSurface));
170 
171             //MOS_SURFACE altRefSurface;
172             DECODE_CHK_STATUS(MOS_SecureMemcpy(
173                 &m_basicFeature->m_altRefSurface.OsResource,
174                 sizeof(MOS_RESOURCE),
175                 m_basicFeature->m_presAltRefSurface,
176                 sizeof(MOS_RESOURCE)));
177             DECODE_CHK_STATUS(CodecUtilities::CodecHalGetResourceInfo(
178                 m_basicFeature->m_osInterface,
179                 &m_basicFeature->m_altRefSurface));
180 
181             return MOS_STATUS_SUCCESS;
182         }
183         return MOS_STATUS_SUCCESS;
184     }
185 
GetActiveReferenceList(CODEC_VP9_PIC_PARAMS & picParams)186     const std::vector<uint8_t> &Vp9ReferenceFrames::GetActiveReferenceList(CODEC_VP9_PIC_PARAMS &picParams)
187     {
188         DECODE_FUNC_CALL();
189 
190         m_activeReferenceList.clear();
191         for (auto i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
192         {
193             m_activeReferenceList.push_back(picParams.RefFrameList[i].FrameIdx);
194         }
195 
196         return m_activeReferenceList;
197     }
198 
GetReferenceByFrameIndex(uint8_t frameIndex)199     PMOS_RESOURCE Vp9ReferenceFrames::GetReferenceByFrameIndex(uint8_t frameIndex)
200     {
201         DECODE_FUNC_CALL();
202 
203         if (frameIndex >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9)
204         {
205             DECODE_ASSERTMESSAGE("Invalid reference frame index");
206             return nullptr;
207         }
208 
209         PCODEC_REF_LIST ref = m_vp9RefList[frameIndex];
210 
211         if (ref == nullptr || m_allocator->ResourceIsNull(&(ref->resRefPic)))
212         {
213             return nullptr;
214         }
215 
216         return &(ref->resRefPic);
217     }
218 
219 
GetValidReference()220     PMOS_RESOURCE Vp9ReferenceFrames::GetValidReference()
221     {
222         DECODE_FUNC_CALL();
223 
224         if (m_basicFeature->m_vp9PicParams == nullptr)
225         {
226             return nullptr;
227         }
228         auto m_picParams = m_basicFeature->m_vp9PicParams;
229 
230         for (auto i = 0; i < CODECHAL_DECODE_VP9_MAX_NUM_REF_FRAME; i++)
231         {
232             uint8_t frameIdx = m_picParams->RefFrameList[i].FrameIdx;
233             if (frameIdx >= m_basicFeature->m_maxFrameIndex)
234             {
235                 continue;
236             }
237             PMOS_RESOURCE buffer = GetReferenceByFrameIndex(frameIdx);
238             if (buffer != nullptr)
239             {
240                 return buffer;
241             }
242         }
243 
244         return &(m_basicFeature->m_destSurface.OsResource);
245     }
246 
UpdateCurResource(const CODEC_VP9_PIC_PARAMS & picParams)247     MOS_STATUS Vp9ReferenceFrames::UpdateCurResource(const CODEC_VP9_PIC_PARAMS& picParams)
248     {
249         DECODE_FUNC_CALL();
250 
251         PCODEC_REF_LIST destEntry    = m_vp9RefList[picParams.CurrPic.FrameIdx];
252         destEntry->resRefPic         = m_basicFeature->m_destSurface.OsResource;
253         destEntry->dwFrameWidth      = picParams.FrameWidthMinus1 + 1;
254         destEntry->dwFrameHeight     = picParams.FrameHeightMinus1 + 1;
255 
256         return MOS_STATUS_SUCCESS;
257     }
258 
UpdateCurFrame(const CODEC_VP9_PIC_PARAMS & picParams)259     MOS_STATUS Vp9ReferenceFrames::UpdateCurFrame(const CODEC_VP9_PIC_PARAMS &picParams)
260     {
261         DECODE_FUNC_CALL();
262 
263         DECODE_CHK_COND(picParams.CurrPic.FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VP9,
264                         "Invalid frame index of current frame");
265         m_currRefList = m_vp9RefList[picParams.CurrPic.FrameIdx];
266         MOS_ZeroMemory(m_currRefList, sizeof(CODEC_REF_LIST));
267 
268         // Overwrite the actual surface height with the coded height and width of the frame
269         // for VP9 since it's possible for a VP9 frame to change size during playback
270         DECODE_CHK_STATUS(UpdateCurResource(picParams));
271         m_currRefList->RefPic = picParams.CurrPic;
272 
273         for (auto i = 0; i < CODECHAL_DECODE_VP9_MAX_NUM_REF_FRAME; i++)
274         {
275             m_currRefList->RefList[i] = picParams.RefFrameList[i];
276         }
277 
278         return MOS_STATUS_SUCCESS;
279     }
280 
281 }  // namespace decode
282