1 // Copyright (c) 2017 Intel Corporation 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in all 11 // copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 // SOFTWARE. 20 21 #include "umc_defs.h" 22 #if defined (MFX_ENABLE_H264_VIDEO_DECODE) 23 24 #ifndef __UMC_H264_HEAP_H 25 #define __UMC_H264_HEAP_H 26 27 #include <memory> 28 #include "umc_mutex.h" 29 #include "umc_h264_dec_defs_dec.h" 30 #include "umc_media_data.h" 31 32 namespace UMC 33 { 34 35 //*********************************************************************************************/ 36 // 37 //*********************************************************************************************/ 38 class H264MemoryPiece 39 { 40 public: 41 // Default constructor H264MemoryPiece()42 H264MemoryPiece() 43 { 44 m_pNext = 0; 45 m_pts = 0; 46 Reset(); 47 } 48 49 // Destructor ~H264MemoryPiece()50 ~H264MemoryPiece() 51 { 52 Release(); 53 } 54 Release()55 void Release() 56 { 57 delete[] m_pSourceBuffer; 58 Reset(); 59 } 60 SetData(MediaData * out)61 void SetData(MediaData *out) 62 { 63 Release(); 64 65 m_pDataPointer = (uint8_t*)out->GetDataPointer(); 66 m_nDataSize = out->GetDataSize(); 67 m_pts = out->GetTime(); 68 } 69 MoveToInternalBuffer()70 void MoveToInternalBuffer() 71 { 72 if (m_pSourceBuffer) 73 return; 74 75 m_nSourceSize = m_nDataSize + DEFAULT_NU_TAIL_SIZE; 76 m_pSourceBuffer = h264_new_array_throw<uint8_t>((int32_t)m_nSourceSize); 77 MFX_INTERNAL_CPY(m_pSourceBuffer, m_pDataPointer, m_nDataSize); 78 m_pDataPointer = m_pSourceBuffer; 79 } 80 81 // Allocate memory piece Allocate(size_t nSize)82 bool Allocate(size_t nSize) 83 { 84 Release(); 85 86 // allocate little more 87 m_pSourceBuffer = h264_new_array_throw<uint8_t>((int32_t)nSize); 88 m_pDataPointer = m_pSourceBuffer; 89 m_nSourceSize = nSize; 90 return true; 91 } 92 93 // Get next element GetNext()94 H264MemoryPiece *GetNext(){return m_pNext;} 95 // Obtain data pointer GetPointer()96 uint8_t *GetPointer(){return m_pDataPointer;} 97 GetSize()98 size_t GetSize() const {return m_nSourceSize;} 99 GetDataSize()100 size_t GetDataSize() const {return m_nDataSize;} SetDataSize(size_t dataSize)101 void SetDataSize(size_t dataSize) {m_nDataSize = dataSize;} 102 GetTime()103 double GetTime() const {return m_pts;} SetTime(double pts)104 void SetTime(double pts) {m_pts = pts;} 105 106 protected: 107 uint8_t *m_pSourceBuffer; // (uint8_t *) pointer to source memory 108 uint8_t *m_pDataPointer; // (uint8_t *) pointer to source memory 109 size_t m_nSourceSize; // (size_t) allocated memory size 110 size_t m_nDataSize; // (size_t) data memory size 111 H264MemoryPiece *m_pNext; // (H264MemoryPiece *) pointer to next memory piece 112 double m_pts; 113 Reset()114 void Reset() 115 { 116 m_pSourceBuffer = 0; 117 m_pDataPointer = 0; 118 m_nSourceSize = 0; 119 m_nDataSize = 0; 120 } 121 122 private: 123 H264MemoryPiece( const H264MemoryPiece &s ); // no copy CTR 124 H264MemoryPiece & operator=(const H264MemoryPiece &s ); 125 }; 126 127 128 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 129 // Item class 130 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 131 class H264_Heap_Objects; 132 133 class Item 134 { 135 public: 136 Item(H264_Heap_Objects * heap, void * ptr, size_t size, bool isTyped = false) 137 : m_pNext(0) 138 , m_Ptr(ptr) 139 , m_Size(size) 140 , m_isTyped(isTyped) 141 , m_heap(heap) 142 { 143 } 144 ~Item()145 ~Item() 146 { 147 } 148 149 Item* m_pNext; 150 void * m_Ptr; 151 size_t m_Size; 152 bool m_isTyped; 153 H264_Heap_Objects * m_heap; 154 155 static Item * Allocate(H264_Heap_Objects * heap, size_t size, bool isTyped = false) 156 { 157 uint8_t * ppp = new uint8_t[size + sizeof(Item)]; 158 if (!ppp) 159 throw h264_exception(UMC_ERR_ALLOC); 160 Item * item = new (ppp) Item(heap, 0, size, isTyped); 161 item->m_Ptr = (uint8_t*)ppp + sizeof(Item); 162 return item; 163 } 164 Free(Item * item)165 static void Free(Item *item) 166 { 167 if (item->m_isTyped) 168 { 169 HeapObject * obj = reinterpret_cast<HeapObject *>(item->m_Ptr); 170 obj->~HeapObject(); 171 } 172 173 item->~Item(); 174 delete[] (uint8_t*)item; 175 } 176 }; 177 178 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 179 // H264_Heap_Objects class 180 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 181 class H264_Heap_Objects 182 { 183 public: 184 H264_Heap_Objects()185 H264_Heap_Objects() 186 : m_pFirstFree(0) 187 { 188 } 189 ~H264_Heap_Objects()190 virtual ~H264_Heap_Objects() 191 { 192 Release(); 193 } 194 195 Item * GetItemForAllocation(size_t size, bool typed = false) 196 { 197 if (!m_pFirstFree) 198 { 199 return 0; 200 } 201 202 if (m_pFirstFree->m_Size == size && m_pFirstFree->m_isTyped == typed) 203 { 204 Item * ptr = m_pFirstFree; 205 m_pFirstFree = m_pFirstFree->m_pNext; 206 return ptr; 207 } 208 209 Item * temp = m_pFirstFree; 210 211 while (temp->m_pNext) 212 { 213 if (temp->m_pNext->m_Size == size && temp->m_pNext->m_isTyped == typed) 214 { 215 Item * ptr = temp->m_pNext; 216 temp->m_pNext = temp->m_pNext->m_pNext; 217 return ptr; 218 } 219 220 temp = temp->m_pNext; 221 } 222 223 return 0; 224 } 225 226 void* Allocate(size_t size, bool isTyped = false) 227 { 228 Item * item = GetItemForAllocation(size); 229 if (!item) 230 { 231 item = Item::Allocate(this, size, isTyped); 232 } 233 234 return item->m_Ptr; 235 } 236 237 template<typename T> 238 T* Allocate(size_t size = sizeof(T), bool isTyped = false) 239 { 240 return (T*)Allocate(size, isTyped); 241 } 242 243 template <typename T> AllocateObject()244 T* AllocateObject() 245 { 246 Item * item = GetItemForAllocation(sizeof(T), true); 247 248 if (!item) 249 { 250 void * ptr = Allocate(sizeof(T), true); 251 return new(ptr) T(); 252 } 253 254 return (T*)(item->m_Ptr); 255 } 256 257 void FreeObject(void * obj, bool force = false) 258 { 259 Free(obj, force); 260 } 261 262 void Free(void * obj, bool force = false) 263 { 264 if (!obj) 265 return; 266 267 Item * item = (Item *) ((uint8_t*)obj - sizeof(Item)); 268 269 // check 270 Item * temp = m_pFirstFree; 271 272 while (temp) 273 { 274 if (temp == item) 275 { //was removed yet 276 return; 277 } 278 279 temp = temp->m_pNext; 280 } 281 282 if (force) 283 { 284 Item::Free(item); 285 return; 286 } 287 else 288 { 289 if (item->m_isTyped) 290 { 291 HeapObject * object = reinterpret_cast<HeapObject *>(item->m_Ptr); 292 object->Reset(); 293 } 294 } 295 296 item->m_pNext = m_pFirstFree; 297 m_pFirstFree = item; 298 } 299 Release()300 void Release() 301 { 302 while (m_pFirstFree) 303 { 304 Item *pTemp = m_pFirstFree->m_pNext; 305 Item::Free(m_pFirstFree); 306 m_pFirstFree = pTemp; 307 } 308 } 309 310 private: 311 312 Item * m_pFirstFree; 313 }; 314 315 316 //*********************************************************************************************/ 317 // H264_List implementation 318 //*********************************************************************************************/ 319 template <typename T> 320 class H264_List 321 { 322 public: 323 class Item : public HeapObject 324 { 325 public: Item(T * item,int32_t pid)326 Item(T *item, int32_t pid) 327 : m_pNext(0) 328 , m_Item(item) 329 , m_pid(pid) 330 { 331 } 332 Reset()333 virtual void Reset() 334 { 335 m_Item->Reset(); 336 } 337 338 Item * m_pNext; 339 T *m_Item; 340 int32_t m_pid; 341 }; 342 H264_List(H264_Heap_Objects * pObjHeap)343 H264_List(H264_Heap_Objects * pObjHeap) 344 : m_pHead(0) 345 , m_pObjHeap(pObjHeap) 346 { 347 } 348 ~H264_List()349 ~H264_List() 350 { 351 Reset(); 352 } 353 RemoveHead()354 void RemoveHead() 355 { 356 Item * tmp = m_pHead; 357 m_pHead = m_pHead->m_pNext; 358 m_pObjHeap->FreeObject(tmp); 359 } 360 RemoveItem(T * item)361 void RemoveItem(T * item) 362 { 363 if (!m_pHead) 364 { 365 VM_ASSERT(false); 366 return; 367 } 368 369 Item *tmp = m_pHead; 370 371 if (tmp->m_Item == item) 372 { 373 m_pHead = m_pHead->m_pNext; 374 m_pObjHeap->FreeObject(tmp); 375 return; 376 } 377 378 while (tmp->m_pNext) 379 { 380 if (tmp->m_pNext->m_Item == item) 381 { 382 Item * list_item = tmp->m_pNext; 383 tmp->m_pNext = tmp->m_pNext->m_pNext; 384 m_pObjHeap->FreeObject(list_item); 385 return; 386 } 387 388 tmp = tmp->m_pNext; 389 } 390 391 // it was removed before 392 VM_ASSERT(false); 393 } 394 DetachItemByPid(int32_t pid)395 T * DetachItemByPid(int32_t pid) 396 { 397 if (!m_pHead) 398 { 399 return 0; 400 } 401 402 T * item = 0; 403 Item *tmp = m_pHead; 404 for (; tmp; tmp = tmp->m_pNext) 405 { 406 if (tmp->m_pid == pid) 407 { 408 item = tmp->m_Item; 409 break; 410 } 411 } 412 413 if (!tmp) 414 return 0; 415 416 tmp = m_pHead; 417 418 if (tmp->m_Item == item) 419 { 420 m_pHead = m_pHead->m_pNext; 421 m_pObjHeap->FreeObject(tmp); 422 return item; 423 } 424 425 while (tmp->m_pNext) 426 { 427 if (tmp->m_pNext->m_Item == item) 428 { 429 Item * list_item = tmp->m_pNext; 430 tmp->m_pNext = tmp->m_pNext->m_pNext; 431 m_pObjHeap->FreeObject(list_item); 432 return item; 433 } 434 435 tmp = tmp->m_pNext; 436 } 437 438 VM_ASSERT(false); 439 return 0; 440 } 441 FindByPid(int32_t pid)442 T* FindByPid(int32_t pid) 443 { 444 for (Item *tmp = m_pHead; tmp; tmp = tmp->m_pNext) 445 { 446 if (tmp->m_pid == pid) 447 return tmp->m_Item; 448 } 449 450 return 0; 451 } 452 FindLastByPid(int32_t pid)453 T* FindLastByPid(int32_t pid) const 454 { 455 T *last = 0; 456 for (Item *tmp = m_pHead; tmp; tmp = tmp->m_pNext) 457 { 458 if (tmp->m_pid == pid) 459 last = tmp->m_Item; 460 } 461 462 return last; 463 } 464 AddItem(T * item,int32_t pid)465 void AddItem(T *item, int32_t pid) 466 { 467 Item * buf = (Item*)m_pObjHeap->Allocate(sizeof(Item)); 468 Item *newItem = new(buf) Item(item, pid); 469 470 Item *tmp = m_pHead; 471 if (m_pHead) 472 { 473 while (tmp->m_pNext) 474 { 475 tmp = tmp->m_pNext; 476 } 477 478 tmp->m_pNext = newItem; 479 } 480 else 481 { 482 m_pHead = newItem; 483 } 484 } 485 GetHead()486 T * GetHead() 487 { 488 return m_pHead->m_Item; 489 } 490 GetHead()491 const T * GetHead() const 492 { 493 return m_pHead->m_Item; 494 } 495 Reset()496 void Reset() 497 { 498 for (Item *tmp = m_pHead; tmp; ) 499 { 500 Item *tmp1 = tmp; 501 tmp = tmp->m_pNext; 502 m_pObjHeap->FreeObject(tmp1); 503 } 504 505 m_pHead = 0; 506 } 507 508 private: 509 Item * m_pHead; 510 H264_Heap_Objects * m_pObjHeap; 511 }; 512 513 //*********************************************************************************************/ 514 // 515 //*********************************************************************************************/ 516 class H264CoeffsBuffer : public HeapObject 517 { 518 public: 519 // Default constructor 520 H264CoeffsBuffer(void); 521 // Destructor 522 virtual ~H264CoeffsBuffer(void); 523 524 // Initialize buffer 525 Status Init(int32_t numberOfItems, int32_t sizeOfItem); 526 527 bool IsInputAvailable() const; 528 // Lock input buffer 529 uint8_t* LockInputBuffer(); 530 // Unlock input buffer 531 bool UnLockInputBuffer(size_t size); 532 533 bool IsOutputAvailable() const; 534 // Lock output buffer 535 bool LockOutputBuffer(uint8_t *& pointer, size_t &size); 536 // Unlock output buffer 537 bool UnLockOutputBuffer(); 538 // Release object 539 void Close(void); 540 // Reset object 541 virtual void Reset(void); 542 543 virtual void Free(); 544 545 protected: 546 uint8_t *m_pbAllocatedBuffer; // (uint8_t *) pointer to allocated unaligned buffer 547 size_t m_lAllocatedBufferSize; // (int32_t) size of allocated buffer 548 549 uint8_t *m_pbBuffer; // (uint8_t *) pointer to allocated buffer 550 size_t m_lBufferSize; // (int32_t) size of using buffer 551 552 uint8_t *m_pbFree; // (uint8_t *) pointer to free space 553 size_t m_lFreeSize; // (int32_t) size of free space 554 555 size_t m_lItemSize; // (int32_t) size of output data portion 556 557 struct BufferInfo 558 { 559 uint8_t * m_pPointer; 560 size_t m_Size; 561 BufferInfo *m_pNext; 562 }; 563 564 BufferInfo *m_pBuffers; // (Buffer *) queue of filled sample info 565 private: 566 H264CoeffsBuffer( const H264CoeffsBuffer &s ); // no copy CTR 567 H264CoeffsBuffer & operator=(const H264CoeffsBuffer &s ); 568 }; 569 570 } // namespace UMC 571 572 #endif // __UMC_H264_HEAP_H 573 #endif // MFX_ENABLE_H264_VIDEO_DECODE 574