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; 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; 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 83 void increment_refcnt() 84 { 85 ++refcount; 86 }; 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 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 }; 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 112 void *get_ptr() 113 { 114 return ptr; 115 }; 116 int32 get_refcount() 117 { 118 return refcount; 119 }; 120 121 BufferFreeFuncPtr get_free_function() 122 { 123 return free_function; 124 }; 125 BufferMgr* get_buf_mgr() 126 { 127 return buf_mgr; 128 }; 129 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 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 161 virtual ~BufFragGroup() {} 162 163 int32 GetMaxFrags() const 164 { 165 return max_frags; 166 }; 167 int32 GetNumFrags() const 168 { 169 return num_fragments; 170 }; 171 uint32 GetLength() const 172 { 173 return length; 174 }; 175 176 BufferFragment * GetFragment(const int32 idx); 177 178 BufferState * GetBufferState(const int32 idx); 179 180 void AppendNext(ChainClass* next_ptr) 181 { 182 next = next_ptr; 183 }; 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 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 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 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: 291 MediaData(): timestamp(0), available_localbuf(local_bufsize), num_reserved_fragments(0) {}; 292 293 virtual ~MediaData() {} 294 295 uint32 GetLocalBufsize() const 296 { 297 return local_bufsize; 298 }; 299 MediaTimestamp GetTimestamp() const 300 { 301 return timestamp; 302 }; 303 void SetTimestamp(MediaTimestamp in_timestamp) 304 { 305 timestamp = in_timestamp; 306 }; 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. 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 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 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 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 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 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 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