• 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 // -*- c++ -*-
19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
20 
21 //               O S C L _ M E D I A _ D A T A
22 
23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
24 
25 /*! \addtogroup osclutil OSCL Util
26  *
27  * @{
28  */
29 
30 
31 /** \file oscl_media_data.h
32     \brief Defines a container class for media data made up of a collection of memory fragments.
33 */
34 
35 #ifndef OSCL_MEDIA_DATA_H
36 #define OSCL_MEDIA_DATA_H
37 
38 #ifndef OSCL_BASE_H_INCLUDED
39 #include "oscl_base.h"
40 #endif
41 
42 #ifndef OSCL_MEM_BASIC_FUNCTIONS_H_INCLUDED
43 #include "oscl_mem_basic_functions.h"
44 #endif
45 
46 #ifndef OSCL_MEDIA_STATUS_H_INCLUDED
47 #include "oscl_media_status.h"
48 #endif
49 
50 typedef void (*BufferFreeFuncPtr)(void *);
51 
52 typedef uint32 MediaTimestamp;
53 
54 template <class T> class MemAllocator
55 {
56     public:
57         typedef T* pointer;
58         //  virtual pointer allocate(size_t size, void *hint = 0) = 0;
59         virtual pointer allocate(void * hint = 0, const int num_reserved_frags = 1) = 0;
60         virtual void deallocate(pointer p) = 0;
~MemAllocator()61         virtual ~MemAllocator() {}
62 };
63 
64 class BufferState;
65 /* Buffer referee (how about the "whistle blower" ?*/
66 class BufferMgr
67 {
68     public:
69         virtual void BufferReleased(void* ptr, BufferState* state = NULL) = 0;
~BufferMgr()70         virtual ~BufferMgr() {}
71 };
72 
73 
74 class BufferState
75 {
76     public:
77         BufferState(BufferFreeFuncPtr the_free_function, void *bufptr = 0) :
78                 refcount(0), ptr(bufptr), free_function(the_free_function), buf_mgr(0) {};
79 
80         BufferState(BufferMgr* the_buf_mgr = 0, void *bufptr = 0) :
81                 refcount(0), ptr(bufptr), free_function(0), buf_mgr(the_buf_mgr) {};
82 
increment_refcnt()83         void increment_refcnt()
84         {
85             ++refcount;
86         };
decrement_refcnt()87         void decrement_refcnt()
88         {
89             if (!(--refcount))
90             {
91                 if (buf_mgr) buf_mgr->BufferReleased(ptr, this);
92                 else if (free_function)
93                 {
94                     free_function(ptr);
95                     ptr = 0;
96                 }
97             }
98         };
99 
bind(void * in_ptr,BufferFreeFuncPtr in_free_function)100         void bind(void *in_ptr, BufferFreeFuncPtr in_free_function)
101         {
102             refcount = 0;
103             ptr = in_ptr, free_function = in_free_function;
104 
105         };
bind(void * in_ptr,BufferMgr * in_buf_mgr)106         void bind(void *in_ptr, BufferMgr* in_buf_mgr)
107         {
108             refcount = 0;
109             ptr = in_ptr, buf_mgr = in_buf_mgr;
110         };
111 
get_ptr()112         void *get_ptr()
113         {
114             return ptr;
115         };
get_refcount()116         int32 get_refcount()
117         {
118             return refcount;
119         };
120 
get_free_function()121         BufferFreeFuncPtr get_free_function()
122         {
123             return free_function;
124         };
get_buf_mgr()125         BufferMgr* get_buf_mgr()
126         {
127             return buf_mgr;
128         };
129 
reset()130         void reset()
131         {
132             refcount = 0;
133             ptr = 0;
134         };
135 
136     private:
137         int32 refcount;
138         void *ptr;
139         BufferFreeFuncPtr free_function; // called to free the buffer
140         BufferMgr* buf_mgr; // called to free the buffer
141 };
142 
143 
144 // BufferFragment is a special case of a memory
145 // fragment since it refers to fragments of a reference
146 // counted memory.  The name is used to make this explicit.
147 class BufferFragment : public OsclMemoryFragment {};
148 
149 
150 template <class ChainClass, uint32 max_frags> class BufFragGroup
151 {
152     public:
153 
154 
BufFragGroup()155         BufFragGroup(): next(0), num_fragments(0), length(0)
156         {
157             oscl_memset(fragments, 0, sizeof(fragments));
158             oscl_memset(buffer_states, 0, sizeof(buffer_states));
159         };
160 
~BufFragGroup()161         virtual ~BufFragGroup() {}
162 
GetMaxFrags()163         int32 GetMaxFrags() const
164         {
165             return max_frags;
166         };
GetNumFrags()167         int32 GetNumFrags() const
168         {
169             return num_fragments;
170         };
GetLength()171         uint32 GetLength() const
172         {
173             return length;
174         };
175 
176         BufferFragment * GetFragment(const int32 idx);
177 
178         BufferState * GetBufferState(const int32 idx);
179 
AppendNext(ChainClass * next_ptr)180         void AppendNext(ChainClass* next_ptr)
181         {
182             next = next_ptr;
183         };
GetNext()184         ChainClass* GetNext() const
185         {
186             return next;
187         };
188 
189         // make fragment array accessible to allow usage within socket
190         // send functions.
191 
192     protected:
193 
194 
195         // BufferFragment * GetFragment(const uint32 idx) const;
196 
197 
198 
Clear()199         virtual void Clear()
200         {
201             for (uint ii = 0 ; ii < num_fragments; ++ii)
202             {
203                 if (buffer_states[ii])
204                 {
205                     buffer_states[ii]->decrement_refcnt();
206                 }
207             }
208             num_fragments = length = 0;
209             oscl_memset(buffer_states, 0, sizeof(buffer_states));
210             oscl_memset(fragments, 0, sizeof(fragments));
211         };
212 
213         BufFragStatusClass::status_t AddFragment(const BufferFragment& frag, BufferState* in_buffer_state,
214                 int32 location_offset = max_frags)
215         {
216             if (num_fragments > max_frags)
217             {
218                 return BufFragStatusClass::TOO_MANY_FRAGS;
219             }
220             if (frag.ptr == NULL)
221             {
222                 return BufFragStatusClass::EMPTY_FRAGMENT;
223             }
224 
225             if (location_offset >= 0 && location_offset < (int32) num_fragments)
226             {
227                 if (fragments[location_offset].ptr)
228                 {
229                     // make room for the new fragment
230                     oscl_memmove(fragments + location_offset + 1, fragments + location_offset,
231                                  (num_fragments - location_offset)*sizeof(BufferFragment));
232                     oscl_memmove(buffer_states + location_offset + 1, buffer_states + location_offset,
233                                  (num_fragments - location_offset)*sizeof(BufferState*));
234                     ++num_fragments; /* increment the number of fragments if a move
235                           * is necessary.  If the location was empty, then
236                           * has already been reserved and counted.
237                           */
238                 }
239                 fragments[location_offset] = frag;
240                 buffer_states[location_offset] = in_buffer_state;
241                 if (in_buffer_state) in_buffer_state->increment_refcnt();
242                 length += frag.len;
243                 return BufFragStatusClass::BFG_SUCCESS;
244             }
245 
246             // append the new fragment to the end
247             fragments[num_fragments] = frag;
248             buffer_states[num_fragments++] = in_buffer_state;
249             length += frag.len;
250             if (in_buffer_state) in_buffer_state->increment_refcnt();
251             return BufFragStatusClass::BFG_SUCCESS;
252         };
253 
254         BufferFragment fragments[max_frags];
255         BufferState* buffer_states[max_frags];
256         ChainClass* next;
257         uint32 num_fragments;
258         uint32 length;
259 };
260 
GetFragment(const int32 idx)261 template <class ChainClass, uint32 max_frags> inline BufferFragment *  BufFragGroup<ChainClass, max_frags> :: GetFragment(const int32 idx)
262 {
263     if (idx < (int)num_fragments && idx >= 0)
264     {
265         return & fragments[idx];
266     }
267     else
268     {
269         return NULL;
270     }
271 }
272 
GetBufferState(const int32 idx)273 template <class ChainClass, uint32 max_frags> inline BufferState *  BufFragGroup<ChainClass, max_frags> :: GetBufferState(const int32 idx)
274 {
275     if (idx < (int)num_fragments && idx >= 0)
276     {
277         return  buffer_states[idx];
278     }
279     else
280     {
281         return NULL;
282     }
283 }
284 
285 
286 template <class ChainClass, uint32 max_frags, uint32 local_bufsize> class MediaData :
287         public BufFragGroup<ChainClass, max_frags>
288 {
289 
290     public:
MediaData()291         MediaData(): timestamp(0), available_localbuf(local_bufsize), num_reserved_fragments(0) {};
292 
~MediaData()293         virtual ~MediaData() {}
294 
GetLocalBufsize()295         uint32 GetLocalBufsize() const
296         {
297             return local_bufsize;
298         };
GetTimestamp()299         MediaTimestamp GetTimestamp() const
300         {
301             return timestamp;
302         };
SetTimestamp(MediaTimestamp in_timestamp)303         void SetTimestamp(MediaTimestamp in_timestamp)
304         {
305             timestamp = in_timestamp;
306         };
GetAvailableBufferSize()307         uint32 GetAvailableBufferSize() const
308         {
309             return available_localbuf;
310         };
311 
312 
313 
314         // The input should be initialized so that the fragment length is the
315         // request size.  The returned value will have a non-NULL pointer if the
316         // request could be fulfilled.
GetLocalFragment(BufferFragment & fragment)317         MediaStatusClass::status_t GetLocalFragment(BufferFragment& fragment)
318         {
319             if (fragment.len > available_localbuf)
320             {
321                 fragment.ptr = NULL;
322                 fragment.len = available_localbuf;
323                 return MediaStatusClass::NOT_ENOUGH_SPACE;
324             }
325 
326             fragment.ptr = localbuf + (local_bufsize - available_localbuf);
327             available_localbuf -= fragment.len;
328             return MediaStatusClass::BFG_SUCCESS;
329         };
330 
Clear()331         virtual void Clear()
332         {
333             for (uint ii = 0 ; ii < this->num_fragments; ++ii)
334             {
335                 if (this->buffer_states[ii])
336                 {
337                     this->buffer_states[ii]->decrement_refcnt();
338                 }
339             }
340             this->num_fragments = 0;
341             this->length = 0;
342             oscl_memset(this->buffer_states, 0, sizeof(this->buffer_states));
343             oscl_memset(this->fragments, 0, sizeof(this->fragments));
344             this->available_localbuf = local_bufsize;
345         };
346 
347 
IsLocalData(const OsclMemoryFragment & frag)348         bool IsLocalData(const OsclMemoryFragment& frag) const
349         {
350             if (frag.ptr == NULL)
351                 return true;
352             if ((uint8 *)frag.ptr >= localbuf)
353             {
354                 if (((uint8 *)frag.ptr) + frag.len < localbuf + local_bufsize)
355                 {
356                     return true;
357                 }
358                 return false;
359             }
360             return false;
361         }
362 
GetMediaSize()363         int GetMediaSize() const
364         {
365             int num_reserved = 0;
366             for (int ii = 0; ii < num_reserved_fragments; ii++)
367                 num_reserved += this->fragments[ii].len;
368 
369             return (this->length - num_reserved);
370         }
371 
GetMediaFragment(const uint32 idx)372         BufferFragment * GetMediaFragment(const uint32 idx)
373         {
374             uint32 tmp = idx + this->num_reserved_fragments;
375             if (tmp > this->num_fragments)
376             {
377                 return NULL;
378             }
379             else
380             {
381                 return & this->fragments[tmp];
382             }
383         }
384 
GetNumMediaFrags(const uint32 idx)385         uint32 GetNumMediaFrags(const uint32 idx) const
386         {
387             if (this->num_fragments >= this->num_reserved_fragments)
388                 return this->num_fragments - this->num_reserved_fragments;
389             else return 0;
390         }
391 
392     protected:
393         // This function copies the fragment data to the local buffer
AddLocalFragment(const BufferFragment & frag,int32 location_offset)394         MediaStatusClass::status_t AddLocalFragment(const BufferFragment& frag,
395                 int32 location_offset)
396         {
397 
398             if (this->num_fragments > max_frags)
399             {
400                 return MediaStatusClass::TOO_MANY_FRAGS;
401             }
402 
403             if (frag.ptr == NULL || frag.len == 0)
404             {
405                 return MediaStatusClass::EMPTY_FRAGMENT;
406             }
407 
408             // see if there is enough room in the local buffer
409             if (frag.len > available_localbuf)
410             {
411                 return MediaStatusClass::NOT_ENOUGH_SPACE;
412             }
413 
414             // get the fragment
415             BufferFragment local_fragment;
416             local_fragment.len = frag.len;
417             local_fragment.ptr = localbuf + (local_bufsize - available_localbuf);
418             available_localbuf -= frag.len;
419             this->length += frag.len;
420 
421             oscl_memcpy(local_fragment.ptr, frag.ptr, frag.len*sizeof(uint8));
422 
423             if (location_offset >= 0 && location_offset < (int32) this->num_fragments)
424             {
425                 if (this->fragments[location_offset].ptr)
426                 {
427                     // make room for the new fragment
428                     oscl_memmove(this->fragments + location_offset + 1, this->fragments + location_offset,
429                                  (this->num_fragments - location_offset)*sizeof(BufferFragment));
430                     oscl_memmove(this->buffer_states + location_offset + 1, this->buffer_states + location_offset,
431                                  (this->num_fragments - location_offset)*sizeof(BufferState*));
432                     ++this->num_fragments; /* increment the number of fragments if a move
433                                 * is necessary.  If the location was empty, then
434                                 * has already been reserved and counted.
435                                 */
436                 }
437                 this->fragments[location_offset] = local_fragment;
438                 this->buffer_states[location_offset] = NULL;
439                 return MediaStatusClass::BFG_SUCCESS;
440             }
441 
442             // append the new fragment to the end
443             this->fragments[this->num_fragments] = local_fragment;
444             this->buffer_states[this->num_fragments++] = NULL;
445             return MediaStatusClass::BFG_SUCCESS;
446         };
447 
448         MediaTimestamp timestamp;
449         uint8 localbuf[local_bufsize];
450         uint32 available_localbuf;
451 
452         int num_reserved_fragments;
453 };
454 
455 #endif
456 
457 /*! @} */
458