• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef  OSCL_MIME_STRING_UTILS_H_INCLUDED
19 #include "pv_mime_string_utils.h"
20 #endif
21 #ifndef  OSCL_STRING_UTILS_H_INCLUDED
22 #include "oscl_string_utils.h"
23 #endif
24 #ifndef  OSCL_ASSERT_H_INCLUDED
25 #include "oscl_assert.h"
26 #endif
27 #ifndef OSCL_DLL_H_INCLUDED
28 #include "oscl_dll.h"
29 #endif
30 #ifndef PVMF_MEDIA_CMD_H_INCLUDED
31 #include "pvmf_media_cmd.h"
32 #endif
33 #ifndef PVMF_MEDIA_MSG_FORMAT_IDS_H_INCLUDED
34 #include "pvmf_media_msg_format_ids.h"
35 #endif
36 #ifndef PVMF_BASIC_ERRORINFOMESSAGE_H_INCLUDED
37 #include "pvmf_basic_errorinfomessage.h"
38 #endif
39 #ifndef PVMF_ERRORINFOMESSAGE_EXTENSION_H_INCLUDED
40 #include "pvmf_errorinfomessage_extension.h"
41 #endif
42 #ifndef MEDIAINFO_H_INCLUDED
43 #include "media_info.h"
44 #endif
45 #ifndef PVMF_SM_TUNABLES_H_INCLUDED
46 #include "pvmf_sm_tunables.h"
47 #endif
48 #ifndef PVMF_MEDIALAYER_NODE_H_INCLUDED
49 #include "pvmf_medialayer_node.h"
50 #endif
51 #ifndef PVMF_MEDIA_MSG_HEADER_H_INCLUDED
52 #include "pvmf_media_msg_header.h"
53 #endif
54 #ifndef PVMF_SM_CONFIG_H_INCLUDED
55 #include "pvmf_sm_config.h"
56 #endif
57 
58 #define RETURN_ERROR_WHEN_MINUS_TIMESTAMP
59 // Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT()60 OSCL_DLL_ENTRY_POINT_DEFAULT()
61 
62 /**
63  * Node Constructor & Destructor
64  */
65 OSCL_EXPORT_REF PVMFMediaLayerNode::PVMFMediaLayerNode(int32 aPriority)
66         : OsclActiveObject(aPriority, "PVMFMediaLayerNode")
67 {
68     iLogger = NULL;
69     iDataPathLogger = NULL;
70     iDataPathLoggerFlowCtrl = NULL;
71     iClockLogger = NULL;
72     iOsclErrorTrapImp = NULL;
73     iExtensionInterface = NULL;
74     iPayLoadParserRegistry = NULL;
75     oPortDataLog = false;
76     iLogFileIndex = '0';
77     iClientPlayBackClock = NULL;
78     iDecryptionInterface = NULL;
79     srcPtr = NULL;
80     diffAudioVideoTS = 0;
81     iAdjustTimeReady = false;
82     oEOSsendunits = false;
83     iTimerNoDataTrack = 10 * 1000;
84     iReposTime = 0;
85     preroll64 = 0;
86     iStreamID = 0;
87     iExtensionInterface = NULL;
88     iNumRunL = 0;
89     iDiagnosticsLogged = false;
90 
91     int32 err;
92     OSCL_TRY(err,
93              /*
94               * Create the input command queue.Use a reserve to avoid lots of
95               * dynamic memory allocation.
96               */
97              iInputCommands.Construct(MEDIA_LAYER_NODE_CMD_START,
98                                       MEDIA_LAYER_NODE_CMD_QUE_RESERVE);
99 
100              /*
101               * Create the "current command" queue.  It will only contain one
102               * command at a time, so use a reserve of 1.
103               */
104              iCurrentCommand.Construct(0, 1);
105 
106              /* Create the port vector */
107              iPortVector.Construct(MEDIA_LAYER_NODE_VECTOR_RESERVE);
108 
109              /*
110               * Set the node capability data.
111               * This node can support an unlimited number of ports.
112               */
113              iCapability.iCanSupportMultipleInputPorts = true;
114              iCapability.iCanSupportMultipleOutputPorts = true;
115              iCapability.iHasMaxNumberOfPorts = false;
116              iCapability.iMaxNumberOfPorts = 0; /* no maximum */
117 
118              iCapability.iInputFormatCapability.push_back(PVMF_MIME_RTP);
119              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_M4V);
120              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_AMR_IETF);
121 
122             );
123 
124 
125 
126     if (err != OsclErrNone)
127     {
128         //if a leave happened, cleanup and re-throw the error
129         iInputCommands.clear();
130         iCurrentCommand.clear();
131         iPortVector.clear();
132         iCapability.iInputFormatCapability.clear();
133         iCapability.iOutputFormatCapability.clear();
134         OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
135         OSCL_CLEANUP_BASE_CLASS(OsclActiveObject);
136         OSCL_LEAVE(err);
137     }
138 }
139 
~PVMFMediaLayerNode()140 OSCL_EXPORT_REF PVMFMediaLayerNode::~PVMFMediaLayerNode()
141 {
142     LogSessionDiagnostics();
143 
144     Cancel();
145     if (iExtensionInterface)
146     {
147         iExtensionInterface->removeRef();
148     }
149 
150     /* delete related decryption */
151     iDecryptionInterface = NULL;
152     if (srcPtr != NULL)
153         oscl_free((uint8*)srcPtr);
154     srcPtr = NULL;
155 
156     /* thread logoff */
157     if (IsAdded())
158         RemoveFromScheduler();
159 
160     /*
161      * Cleanup allocated ports
162      * The port vector is self-deleting, but we want to notify
163      * observers that ports are being deleted
164      */
165     while (!iPortVector.empty())
166     {
167         /* delete corresponding port params */
168         Oscl_Vector<PVMFMediaLayerPortContainer, PVMFMediaLayerNodeAllocator>::iterator it;
169 
170         for (it = iPortParamsQueue.begin();
171                 it != iPortParamsQueue.end();
172                 it++)
173         {
174             if (it->iPort == iPortVector.front())
175             {
176                 if (it->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
177                 {
178                     DestroyPayLoadParser(&(it->iMimeType), it->iPayLoadParser);
179                     if (oPortDataLog)
180                     {
181                         if (it->iBinAppenderPtr.GetRep() != NULL)
182                         {
183                             it->iPortLogger->RemoveAppender(it->iBinAppenderPtr);
184                             it->iBinAppenderPtr.Unbind();
185                         }
186                     }
187                 }
188                 if (it->ipFragGroupAllocator != NULL)
189                 {
190                     it->ipFragGroupAllocator->CancelFreeChunkAvailableCallback();
191                     it->ipFragGroupAllocator->removeRef();
192                 }
193                 if (it->ipFragGroupMemPool != NULL)
194                 {
195                     it->ipFragGroupMemPool->removeRef();
196                 }
197                 it->CleanUp();
198                 iPortParamsQueue.erase(it);
199                 break;
200             }
201         }
202         iPortVector.Erase(&iPortVector.front());
203     }
204 
205     /*
206      * Cleanup commands
207      * The command queues are self-deleting, but we want to
208      * notify the observer of unprocessed commands.
209      */
210     while (!iCurrentCommand.empty())
211     {
212         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
213     }
214     while (!iInputCommands.empty())
215     {
216         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
217     }
218 }
219 
220 /**
221  * Public Node API implementation
222  */
223 
224 /**
225  * Do thread-specific node creation and go to "Idle" state.
226  */
ThreadLogon()227 OSCL_EXPORT_REF PVMFStatus PVMFMediaLayerNode::ThreadLogon()
228 {
229     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:ThreadLogon"));
230     PVMFStatus status;
231     switch (iInterfaceState)
232     {
233         case EPVMFNodeCreated:
234         {
235             if (!IsAdded())
236                 AddToScheduler();
237             iLogger = PVLogger::GetLoggerObject("PVMFMediaLayerNode");
238             iRunlLogger = PVLogger::GetLoggerObject("Run.PVMFMediaLayerNode");
239             iDataPathLogger = PVLogger::GetLoggerObject("datapath.sourcenode.medialayer");
240             iDataPathLoggerIn = PVLogger::GetLoggerObject("datapath.sourcenode.medialayer.in");
241             iDataPathLoggerOut = PVLogger::GetLoggerObject("datapath.sourcenode.medialayer.out");
242             iDataPathLoggerFlowCtrl = PVLogger::GetLoggerObject("datapath.sourcenode.medialayer.portflowcontrol");
243             if (iDataPathLoggerFlowCtrl != NULL)
244             {
245                 iDataPathLoggerFlowCtrl->DisableAppenderInheritance();
246             }
247             iClockLogger = PVLogger::GetLoggerObject("clock");
248             iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.streamingmanager.medialayer");
249             iDiagnosticsLogged = false;
250             iReposLogger = PVLogger::GetLoggerObject("pvplayerrepos.sourcenode.streamingmanager.medialayer");
251             iOsclErrorTrapImp = OsclErrorTrap::GetErrorTrapImp();
252             SetState(EPVMFNodeIdle);
253             status = PVMFSuccess;
254         }
255         break;
256         default:
257             status = PVMFErrInvalidState;
258             break;
259     }
260     return status;
261 }
262 
263 /**
264  * Do thread-specific node cleanup and go to "Created" state.
265  */
ThreadLogoff()266 OSCL_EXPORT_REF PVMFStatus PVMFMediaLayerNode::ThreadLogoff()
267 {
268     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:ThreadLogoff"));
269     PVMFStatus status;
270     switch (iInterfaceState)
271     {
272         case EPVMFNodeIdle:
273         {
274             if (IsAdded())
275             {
276                 RemoveFromScheduler();
277             }
278             iLogger = NULL;
279             iDataPathLogger = NULL;
280             iDataPathLoggerFlowCtrl = NULL;
281             iClockLogger = NULL;
282             iDiagnosticsLogger = NULL;
283             iOsclErrorTrapImp = NULL;
284             SetState(EPVMFNodeCreated);
285             status = PVMFSuccess;
286         }
287         break;
288 
289         default:
290             status = PVMFErrInvalidState;
291             break;
292     }
293     return status;
294 }
295 
296 /**
297  * retrieve node capabilities.
298  */
299 OSCL_EXPORT_REF
GetCapability(PVMFNodeCapability & aNodeCapability)300 PVMFStatus PVMFMediaLayerNode::GetCapability(PVMFNodeCapability& aNodeCapability)
301 {
302     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:GetCapability"));
303     aNodeCapability = iCapability;
304     return PVMFSuccess;
305 }
306 
307 /**
308  * retrieve a port iterator.
309  */
310 OSCL_EXPORT_REF
GetPorts(const PVMFPortFilter * aFilter)311 PVMFPortIter* PVMFMediaLayerNode::GetPorts(const PVMFPortFilter* aFilter)
312 {
313     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:GetPorts"));
314     OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
315     iPortVector.Reset();
316     return &iPortVector;
317 }
318 
319 /**
320  * Queue an asynchronous node command
321  */
322 OSCL_EXPORT_REF
QueryUUID(PVMFSessionId s,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)323 PVMFCommandId PVMFMediaLayerNode::QueryUUID(PVMFSessionId s,
324         const PvmfMimeString& aMimeType,
325         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
326         bool aExactUuidsOnly,
327         const OsclAny* aContext)
328 {
329     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:QueryUUID"));
330     PVMFMediaLayerNodeCommand cmd;
331     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
332             PVMF_MEDIA_LAYER_NODE_QUERYUUID,
333             aMimeType,
334             aUuids,
335             aExactUuidsOnly,
336             aContext);
337     return QueueCommandL(cmd);
338 }
339 
340 /**
341  * Queue an asynchronous node command
342  */
343 OSCL_EXPORT_REF
QueryInterface(PVMFSessionId s,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)344 PVMFCommandId PVMFMediaLayerNode::QueryInterface(PVMFSessionId s,
345         const PVUuid& aUuid,
346         PVInterface*& aInterfacePtr,
347         const OsclAny* aContext)
348 {
349     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:QueryInterface"));
350     PVMFMediaLayerNodeCommand cmd;
351     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
352             PVMF_MEDIA_LAYER_NODE_QUERYINTERFACE,
353             aUuid,
354             aInterfacePtr,
355             aContext);
356     return QueueCommandL(cmd);
357 }
358 
359 /**
360  * Queue an asynchronous node command
361  */
362 OSCL_EXPORT_REF
RequestPort(PVMFSessionId aSession,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)363 PVMFCommandId PVMFMediaLayerNode::RequestPort(PVMFSessionId aSession,
364         int32 aPortTag,
365         const PvmfMimeString* aPortConfig,
366         const OsclAny* aContext)
367 {
368     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:RequestPort"));
369     PVMFMediaLayerNodeCommand cmd;
370     cmd.PVMFMediaLayerNodeCommandBase::Construct(aSession,
371             PVMF_MEDIA_LAYER_NODE_REQUESTPORT,
372             aPortTag,
373             aPortConfig,
374             aContext);
375     return QueueCommandL(cmd);
376 }
377 
378 /**
379  * Queue an asynchronous node command
380  */
381 OSCL_EXPORT_REF
ReleasePort(PVMFSessionId s,PVMFPortInterface & aPort,const OsclAny * aContext)382 PVMFCommandId PVMFMediaLayerNode::ReleasePort(PVMFSessionId s,
383         PVMFPortInterface& aPort,
384         const OsclAny* aContext)
385 {
386     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:ReleasePort"));
387     PVMFMediaLayerNodeCommand cmd;
388     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
389             PVMF_MEDIA_LAYER_NODE_RELEASEPORT,
390             aPort,
391             aContext);
392     return QueueCommandL(cmd);
393 }
394 
395 /**
396  * Queue an asynchronous node command
397  */
398 OSCL_EXPORT_REF
Init(PVMFSessionId s,const OsclAny * aContext)399 PVMFCommandId PVMFMediaLayerNode::Init(PVMFSessionId s,
400                                        const OsclAny* aContext)
401 {
402     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:Init"));
403     PVMFMediaLayerNodeCommand cmd;
404     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
405             PVMF_MEDIA_LAYER_NODE_INIT,
406             aContext);
407     return QueueCommandL(cmd);
408 }
409 
410 /**
411  * Queue an asynchronous node command
412  */
413 OSCL_EXPORT_REF
Prepare(PVMFSessionId s,const OsclAny * aContext)414 PVMFCommandId PVMFMediaLayerNode::Prepare(PVMFSessionId s,
415         const OsclAny* aContext)
416 {
417     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:Prepare"));
418     PVMFMediaLayerNodeCommand cmd;
419     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
420             PVMF_MEDIA_LAYER_NODE_PREPARE,
421             aContext);
422     return QueueCommandL(cmd);
423 }
424 
425 /**
426  * Queue an asynchronous node command
427  */
428 OSCL_EXPORT_REF
Start(PVMFSessionId s,const OsclAny * aContext)429 PVMFCommandId PVMFMediaLayerNode::Start(PVMFSessionId s,
430                                         const OsclAny* aContext)
431 {
432     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:Start"));
433     PVMFMediaLayerNodeCommand cmd;
434     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
435             PVMF_MEDIA_LAYER_NODE_START,
436             aContext);
437     return QueueCommandL(cmd);
438 }
439 
440 /**
441  * Queue an asynchronous node command
442  */
443 OSCL_EXPORT_REF
Stop(PVMFSessionId s,const OsclAny * aContext)444 PVMFCommandId PVMFMediaLayerNode::Stop(PVMFSessionId s,
445                                        const OsclAny* aContext)
446 {
447     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:Stop"));
448     PVMFMediaLayerNodeCommand cmd;
449     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
450             PVMF_MEDIA_LAYER_NODE_STOP,
451             aContext);
452     return QueueCommandL(cmd);
453 }
454 
455 /**
456  * Queue an asynchronous node command
457  */
458 OSCL_EXPORT_REF
Flush(PVMFSessionId s,const OsclAny * aContext)459 PVMFCommandId PVMFMediaLayerNode::Flush(PVMFSessionId s,
460                                         const OsclAny* aContext)
461 {
462     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:Flush"));
463     PVMFMediaLayerNodeCommand cmd;
464     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
465             PVMF_MEDIA_LAYER_NODE_FLUSH,
466             aContext);
467     return QueueCommandL(cmd);
468 }
469 
470 /**
471  * Queue an asynchronous node command
472  */
473 OSCL_EXPORT_REF
Pause(PVMFSessionId s,const OsclAny * aContext)474 PVMFCommandId PVMFMediaLayerNode::Pause(PVMFSessionId s,
475                                         const OsclAny* aContext)
476 {
477     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:Pause"));
478     PVMFMediaLayerNodeCommand cmd;
479     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
480             PVMF_MEDIA_LAYER_NODE_PAUSE,
481             aContext);
482     return QueueCommandL(cmd);
483 }
484 
485 /**
486  * Queue an asynchronous node command
487  */
488 OSCL_EXPORT_REF
Reset(PVMFSessionId s,const OsclAny * aContext)489 PVMFCommandId PVMFMediaLayerNode::Reset(PVMFSessionId s,
490                                         const OsclAny* aContext)
491 {
492     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:Reset"));
493     PVMFMediaLayerNodeCommand cmd;
494     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
495             PVMF_MEDIA_LAYER_NODE_RESET,
496             aContext);
497     return QueueCommandL(cmd);
498 }
499 
500 /**
501  * Queue an asynchronous node command
502  */
503 OSCL_EXPORT_REF
CancelAllCommands(PVMFSessionId s,const OsclAny * aContext)504 PVMFCommandId PVMFMediaLayerNode::CancelAllCommands(PVMFSessionId s,
505         const OsclAny* aContext)
506 {
507     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:CancelAllCommands"));
508     PVMFMediaLayerNodeCommand cmd;
509     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
510             PVMF_MEDIA_LAYER_NODE_CANCELALLCOMMANDS,
511             aContext);
512     return QueueCommandL(cmd);
513 }
514 
515 /**
516  * Queue an asynchronous node command
517  */
518 OSCL_EXPORT_REF
CancelCommand(PVMFSessionId s,PVMFCommandId aCmdId,const OsclAny * aContext)519 PVMFCommandId PVMFMediaLayerNode::CancelCommand(PVMFSessionId s,
520         PVMFCommandId aCmdId,
521         const OsclAny* aContext)
522 {
523     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:CancelCommand"));
524     PVMFMediaLayerNodeCommand cmd;
525     cmd.PVMFMediaLayerNodeCommandBase::Construct(s,
526             PVMF_MEDIA_LAYER_NODE_CANCELCOMMAND,
527             aCmdId,
528             aContext);
529     return QueueCommandL(cmd);
530 }
531 
532 
533 /**
534  * This routine is called by various command APIs to queue an
535  * asynchronous command for processing by the command handler AO.
536  * This function may leave if the command can't be queued due to
537  * memory allocation failure.
538  */
QueueCommandL(PVMFMediaLayerNodeCommand & aCmd)539 PVMFCommandId PVMFMediaLayerNode::QueueCommandL(PVMFMediaLayerNodeCommand& aCmd)
540 {
541     PVMFCommandId id;
542     id = iInputCommands.AddL(aCmd);
543     if (IsAdded())
544     {
545         //wakeup the AO
546         RunIfNotReady();
547     }
548     return id;
549 }
550 
551 void
MoveCmdToCurrentQueue(PVMFMediaLayerNodeCommand & aCmd)552 PVMFMediaLayerNode::MoveCmdToCurrentQueue(PVMFMediaLayerNodeCommand& aCmd)
553 {
554     int32 err;
555     OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
556     if (err != OsclErrNone)
557     {
558         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
559         return;
560     }
561     iInputCommands.Erase(&aCmd);
562     return;
563 }
564 
565 /**
566  * Asynchronous Command processing routines.
567  * These routines are all called under the AO.
568  */
569 
570 /**
571  * Called by the command handler AO to process a command from
572  * the input queue.
573  * Return true if a command was processed, false if the command
574  * processor is busy and can't process another command now.
575  */
ProcessCommand(PVMFMediaLayerNodeCommand & aCmd)576 bool PVMFMediaLayerNode::ProcessCommand(PVMFMediaLayerNodeCommand& aCmd)
577 {
578     /*
579      * normally this node will not start processing one command
580      * until the prior one is finished.  However, a hi priority
581      * command such as Cancel must be able to interrupt a command
582      * in progress.
583      */
584     if (!iCurrentCommand.empty() && !aCmd.hipri())
585         return false;
586 
587     switch (aCmd.iCmd)
588     {
589         case PVMF_MEDIA_LAYER_NODE_QUERYUUID:
590             DoQueryUuid(aCmd);
591             break;
592 
593         case PVMF_MEDIA_LAYER_NODE_QUERYINTERFACE:
594             DoQueryInterface(aCmd);
595             break;
596 
597         case PVMF_MEDIA_LAYER_NODE_REQUESTPORT:
598             DoRequestPort(aCmd);
599             break;
600 
601         case PVMF_MEDIA_LAYER_NODE_RELEASEPORT:
602             DoReleasePort(aCmd);
603             break;
604 
605         case PVMF_MEDIA_LAYER_NODE_INIT:
606             DoInit(aCmd);
607             break;
608 
609         case PVMF_MEDIA_LAYER_NODE_PREPARE:
610             DoPrepare(aCmd);
611             break;
612 
613         case PVMF_MEDIA_LAYER_NODE_START:
614             DoStart(aCmd);
615             break;
616 
617         case PVMF_MEDIA_LAYER_NODE_STOP:
618             DoStop(aCmd);
619             break;
620 
621         case PVMF_MEDIA_LAYER_NODE_FLUSH:
622             DoFlush(aCmd);
623             break;
624 
625         case PVMF_MEDIA_LAYER_NODE_PAUSE:
626             DoPause(aCmd);
627             break;
628 
629         case PVMF_MEDIA_LAYER_NODE_RESET:
630             DoReset(aCmd);
631             break;
632 
633         case PVMF_MEDIA_LAYER_NODE_CANCELALLCOMMANDS:
634             DoCancelAllCommands(aCmd);
635             break;
636 
637         case PVMF_MEDIA_LAYER_NODE_CANCELCOMMAND:
638             DoCancelCommand(aCmd);
639             break;
640 
641         default:
642         {
643             /* unknown command type */
644             CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
645         }
646         break;
647     }
648 
649     return true;
650 }
651 
652 /**
653  * The various command handlers call this when a command is complete.
654  */
CommandComplete(MediaLayerNodeCmdQ & aCmdQ,PVMFMediaLayerNodeCommand & aCmd,PVMFStatus aStatus,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)655 void PVMFMediaLayerNode::CommandComplete(MediaLayerNodeCmdQ& aCmdQ,
656         PVMFMediaLayerNodeCommand& aCmd,
657         PVMFStatus aStatus,
658         OsclAny* aEventData,
659         PVUuid* aEventUUID,
660         int32* aEventCode)
661 {
662     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
663                          , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
664 
665     PVInterface* extif = NULL;
666     PVMFBasicErrorInfoMessage* errormsg = NULL;
667     if (aEventUUID && aEventCode)
668     {
669         PVMF_MEDIA_LAYER_NEW(NULL, PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL), errormsg);
670         extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
671     }
672 
673     /* create response */
674     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, extif, aEventData);
675     PVMFSessionId session = aCmd.iSession;
676 
677     /* Erase the command from the queue. */
678     aCmdQ.Erase(&aCmd);
679 
680     /* Report completion to the session observer */
681     ReportCmdCompleteEvent(session, resp);
682 
683     if (errormsg)
684     {
685         errormsg->removeRef();
686     }
687     /*
688      * Transition to error state in case of select errors only, viz.
689      * PVMFFailure, PVMFErrNoMemory, PVMFErrNoResources
690      * Any other status implies that the node is probably in a recoverable
691      * state
692      */
693     if ((aStatus == PVMFFailure) ||
694             (aStatus == PVMFErrNoMemory) ||
695             (aStatus == PVMFErrNoResources))
696     {
697         SetState(EPVMFNodeError);
698     }
699 }
700 
701 /**
702  * Called by the command handler AO to do the node Reset.
703  */
DoReset(PVMFMediaLayerNodeCommand & aCmd)704 void PVMFMediaLayerNode::DoReset(PVMFMediaLayerNodeCommand& aCmd)
705 {
706     LogSessionDiagnostics();
707 
708     switch (iInterfaceState)
709     {
710         case EPVMFNodeStarted:
711         case EPVMFNodePaused:
712         {
713             /* Clear queued messages in ports */
714             uint32 i;
715             for (i = 0; i < iPortVector.size(); i++)
716             {
717                 iPortVector[i]->ClearMsgQueues();
718                 PVMFMediaLayerPortContainer* portContainerPtr = NULL;
719                 GetPortContainer(iPortVector[i], portContainerPtr);
720                 if (portContainerPtr)
721                     portContainerPtr->ResetParams();
722             }
723         }
724         /* Intentional fall thru */
725         case EPVMFNodeCreated:
726         case EPVMFNodeIdle:
727         case EPVMFNodeInitialized:
728         case EPVMFNodePrepared:
729         case EPVMFNodeError:
730         {
731             /* delete related decryption */
732             iDecryptionInterface = NULL;
733             if (srcPtr != NULL)
734                 oscl_free((uint8*)srcPtr);
735             srcPtr = NULL;
736 
737             Oscl_Vector<PVMFMediaLayerPortContainer, PVMFMediaLayerNodeAllocator>::iterator it;
738             for (it = iPortParamsQueue.begin(); it != iPortParamsQueue.end(); it++)
739             {
740                 if (it->ipFragGroupAllocator != NULL)
741                     it->ipFragGroupAllocator->CancelFreeChunkAvailableCallback();
742             }
743 
744             /* delete all ports and notify observer */
745             while (!iPortVector.empty())
746             {
747                 iPortVector.Erase(&iPortVector.front());
748             }
749 
750             /* delete port params */
751             while (!iPortParamsQueue.empty())
752             {
753                 it = iPortParamsQueue.begin();
754                 if (it->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
755                 {
756                     DestroyPayLoadParser(&(it->iMimeType), it->iPayLoadParser);
757                     if (oPortDataLog)
758                     {
759                         if (it->iBinAppenderPtr.GetRep() != NULL)
760                         {
761                             it->iPortLogger->RemoveAppender(it->iBinAppenderPtr);
762                             it->iBinAppenderPtr.Unbind();
763                         }
764                     }
765                 }
766                 if (it->ipFragGroupAllocator != NULL)
767                 {
768                     it->ipFragGroupAllocator->CancelFreeChunkAvailableCallback();
769                     it->ipFragGroupAllocator->removeRef();
770                 }
771                 if (it->ipFragGroupMemPool != NULL)
772                 {
773                     it->ipFragGroupMemPool->removeRef();
774                 }
775                 it->CleanUp();
776                 iPortParamsQueue.erase(it);
777             }
778             /* restore original port vector reserve */
779             iPortVector.Reconstruct();
780 
781             SetState(EPVMFNodeIdle);
782             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
783         }
784         break;
785 
786         default:
787             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
788             break;
789     }
790 }
791 
792 /**
793  * Called by the command handler AO to do the Query UUID
794  */
DoQueryUuid(PVMFMediaLayerNodeCommand & aCmd)795 void PVMFMediaLayerNode::DoQueryUuid(PVMFMediaLayerNodeCommand& aCmd)
796 {
797     /* This node supports Query UUID from any state */
798     OSCL_String* mimetype;
799     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
800     bool exactmatch;
801     aCmd.PVMFMediaLayerNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
802 
803     /*
804      * Try to match the input mimetype against any of
805      * the custom interfaces for this node
806      */
807 
808     /*
809      * Match against custom interface1...
810      * also match against base mimetypes for custom interface1,
811      * unless exactmatch is set.
812      */
813     if (*mimetype == PVMF_MEDIALAYER_CUSTOMINTERFACE_MIMETYPE
814             || (!exactmatch && *mimetype == PVMF_MEDIALAYER_MIMETYPE)
815             || (!exactmatch && *mimetype == PVMF_MEDIALAYER_BASEMIMETYPE))
816     {
817         PVUuid uuid(PVMF_MEDIALAYERNODE_EXTENSIONINTERFACE_UUID);
818         uuidvec->push_back(uuid);
819     }
820     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
821 }
822 
823 /**
824  * Called by the command handler AO to do the Query Interface.
825  */
DoQueryInterface(PVMFMediaLayerNodeCommand & aCmd)826 void PVMFMediaLayerNode::DoQueryInterface(PVMFMediaLayerNodeCommand& aCmd)
827 {
828     /* This node supports Query Interface from any state */
829     PVUuid* uuid;
830     PVInterface** ptr;
831     aCmd.PVMFMediaLayerNodeCommandBase::Parse(uuid, ptr);
832 
833     if (*uuid == PVUuid(PVMF_MEDIALAYERNODE_EXTENSIONINTERFACE_UUID))
834     {
835         if (!iExtensionInterface)
836         {
837             PVMFMediaLayerNodeAllocator alloc;
838             int32 err;
839             OsclAny*ptr = NULL;
840             OSCL_TRY(err,
841                      ptr = alloc.ALLOCATE(sizeof(PVMFMediaLayerNodeExtensionInterfaceImpl));
842                     );
843             if (err != OsclErrNone || !ptr)
844             {
845                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
846                 return;
847             }
848             iExtensionInterface =
849                 OSCL_PLACEMENT_NEW(ptr, PVMFMediaLayerNodeExtensionInterfaceImpl(this));
850         }
851 
852         if (iExtensionInterface->queryInterface(*uuid, *ptr))
853         {
854             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
855         }
856         else
857         {
858             CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
859         }
860     }
861     else
862     {
863         //not supported
864         *ptr = NULL;
865         CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
866     }
867 }
868 
869 /**
870  * Called by the command handler AO to do the port request
871  */
DoRequestPort(PVMFMediaLayerNodeCommand & aCmd)872 void PVMFMediaLayerNode::DoRequestPort(PVMFMediaLayerNodeCommand& aCmd)
873 {
874     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::DoRequestPort"));
875 
876     /* retrieve port tag and mime string */
877     int32 tag;
878     OSCL_String* portConfig;
879     aCmd.PVMFMediaLayerNodeCommandBase::Parse(tag, portConfig);
880 
881     /* Allocate a new port */
882     OsclAny *ptr = NULL;
883     bool retVal;
884 
885     retVal = Allocate(ptr);
886 
887     if (retVal == false || !ptr)
888     {
889         PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::DoRequestPort: Error - iPortVector Out of memory"));
890         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
891         return;
892     }
893 
894     OsclExclusivePtr<PVMFMediaLayerPort> portAutoPtr;
895     PVMFMediaLayerPort* port = NULL;
896     PVMFMediaLayerPortContainer portParams;
897     OSCL_StackString<8> asf(_STRLIT_CHAR("asf"));
898     OSCL_StackString<8> rtp(_STRLIT_CHAR("rtp"));
899 
900     /*
901      * Odd numbered ports are output
902      */
903     if (tag % 2)
904     {
905         portParams.tag = PVMF_MEDIALAYER_PORT_TYPE_OUTPUT;
906         port = OSCL_PLACEMENT_NEW(ptr, PVMFMediaLayerPort(tag, this, "MediaLayerOut"));
907         portAutoPtr.set(port);
908         portParams.iPort = port;
909         portParams.id = tag;
910         portParams.iMimeType = portConfig->get_cstr();
911 
912         // parse the mime string to find out the associated input port
913         uint inputPort;
914         if ((portConfig == NULL) ||
915                 (oscl_strncmp(portConfig->get_cstr(), asf.get_cstr(), 3) != 0))
916         {
917             // no mime string -> use the old mapping from output port to input port
918             //   input port tag = output port tag - 1
919 
920             inputPort = tag - 1;
921             portParams.iTransportType = rtp;
922         }
923         else
924         {
925             portParams.iTransportType = asf;
926 
927             if (!parseOutputPortMime(portConfig, inputPort))
928             {
929                 PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error"
930                                       " - cannot parse mime string: %s for output port %d",
931                                       this, portConfig, tag));
932             }
933 
934             // according to our tag scheme, the input port tag should be even
935             if (inputPort % 2)
936             {
937                 PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error"
938                                       " - invalid input port tag %d in output port mime %s",
939                                       this, inputPort, portConfig));
940                 CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
941                 return;
942             }
943         }
944 
945         // now, we have the tag for the input port - try to find it in the queue
946         uint index;
947         for (index = 0; index < iPortParamsQueue.size(); index++)
948         {
949             if ((uint)iPortParamsQueue[index].id == inputPort)
950             {
951                 break;
952             }
953         }
954 
955         if (index == iPortParamsQueue.size())
956         {
957             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error"
958                                   " - input port %d not yet commissioned (output port %d setup)",
959                                   this, inputPort, tag));
960             CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
961             return;
962         }
963 
964         // add the index of the input port in the counter port vector for the output port
965         portParams.vCounterPorts.push_back(index);
966 
967         // create frag group allocator
968         portParams.ipFragGroupMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (MEDIALAYERNODE_MAXNUM_MEDIA_DATA));
969         if (portParams.ipFragGroupMemPool == NULL)
970         {
971             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error - Unable to allocate mempool", this));
972             CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
973             portAutoPtr.release();
974             return;
975         }
976         portParams.ipFragGroupAllocator = new PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>(
977             MEDIALAYERNODE_MAXNUM_MEDIA_DATA,
978             MEDIALAYERNODE_MAXNUM_MEDIA_DATA,
979             portParams.ipFragGroupMemPool);
980         if (portParams.ipFragGroupAllocator == NULL)
981         {
982             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error - Unable to create frag group allocator", this));
983             CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
984             return;
985         }
986         portParams.ipFragGroupAllocator->create();
987 
988         // add the output port to the queue
989         int newIndex = iPortParamsQueue.size();
990 
991         retVal = Push(portParams);
992         if (retVal == false)
993         {
994             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error - iPortParamsQueue.push_back() failed", this));
995             CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
996             return;
997         }
998 
999         // now, add the new output port's index to the input port's counter port vector
1000         iPortParamsQueue[index].vCounterPorts.push_back(newIndex);
1001     }
1002     /*
1003      * Even numbered ports are input
1004      */
1005     else
1006     {
1007         portParams.tag = PVMF_MEDIALAYER_PORT_TYPE_INPUT;
1008         port = OSCL_PLACEMENT_NEW(ptr, PVMFMediaLayerPort(tag, this, "MediaLayerIn"));
1009         portAutoPtr.set(port);
1010         portParams.iPort = port;
1011         portParams.id = tag;
1012 
1013         {
1014             portParams.iTransportType = rtp;
1015         }
1016 
1017         IPayloadParser* parser = CreatePayLoadParser(portConfig);
1018         if (parser != NULL)
1019         {
1020             portParams.iPayLoadParser = parser;
1021             portParams.iMimeType = portConfig->get_cstr();
1022         }
1023         else
1024         {
1025             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error - CreatePayLoadParser() failed", this));
1026             CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported);
1027             portAutoPtr.release();
1028             return;
1029         }
1030 
1031         if (oPortDataLog)
1032         {
1033             OSCL_StackString<32> iMLPortLoggerTag("PVMFMLNode");
1034             iMLPortLoggerTag += iLogFileIndex;
1035             iLogFileIndex += 1;
1036             iMLPortLoggerTag += portConfig->get_cstr();
1037             portParams.iPortLogger = PVLogger::GetLoggerObject(iMLPortLoggerTag.get_cstr());
1038             OSCL_StackString<32> MLPortLogFile;
1039             MLPortLogFile = portLogPath;
1040             MLPortLogFile += iMLPortLoggerTag.get_cstr();
1041             portParams.iLogFile = MLPortLogFile;
1042 
1043             PVLoggerAppender *binAppender =
1044                 BinaryFileAppender::CreateAppender((char*)(portParams.iLogFile.get_cstr()));
1045 
1046             if (binAppender == NULL)
1047             {
1048                 PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error - Binary Appender Create failed", this));
1049                 CommandComplete(iInputCommands, aCmd, PVMFErrNoResources);
1050                 portAutoPtr.release();
1051                 return;
1052             }
1053             OsclRefCounterSA<PVMFMediaLayerNodeLoggerDestructDealloc>* binAppenderRefCounter =
1054                 new OsclRefCounterSA<PVMFMediaLayerNodeLoggerDestructDealloc>(binAppender);
1055 
1056             OsclSharedPtr<PVLoggerAppender> appenderSharedPtr(binAppender, binAppenderRefCounter);
1057             portParams.iBinAppenderPtr = appenderSharedPtr;
1058             portParams.iPortLogger->AddAppender(portParams.iBinAppenderPtr);
1059         }
1060 
1061         retVal = Push(portParams);
1062         if (retVal == false)
1063         {
1064             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DoRequestPort: Error - iPortParamsQueue.push_back() failed", this));
1065             CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
1066             return;
1067         }
1068     }
1069 
1070     /* Add the port to the port vector. */
1071     retVal = AddPort(port);
1072 
1073     if (retVal == false)
1074     {
1075         CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
1076         portAutoPtr.release();
1077         return;
1078     }
1079 
1080     portAutoPtr.release();
1081 
1082     /* Return the port pointer to the caller. */
1083     CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)port);
1084 }
1085 
Allocate(OsclAny * & ptr)1086 bool PVMFMediaLayerNode::Allocate(OsclAny*& ptr)
1087 {
1088     int32 err;
1089     OSCL_TRY(err, ptr = iPortVector.Allocate(););
1090     if (err != OsclErrNone)
1091     {
1092         return false;
1093     }
1094     return true;
1095 }
1096 
Push(PVMFMediaLayerPortContainer portParams)1097 bool PVMFMediaLayerNode::Push(PVMFMediaLayerPortContainer portParams)
1098 {
1099     int32 err;
1100     OSCL_TRY(err, iPortParamsQueue.push_back(portParams););
1101     if (err != OsclErrNone)
1102     {
1103         return false;
1104     }
1105     return true;
1106 }
1107 
AddPort(PVMFMediaLayerPort * port)1108 bool PVMFMediaLayerNode::AddPort(PVMFMediaLayerPort* port)
1109 {
1110     int32 err;
1111     OSCL_TRY(err, iPortVector.AddL(port););
1112     if (err != OsclErrNone)
1113     {
1114         return false;
1115     }
1116     return true;
1117 }
1118 /**
1119  * Called by the command handler AO to do the port release
1120  */
DoReleasePort(PVMFMediaLayerNodeCommand & aCmd)1121 void PVMFMediaLayerNode::DoReleasePort(PVMFMediaLayerNodeCommand& aCmd)
1122 {
1123     /* This node supports release port from any state */
1124 
1125     /* Find the port in the port vector */
1126     PVMFPortInterface* p = NULL;
1127     aCmd.PVMFMediaLayerNodeCommandBase::Parse(p);
1128 
1129     PVMFMediaLayerPort* port = (PVMFMediaLayerPort*)p;
1130 
1131     PVMFMediaLayerPort** portPtr = iPortVector.FindByValue(port);
1132     if (portPtr)
1133     {
1134         /* delete corresponding port params */
1135         Oscl_Vector<PVMFMediaLayerPortContainer, PVMFMediaLayerNodeAllocator>::iterator it;
1136 
1137         for (it = iPortParamsQueue.begin();
1138                 it != iPortParamsQueue.end();
1139                 it++)
1140         {
1141             if (it->iPort == port)
1142             {
1143                 if (it->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
1144                 {
1145                     DestroyPayLoadParser(&(it->iMimeType), it->iPayLoadParser);
1146                     if (oPortDataLog)
1147                     {
1148                         if (it->iBinAppenderPtr.GetRep() != NULL)
1149                         {
1150                             it->iPortLogger->RemoveAppender(it->iBinAppenderPtr);
1151                             it->iBinAppenderPtr.Unbind();
1152                         }
1153                     }
1154                 }
1155                 if (it->ipFragGroupAllocator != NULL)
1156                 {
1157                     it->ipFragGroupAllocator->CancelFreeChunkAvailableCallback();
1158                     it->ipFragGroupAllocator->removeRef();
1159                 }
1160                 if (it->ipFragGroupMemPool != NULL)
1161                 {
1162                     it->ipFragGroupMemPool->removeRef();
1163                 }
1164                 it->CleanUp();
1165                 iPortParamsQueue.erase(it);
1166                 break;
1167             }
1168         }
1169         iPortVector.Erase(portPtr);
1170         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1171     }
1172     else
1173     {
1174         /* port not found */
1175         CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
1176     }
1177 }
1178 
1179 /**
1180  * Called by the command handler AO to do the node Init
1181  */
DoInit(PVMFMediaLayerNodeCommand & aCmd)1182 void PVMFMediaLayerNode::DoInit(PVMFMediaLayerNodeCommand& aCmd)
1183 {
1184     switch (iInterfaceState)
1185     {
1186         case EPVMFNodeIdle:
1187         {
1188             SetState(EPVMFNodeInitialized);
1189             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1190         }
1191         break;
1192 
1193         default:
1194             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
1195             break;
1196     }
1197 }
1198 /**
1199 
1200  * Called by the command handler AO to do the node Prepare
1201  */
DoPrepare(PVMFMediaLayerNodeCommand & aCmd)1202 void PVMFMediaLayerNode::DoPrepare(PVMFMediaLayerNodeCommand& aCmd)
1203 {
1204     switch (iInterfaceState)
1205     {
1206         case EPVMFNodeInitialized:
1207         {
1208             SetState(EPVMFNodePrepared);
1209             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1210         }
1211         break;
1212 
1213         default:
1214             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
1215             break;
1216     }
1217 }
1218 
1219 IPayloadParser*
CreatePayLoadParser(PvmfMimeString * aPortConfig)1220 PVMFMediaLayerNode::CreatePayLoadParser(PvmfMimeString* aPortConfig)
1221 {
1222     PayloadParserRegistry* registry = iPayLoadParserRegistry;
1223 
1224     if (registry == NULL)
1225     {
1226         PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::CreatePayLoadParser: Error - Invalid Registry", this));
1227         return NULL;
1228     }
1229 
1230     OsclMemoryFragment memFrag;
1231     memFrag.ptr = (OsclAny*)(aPortConfig->get_cstr());
1232     memFrag.len = aPortConfig->get_size();
1233     IPayloadParserFactory* factory = registry->lookupPayloadParserFactory(memFrag);
1234     if (factory == NULL)
1235     {
1236         PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::CreatePayLoadParser: Error - Invalid Factory", this));
1237         return NULL;
1238     }
1239     return (factory->createPayloadParser());
1240 }
1241 
1242 void
DestroyPayLoadParser(PvmfMimeString * aPortConfig,IPayloadParser * aParser)1243 PVMFMediaLayerNode::DestroyPayLoadParser(PvmfMimeString* aPortConfig,
1244         IPayloadParser* aParser)
1245 {
1246     PayloadParserRegistry* registry = iPayLoadParserRegistry;
1247 
1248     if (registry == NULL)
1249     {
1250         PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DestroyPayLoadParser: Error - Invalid Registry", this));
1251         OSCL_LEAVE(OsclErrBadHandle);
1252     }
1253 
1254     OsclMemoryFragment memFrag;
1255     memFrag.ptr = (OsclAny*)(aPortConfig->get_cstr());
1256     memFrag.len = aPortConfig->get_size();
1257     IPayloadParserFactory* factory =
1258         registry->lookupPayloadParserFactory(memFrag);
1259     if (factory == NULL)
1260     {
1261         PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::DestroyPayLoadParser: Error - Invalid Factory", this));
1262         OSCL_LEAVE(OsclErrBadHandle);
1263     }
1264     factory->destroyPayloadParser(aParser);
1265 }
1266 
1267 /**
1268  * Called by the command handler AO to do the node Start
1269  */
DoStart(PVMFMediaLayerNodeCommand & aCmd)1270 void PVMFMediaLayerNode::DoStart(PVMFMediaLayerNodeCommand& aCmd)
1271 {
1272     iDiagnosticsLogged = false;
1273     PVMFStatus status = PVMFSuccess;
1274     switch (iInterfaceState)
1275     {
1276         case EPVMFNodePrepared:
1277         case EPVMFNodePaused:
1278         {
1279             /* transition to Started */
1280             SetState(EPVMFNodeStarted);
1281         }
1282         break;
1283 
1284         default:
1285             status = PVMFErrInvalidState;
1286             break;
1287     }
1288 
1289     CommandComplete(iInputCommands, aCmd, status);
1290 }
1291 
1292 /**
1293  * Called by the command handler AO to do the node Stop
1294  */
DoStop(PVMFMediaLayerNodeCommand & aCmd)1295 void PVMFMediaLayerNode::DoStop(PVMFMediaLayerNodeCommand& aCmd)
1296 {
1297     LogSessionDiagnostics();
1298 
1299     switch (iInterfaceState)
1300     {
1301         case EPVMFNodeStarted:
1302         case EPVMFNodePaused:
1303         {
1304             /* Clear queued messages in ports */
1305             uint32 i;
1306             for (i = 0; i < iPortVector.size(); i++)
1307             {
1308                 iPortVector[i]->ClearMsgQueues();
1309 
1310                 PVMFMediaLayerPortContainer* portContainerPtr = NULL;
1311                 bool bRet = GetPortContainer(iPortVector[i], portContainerPtr);
1312                 if (bRet)
1313                 {
1314                     portContainerPtr->ResetParams();
1315                     portContainerPtr->vAccessUnits.clear();
1316                 }
1317             }
1318             /* transition to Prepared state */
1319             Oscl_Int64_Utils::set_uint64(preroll64, 0, 0);
1320             oEOSsendunits = false;
1321             SetState(EPVMFNodePrepared);
1322             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1323         }
1324         break;
1325 
1326         default:
1327             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
1328             break;
1329     }
1330 }
1331 
1332 /**
1333  * Called by the command handler AO to do the node Flush
1334  */
DoFlush(PVMFMediaLayerNodeCommand & aCmd)1335 void PVMFMediaLayerNode::DoFlush(PVMFMediaLayerNodeCommand& aCmd)
1336 {
1337     switch (iInterfaceState)
1338     {
1339         case EPVMFNodeStarted:
1340         case EPVMFNodePaused:
1341         {
1342             /*
1343              * the flush is asynchronous.  move the command from
1344              * the input command queue to the current command, where
1345              * it will remain until the flush completes.
1346              */
1347             int32 err;
1348             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
1349             if (err != OsclErrNone)
1350             {
1351                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
1352                 return;
1353             }
1354             iInputCommands.Erase(&aCmd);
1355             /* Notify all ports to suspend their input */
1356             for (uint32 i = 0; i < iPortVector.size(); i++)
1357                 iPortVector[i]->SuspendInput();
1358         }
1359         break;
1360 
1361         default:
1362             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
1363             break;
1364     }
1365 }
1366 
1367 /**
1368  * A routine to tell if a flush operation is in progress.
1369  */
FlushPending()1370 bool PVMFMediaLayerNode::FlushPending()
1371 {
1372     return (iCurrentCommand.size() > 0
1373             && iCurrentCommand.front().iCmd == PVMF_MEDIA_LAYER_NODE_FLUSH);
1374 }
1375 
1376 
1377 /**
1378  * Called by the command handler AO to do the node Pause
1379  */
DoPause(PVMFMediaLayerNodeCommand & aCmd)1380 void PVMFMediaLayerNode::DoPause(PVMFMediaLayerNodeCommand& aCmd)
1381 {
1382     PVMFStatus status;
1383     switch (iInterfaceState)
1384     {
1385         case EPVMFNodeStarted:
1386         {
1387             /* transition to paused state */
1388             SetState(EPVMFNodePaused);
1389             status = PVMFSuccess;
1390         }
1391         break;
1392 
1393         case EPVMFNodePaused:
1394             /* Ignore Pause if already paused */
1395             status = PVMFSuccess;
1396             break;
1397 
1398         default:
1399             status = PVMFErrInvalidState;
1400             break;
1401     }
1402     CommandComplete(iInputCommands, aCmd, status);
1403     return;
1404 }
1405 
1406 /**
1407  * Called by the command handler AO to do the Cancel All
1408  */
DoCancelAllCommands(PVMFMediaLayerNodeCommand & aCmd)1409 void PVMFMediaLayerNode::DoCancelAllCommands(PVMFMediaLayerNodeCommand& aCmd)
1410 {
1411     /* first cancel the current command if any */
1412     {
1413         while (!iCurrentCommand.empty())
1414             CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
1415     }
1416 
1417     /* next cancel all queued commands */
1418     {
1419         /* start at element 1 since this cancel command is element 0 */
1420         while (iInputCommands.size() > 1)
1421             CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
1422     }
1423 
1424     /* finally, report cancel complete */
1425     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1426 }
1427 
1428 /**
1429  * Called by the command handler AO to do the Cancel single command
1430  */
DoCancelCommand(PVMFMediaLayerNodeCommand & aCmd)1431 void PVMFMediaLayerNode::DoCancelCommand(PVMFMediaLayerNodeCommand& aCmd)
1432 {
1433     /* extract the command ID from the parameters */
1434     PVMFCommandId id;
1435     aCmd.PVMFMediaLayerNodeCommandBase::Parse(id);
1436 
1437     /* first check "current" command if any */
1438     {
1439         PVMFMediaLayerNodeCommand* cmd = iCurrentCommand.FindById(id);
1440         if (cmd)
1441         {
1442             /* cancel the queued command */
1443             CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
1444             /* report cancel success */
1445             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1446             return;
1447         }
1448     }
1449 
1450     /* next check input queue */
1451     {
1452         /* start at element 1 since this cancel command is element 0 */
1453         PVMFMediaLayerNodeCommand* cmd = iInputCommands.FindById(id, 1);
1454         if (cmd)
1455         {
1456             /* cancel the queued command */
1457             CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
1458             /* report cancel success */
1459             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
1460             return;
1461         }
1462     }
1463     /* if we get here the command isn't queued so the cancel fails */
1464     CommandComplete(iInputCommands, aCmd, PVMFFailure);
1465 }
1466 
1467 
1468 /////////////////////////////////////////////////////
1469 // Event reporting routines.
1470 /////////////////////////////////////////////////////
SetState(TPVMFNodeInterfaceState s)1471 void PVMFMediaLayerNode::SetState(TPVMFNodeInterfaceState s)
1472 {
1473     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:SetState %d", s));
1474     PVMFNodeInterface::SetState(s);
1475 }
1476 
ReportErrorEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)1477 void PVMFMediaLayerNode::ReportErrorEvent(PVMFEventType aEventType,
1478         OsclAny* aEventData,
1479         PVUuid* aEventUUID,
1480         int32* aEventCode)
1481 {
1482     PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode:NodeErrorEvent Type %d Data %d"
1483                           , aEventType, aEventData));
1484 
1485     if (aEventUUID && aEventCode)
1486     {
1487         PVMFBasicErrorInfoMessage* eventmsg;
1488         PVMF_MEDIA_LAYER_NEW(NULL, PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL), eventmsg);
1489         PVMFAsyncEvent asyncevent(PVMFErrorEvent,
1490                                   aEventType,
1491                                   NULL,
1492                                   OSCL_STATIC_CAST(PVInterface*, eventmsg),
1493                                   aEventData,
1494                                   NULL,
1495                                   0);
1496         PVMFNodeInterface::ReportErrorEvent(asyncevent);
1497         eventmsg->removeRef();
1498     }
1499     else
1500     {
1501         PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
1502     }
1503 }
1504 
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)1505 void PVMFMediaLayerNode::ReportInfoEvent(PVMFEventType aEventType,
1506         OsclAny* aEventData,
1507         PVUuid* aEventUUID,
1508         int32* aEventCode)
1509 {
1510     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode:NodeInfoEvent Type %d Data %d"
1511                          , aEventType, aEventData));
1512 
1513     if (aEventUUID && aEventCode)
1514     {
1515         PVMFBasicErrorInfoMessage* eventmsg;
1516         PVMF_MEDIA_LAYER_NEW(NULL, PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL), eventmsg);
1517         PVMFAsyncEvent asyncevent(PVMFInfoEvent,
1518                                   aEventType,
1519                                   NULL,
1520                                   OSCL_STATIC_CAST(PVInterface*, eventmsg),
1521                                   aEventData,
1522                                   NULL,
1523                                   0);
1524         PVMFNodeInterface::ReportInfoEvent(asyncevent);
1525         eventmsg->removeRef();
1526     }
1527     else
1528     {
1529         PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
1530     }
1531 }
1532 
1533 /////////////////////////////////////////////////////
1534 // Port Processing routines
1535 /////////////////////////////////////////////////////
QueuePortActivity(PVMFMediaLayerPortContainer * aPortContainer,const PVMFPortActivity & aActivity)1536 void PVMFMediaLayerNode::QueuePortActivity(PVMFMediaLayerPortContainer* aPortContainer,
1537         const PVMFPortActivity &aActivity)
1538 {
1539     OSCL_UNUSED_ARG(aPortContainer);
1540     OSCL_UNUSED_ARG(aActivity);
1541     if (IsAdded())
1542     {
1543         RunIfNotReady();
1544     }
1545 }
1546 
freechunkavailable(PVMFPortInterface * aPort)1547 void PVMFMediaLayerNode::freechunkavailable(PVMFPortInterface* aPort)
1548 {
1549     PVMF_MLNODE_LOGINFO((0, "0x%x PVMFMediaLayerNode::freechunkavailable: port=0x%x",
1550                          this, aPort));
1551 
1552     PVMFMediaLayerPortContainer* portContainerPtr = NULL;
1553 
1554     if (!GetPortContainer(aPort, portContainerPtr))
1555     {
1556         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aPort));
1557         PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::freechunkavailable: Error - GetPortContainer failed", this));
1558         return;
1559     }
1560 
1561     portContainerPtr->oProcessIncomingMessages = true;
1562     PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
1563                                          "PVMFMediaLayerNode::freechunkavailable: Mime=%s, QSize =%d", portContainerPtr->iMimeType.get_cstr(), aPort->IncomingMsgQueueSize()));
1564     /*
1565      * An input port will call this when memory is available in the rtp
1566      * payload parser.  We may need to wake up the input data processing.
1567      */
1568     if (IsAdded())
1569     {
1570         PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
1571                                              "PVMFMediaLayerNode::freechunkavailable: - Calling RunIfNotReady"));
1572         RunIfNotReady();
1573     }
1574 }
1575 
HandlePortActivity(const PVMFPortActivity & aActivity)1576 void PVMFMediaLayerNode::HandlePortActivity(const PVMFPortActivity &aActivity)
1577 {
1578     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::PortActivity: port=0x%x, type=%d",
1579                          aActivity.iPort, aActivity.iType));
1580 
1581     PVMFMediaLayerPortContainer* portContainerPtr = NULL;
1582 
1583     if (aActivity.iType != PVMF_PORT_ACTIVITY_DELETED)
1584     {
1585         if (!GetPortContainer(aActivity.iPort, portContainerPtr))
1586         {
1587             ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1588             PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HPA: Error - GetPortContainer failed"));
1589             return;
1590         }
1591     }
1592 
1593     /*
1594      * A port is reporting some activity or state change.  This code
1595      * figures out whether we need to queue a processing event
1596      * for the AO, and/or report a node event to the observer.
1597      */
1598 
1599     switch (aActivity.iType)
1600     {
1601         case PVMF_PORT_ACTIVITY_CREATED:
1602             /*
1603              * Report port created info event to the node.
1604              */
1605             ReportInfoEvent(PVMFInfoPortCreated, (OsclAny*)aActivity.iPort);
1606             break;
1607 
1608         case PVMF_PORT_ACTIVITY_DELETED:
1609         {
1610             /*
1611              * Report port deleted info event to the node.
1612              */
1613             ReportInfoEvent(PVMFInfoPortDeleted, (OsclAny*)aActivity.iPort);
1614         }
1615         break;
1616 
1617         case PVMF_PORT_ACTIVITY_CONNECT:
1618             break;
1619 
1620         case PVMF_PORT_ACTIVITY_DISCONNECT:
1621             break;
1622 
1623         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
1624         {
1625             /*
1626              * An outgoing message was queued on this port.
1627              * Only output ports have outgoing messages in
1628              * this node
1629              */
1630             int32 portTag = portContainerPtr->tag;
1631             switch (portTag)
1632             {
1633                 case PVMF_MEDIALAYER_PORT_TYPE_OUTPUT:
1634                     if (portContainerPtr->oProcessOutgoingMessages)
1635                         QueuePortActivity(portContainerPtr, aActivity);
1636                     break;
1637 
1638                 default:
1639                     OSCL_ASSERT(false);
1640                     break;
1641             }
1642         }
1643         break;
1644 
1645         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
1646         {
1647             /*
1648              * An incoming message was queued on this port.
1649              * Input ports only get incoming messages in this
1650              * node
1651              */
1652             int32 portTag = portContainerPtr->tag;
1653 
1654             switch (portTag)
1655             {
1656                 case PVMF_MEDIALAYER_PORT_TYPE_INPUT:
1657                     if (portContainerPtr->oProcessIncomingMessages)
1658                         QueuePortActivity(portContainerPtr, aActivity);
1659                     break;
1660 
1661                 default:
1662                     OSCL_ASSERT(false);
1663                     break;
1664             }
1665         }
1666         break;
1667 
1668         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY:
1669         {
1670             int32 portTag = portContainerPtr->tag;
1671             switch (portTag)
1672             {
1673                 case PVMF_MEDIALAYER_PORT_TYPE_INPUT:
1674                     /*
1675                      * Input ports do not use their outgoing queues
1676                      * in this node.
1677                      */
1678                     OSCL_ASSERT(false);
1679                     break;
1680 
1681                 case PVMF_MEDIALAYER_PORT_TYPE_OUTPUT:
1682                 {
1683                     /*
1684                      * This implies that this output port cannot accept any more
1685                      * msgs on its outgoing queue. This implies that the corresponding
1686                      * input port must stop processing messages.
1687                      */
1688                     PVMFPortInterface* inPort = getPortCounterpart(portContainerPtr);
1689                     if (inPort != NULL)
1690                     {
1691                         PVMFMediaLayerPortContainer* inPortContainerPtr = NULL;
1692                         if (!GetPortContainer(inPort, inPortContainerPtr))
1693                         {
1694                             ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1695                             PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - GetPortContainer failed"));
1696                             return;
1697                         }
1698                         PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0, "PVMFMediaLayerNode::HPA: Output Port Queue Busy - Mime=%s",
1699                                                              inPortContainerPtr->iMimeType.get_cstr()));
1700                         inPortContainerPtr->oProcessIncomingMessages = false;
1701                     }
1702                     else
1703                     {
1704                         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1705                         PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - getPortCounterpart failed"));
1706                         return;
1707                     }
1708                 }
1709                 break;
1710 
1711                 default:
1712                     OSCL_ASSERT(false);
1713                     break;
1714             }
1715         }
1716         break;
1717 
1718         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
1719         {
1720             /*
1721              * Outgoing queue was previously busy, but is now ready.
1722              * We may need to schedule new processing events depending
1723              * on the port type.
1724              */
1725             int32 portTag = portContainerPtr->tag;
1726             switch (portTag)
1727             {
1728                 case PVMF_MEDIALAYER_PORT_TYPE_INPUT:
1729                     /*
1730                      * Input ports do not use their outgoing queues
1731                      * in this node.
1732                      */
1733                     OSCL_ASSERT(false);
1734                     break;
1735 
1736                 case PVMF_MEDIALAYER_PORT_TYPE_OUTPUT:
1737                 {
1738                     /*
1739                      * This implies that this output port can accept more
1740                      * msgs on its outgoing queue. This implies that the corresponding
1741                      * input port can start processing messages again.
1742                      */
1743                     PVMFPortInterface* inPort = getPortCounterpart(portContainerPtr);
1744                     if (inPort != NULL)
1745                     {
1746                         PVMFMediaLayerPortContainer* inPortContainerPtr = NULL;
1747                         if (!GetPortContainer(inPort, inPortContainerPtr))
1748                         {
1749                             ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1750                             PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - GetPortContainer failed"));
1751                             return;
1752                         }
1753                         PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0, "PVMFMediaLayerNode::HPA: Output Port Queue Ready - Mime=%s",
1754                                                              inPortContainerPtr->iMimeType.get_cstr()));
1755                         inPortContainerPtr->oProcessIncomingMessages = true;
1756                     }
1757                     else
1758                     {
1759                         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1760                         PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - getPortCounterpart failed"));
1761                         return;
1762                     }
1763                 }
1764                 break;
1765 
1766                 default:
1767                     OSCL_ASSERT(false);
1768                     break;
1769             }
1770             if (IsAdded())
1771             {
1772                 RunIfNotReady();
1773             }
1774         }
1775         break;
1776 
1777         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
1778         {
1779             /*
1780              * The connected port has become busy (its incoming queue is
1781              * busy).
1782              */
1783             int32 portTag = portContainerPtr->tag;
1784             switch (portTag)
1785             {
1786                 case PVMF_MEDIALAYER_PORT_TYPE_INPUT:
1787                     /*
1788                      * Input ports do not use their outgoing queues
1789                      * in this node.
1790                      */
1791                     OSCL_ASSERT(false);
1792                     break;
1793 
1794                 case PVMF_MEDIALAYER_PORT_TYPE_OUTPUT:
1795                 {
1796                     /*
1797                      * This implies that this output port cannot send any more
1798                      * msgs from its outgoing queue. It should stop processing
1799                      * messages till the connect port is ready.
1800                      */
1801                     portContainerPtr->oProcessOutgoingMessages = false;
1802                     PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0, "PVMFMediaLayerNode::HPA: Connected port busy - Mime=%s",
1803                                                          portContainerPtr->iMimeType.get_cstr()));
1804                     PVMFPortInterface* inPort = getPortCounterpart(portContainerPtr);
1805                     if (inPort != NULL)
1806                     {
1807                         PVMFMediaLayerPortContainer* inPortContainerPtr = NULL;
1808                         if (!GetPortContainer(inPort, inPortContainerPtr))
1809                         {
1810                             ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1811                             PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - GetPortContainer failed"));
1812                             return;
1813                         }
1814                         PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0, "PVMFMediaLayerNode::HPA: Connected port busy - Stop Input - Mime=%s",
1815                                                              inPortContainerPtr->iMimeType.get_cstr()));
1816                         if (checkOutputPortsBusy(inPortContainerPtr))
1817                         {
1818                             inPortContainerPtr->oProcessIncomingMessages = false;
1819                         }
1820                     }
1821                     else
1822                     {
1823                         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1824                         PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - getPortCounterpart failed"));
1825                         return;
1826                     }
1827                 }
1828                 break;
1829 
1830                 default:
1831                     OSCL_ASSERT(false);
1832                     break;
1833             }
1834         }
1835         break;
1836 
1837         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
1838         {
1839             /*
1840              * The connected port has transitioned from Busy to Ready.
1841              * It's time to start processing messages outgoing again.
1842              */
1843             int32 portTag = portContainerPtr->tag;
1844             switch (portTag)
1845             {
1846                 case PVMF_MEDIALAYER_PORT_TYPE_INPUT:
1847                     /*
1848                      * Input ports do not use their outgoing queues
1849                      * in this node.
1850                      */
1851                     OSCL_ASSERT(false);
1852                     break;
1853 
1854                 case PVMF_MEDIALAYER_PORT_TYPE_OUTPUT:
1855                 {
1856                     /*
1857                      * This implies that this output port can now send
1858                      * msgs from its outgoing queue. It can start processing
1859                      * messages now.
1860                      */
1861                     portContainerPtr->oProcessOutgoingMessages = true;
1862                     PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0, "PVMFMediaLayerNode::HPA: Connected port ready - Mime=%s",
1863                                                          portContainerPtr->iMimeType.get_cstr()));
1864                     PVMFPortInterface* inPort = getPortCounterpart(portContainerPtr);
1865                     if (inPort != NULL)
1866                     {
1867                         PVMFMediaLayerPortContainer* inPortContainerPtr = NULL;
1868                         if (!GetPortContainer(inPort, inPortContainerPtr))
1869                         {
1870                             ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1871                             PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - GetPortContainer failed"));
1872                             return;
1873                         }
1874                         PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0, "PVMFMediaLayerNode::HPA: Connected port busy - Resume Input - Mime=%s",
1875                                                              inPortContainerPtr->iMimeType.get_cstr()));
1876                         inPortContainerPtr->oProcessIncomingMessages = true;
1877                     }
1878                     else
1879                     {
1880                         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
1881                         PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::HandlePortActivity: Error - getPortCounterpart failed"));
1882                         return;
1883                     }
1884                 }
1885                 break;
1886 
1887                 default:
1888                     OSCL_ASSERT(false);
1889                     break;
1890             }
1891             if (IsAdded())
1892             {
1893                 RunIfNotReady();
1894             }
1895         }
1896         break;
1897 
1898 
1899         default:
1900             break;
1901     }
1902 }
1903 
1904 /*
1905  * called by the AO to process a port activity message
1906  */
ProcessPortActivity(PVMFMediaLayerPortContainer * aPortContainer)1907 bool PVMFMediaLayerNode::ProcessPortActivity(PVMFMediaLayerPortContainer* aPortContainer)
1908 {
1909     PVMFStatus status = PVMFSuccess;
1910     switch (aPortContainer->tag)
1911     {
1912         case PVMF_MEDIALAYER_PORT_TYPE_OUTPUT:
1913         {
1914             if ((aPortContainer->oProcessOutgoingMessages) &&
1915                     (aPortContainer->iPort->OutgoingMsgQueueSize() > 0))
1916             {
1917                 status = ProcessOutgoingMsg(aPortContainer);
1918             }
1919             else
1920             {
1921                 status = PVMFErrBusy;
1922             }
1923         }
1924         break;
1925 
1926         case PVMF_MEDIALAYER_PORT_TYPE_INPUT:
1927         {
1928             /*
1929              * attempt to send any left over payloads first
1930              * If both output port payload msg is not available or outgoing queue is busy,
1931              * oProcessIncomingMessages is set to false and PVMFErrBusy is replied.
1932              */
1933             status = sendAccessUnits(aPortContainer);
1934             /*
1935              * Process any incoming messages if the output ports are not busy
1936              * and if there are media msgs available
1937              */
1938             if (status == PVMFSuccess && aPortContainer->iPort->IncomingMsgQueueSize() > 0)
1939             {
1940                 if (aPortContainer->oProcessIncomingMessages)
1941                 {
1942                     status = ProcessIncomingMsg(aPortContainer);
1943                 }
1944                 else
1945                 {
1946                     status = PVMFErrBusy;
1947                 }
1948             }
1949         }
1950         break;
1951 
1952         default:
1953             OSCL_ASSERT(false);
1954             break;
1955     }
1956 
1957     /* report a failure in port processing */
1958     if (status != PVMFErrBusy && status != PVMFSuccess)
1959     {
1960         PVMF_MLNODE_LOGERROR((0,
1961                               "PVMFMediaLayerNode::ProcessPortActivity: Error - ProcessPortActivity failed. port=0x%x",
1962                               aPortContainer->iPort));
1963         ReportErrorEvent(PVMFErrPortProcessing);
1964     }
1965 
1966     /* return true if we processed an activity */
1967     return (status != PVMFErrBusy);
1968 }
1969 
ProcessIncomingMsg(PVMFMediaLayerPortContainer * pinputPort)1970 PVMFStatus PVMFMediaLayerNode::ProcessIncomingMsg(PVMFMediaLayerPortContainer* pinputPort)
1971 {
1972     PVMFStatus status;
1973 
1974     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::ProcessIncomingMsg: aPort=0x%x",
1975                          pinputPort->iPort));
1976 
1977     if (pinputPort->tag != PVMF_MEDIALAYER_PORT_TYPE_INPUT)
1978     {
1979         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(pinputPort->iPort));
1980         PVMF_MLNODE_LOGERROR((0,
1981                               "PVMFMediaLayerNode::ProcessIncomingMsg: Error - Not an Input Port"));
1982         return PVMFFailure;
1983     }
1984 
1985     //
1986     // Check if the output port is busy.
1987     //
1988     if (checkOutputPortsBusy(pinputPort))
1989     {
1990         PVUuid eventuuid = PVMFMediaLayerNodeEventTypeUUID;
1991 
1992         PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
1993                                              "PVMFMediaLayerNode::ProcessIncomingMsg: Cant Send Data - Output Queue Busy"));
1994         /*
1995          * Processing will resume when we get outgoing queue ready notification
1996          * in the port activity
1997          */
1998         pinputPort->oProcessIncomingMessages = false;
1999         return PVMFErrBusy;
2000     }
2001 
2002     //
2003     // dequeue the message
2004     // if it is EOS leave it on the port queue until we are
2005     // done sending all payloads
2006     //
2007     PVMFSharedMediaMsgPtr msgIn;
2008     PVMFSharedMediaDataPtr peekDataPtr;
2009     if (!oEOSsendunits)
2010     {
2011         bool oIsEOSCmd = false;
2012 
2013         PVMFMediaLayerPort* mlPort =
2014             OSCL_STATIC_CAST(PVMFMediaLayerPort*, pinputPort->iPort);
2015         status = mlPort->peekHead(peekDataPtr, oIsEOSCmd);
2016         if (status != PVMFSuccess)
2017         {
2018             ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(pinputPort->iPort));
2019             PVMF_MLNODE_LOGERROR((0,
2020                                   "0x%x PVMFMediaLayerNode::ProcessIncomingMsg: Error - peekHead failed", this));
2021             return status;
2022         }
2023         if (oIsEOSCmd == true)
2024         {
2025             PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::ProcessIncomingMsg() Detect EOS message"));
2026 
2027             //EOS msg is received. Before sending EOS, we send left payload msgs.
2028             bool IsAccessUnitsEmpty = false;
2029             status = checkPortCounterpartAccessUnitQueue(pinputPort, &IsAccessUnitsEmpty);
2030             if (status != PVMFSuccess)
2031             {
2032                 ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(pinputPort->iPort));
2033                 PVMF_MLNODE_LOGERROR((0,
2034                                       "0x%x PVMFMediaLayerNode::ProcessIncomingMsg: Error - checkPortCounterpartAccessUnitQueue failed", this));
2035                 return status;
2036             }
2037             if (IsAccessUnitsEmpty)
2038             {
2039                 oEOSsendunits = true;
2040                 return sendAccessUnits(pinputPort);
2041             }
2042         }
2043     }
2044     else
2045     {
2046         bool IsAccessUnitsEmpty = false;
2047         status = checkPortCounterpartAccessUnitQueue(pinputPort, &IsAccessUnitsEmpty);
2048         if (status != PVMFSuccess)
2049         {
2050             ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(pinputPort->iPort));
2051             PVMF_MLNODE_LOGERROR((0,
2052                                   "0x%x PVMFMediaLayerNode::ProcessIncomingMsg: Error - checkPortCounterpartAccessUnitQueue failed", this));
2053             return status;
2054         }
2055         if (IsAccessUnitsEmpty)
2056         {
2057             return sendAccessUnits(pinputPort);
2058         }
2059         else
2060         {
2061             oEOSsendunits = false;
2062         }
2063     }
2064     status = pinputPort->iPort->DequeueIncomingMsg(msgIn);
2065     if (status != PVMFSuccess)
2066     {
2067         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(pinputPort->iPort));
2068         PVMF_MLNODE_LOGERROR((0,
2069                               "0x%x PVMFMediaLayerNode::ProcessIncomingMsg: Error - DequeueIncomingMsg failed", this));
2070         return status;
2071     }
2072     //
2073     // what kind of demuxing are we doing?
2074     //
2075     bool isOneToN = pinputPort->iIsOneToN;
2076 
2077     PVUid32 msgFormatID = msgIn->getFormatID();
2078 
2079     if (msgFormatID > PVMF_MEDIA_CMD_FORMAT_IDS_START)
2080     {
2081         if (msgFormatID == PVMF_MEDIA_CMD_BOS_FORMAT_ID)
2082         {
2083             iStreamID = msgIn->getStreamID();
2084             PVMF_MLNODE_LOGDATATRAFFIC_IN((0, "PVMFMediaLayerNode::ProcessInputMsg_OneToN: Sending MediaCmd - BOS Received"));
2085             PVMF_MLNODE_LOG_REPOS((0, "PVMFMediaLayerNode::ProcessInputMsg_OneToN: Sending MediaCmd - BOS Received"));
2086             // send BOS on every output port
2087             for (uint i = 0; i < pinputPort->vCounterPorts.size(); i++)
2088             {
2089                 PVMFMediaLayerPortContainer* poutPort = &this->iPortParamsQueue[pinputPort->vCounterPorts[i]];
2090                 // set BOS Timestamp to last media ts sent on this port
2091                 msgIn->setTimestamp(poutPort->iContinuousTimeStamp);
2092                 status = poutPort->iPort->QueueOutgoingMsg(msgIn);
2093 
2094                 if (status != PVMFSuccess)
2095                 {
2096                     PVMF_MLNODE_LOGERROR((0,
2097                                           "0x%x PVMFMediaLayerNode::ProcessInputMsg_OneToN: "
2098                                           "Error - QueueOutgoingMsg for BOS failed", this));
2099                     return status;
2100                 }
2101                 else
2102                 {
2103 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
2104                     uint32 timebase32 = 0;
2105                     uint32 clientClock32 = 0;
2106                     bool overflowFlag = false;
2107                     iClientPlayBackClock->GetCurrentTime32(clientClock32, overflowFlag,
2108                                                            PVMF_MEDIA_CLOCK_MSEC, timebase32);
2109                     PVMF_MLNODE_LOGDATATRAFFIC_OUT((0,
2110                                                     "PVMFMediaLayerNode::ProcessInputMsg_OneToN: Sending BOS - MimeType=%s Clock=%d",
2111                                                     poutPort->iMimeType.get_cstr(), clientClock32));
2112                     PVMF_MLNODE_LOG_REPOS((0,
2113                                            "PVMFMediaLayerNode::ProcessInputMsg_OneToN: Sending BOS - MimeType=%s Clock=%d",
2114                                            poutPort->iMimeType.get_cstr(), clientClock32));
2115 #endif
2116                 }
2117             }
2118 
2119         }
2120         else if (msgFormatID == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
2121         {
2122             //
2123             // check for EOS
2124             //
2125             // Upstream EOS recvd
2126             pinputPort->oUpStreamEOSRecvd = true;
2127             pinputPort->oEOSReached = true;
2128 
2129             // send EOS on every output port
2130             for (uint i = 0; i < pinputPort->vCounterPorts.size(); i++)
2131             {
2132                 PVMFMediaLayerPortContainer* poutPort = &this->iPortParamsQueue[pinputPort->vCounterPorts[i]];
2133                 // set EOS Timestamp to last media ts sent on this port
2134                 if (poutPort->oDisableTrack == false && poutPort->oEOSReached == false)
2135                 {
2136                     poutPort->iContinuousTimeStamp += PVMF_MEDIA_LAYER_NODE_ASF_REPOS_TIME_OFFSET_IN_MS;
2137                     msgIn->setTimestamp(poutPort->iContinuousTimeStamp);
2138                     msgIn->setStreamID(iStreamID);
2139                     status = poutPort->iPort->QueueOutgoingMsg(msgIn);
2140 
2141                     if (status != PVMFSuccess)
2142                     {
2143                         PVMF_MLNODE_LOGERROR((0,
2144                                               "0x%x PVMFMediaLayerNode::ProcessInputMsg_OneToN: "
2145                                               "Error - QueueOutgoingMsg for EOS failed", this));
2146                         return status;
2147                     }
2148                     else
2149                     {
2150 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
2151                         uint32 timebase32 = 0;
2152                         uint32 clientClock32 = 0;
2153                         bool overflowFlag = false;
2154                         iClientPlayBackClock->GetCurrentTime32(clientClock32, overflowFlag,
2155                                                                PVMF_MEDIA_CLOCK_MSEC, timebase32);
2156                         PVMF_MLNODE_LOGDATATRAFFIC_OUT((0,
2157                                                         "PVMFMediaLayerNode::ProcessInputMsg_OneToN: Sending EOS - MimeType=%s, StreamId=%d, Clock=%d",
2158                                                         pinputPort->iMimeType.get_cstr(),
2159                                                         msgIn->getStreamID(),
2160                                                         clientClock32));
2161 #endif
2162                     }
2163                 }
2164             }
2165         }
2166         else
2167         {
2168 
2169             /* unknown command - pass it along */
2170             for (uint i = 0; i < pinputPort->vCounterPorts.size(); i++)
2171             {
2172                 PVMFMediaLayerPortContainer* poutPort = &this->iPortParamsQueue[pinputPort->vCounterPorts[i]];
2173                 status = poutPort->iPort->QueueOutgoingMsg(msgIn);
2174 
2175                 if (status != PVMFSuccess)
2176                 {
2177                     PVMF_MLNODE_LOGERROR((0,
2178                                           "0x%x PVMFMediaLayerNode::ProcessInputMsg_OneToN: "
2179                                           "Error - QueueOutgoingMsg for MediaCmd=%d failed", msgFormatID, this));
2180                     return status;
2181                 }
2182                 else
2183                 {
2184                     poutPort->iReConfig = false;
2185 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
2186                     uint32 timebase32 = 0;
2187                     uint32 clientClock32 = 0;
2188                     bool overflowFlag = false;
2189                     iClientPlayBackClock->GetCurrentTime32(clientClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32);
2190                     PVMF_MLNODE_LOGDATATRAFFIC_OUT((0,
2191                                                     "PVMFMediaLayerNode::ProcessInputMsg_OneToN: Sending MediaCmd - CmdId=%d, MimeType=%s Clock=%2d",
2192                                                     msgFormatID, pinputPort->iMimeType.get_cstr(), clientClock32));
2193 #endif
2194                 }
2195             }
2196         }
2197         return status;
2198     }
2199 
2200     //If error is detected in track config info, EOS should be sent.
2201     for (uint k = 0; k < pinputPort->vCounterPorts.size(); k++)
2202     {
2203         PVMFMediaLayerPortContainer* poutPort = &this->iPortParamsQueue[pinputPort->vCounterPorts[k]];
2204         if (poutPort->oDisableTrack == true && poutPort->oDetectBrokenTrack == true)
2205         {
2206             poutPort->oDetectBrokenTrack = false;
2207             poutPort->iFirstFrameAfterRepositioning = false;
2208             poutPort->iContinuousTimeStamp += PVMF_MEDIA_LAYER_NODE_ASF_REPOS_TIME_OFFSET_IN_MS;
2209             status = sendEndOfTrackCommand(poutPort);
2210             if (status != PVMFSuccess)
2211             {
2212                 PVMF_MLNODE_LOGERROR((0,
2213                                       "0x%x PVMFMediaLayerNode::ProcessInputMsg_OneToN: "
2214                                       "Error - QueueOutgoingMsg for EOS failed", this));
2215                 return status;
2216             }
2217         }
2218     }
2219 
2220     if (pinputPort->oEOSReached == true)
2221     {
2222         PVMF_MLNODE_LOGWARNING((0,
2223                                 "PVMFMediaLayerNode::ProcessInputMsg_OneToN: "
2224                                 "Msg too late, discard - EOS already sent"));
2225         return PVMFSuccess;
2226     }
2227 
2228     //
2229     // unpack the payload data
2230     //
2231     PVMFSharedMediaDataPtr dataIn;
2232     convertToPVMFMediaData(dataIn, msgIn);
2233     iPayLoad.vfragments.clear();
2234     iPayLoad.stream = dataIn->getStreamID();
2235     iPayLoad.marker = (dataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT);
2236     if (dataIn->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT)
2237         iPayLoad.randAccessPt = true;
2238     iPayLoad.sequence = dataIn->getSeqNum();
2239     iPayLoad.timestamp = dataIn->getTimestamp();
2240     pinputPort->iCurrFormatId = dataIn->getFormatID();
2241     OsclRefCounterMemFrag fsi;
2242     dataIn->getFormatSpecificInfo(fsi);
2243 
2244     pinputPort->iCurrFormatSpecInfo = fsi;
2245 
2246     for (uint f = 0; f < dataIn->getNumFragments(); f++)
2247     {
2248         OsclRefCounterMemFrag memFrag;
2249         dataIn->getMediaFragment(f, memFrag);
2250         iPayLoad.vfragments.push_back(memFrag);
2251     }
2252 
2253 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
2254     uint32 inputDataSize = 0;
2255     /* Get input size for logging */
2256     uint32 inputNumFrags = dataIn->getNumFragments();
2257     for (uint32 i = 0; i < inputNumFrags; i++)
2258     {
2259         OsclRefCounterMemFrag memFrag;
2260         dataIn->getMediaFragment(i, memFrag);
2261         inputDataSize += memFrag.getMemFragSize();
2262     }
2263 
2264     uint32 timebase32 = 0;
2265     uint32 clientClock32 = 0;
2266     bool overflowFlag = false;
2267     iClientPlayBackClock->GetCurrentTime32(clientClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32);
2268     PVMF_MLNODE_LOGDATATRAFFIC_IN((0,
2269                                    "PVMFMediaLayerNode::ProcessInputMsg_OneToN - Input: MimeType=%s, TS=%d, SEQNUM=%d, SIZE=%d, Clock=%d",
2270                                    pinputPort->iMimeType.get_cstr(), msgIn->getTimestamp(), msgIn->getSeqNum(), inputDataSize, clientClock32));
2271 #endif
2272 
2273     PVMFMediaLayerPortContainer* poutPort = NULL;
2274     bool bRet = false;
2275     if (isOneToN == false)
2276     {
2277         bRet = GetPortContainer(getPortCounterpart(pinputPort), poutPort);
2278     }
2279 
2280     //
2281     // parse the payload data until all payloads are extracted.
2282     // in case of http streaming, we parse audio & video data to each output port access units.
2283     //
2284     PayloadParserStatus retVal = PayloadParserStatus_InputNotExhausted;
2285     while (retVal == PayloadParserStatus_InputNotExhausted)
2286     {
2287         {
2288             if (bRet)
2289             {
2290                 retVal =
2291                     pinputPort->iPayLoadParser->Parse(iPayLoad,
2292                                                       poutPort->vAccessUnits);
2293             }
2294         }
2295 
2296         if ((retVal == PayloadParserStatus_MemorAllocFail) ||
2297                 (retVal == PayloadParserStatus_Failure))
2298         {
2299             PVUuid eventuuid = PVMFMediaLayerNodeEventTypeUUID;
2300             int32 infocode = PVMFMediaLayerNodePayloadParserError;
2301             ReportInfoEvent(PVMFErrProcessing, (OsclAny*)(&(pinputPort->iMimeType)), &eventuuid, &infocode);
2302             PVMF_MLNODE_LOGWARNING((0,
2303                                     "PVMFMediaLayerNode::ProcessIncomingMsg: Error - parse Payload failed ErrCode = %d", retVal));
2304             status = PVMFFailure;
2305         }
2306     }
2307 
2308     if (retVal != PayloadParserStatus_Success)
2309     {
2310         // no data ready yet
2311         return PVMFSuccess;
2312     }
2313 
2314     return sendAccessUnits(pinputPort);
2315 }
2316 
2317 
sendAccessUnits(PVMFMediaLayerPortContainer * pinputPort)2318 PVMFStatus PVMFMediaLayerNode::sendAccessUnits(PVMFMediaLayerPortContainer* pinputPort)
2319 {
2320 
2321     PVMFStatus status = PVMFSuccess;
2322     bool checkAccessUnitsSize = false;
2323 
2324     for (uint i = 0; i < pinputPort->vCounterPorts.size(); i++)
2325     {
2326         PVMFMediaLayerPortContainer* poutPort =
2327             &this->iPortParamsQueue[pinputPort->vCounterPorts[i]];
2328 
2329         if (poutPort->vAccessUnits.size() > 0)
2330         {
2331             checkAccessUnitsSize = true;
2332 
2333             if ((poutPort->iPort->IsOutgoingQueueBusy() == false) &&
2334                     (poutPort->ipFragGroupAllocator->IsMsgAvailable() == true))
2335             {
2336                 //send each access unit to its respective port
2337                 status = dispatchAccessUnits(pinputPort, poutPort);
2338             }
2339             else
2340             {
2341                 PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
2342                                                      "PVMFMediaLayerNode::sendAccessUnits: Port / Mem Pool Busy - Mime=%s vQ=%d",
2343                                                      poutPort->iMimeType.get_cstr(), poutPort->vAccessUnits.size()));
2344                 status = PVMFErrBusy;
2345             }
2346             if (status == PVMFErrBusy)
2347             {
2348                 // Processing will resume when we get freechunkavailable notice from the port.
2349                 pinputPort->oProcessIncomingMessages = false;
2350                 {
2351                     if (!poutPort->ipFragGroupAllocator->IsMsgAvailable())
2352                     {
2353                         poutPort->ipFragGroupAllocator->notifyfreechunkavailable(*((PVMFMediaLayerPort*)pinputPort->iPort));
2354                         PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
2355                                                              "PVMFMediaLayerNode::sendAccessUnits: Calling notifyfreechunkavailable - Mime=%s vQ=%d",
2356                                                              poutPort->iMimeType.get_cstr(), poutPort->vAccessUnits.size()));
2357                     }
2358                 }
2359                 if (pinputPort->oProcessIncomingMessages == false)
2360                 {
2361                     // no media msgs available on any output port.
2362                     // then we set oProcessIncomingMessages as false not to call ProcessIncomingMsg.
2363                     status = PVMFErrBusy;
2364                     break;
2365                 }
2366                 else
2367                 {
2368                     //at least, media msgs on one output port is available and we set oProcessIncomingMessages to true again.
2369                     status = PVMFSuccess;
2370                     continue;
2371                 }
2372             }
2373         }
2374     }
2375     //in case that both output port vAccessUnits is empty and oProcessIncomingMessages is set as false,
2376     //we never set oProcessIncomingMessages to true and cannot call ProcessIncomingMsg.
2377     //to escape this situation, we check IsMsgAvailable for both output port here.
2378     if (checkAccessUnitsSize == false)
2379     {
2380         if (pinputPort->oProcessIncomingMessages == false)
2381         {
2382             if (pinputPort->oProcessIncomingMessages == false)
2383             {
2384                 // no media msgs available on any output port
2385                 status = PVMFErrBusy;
2386             }
2387             else
2388             {
2389                 //at least, media msgs on one output port is available and we set oProcessIncomingMessages to true again.
2390                 status = PVMFSuccess;
2391             }
2392         }
2393     }
2394     return status;
2395 }
2396 
dispatchAccessUnits(PVMFMediaLayerPortContainer * pinputPort,PVMFMediaLayerPortContainer * poutPort)2397 PVMFStatus PVMFMediaLayerNode::dispatchAccessUnits(PVMFMediaLayerPortContainer* pinputPort,
2398         PVMFMediaLayerPortContainer* poutPort)
2399 {
2400     PVMFStatus status = PVMFSuccess;
2401     //
2402     // send each access unit to its respective port
2403     //
2404     typedef Oscl_Vector<IPayloadParser::Payload, OsclMemAllocator>::iterator iterator_type;
2405     iterator_type it;
2406     for (it = poutPort->vAccessUnits.begin(); it != poutPort->vAccessUnits.end(); it++)
2407     {
2408         // check out port status
2409         if (poutPort->iPort->IsOutgoingQueueBusy())
2410         {
2411             PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
2412                                                  "PVMFMediaLayerNode::dispatchAccessUnits: Output Port Busy - Mime=%s", poutPort->iMimeType.get_cstr()));
2413             status = PVMFErrBusy;
2414             break;
2415         }
2416         //
2417         // check if a media message is available
2418         //
2419         if (!poutPort->ipFragGroupAllocator->IsMsgAvailable())
2420         {
2421             PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0, "PVMFMediaLayerNode::dispatchAccessUnits: Can't send - Waiting for free buffers - Mime=%s vQ=%d", poutPort->iMimeType.get_cstr(), poutPort->vAccessUnits.size()));
2422             status = PVMFErrBusy;
2423             break;
2424         }
2425 
2426         // retrieve a data implementation
2427         OsclSharedPtr<PVMFMediaDataImpl> mediaDataImplOut;
2428         bool retVal;
2429         retVal = Allocate(mediaDataImplOut, poutPort);
2430 
2431         if (retVal == false)
2432         {
2433             status = PVMFErrNoMemory;
2434             break;
2435         }
2436 
2437         // Once we detect received DATA is same as reconfig streamID, we send reconfig msg first.
2438         // Reconfig streamID is informed from SM node at switchstream.
2439         if (poutPort->iReConfig == true && poutPort->oReconfigId == it->stream)
2440         {
2441             if (poutPort->oMsgReconfig.GetRep() != NULL)
2442             {
2443                 PVMFSharedMediaDataPtr mediaData;
2444                 convertToPVMFMediaData(mediaData, poutPort->oMsgReconfig);
2445 
2446                 status = poutPort->iPort->QueueOutgoingMsg(poutPort->oMsgReconfig);
2447 
2448                 if (status != PVMFSuccess)
2449                 {
2450                     PVMF_MLNODE_LOGERROR((0,
2451                                           "0x%x PVMFMediaLayerNode::dispatchAccessUnits: "
2452                                           "Error - QueueOutgoingMsg for ReConfig failed", this));
2453                     return status;
2454                 }
2455                 else
2456                 {
2457                     poutPort->iReConfig = false;
2458                     poutPort->oReconfigId = 0;
2459                     poutPort->oMsgReconfig.Unbind();
2460 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
2461                     uint32 timebase32 = 0;
2462                     uint32 clientClock32 = 0;
2463                     bool overflowFlag = false;
2464                     iClientPlayBackClock->GetCurrentTime32(clientClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32);
2465                     PVMF_MLNODE_LOGDATATRAFFIC_OUT((0,
2466                                                     "PVMFMediaLayerNode::dispatchAccessUnits: Sending ReConfig - MimeType=%s Clock=%2d",
2467                                                     poutPort->iMimeType.get_cstr(), clientClock32));
2468 #endif
2469                 }
2470             }
2471             else
2472             {
2473                 poutPort->iReConfig = false;
2474                 PVUuid eventuuid = PVMFMediaLayerNodeEventTypeUUID;
2475                 int32 infocode = PVMFMediaLayerNodePayloadParserError;
2476                 ReportErrorEvent(PVMFErrResourceConfiguration, (OsclAny*)(&(poutPort->iMimeType)), &eventuuid, &infocode);
2477 
2478                 PVMF_MLNODE_LOGDATATRAFFIC_E((0, "PVMFMediaLayerNode::dispatchAccessUnits: Error - We don't receive Reconfig msg yet - Mime=%s vQ=%d", poutPort->iMimeType.get_cstr(), poutPort->vAccessUnits.size()));
2479                 SetState(EPVMFNodeError);
2480                 status = PVMFFailure;
2481                 break;
2482             }
2483         }
2484 
2485 
2486         // fill the data implementation with the contents of the payload structure
2487         uint32 markerInfo = 0;
2488         if (it->marker == 1)
2489         {
2490             markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_M_BIT;
2491         }
2492         if (it->randAccessPt == true)
2493         {
2494             markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT;
2495         }
2496 
2497         if (it->endOfNAL)
2498         {
2499             markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT;
2500         }
2501 
2502         mediaDataImplOut->setMarkerInfo(markerInfo);
2503         mediaDataImplOut->setRandomAccessPoint(it->randAccessPt);
2504         for (uint j = 0; j < it->vfragments.size(); j++)
2505         {
2506             mediaDataImplOut->appendMediaFragment(it->vfragments[j]);
2507         }
2508 
2509         // create a data message
2510         PVMFMediaMsgHeader newMsgHeader;
2511         newMsgHeader.format_id = pinputPort->iCurrFormatId;
2512         PVMFSharedMediaDataPtr mediaDataOut =
2513             PVMFMediaData::createMediaData(mediaDataImplOut, &newMsgHeader);
2514         /*
2515          * Could happen during bitstream switching,
2516          * asf payload parser starts seq num for each stream from zero
2517          */
2518         if (it->sequence < poutPort->iPrevMsgSeqNum)
2519         {
2520             poutPort->iPrevMsgSeqNum++;
2521             it->sequence = poutPort->iPrevMsgSeqNum;
2522         }
2523         else
2524         {
2525             poutPort->iPrevMsgSeqNum = it->sequence;
2526         }
2527         mediaDataOut->setSeqNum(it->sequence);
2528         mediaDataOut->setStreamID(it->stream);
2529         mediaDataOut->setTimestamp(it->timestamp);
2530         mediaDataOut->setFormatSpecificInfo(pinputPort->iCurrFormatSpecInfo);
2531 
2532         /* Decrypt sample if protected */
2533         if (iDecryptionInterface != NULL)
2534         {
2535             if (iDecryptionInterface->CanDecryptInPlace())
2536             {
2537                 PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::dispatchAccessUnits() Decryption is needed"));
2538 
2539                 /* Retrieve memory fragment to write to */
2540                 OsclRefCounterMemFrag refCtrMemFragOut;
2541                 OsclMemoryFragment memFragOut;
2542                 uint32 num = mediaDataOut->getNumFragments();
2543                 uint32 totalPayloadSize = mediaDataOut->getFilledSize();
2544                 uint8* srcDrmPtr = srcPtr;
2545                 uint32 payloadSize = 0;
2546 
2547                 for (uint32 i = 0; i < num; i++)
2548                 {
2549                     mediaDataOut->getMediaFragment(i, refCtrMemFragOut);
2550                     memFragOut.ptr = refCtrMemFragOut.getMemFrag().ptr;
2551                     payloadSize = refCtrMemFragOut.getMemFrag().len;
2552                     oscl_memcpy(srcDrmPtr, (uint8*)(memFragOut.ptr), (payloadSize*sizeof(uint8)));
2553 
2554                     srcDrmPtr += payloadSize;
2555                     payloadSize = 0;
2556 
2557                 }
2558 
2559                 if (totalPayloadSize > maxPacketSize)
2560                 {
2561                     PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::dispatchAccessUnits() - PayloadSize is bigger than Packet size"));
2562                     return PVMFFailure;
2563                 }
2564 
2565                 bool oDecryptRet =
2566                     iDecryptionInterface->DecryptAccessUnit(srcPtr,
2567                                                             totalPayloadSize);
2568                 srcDrmPtr = srcPtr;
2569                 for (uint32 j = 0; j < num; j++)
2570                 {
2571                     mediaDataOut->getMediaFragment(j, refCtrMemFragOut);
2572                     memFragOut.ptr = refCtrMemFragOut.getMemFrag().ptr;
2573                     payloadSize = refCtrMemFragOut.getMemFrag().len;
2574                     oscl_memcpy((uint8*)(memFragOut.ptr), srcDrmPtr, (payloadSize*sizeof(uint8)));
2575 
2576                     srcDrmPtr += payloadSize;
2577                     payloadSize = 0;
2578 
2579                 }
2580                 if (oDecryptRet != true)
2581                 {
2582                     PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::dispatchAccessUnits() - Decrypt Sample Failed"));
2583                     return PVMFFailure;
2584                 }
2585 
2586                 PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::dispatchAccessUnits() Decryption completed : payload lenght=%d", totalPayloadSize));
2587             }
2588             else
2589             {
2590                 /* We always decrpt in place for Janus */
2591                 PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::dispatchAccessUnits() - Inplace Decrypt Not available"));
2592                 OSCL_ASSERT(false);
2593             }
2594         }
2595 
2596         // queue the message
2597         PVMFSharedMediaMsgPtr msgOut;
2598         convertToPVMFMediaMsg(msgOut, mediaDataOut);
2599 
2600 
2601         // send the message
2602         msgOut->setStreamID(iStreamID);
2603         status = poutPort->iPort->QueueOutgoingMsg(msgOut);
2604 
2605         if (status == PVMFErrBusy)
2606         {
2607             PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
2608                                                  "PVMFMediaLayerNode::dispatchAccessUnits: Outgoing Queue Busy - MimeType=%s", poutPort->iMimeType.get_cstr()));
2609             break;
2610         }
2611         else if (status != PVMFSuccess)
2612         {
2613             PVMF_MLNODE_LOGERROR((0,
2614                                   "0x%x PVMFMediaLayerNode::sendAccessUnits: "
2615                                   "Error - QueueOutgoingMsg failed", this));
2616             break;
2617         }
2618         else
2619         {
2620 #if (PVLOGGER_INST_LEVEL > PVLOGMSG_INST_LLDBG)
2621             if (oPortDataLog)
2622             {
2623                 LogMediaData(mediaDataOut, pinputPort->iPort);
2624             }
2625 
2626             uint32 timebase32 = 0;
2627             uint32 clientClock32 = 0;
2628             bool overflowFlag = false;
2629             iClientPlayBackClock->GetCurrentTime32(clientClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32);
2630 
2631             /* Get size for log purposes */
2632             uint32 numFrags = mediaDataOut->getNumFragments();
2633             uint32 size = 0;
2634             OsclRefCounterMemFrag memFrag;
2635             for (uint32 sizecount = 0; sizecount < numFrags; sizecount++)
2636             {
2637                 mediaDataOut->getMediaFragment(sizecount, memFrag);
2638                 size += memFrag.getMemFragSize();
2639             }
2640             PVMF_MLNODE_LOGDATATRAFFIC_OUT((0,
2641                                             "PVMFMediaLayerNode::dispatchAccessUnits: "
2642                                             "SSRC=%d, MimeType=%s SIZE=%d, TS=%d, SEQNUM=%d, MBIT=%d, KEY=%d, Clock=%d Delta=%d",
2643                                             msgOut->getStreamID(), poutPort->iMimeType.get_cstr(),
2644                                             size, msgOut->getTimestamp(), msgOut->getSeqNum(),
2645                                             (mediaDataOut->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_M_BIT),
2646                                             (mediaDataOut->getMarkerInfo() & PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT),
2647                                             clientClock32, (msgOut->getTimestamp() - clientClock32)));
2648 #endif
2649         }
2650     }
2651     // clear payloads successfully sent
2652     if (it != poutPort->vAccessUnits.begin())
2653     {
2654         // there is something to delete (if it == v.begin() then nothing was processed in the loop)
2655         it = poutPort->vAccessUnits.erase(poutPort->vAccessUnits.begin(), it);
2656     }
2657     return status;
2658 }
2659 
Allocate(OsclSharedPtr<PVMFMediaDataImpl> & mediaDataImplOut,PVMFMediaLayerPortContainer * poutPort)2660 bool PVMFMediaLayerNode::Allocate(OsclSharedPtr<PVMFMediaDataImpl>& mediaDataImplOut, PVMFMediaLayerPortContainer* poutPort)
2661 {
2662     int32 err;
2663     OSCL_TRY_NO_TLS(iOsclErrorTrapImp, err, mediaDataImplOut = poutPort->ipFragGroupAllocator->allocate());
2664     OSCL_ASSERT(err == OsclErrNone); // we just checked that a message is available
2665 
2666     if (err != OsclErrNone)
2667     {
2668         return false;
2669     }
2670     return true;
2671 }
2672 
checkOutputPortsBusy(PVMFMediaLayerPortContainer * pinputPort)2673 bool PVMFMediaLayerNode::checkOutputPortsBusy(PVMFMediaLayerPortContainer* pinputPort)
2674 {
2675     OSCL_ASSERT(pinputPort->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT);
2676 
2677     // check each output port's queue status
2678     // return true only if ALL output ports are busy
2679     for (uint i = 0; i < pinputPort->vCounterPorts.size(); i++)
2680     {
2681         if (iPortParamsQueue[pinputPort->vCounterPorts[i]].iPort->IsOutgoingQueueBusy() == false)
2682         {
2683             return false;
2684         }
2685     }
2686 
2687     return true;
2688 }
2689 
ProcessOutgoingMsg(PVMFMediaLayerPortContainer * aPortContainer)2690 PVMFStatus PVMFMediaLayerNode::ProcessOutgoingMsg(PVMFMediaLayerPortContainer* aPortContainer)
2691 {
2692     PVMFPortInterface* aPort = aPortContainer->iPort;
2693     PVMF_MLNODE_LOGINFO((0, "0x%x PVMFMediaLayerNode::ProcessOutgoingMsg: aPort=0x%x", this, aPort));
2694 
2695     PVMFStatus status;
2696     if (aPortContainer->tag == PVMF_MEDIALAYER_PORT_TYPE_OUTPUT)
2697     {
2698         /*
2699          * If connected port is busy, the outgoing message cannot be process. It will be
2700          * queued to be processed again after receiving PORT_ACTIVITY_CONNECTED_PORT_READY
2701          * from this port.
2702          */
2703         if (aPort->IsConnectedPortBusy())
2704         {
2705             PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
2706                                                  "0x%x PVMFMediaLayerNode::ProcessOutgoingMsg: Connected port is busy", this));
2707             aPortContainer->oProcessOutgoingMessages = false;
2708             return PVMFErrBusy;
2709         }
2710 
2711         status = aPort->Send();
2712         if (status == PVMFErrBusy)
2713         {
2714             PVMF_MLNODE_LOGDATATRAFFIC_FLOWCTRL((0,
2715                                                  "0x%x PVMFMediaLayerNode::ProcessOutgoingMsg: Connected port goes into busy state", this));
2716             aPortContainer->oProcessOutgoingMessages = false;
2717         }
2718         PVMF_MLNODE_LOGINFO((0,
2719                              "PVMFMediaLayerNode::ProcessOutgoingMsg: Send - %s", aPortContainer->iMimeType.get_cstr()));
2720     }
2721     else
2722     {
2723         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aPort));
2724         PVMF_MLNODE_LOGERROR((0,
2725                               "0x%x PVMFMediaLayerNode::ProcessOutgoingMsg: Error - Not an Output Port", this));
2726         status = PVMFFailure;
2727     }
2728     return status;
2729 }
2730 
CheckForPortRescheduling()2731 bool PVMFMediaLayerNode::CheckForPortRescheduling()
2732 {
2733     uint32 i;
2734     for (i = 0; i < iPortVector.size(); i++)
2735     {
2736         PVMFMediaLayerPortContainer* portContainerPtr = NULL;
2737 
2738         if (!GetPortContainer(iPortVector[i], portContainerPtr))
2739         {
2740             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::CheckForPortRescheduling: Error - GetPortContainer failed", this));
2741             return false;
2742         }
2743 
2744         if (portContainerPtr->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
2745         {
2746             if (portContainerPtr->iPort->IncomingMsgQueueSize() > 0)
2747             {
2748                 if (portContainerPtr->oProcessIncomingMessages)
2749                 {
2750                     if (oEOSsendunits)
2751                         return false;
2752                     /*
2753                      * Found a port that has outstanding activity and
2754                      * is not busy.
2755                      */
2756                     return true;
2757                 }
2758             }
2759         }
2760         else if (portContainerPtr->tag == PVMF_MEDIALAYER_PORT_TYPE_OUTPUT)
2761         {
2762             /*
2763              * If there are output msgs waiting and if the connected port
2764              * is not busy - reschedule
2765              */
2766             if ((portContainerPtr->iPort->OutgoingMsgQueueSize() > 0) &&
2767                     (portContainerPtr->oProcessOutgoingMessages))
2768             {
2769                 /*
2770                  * Found a port that has outstanding activity and
2771                  * is not busy.
2772                  */
2773                 return true;
2774             }
2775             /*
2776              * If there are payload access units msgs waiting and if the connected port
2777              * is not busy or message is available - reschedule
2778              * If another output port is ok and the connected port is busy, we do not reschedule.
2779              */
2780             if (portContainerPtr->vAccessUnits.size() > 0)
2781             {
2782                 if ((portContainerPtr->iPort->IsOutgoingQueueBusy() == false) &&
2783                         (portContainerPtr->ipFragGroupAllocator->IsMsgAvailable() == true))
2784                 {
2785                     /*
2786                      * Found payload access units msgs that is available and outgoing queue
2787                      * is not busy.
2788                      */
2789                     return true;
2790                 }
2791             }
2792         }
2793     }
2794     /*
2795      * No port processing needed - either all port activity queues are empty
2796      * or the ports are backed up due to flow control.
2797      */
2798     return false;
2799 }
2800 
CheckForPortActivityQueues()2801 bool PVMFMediaLayerNode::CheckForPortActivityQueues()
2802 {
2803     uint32 i;
2804     for (i = 0; i < iPortVector.size(); i++)
2805     {
2806         PVMFMediaLayerPortContainer* portContainerPtr = NULL;
2807 
2808         if (!GetPortContainer(iPortVector[i], portContainerPtr))
2809         {
2810             PVMF_MLNODE_LOGERROR((0, "0x%x PVMFMediaLayerNode::CheckForPortRescheduling: Error - GetPortContainer failed", this));
2811             return false;
2812         }
2813 
2814         if ((portContainerPtr->iPort->IncomingMsgQueueSize() > 0) ||
2815                 (portContainerPtr->iPort->OutgoingMsgQueueSize() > 0))
2816         {
2817             /*
2818              * Found a port that still has an outstanding activity.
2819              */
2820             return true;
2821         }
2822     }
2823     /*
2824      * All port activity queues are empty
2825      */
2826     return false;
2827 }
2828 
2829 /**
2830  * Active object implementation
2831  */
2832 /**
2833  * This AO handles both API commands and port activity.
2834  * The AO will either process one command or service all connected
2835  * ports once per call.  It will re-schedule itself and run continuously
2836  * until it runs out of things to do.
2837  */
Run()2838 void PVMFMediaLayerNode::Run()
2839 {
2840     iNumRunL++;
2841 
2842     uint32 startticks = OsclTickCount::TickCount();
2843     uint32 starttime = OsclTickCount::TicksToMsec(startticks);
2844 
2845     uint32 i;
2846     /* Process commands */
2847     if (!iInputCommands.empty())
2848     {
2849         if (ProcessCommand(iInputCommands.front()))
2850         {
2851             /*
2852              * note: need to check the state before re-scheduling
2853              * since the node could have been reset in the ProcessCommand
2854              * call.
2855              */
2856             if (iInterfaceState != EPVMFNodeCreated)
2857             {
2858                 if (IsAdded())
2859                 {
2860                     RunIfNotReady();
2861                 }
2862             }
2863             return;
2864         }
2865     }
2866 
2867     /*
2868      * Process ports activity - This node would run thru the entire
2869      * list of ports and would try and process atleast one actvity per
2870      * port.
2871      */
2872     if (iInterfaceState == EPVMFNodeStarted || FlushPending())
2873     {
2874         bool oRescheduleBasedOnPorts = false;
2875         bool oContinueToProcess = true;
2876         uint32 count = 0;
2877         uint32 timespentinloop = 0;
2878         while (oContinueToProcess)
2879         {
2880             count++;
2881             for (i = 0; i < iPortVector.size(); i++)
2882             {
2883                 PVMFMediaLayerPortContainer* portContainerPtr = NULL;
2884 
2885                 if (!GetPortContainer(iPortVector[i], portContainerPtr))
2886                 {
2887                     PVMF_MLNODE_LOGERROR((0, "PVMFMediaLayerNode::Run: Error - GetPortContainer failed"));
2888                     return;
2889                 }
2890 
2891                 ProcessPortActivity(portContainerPtr);
2892             }
2893 
2894             oRescheduleBasedOnPorts = CheckForPortRescheduling();
2895 
2896             uint32 currticks = OsclTickCount::TickCount();
2897             uint32 currtime = OsclTickCount::TicksToMsec(currticks);
2898             timespentinloop += (currtime - starttime);
2899 
2900             if (timespentinloop < MEDIALAYERNODE_MAX_RUNL_TIME_IN_MS)
2901             {
2902                 if (oRescheduleBasedOnPorts == false)
2903                 {
2904                     // we have time, but we have nothing to do
2905                     oContinueToProcess = false;
2906                 }
2907             }
2908             else
2909             {
2910                 //we have exceeded time limit so yield, if we have more stuff to do
2911                 //we will reschedule below
2912                 oContinueToProcess = false;
2913             }
2914         }
2915         if (oRescheduleBasedOnPorts)
2916         {
2917             if (IsAdded())
2918             {
2919                 /*
2920                  * Re-schedule since there is atleast one port that needs processing
2921                  */
2922                 RunIfNotReady();
2923             }
2924         }
2925         PVMF_MLNODE_LOG_RUNL((0, "PVMFMediaLayerNode::Run: NumLoops=%d, TotalTime=%d ms", count, timespentinloop));
2926         return;
2927     }
2928 
2929     /*
2930      * If we get here we did not process any ports or commands.
2931      * Check for completion of a flush command...
2932      */
2933     if (FlushPending() && (!CheckForPortActivityQueues()))
2934     {
2935         /*
2936          * Debug check-- all the port queues should be empty at
2937          * this point.
2938          */
2939         for (i = 0; i < iPortVector.size(); i++)
2940         {
2941             if (iPortVector[i]->IncomingMsgQueueSize() > 0 ||
2942                     iPortVector[i]->OutgoingMsgQueueSize() > 0)
2943             {
2944                 OSCL_ASSERT(false);
2945             }
2946         }
2947         /*
2948          * Flush is complete.  Go to prepared state.
2949          */
2950         SetState(EPVMFNodePrepared);
2951         /*
2952          * resume port input so the ports can be re-started.
2953          */
2954         for (i = 0; i < iPortVector.size(); i++)
2955         {
2956             iPortVector[i]->ResumeInput();
2957         }
2958         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
2959         if (IsAdded())
2960         {
2961             RunIfNotReady();
2962         }
2963     }
2964 }
2965 
DoCancel()2966 void PVMFMediaLayerNode::DoCancel()
2967 {
2968     /* the base class cancel operation is sufficient */
2969     OsclActiveObject::DoCancel();
2970 }
2971 
2972 bool
GetPortContainer(PVMFPortInterface * aPort,PVMFMediaLayerPortContainer & aContainer)2973 PVMFMediaLayerNode::GetPortContainer(PVMFPortInterface* aPort,
2974                                      PVMFMediaLayerPortContainer& aContainer)
2975 {
2976     uint32 i;
2977     for (i = 0; i < iPortParamsQueue.size(); i++)
2978     {
2979         PVMFMediaLayerPortContainer portParams = iPortParamsQueue[i];
2980 
2981         if (portParams.iPort == aPort)
2982         {
2983             aContainer = portParams;
2984             return true;
2985         }
2986     }
2987     return false;
2988 }
2989 
2990 bool
GetPortContainer(PVMFPortInterface * aPort,int & index)2991 PVMFMediaLayerNode::GetPortContainer(PVMFPortInterface* aPort, int& index)
2992 {
2993     for (index = 0; index < (int)iPortParamsQueue.size(); index++)
2994     {
2995         if (iPortParamsQueue[index].iPort == aPort)
2996         {
2997             return true;
2998         }
2999     }
3000 
3001     return false;
3002 }
3003 bool
GetPortContainer(PVMFPortInterface * aPort,PVMFMediaLayerPortContainer * & aContainerPtr)3004 PVMFMediaLayerNode::GetPortContainer(PVMFPortInterface* aPort,
3005                                      PVMFMediaLayerPortContainer*& aContainerPtr)
3006 {
3007     Oscl_Vector<PVMFMediaLayerPortContainer, PVMFMediaLayerNodeAllocator>::iterator it;
3008     for (it = iPortParamsQueue.begin(); it != iPortParamsQueue.end(); it++)
3009     {
3010         if (it->iPort == aPort)
3011         {
3012             aContainerPtr = it;
3013             return true;
3014         }
3015     }
3016     return false;
3017 }
3018 
3019 PVMFPortInterface*
getPortCounterpart(PVMFMediaLayerPortContainer aContainer)3020 PVMFMediaLayerNode::getPortCounterpart(PVMFMediaLayerPortContainer aContainer)
3021 {
3022     return iPortParamsQueue[aContainer.vCounterPorts[0]].iPort;
3023 }
3024 
3025 PVMFPortInterface*
getPortCounterpart(PVMFMediaLayerPortContainer * aContainerPtr)3026 PVMFMediaLayerNode::getPortCounterpart(PVMFMediaLayerPortContainer* aContainerPtr)
3027 {
3028     return iPortParamsQueue[aContainerPtr->vCounterPorts[0]].iPort;
3029 }
3030 
3031 void
LogMediaData(PVMFSharedMediaDataPtr data,PVMFPortInterface * aPort)3032 PVMFMediaLayerNode::LogMediaData(PVMFSharedMediaDataPtr data,
3033                                  PVMFPortInterface* aPort)
3034 {
3035     PVMFMediaLayerPortContainer* portContainerPtr = NULL;
3036     if (!GetPortContainer(aPort, portContainerPtr))
3037     {
3038         return;
3039     }
3040 
3041     PVMFMediaData* mediaData = data.GetRep();
3042 
3043     if (mediaData != NULL)
3044     {
3045         OsclRefCounterMemFrag memFrag;
3046         /* Get Format Specific Info, if any */
3047         mediaData->getFormatSpecificInfo(memFrag);
3048         OsclAny* ptr = memFrag.getMemFragPtr();
3049         uint32 size = memFrag.getMemFragSize();
3050 
3051         OSCL_StackString<8> h264("H264");
3052         if ((size > 0) && (portContainerPtr->oFormatSpecificInfoLogged == false))
3053         {
3054             portContainerPtr->oFormatSpecificInfoLogged = true;
3055             if (!oscl_strcmp(portContainerPtr->iMimeType.get_cstr(), h264.get_cstr()))
3056             {
3057                 PVMF_MLNODE_LOGBIN(portContainerPtr->iPortLogger, (0, 1, sizeof(uint32), &size));
3058             }
3059             PVMF_MLNODE_LOGBIN(portContainerPtr->iPortLogger, (0, 1, size, ptr));
3060         }
3061 
3062         /* Log Media Fragments */
3063         uint32 numFrags = mediaData->getNumFragments();
3064         for (uint32 i = 0; i < numFrags; i++)
3065         {
3066             mediaData->getMediaFragment(i, memFrag);
3067             ptr = memFrag.getMemFragPtr();
3068             size = memFrag.getMemFragSize();
3069             if (!oscl_strcmp(portContainerPtr->iMimeType.get_cstr(), h264.get_cstr()))
3070             {
3071                 PVMF_MLNODE_LOGBIN(portContainerPtr->iPortLogger, (0, 1, sizeof(uint32), &size));
3072             }
3073             PVMF_MLNODE_LOGBIN(portContainerPtr->iPortLogger, (0, 1, size, ptr));
3074         }
3075     }
3076 }
3077 
3078 
CheckForEOS()3079 bool PVMFMediaLayerNode::CheckForEOS()
3080 {
3081     Oscl_Vector<PVMFMediaLayerPortContainer, PVMFMediaLayerNodeAllocator>::iterator it;
3082     for (it = iPortParamsQueue.begin();
3083             it != iPortParamsQueue.end();
3084             it++)
3085     {
3086         if (it->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
3087         {
3088             if (it->oEOSReached == false)
3089             {
3090                 return false;
3091             }
3092         }
3093     }
3094     return true;
3095 }
3096 
3097 bool
setPortMediaParams(PVMFPortInterface * aPort,OsclRefCounterMemFrag & aConfig,mediaInfo * aMediaInfo)3098 PVMFMediaLayerNode::setPortMediaParams(PVMFPortInterface* aPort,
3099                                        OsclRefCounterMemFrag& aConfig,
3100                                        mediaInfo* aMediaInfo)
3101 {
3102     PVMFMediaLayerPortContainer* portContainerPtr = NULL;
3103 
3104     if (!GetPortContainer(aPort, portContainerPtr))
3105     {
3106         return false;
3107     }
3108 
3109     /*
3110      * there is a previously set config. make a note of it.
3111      * in case a re config media cmd comes along we would send out this config
3112      */
3113     if (portContainerPtr->iTrackConfig.getMemFragSize() > 0)
3114     {
3115         portContainerPtr->iReConfig = true;
3116     }
3117     portContainerPtr->iTrackConfig = aConfig;
3118 
3119     // this method is called for input and output ports
3120     if (portContainerPtr->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
3121     {
3122         return portContainerPtr->iPayLoadParser->Init(aMediaInfo);
3123     }
3124     else
3125     {
3126         return true;
3127     }
3128 
3129 }
3130 
3131 PVMFStatus
verifyPortConfigParams(const char * aFormatValType,PVMFPortInterface * aPort,OsclAny * aConfig,mediaInfo * aMediaInfo)3132 PVMFMediaLayerNode::verifyPortConfigParams(const char* aFormatValType,
3133         PVMFPortInterface* aPort,
3134         OsclAny* aConfig,
3135         mediaInfo* aMediaInfo)
3136 {
3137     OSCL_UNUSED_ARG(aMediaInfo);
3138     PVMFMediaLayerPortContainer* portContainerPtr = NULL;
3139     if (GetPortContainer(aPort, portContainerPtr))
3140     {
3141         if (portContainerPtr->tag == PVMF_MEDIALAYER_PORT_TYPE_OUTPUT)
3142         {
3143             PVMFMediaLayerPort* mediaLayerNodePort = OSCL_STATIC_CAST(PVMFMediaLayerPort*, aPort);
3144 
3145             PVMFStatus status =
3146                 mediaLayerNodePort->pvmiVerifyPortFormatSpecificInfoSync(aFormatValType,
3147                         aConfig);
3148             return status;
3149         }
3150     }
3151     return PVMFErrArgument;
3152 }
3153 
3154 bool
setTrackDisable(PVMFPortInterface * aPort)3155 PVMFMediaLayerNode::setTrackDisable(PVMFPortInterface* aPort)
3156 {
3157     PVMFMediaLayerPortContainer* portContainerPtr = NULL;
3158     if (GetPortContainer(aPort, portContainerPtr))
3159     {
3160         portContainerPtr->oDetectBrokenTrack = true;
3161         portContainerPtr->oDisableTrack = true;
3162         return true;
3163     }
3164     return false;
3165 }
3166 
3167 bool
setOutPortStreamParams(PVMFPortInterface * aPort,uint streamid,uint32 aPreroll,bool aLiveStream)3168 PVMFMediaLayerNode::setOutPortStreamParams(PVMFPortInterface* aPort,
3169         uint streamid,
3170         uint32 aPreroll,
3171         bool aLiveStream)
3172 {
3173     OSCL_UNUSED_ARG(streamid);
3174     OSCL_UNUSED_ARG(aPreroll);
3175     OSCL_UNUSED_ARG(aLiveStream);
3176     PVMFMediaLayerPortContainer* outPort = NULL;
3177     int id;
3178 
3179     if (!GetPortContainer(aPort, id))
3180     {
3181         return false;
3182     }
3183     else
3184     {
3185         outPort = &iPortParamsQueue[id];
3186     }
3187 
3188     return true;
3189 }
3190 
parseOutputPortMime(OSCL_String * pmime,uint & inputPort)3191 bool PVMFMediaLayerNode::parseOutputPortMime(OSCL_String* pmime,
3192         uint& inputPort)
3193 {
3194     char* param = NULL;
3195 
3196     // get the input-port parameter from the mime string
3197     pv_mime_string_extract_param(0, (char*)pmime->get_cstr(), param);
3198     if (param == NULL)
3199     {
3200         return false;
3201     }
3202 
3203     // now, find where the parameter value starts
3204     do
3205     {
3206         if (*param++ == '=')
3207         {
3208             break;
3209         }
3210     }
3211     while (*param != 0);
3212 
3213     if (*param == 0)
3214     {
3215         // end of string
3216         return false;
3217     }
3218 
3219     // retrieve the numeric parameter value
3220     return PV_atoi(param, 'd', (uint32&)inputPort);
3221 }
3222 
3223 
setInPortReposFlag(PVMFPortInterface * aPort,uint32 aSeekTimeInMS)3224 void PVMFMediaLayerNode::setInPortReposFlag(PVMFPortInterface* aPort, uint32 aSeekTimeInMS)
3225 {
3226     PVMFMediaLayerPortContainer* portContainerPtr = NULL;
3227 
3228     PVMF_MLNODE_LOGINFO((0, "0x%x PVMFMediaLayerNode::setInPortReposFlag In", this));
3229 
3230     GetPortContainer(aPort, portContainerPtr);
3231 
3232     OSCL_ASSERT(portContainerPtr != NULL);
3233     OSCL_ASSERT(portContainerPtr->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT);
3234     OSCL_ASSERT(portContainerPtr->iPayLoadParser != NULL);
3235 
3236     portContainerPtr->oEOSReached = false;
3237 
3238     // sequence numbers down to decoder must be sequential- find out min. packet seq number for each stream
3239     // before we delete unsent buffer so that subsequent seq numbers can be adjusted and gap closed
3240 
3241     typedef Oscl_Vector<uint32, OsclMemAllocator> OsclUintVector;
3242     typedef Oscl_Vector<IPayloadParser::Payload, OsclMemAllocator>::iterator payload_iterator;
3243 
3244     // maximum sequence number for given stream
3245     OsclUintVector vecMinSeqNum;
3246     // list of all streams that have unsent packets and need to be adjusted
3247     OsclUintVector vecStreamsRequiringAdjustment;
3248 
3249     for (payload_iterator it = portContainerPtr->vAccessUnits.begin();
3250             it != portContainerPtr->vAccessUnits.end(); it++)
3251     {
3252         const uint32 currStreamNum = it->stream;
3253         const uint32 currSeq = it->sequence;
3254 
3255         // check whether we have this stream number already in our records
3256         bool bStreamAlreadyListed = false;
3257         for (uint32 uiS = 0; uiS < vecStreamsRequiringAdjustment.size(); ++uiS)
3258         {
3259             if (vecStreamsRequiringAdjustment[uiS] == currStreamNum)
3260             {
3261                 bStreamAlreadyListed = true;
3262                 break;
3263             }
3264         }
3265         if (!bStreamAlreadyListed)
3266             vecStreamsRequiringAdjustment.push_back(currStreamNum);
3267 
3268         // extend vector to cover all streams
3269         while (currStreamNum + 1 > vecMinSeqNum.size())
3270             vecMinSeqNum.push_back(0xFFFFFFFF);
3271 
3272         // keep track of smallest value so far
3273         if (currSeq < vecMinSeqNum[currStreamNum])
3274             vecMinSeqNum[currStreamNum] = currSeq;
3275     }
3276 
3277     // sequence generator keeps track of current sequence numbers. update it for all streams
3278 
3279     for (OsclUintVector::iterator itStream = vecStreamsRequiringAdjustment.begin();
3280             itStream != vecStreamsRequiringAdjustment.end(); ++itStream)
3281     {
3282         portContainerPtr->iPayLoadParser->Reposition(true, *itStream, vecMinSeqNum[*itStream]);
3283     }
3284 
3285     portContainerPtr->iPayLoadParser->Reposition();
3286     portContainerPtr->vAccessUnits.clear();
3287     for (uint i = 0; i < portContainerPtr->vCounterPorts.size(); i++)
3288     {
3289         PVMFMediaLayerPortContainer* poutPort = &this->iPortParamsQueue[portContainerPtr->vCounterPorts[i]];
3290         poutPort->vAccessUnits.clear();
3291     }
3292     portContainerPtr->iFirstFrameAfterRepositioning = true;
3293     portContainerPtr->iFirstFrameAfterReposTimeStamp = aSeekTimeInMS;
3294     portContainerPtr->iPort->ClearMsgQueues();
3295 
3296     diffAudioVideoTS = 0;
3297     iAdjustTimeReady = false;
3298     oEOSsendunits = false;
3299 
3300     PVMF_MLNODE_LOGINFO((0, "0x%x PVMFMediaLayerNode::setInPortReposFlag Out", this));
3301 }
3302 
getMaxOutPortTimestamp(PVMFPortInterface * aPort,bool oPeek)3303 uint32 PVMFMediaLayerNode::getMaxOutPortTimestamp(PVMFPortInterface* aPort,
3304         bool oPeek)
3305 {
3306     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::getMaxOutPortTimestamp() In"));
3307 
3308     PVMFMediaLayerPortContainer* inportContainerPtr = NULL;
3309 
3310     GetPortContainer(aPort, inportContainerPtr);
3311 
3312     OSCL_ASSERT(inportContainerPtr != NULL);
3313     OSCL_ASSERT(inportContainerPtr->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT);
3314     OSCL_ASSERT(inportContainerPtr->iPayLoadParser != NULL);
3315 
3316     inportContainerPtr->oEOSReached = false;
3317 
3318     uint32 max = 0;
3319     uint i;
3320     for (i = 0; i < inportContainerPtr->vCounterPorts.size(); i++)
3321     {
3322         PVMFMediaLayerPortContainer* outportContainerPtr =
3323             &this->iPortParamsQueue[inportContainerPtr->vCounterPorts[i]];
3324 
3325         uint64 ts64 = outportContainerPtr->iContinuousTimeStamp;
3326         uint32 ts32 = Oscl_Int64_Utils::get_uint64_lower32(ts64);
3327         if (ts32 > max)
3328         {
3329             max = ts32;
3330         }
3331         outportContainerPtr->oEOSReached = false;
3332     }
3333     if (oPeek == false)
3334     {
3335         /* reset all continuous ts to max */
3336         uint64 max64 = 0;
3337         Oscl_Int64_Utils::set_uint64(max64, 0, max);
3338         for (i = 0; i < inportContainerPtr->vCounterPorts.size(); i++)
3339         {
3340             PVMFMediaLayerPortContainer* outportContainerPtr =
3341                 &this->iPortParamsQueue[inportContainerPtr->vCounterPorts[i]];
3342             outportContainerPtr->iContinuousTimeStamp = max64;
3343         }
3344     }
3345     return max;
3346 }
3347 
sendEndOfTrackCommand(PVMFMediaLayerPortContainer * poutputPort)3348 PVMFStatus PVMFMediaLayerNode::sendEndOfTrackCommand(PVMFMediaLayerPortContainer* poutputPort)
3349 {
3350     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::sendEndOfTrackCommand() In"));
3351 
3352     PVMFStatus retval;
3353 
3354     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
3355     // Set the format ID
3356     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);
3357 
3358     //Set stream ID
3359     sharedMediaCmdPtr->setStreamID(iStreamID);
3360 
3361     // Set the timestamp
3362     sharedMediaCmdPtr->setTimestamp(poutputPort->iContinuousTimeStamp);
3363 
3364     // Set the sequence number
3365     sharedMediaCmdPtr->setSeqNum(poutputPort->iPrevMsgSeqNum);
3366 
3367     PVMFSharedMediaMsgPtr mediaMsgOut;
3368     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
3369     retval = poutputPort->iPort->QueueOutgoingMsg(mediaMsgOut);
3370     if (retval != PVMFSuccess)
3371     {
3372         PVMF_MLNODE_LOGERROR((0,
3373                               "0x%x PVMFMediaLayerNode::sendEndOfTrackCommand: "
3374                               "Error - QueueOutgoingMsg for EOS failed", this));
3375         return retval;
3376     }
3377 
3378     PVMF_MLNODE_LOGDATATRAFFIC_OUT((0, "PVMFMediaLayerNode::sendEndOfTrackCommand() MimeType=%s, StreamID=%d, TS=%d",
3379                                     poutputPort->iMimeType.get_cstr(),
3380                                     iStreamID,
3381                                     poutputPort->iContinuousTimeStamp));
3382     PVMF_MLNODE_LOGINFO((0, "PVMFMediaLayerNode::sendEndOfTrackCommand() Out"));
3383     return retval;
3384 }
3385 
setPlayRange(int32 aStartTimeInMS,int32 aStopTimeInMS,bool oRepositioning)3386 bool PVMFMediaLayerNode::setPlayRange(int32 aStartTimeInMS,
3387                                       int32 aStopTimeInMS,
3388                                       bool oRepositioning)
3389 {
3390     iPlayStartTime = aStartTimeInMS;
3391     iPlayStopTime = aStopTimeInMS;
3392     Oscl_Vector<PVMFMediaLayerPortContainer, PVMFMediaLayerNodeAllocator>::iterator it;
3393     for (it = iPortParamsQueue.begin(); it != iPortParamsQueue.end(); it++)
3394     {
3395         if (oRepositioning)
3396         {
3397             it->iPort->ClearMsgQueues();
3398             it->vAccessUnits.clear();
3399         }
3400 
3401         if (it->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
3402             it->oEOSReached = false;
3403     }
3404     return true;
3405 }
3406 
checkPortCounterpartAccessUnitQueue(PVMFMediaLayerPortContainer * pinputPort,bool * IsAccessUnitsEmpty)3407 PVMFStatus PVMFMediaLayerNode::checkPortCounterpartAccessUnitQueue(PVMFMediaLayerPortContainer* pinputPort, bool* IsAccessUnitsEmpty)
3408 {
3409     for (uint i = 0; i < pinputPort->vCounterPorts.size(); i++)
3410     {
3411         PVMFMediaLayerPortContainer* poutPort =
3412             &this->iPortParamsQueue[pinputPort->vCounterPorts[i]];
3413 
3414         if (poutPort->vAccessUnits.size() > 0)
3415         {
3416             *IsAccessUnitsEmpty = true;
3417         }
3418     }
3419     return PVMFSuccess;
3420 }
3421 
3422 
LogPayLoadParserStats()3423 PVMFStatus PVMFMediaLayerNode::LogPayLoadParserStats()
3424 {
3425     return PVMFSuccess;
3426 }
3427 
LogSessionDiagnostics()3428 void PVMFMediaLayerNode::LogSessionDiagnostics()
3429 {
3430     if (iDiagnosticsLogged == false)
3431     {
3432         iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.streamingmanager.medialayer");
3433 
3434         PVMF_MLNODE_LOGDIAGNOSTICS((0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"));
3435         PVMF_MLNODE_LOGDIAGNOSTICS((0, "PVMFMediaLayerNode - iNumRunL = %d", iNumRunL));
3436 
3437         Oscl_Vector<PVMFMediaLayerPortContainer, PVMFMediaLayerNodeAllocator>::iterator it;
3438         for (it = iPortParamsQueue.begin(); it != iPortParamsQueue.end(); it++)
3439         {
3440             PvmfPortBaseImpl* ptr =
3441                 OSCL_STATIC_CAST(PvmfPortBaseImpl*, it->iPort);
3442             PvmfPortBaseImplStats stats;
3443             ptr->GetStats(stats);
3444 
3445             if (it->tag == PVMF_MEDIALAYER_PORT_TYPE_INPUT)
3446             {
3447                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"));
3448                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "PVMF_MEDIALAYER_PORT_TYPE_INPUT"));
3449                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iIncomingMsgRecv = %d", stats.iIncomingMsgRecv));
3450                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iIncomingMsgConsumed = %d", stats.iIncomingMsgConsumed));
3451                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iIncomingQueueBusy = %d", stats.iIncomingQueueBusy));
3452                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingMsgQueued = %d", stats.iOutgoingMsgQueued));
3453                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingMsgSent = %d", stats.iOutgoingMsgSent));
3454                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingQueueBusy = %d", stats.iOutgoingQueueBusy));
3455                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingMsgDiscarded = %d", stats.iOutgoingMsgDiscarded));
3456             }
3457             else if (it->tag == PVMF_MEDIALAYER_PORT_TYPE_OUTPUT)
3458             {
3459                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"));
3460                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "PVMF_MEDIALAYER_PORT_TYPE_OUTPUT"));
3461                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iIncomingMsgRecv = %d", stats.iIncomingMsgRecv));
3462                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iIncomingMsgConsumed = %d", stats.iIncomingMsgConsumed));
3463                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iIncomingQueueBusy = %d", stats.iIncomingQueueBusy));
3464                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingMsgQueued = %d", stats.iOutgoingMsgQueued));
3465                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingMsgSent = %d", stats.iOutgoingMsgSent));
3466                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingQueueBusy = %d", stats.iOutgoingQueueBusy));
3467                 PVMF_MLNODE_LOGDIAGNOSTICS((0, "iOutgoingMsgDiscarded = %d", stats.iOutgoingMsgDiscarded));
3468             }
3469         }
3470         iDiagnosticsLogged = true;
3471     }
3472 }
3473 
3474 
3475 /*********************************************************************/
3476 /* Extension interface */
PVMFMediaLayerNodeExtensionInterfaceImpl(PVMFMediaLayerNode * c)3477 PVMFMediaLayerNodeExtensionInterfaceImpl::PVMFMediaLayerNodeExtensionInterfaceImpl(PVMFMediaLayerNode*c)
3478         : PVInterfaceImpl<PVMFMediaLayerNodeAllocator>(PVUuid(PVMF_MEDIALAYERNODE_EXTENSIONINTERFACE_UUID))
3479         , iContainer(c)
3480 {}
3481 
~PVMFMediaLayerNodeExtensionInterfaceImpl()3482 PVMFMediaLayerNodeExtensionInterfaceImpl::~PVMFMediaLayerNodeExtensionInterfaceImpl()
3483 {}
3484 
3485 PVMFStatus
setDRMDecryptionInterface(uint32 maxPacketSize,PVMFCPMPluginAccessUnitDecryptionInterface * aDecryptionInterface)3486 PVMFMediaLayerNodeExtensionInterfaceImpl::setDRMDecryptionInterface(uint32 maxPacketSize,
3487         PVMFCPMPluginAccessUnitDecryptionInterface* aDecryptionInterface)
3488 {
3489     return (iContainer->setDRMDecryptionInterface(maxPacketSize, aDecryptionInterface));
3490 }
3491 
3492 PVMFStatus
setPayloadParserRegistry(PayloadParserRegistry * registry)3493 PVMFMediaLayerNodeExtensionInterfaceImpl::setPayloadParserRegistry(PayloadParserRegistry* registry)
3494 {
3495     iContainer->setPayloadParserRegistry(registry);
3496     return PVMFSuccess;
3497 }
3498 
3499 PVMFStatus
setPortDataLogging(bool logEnable,OSCL_String * logPath)3500 PVMFMediaLayerNodeExtensionInterfaceImpl::setPortDataLogging(bool logEnable,
3501         OSCL_String* logPath)
3502 {
3503     return (iContainer->setPortDataLogging(logEnable, logPath));
3504 }
3505 
3506 bool
setPlayRange(int32 aStartTimeInMS,int32 aStopTimeInMS,bool oRepositioning)3507 PVMFMediaLayerNodeExtensionInterfaceImpl::setPlayRange(int32 aStartTimeInMS,
3508         int32 aStopTimeInMS,
3509         bool oRepositioning)
3510 {
3511     return (iContainer->setPlayRange(aStartTimeInMS, aStopTimeInMS, oRepositioning));
3512 }
3513 
3514 bool
setClientPlayBackClock(PVMFMediaClock * aClientPlayBackClock)3515 PVMFMediaLayerNodeExtensionInterfaceImpl::setClientPlayBackClock(PVMFMediaClock* aClientPlayBackClock)
3516 {
3517     return (iContainer->setClientPlayBackClock(aClientPlayBackClock));
3518 }
3519 
3520 bool
setPortMediaParams(PVMFPortInterface * aPort,OsclRefCounterMemFrag & aConfig,mediaInfo * aMediaInfo)3521 PVMFMediaLayerNodeExtensionInterfaceImpl::setPortMediaParams(PVMFPortInterface* aPort,
3522         OsclRefCounterMemFrag& aConfig,
3523         mediaInfo* aMediaInfo)
3524 {
3525     return (iContainer->setPortMediaParams(aPort, aConfig, aMediaInfo));
3526 }
3527 
3528 PVMFStatus
verifyPortConfigParams(const char * aFormatValType,PVMFPortInterface * aPort,OsclAny * aConfig,mediaInfo * aMediaInfo)3529 PVMFMediaLayerNodeExtensionInterfaceImpl::verifyPortConfigParams(const char* aFormatValType,
3530         PVMFPortInterface* aPort,
3531         OsclAny* aConfig,
3532         mediaInfo* aMediaInfo)
3533 {
3534     return (iContainer->verifyPortConfigParams(aFormatValType, aPort, aConfig, aMediaInfo));
3535 }
3536 
3537 bool
setTrackDisable(PVMFPortInterface * aPort)3538 PVMFMediaLayerNodeExtensionInterfaceImpl::setTrackDisable(PVMFPortInterface* aPort)
3539 {
3540     return (iContainer->setTrackDisable(aPort));
3541 }
3542 
3543 void
setMediaLayerTimerDurationMS(uint32 aTimer)3544 PVMFMediaLayerNodeExtensionInterfaceImpl::setMediaLayerTimerDurationMS(uint32 aTimer)
3545 {
3546     iContainer->setMediaLayerTimerDurationMS(aTimer);
3547 }
3548 
3549 bool
setOutPortStreamParams(PVMFPortInterface * aPort,uint streamid,uint32 aPreroll,bool aLiveStream)3550 PVMFMediaLayerNodeExtensionInterfaceImpl::setOutPortStreamParams(PVMFPortInterface* aPort,
3551         uint streamid,
3552         uint32 aPreroll,
3553         bool aLiveStream)
3554 {
3555     return (iContainer->setOutPortStreamParams(aPort, streamid, aPreroll, aLiveStream));
3556 }
3557 
setInPortReposFlag(PVMFPortInterface * aPort,uint32 aSeekTimeInMS)3558 void PVMFMediaLayerNodeExtensionInterfaceImpl::setInPortReposFlag(PVMFPortInterface* aPort, uint32 aSeekTimeInMS)
3559 {
3560     iContainer->setInPortReposFlag(aPort, aSeekTimeInMS);
3561 }
3562 
3563 uint32
getMaxOutPortTimestamp(PVMFPortInterface * aPort,bool oPeek)3564 PVMFMediaLayerNodeExtensionInterfaceImpl::getMaxOutPortTimestamp(PVMFPortInterface* aPort,
3565         bool oPeek)
3566 {
3567     return iContainer->getMaxOutPortTimestamp(aPort, oPeek);
3568 }
3569