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

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 

OSCL API
Posting Version: OPENCORE_20090310