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