Main Page Modules Class Hierarchy Data Structures File List Data Fields Globals Related Pages

# oscl_media_data.h

Go to the documentation of this file.

    00001 // -*- c++ -*-
    00002 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    00003
    00004 //               O S C L _ M E D I A _ D A T A
    00005
    00006 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    00007
    00018 #ifndef OSCL_MEDIA_DATA_H
    00019 #define OSCL_MEDIA_DATA_H
    00020
    00021 #ifndef OSCL_BASE_H_INCLUDED
    00022 #include "oscl_base.h"
    00023 #endif
    00024
    00025 #ifndef OSCL_MEM_BASIC_FUNCTIONS_H_INCLUDED
    00026 #include "oscl_mem_basic_functions.h"
    00027 #endif
    00028
    00029 #ifndef OSCL_MEDIA_STATUS_H_INCLUDED
    00030 #include "oscl_media_status.h"
    00031 #endif
    00032
    00033 typedef void (*BufferFreeFuncPtr)(void *);
    00034
    00035 typedef uint32 MediaTimestamp;
    00036
    00037 template <class T> class MemAllocator
    00038 {
    00039     public:
    00040         typedef T* pointer;
    00041         //  virtual pointer allocate(size_t size, void *hint = 0) = 0;
    00042         virtual pointer allocate(void * hint = 0, const int num_reserved_frags = 1) = 0;
    00043         virtual void deallocate(pointer p) = 0;
    00044         virtual ~MemAllocator() {}
    00045 };
    00046
    00047 class BufferState;
    00048 /* Buffer referee (how about the "whistle blower" ?*/
    00049 class BufferMgr
    00050 {
    00051     public:
    00052         virtual void BufferReleased(void* ptr, BufferState* state = NULL) = 0;
    00053         virtual ~BufferMgr() {}
    00054 };
    00055
    00056
    00057 class BufferState
    00058 {
    00059     public:
    00060         BufferState(BufferFreeFuncPtr the_free_function, void *bufptr = 0) :
    00061                 refcount(0), ptr(bufptr), free_function(the_free_function), buf_mgr(0) {};
    00062
    00063         BufferState(BufferMgr* the_buf_mgr = 0, void *bufptr = 0) :
    00064                 refcount(0), ptr(bufptr), free_function(0), buf_mgr(the_buf_mgr) {};
    00065
    00066         void increment_refcnt()
    00067         {
    00068             ++refcount;
    00069         };
    00070         void decrement_refcnt()
    00071         {
    00072             if (!(--refcount))
    00073             {
    00074                 if (buf_mgr) buf_mgr->BufferReleased(ptr, this);
    00075                 else if (free_function)
    00076                 {
    00077                     free_function(ptr);
    00078                     ptr = 0;
    00079                 }
    00080             }
    00081         };
    00082
    00083         void bind(void *in_ptr, BufferFreeFuncPtr in_free_function)
    00084         {
    00085             refcount = 0;
    00086             ptr = in_ptr, free_function = in_free_function;
    00087
    00088         };
    00089         void bind(void *in_ptr, BufferMgr* in_buf_mgr)
    00090         {
    00091             refcount = 0;
    00092             ptr = in_ptr, buf_mgr = in_buf_mgr;
    00093         };
    00094
    00095         void *get_ptr()
    00096         {
    00097             return ptr;
    00098         };
    00099         int32 get_refcount()
    00100         {
    00101             return refcount;
    00102         };
    00103
    00104         BufferFreeFuncPtr get_free_function()
    00105         {
    00106             return free_function;
    00107         };
    00108         BufferMgr* get_buf_mgr()
    00109         {
    00110             return buf_mgr;
    00111         };
    00112
    00113         void reset()
    00114         {
    00115             refcount = 0;
    00116             ptr = 0;
    00117         };
    00118
    00119     private:
    00120         int32 refcount;
    00121         void *ptr;
    00122         BufferFreeFuncPtr free_function; // called to free the buffer
    00123         BufferMgr* buf_mgr; // called to free the buffer
    00124 };
    00125
    00126
    00127 // BufferFragment is a special case of a memory
    00128 // fragment since it refers to fragments of a reference
    00129 // counted memory.  The name is used to make this explicit.
    00130 class BufferFragment : public OsclMemoryFragment {};
    00131
    00132
    00133 template <class ChainClass, uint32 max_frags> class BufFragGroup
    00134 {
    00135     public:
    00136
    00137
    00138         BufFragGroup(): next(0), num_fragments(0), length(0)
    00139         {
    00140             oscl_memset(fragments, 0, sizeof(fragments));
    00141             oscl_memset(buffer_states, 0, sizeof(buffer_states));
    00142         };
    00143
    00144         virtual ~BufFragGroup() {}
    00145
    00146         int32 GetMaxFrags() const
    00147         {
    00148             return max_frags;
    00149         };
    00150         int32 GetNumFrags() const
    00151         {
    00152             return num_fragments;
    00153         };
    00154         uint32 GetLength() const
    00155         {
    00156             return length;
    00157         };
    00158
    00159         BufferFragment * GetFragment(const int32 idx);
    00160
    00161         BufferState * GetBufferState(const int32 idx);
    00162
    00163         void AppendNext(ChainClass* next_ptr)
    00164         {
    00165             next = next_ptr;
    00166         };
    00167         ChainClass* GetNext() const
    00168         {
    00169             return next;
    00170         };
    00171
    00172         // make fragment array accessible to allow usage within socket
    00173         // send functions.
    00174
    00175     protected:
    00176
    00177
    00178         // BufferFragment * GetFragment(const uint32 idx) const;
    00179
    00180
    00181
    00182         virtual void Clear()
    00183         {
    00184             for (uint ii = 0 ; ii < num_fragments; ++ii)
    00185             {
    00186                 if (buffer_states[ii])
    00187                 {
    00188                     buffer_states[ii]->decrement_refcnt();
    00189                 }
    00190             }
    00191             num_fragments = length = 0;
    00192             oscl_memset(buffer_states, 0, sizeof(buffer_states));
    00193             oscl_memset(fragments, 0, sizeof(fragments));
    00194         };
    00195
    00196         BufFragStatusClass::status_t AddFragment(const BufferFragment& frag, BufferState* in_buffer_state,
    00197                 int32 location_offset = max_frags)
    00198         {
    00199             if (num_fragments > max_frags)
    00200             {
    00201                 return BufFragStatusClass::TOO_MANY_FRAGS;
    00202             }
    00203             if (frag.ptr == NULL)
    00204             {
    00205                 return BufFragStatusClass::EMPTY_FRAGMENT;
    00206             }
    00207
    00208             if (location_offset >= 0 && location_offset < (int32) num_fragments)
    00209             {
    00210                 if (fragments[location_offset].ptr)
    00211                 {
    00212                     // make room for the new fragment
    00213                     oscl_memmove(fragments + location_offset + 1, fragments + location_offset,
    00214                                  (num_fragments - location_offset)*sizeof(BufferFragment));
    00215                     oscl_memmove(buffer_states + location_offset + 1, buffer_states + location_offset,
    00216                                  (num_fragments - location_offset)*sizeof(BufferState*));
    00217                     ++num_fragments; /* increment the number of fragments if a move
    00218                           * is necessary.  If the location was empty, then
    00219                           * has already been reserved and counted.
    00220                           */
    00221                 }
    00222                 fragments[location_offset] = frag;
    00223                 buffer_states[location_offset] = in_buffer_state;
    00224                 if (in_buffer_state) in_buffer_state->increment_refcnt();
    00225                 length += frag.len;
    00226                 return BufFragStatusClass::BFG_SUCCESS;
    00227             }
    00228
    00229             // append the new fragment to the end
    00230             fragments[num_fragments] = frag;
    00231             buffer_states[num_fragments++] = in_buffer_state;
    00232             length += frag.len;
    00233             if (in_buffer_state) in_buffer_state->increment_refcnt();
    00234             return BufFragStatusClass::BFG_SUCCESS;
    00235         };
    00236
    00237         BufferFragment fragments[max_frags];
    00238         BufferState* buffer_states[max_frags];
    00239         ChainClass* next;
    00240         uint32 num_fragments;
    00241         uint32 length;
    00242 };
    00243
    00244 template <class ChainClass, uint32 max_frags> inline BufferFragment *  BufFragGroup<ChainClass, max_frags> :: GetFragment(const int32 idx)
    00245 {
    00246     if (idx < (int)num_fragments && idx >= 0)
    00247     {
    00248         return & fragments[idx];
    00249     }
    00250     else
    00251     {
    00252         return NULL;
    00253     }
    00254 }
    00255
    00256 template <class ChainClass, uint32 max_frags> inline BufferState *  BufFragGroup<ChainClass, max_frags> :: GetBufferState(const int32 idx)
    00257 {
    00258     if (idx < (int)num_fragments && idx >= 0)
    00259     {
    00260         return  buffer_states[idx];
    00261     }
    00262     else
    00263     {
    00264         return NULL;
    00265     }
    00266 }
    00267
    00268
    00269 template <class ChainClass, uint32 max_frags, uint32 local_bufsize> class MediaData :
    00270         public BufFragGroup<ChainClass, max_frags>
    00271 {
    00272
    00273     public:
    00274         MediaData(): timestamp(0), available_localbuf(local_bufsize), num_reserved_fragments(0) {};
    00275
    00276         virtual ~MediaData() {}
    00277
    00278         uint32 GetLocalBufsize() const
    00279         {
    00280             return local_bufsize;
    00281         };
    00282         MediaTimestamp GetTimestamp() const
    00283         {
    00284             return timestamp;
    00285         };
    00286         void SetTimestamp(MediaTimestamp in_timestamp)
    00287         {
    00288             timestamp = in_timestamp;
    00289         };
    00290         uint32 GetAvailableBufferSize() const
    00291         {
    00292             return available_localbuf;
    00293         };
    00294
    00295
    00296
    00297         // The input should be initialized so that the fragment length is the
    00298         // request size.  The returned value will have a non-NULL pointer if the
    00299         // request could be fulfilled.
    00300         MediaStatusClass::status_t GetLocalFragment(BufferFragment& fragment)
    00301         {
    00302             if (fragment.len > available_localbuf)
    00303             {
    00304                 fragment.ptr = NULL;
    00305                 fragment.len = available_localbuf;
    00306                 return MediaStatusClass::NOT_ENOUGH_SPACE;
    00307             }
    00308
    00309             fragment.ptr = localbuf + (local_bufsize - available_localbuf);
    00310             available_localbuf -= fragment.len;
    00311             return MediaStatusClass::BFG_SUCCESS;
    00312         };
    00313
    00314         virtual void Clear()
    00315         {
    00316             for (uint ii = 0 ; ii < this->num_fragments; ++ii)
    00317             {
    00318                 if (this->buffer_states[ii])
    00319                 {
    00320                     this->buffer_states[ii]->decrement_refcnt();
    00321                 }
    00322             }
    00323             this->num_fragments = 0;
    00324             this->length = 0;
    00325             oscl_memset(this->buffer_states, 0, sizeof(this->buffer_states));
    00326             oscl_memset(this->fragments, 0, sizeof(this->fragments));
    00327             this->available_localbuf = local_bufsize;
    00328         };
    00329
    00330
    00331         bool IsLocalData(const OsclMemoryFragment& frag) const
    00332         {
    00333             if (frag.ptr == NULL)
    00334                 return true;
    00335             if ((uint8 *)frag.ptr >= localbuf)
    00336             {
    00337                 if (((uint8 *)frag.ptr) + frag.len < localbuf + local_bufsize)
    00338                 {
    00339                     return true;
    00340                 }
    00341                 return false;
    00342             }
    00343             return false;
    00344         }
    00345
    00346         int GetMediaSize() const
    00347         {
    00348             int num_reserved = 0;
    00349             for (int ii = 0; ii < num_reserved_fragments; ii++)
    00350                 num_reserved += this->fragments[ii].len;
    00351
    00352             return (this->length - num_reserved);
    00353         }
    00354
    00355         BufferFragment * GetMediaFragment(const uint32 idx)
    00356         {
    00357             uint32 tmp = idx + this->num_reserved_fragments;
    00358             if (tmp > this->num_fragments)
    00359             {
    00360                 return NULL;
    00361             }
    00362             else
    00363             {
    00364                 return & this->fragments[tmp];
    00365             }
    00366         }
    00367
    00368         uint32 GetNumMediaFrags(const uint32 idx) const
    00369         {
    00370             if (this->num_fragments >= this->num_reserved_fragments)
    00371                 return this->num_fragments - this->num_reserved_fragments;
    00372             else return 0;
    00373         }
    00374
    00375     protected:
    00376         // This function copies the fragment data to the local buffer
    00377         MediaStatusClass::status_t AddLocalFragment(const BufferFragment& frag,
    00378                 int32 location_offset)
    00379         {
    00380
    00381             if (this->num_fragments > max_frags)
    00382             {
    00383                 return MediaStatusClass::TOO_MANY_FRAGS;
    00384             }
    00385
    00386             if (frag.ptr == NULL || frag.len == 0)
    00387             {
    00388                 return MediaStatusClass::EMPTY_FRAGMENT;
    00389             }
    00390
    00391             // see if there is enough room in the local buffer
    00392             if (frag.len > available_localbuf)
    00393             {
    00394                 return MediaStatusClass::NOT_ENOUGH_SPACE;
    00395             }
    00396
    00397             // get the fragment
    00398             BufferFragment local_fragment;
    00399             local_fragment.len = frag.len;
    00400             local_fragment.ptr = localbuf + (local_bufsize - available_localbuf);
    00401             available_localbuf -= frag.len;
    00402             this->length += frag.len;
    00403
    00404             oscl_memcpy(local_fragment.ptr, frag.ptr, frag.len*sizeof(uint8));
    00405
    00406             if (location_offset >= 0 && location_offset < (int32) this->num_fragments)
    00407             {
    00408                 if (this->fragments[location_offset].ptr)
    00409                 {
    00410                     // make room for the new fragment
    00411                     oscl_memmove(this->fragments + location_offset + 1, this->fragments + location_offset,
    00412                                  (this->num_fragments - location_offset)*sizeof(BufferFragment));
    00413                     oscl_memmove(this->buffer_states + location_offset + 1, this->buffer_states + location_offset,
    00414                                  (this->num_fragments - location_offset)*sizeof(BufferState*));
    00415                     ++this->num_fragments; /* increment the number of fragments if a move
    00416                                 * is necessary.  If the location was empty, then
    00417                                 * has already been reserved and counted.
    00418                                 */
    00419                 }
    00420                 this->fragments[location_offset] = local_fragment;
    00421                 this->buffer_states[location_offset] = NULL;
    00422                 return MediaStatusClass::BFG_SUCCESS;
    00423             }
    00424
    00425             // append the new fragment to the end
    00426             this->fragments[this->num_fragments] = local_fragment;
    00427             this->buffer_states[this->num_fragments++] = NULL;
    00428             return MediaStatusClass::BFG_SUCCESS;
    00429         };
    00430
    00431         MediaTimestamp timestamp;
    00432         uint8 localbuf[local_bufsize];
    00433         uint32 available_localbuf;
    00434
    00435         int num_reserved_fragments;
    00436 };
    00437
    00438 #endif
    00439