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