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