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*/
33template<class Alloc>
34class 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*/
73template<class Port, class Alloc>
74class 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.
193enum 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*/
216template<class Alloc>
217class 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*/
438template<class Command, class Alloc>
439class 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