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_reference_associated_buffer.h 24 //! \brief Defines the interface for reference associated buffer 25 //! \details Each reference has associated buffers for most of the codecs, 26 //! this file implements the basic management for such buffers. 27 //! 28 29 #ifndef __DECODE_REFRENCE_ASSOCIATED_BUFFER_H__ 30 #define __DECODE_REFRENCE_ASSOCIATED_BUFFER_H__ 31 32 #include "decode_allocator.h" 33 #include "decode_utils.h" 34 #include "codec_hw_next.h" 35 36 namespace decode { 37 38 template<typename BufferType, typename BasicFeature> 39 class BufferOpInf 40 { 41 public: ~BufferOpInf()42 virtual ~BufferOpInf() {} Init(void * hwInterface,DecodeAllocator & allocator,BasicFeature & basicFeature)43 virtual MOS_STATUS Init(void *hwInterface, DecodeAllocator &allocator, BasicFeature &basicFeature) 44 { 45 m_hwInterface = hwInterface; 46 m_allocator = &allocator; 47 m_basicFeature = &basicFeature; 48 return MOS_STATUS_SUCCESS; 49 } 50 51 virtual BufferType *Allocate() = 0; 52 virtual MOS_STATUS Resize(BufferType* &buffer) = 0; Deactive(BufferType * & buffer)53 virtual MOS_STATUS Deactive(BufferType* &buffer) { return MOS_STATUS_SUCCESS; } IsAvailable(BufferType * & buffer)54 virtual bool IsAvailable(BufferType* &buffer) { return true; } 55 virtual void Destroy(BufferType* &buffer) = 0; 56 57 void* m_hwInterface = nullptr; 58 DecodeAllocator* m_allocator = nullptr; 59 BasicFeature* m_basicFeature = nullptr; 60 61 MEDIA_CLASS_DEFINE_END(decode__BufferOpInf) 62 }; 63 64 template<typename BufferType, typename BufferOp, typename BasicFeature> 65 class RefrenceAssociatedBuffer 66 { 67 public: 68 //! 69 //! \brief RefrenceAssociatedBuffer constructor 70 //! RefrenceAssociatedBuffer()71 RefrenceAssociatedBuffer() 72 {}; 73 74 //! 75 //! \brief RefrenceAssociatedBuffer deconstructor 76 //! ~RefrenceAssociatedBuffer()77 virtual ~RefrenceAssociatedBuffer() 78 { 79 DECODE_FUNC_CALL(); 80 81 for (auto& buf : m_activeBuffers) 82 { 83 m_bufferOp.Destroy(buf.second); 84 } 85 m_activeBuffers.clear(); 86 87 for (auto& buf : m_availableBuffers) 88 { 89 m_bufferOp.Destroy(buf); 90 } 91 m_availableBuffers.clear(); 92 } 93 94 //! 95 //! \brief Initialize buffers 96 //! \param [in] hwInterface 97 //! Point to hardware interface 98 //! \param [in] allocator 99 //! Reference to decode allocator 100 //! \param [in] basicFeature 101 //! Basic feature 102 //! \param [in] initialAllocNum 103 //! The number of buffers allocated when initialize 104 //! \return MOS_STATUS 105 //! MOS_STATUS_SUCCESS if success, else fail reason 106 //! Init(void * hwInterface,DecodeAllocator & allocator,BasicFeature & basicFeature,uint32_t initialAllocNum)107 MOS_STATUS Init(void* hwInterface, DecodeAllocator& allocator, BasicFeature& basicFeature, 108 uint32_t initialAllocNum) 109 { 110 DECODE_FUNC_CALL(); 111 112 DECODE_CHK_STATUS(m_bufferOp.Init(hwInterface, allocator, basicFeature)); 113 114 DECODE_ASSERT(m_availableBuffers.empty()); 115 DECODE_ASSERT(m_activeBuffers.empty()); 116 117 for (uint32_t i = 0; i < initialAllocNum; i++) 118 { 119 BufferType *buffer = m_bufferOp.Allocate(); 120 DECODE_CHK_NULL(buffer); 121 m_availableBuffers.push_back(buffer); 122 } 123 124 return MOS_STATUS_SUCCESS; 125 } 126 127 //! 128 //! \brief Update buffers for current picture 129 //! \param [in] frameIdx 130 //! The frame index for current picture 131 //! \param [in] refFrameList 132 //! The frame indicies of reference frame list 133 //! \param [in] fixedFrameIdx 134 //! The frameIdx user wants to keep into the refFrameList 135 //! Default value is 0xff 136 //! \return MOS_STATUS 137 //! MOS_STATUS_SUCCESS if success, else fail reason 138 //! 139 MOS_STATUS UpdatePicture(uint32_t curFrameIdx, const std::vector<uint32_t> &refFrameList, uint32_t fixedFrameIdx = 0xff) 140 { 141 DECODE_FUNC_CALL(); 142 143 DECODE_CHK_STATUS(UpdateRefList(curFrameIdx, refFrameList, fixedFrameIdx)); 144 DECODE_CHK_STATUS(ActiveCurBuffer(curFrameIdx)); 145 146 return MOS_STATUS_SUCCESS; 147 } 148 149 //! 150 //! \brief Return buffer for current frame 151 //! \return BufferType* 152 //! Point to buffer for current frame, nullptr if fail 153 //! GetCurBuffer()154 BufferType* GetCurBuffer() { return m_currentBuffer; } 155 156 //! 157 //! \brief Return valid buffer for reference error concealment 158 //! \param [in] refFrameList 159 //! The frame indicies of reference frame list 160 //! \return BufferType* 161 //! Point of valid buffer, nullptr if fail 162 //! GetValidBufferForReference(const std::vector<uint32_t> & refFrameList)163 BufferType* GetValidBufferForReference(const std::vector<uint32_t> &refFrameList) 164 { 165 DECODE_FUNC_CALL(); 166 167 for(auto frameIdx : refFrameList) 168 { 169 BufferType* buffer = GetBufferByFrameIndex(frameIdx); 170 if (buffer != nullptr) 171 { 172 return buffer; 173 } 174 } 175 176 return GetCurBuffer(); 177 } 178 179 //! 180 //! \brief Return buffer by frame index 181 //! \param [in] frameIdx 182 //! The frame index for current picture 183 //! \return BufferType* 184 //! Point of buffer, nullptr if fail 185 //! GetBufferByFrameIndex(uint32_t frameIndex)186 BufferType* GetBufferByFrameIndex(uint32_t frameIndex) 187 { 188 DECODE_FUNC_CALL(); 189 190 auto iter = m_activeBuffers.find(frameIndex); 191 if (iter != m_activeBuffers.end()) 192 { 193 DECODE_ASSERT(iter->second != nullptr); 194 return iter->second; 195 } 196 197 return nullptr; 198 } 199 200 //! 201 //! \brief Return one available buffer 202 //! \return BufferType* 203 //! Point of buffer, nullptr if fail 204 //! GetAvailableBuffer()205 BufferType *GetAvailableBuffer() 206 { 207 DECODE_FUNC_CALL(); 208 209 BufferType *buffer = nullptr; 210 for (auto &availableBuffer : m_availableBuffers) 211 { 212 if (m_bufferOp.IsAvailable(availableBuffer)) 213 { 214 buffer = availableBuffer; 215 } 216 } 217 218 if (buffer == nullptr) 219 { 220 buffer = m_bufferOp.Allocate(); 221 if (buffer != nullptr) 222 { 223 m_availableBuffers.push_back(buffer); 224 } 225 } 226 227 return buffer; 228 } 229 230 //! 231 //! \brief Figure out buffer for current picture, and add it to active buffer list 232 //! \param [in] frameIdx 233 //! The frame index for current picture 234 //! \return MOS_STATUS 235 //! MOS_STATUS_SUCCESS if success, else fail reason 236 //! ActiveCurBuffer(uint32_t curFrameIdx)237 MOS_STATUS ActiveCurBuffer(uint32_t curFrameIdx) 238 { 239 DECODE_FUNC_CALL(); 240 241 m_currentBuffer = nullptr; 242 243 for (auto iter = m_activeBuffers.begin(); iter != m_activeBuffers.end(); iter++) 244 { 245 if (curFrameIdx == iter->first) 246 { 247 m_currentBuffer = iter->second; 248 return MOS_STATUS_SUCCESS; 249 } 250 } 251 252 // The function UpdateRefList always attach the retired buffers to end of 253 // available buffer list, reusing those buffers could improve the health with 254 // error stream, so pick up the last element of list for current frame as possible. 255 for (auto iter = m_availableBuffers.rbegin(); iter != m_availableBuffers.rend(); iter++) 256 { 257 if (m_bufferOp.IsAvailable(*iter)) 258 { 259 m_currentBuffer = *iter; 260 m_availableBuffers.erase((++iter).base()); 261 break; 262 } 263 } 264 265 if (m_currentBuffer == nullptr) 266 { 267 m_currentBuffer = m_bufferOp.Allocate(); 268 DECODE_CHK_NULL(m_currentBuffer); 269 } 270 m_bufferOp.Resize(m_currentBuffer); 271 272 auto ret = m_activeBuffers.insert(std::make_pair(curFrameIdx, m_currentBuffer)); 273 DECODE_CHK_COND(ret.second == false, 274 "Failed to acitve reference associated buffer with index %d, maybe it is already existed", 275 ret.first->first); 276 277 return MOS_STATUS_SUCCESS; 278 } 279 280 protected: 281 //! 282 //! \brief Update buffers corresponding to reference list 283 //! \param [in] curFrameIdx 284 //! The frame index for current picture 285 //! \param [in] refFrameList 286 //! The frame indicies of reference frame list 287 //! \param [in] fixedFrameIdx 288 //! The frameIdx user wants to keep into the refFrameList 289 //! \return MOS_STATUS 290 //! MOS_STATUS_SUCCESS if success, else fail reason 291 //! UpdateRefList(uint32_t curFrameIdx,const std::vector<uint32_t> & refFrameList,uint32_t fixedFrameIdx)292 MOS_STATUS UpdateRefList(uint32_t curFrameIdx, const std::vector<uint32_t> &refFrameList, uint32_t fixedFrameIdx) 293 { 294 DECODE_FUNC_CALL(); 295 296 auto iter = m_activeBuffers.begin(); 297 while (iter != m_activeBuffers.end()) 298 { 299 if (iter->first == fixedFrameIdx) 300 { 301 ++iter; 302 continue; 303 } 304 305 if (!IsReference(iter->first, curFrameIdx, refFrameList)) 306 { 307 auto buffer = iter->second; 308 iter = m_activeBuffers.erase(iter); 309 310 m_availableBuffers.push_back(buffer); 311 DECODE_CHK_STATUS(m_bufferOp.Deactive(buffer)); 312 } 313 else 314 { 315 ++iter; 316 } 317 } 318 319 return MOS_STATUS_SUCCESS; 320 } 321 322 //! 323 //! \brief Check if the index of buffer is persent in current reference list 324 //! \param [in] frameIndex 325 //! The frame index corresponding to buffer 326 //! \param [in] frameIdx 327 //! The frame index for current picture 328 //! \param [in] refFrameList 329 //! The frame indicies of reference frame list 330 //! \return bool 331 //! True if buffer is using by current frame, false if not 332 //! IsReference(uint32_t frameIdx,uint32_t curFrameIdx,const std::vector<uint32_t> & refFrameList)333 bool IsReference(uint32_t frameIdx, uint32_t curFrameIdx, const std::vector<uint32_t> &refFrameList) 334 { 335 DECODE_FUNC_CALL(); 336 337 if (frameIdx == curFrameIdx) 338 { 339 return false; 340 } 341 342 for(auto iter : refFrameList) 343 { 344 if (frameIdx == iter) 345 { 346 return true; 347 } 348 } 349 350 return false; 351 } 352 353 BufferOp m_bufferOp; //!< Buffer operation 354 std::map<uint32_t, BufferType*> m_activeBuffers; //!< Active buffers corresponding to current reference frame list 355 std::vector<BufferType*> m_availableBuffers; //!< Buffers in idle 356 BufferType* m_currentBuffer = nullptr; //!< Point to buffer of current picture 357 358 MEDIA_CLASS_DEFINE_END(decode__RefrenceAssociatedBuffer) 359 }; 360 361 } 362 #endif // !__DECODE_REFRENCE_ASSOCIATED_BUFFER_H__ 363