Home | History | Annotate | Download | only in src
      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