• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #ifndef PVMF_MEDIA_FRAG_GROUP_H_INCLUDED
19 #define PVMF_MEDIA_FRAG_GROUP_H_INCLUDED
20 
21 #ifndef PVMF_MEDIA_DATA_IMPL_H_INCLUDED
22 #include "pvmf_media_data_impl.h"
23 #endif
24 
25 #ifndef OSCL_SHARED_PTR_H_INCLUDED
26 #include "oscl_shared_ptr.h"
27 #endif
28 
29 #ifndef OSCL_VECTOR_H_INCLUDED
30 #include "oscl_vector.h"
31 #endif
32 
33 #ifndef OSCL_MEM_H_INCLUDED
34 #include "oscl_mem.h"
35 #endif
36 
37 #ifndef OSCL_MEM_MEMPOOL_H_INCLUDED
38 #include "oscl_mem_mempool.h"
39 #endif
40 
41 // constants
42 const uint PVMF_MEDIA_FRAG_GROUP_DEFAULT_CAPACITY = 10;
43 
44 class MediaDataEntry
45 {
46     public:
MediaDataEntry()47         MediaDataEntry() : next(NULL) {}
~MediaDataEntry()48         ~MediaDataEntry()
49         {
50             mediaDataImpl.Unbind();
51         }
52         OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl;
53         MediaDataEntry* next;
54 };
55 
56 /**
57  * The PVMFMediaFragGroup class is a MediaDataImpl implementation that
58  * stores multiple OsclRefCounterMemFrag which have been separately allocated.
59  * It takes an allocator as a templatized parameter to allow the user to determine
60  * how memory for storing the fragments internally is allocated.
61  * The PVMFMediaFragGroup is created with a fixed capacity that is passed in at
62  * construction time.
63  */
64 template<class Alloc>
65 class PVMFMediaFragGroup : public PVMFMediaDataImpl
66 {
67 
68     public:
69         virtual uint32 getMarkerInfo();
70         virtual bool isRandomAccessPoint();
71         virtual uint32 getErrorsFlag();
72         virtual uint32 getNumFragments();
73         virtual bool getMediaFragment(uint32 index, OsclRefCounterMemFrag& memfrag);
74         virtual bool getMediaFragmentSize(uint32 index, uint32& size);
75         virtual uint32 getFilledSize();
76         virtual uint32 getCapacity();
77 
78         virtual void setCapacity(uint32 aCapacity);
79         virtual bool setMediaFragFilledLen(uint32 index, uint32 len);
80         virtual bool setMarkerInfo(uint32 marker);
81         virtual bool setRandomAccessPoint(bool flag);
82         virtual bool setErrorsFlag(uint32 flag);
83 
84         virtual bool appendMediaFragment(OsclRefCounterMemFrag& memfrag);
85         virtual bool clearMediaFragments();
86 
87         /* NOTE!!:  The constructor assumes the refcnt has already been incremented
88          * to reflect this class holding a reference to the buffer. Increment it
89          * externally if you aren't simply passing ownership of a reference
90          */
91         PVMFMediaFragGroup(uint32 capacity = PVMF_MEDIA_FRAG_GROUP_DEFAULT_CAPACITY);
92 
93         virtual ~PVMFMediaFragGroup();
94 
95     private:
96         uint32 marker_info;
97         bool random_access_point;
98         uint32 errors_flag;
99         Oscl_Vector<OsclRefCounterMemFrag, Alloc> iFragments;
100         uint32 capacity;
101         uint32 filled_size;
102 };
103 
104 
105 /**
106  * The PVMFMediaFragGroupCombinedAlloc allocator class
107  * takes care of allocating the refcounter, PVMFMediaFragGroup container,
108  * and the actual buffer space in a single block of memory.
109  */
110 template<class Alloc>
111 class PVMFMediaFragGroupCombinedAlloc : public OsclDestructDealloc
112 {
113 
114     public:
115         PVMFMediaFragGroupCombinedAlloc(uint in_capacity, uint in_fragment_capacity,
116                                         Oscl_DefAlloc* opt_gen_alloc = 0)
capacity(in_capacity)117                 : capacity(in_capacity)
118                 , fragment_capacity(in_fragment_capacity)
119                 , gen_alloc(opt_gen_alloc)
120                 , available_mfgs(NULL)
121                 , num_available_mfgs(0)
122                 , iRefCnt(0)
123                 , iDestroy(false)
124                 , iCheckNextAvailableFreeChunk(false)
125                 , iObserver(NULL)
126                 , iNextAvailableContextData(NULL)
127         {
128             addRef();
129         };
130         virtual ~PVMFMediaFragGroupCombinedAlloc();
131         void create();
132         void destroy();
133         void addRef();
134         void removeRef();
135         void do_allocate(uint32 requested_fragment_capacity = 0);
136         OsclSharedPtr<PVMFMediaDataImpl> allocate(uint32 requested_fragment_capacity = 0);
137         void destruct_and_dealloc(OsclAny* ptr);
IsMsgAvailable()138         bool IsMsgAvailable()
139         {
140             if (available_mfgs == NULL)
141             {
142                 return false;
143             }
144             return true;
145         }
146 
147         void notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& obs, OsclAny* aContextData = NULL)
148         {
149             iCheckNextAvailableFreeChunk = true;
150             iObserver = &obs;
151             iNextAvailableContextData = aContextData;
152         }
153 
CancelFreeChunkAvailableCallback()154         void CancelFreeChunkAvailableCallback()
155         {
156             iCheckNextAvailableFreeChunk = false;
157             iObserver = NULL;
158             iNextAvailableContextData = NULL;
159         }
160 
NumMsgAvail()161         unsigned NumMsgAvail()
162         {
163             return num_available_mfgs;
164         }
165 
166     protected:
167         void append(OsclSharedPtr<PVMFMediaDataImpl> & media_data);
168         void append(uint8* my_ptr);
169 
170         uint capacity;
171         uint fragment_capacity;
172         Oscl_DefAlloc* gen_alloc;
173         MediaDataEntry* available_mfgs;
174         unsigned num_available_mfgs;
175         OsclMemPoolFixedChunkAllocator* media_data_entry_alloc;
176         int32 iRefCnt;
177         bool iDestroy;
178         bool iCheckNextAvailableFreeChunk;
179         OsclMemPoolFixedChunkAllocatorObserver* iObserver;
180         OsclAny* iNextAvailableContextData;
181 };
182 
183 
184 template<class Alloc>
~PVMFMediaFragGroup()185 PVMFMediaFragGroup<Alloc>::~PVMFMediaFragGroup()
186 {
187     // clear all the fragments
188     iFragments.clear();
189 }
190 
191 template<class Alloc>
getMarkerInfo()192 uint32 PVMFMediaFragGroup<Alloc>::getMarkerInfo()
193 {
194     return marker_info;
195 }
196 
197 template<class Alloc>
isRandomAccessPoint()198 bool PVMFMediaFragGroup<Alloc>::isRandomAccessPoint()
199 {
200     return random_access_point;
201 }
202 
203 template<class Alloc>
getErrorsFlag()204 uint32 PVMFMediaFragGroup<Alloc>::getErrorsFlag()
205 {
206     return errors_flag;
207 }
208 
209 template<class Alloc>
getNumFragments()210 uint32 PVMFMediaFragGroup<Alloc>::getNumFragments()
211 {
212     return iFragments.size();
213 }
214 
215 template<class Alloc>
getMediaFragment(uint32 index,OsclRefCounterMemFrag & memfrag)216 bool PVMFMediaFragGroup<Alloc>::getMediaFragment(uint32 index, OsclRefCounterMemFrag& memfrag)
217 {
218     if (index >= iFragments.size())
219     {
220         return false;
221     }
222 
223     memfrag = OsclRefCounterMemFrag(iFragments[index]);
224 
225     return true;
226 }
227 
228 template<class Alloc>
getMediaFragmentSize(uint32 index,uint32 & size)229 bool PVMFMediaFragGroup<Alloc>::getMediaFragmentSize(uint32 index, uint32& size)
230 {
231     size = 0;
232     if (index >= iFragments.size())
233     {
234         return false;
235     }
236 
237     size = iFragments[index].getMemFrag().len;
238 
239     return true;
240 }
241 
242 template<class Alloc>
getFilledSize()243 uint32 PVMFMediaFragGroup<Alloc>::getFilledSize()
244 {
245     return filled_size;
246 }
247 
248 template<class Alloc>
getCapacity()249 uint32 PVMFMediaFragGroup<Alloc>::getCapacity()
250 {
251     return capacity;
252 }
253 
254 template<class Alloc>
setCapacity(uint32 aCapacity)255 void PVMFMediaFragGroup<Alloc>::setCapacity(uint32 aCapacity)
256 {
257     capacity = aCapacity;
258     return;
259 }
260 
261 template<class Alloc>
setMediaFragFilledLen(uint32 index,uint32 len)262 bool PVMFMediaFragGroup<Alloc>::setMediaFragFilledLen(uint32 index, uint32 len)
263 {
264     if (index >= iFragments.size())
265     {
266         return false;
267     }
268 
269     if (len > iFragments[index].getCapacity())
270     {
271         return false;
272     }
273 
274     filled_size -= iFragments[index].getMemFrag().len;
275     iFragments[index].getMemFrag().len = len;
276     filled_size += len;
277     return true;
278 }
279 
280 template<class Alloc>
setMarkerInfo(uint32 in_marker)281 bool PVMFMediaFragGroup<Alloc>::setMarkerInfo(uint32 in_marker)
282 {
283     marker_info = in_marker;
284     return true;
285 }
286 
287 template<class Alloc>
setRandomAccessPoint(bool flag)288 bool PVMFMediaFragGroup<Alloc>::setRandomAccessPoint(bool flag)
289 {
290     random_access_point = flag;
291     return true;
292 }
293 
294 template<class Alloc>
setErrorsFlag(uint32 flag)295 bool PVMFMediaFragGroup<Alloc>::setErrorsFlag(uint32 flag)
296 {
297     errors_flag = flag;
298     return true;
299 }
300 
301 template<class Alloc>
PVMFMediaFragGroup(uint32 in_capacity)302 PVMFMediaFragGroup<Alloc>::PVMFMediaFragGroup(uint32 in_capacity) :
303         marker_info(0), random_access_point(false), errors_flag(0)
304 {
305     iFragments.reserve(in_capacity);
306     capacity = 0;
307     filled_size = 0;
308 }
309 
310 template<class Alloc>
appendMediaFragment(OsclRefCounterMemFrag & memfrag)311 bool PVMFMediaFragGroup<Alloc>::appendMediaFragment(OsclRefCounterMemFrag& memfrag)
312 {
313     iFragments.push_back(memfrag);
314     capacity += memfrag.getCapacity();
315     filled_size += memfrag.getMemFrag().len;
316     return true;
317 }
318 
319 template<class Alloc>
clearMediaFragments()320 bool PVMFMediaFragGroup<Alloc>::clearMediaFragments()
321 {
322     iFragments.clear();
323     capacity = 0;
324     filled_size = 0;
325     return true;
326 }
327 
328 template<class Alloc>
~PVMFMediaFragGroupCombinedAlloc()329 PVMFMediaFragGroupCombinedAlloc<Alloc>::~PVMFMediaFragGroupCombinedAlloc()
330 {
331     removeRef();
332 }
333 
334 template<class Alloc>
addRef()335 void PVMFMediaFragGroupCombinedAlloc<Alloc>::addRef()
336 {
337     iRefCnt++;
338 }
339 
340 template<class Alloc>
removeRef()341 void PVMFMediaFragGroupCombinedAlloc<Alloc>::removeRef()
342 {
343     //we need to make sure that this allocator persists as long as
344     //all buffers allocated it have been released. Therefore we need
345     //a notion of reference count for the allocator itself. iRefCnt
346     //is incremented in addRef and is set decremented here.
347     iRefCnt--;
348     if ((iRefCnt == 0) &&
349             (num_available_mfgs == capacity))
350     {
351         //implies that all messages are have been returned
352         //if not, wait for all messages to return
353         //this allocator needs to live till all messages allocated by
354         //it have been released
355         destroy();
356     }
357 }
358 
359 template<class Alloc>
create()360 void PVMFMediaFragGroupCombinedAlloc<Alloc>::create()
361 {
362     media_data_entry_alloc = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (capacity));
363     for (uint num = 0; num < capacity; num++)
364     {
365         do_allocate(fragment_capacity);
366     }
367 }
368 
369 template<class Alloc>
do_allocate(uint32 requested_size)370 void PVMFMediaFragGroupCombinedAlloc<Alloc>::do_allocate(uint32 requested_size)
371 {
372     if (requested_size == 0)
373     {
374         requested_size = PVMF_MEDIA_FRAG_GROUP_DEFAULT_CAPACITY;
375     }
376 
377     uint aligned_class_size = oscl_mem_aligned_size(sizeof(PVMFMediaFragGroup<Alloc>));
378     OsclRefCounter* my_refcnt = NULL;
379     uint8* my_ptr = NULL;
380 
381     uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
382     my_ptr = (uint8*) gen_alloc->ALLOCATE(aligned_refcnt_size + aligned_class_size);
383     // create the recounter after the cleanup object
384     my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(my_ptr, this));
385     my_ptr += aligned_refcnt_size;
386 
387     PVMFMediaDataImpl* media_data_ptr = OSCL_PLACEMENT_NEW(my_ptr, PVMFMediaFragGroup<Alloc>(requested_size));
388 
389     OsclSharedPtr<PVMFMediaDataImpl> shared_media_data(media_data_ptr, my_refcnt);
390     append(shared_media_data);
391 }
392 
393 template<class Alloc>
append(OsclSharedPtr<PVMFMediaDataImpl> & media_data)394 void PVMFMediaFragGroupCombinedAlloc<Alloc>::append(OsclSharedPtr<PVMFMediaDataImpl> & media_data)
395 {
396     void* memory_for_entry = media_data_entry_alloc->ALLOCATE(sizeof(MediaDataEntry));
397     MediaDataEntry* entry = OSCL_PLACEMENT_NEW(memory_for_entry, MediaDataEntry());
398     entry->mediaDataImpl = media_data;
399 
400     MediaDataEntry* first = entry;
401     if (available_mfgs)
402     {
403         first = available_mfgs->next;
404         available_mfgs->next = entry;
405     }
406     available_mfgs = entry;
407     entry->next = first;
408     num_available_mfgs++;
409 }
410 
411 template<class Alloc>
append(uint8 * my_ptr)412 void PVMFMediaFragGroupCombinedAlloc<Alloc>::append(uint8* my_ptr)
413 {
414     uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
415     PVMFMediaDataImpl* media_data_ptr = (PVMFMediaDataImpl*)(my_ptr + aligned_refcnt_size);
416     OsclRefCounter* my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterDA(my_ptr, this));
417     void* memory_for_entry = media_data_entry_alloc->ALLOCATE(sizeof(MediaDataEntry));
418     MediaDataEntry* entry = OSCL_PLACEMENT_NEW(memory_for_entry, MediaDataEntry());
419     entry->mediaDataImpl.Bind(media_data_ptr, my_refcnt);
420 
421     MediaDataEntry* first = entry;
422     if (available_mfgs)
423     {
424         first = available_mfgs->next;
425         available_mfgs->next = entry;
426     }
427     available_mfgs = entry;
428     entry->next = first;
429     num_available_mfgs++;
430     if ((iRefCnt == 0) && (num_available_mfgs == capacity))
431     {
432         //iRefCnt of zero implies that owner of PVMFMediaFragGroupCombinedAlloc
433         //has given up ownership (meaning no more allocations)
434         //But we need to wait for all msgs to be released before we can destroy
435         //the allocators.
436         destroy();
437     }
438 }
439 
440 template<class Alloc>
allocate(uint32 requested_size)441 OsclSharedPtr<PVMFMediaDataImpl> PVMFMediaFragGroupCombinedAlloc<Alloc>::allocate(uint32 requested_size)
442 {
443     OsclSharedPtr<PVMFMediaDataImpl> media_data;
444 
445     if (requested_size > fragment_capacity)
446     {
447         OSCL_LEAVE(OSCL_BAD_ALLOC_EXCEPTION_CODE);
448     }
449 
450     if (available_mfgs == NULL)
451     {
452         //all required memory must have been allocated in "do_allocate"
453         //which is called as part of "create". any exception in either of
454         //these methods means that the allocator could not be created, but
455         //upon successful creation if "available_mfgs" is NULL then it means
456         //we are temporarily out of memory, and there is no need to throw
457         //an exception in this case
458         return media_data;
459     }
460 
461     MediaDataEntry* first = available_mfgs->next;
462     media_data = first->mediaDataImpl;
463 
464     if (first == available_mfgs)
465     {
466         available_mfgs = NULL;
467     }
468     else
469     {
470         available_mfgs->next = first->next;
471     }
472     first->~MediaDataEntry();
473     media_data_entry_alloc->deallocate(first);
474     num_available_mfgs--;
475     return media_data;
476 }
477 
478 template<class Alloc>
destroy()479 void PVMFMediaFragGroupCombinedAlloc<Alloc>::destroy()
480 {
481     iDestroy = true;
482     MediaDataEntry* first = NULL;
483     if (available_mfgs)
484     {
485         first = available_mfgs->next;
486         available_mfgs->next = NULL;
487     }
488 
489     while (first)
490     {
491         MediaDataEntry* cur = first;
492         first = first->next;
493         cur->~MediaDataEntry();
494         media_data_entry_alloc->deallocate(cur);
495     }
496 
497     if (media_data_entry_alloc)
498     {
499         OSCL_DELETE(media_data_entry_alloc);
500     }
501     OSCL_DELETE(this);
502 }
503 
504 
505 template<class Alloc>
destruct_and_dealloc(OsclAny * ptr)506 void PVMFMediaFragGroupCombinedAlloc<Alloc>::destruct_and_dealloc(OsclAny* ptr)
507 {
508     uint8* my_ptr = (uint8*)ptr;
509     uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
510     PVMFMediaDataImpl* media_data_ptr = (PVMFMediaDataImpl*)(my_ptr + aligned_refcnt_size);
511     media_data_ptr->clearMediaFragments();
512 
513     if (!iDestroy)
514     {
515         if (iCheckNextAvailableFreeChunk == true)
516         {
517             iCheckNextAvailableFreeChunk = false;
518             if (iObserver)
519             {
520                 iObserver->freechunkavailable(iNextAvailableContextData);
521             }
522         }
523         append(my_ptr);
524     }
525     else
526     {
527         media_data_ptr->~PVMFMediaDataImpl();
528         gen_alloc->deallocate(ptr);
529     }
530 }
531 
532 #endif
533 
534