• 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 /**
19  * @file pvmi_io_interface_node.cpp
20  * @brief
21  */
22 
23 #include "oscl_base.h"
24 #include "pv_media_output_node_factory.h"
25 #include "pv_media_output_node.h"
26 #include "pv_media_output_node_inport.h"
27 #include "oscl_dll.h"
28 #include "pvmf_basic_errorinfomessage.h"
29 #include "pv_media_output_node_events.h"
30 
31 // Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT()32 OSCL_DLL_ENTRY_POINT_DEFAULT()
33 
34 /**
35 //Macros for calling PVLogger
36 */
37 #define LOGREPOS(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iReposLogger,PVLOGMSG_INFO,m);
38 #define LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
39 #define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
40 #define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
41 #define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
42 #define LOGINFO(m) LOGINFOMED(m)
43 #define LOGDIAGNOSTICS(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_PROF,iDiagnosticsLogger,PVLOGMSG_INFO,m);
44 
45 //this should always be 1. set this to zero if
46 //you want to bypass avsync (typically used in
47 //case one wants to decode and render ASAP)
48 #define PVMF_MEDIA_OUTPUT_NODE_ENABLE_AV_SYNC 1
49 
50 ////////////////////////////////////////////////////////////////////////////
51 OSCL_EXPORT_REF PVMFNodeInterface* PVMediaOutputNodeFactory::CreateMediaOutputNode(
52     PvmiMIOControl* aMIOControl)
53 {
54     return PVMediaOutputNode::Create(aMIOControl);
55 }
56 
57 ////////////////////////////////////////////////////////////////////////////
DeleteMediaOutputNode(PVMFNodeInterface * aNode)58 OSCL_EXPORT_REF void PVMediaOutputNodeFactory::DeleteMediaOutputNode(PVMFNodeInterface* aNode)
59 {
60     PVMediaOutputNode::Release(aNode);
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////
Create(PvmiMIOControl * aIOInterfacePtr)64 PVMFNodeInterface* PVMediaOutputNode::Create(PvmiMIOControl* aIOInterfacePtr)
65 {
66     PVMediaOutputNode* node = OSCL_NEW(PVMediaOutputNode, ());
67     if (node)
68     {
69         OSCL_TRAPSTACK_PUSH(node);
70         node->ConstructL(aIOInterfacePtr);
71         OSCL_TRAPSTACK_POP();
72     }
73     return (PVMFNodeInterface*)node;
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////
Release(PVMFNodeInterface * aNode)77 void PVMediaOutputNode::Release(PVMFNodeInterface* aNode)
78 {
79     OSCL_DELETE(((PVMediaOutputNode*)aNode));
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////
~PVMediaOutputNode()83 PVMediaOutputNode::~PVMediaOutputNode()
84 {
85     LogDiagnostics();
86 
87     Cancel();
88     if (IsAdded())
89         RemoveFromScheduler();
90 
91     iLogger = NULL;
92 
93     if (iMIOControl)
94     {
95         //call disconnect to make sure that there are no
96         //callback once the object has been destroyed
97         iMIOControl->disconnect(iMIOSession);
98         //ignore any returned errors.
99         iMIOControl->ThreadLogoff();
100     }
101 
102     //if any MIO commands are outstanding, there will be
103     //a crash when they callback-- so panic here instead.
104     if (!iCancelCommand.empty()
105             || iMediaIORequest != ENone)
106         OSCL_ASSERT(0);//OsclError::Panic("PVMOUT",PVMoutPanic_OutstandingMIO_Command);
107 
108     //Cleanup allocated ports
109     while (!iInPortVector.empty())
110         iInPortVector.Erase(&iInPortVector.front());
111 
112     //Cleanup commands
113     //The command queues are self-deleting, but we want to
114     //notify the observer of unprocessed commands.
115     while (!iCurrentCommand.empty())
116     {
117         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
118     }
119     while (!iInputCommands.empty())
120     {
121         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
122     }
123 
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////
ThreadLogon()127 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::ThreadLogon()
128 {
129     if (iInterfaceState != EPVMFNodeCreated)
130         return PVMFErrInvalidState;
131 
132     iLogger = PVLogger::GetLoggerObject("PVMediaOutputNode");
133     iReposLogger = PVLogger::GetLoggerObject("pvplayerrepos.mionode");
134     iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.mionode");
135 
136     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
137                     (0, "PVMediaOutputNode::ThreadLogon"));
138 
139     if (!IsAdded())
140         AddToScheduler();
141 
142     if (iMIOControl)
143     {
144         iMIOControl->ThreadLogon();
145         iMediaIOState = STATE_LOGGED_ON;
146     }
147 
148     if (iMIOControl->connect(iMIOSession, this) != PVMFSuccess)
149     {
150         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
151                         (0, "PVMediaOutputNode::ThreadLogon: Error - iMIOControl->connect failed"));
152         return PVMFFailure;
153     }
154 
155     SetState(EPVMFNodeIdle);
156     return PVMFSuccess;
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////
ThreadLogoff()160 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::ThreadLogoff()
161 {
162     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
163                     (0, "PVMediaOutputNode::ThreadLogoff"));
164 
165     if (iInterfaceState != EPVMFNodeIdle)
166         return PVMFErrInvalidState;
167 
168     if (IsAdded())
169         RemoveFromScheduler();
170 
171     iLogger = NULL;
172 
173     if (iMIOControl)
174     {
175         // Currently we do not distinguish between these states
176         // in how we drive the MIO. In the future, we will be
177         // able to independently reset/disconnect MIOs.
178         //
179         // The MIO reset is called here instead of the internal
180         // reset because there is currently no processing there.
181         // This is to reduce risk to existing MIOs.
182         //
183         // It can be moved to the internal node reset in the future.
184         PVMFStatus status = PVMFFailure;
185         status = iMIOControl->disconnect(iMIOSession);
186         //ignore any returned errors.
187         iMIOControl->ThreadLogoff();
188         iMediaIOState = STATE_IDLE;
189     }
190 
191     SetState(EPVMFNodeCreated);
192     return PVMFSuccess;
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////
GetCapability(PVMFNodeCapability & aNodeCapability)196 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::GetCapability(PVMFNodeCapability& aNodeCapability)
197 {
198     if (!iMIOConfig)
199         return PVMFFailure;
200 
201     aNodeCapability.iCanSupportMultipleInputPorts = false;
202     aNodeCapability.iCanSupportMultipleOutputPorts = false;
203     aNodeCapability.iHasMaxNumberOfPorts = true;
204     aNodeCapability.iMaxNumberOfPorts = 1;
205 
206     PvmiKvp* kvp ;
207     int numParams ;
208     int32 err ;
209     int32 i ;
210     PVMFStatus status;
211 
212     // Get input formats capability from media IO
213     kvp = NULL;
214     numParams = 0;
215     status = iMIOConfig->getParametersSync(NULL, (char*)INPUT_FORMATS_CAP_QUERY, kvp, numParams, NULL);
216     if (status == PVMFSuccess)
217     {
218         OSCL_TRY(err,
219                  for (i = 0; i < numParams; i++)
220                  aNodeCapability.iInputFormatCapability.push_back(PVMFFormatType(kvp[i].value.pChar_value));
221                 );
222         if (kvp)
223             iMIOConfig->releaseParameters(0, kvp, numParams);
224     }
225     //else ignore errors.
226 
227     // Get output formats capability from media IO
228     kvp = NULL;
229     numParams = 0;
230     status = iMIOConfig->getParametersSync(NULL, (char*)OUTPUT_FORMATS_CAP_QUERY, kvp, numParams, NULL);
231     if (status == PVMFSuccess)
232     {
233         OSCL_TRY(err,
234                  for (i = 0; i < numParams; i++)
235                  aNodeCapability.iOutputFormatCapability.push_back(PVMFFormatType(kvp[i].value.pChar_value));
236                 );
237         if (kvp)
238             iMIOConfig->releaseParameters(0, kvp, numParams);
239     }
240     //else ignore errors.
241 
242     if (aNodeCapability.iInputFormatCapability.empty() && aNodeCapability.iOutputFormatCapability.empty())
243         return PVMFFailure;
244 
245     return PVMFSuccess;
246 }
247 
248 ////////////////////////////////////////////////////////////////////////////
GetPorts(const PVMFPortFilter * aFilter)249 OSCL_EXPORT_REF PVMFPortIter* PVMediaOutputNode::GetPorts(const PVMFPortFilter* aFilter)
250 {
251     OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
252     iInPortVector.Reset();
253     return &iInPortVector;
254 }
255 
256 ////////////////////////////////////////////////////////////////////////////
QueryUUID(PVMFSessionId s,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)257 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
258         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
259         bool aExactUuidsOnly,
260         const OsclAny* aContext)
261 {
262     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
263                     (0, "PVMediaOutputNode::QueryUUID() called"));
264     PVMediaOutputNodeCmd cmd;
265     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
266     return QueueCommandL(cmd);
267 }
268 
269 ////////////////////////////////////////////////////////////////////////////
QueryInterface(PVMFSessionId s,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)270 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
271         PVInterface*& aInterfacePtr,
272         const OsclAny* aContext)
273 {
274     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
275                     (0, "PVMediaOutputNode::QueryInterface() called"));
276     PVMediaOutputNodeCmd cmd;
277     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
278     return QueueCommandL(cmd);
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////
RequestPort(PVMFSessionId s,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)282 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
283 {
284     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
285                     (0, "PVMediaOutputNode::RequestPort() called"));
286     PVMediaOutputNodeCmd cmd;
287     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
288     return QueueCommandL(cmd);
289 }
290 
291 ////////////////////////////////////////////////////////////////////////////
ReleasePort(PVMFSessionId s,PVMFPortInterface & aPort,const OsclAny * aContext)292 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
293 {
294     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
295                     (0, "PVMediaOutputNode::ReleasePort() called"));
296     PVMediaOutputNodeCmd cmd;
297     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
298     return QueueCommandL(cmd);
299 }
300 
301 ////////////////////////////////////////////////////////////////////////////
Init(PVMFSessionId s,const OsclAny * aContext)302 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::Init(PVMFSessionId s, const OsclAny* aContext)
303 {
304     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
305                     (0, "PVMediaOutputNode::Init() called"));
306     PVMediaOutputNodeCmd cmd;
307     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
308     return QueueCommandL(cmd);
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////
Prepare(PVMFSessionId s,const OsclAny * aContext)312 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
313 {
314     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
315                     (0, "PVMediaOutputNode::Prepare() called"));
316     PVMediaOutputNodeCmd cmd;
317     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
318     return QueueCommandL(cmd);
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////
Start(PVMFSessionId s,const OsclAny * aContext)322 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::Start(PVMFSessionId s, const OsclAny* aContext)
323 {
324     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
325                     (0, "PVMediaOutputNode::Start() called"));
326     PVMediaOutputNodeCmd cmd;
327     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
328     return QueueCommandL(cmd);
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////
Stop(PVMFSessionId s,const OsclAny * aContext)332 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::Stop(PVMFSessionId s, const OsclAny* aContext)
333 {
334     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
335                     (0, "PVMediaOutputNode::Stop() called"));
336     PVMediaOutputNodeCmd cmd;
337     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
338     return QueueCommandL(cmd);
339 }
340 
341 ////////////////////////////////////////////////////////////////////////////
Flush(PVMFSessionId s,const OsclAny * aContext)342 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::Flush(PVMFSessionId s, const OsclAny* aContext)
343 {
344     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
345                     (0, "PVMediaOutputNode::Flush() called"));
346     PVMediaOutputNodeCmd cmd;
347     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
348     return QueueCommandL(cmd);
349 }
350 
351 ////////////////////////////////////////////////////////////////////////////
Pause(PVMFSessionId s,const OsclAny * aContext)352 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::Pause(PVMFSessionId s, const OsclAny* aContext)
353 {
354     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
355                     (0, "PVMediaOutputNode::Pause() called"));
356     PVMediaOutputNodeCmd cmd;
357     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
358     return QueueCommandL(cmd);
359 }
360 
361 ////////////////////////////////////////////////////////////////////////////
Reset(PVMFSessionId s,const OsclAny * aContext)362 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::Reset(PVMFSessionId s, const OsclAny* aContext)
363 {
364     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
365                     (0, "PVMediaOutputNode::Reset() called"));
366     PVMediaOutputNodeCmd cmd;
367     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
368     return QueueCommandL(cmd);
369 }
370 
371 ////////////////////////////////////////////////////////////////////////////
CancelAllCommands(PVMFSessionId s,const OsclAny * aContext)372 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
373 {
374     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
375                     (0, "PVMediaOutputNode::CancelAllCommands() called"));
376     PVMediaOutputNodeCmd cmd;
377     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
378     return QueueCommandL(cmd);
379 }
380 
381 ////////////////////////////////////////////////////////////////////////////
CancelCommand(PVMFSessionId s,PVMFCommandId aCmdId,const OsclAny * aContext)382 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
383 {
384     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
385                     (0, "PVMediaOutputNode::CancelCommands() called cmdId=%d", aCmdId));
386     PVMediaOutputNodeCmd cmd;
387     cmd.PVMediaOutputNodeCmdBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
388     return QueueCommandL(cmd);
389 }
390 
391 ////////////////////////////////////////////////////////////////////////////
addRef()392 OSCL_EXPORT_REF void PVMediaOutputNode::addRef()
393 {
394     ++iExtensionRefCount;
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////
removeRef()398 OSCL_EXPORT_REF void PVMediaOutputNode::removeRef()
399 {
400     if (iExtensionRefCount > 0)
401         --iExtensionRefCount;
402 }
403 
404 ////////////////////////////////////////////////////////////////////////////
queryInterface(const PVUuid & uuid,PVInterface * & iface)405 OSCL_EXPORT_REF bool PVMediaOutputNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
406 {
407     if (uuid == PvmfNodesSyncControlUuid)
408     {
409         PvmfNodesSyncControlInterface* myInterface = OSCL_STATIC_CAST(PvmfNodesSyncControlInterface*, this);
410         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
411         ++iExtensionRefCount;
412     }
413     else if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
414     {
415         PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this);
416         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
417         ++iExtensionRefCount;
418     }
419     else
420     {
421         iface = NULL;
422         return false;
423     }
424 
425     return true;
426 }
427 
428 ////////////////////////////////////////////////////////////////////////////
SetClock(PVMFMediaClock * aClock)429 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::SetClock(PVMFMediaClock* aClock)
430 {
431     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
432                     (0, "PVMediaOutputNode::SetClock: aClock=0x%x", aClock));
433 
434     //remove any old clock
435     if (iClock)
436     {
437         if (iMIOClockExtension)
438             iMIOClockExtension->SetClock(NULL);
439         for (uint32 i = 0; i < iInPortVector.size(); i++)
440             iInPortVector[i]->SetClock(NULL);
441     }
442 
443     iClock = aClock;
444     for (uint32 i = 0; i < iInPortVector.size(); i++)
445     {
446         iInPortVector[i]->SetClock(aClock);
447         iInPortVector[i]->ChangeClockRate(iClockRate);
448     }
449 
450     //pass the clock to the optional MIO clock interface
451     if (iMIOClockExtension)
452     {
453         iMIOClockExtension->SetClock(aClock);
454     }
455     else
456     {
457 #if (PVMF_MEDIA_OUTPUT_NODE_ENABLE_AV_SYNC)
458         //turn on sync params
459         for (uint32 i = 0; i < iInPortVector.size(); i++)
460         {
461             iInPortVector[i]->EnableMediaSync();
462             iInPortVector[i]->SetMargins(iEarlyMargin, iLateMargin);
463         }
464 #endif
465     }
466     return PVMFSuccess;
467 }
468 
469 ///////////////////////////////////////////////////////////////////////////
ChangeClockRate(int32 aRate)470 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::ChangeClockRate(int32 aRate)
471 {
472     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
473                     (0, "PVMediaOutputNode::ChangeClockRate: aRate=%d", aRate));
474 
475     iClockRate = aRate;
476     for (uint32 i = 0; i < iInPortVector.size() ; i++)
477         iInPortVector[i]->ChangeClockRate(aRate);
478 
479     // For now support all rates.
480     // In future, need to check with underlying media IO component
481 
482     return PVMFSuccess;
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////
SetMargins(int32 aEarlyMargin,int32 aLateMargin)486 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::SetMargins(int32 aEarlyMargin, int32 aLateMargin)
487 {
488     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
489                     (0, "PVMediaOutputNode::SetMargins: aEarlyMargin=%d, aLateMargin=%d", aEarlyMargin, aLateMargin));
490 
491     //save the margins
492     iEarlyMargin = aEarlyMargin;
493     iLateMargin = aLateMargin;
494 
495     //pass the margins to the ports
496     for (uint32 i = 0; i < iInPortVector.size() ; i++)
497         iInPortVector[i]->SetMargins(aEarlyMargin, aLateMargin);
498 
499     return PVMFSuccess;
500 }
501 
502 ////////////////////////////////////////////////////////////////////////////
ClockStarted()503 OSCL_EXPORT_REF void PVMediaOutputNode::ClockStarted()
504 {
505     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
506                     (0, "PVMediaOutputNode::ClockStarted"));
507 
508     //notify the ports
509     for (uint32 i = 0; i < iInPortVector.size() ; i++)
510         iInPortVector[i]->ClockStarted();
511 
512 }
513 
514 ////////////////////////////////////////////////////////////////////////////
ClockStopped()515 OSCL_EXPORT_REF void PVMediaOutputNode::ClockStopped()
516 {
517     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
518                     (0, "PVMediaOutputNode::ClockStopped"));
519 
520     //notify the ports
521     for (uint32 i = 0; i < iInPortVector.size() ; i++)
522         iInPortVector[i]->ClockStopped();
523 }
524 
525 
526 ////////////////////////////////////////////////////////////////////////////
SkipMediaData(PVMFSessionId s,PVMFTimestamp aResumeTimestamp,uint32 aStreamID,bool aPlayBackPositionContinuous,OsclAny * aContext)527 OSCL_EXPORT_REF PVMFCommandId PVMediaOutputNode::SkipMediaData(PVMFSessionId s,
528         PVMFTimestamp aResumeTimestamp,
529         uint32 aStreamID,
530         bool aPlayBackPositionContinuous,
531         OsclAny* aContext)
532 {
533     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
534                     (0, "PVMediaOutputNode::SkipMediaData() called "));
535     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
536                     (0, "PVMediaOutputNode::SkipMediaData() called - Mime=%s", iSinkFormatString.get_str()));
537     PVMediaOutputNodeCmd cmd;
538     cmd.Construct(s,
539                   PVMF_MEDIAOUTPUTNODE_SKIPMEDIADATA,
540                   aResumeTimestamp,
541                   aStreamID,
542                   aPlayBackPositionContinuous,
543                   aContext);
544     return QueueCommandL(cmd);
545 }
546 
547 ////////////////////////////////////////////////////////////////////////////
RequestCompleted(const PVMFCmdResp & aResponse)548 OSCL_EXPORT_REF void PVMediaOutputNode::RequestCompleted(const PVMFCmdResp& aResponse)
549 //callback from the MIO module.
550 {
551     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
552                     (0, "PVMediaOutputNode::RequestCompleted: Cmd ID=%d", aResponse.GetCmdId()));
553 
554     //look for cancel completion.
555     if (iMediaIOCancelPending
556             && aResponse.GetCmdId() == iMediaIOCancelCmdId)
557     {
558         iMediaIOCancelPending = false;
559 
560         OSCL_ASSERT(!iCancelCommand.empty());
561 
562         //Current cancel command is now complete.
563         CommandComplete(iCancelCommand, iCancelCommand.front(), PVMFSuccess);
564     }
565     //look for non-cancel completion
566     else if (iMediaIORequest != ENone
567              && aResponse.GetCmdId() == iMediaIOCmdId)
568     {
569         OSCL_ASSERT(!iCurrentCommand.empty());
570         PVMediaOutputNodeCmd& cmd = iCurrentCommand.front();
571 
572         switch (iMediaIORequest)
573         {
574             case EQueryCapability:
575                 iMIOConfig = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, iMIOConfigPVI);
576                 iMIOConfigPVI = NULL;
577                 if (aResponse.GetCmdStatus() != PVMFSuccess)
578                     cmd.iEventCode = PVMFMoutNodeErr_MediaIOQueryCapConfigInterface;
579                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
580                 break;
581 
582             case EQueryClockExtension:
583                 //ignore any error from this query since the interface is optional.
584                 iMediaIORequest = ENone;
585                 iMIOClockExtension = OSCL_STATIC_CAST(PvmiClockExtensionInterface*, iMIOClockExtensionPVI);
586                 iMIOClockExtensionPVI = NULL;
587                 //re-do the clock setting call since iMIOClockExtension may have changed.
588                 if (aResponse.GetCmdStatus() == PVMFSuccess
589                         && iMIOClockExtension)
590                 {
591                     SetClock(iClock);
592                 }
593                 //To continue the Node Init, query for the
594                 //capability & config interface
595                 {
596                     PVMFStatus status = SendMioRequest(iCurrentCommand[0], EQueryCapability);
597                     if (status == PVMFPending)
598                         return;//wait on response
599                     else
600                         CommandComplete(iCurrentCommand, iCurrentCommand.front(), status);
601                 }
602                 break;
603 
604             case EInit:
605                 if (aResponse.GetCmdStatus() != PVMFSuccess)
606                     cmd.iEventCode = PVMFMoutNodeErr_MediaIOInit;
607                 else
608                     iMediaIOState = STATE_INITIALIZED;
609                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
610                 break;
611 
612             case EStart:
613                 if (aResponse.GetCmdStatus() != PVMFSuccess)
614                     cmd.iEventCode = PVMFMoutNodeErr_MediaIOStart;
615                 else
616                     iMediaIOState = STATE_STARTED;
617                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
618                 break;
619 
620             case EPause:
621                 if (aResponse.GetCmdStatus() != PVMFSuccess)
622                     cmd.iEventCode = PVMFMoutNodeErr_MediaIOPause;
623                 else
624                     iMediaIOState = STATE_PAUSED;
625                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
626                 break;
627 
628             case EStop:
629                 if (aResponse.GetCmdStatus() != PVMFSuccess)
630                     cmd.iEventCode = PVMFMoutNodeErr_MediaIOStop;
631                 else
632                     iMediaIOState = STATE_INITIALIZED;
633                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
634                 break;
635 
636             case EDiscard:
637             {
638                 if (aResponse.GetCmdStatus() != PVMFSuccess)
639                 {
640                     cmd.iEventCode = PVMFMoutNodeErr_MediaIODiscardData;
641                     CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
642                 }
643                 else
644                 {
645                     iMediaIORequest = ENone;
646                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
647                                     (0, "PVMediaOutputNode::ResuestCompleted - EDiscard success - Mime=%s",
648                                      iSinkFormatString.get_str()));
649                     //attempt to complete skip media data
650                     CompleteSkipMediaData();
651                 }
652             }
653             break;
654 
655             case EReset:
656             {
657                 if (aResponse.GetCmdStatus() != PVMFSuccess)
658                 {
659                     cmd.iEventCode = PVMFMoutNodeErr_MediaIOReset;
660                 }
661                 else
662                 {
663                     iMediaIOState = STATE_LOGGED_ON;
664                 }
665                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
666             }
667             break;
668 
669             default:
670                 OSCL_ASSERT(false);
671                 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
672                 break;
673         }
674 
675     }
676     else
677     {
678         //unexpected response.
679         LOGERROR((0, "PVMediaOutputNode:RequestComplete Warning! Unexpected command ID %d"
680                   , aResponse.GetCmdId()));
681     }
682 }
683 
ReportErrorEvent(PVMFEventType aEventType,PVInterface * aExtMsg)684 OSCL_EXPORT_REF void PVMediaOutputNode::ReportErrorEvent(PVMFEventType aEventType, PVInterface* aExtMsg)
685 {
686     OSCL_UNUSED_ARG(aEventType);
687     OSCL_UNUSED_ARG(aExtMsg);
688 }
ReportInfoEvent(PVMFEventType aEventType,PVInterface * aExtMsg)689 OSCL_EXPORT_REF void PVMediaOutputNode::ReportInfoEvent(PVMFEventType aEventType, PVInterface* aExtMsg)
690 {
691     OSCL_UNUSED_ARG(aExtMsg);
692     if (PVMFMIOConfigurationComplete == aEventType)
693     {
694         LOGINFO((0, "PVMediaOutputNode::ReportInfoEvent PVMFMIOConfigurationComplete received"));
695         for (uint32 i = 0; i < iInPortVector.size(); i++)
696         {
697             iInPortVector[i]->SetMIOComponentConfigStatus(true);
698         }
699     }
700 }
701 
702 
703 ////////////////////////////////////////////////////////////////////////////
PVMediaOutputNode()704 PVMediaOutputNode::PVMediaOutputNode()
705         : OsclActiveObject(OsclActiveObject::EPriorityNominal, "PVMediaOutputNode")
706         , iEventUuid(PVMFMediaOutputNodeEventTypesUUID)
707         , iMIOControl(NULL)
708         , iMIOSession(NULL)
709         , iMIOConfig(NULL)
710         , iMIOConfigPVI(NULL)
711         , iMediaIOState(STATE_IDLE)
712         , iClock(NULL)
713         , iEarlyMargin(DEFAULT_EARLY_MARGIN)
714         , iLateMargin(DEFAULT_LATE_MARGIN)
715         , iDiagnosticsLogger(NULL)
716         , iDiagnosticsLogged(false)
717         , iExtensionRefCount(0)
718         , iLogger(NULL)
719         , iReposLogger(NULL)
720         , iRecentBOSStreamID(0)
721 {
722 }
723 
724 ////////////////////////////////////////////////////////////////////////////
ConstructL(PvmiMIOControl * aIOInterfacePtr)725 void PVMediaOutputNode::ConstructL(PvmiMIOControl* aIOInterfacePtr)
726 {
727     iLogger = NULL;
728     iMIOControl = aIOInterfacePtr;
729     iInputCommands.Construct(1, 10);//reserve 10
730     iCurrentCommand.Construct(1, 1);//reserve 1.
731     iCancelCommand.Construct(1, 1);//reserve 1.
732     iInPortVector.Construct(0);//reserve zero
733     iMediaIORequest = ENone;
734     iMediaIOCancelPending = false;
735     iMIOClockExtension = NULL;
736     iMIOClockExtensionPVI = NULL;
737     iClockRate = 100000;
738 }
739 
740 ////////////////////////////////////////////////////////////////////////////
741 /**
742 //This routine is called by various command APIs to queue an
743 //asynchronous command for processing by the command handler AO.
744 //This function may leave if the command can't be queued due to
745 //memory allocation failure.
746 */
QueueCommandL(PVMediaOutputNodeCmd & aCmd)747 PVMFCommandId PVMediaOutputNode::QueueCommandL(PVMediaOutputNodeCmd& aCmd)
748 {
749     PVMFCommandId id;
750 
751     id = iInputCommands.AddL(aCmd);
752 
753     //wakeup the AO
754     RunIfNotReady();
755 
756     return id;
757 }
758 
759 /**
760 //The various command handlers call this when a command is complete.
761 */
CommandComplete(PVMediaOutputNodeCmdQ & aCmdQ,PVMediaOutputNodeCmd & aCmd,PVMFStatus aStatus,OsclAny * aEventData)762 void PVMediaOutputNode::CommandComplete(PVMediaOutputNodeCmdQ& aCmdQ, PVMediaOutputNodeCmd& aCmd, PVMFStatus aStatus, OsclAny*aEventData)
763 {
764     if (aStatus == PVMFSuccess || aCmd.iCmd == PVMF_GENERIC_NODE_QUERYINTERFACE) //(mg) treat QueryIF failures as info, not errors
765     {
766         LOGINFO((0, "PVMediaOutputNode:CommandComplete Id %d Cmd %d Status %d Context %d EVData %d EVCode %d"
767                  , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData, aCmd.iEventCode));
768     }
769     else
770     {
771         LOGERROR((0, "PVMediaOutputNode:CommandComplete Error! Id %d Cmd %d Status %d Context %d EVData %d EVCode %d"
772                   , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData, aCmd.iEventCode));
773     }
774 
775     //do state transitions and any final command completion.
776     if (aStatus == PVMFSuccess)
777     {
778         switch (aCmd.iCmd)
779         {
780             case PVMF_GENERIC_NODE_INIT:
781                 SetState(EPVMFNodeInitialized);
782                 break;
783             case PVMF_GENERIC_NODE_PREPARE:
784                 SetState(EPVMFNodePrepared);
785                 break;
786             case PVMF_GENERIC_NODE_START:
787                 SetState(EPVMFNodeStarted);
788                 {
789                     for (uint32 i = 0; i < iInPortVector.size(); i++)
790                         iInPortVector[i]->NodeStarted();
791                 }
792                 break;
793             case PVMF_GENERIC_NODE_PAUSE:
794                 SetState(EPVMFNodePaused);
795                 break;
796             case PVMF_GENERIC_NODE_STOP:
797                 SetState(EPVMFNodePrepared);
798                 break;
799             case PVMF_GENERIC_NODE_FLUSH:
800                 SetState(EPVMFNodePrepared);
801                 //resume port input so the ports can be re-started.
802                 {
803                     for (uint32 i = 0; i < iInPortVector.size(); i++)
804                         iInPortVector[i]->ResumeInput();
805                 }
806                 break;
807             case PVMF_GENERIC_NODE_RESET:
808                 SetState(EPVMFNodeIdle);
809                 break;
810             default:
811                 break;
812         }
813     }
814 
815     //Reset the media I/O request
816     iMediaIORequest = ENone;
817     {
818         //Extract parameters needed for command response.
819         PVMFCommandId cmdId = aCmd.iId;
820         const OsclAny* cmdContext = aCmd.iContext;
821         PVMFSessionId cmdSess = aCmd.iSession;
822         PVMFStatus eventCode = aCmd.iEventCode;
823 
824         //Erase the command from the queue.
825         aCmdQ.Erase(&aCmd);
826 
827         if (eventCode != PVMFMoutNodeErr_First)
828         {
829             //create extended response.
830 
831             PVMFBasicErrorInfoMessage*eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (eventCode, iEventUuid, NULL));
832 
833             PVMFCmdResp resp(cmdId
834                              , cmdContext
835                              , aStatus
836                              , OSCL_STATIC_CAST(PVInterface*, eventmsg)
837                              , aEventData);
838 
839             //report to the session observers.
840             PVMFNodeInterface::ReportCmdCompleteEvent(cmdSess, resp);
841 
842             //remove the ref to the extended response
843             if (eventmsg)
844                 eventmsg->removeRef();
845         }
846         else
847         {
848             //create basic response
849             PVMFCmdResp resp(cmdId, cmdContext, aStatus, aEventData);
850 
851             //report to the session observers.
852             PVMFNodeInterface::ReportCmdCompleteEvent(cmdSess, resp);
853         }
854     }
855     //re-schedule if there are more commands and node isn't logged off
856     if (!iInputCommands.empty()
857             && IsAdded())
858         RunIfNotReady();
859 }
860 
861 
862 ////////////////////////////////////////////////////////////////////////////
Run()863 void PVMediaOutputNode::Run()
864 {
865     //Process async node commands.
866     if (!iInputCommands.empty())
867     {
868         ProcessCommand();
869     }
870 
871     //Check for completion of a flush command...
872     if (iCurrentCommand.size() > 0
873             && iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH
874             && PortQueuesEmpty())
875     {
876         //Flush is complete.
877         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
878     }
879 }
880 
PortQueuesEmpty()881 bool PVMediaOutputNode::PortQueuesEmpty()
882 {
883     uint32 i;
884     for (i = 0; i < iInPortVector.size(); i++)
885     {
886         if (iInPortVector[i]->IncomingMsgQueueSize() > 0 ||
887                 iInPortVector[i]->OutgoingMsgQueueSize())
888         {
889             return false;
890         }
891     }
892     return true;
893 }
894 
895 /**
896 //Called by the command handler AO to process a command from
897 //the input queue.
898 */
ProcessCommand()899 void PVMediaOutputNode::ProcessCommand()
900 {
901     //Can't do anything when an asynchronous cancel is in progress-- just
902     //need to wait on completion.
903     if (!iCancelCommand.empty())
904     {
905         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
906                         (0, "PVMediaOutputNode::ProcessCommand Cancel pending so return"));
907         return ; //keep waiting.
908     }
909 
910     //If a command is in progress, only certain commands can interrupt it.
911     if (!iCurrentCommand.empty()
912             && !iInputCommands.front().caninterrupt())
913     {
914         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
915                         (0, "PVMediaOutputNode::ProcessCommand Command pending so return"));
916         return ; //keep waiting
917     }
918 
919     //The newest or highest pri command is in the front of the queue.
920     OSCL_ASSERT(!iInputCommands.empty());
921     PVMediaOutputNodeCmd& aCmd = iInputCommands.front();
922 
923     PVMFStatus cmdstatus;
924     OsclAny* aEventData = NULL;
925     if (aCmd.caninterrupt())
926     {
927         //save input command in cancel command
928         int32 err;
929         OSCL_TRY(err, iCancelCommand.StoreL(aCmd););
930         if (err != OsclErrNone)
931         {
932             cmdstatus = PVMFErrNoMemory;
933         }
934         else
935         {
936             //Process the interrupt commands.
937             switch (aCmd.iCmd)
938             {
939                 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
940                     cmdstatus = DoCancelAllCommands(aCmd);
941                     break;
942 
943                 case PVMF_GENERIC_NODE_CANCELCOMMAND:
944                     cmdstatus = DoCancelCommand(aCmd);
945                     break;
946 
947                 default:
948                     OSCL_ASSERT(false);
949                     cmdstatus = PVMFFailure;
950                     break;
951             }
952         }
953 
954         //erase the input command.
955         if (cmdstatus != PVMFPending)
956         {
957             //Request already failed or completed successfully -- erase from Cancel Command.
958             //Node command remains in Input Commands to be completed at end of this function
959             if (iCancelCommand.size() > 0)
960                 iCancelCommand.Erase(&iCancelCommand.front());
961         }
962         else
963         {
964             //Cancel is still pending.
965             //Node command is now stored in Cancel Command, so erase from Input Commands and wait
966             iInputCommands.Erase(&aCmd);
967         }
968     }
969     else
970     {
971         //save input command in current command
972         int32 err;
973         OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
974         if (err != OsclErrNone)
975         {
976             cmdstatus = PVMFErrNoMemory;
977         }
978         else
979         {
980             //Process the normal pri commands.
981             switch (aCmd.iCmd)
982             {
983                 case PVMF_GENERIC_NODE_QUERYUUID:
984                     cmdstatus = DoQueryUuid(aCmd);
985                     break;
986 
987                 case PVMF_GENERIC_NODE_QUERYINTERFACE:
988                     cmdstatus = DoQueryInterface(aCmd);
989                     break;
990 
991                 case PVMF_GENERIC_NODE_REQUESTPORT:
992                     cmdstatus = DoRequestPort(aCmd, aEventData);
993                     break;
994 
995                 case PVMF_GENERIC_NODE_RELEASEPORT:
996                     cmdstatus = DoReleasePort(aCmd);
997                     break;
998 
999                 case PVMF_GENERIC_NODE_INIT:
1000                     cmdstatus = DoInit(aCmd);
1001                     break;
1002 
1003                 case PVMF_GENERIC_NODE_PREPARE:
1004                     cmdstatus = DoPrepare(aCmd);
1005                     break;
1006 
1007                 case PVMF_GENERIC_NODE_START:
1008                     cmdstatus = DoStart(aCmd);
1009                     break;
1010 
1011                 case PVMF_GENERIC_NODE_STOP:
1012                     cmdstatus = DoStop(aCmd);
1013                     break;
1014 
1015                 case PVMF_GENERIC_NODE_FLUSH:
1016                     cmdstatus = DoFlush(aCmd);
1017                     break;
1018 
1019                 case PVMF_GENERIC_NODE_PAUSE:
1020                     cmdstatus = DoPause(aCmd);
1021                     break;
1022 
1023                 case PVMF_GENERIC_NODE_RESET:
1024                     cmdstatus = DoReset(aCmd);
1025                     break;
1026 
1027                 case PVMF_MEDIAOUTPUTNODE_SKIPMEDIADATA:
1028                     cmdstatus = DoSkipMediaData(aCmd);
1029                     break;
1030 
1031                 default://unknown command type
1032                     OSCL_ASSERT(false);
1033                     cmdstatus = PVMFFailure;
1034                     break;
1035             }
1036         }
1037 
1038         //erase the input command.
1039         if (cmdstatus != PVMFPending)
1040         {
1041             //Request already failed-- erase from Current Command.
1042             //Node command remains in Input Commands.
1043             iCurrentCommand.Erase(&iCurrentCommand.front());
1044         }
1045         else
1046         {
1047             //Node command is now stored in Current Command, so erase from Input Commands.
1048             iInputCommands.Erase(&aCmd);
1049         }
1050     }
1051 
1052     if (cmdstatus != PVMFPending)
1053     {
1054         CommandComplete(iInputCommands, aCmd, cmdstatus, aEventData);
1055     }
1056 }
1057 
1058 ////////////////////////////////////////////////////////////////////////////
DoQueryUuid(PVMediaOutputNodeCmd & aCmd)1059 PVMFStatus PVMediaOutputNode::DoQueryUuid(PVMediaOutputNodeCmd& aCmd)
1060 {
1061     //This node supports Query UUID from any state
1062 
1063     OSCL_String* mimetype;
1064     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
1065     bool exactmatch;
1066     aCmd.PVMediaOutputNodeCmdBase::Parse(mimetype, uuidvec, exactmatch);
1067 
1068     uuidvec->push_back(PvmfNodesSyncControlUuid);
1069 
1070     return PVMFSuccess;
1071 }
1072 
1073 ////////////////////////////////////////////////////////////////////////////
DoQueryInterface(PVMediaOutputNodeCmd & aCmd)1074 PVMFStatus PVMediaOutputNode::DoQueryInterface(PVMediaOutputNodeCmd& aCmd)
1075 {
1076     PVUuid* uuid;
1077     PVInterface** ptr;
1078     aCmd.PVMediaOutputNodeCmdBase::Parse(uuid, ptr);
1079     if (uuid && ptr)
1080     {
1081         if (queryInterface(*uuid, *ptr))
1082             return PVMFSuccess;
1083     }
1084     return PVMFFailure;
1085 }
1086 
1087 ////////////////////////////////////////////////////////////////////////////
DoRequestPort(PVMediaOutputNodeCmd & aCmd,OsclAny * & aEventData)1088 PVMFStatus PVMediaOutputNode::DoRequestPort(PVMediaOutputNodeCmd& aCmd, OsclAny*&aEventData)
1089 {
1090     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1091                     (0, "PVMediaOutputNode::DoRequestPort"));
1092     //This node supports port request from any state
1093 
1094     //retrieve port tag & mimetype
1095     int32 tag;
1096     OSCL_String* mimetype;
1097     aCmd.PVMediaOutputNodeCmdBase::Parse(tag, mimetype);
1098 
1099     switch (tag)
1100     {
1101         case PVMF_MEDIAIO_NODE_INPUT_PORT_TAG:
1102         {
1103             //Allocate a new port
1104             OsclAny *ptr = NULL;
1105             int32 err;
1106             OSCL_TRY(err, ptr = iInPortVector.Allocate(););
1107             if (err != OsclErrNone || !ptr)
1108             {
1109                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1110                                 (0, "PVMediaOutputNode::DoRequestPort: Error - iInPortVector Out of memory"));
1111                 return PVMFErrNoMemory;
1112             }
1113             PVMediaOutputNodePort *port = OSCL_PLACEMENT_NEW(ptr, PVMediaOutputNodePort(this));
1114 
1115             //Add the port to the port vector.
1116             OSCL_TRY(err, iInPortVector.AddL(port););
1117             if (err != OsclErrNone)
1118             {
1119                 iInPortVector.DestructAndDealloc(port);
1120                 return PVMFErrNoMemory;
1121             }
1122 
1123             //set the format from the mimestring, if provided
1124             if (mimetype)
1125             {
1126                 PVMFStatus status = port->Configure(*mimetype);
1127                 if (status != PVMFSuccess)
1128                 {
1129                     //bad format!
1130                     iInPortVector.Erase(&port);
1131                     iInPortVector.DestructAndDealloc(port);
1132                     return PVMFErrArgument;
1133                 }
1134             }
1135 
1136             iSinkFormatString = *mimetype;
1137 
1138             //pass the current clock settings to the port.
1139             SetClock(iClock);
1140 
1141             //cast the port to the generic interface before returning.
1142             PVMFPortInterface*retval = port;
1143             aEventData = (OsclAny*)retval;
1144             return PVMFSuccess;
1145         }
1146         break;
1147 
1148         default:
1149         {
1150             //bad port tag
1151             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1152                             (0, "PVMediaOutputNode::DoRequestPort: Error - Invalid port tag"));
1153             return PVMFFailure;
1154         }
1155         break;
1156     }
1157 }
1158 
1159 ////////////////////////////////////////////////////////////////////////////
DoInit(PVMediaOutputNodeCmd & aCmd)1160 PVMFStatus PVMediaOutputNode::DoInit(PVMediaOutputNodeCmd& aCmd)
1161 {
1162     OSCL_UNUSED_ARG(aCmd);
1163 
1164     if (iInterfaceState != EPVMFNodeIdle)
1165         return PVMFErrInvalidState;
1166 
1167     if (!iMIOControl)
1168     {
1169         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1170                         (0, "PVMediaOutputNode::DoInit: Error - iMIOControl is NULL"));
1171         aCmd.iEventCode = PVMFMoutNodeErr_MediaIONotExist;
1172         return PVMFFailure;
1173     }
1174 
1175     //Query for MIO interfaces.
1176     return SendMioRequest(aCmd, EQueryClockExtension);
1177 }
1178 
1179 ////////////////////////////////////////////////////////////////////////////
DoPrepare(PVMediaOutputNodeCmd & aCmd)1180 PVMFStatus PVMediaOutputNode::DoPrepare(PVMediaOutputNodeCmd& aCmd)
1181 {
1182     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1183                     (0, "PVMediaOutputNode::DoPrepare"));
1184 
1185     if (iInterfaceState != EPVMFNodeInitialized)
1186         return PVMFErrInvalidState;
1187 
1188     return SendMioRequest(aCmd, EInit);
1189 
1190 }
1191 
1192 ////////////////////////////////////////////////////////////////////////////
DoStart(PVMediaOutputNodeCmd & aCmd)1193 PVMFStatus PVMediaOutputNode::DoStart(PVMediaOutputNodeCmd& aCmd)
1194 {
1195     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1196                     (0, "PVMediaOutputNode::DoStart"));
1197 
1198     if (iInterfaceState != EPVMFNodePrepared
1199             && iInterfaceState != EPVMFNodePaused)
1200         return PVMFErrInvalidState;
1201 
1202     iDiagnosticsLogged = false;
1203     iInPortVector[0]->iFramesDropped = 0;
1204     iInPortVector[0]->iTotalFrames = 0;
1205 
1206     //Start the MIO
1207 
1208     return SendMioRequest(aCmd, EStart);
1209 }
1210 
1211 
1212 ////////////////////////////////////////////////////////////////////////////
DoStop(PVMediaOutputNodeCmd & aCmd)1213 PVMFStatus PVMediaOutputNode::DoStop(PVMediaOutputNodeCmd& aCmd)
1214 {
1215     //clear the message queues of any unprocessed data now.
1216     uint32 i;
1217     for (i = 0; i < iInPortVector.size(); i++)
1218     {
1219         iInPortVector[i]->ClearMsgQueues();
1220     }
1221     if (iInterfaceState != EPVMFNodeStarted
1222             && iInterfaceState != EPVMFNodePaused)
1223         return PVMFErrInvalidState;
1224 
1225     LogDiagnostics();
1226 
1227     if (iMediaIOState == STATE_STARTED || iMediaIOState == STATE_PAUSED)
1228     {
1229         //Stop the MIO component only if MIOs are in Paused or Started states.
1230         return SendMioRequest(aCmd, EStop);
1231     }
1232     else
1233     {
1234         // no stop needed if MIOs are not in started or paused states. return success.
1235         return PVMFSuccess;
1236     }
1237 }
1238 
1239 ////////////////////////////////////////////////////////////////////////////
DoFlush(PVMediaOutputNodeCmd & aCmd)1240 PVMFStatus PVMediaOutputNode::DoFlush(PVMediaOutputNodeCmd& aCmd)
1241 {
1242     OSCL_UNUSED_ARG(aCmd);
1243 
1244     if (iInterfaceState != EPVMFNodeStarted
1245             && iInterfaceState != EPVMFNodePaused)
1246         return PVMFErrInvalidState;
1247 
1248     //Disable the input.
1249     if (iInPortVector.size() > 0)
1250     {
1251         for (uint32 i = 0; i < iInPortVector.size(); i++)
1252             iInPortVector[i]->SuspendInput();
1253     }
1254 
1255     //wait for all data to be consumed
1256     return PVMFPending;
1257 }
1258 
1259 ////////////////////////////////////////////////////////////////////////////
DoPause(PVMediaOutputNodeCmd & aCmd)1260 PVMFStatus PVMediaOutputNode::DoPause(PVMediaOutputNodeCmd& aCmd)
1261 {
1262 
1263     if (iInterfaceState != EPVMFNodeStarted)
1264         return PVMFErrInvalidState;
1265 
1266     return SendMioRequest(aCmd, EPause);
1267 }
1268 
1269 ////////////////////////////////////////////////////////////////////////////
DoSkipMediaData(PVMediaOutputNodeCmd & aCmd)1270 PVMFStatus PVMediaOutputNode::DoSkipMediaData(PVMediaOutputNodeCmd& aCmd)
1271 {
1272     //Here is what we do during skip:
1273     //1) We pass the skiptimestamp to ports. This is to make sure that
1274     //they can start tossing out data ASAP
1275     //2) We send DiscardData to media output components. Failure to
1276     //queue discarddata on mediaoutput comps is considered fatal failure
1277     //and will result in skip failure on media output node
1278     //3) Then we wait for all discard data to complete and all ports to
1279     //report BOS. Ports call "ReportBOS" when they recv BOS.
1280 
1281     PVMFTimestamp resumeTimestamp;
1282     bool playbackpositioncontinuous;
1283     uint32 streamID;
1284     aCmd.Parse(resumeTimestamp,
1285                playbackpositioncontinuous,
1286                streamID);
1287     iRecentBOSStreamID = streamID;
1288 
1289     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
1290                     (0, "PVMediaOutputNode::DoSkipMediaData - Mime=%s, SkipTS=%d, StreamID=%d, SFR=%d",
1291                      iSinkFormatString.get_str(),
1292                      resumeTimestamp,
1293                      iRecentBOSStreamID,
1294                      playbackpositioncontinuous));
1295 
1296     //although we treat inport as a vector, we still
1297     //assume just one media output comp per node
1298     if (iInPortVector.size() > 0)
1299     {
1300         iInPortVector[0]->SetSkipTimeStamp(resumeTimestamp, iRecentBOSStreamID);
1301     }
1302     else
1303     {
1304         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_ERR,
1305                         (0, "PVMediaOutputNode::DoSkipMediaData - No Input Ports - Mime=%s", iSinkFormatString.get_str()));
1306         return PVMFErrInvalidState;
1307     }
1308 
1309     PVMFStatus status = PVMFFailure;
1310     if (playbackpositioncontinuous == true)
1311     {
1312         //source node has not be involved in determining this skip
1313         //boundaries. in this case if an EOS has been sent to the mio
1314         //component, then do not call discard data
1315         //assume that there is only one port per mio node and one
1316         //mio comp per node.
1317         //also do NOT ever call discard data in case of compressed mio
1318         if (iInPortVector[0]->isUnCompressedMIO == true)
1319         {
1320             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
1321                             (0, "PVMediaOutputNode::DoSkipMediaData - SFR - Calling DiscardData - Mime=%s", iSinkFormatString.get_str()));
1322             status = SendMioRequest(aCmd, EDiscard);
1323             if (status != PVMFPending)
1324             {
1325                 iMediaIORequest = ENone;
1326                 return status;
1327             }
1328         }
1329         else
1330         {
1331             // For Compressed MIO, we need not call discard data and should report Skip Media Complete
1332             // right away.
1333             return PVMFSuccess;
1334         }
1335     }
1336     else
1337     {
1338         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
1339                         (0, "PVMediaOutputNode::DoSkipMediaData - Calling DiscardData - Mime=%s", iSinkFormatString.get_str()));
1340         status = SendMioRequest(aCmd, EDiscard);
1341         if (status != PVMFPending)
1342         {
1343             iMediaIORequest = ENone;
1344             return status;
1345         }
1346     }
1347     //wait on discard
1348     return status;
1349 }
1350 
CompleteSkipMediaData()1351 void PVMediaOutputNode::CompleteSkipMediaData()
1352 {
1353     if ((!iCurrentCommand.empty()) &&
1354             ((iCurrentCommand.front().iCmd == PVMF_MEDIAOUTPUTNODE_SKIPMEDIADATA)))
1355     {
1356         if (iMediaIORequest == ENone)
1357         {
1358             //implies that discard is complete
1359             if (CheckForBOS() == PVMFSuccess)
1360             {
1361                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
1362                                 (0, "PVMediaOutputNode::CompleteSkipMediaData - SkipComplete - Mime=%s", iSinkFormatString.get_str()));
1363                 CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFSuccess);
1364                 for (uint32 i = 0; i < iInPortVector.size(); i++)
1365                 {
1366                     //clear out the bos stream id vec on all ports so that they is no confusion later on
1367                     iInPortVector[i]->ClearPreviousBOSStreamIDs(iRecentBOSStreamID);
1368                 }
1369                 return;
1370             }
1371         }
1372         //else continue waiting on the discard to complete.
1373     }
1374     else
1375     {
1376         //this means that either skipmediadata cmd is yet to be issued or processed
1377         //this should be a problem since ports record the BOS stream ids which would
1378         //be checked later
1379         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_ERR,
1380                         (0, "PVMediaOutputNode::CompleteSkipMediaData - Waiting On SkipCmd To Be Issued/Processed - Mime=%s", iSinkFormatString.get_str()));
1381         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1382                         (0, "PVMediaOutputNode::CompleteSkipMediaData - Waiting On SkipCmd To Be Issued/Processed - Mime=%s", iSinkFormatString.get_str()));
1383     }
1384 }
1385 
1386 
1387 ////////////////////////////////////////////////////////////////////////////
DoCancelAllCommands(PVMediaOutputNodeCmd & aCmd)1388 PVMFStatus PVMediaOutputNode::DoCancelAllCommands(PVMediaOutputNodeCmd& aCmd)
1389 {
1390     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1391                     (0, "PVMediaOutputNode::DoCancelAllCommands In"));
1392 
1393     if (!iCurrentCommand.empty())
1394     {
1395         if (iCurrentCommand.front().iCmd == PVMF_MEDIAOUTPUTNODE_SKIPMEDIADATA)
1396         {
1397             for (uint32 i = 0; i < iInPortVector.size(); i++)
1398             {
1399                 iInPortVector[i]->CancelSkip();
1400             }
1401         }
1402     }
1403 
1404     //First cancel any MIO commmand in progress.
1405     bool cancelmiopending = false;
1406     if (iMediaIORequest != ENone)
1407     {
1408         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1409                         (0, "PVMediaOutputNode::DoCancelAllCommands Cancelling any pending MIO request"));
1410         if (CancelMioRequest(aCmd) == PVMFPending)
1411         {
1412             cancelmiopending = true;
1413         }
1414     }
1415 
1416     //Then cancel the current command if any
1417     {
1418         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1419                         (0, "PVMediaOutputNode::DoCancelAllCommands Cancelling current command"));
1420         while (!iCurrentCommand.empty())
1421         {
1422             CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
1423         }
1424     }
1425 
1426     //next cancel all queued commands
1427     {
1428         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1429                         (0, "PVMediaOutputNode::DoCancelAllCommands Cancelling all queued commands"));
1430         //start at element 1 since this cancel command is element 0.
1431         while (iInputCommands.size() > 1)
1432         {
1433             CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
1434         }
1435     }
1436 
1437     if (cancelmiopending)
1438     {
1439         // Need to wait for MIO cancel to complete before completing
1440         // the cancelall command
1441         return PVMFPending;
1442     }
1443     else
1444     {
1445         //Cancel is complete
1446         return PVMFSuccess;
1447     }
1448 }
1449 
1450 ////////////////////////////////////////////////////////////////////////////
DoCancelCommand(PVMediaOutputNodeCmd & aCmd)1451 PVMFStatus PVMediaOutputNode::DoCancelCommand(PVMediaOutputNodeCmd& aCmd)
1452 {
1453     //extract the command ID from the parameters.
1454     PVMFCommandId id;
1455     aCmd.PVMediaOutputNodeCmdBase::Parse(id);
1456 
1457     //first check "current" command if any
1458     {
1459         PVMediaOutputNodeCmd* cmd = iCurrentCommand.FindById(id);
1460         if (cmd)
1461         {
1462             if (cmd->iCmd == PVMF_MEDIAOUTPUTNODE_SKIPMEDIADATA)
1463             {
1464                 //cancel any SkipMediaData in progress on the ports.
1465                 for (uint32 i = 0; i < iInPortVector.size(); i++)
1466                 {
1467                     iInPortVector[i]->CancelSkip();
1468                 }
1469             }
1470 
1471             //Check if MIO request needs to be cancelled
1472             bool pendingmiocancel = false;
1473             if (iMediaIORequest != ENone)
1474             {
1475                 if (CancelMioRequest(aCmd) == PVMFPending)
1476                 {
1477                     pendingmiocancel = true;
1478                 }
1479             }
1480 
1481             //Cancel the queued command
1482             CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
1483 
1484             if (pendingmiocancel)
1485             {
1486                 // Wait for MIO cancel to complete
1487                 // before completing CancelCommand
1488                 return PVMFPending;
1489             }
1490             else
1491             {
1492                 //report cancel success
1493                 return PVMFSuccess;
1494             }
1495         }
1496     }
1497 
1498     //next check input queue.
1499     {
1500         //start at element 1 since this cancel command is element 0.
1501         PVMediaOutputNodeCmd* cmd = iInputCommands.FindById(id, 1);
1502         if (cmd)
1503         {
1504             //cancel the queued command
1505             CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
1506             //report cancel success
1507             return PVMFSuccess;
1508         }
1509     }
1510     //if we get here the command isn't queued so the cancel fails.
1511     aCmd.iEventCode = PVMFMoutNodeErr_CmdNotQueued;
1512     return PVMFFailure;
1513 }
1514 
1515 ////////////////////////////////////////////////////////////////////////////
DoReleasePort(PVMediaOutputNodeCmd & aCmd)1516 PVMFStatus PVMediaOutputNode::DoReleasePort(PVMediaOutputNodeCmd& aCmd)
1517 {
1518     //This node supports release port from any state
1519     PVMFPortInterface* p;
1520     aCmd.PVMediaOutputNodeCmdBase::Parse(p);
1521     //search the input port vector
1522     {
1523         PVMediaOutputNodePort* port = (PVMediaOutputNodePort*)p;
1524         PVMediaOutputNodePort** portPtr = iInPortVector.FindByValue(port);
1525         if (portPtr)
1526         {
1527             (*portPtr)->Disconnect();
1528             iInPortVector.Erase(portPtr);
1529             return PVMFSuccess;
1530         }
1531     }
1532     aCmd.iEventCode = PVMFMoutNodeErr_PortNotExist;
1533     return PVMFFailure;
1534 }
1535 
1536 ////////////////////////////////////////////////////////////////////////////
DoReset(PVMediaOutputNodeCmd & aCmd)1537 PVMFStatus PVMediaOutputNode::DoReset(PVMediaOutputNodeCmd& aCmd)
1538 {
1539     OSCL_UNUSED_ARG(aCmd);
1540 
1541     LogDiagnostics();
1542 
1543     // delete all ports and notify observer.
1544     while (!iInPortVector.empty())
1545     {
1546         iInPortVector.front()->Disconnect();
1547         iInPortVector.Erase(&iInPortVector.front());
1548     }
1549 
1550     // restore original port vector reserve.
1551     iInPortVector.Reconstruct();
1552 
1553     if ((iInterfaceState == EPVMFNodeIdle) ||
1554             (iInterfaceState == EPVMFNodeCreated))
1555     {
1556         // node is either in Created or Idle state, no need to call Reset on MIO. MIO has not been
1557         // connected yet so no need to send a asynchronous command to MIO.
1558         return PVMFSuccess;
1559     }
1560     else
1561     {
1562         return SendMioRequest(aCmd, EReset);
1563     }
1564 }
1565 
1566 ////////////////////////////////////////////////////////////////////////////
CancelMioRequest(PVMediaOutputNodeCmd & aCmd)1567 PVMFStatus PVMediaOutputNode::CancelMioRequest(PVMediaOutputNodeCmd& aCmd)
1568 {
1569     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1570                     (0, "PVMediaOutputNode::CancelMioRequest In"));
1571 
1572     OSCL_ASSERT(iMediaIORequest != ENone);
1573 
1574     OSCL_ASSERT(!iMediaIOCancelPending);
1575 
1576     //Issue the cancel to the MIO.
1577     iMediaIOCancelPending = true;
1578     int32 err;
1579     OSCL_TRY(err, iMediaIOCancelCmdId = iMIOControl->CancelCommand(iMediaIOCmdId););
1580     if (err != OsclErrNone)
1581     {
1582         aCmd.iEventCode = PVMFMoutNodeErr_MediaIOCancelCommand;
1583         iMediaIOCancelPending = false;
1584         LOGINFOHI((0, "PVMediaOutputNode::CancelMioRequest: CancelCommand on MIO failed"));
1585         return PVMFFailure;
1586     }
1587     LOGINFOHI((0, "PVMediaOutputNode::CancelMioRequest: Cancel Command Issued to MIO component, waiting on response..."));
1588     return PVMFPending;//wait on request to cancel.
1589 }
1590 
1591 ////////////////////////////////////////////////////////////////////////////
SendMioRequest(PVMediaOutputNodeCmd & aCmd,EMioRequest aRequest)1592 PVMFStatus PVMediaOutputNode::SendMioRequest(PVMediaOutputNodeCmd& aCmd, EMioRequest aRequest)
1593 {
1594     //Make an asynchronous request to MIO component
1595     //and save the request in iMediaIORequest.
1596 
1597 
1598     //there should not be a MIO command in progress..
1599     OSCL_ASSERT(iMediaIORequest == ENone);
1600 
1601 
1602     //save media io request.
1603     iMediaIORequest = aRequest;
1604 
1605     PVMFStatus status;
1606 
1607     //Issue the command to the MIO.
1608     switch (aRequest)
1609     {
1610         case EQueryCapability:
1611         {
1612             int32 err ;
1613             iMIOConfigPVI = NULL;
1614             OSCL_TRY(err,
1615                      iMediaIOCmdId = iMIOControl->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID,
1616                                      iMIOConfigPVI, NULL);
1617                     );
1618 
1619             if (err != OsclErrNone)
1620             {
1621                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1622                                 (0, "PVMediaOutputNode::SendMioRequest: Error - iMIOControl->QueryInterface(cap & config) failed"));
1623                 aCmd.iEventCode = PVMFMoutNodeErr_MediaIOQueryCapConfigInterface;
1624                 status = PVMFFailure;
1625             }
1626             else
1627             {
1628                 status = PVMFPending;
1629             }
1630         }
1631         break;
1632 
1633         case EQueryClockExtension:
1634         {
1635             int32 err ;
1636             iMIOClockExtensionPVI = NULL;
1637             OSCL_TRY(err,
1638                      iMediaIOCmdId = iMIOControl->QueryInterface(PvmiClockExtensionInterfaceUuid,
1639                                      iMIOClockExtensionPVI, NULL);
1640                     );
1641 
1642             if (err != OsclErrNone)
1643             {
1644                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1645                                 (0, "PVMediaOutputNode::SendMioRequest: Error iMIOControl->QueryInterface(clock ext) failed"));
1646                 //this interface is optional so ignore the error
1647                 status = PVMFSuccess;
1648             }
1649             else
1650             {
1651                 status = PVMFPending;
1652             }
1653         }
1654         break;
1655 
1656         case EInit:
1657         {
1658             int32 err = OsclErrNone;
1659             PvmiMediaTransfer* mediaTransfer = NULL;
1660             if (iInPortVector.size() > 0)
1661             {
1662                 mediaTransfer = iInPortVector[0]->getMediaTransfer();
1663             }
1664 
1665             OSCL_TRY(err, iMediaIOCmdId = iMIOControl->Init(););
1666             if ((err != OsclErrNone))
1667             {
1668                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1669                                 (0, "PVMediaOutputNode::SendMioRequest: Error - iMIOControl->Init failed"));
1670                 aCmd.iEventCode = PVMFMoutNodeErr_MediaIOInit;
1671                 status = PVMFFailure;
1672             }
1673             else
1674             {
1675                 status = PVMFPending;
1676             }
1677         }
1678         break;
1679 
1680         case EStart:
1681         {
1682 
1683             int32 err = OsclErrNone;
1684             PvmiMediaTransfer* mediaTransfer = NULL;
1685             if (iInPortVector.size() > 0)
1686             {
1687                 mediaTransfer = iInPortVector[0]->getMediaTransfer();
1688             }
1689             if (mediaTransfer != NULL)
1690             {
1691                 OSCL_TRY(err, iMediaIOCmdId = iMIOControl->Start(););
1692             }
1693             if ((err != OsclErrNone) || (mediaTransfer == NULL))
1694             {
1695                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1696                                 (0, "PVMediaOutputNode::SendMioRequest: Error - iMIOControl->Start failed"));
1697                 aCmd.iEventCode = PVMFMoutNodeErr_MediaIOStart;
1698                 status = PVMFFailure;
1699             }
1700             else
1701             {
1702                 status = PVMFPending;
1703             }
1704         }
1705         break;
1706 
1707         case EPause:
1708         {
1709             int32 err = OsclErrNone;
1710             PvmiMediaTransfer* mediaTransfer = NULL;
1711             if (iInPortVector.size() > 0)
1712             {
1713                 mediaTransfer = iInPortVector[0]->getMediaTransfer();
1714             }
1715             if (mediaTransfer != NULL)
1716             {
1717                 OSCL_TRY(err, iMediaIOCmdId = iMIOControl->Pause(););
1718             }
1719             if ((err != OsclErrNone) || (mediaTransfer == NULL))
1720             {
1721                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1722                                 (0, "PVMediaOutputNode::SendMioRequest: Error - iMIOControl->Pause failed"));
1723                 aCmd.iEventCode = PVMFMoutNodeErr_MediaIOPause;
1724                 status = PVMFFailure;
1725             }
1726             else
1727             {
1728                 status = PVMFPending;
1729             }
1730         }
1731         break;
1732 
1733         case EStop:
1734         {
1735 
1736             int32 err = OsclErrNone;
1737             PvmiMediaTransfer* mediaTransfer = NULL;
1738             if (iInPortVector.size() > 0)
1739             {
1740                 mediaTransfer = iInPortVector[0]->getMediaTransfer();
1741             }
1742             else
1743             {
1744                 /*There can be cases where stop is called after ports have been released and in such cases
1745                 we succeed stop as no-op assuming a subsequent reset will be called which would
1746                 guarantee proper reset of mio comp. */
1747                 return PVMFSuccess;
1748             }
1749             if (mediaTransfer != NULL)
1750             {
1751                 OSCL_TRY(err, iMediaIOCmdId = iMIOControl->Stop(););
1752             }
1753             if ((err != OsclErrNone) || (mediaTransfer == NULL))
1754             {
1755                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1756                                 (0, "PVMediaOutputNode::SendMioRequest: Error - iMIOControl->Stop failed"));
1757                 aCmd.iEventCode = PVMFMoutNodeErr_MediaIOStop;
1758                 status = PVMFFailure;
1759             }
1760             else
1761             {
1762                 status = PVMFPending;
1763             }
1764         }
1765         break;
1766 
1767         case EDiscard:
1768         {
1769             int32 err = OsclErrNone;
1770             PvmiMediaTransfer* mediaTransfer = NULL;
1771             if (iInPortVector.size() > 0)
1772             {
1773                 mediaTransfer = iInPortVector[0]->getMediaTransfer();
1774             }
1775             if (mediaTransfer != NULL)
1776             {
1777                 PVMFTimestamp resumeTimestamp;
1778                 bool playbackpositioncontinuous;
1779                 uint32 streamId;
1780                 aCmd.Parse(resumeTimestamp, playbackpositioncontinuous, streamId);
1781                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
1782                                 (0, "PVMediaOutputNode::SendMioRequest(EDiscard): skipTimestamp=%d", resumeTimestamp));
1783                 OSCL_TRY(err, iMediaIOCmdId = iMIOControl->DiscardData(resumeTimestamp););
1784             }
1785             if ((err != OsclErrNone) || (mediaTransfer == NULL))
1786             {
1787                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1788                                 (0, "PVMediaOutputNode::SendMioRequest: Error - iMIOControl->DiscardData failed"));
1789                 aCmd.iEventCode = PVMFMoutNodeErr_MediaIODiscardData;
1790                 status = PVMFFailure;
1791             }
1792             else
1793             {
1794                 status = PVMFPending;
1795             }
1796         }
1797         break;
1798 
1799         case EReset:
1800         {
1801             int32 err ;
1802             OSCL_TRY(err, iMediaIOCmdId = iMIOControl->Reset(););
1803             if (err != OsclErrNone)
1804             {
1805                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1806                                 (0, "PVMediaOutputNode::SendMioRequest: Error - iMIOControl->Reset failed"));
1807                 aCmd.iEventCode = PVMFMoutNodeErr_MediaIOReset;
1808                 status = PVMFFailure;
1809             }
1810             else
1811             {
1812                 status = PVMFPending;
1813             }
1814         }
1815         break;
1816 
1817         default:
1818             OSCL_ASSERT(false);//unrecognized command.
1819             status = PVMFFailure;
1820             break;
1821     }
1822 
1823     if (status == PVMFPending)
1824     {
1825         LOGINFOHI((0, "PVMediaOutputNode:SendMIORequest: Command Issued to MIO component, waiting on response..."));
1826     }
1827 
1828     return status;
1829 }
1830 
1831 
1832 
1833 
1834 /////////////////////////////////////////////////////
1835 // Event reporting routines.
1836 /////////////////////////////////////////////////////
SetState(TPVMFNodeInterfaceState s)1837 void PVMediaOutputNode::SetState(TPVMFNodeInterfaceState s)
1838 {
1839     LOGINFO((0, "PVMediaOutputNode:SetState %d", s));
1840     PVMFNodeInterface::SetState(s);
1841 }
1842 
ReportErrorEvent(PVMFEventType aEventType,OsclAny * aEventData,PVMFStatus aEventCode)1843 void PVMediaOutputNode::ReportErrorEvent(PVMFEventType aEventType, OsclAny* aEventData, PVMFStatus aEventCode)
1844 {
1845     LOGERROR((0, "PVMediaOutputNode:NodeErrorEvent Type %d EVData %d EVCode %d"
1846               , aEventType, aEventData, aEventCode));
1847 
1848     //create the extension message if any.
1849     if (aEventCode != PVMFMoutNodeErr_First)
1850     {
1851         PVMFBasicErrorInfoMessage* eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, iEventUuid, NULL));
1852         PVMFAsyncEvent asyncevent(PVMFErrorEvent, aEventType, NULL, OSCL_STATIC_CAST(PVInterface*, eventmsg), aEventData, NULL, 0);
1853         PVMFNodeInterface::ReportErrorEvent(asyncevent);
1854         eventmsg->removeRef();
1855     }
1856     else
1857         PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
1858 }
1859 
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData,PVMFStatus aEventCode)1860 void PVMediaOutputNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData, PVMFStatus aEventCode)
1861 {
1862     LOGINFO((0, "PVMediaOutputNode:NodeInfoEvent Type %d EVData %d EVCode %d"
1863              , aEventType, aEventData, aEventCode));
1864 
1865     //create the extension message if any.
1866     if (aEventCode != PVMFMoutNodeErr_First)
1867     {
1868         PVMFBasicErrorInfoMessage* eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, iEventUuid, NULL));
1869         PVMFAsyncEvent asyncevent(PVMFErrorEvent, aEventType, NULL, OSCL_STATIC_CAST(PVInterface*, eventmsg), aEventData, NULL, 0);
1870         PVMFNodeInterface::ReportInfoEvent(asyncevent);
1871         eventmsg->removeRef();
1872     }
1873     else
1874         PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
1875 }
1876 
verifyParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)1877 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
1878 {
1879     OSCL_UNUSED_ARG(aSession);
1880     if (iMIOConfig)
1881     {
1882         return (iMIOConfig->verifyParametersSync(iMIOSession, aParameters, num_elements));
1883     }
1884     else
1885     {
1886         return PVMFFailure;
1887     }
1888 }
1889 
getParametersSync(PvmiMIOSession aSession,PvmiKeyType aIdentifier,PvmiKvp * & aParameters,int & aNumParamElements,PvmiCapabilityContext aContext)1890 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::getParametersSync(PvmiMIOSession aSession,
1891         PvmiKeyType aIdentifier,
1892         PvmiKvp*& aParameters,
1893         int& aNumParamElements,
1894         PvmiCapabilityContext aContext)
1895 {
1896     OSCL_UNUSED_ARG(aSession);
1897     return (iMIOConfig->getParametersSync(iMIOSession, aIdentifier, aParameters, aNumParamElements, aContext));
1898 }
1899 
releaseParameters(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)1900 OSCL_EXPORT_REF PVMFStatus PVMediaOutputNode::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
1901 {
1902     OSCL_UNUSED_ARG(aSession);
1903     return (iMIOConfig->releaseParameters(iMIOSession, aParameters, num_elements));
1904 }
1905 
ReportBOS()1906 void PVMediaOutputNode::ReportBOS()
1907 {
1908     CompleteSkipMediaData();
1909 }
1910 
CheckForBOS()1911 PVMFStatus PVMediaOutputNode::CheckForBOS()
1912 {
1913     Oscl_Vector<uint32, OsclMemAllocator>::iterator it;
1914     for (it = iInPortVector[0]->iBOSStreamIDVec.begin();
1915             it != iInPortVector[0]->iBOSStreamIDVec.end();
1916             it++)
1917     {
1918         if (*it == iRecentBOSStreamID)
1919         {
1920             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iReposLogger, PVLOGMSG_INFO,
1921                             (0, "PVMediaOutputNode::CheckForBOS - BOS Found - Mime=%s, BOSStreamID=%d",
1922                              iSinkFormatString.get_str(), iRecentBOSStreamID));
1923             //we have recvd BOS
1924             return PVMFSuccess;
1925         }
1926     }
1927     return PVMFPending;
1928 }
1929 
LogDiagnostics()1930 void PVMediaOutputNode::LogDiagnostics()
1931 {
1932     if (iDiagnosticsLogged == false)
1933     {
1934         iDiagnosticsLogged = true;
1935 
1936         if (!iInPortVector.empty())
1937         {
1938             LOGDIAGNOSTICS((0, "PVMediaOutputNode:LogDiagnostics Mime %s, FramesDropped/TotalFrames %d/%d"
1939                             , iSinkFormatString.get_str(), iInPortVector[0]->iFramesDropped, iInPortVector[0]->iTotalFrames));
1940         }
1941     }
1942 }
1943 
1944 
1945 
1946 
1947 
1948 
1949 
1950 
1951 
1952 
1953 
1954 
1955