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