Home | History | Annotate | Download | only in include
      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 
     19 #ifndef PVMF_NODE_UTILS_H_INCLUDED
     20 #define PVMF_NODE_UTILS_H_INCLUDED
     21 
     22 #ifndef PVMF_NODE_INTERFACE_H_INCLUDED
     23 #include "pvmf_node_interface.h"
     24 #endif
     25 #ifndef OSCL_STRING_CONTAINERS_H_INCLUDED
     26 #include "oscl_string_containers.h"
     27 #endif
     28 
     29 /**
     30 //A basic implemention of PVInterface.  Interface implementations
     31 //can derive from this.
     32 */
     33 template<class Alloc>
     34 class PVInterfaceImpl
     35 {
     36     public:
     37         PVInterfaceImpl(const PVUuid& uuid)
     38                 : iRefCounter(1)
     39                 , iUuid(uuid)
     40         {}
     41         virtual ~PVInterfaceImpl()
     42         {}
     43         void removeRef()
     44         {
     45             --iRefCounter;
     46             if (iRefCounter <= 0)
     47             {
     48                 this->~PVInterfaceImpl();
     49                 Alloc alloc;
     50                 alloc.deallocate(this);
     51             }
     52         }
     53         void addRef()
     54         {
     55             iRefCounter++;
     56         }
     57         const PVUuid& Uuid()const
     58         {
     59             return iUuid;
     60         }
     61     private:
     62         int32 iRefCounter;
     63         PVUuid iUuid;
     64 };
     65 
     66 
     67 /**
     68 //A vector for holding port pointers, with a built-in port iterator.
     69 //This vector automatically calls the port destructor when pointers are
     70 //removed from the vector.
     71 //Node implementations can use this to manage multiple ports.
     72 */
     73 template<class Port, class Alloc>
     74 class PVMFPortVector: public PVMFPortIter
     75 {
     76     public:
     77         typedef Port vec_element_deref;
     78         typedef Port* vec_element;
     79         typedef vec_element* vec_element_ptr;
     80 
     81         virtual ~PVMFPortVector()
     82         {
     83             while (iVec.size() > 0)
     84                 Erase(&front());
     85         }
     86         void Construct(uint32 nres)
     87         {//construct the vector
     88             iIterIndex = 0;
     89             iVec.reserve(nres);
     90             iNres = nres;
     91         }
     92         void Erase(vec_element_ptr elem)
     93         {//erase an element
     94             if (elem)
     95             {   //must explicitly call port destructor, since
     96                 //vec elements are pointers.
     97                 Oscl_TAlloc<vec_element_deref, Alloc> talloc;
     98                 talloc.destruct_and_dealloc(*elem);
     99                 iVec.erase(elem);
    100             }
    101         }
    102         void Reconstruct()
    103         {//erase all elements & reconstruct the vector.
    104             for (uint32 i = 0; i < iVec.size(); i++)
    105                 Erase(&iVec[i]);
    106             iVec.clear();
    107             iVec.reserve(iNres);
    108         }
    109 
    110         OsclAny* Allocate()
    111         {//allocate space for a port.
    112             Alloc alloc;
    113             return alloc.ALLOCATE(sizeof(Port));
    114         }
    115         void DestructAndDealloc(Port* port)
    116         {//Cleanup a port using the allocator.  For use only
    117             //on port pointers that aren't yet in the vector.
    118             Oscl_TAlloc<Port, Alloc> talloc;
    119             talloc.destruct_and_dealloc(port);
    120         }
    121 
    122         void AddL(vec_element &elem)
    123         {//add an element to the end.
    124             iVec.push_back(elem);
    125         }
    126 
    127         void InsertL(vec_element &elem)
    128         {//add an element to the front
    129             iVec.push_front(elem);
    130         }
    131 
    132         vec_element_ptr FindByValue(vec_element &elem)
    133         {//find an element by its value
    134             for (uint32 i = 0; i < iVec.size(); i++)
    135                 if (iVec[i] == elem)
    136                     return &iVec[i];
    137             return NULL;
    138         }
    139 
    140         //From PVMFPortIter
    141         uint16 NumPorts()
    142         {
    143             return (uint16)iVec.size();
    144         }
    145         PVMFPortInterface* GetNext()
    146         {
    147             if (iVec.size() > iIterIndex)
    148                 return iVec[iIterIndex++];
    149             return NULL;
    150         }
    151         void Reset()
    152         {
    153             iIterIndex = 0;
    154         }
    155 
    156         //wrappers for methods from Oscl_Vector
    157         vec_element& operator[](uint32 n)
    158         {
    159             return iVec[n];
    160         }
    161         const vec_element& operator[](uint32 n) const
    162         {
    163             return iVec[n];
    164         }
    165         uint32 size()const
    166         {
    167             return iVec.size();
    168         }
    169         void clear()
    170         {
    171             iVec.clear();
    172         }
    173         vec_element& front()
    174         {
    175             return iVec.front();
    176         }
    177         bool empty()const
    178         {
    179             return iVec.empty();
    180         }
    181 
    182     private:
    183         Oscl_Vector<vec_element, Alloc> iVec;
    184         uint32 iNres;
    185         uint32 iIterIndex;
    186 };
    187 
    188 /**
    189 // Node Command queue utilities.
    190 */
    191 
    192 //IDs for all of the asynchronous node commands.
    193 enum TPVMFGenericNodeCommand
    194 {
    195     PVMF_GENERIC_NODE_QUERYUUID
    196     , PVMF_GENERIC_NODE_QUERYINTERFACE
    197     , PVMF_GENERIC_NODE_REQUESTPORT
    198     , PVMF_GENERIC_NODE_RELEASEPORT
    199     , PVMF_GENERIC_NODE_INIT
    200     , PVMF_GENERIC_NODE_PREPARE
    201     , PVMF_GENERIC_NODE_START
    202     , PVMF_GENERIC_NODE_STOP
    203     , PVMF_GENERIC_NODE_FLUSH
    204     , PVMF_GENERIC_NODE_PAUSE
    205     , PVMF_GENERIC_NODE_RESET
    206     , PVMF_GENERIC_NODE_CANCELALLCOMMANDS
    207     , PVMF_GENERIC_NODE_CANCELCOMMAND
    208     , PVMF_GENERIC_NODE_COMMAND_LAST //a placeholder for adding
    209     //node-specific commands to this list.
    210 };
    211 
    212 /**
    213 //A node command class with constructors and destructors
    214 //for all of the generic asynchronous node commands.
    215 */
    216 template<class Alloc>
    217 class PVMFGenericNodeCommand
    218 {
    219     public:
    220         virtual ~PVMFGenericNodeCommand() {}
    221 
    222         //base construction for all commands.  derived class can override this
    223         //to add initialization of other parameters.
    224         virtual void BaseConstruct(PVMFSessionId s, int32 aCmd, const OsclAny* aContext)
    225         {
    226             iSession = s;
    227             iCmd = aCmd;
    228             iContext = aContext;
    229             iParam1 = NULL;
    230             iParam2 = NULL;
    231             iParam3 = NULL;
    232             iParam4 = NULL;
    233             iParam5 = NULL;
    234         }
    235 
    236         //for Init, Start, Stop, Pause and other commands.
    237         void Construct(PVMFSessionId s, int32 aCmd, const OsclAny* aContext)
    238         {
    239             BaseConstruct(s, aCmd, aContext);
    240         }
    241 
    242         //for CancelCommand
    243         void Construct(PVMFSessionId s, int32 aCmd, int32 aTag, const OsclAny* aContext)
    244         {
    245             BaseConstruct(s, aCmd, aContext);
    246             iParam1 = (OsclAny*)aTag;
    247         }
    248         void Parse(int32&aTag)
    249         {
    250             aTag = (int32)iParam1;
    251         }
    252 
    253         //for ReleasePort
    254         void Construct(PVMFSessionId s, int32 aCmd, PVMFPortInterface& aPort, const OsclAny* aContext)
    255         {
    256             BaseConstruct(s, aCmd, aContext);
    257             iParam1 = (OsclAny*) & aPort;
    258         }
    259         void Parse(PVMFPortInterface*&aPort)
    260         {
    261             aPort = (PVMFPortInterface*)iParam1;
    262         }
    263 
    264         //for QueryInterface
    265         void Construct(PVMFSessionId s, int32 aCmd, const PVUuid& aUuid,
    266                        PVInterface*& aInterfacePtr,
    267                        const OsclAny* aContext)
    268         {
    269             BaseConstruct(s, aCmd, aContext);
    270             //if input cmd id isn't as expected, memory won't get
    271             //cleaned up later, so assert here.
    272             OSCL_ASSERT(aCmd == PVMF_GENERIC_NODE_QUERYINTERFACE);
    273             //allocate a copy of the Uuid.
    274             Oscl_TAlloc<PVUuid, Alloc>uuid;
    275             iParam1 = uuid.ALLOC_AND_CONSTRUCT(aUuid);
    276             iParam2 = (OsclAny*) & aInterfacePtr;
    277         }
    278         void Parse(PVUuid*&aUuid, PVInterface**&aInterface)
    279         {
    280             aUuid = (PVUuid*)iParam1;
    281             aInterface = (PVInterface**)iParam2;
    282         }
    283 
    284         //for QueryUuids
    285         void Construct(PVMFSessionId s, int32 aCmd, const PvmfMimeString& aMimeType,
    286                        Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    287                        bool aExactUuidsOnly,
    288                        const OsclAny* aContext)
    289         {
    290             BaseConstruct(s, aCmd, aContext);
    291             //if input cmd id isn't as expected, memory won't get
    292             //cleaned up later, so assert here.
    293             OSCL_ASSERT(aCmd == PVMF_GENERIC_NODE_QUERYUUID);
    294             //allocate a copy of the mime type string.
    295             Oscl_TAlloc<OSCL_HeapString<Alloc>, Alloc> mimetype;
    296             iParam1 = mimetype.ALLOC_AND_CONSTRUCT(aMimeType);
    297             iParam2 = (OsclAny*) & aUuids;
    298             iParam3 = (OsclAny*)aExactUuidsOnly;
    299         }
    300         void Parse(OSCL_String*&aMimetype, Oscl_Vector<PVUuid, OsclMemAllocator>*&aUuids, bool &aExact)
    301         {
    302             aMimetype = (OSCL_HeapString<Alloc>*)iParam1;
    303             aUuids = (Oscl_Vector<PVUuid, OsclMemAllocator>*)iParam2;
    304             aExact = (iParam3) ? true : false;
    305         }
    306 
    307         //for RequestPort
    308         void Construct(PVMFSessionId s, int32 aCmd
    309                        , int32 aPortTag
    310                        , const PvmfMimeString* aMimeType
    311                        , const OsclAny* aContext)
    312         {
    313             BaseConstruct(s, aCmd, aContext);
    314             iParam1 = (OsclAny*)aPortTag;
    315             //if input cmd id isn't as expected, memory won't get
    316             //cleaned up later, so assert here.
    317             OSCL_ASSERT(aCmd == PVMF_GENERIC_NODE_REQUESTPORT);
    318             //allocate a copy of the mime type string.
    319             if (aMimeType)
    320             {
    321                 Oscl_TAlloc<OSCL_HeapString<Alloc>, Alloc> mimetype;
    322                 iParam2 = mimetype.ALLOC_AND_CONSTRUCT(*aMimeType);
    323             }
    324         }
    325         void Parse(int32&aPortTag, OSCL_String*&aMimetype)
    326         {
    327             aPortTag = (int32)iParam1;
    328             aMimetype = (OSCL_HeapString<Alloc>*)iParam2;
    329         }
    330 
    331         //cleanup routine.  Derived class can override this to cleanup additional
    332         //allocated memory.
    333         virtual void Destroy()
    334         {
    335             switch (iCmd)
    336             {
    337                 case PVMF_GENERIC_NODE_QUERYUUID:
    338                 {//destroy the allocated mimetype string
    339                     Oscl_TAlloc<OSCL_HeapString<Alloc>, Alloc> mimetype;
    340                     mimetype.destruct_and_dealloc(iParam1);
    341                 }
    342                 break;
    343                 case PVMF_GENERIC_NODE_REQUESTPORT:
    344                 {//destroy the allocated mimetype string
    345                     if (iParam2)
    346                     {
    347                         Oscl_TAlloc<OSCL_HeapString<Alloc>, Alloc> mimetype;
    348                         mimetype.destruct_and_dealloc(iParam2);
    349                     }
    350                 }
    351                 break;
    352                 case PVMF_GENERIC_NODE_QUERYINTERFACE:
    353                 {//destroy the allocated uuid
    354                     Oscl_TAlloc<PVUuid, Alloc>uuid;
    355                     uuid.destruct_and_dealloc(iParam1);
    356                 }
    357                 break;
    358                 default:
    359                     break;
    360             }
    361         }
    362 
    363         //command copy.  derived class can override this to allocate
    364         //any additional parameters.
    365         virtual void Copy(const PVMFGenericNodeCommand<Alloc>& aCmd)
    366         {
    367             iId = aCmd.iId;
    368             iSession = aCmd.iSession;
    369             iContext = aCmd.iContext;
    370             iParam1 = aCmd.iParam1;
    371             iParam2 = aCmd.iParam2;
    372             iParam3 = aCmd.iParam3;
    373             iParam4 = aCmd.iParam4;
    374             iParam5 = aCmd.iParam5;
    375             iCmd = aCmd.iCmd;
    376             switch (aCmd.iCmd)
    377             {
    378                 case PVMF_GENERIC_NODE_QUERYUUID:
    379                 {//copy the allocated mimetype string
    380                     OSCL_HeapString<Alloc>* aMimetype = (OSCL_HeapString<Alloc>*)aCmd.iParam1;
    381                     Oscl_TAlloc<OSCL_HeapString<Alloc>, Alloc> mimetype;
    382                     iParam1 = mimetype.ALLOC_AND_CONSTRUCT(*aMimetype);
    383                 }
    384                 break;
    385                 case PVMF_GENERIC_NODE_REQUESTPORT:
    386                 {//copy the allocated mimetype string
    387                     OSCL_HeapString<Alloc>* aMimetype = (OSCL_HeapString<Alloc>*)aCmd.iParam2;
    388                     if (aMimetype)
    389                     {
    390                         Oscl_TAlloc<OSCL_HeapString<Alloc>, Alloc> mimetype;
    391                         iParam2 = mimetype.ALLOC_AND_CONSTRUCT(*aMimetype);
    392                     }
    393                 }
    394                 break;
    395                 case PVMF_GENERIC_NODE_QUERYINTERFACE:
    396                 {//copy the allocated uuid
    397                     PVUuid* aUuid = (PVUuid*)aCmd.iParam1;
    398                     Oscl_TAlloc<PVUuid, Alloc>uuid;
    399                     iParam1 = uuid.ALLOC_AND_CONSTRUCT(*aUuid);
    400                 }
    401                 break;
    402                 default:
    403                     break;
    404             }
    405         }
    406 
    407         //this routine identifies commands that need to
    408         //go at the front of the queue.  derived command
    409         //classes can override it if needed.
    410         virtual bool hipri()
    411         {
    412             return (iCmd == PVMF_GENERIC_NODE_CANCELALLCOMMANDS
    413                     || iCmd == PVMF_GENERIC_NODE_CANCELCOMMAND);
    414         }
    415 
    416         //allocate space for a command using the class allocator.
    417         static OsclAny* Allocate()
    418         {
    419             Alloc alloc;
    420             return alloc.ALLOCATE(sizeof(PVMFGenericNodeCommand));
    421         }
    422 
    423         //command parameters.
    424         PVMFCommandId iId;
    425         PVMFSessionId iSession;
    426         const OsclAny *iContext;
    427         OsclAny* iParam1;
    428         OsclAny* iParam2;
    429         OsclAny* iParam3;
    430         OsclAny* iParam4;
    431         OsclAny* iParam5;
    432         int32 iCmd;
    433 };
    434 
    435 /**
    436 //A command queue with a built-in command ID generator.
    437 */
    438 template<class Command, class Alloc>
    439 class PVMFNodeCommandQueue
    440 {
    441     public:
    442         typedef Command vec_element;
    443         typedef vec_element* vec_element_ptr;
    444 
    445         PVMFNodeCommandQueue()
    446         {
    447             iCommandCounter = 0;
    448         }
    449 
    450         //note: usage of the class requires calling the Construct function
    451         void Construct(int32 init, uint32 nres)
    452         {//construct the vector
    453             iCommandCounter = init;
    454             iVec.reserve(nres);
    455         }
    456 
    457         ~PVMFNodeCommandQueue()
    458         {
    459             while (!empty())
    460             {//must explicitly destroy all elements.
    461                 Erase(&iVec[0]);
    462             }
    463         }
    464 
    465         void Erase(vec_element_ptr elem)
    466         {//erase an element
    467             elem->Destroy();
    468             iVec.erase(elem);
    469         }
    470 
    471         int32 AddL(vec_element &elem)
    472         {//add an element with a new ID
    473             elem.iId = iCommandCounter++;
    474             if (elem.hipri())
    475                 iVec.push_front(elem);
    476             else
    477                 iVec.push_back(elem);
    478             return elem.iId;
    479         }
    480 
    481         vec_element_ptr StoreL(vec_element &elem)
    482         {//store a copy of an element
    483             vec_element newelem;
    484             newelem.Copy(elem);
    485             if (newelem.hipri())
    486             {
    487                 iVec.push_front(newelem);
    488                 return &iVec[0];
    489             }
    490             else
    491             {
    492                 iVec.push_back(newelem);
    493                 return &iVec[iVec.size()-1];
    494             }
    495         }
    496 
    497         vec_element_ptr FindById(PVMFCommandId aId, uint32 aOffset = 0)
    498         {//find an element by its command id
    499             for (uint32 i = aOffset; i < iVec.size(); i++)
    500                 if (iVec[i].iId == aId)
    501                     return &iVec[i];
    502             return NULL;
    503         }
    504 
    505         //Wrappers for methods from Oscl_Vector
    506         vec_element& operator[](uint32 n)
    507         {
    508             return iVec[n];
    509         }
    510         const vec_element& operator[](uint32 n) const
    511         {
    512             return iVec[n];
    513         }
    514         uint32 size()const
    515         {
    516             return iVec.size();
    517         }
    518         void clear()
    519         {
    520             iVec.clear();
    521         }
    522         vec_element& front()
    523         {
    524             return iVec.front();
    525         }
    526         bool empty()const
    527         {
    528             return iVec.empty();
    529         }
    530 
    531     private:
    532         Oscl_Vector<vec_element, Alloc> iVec;
    533         int32 iCommandCounter;
    534 };
    535 
    536 
    537 
    538 
    539 #endif
    540 
    541 
    542