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