1 /* 2 * Copyright (c) 2019-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_av1_temporal_buffers.cpp 24 //! \brief Defines temporal buffers related logic for av1 decode 25 //! 26 27 #include "codec_def_decode_av1.h" 28 #include "decode_av1_basic_feature.h" 29 #include "decode_av1_temporal_buffers.h" 30 #include "decode_utils.h" 31 32 namespace decode 33 { Init(void * hwInterface,DecodeAllocator & allocator,Av1BasicFeature & basicFeature)34 MOS_STATUS Av1TempBufferOpInf::Init(void* hwInterface, DecodeAllocator& allocator, 35 Av1BasicFeature& basicFeature) 36 { 37 DECODE_CHK_STATUS(BufferOpInf::Init(hwInterface, allocator, basicFeature)); 38 if (m_hwInterface != nullptr) 39 { 40 m_avpItf = std::static_pointer_cast<mhw::vdbox::avp::Itf>(((CodechalHwInterfaceNext*)m_hwInterface)->GetAvpInterfaceNext()); 41 } 42 m_basicFeature = &basicFeature; 43 return MOS_STATUS_SUCCESS; 44 } 45 Allocate()46 Av1RefAssociatedBufs* Av1TempBufferOpInf::Allocate() 47 { 48 DECODE_FUNC_CALL(); 49 50 int32_t mibSizeLog2 = av1MinMibSizeLog2; 51 AvpBufferSizePar avpBufSizeParam; 52 SetAvpBufSizeParam(avpBufSizeParam, mibSizeLog2); 53 54 if (m_avpItf->GetAvpBufSize(mhw::vdbox::avp::mvTemporalBuffer, 55 &avpBufSizeParam) != MOS_STATUS_SUCCESS) 56 { 57 DECODE_ASSERTMESSAGE( "Failed to get MvTemporalBuffer size."); 58 } 59 60 Av1RefAssociatedBufs *bufs = MOS_New(Av1RefAssociatedBufs); 61 bufs->mvBuf = m_allocator->AllocateBuffer( 62 avpBufSizeParam.bufferSize, "MvTemporalBuffer", resourceInternalReadWriteCache, notLockableVideoMem); 63 64 if (m_avpItf->GetAvpBufSize(mhw::vdbox::avp::segmentIdBuffer, 65 &avpBufSizeParam) != MOS_STATUS_SUCCESS) 66 { 67 DECODE_ASSERTMESSAGE( "Failed to get SegmentIdBuffer size."); 68 } 69 bufs->segIdWriteBuf.buffer = m_allocator->AllocateBuffer( 70 avpBufSizeParam.bufferSize, "SegmentIdWriteBuffer", resourceInternalReadWriteCache, notLockableVideoMem); 71 72 bufs->bwdAdaptCdfBuf.buffer = m_allocator->AllocateBuffer(MOS_ALIGN_CEIL(m_basicFeature->m_cdfMaxNumBytes, 73 CODECHAL_PAGE_SIZE), "CdfTableBuffer", resourceInternalReadWriteCache, notLockableVideoMem); 74 return bufs; 75 } 76 Resize(Av1RefAssociatedBufs * & buffer)77 MOS_STATUS Av1TempBufferOpInf::Resize(Av1RefAssociatedBufs* &buffer) 78 { 79 DECODE_FUNC_CALL(); 80 81 if (buffer == nullptr) 82 { 83 DECODE_CHK_NULL(buffer = Allocate()); 84 return MOS_STATUS_SUCCESS; 85 } 86 87 int32_t mibSizeLog2 = m_basicFeature->m_av1PicParams->m_seqInfoFlags.m_fields.m_use128x128Superblock ? av1MaxMibSizeLog2 : av1MinMibSizeLog2; 88 AvpBufferSizePar avpBufSizeParam; 89 SetAvpBufSizeParam(avpBufSizeParam, mibSizeLog2); 90 91 DECODE_CHK_STATUS(m_avpItf->GetAvpBufSize( 92 mhw::vdbox::avp::mvTemporalBuffer, 93 &avpBufSizeParam)); 94 DECODE_CHK_STATUS(m_allocator->Resize( 95 buffer->mvBuf, avpBufSizeParam.bufferSize, notLockableVideoMem, false)); 96 97 DECODE_CHK_STATUS(m_avpItf->GetAvpBufSize( 98 mhw::vdbox::avp::segmentIdBuffer, 99 &avpBufSizeParam)); 100 DECODE_CHK_STATUS(m_allocator->Resize( 101 buffer->segIdWriteBuf.buffer, avpBufSizeParam.bufferSize, notLockableVideoMem, false)); 102 103 RecordSegIdBufInfo(buffer); 104 RecordCdfTableBufInfo(buffer); 105 106 return MOS_STATUS_SUCCESS; 107 } 108 SetAvpBufSizeParam(AvpBufferSizePar & params,int32_t mibSizeLog2)109 void Av1TempBufferOpInf::SetAvpBufSizeParam(AvpBufferSizePar ¶ms, int32_t mibSizeLog2) 110 { 111 int32_t miCols = MOS_ALIGN_CEIL(m_basicFeature->m_width, 8) >> av1MiSizeLog2; 112 int32_t miRows = MOS_ALIGN_CEIL(m_basicFeature->m_height, 8) >> av1MiSizeLog2; 113 miCols = MOS_ALIGN_CEIL(miCols, 1 << mibSizeLog2); 114 miRows = MOS_ALIGN_CEIL(miRows, 1 << mibSizeLog2); 115 widthInSb = miCols >> mibSizeLog2; 116 heightInSb = miRows >> mibSizeLog2; 117 118 MOS_ZeroMemory(¶ms, sizeof(params)); 119 params.width = widthInSb; 120 params.height = heightInSb; 121 params.isSb128x128 = false; 122 if (m_basicFeature->m_av1PicParams != nullptr) 123 { 124 params.isSb128x128 = m_basicFeature->m_av1PicParams->m_seqInfoFlags.m_fields.m_use128x128Superblock ? true : false; 125 } 126 params.chromaFormat = m_basicFeature->m_chromaFormat; 127 } 128 RecordSegIdBufInfo(Av1RefAssociatedBufs * buffer)129 void Av1TempBufferOpInf::RecordSegIdBufInfo(Av1RefAssociatedBufs *buffer) 130 { 131 auto picParams = m_basicFeature->m_av1PicParams; 132 uint8_t prevFrameIdx = m_basicFeature->m_refFrames.GetPrimaryRefIdx(); 133 if (picParams->m_av1SegData.m_enabled) 134 { 135 if (picParams->m_av1SegData.m_updateMap) 136 { 137 buffer->segIdBuf = RefSharedBuffer(&buffer->segIdWriteBuf); 138 } 139 else 140 { 141 auto tempBuffers = &(m_basicFeature->m_tempBuffers); 142 auto prevTempBuffer = tempBuffers->GetBufferByFrameIndex(prevFrameIdx); 143 if (prevTempBuffer != nullptr) 144 { 145 if (m_basicFeature->m_refFrames.CheckSegForPrimFrame(*picParams)) 146 { 147 buffer->segIdBuf = RefSharedBuffer(prevTempBuffer->segIdBuf); 148 } 149 else 150 { 151 buffer->segIdBuf = nullptr; 152 } 153 } 154 } 155 } 156 else 157 { 158 buffer->segIdBuf = nullptr; 159 } 160 } 161 RecordCdfTableBufInfo(Av1RefAssociatedBufs * buffer)162 void Av1TempBufferOpInf::RecordCdfTableBufInfo(Av1RefAssociatedBufs *buffer) 163 { 164 auto picParams = m_basicFeature->m_av1PicParams; 165 uint8_t prevFrameIdx = m_basicFeature->m_refFrames.GetPrimaryRefIdx(); 166 buffer->disableFrmEndUpdateCdf = picParams->m_picInfoFlags.m_fields.m_disableFrameEndUpdateCdf; 167 168 if (picParams->m_primaryRefFrame == av1PrimaryRefNone) 169 { 170 buffer->defaultCdfBuf.buffer = m_basicFeature->m_defaultCdfBufferInUse; 171 buffer->initCdfBuf = RefSharedBuffer(&buffer->defaultCdfBuf); 172 } 173 else 174 { 175 auto tempBuffers = &(m_basicFeature->m_tempBuffers); 176 auto prevTempBuffer = tempBuffers->GetBufferByFrameIndex(prevFrameIdx); 177 if (prevTempBuffer != nullptr) 178 { 179 if (prevTempBuffer->disableFrmEndUpdateCdf) 180 { 181 buffer->initCdfBuf = RefSharedBuffer(prevTempBuffer->initCdfBuf); 182 } 183 else 184 { 185 buffer->initCdfBuf = RefSharedBuffer(&prevTempBuffer->bwdAdaptCdfBuf); 186 } 187 } 188 } 189 } 190 Deactive(Av1RefAssociatedBufs * & buffer)191 MOS_STATUS Av1TempBufferOpInf::Deactive(Av1RefAssociatedBufs* &buffer) 192 { 193 DeRefSharedBuffer(buffer->segIdBuf); 194 DeRefSharedBuffer(buffer->initCdfBuf); 195 return MOS_STATUS_SUCCESS; 196 } 197 IsAvailable(Av1RefAssociatedBufs * & buffer)198 bool Av1TempBufferOpInf::IsAvailable(Av1RefAssociatedBufs* &buffer) 199 { 200 if (buffer == nullptr) 201 { 202 return false; 203 } 204 if (buffer->segIdWriteBuf.refCnt > 0) 205 { 206 return false; 207 } 208 if (buffer->bwdAdaptCdfBuf.refCnt > 0) 209 { 210 return false; 211 } 212 if (buffer->defaultCdfBuf.refCnt > 0) 213 { 214 return false; 215 } 216 return true; 217 } 218 Destroy(Av1RefAssociatedBufs * & buffer)219 void Av1TempBufferOpInf::Destroy(Av1RefAssociatedBufs* &buffer) 220 { 221 DECODE_FUNC_CALL(); 222 223 if (buffer != nullptr && m_allocator != nullptr) 224 { 225 m_allocator->Destroy(buffer->mvBuf); 226 227 m_allocator->Destroy(buffer->segIdWriteBuf.buffer); 228 if (buffer->segIdWriteBuf.refCnt != 0) 229 { 230 DECODE_NORMALMESSAGE("The reference count is %d while destory SegId buffer", buffer->segIdWriteBuf.refCnt); 231 } 232 233 m_allocator->Destroy(buffer->bwdAdaptCdfBuf.buffer); 234 if (buffer->bwdAdaptCdfBuf.refCnt != 0) 235 { 236 DECODE_NORMALMESSAGE("The reference count is %d while destory CDF buffer", buffer->bwdAdaptCdfBuf.refCnt); 237 } 238 239 MOS_Delete(buffer); 240 buffer = nullptr; 241 } 242 } 243 RefSharedBuffer(Av1SharedBuf * sharedBuf)244 Av1SharedBuf *Av1TempBufferOpInf::RefSharedBuffer(Av1SharedBuf *sharedBuf) 245 { 246 if (sharedBuf != nullptr) 247 { 248 sharedBuf->refCnt++; 249 } 250 return sharedBuf; 251 } 252 DeRefSharedBuffer(Av1SharedBuf * sharedBuf)253 Av1SharedBuf *Av1TempBufferOpInf::DeRefSharedBuffer(Av1SharedBuf *sharedBuf) 254 { 255 if (sharedBuf != nullptr) 256 { 257 sharedBuf->refCnt--; 258 if (sharedBuf->refCnt < 0) 259 { 260 DECODE_ASSERTMESSAGE("AV1 shared buffer reference count is %d which should not small than zero.", sharedBuf->refCnt); 261 sharedBuf->refCnt = 0; 262 } 263 } 264 return sharedBuf; 265 } 266 } // namespace decode 267