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: PVInterfaceImpl(const PVUuid & uuid)37 PVInterfaceImpl(const PVUuid& uuid) 38 : iRefCounter(1) 39 , iUuid(uuid) 40 {} ~PVInterfaceImpl()41 virtual ~PVInterfaceImpl() 42 {} removeRef()43 void removeRef() 44 { 45 --iRefCounter; 46 if (iRefCounter <= 0) 47 { 48 this->~PVInterfaceImpl(); 49 Alloc alloc; 50 alloc.deallocate(this); 51 } 52 } addRef()53 void addRef() 54 { 55 iRefCounter++; 56 } Uuid()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 ~PVMFPortVector()81 virtual ~PVMFPortVector() 82 { 83 while (iVec.size() > 0) 84 Erase(&front()); 85 } Construct(uint32 nres)86 void Construct(uint32 nres) 87 {//construct the vector 88 iIterIndex = 0; 89 iVec.reserve(nres); 90 iNres = nres; 91 } Erase(vec_element_ptr elem)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 } Reconstruct()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 Allocate()110 OsclAny* Allocate() 111 {//allocate space for a port. 112 Alloc alloc; 113 return alloc.ALLOCATE(sizeof(Port)); 114 } DestructAndDealloc(Port * port)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 AddL(vec_element & elem)122 void AddL(vec_element &elem) 123 {//add an element to the end. 124 iVec.push_back(elem); 125 } 126 InsertL(vec_element & elem)127 void InsertL(vec_element &elem) 128 {//add an element to the front 129 iVec.push_front(elem); 130 } 131 FindByValue(vec_element & elem)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 NumPorts()141 uint16 NumPorts() 142 { 143 return (uint16)iVec.size(); 144 } GetNext()145 PVMFPortInterface* GetNext() 146 { 147 if (iVec.size() > iIterIndex) 148 return iVec[iIterIndex++]; 149 return NULL; 150 } Reset()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 } size()165 uint32 size()const 166 { 167 return iVec.size(); 168 } clear()169 void clear() 170 { 171 iVec.clear(); 172 } front()173 vec_element& front() 174 { 175 return iVec.front(); 176 } empty()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: ~PVMFGenericNodeCommand()220 virtual ~PVMFGenericNodeCommand() {} 221 222 //base construction for all commands. derived class can override this 223 //to add initialization of other parameters. BaseConstruct(PVMFSessionId s,int32 aCmd,const OsclAny * aContext)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. Construct(PVMFSessionId s,int32 aCmd,const OsclAny * aContext)237 void Construct(PVMFSessionId s, int32 aCmd, const OsclAny* aContext) 238 { 239 BaseConstruct(s, aCmd, aContext); 240 } 241 242 //for CancelCommand Construct(PVMFSessionId s,int32 aCmd,int32 aTag,const OsclAny * aContext)243 void Construct(PVMFSessionId s, int32 aCmd, int32 aTag, const OsclAny* aContext) 244 { 245 BaseConstruct(s, aCmd, aContext); 246 iParam1 = (OsclAny*)aTag; 247 } Parse(int32 & aTag)248 void Parse(int32&aTag) 249 { 250 aTag = (int32)iParam1; 251 } 252 253 //for ReleasePort Construct(PVMFSessionId s,int32 aCmd,PVMFPortInterface & aPort,const OsclAny * aContext)254 void Construct(PVMFSessionId s, int32 aCmd, PVMFPortInterface& aPort, const OsclAny* aContext) 255 { 256 BaseConstruct(s, aCmd, aContext); 257 iParam1 = (OsclAny*) & aPort; 258 } Parse(PVMFPortInterface * & aPort)259 void Parse(PVMFPortInterface*&aPort) 260 { 261 aPort = (PVMFPortInterface*)iParam1; 262 } 263 264 //for QueryInterface Construct(PVMFSessionId s,int32 aCmd,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)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 } Parse(PVUuid * & aUuid,PVInterface ** & aInterface)278 void Parse(PVUuid*&aUuid, PVInterface**&aInterface) 279 { 280 aUuid = (PVUuid*)iParam1; 281 aInterface = (PVInterface**)iParam2; 282 } 283 284 //for QueryUuids Construct(PVMFSessionId s,int32 aCmd,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)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 } Parse(OSCL_String * & aMimetype,Oscl_Vector<PVUuid,OsclMemAllocator> * & aUuids,bool & aExact)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 Construct(PVMFSessionId s,int32 aCmd,int32 aPortTag,const PvmfMimeString * aMimeType,const OsclAny * aContext)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 } Parse(int32 & aPortTag,OSCL_String * & aMimetype)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. Destroy()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. Copy(const PVMFGenericNodeCommand<Alloc> & aCmd)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. hipri()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. Allocate()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 PVMFNodeCommandQueue()445 PVMFNodeCommandQueue() 446 { 447 iCommandCounter = 0; 448 } 449 450 //note: usage of the class requires calling the Construct function Construct(int32 init,uint32 nres)451 void Construct(int32 init, uint32 nres) 452 {//construct the vector 453 iCommandCounter = init; 454 iVec.reserve(nres); 455 } 456 ~PVMFNodeCommandQueue()457 ~PVMFNodeCommandQueue() 458 { 459 while (!empty()) 460 {//must explicitly destroy all elements. 461 Erase(&iVec[0]); 462 } 463 } 464 Erase(vec_element_ptr elem)465 void Erase(vec_element_ptr elem) 466 {//erase an element 467 elem->Destroy(); 468 iVec.erase(elem); 469 } 470 AddL(vec_element & elem)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 StoreL(vec_element & elem)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 } size()514 uint32 size()const 515 { 516 return iVec.size(); 517 } clear()518 void clear() 519 { 520 iVec.clear(); 521 } front()522 vec_element& front() 523 { 524 return iVec.front(); 525 } empty()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