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 pv_comms_io_node.cpp
20 * @brief
21 */
22
23 #include "oscl_base.h"
24 #include "pv_comms_io_node_factory.h"
25 #include "pv_comms_io_node.h"
26 #include "pv_comms_io_node_port.h"
27 #include "oscl_dll.h"
28 #include "pvmf_basic_errorinfomessage.h"
29 #include "pv_comms_io_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 LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
38 #define LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
39 #define LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
40 #define LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
41 #define LOGINFO(m) LOGINFOMED(m)
42
43 ////////////////////////////////////////////////////////////////////////////
44 OSCL_EXPORT_REF PVMFNodeInterface* PVCommsIONodeFactory::Create(PvmiMIOControl* aMIOInputControl, PvmiMIOControl *aMIOOutputControl, bool logBitstream)
45 {
46 return PVCommsIONode::Create(aMIOInputControl, aMIOOutputControl, logBitstream);
47 }
48
49 ////////////////////////////////////////////////////////////////////////////
Create(PvmiMIOControl * aMIOControl,bool logBitstream)50 OSCL_EXPORT_REF PVMFNodeInterface* PVCommsIONodeFactory::Create(PvmiMIOControl *aMIOControl, bool logBitstream)
51 {
52 return PVCommsIONode::Create(aMIOControl, logBitstream);
53 }
54
55
56 ////////////////////////////////////////////////////////////////////////////
Delete(PVMFNodeInterface * aNode)57 OSCL_EXPORT_REF void PVCommsIONodeFactory::Delete(PVMFNodeInterface* aNode)
58 {
59 PVCommsIONode::Release(aNode);
60 }
61
62 ////////////////////////////////////////////////////////////////////////////
Create(PvmiMIOControl * aMIOInputControl,PvmiMIOControl * aMIOOutputControl,bool logBitstream)63 PVMFNodeInterface* PVCommsIONode::Create(PvmiMIOControl* aMIOInputControl, PvmiMIOControl *aMIOOutputControl, bool logBitstream)
64 {
65 PVCommsIONode* node = OSCL_NEW(PVCommsIONode, (logBitstream));
66 if (node)
67 {
68 OSCL_TRAPSTACK_PUSH(node);
69 node->ConstructL(aMIOInputControl, aMIOOutputControl);
70 OSCL_TRAPSTACK_POP();
71 }
72 return (PVMFNodeInterface*)node;
73 }
74
75 ////////////////////////////////////////////////////////////////////////////
Create(PvmiMIOControl * aMIOControl,bool logBitstream)76 PVMFNodeInterface* PVCommsIONode::Create(PvmiMIOControl* aMIOControl, bool logBitstream)
77 {
78 PVCommsIONode* node = OSCL_NEW(PVCommsIONode, (logBitstream));
79 if (node)
80 {
81 OSCL_TRAPSTACK_PUSH(node);
82 node->ConstructL(aMIOControl);
83 OSCL_TRAPSTACK_POP();
84 }
85 return (PVMFNodeInterface*)node;
86 }
87
88 ////////////////////////////////////////////////////////////////////////////
Release(PVMFNodeInterface * aNode)89 void PVCommsIONode::Release(PVMFNodeInterface* aNode)
90 {
91 OSCL_DELETE(((PVCommsIONode*)aNode));
92 }
93
94 ////////////////////////////////////////////////////////////////////////////
ThreadLogon()95 OSCL_EXPORT_REF PVMFStatus PVCommsIONode::ThreadLogon()
96 {
97 if (iInterfaceState != EPVMFNodeCreated)
98 return PVMFErrInvalidState;
99
100 iLogger = PVLogger::GetLoggerObject("PVCommsIONode");
101
102 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
103 (0, "PVCommsIONode::ThreadLogon"));
104
105 if (!IsAdded())
106 AddToScheduler();
107
108 iMediaInputContext.ThreadLogon();
109 if (!(iMediaOutputContext == iMediaInputContext))
110 iMediaOutputContext.ThreadLogon();
111
112 SetState(EPVMFNodeIdle);
113 return PVMFSuccess;
114 }
115
116 ////////////////////////////////////////////////////////////////////////////
ThreadLogoff()117 OSCL_EXPORT_REF PVMFStatus PVCommsIONode::ThreadLogoff()
118 {
119 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
120 (0, "PVCommsIONode::ThreadLogoff"));
121
122 if (iInterfaceState != EPVMFNodeIdle)
123 return PVMFErrInvalidState;
124
125 if (IsAdded())
126 RemoveFromScheduler();
127
128 iLogger = NULL;
129
130 iMediaInputContext.ThreadLogoff();
131 if (!(iMediaOutputContext == iMediaInputContext))
132 iMediaOutputContext.ThreadLogoff();
133
134 SetState(EPVMFNodeCreated);
135 return PVMFSuccess;
136 }
137
138 ////////////////////////////////////////////////////////////////////////////
GetCapability(PVMFNodeCapability & aNodeCapability)139 OSCL_EXPORT_REF PVMFStatus PVCommsIONode::GetCapability(PVMFNodeCapability& aNodeCapability)
140 {
141 if (iInterfaceState == EPVMFNodeIdle ||
142 iInterfaceState == EPVMFNodeCreated)
143 return PVMFFailure;
144
145 if ((iMediaInputContext.isValid() && !iMediaInputContext.hasConfig()) ||
146 (iMediaOutputContext.isValid() && !iMediaOutputContext.hasConfig()))
147 return PVMFFailure;
148
149 aNodeCapability.iCanSupportMultipleInputPorts = false;
150 aNodeCapability.iCanSupportMultipleOutputPorts = false;
151 aNodeCapability.iHasMaxNumberOfPorts = true;
152 if (iMediaOutputContext.isValid() && iMediaInputContext.isValid())
153 aNodeCapability.iMaxNumberOfPorts = 2;
154 else
155 aNodeCapability.iMaxNumberOfPorts = 1;
156
157 PvmiKvp* kvp ;
158 int numParams ;
159 int32 err ;
160 int32 i ;
161 PVMFStatus status;
162
163 // Get input formats capability from media IO
164 kvp = NULL;
165 numParams = 0;
166
167 PvmiCapabilityAndConfig *inputConfig, *outputConfig;
168
169 inputConfig = iMediaInputContext.iMediaIOConfig;
170 outputConfig = iMediaOutputContext.iMediaIOConfig;
171
172 if (inputConfig)
173 {
174 status = inputConfig->getParametersSync(NULL,
175 OSCL_CONST_CAST(char*, INPUT_FORMATS_CAP_QUERY),
176 kvp, numParams, NULL);
177 if (status == PVMFSuccess)
178 {
179 OSCL_TRY(err,
180 for (i = 0; i < numParams; i++)
181 aNodeCapability.iInputFormatCapability.push_back(kvp[i].value.pChar_value););
182 if (kvp)
183 inputConfig->releaseParameters(0, kvp, numParams);
184 }
185 //else ignore errors.
186 }
187 // Get output formats capability from media IO
188 kvp = NULL;
189 numParams = 0;
190
191 if (outputConfig)
192 {
193 status = outputConfig->getParametersSync(NULL,
194 OSCL_CONST_CAST(char*, OUTPUT_FORMATS_CAP_QUERY),
195 kvp, numParams, NULL);
196 if (status == PVMFSuccess)
197 {
198 OSCL_TRY(err,
199 for (i = 0; i < numParams; i++)
200 aNodeCapability.iOutputFormatCapability.push_back(kvp[i].value.pChar_value);
201 );
202 if (kvp)
203 outputConfig->releaseParameters(0, kvp, numParams);
204 }
205 //else ignore errors.
206 }
207
208 if (aNodeCapability.iInputFormatCapability.empty() && aNodeCapability.iOutputFormatCapability.empty())
209 return PVMFFailure;
210
211 return PVMFSuccess;
212 }
213
214 ////////////////////////////////////////////////////////////////////////////
GetPorts(const PVMFPortFilter * aFilter)215 OSCL_EXPORT_REF PVMFPortIter* PVCommsIONode::GetPorts(const PVMFPortFilter* aFilter)
216 {
217 OSCL_UNUSED_ARG(aFilter);//port filter is not implemented.
218 iPortVector.Reset();
219 return &iPortVector;
220 }
221
222 ////////////////////////////////////////////////////////////////////////////
QueryUUID(PVMFSessionId s,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)223 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
224 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
225 bool aExactUuidsOnly,
226 const OsclAny* aContext)
227 {
228 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
229 (0, "PVCommsIONode::QueryUUID() called"));
230 PVCommsIONodeCmd cmd;
231 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
232 return QueueCommandL(cmd);
233 }
234
235 ////////////////////////////////////////////////////////////////////////////
QueryInterface(PVMFSessionId s,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)236 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
237 PVInterface*& aInterfacePtr,
238 const OsclAny* aContext)
239 {
240 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
241 (0, "PVCommsIONode::QueryInterface() called"));
242 PVCommsIONodeCmd cmd;
243 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
244 return QueueCommandL(cmd);
245 }
246
247 ////////////////////////////////////////////////////////////////////////////
RequestPort(PVMFSessionId s,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)248 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
249 {
250 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
251 (0, "PVCommsIONode::RequestPort() called"));
252 PVCommsIONodeCmd cmd;
253 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
254 return QueueCommandL(cmd);
255 }
256
257 ////////////////////////////////////////////////////////////////////////////
ReleasePort(PVMFSessionId s,PVMFPortInterface & aPort,const OsclAny * aContext)258 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
259 {
260 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
261 (0, "PVCommsIONode::ReleasePort() called"));
262 PVCommsIONodeCmd cmd;
263 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
264 return QueueCommandL(cmd);
265 }
266
267 ////////////////////////////////////////////////////////////////////////////
Init(PVMFSessionId s,const OsclAny * aContext)268 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::Init(PVMFSessionId s, const OsclAny* aContext)
269 {
270 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
271 (0, "PVCommsIONode::Init() called"));
272 PVCommsIONodeCmd cmd;
273 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
274 return QueueCommandL(cmd);
275 }
276
277 ////////////////////////////////////////////////////////////////////////////
Prepare(PVMFSessionId s,const OsclAny * aContext)278 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::Prepare(PVMFSessionId s, const OsclAny* aContext)
279 {
280 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
281 (0, "PVCommsIONode::Prepare() called"));
282 PVCommsIONodeCmd cmd;
283 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
284 return QueueCommandL(cmd);
285 }
286
287 ////////////////////////////////////////////////////////////////////////////
Start(PVMFSessionId s,const OsclAny * aContext)288 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::Start(PVMFSessionId s, const OsclAny* aContext)
289 {
290 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
291 (0, "PVCommsIONode::Start() called"));
292 PVCommsIONodeCmd cmd;
293 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
294 return QueueCommandL(cmd);
295 }
296
297 ////////////////////////////////////////////////////////////////////////////
Stop(PVMFSessionId s,const OsclAny * aContext)298 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::Stop(PVMFSessionId s, const OsclAny* aContext)
299 {
300 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
301 (0, "PVCommsIONode::Stop() called"));
302 PVCommsIONodeCmd cmd;
303 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
304 return QueueCommandL(cmd);
305 }
306
307 ////////////////////////////////////////////////////////////////////////////
Flush(PVMFSessionId s,const OsclAny * aContext)308 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::Flush(PVMFSessionId s, const OsclAny* aContext)
309 {
310 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
311 (0, "PVCommsIONode::Flush() called"));
312 PVCommsIONodeCmd cmd;
313 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
314 return QueueCommandL(cmd);
315 }
316
317 ////////////////////////////////////////////////////////////////////////////
Pause(PVMFSessionId s,const OsclAny * aContext)318 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::Pause(PVMFSessionId s, const OsclAny* aContext)
319 {
320 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
321 (0, "PVCommsIONode::Pause() called"));
322 PVCommsIONodeCmd cmd;
323 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
324 return QueueCommandL(cmd);
325 }
326
327 ////////////////////////////////////////////////////////////////////////////
Reset(PVMFSessionId s,const OsclAny * aContext)328 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::Reset(PVMFSessionId s, const OsclAny* aContext)
329 {
330 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
331 (0, "PVCommsIONode::Reset() called"));
332 PVCommsIONodeCmd cmd;
333 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
334 return QueueCommandL(cmd);
335 }
336
337 ////////////////////////////////////////////////////////////////////////////
CancelAllCommands(PVMFSessionId s,const OsclAny * aContext)338 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
339 {
340 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
341 (0, "PVCommsIONode::CancelAllCommands() called"));
342 PVCommsIONodeCmd cmd;
343 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
344 return QueueCommandL(cmd);
345 }
346
347 ////////////////////////////////////////////////////////////////////////////
CancelCommand(PVMFSessionId s,PVMFCommandId aCmdId,const OsclAny * aContext)348 OSCL_EXPORT_REF PVMFCommandId PVCommsIONode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
349 {
350 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
351 (0, "PVCommsIONode::CancelCommands() called cmdId=%d", aCmdId));
352 PVCommsIONodeCmd cmd;
353 cmd.PVCommsIONodeCmdBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
354 return QueueCommandL(cmd);
355 }
356
357 ////////////////////////////////////////////////////////////////////////////
addRef()358 OSCL_EXPORT_REF void PVCommsIONode::addRef()
359 {
360 ++iExtensionRefCount;
361 }
362
363 ////////////////////////////////////////////////////////////////////////////
removeRef()364 OSCL_EXPORT_REF void PVCommsIONode::removeRef()
365 {
366 if (iExtensionRefCount > 0)
367 --iExtensionRefCount;
368 }
369
370 ////////////////////////////////////////////////////////////////////////////
queryInterface(const PVUuid & uuid,PVInterface * & iface)371 OSCL_EXPORT_REF bool PVCommsIONode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
372 {
373 if (uuid == PvmfNodesSyncControlUuid)
374 {
375 PvmfNodesSyncControlInterface* myInterface = OSCL_STATIC_CAST(PvmfNodesSyncControlInterface*, this);
376 iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
377 ++iExtensionRefCount;
378 }
379 else
380 {
381 iface = NULL;
382 return false;
383 }
384
385 return true;
386 }
387
388 ////////////////////////////////////////////////////////////////////////////
RequestCompleted(const PVMFCmdResp & aResponse)389 OSCL_EXPORT_REF void PVCommsIONode::RequestCompleted(const PVMFCmdResp& aResponse)
390 //callback from the MIO module.
391 {
392 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
393 (0, "PVCommsIONode::RequestCompleted: Cmd ID=%d", aResponse.GetCmdId()));
394
395 //look for cancel completion.
396 if (iMediaIOCancelPending
397 && aResponse.GetCmdId() == iMediaIOCancelCmdId)
398 {
399 iMediaIOCancelPending = false;
400
401 Assert(!iCancelCommand.empty());
402
403 //Current cancel command is now complete.
404 CommandComplete(iCancelCommand, iCancelCommand.front(), PVMFSuccess);
405 }
406 //look for non-cancel completion
407 else if (iMediaIORequest != ENone
408 && aResponse.GetCmdId() == iMediaIOCmdId)
409 {
410 // Kind of tricky here. For each node request, ie Init()
411 // up to 2 asynchronous MIO requests will be made. We need
412 // to intercept the first MIO response here and make sure to
413 // send another one if necessary. The actual node command
414 // completion message won't be sent until we get the 2nd
415 // MIO response.
416 Assert(!iCurrentCommand.empty());
417 PVCommsIONodeCmd& cmd = iCurrentCommand.front();
418
419 switch (iMediaIORequest)
420 {
421 case EQueryCapability:
422 if (aResponse.GetCmdStatus() != PVMFSuccess)
423 {
424 cmd.iEventCode = PVCommsIONodeErr_MediaIOQueryCapConfigInterface;
425 }
426 else
427 {
428 if ((cmd.iCmd == PVMF_GENERIC_NODE_INIT) && iTempCapConfigInterface)
429 {
430 cmd.iControlContext->iMediaIOConfig = OSCL_STATIC_CAST(PvmiCapabilityAndConfig *, iTempCapConfigInterface);
431 iTempCapConfigInterface = NULL;
432
433 }
434 else
435 {
436 LOGERROR((0, "PVCommsIONode:RequestComplete Error:Not setting interface iCmd=%d,iTempCapConfigInterface=%x",
437 cmd.iCmd, iTempCapConfigInterface));
438
439
440 }
441 if (ReRunCommandForNextMIO(cmd))
442 {
443 return;
444 }
445 else if (cmd.iControlContext == &iMediaInputContext &&
446 iMediaInputContext.iControl == iMediaOutputContext.iControl)
447 {
448 // if we have a single object that supports both input and
449 // output, the context's controls will be identical, and
450 // we don't need to query the interface again, so we'll just
451 // copy the session and config interface
452 // to the output context, since they will be the same
453 iMediaOutputContext = iMediaInputContext;
454 }
455 }
456 break;
457
458 case EInit:
459 if (aResponse.GetCmdStatus() != PVMFSuccess)
460 {
461 cmd.iEventCode = PVCommsIONodeErr_MediaIOInit;
462 }
463 else if (ReRunCommandForNextMIO(cmd))
464 {
465 return;
466 }
467 else
468 {
469 iMediaIOState = MIO_STATE_INITIALIZED;
470 }
471 break;
472
473 case EStart:
474 if (aResponse.GetCmdStatus() != PVMFSuccess)
475 {
476 cmd.iEventCode = PVCommsIONodeErr_MediaIOStart;
477 }
478 else if (ReRunCommandForNextMIO(cmd))
479 {
480 return;
481 }
482 else
483 {
484 iMediaIOState = MIO_STATE_STARTED;
485 //tell all the ports that I/O is started.
486 {
487 uint32 i;
488 for (i = 0; i < iPortVector.size(); i++)
489 iPortVector[i]->MediaIOStarted();
490 }
491 }
492 break;
493
494 case EPause:
495 if (aResponse.GetCmdStatus() != PVMFSuccess)
496 {
497 cmd.iEventCode = PVCommsIONodeErr_MediaIOPause;
498 }
499 else if (ReRunCommandForNextMIO(cmd))
500 {
501 return;
502 }
503 else
504 {
505 iMediaIOState = MIO_STATE_PAUSED;
506 }
507 break;
508
509 case EStop:
510 if (aResponse.GetCmdStatus() != PVMFSuccess)
511 {
512 cmd.iEventCode = PVCommsIONodeErr_MediaIOStop;
513 }
514 else if (ReRunCommandForNextMIO(cmd))
515 {
516 return;
517 }
518 else
519 {
520 iMediaIOState = MIO_STATE_INITIALIZED;
521 }
522 break;
523
524 default:
525 Assert(false);
526 break;
527 }
528
529 //current node command is now complete.
530 if (IsFlushPending())
531 {
532 iMediaIORequest = ENone;
533 FlushComplete();
534 }
535 else
536 {
537 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aResponse.GetCmdStatus());
538 }
539 }
540 else
541 {
542 //unexpected response.
543 LOGERROR((0, "PVCommsIONode:RequestComplete Warning! Unexpected command ID %d"
544 , aResponse.GetCmdId()));
545 }
546 }
547
548 ////////////////////////////////////////////////////////////////////////////
ReportErrorEvent(PVMFEventType aEventType,PVInterface * aExtMsg)549 OSCL_EXPORT_REF void PVCommsIONode::ReportErrorEvent(PVMFEventType aEventType, PVInterface* aExtMsg)
550 {
551 OSCL_UNUSED_ARG(aEventType);
552 OSCL_UNUSED_ARG(aExtMsg);
553 }
554
555 ////////////////////////////////////////////////////////////////////////////
ReportInfoEvent(PVMFEventType aEventType,PVInterface * aExtMsg)556 OSCL_EXPORT_REF void PVCommsIONode::ReportInfoEvent(PVMFEventType aEventType, PVInterface* aExtMsg)
557 {
558 OSCL_UNUSED_ARG(aEventType);
559 OSCL_UNUSED_ARG(aExtMsg);
560 }
561
562 ////////////////////////////////////////////////////////////////////////////
PVCommsIONode(bool logBitstream)563 PVCommsIONode::PVCommsIONode(bool logBitstream)
564 : OsclActiveObject(OsclActiveObject::EPriorityNominal, "PVCommsIONode")
565 , iMediaIOState(PVCommsIONode::MIO_STATE_IDLE)
566 , iEventUuid(PVCommsIONodeEventTypesUUID)
567 , iExtensionRefCount(0)
568 , iLogger(NULL)
569 , iLogBitstream(logBitstream)
570 , iTempCapConfigInterface(NULL)
571 {
572 }
573
574 ////////////////////////////////////////////////////////////////////////////
~PVCommsIONode()575 PVCommsIONode::~PVCommsIONode()
576 {
577 Cancel();
578 if (IsAdded())
579 RemoveFromScheduler();
580
581 //if any MIO commands are outstanding, there will be
582 //a crash when they callback-- so panic here instead.
583 OSCL_ASSERT(!(!iCancelCommand.empty()
584 || iMediaIORequest != ENone));
585
586 //Cleanup allocated ports
587 while (!iPortVector.empty())
588 iPortVector.Erase(&iPortVector.front());
589
590 //Cleanup commands
591 //The command queues are self-deleting, but we want to
592 //notify the observer of unprocessed commands.
593 while (!iCurrentCommand.empty())
594 {
595 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
596 iCurrentCommand.Erase(&iCurrentCommand.front());
597 }
598 while (!iInputCommands.empty())
599 {
600 CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
601 iInputCommands.Erase(&iInputCommands.front());
602 }
603 }
604
605 ////////////////////////////////////////////////////////////////////////////
ConstructL(PvmiMIOControl * aMIOInputControl,PvmiMIOControl * aMIOOutputControl)606 void PVCommsIONode::ConstructL(PvmiMIOControl* aMIOInputControl, PvmiMIOControl *aMIOOutputControl)
607 {
608 if (((aMIOInputControl == NULL) && (aMIOOutputControl == NULL)) ||
609 aMIOInputControl == aMIOOutputControl)
610 OsclError::Leave(OsclErrArgument);
611 iLogger = NULL;
612 iMediaInputContext.iControl = aMIOInputControl;
613 iMediaOutputContext.iControl = aMIOOutputControl;
614 iPortActivity = 0;
615 iInputCommands.Construct(1, 10);//reserve 10
616 iCurrentCommand.Construct(1, 1);//reserve 1.
617 iCancelCommand.Construct(1, 1);//reserve 1.
618 iPortVector.Construct(0);//reserve zero.
619 iMediaIORequest = ENone;
620 iMediaIOCancelPending = false;
621 }
622
ConstructL(PvmiMIOControl * aMIOControl)623 void PVCommsIONode::ConstructL(PvmiMIOControl* aMIOControl)
624 {
625 if (aMIOControl == NULL)
626 OsclError::Leave(OsclErrArgument);
627
628 iLogger = NULL;
629 iMediaInputContext.iControl = aMIOControl;
630 iMediaOutputContext.iControl = aMIOControl;
631
632 iPortActivity = 0;
633 iInputCommands.Construct(1, 10);//reserve 10
634 iCurrentCommand.Construct(1, 1);//reserve 1.
635 iCancelCommand.Construct(1, 1);//reserve 1.
636 iPortVector.Construct(0);//reserve zero.
637 iMediaIORequest = ENone;
638 iMediaIOCancelPending = false;
639 }
640
641
642 ////////////////////////////////////////////////////////////////////////////
Run()643 void PVCommsIONode::Run()
644 {
645 //Process async node commands.
646 if (!iInputCommands.empty())
647 {
648 ProcessCommand();
649 }
650 }
651
652 ////////////////////////////////////////////////////////////////////////////
QueueCommandL(PVCommsIONodeCmd & aCmd)653 PVMFCommandId PVCommsIONode::QueueCommandL(PVCommsIONodeCmd& aCmd)
654 {
655 PVMFCommandId id;
656
657 id = iInputCommands.AddL(aCmd);
658
659 //wakeup the AO
660 RunIfNotReady();
661
662 return id;
663 }
664
665 ////////////////////////////////////////////////////////////////////////////
ProcessCommand()666 void PVCommsIONode::ProcessCommand()
667 {
668 //Can't do anything when an asynchronous cancel is in progress-- just
669 //need to wait on completion.
670 if (!iCancelCommand.empty())
671 return ; //keep waiting.
672
673 //If a command is in progress, only hi pri cancel commands can interrupt it.
674 if (!iCurrentCommand.empty()
675 && !iInputCommands.front().hipri())
676 {
677 return ; //keep waiting
678 }
679
680 //The newest or highest pri command is in the front of the queue.
681 Assert(!iInputCommands.empty());
682 PVCommsIONodeCmd& aCmd = iInputCommands.front();
683
684 PVMFStatus cmdstatus;
685 OsclAny* aEventData = NULL;
686 if (aCmd.hipri())
687 {
688 //save input command in cancel command
689 int32 err;
690 OSCL_TRY(err, iCancelCommand.StoreL(aCmd););
691 if (err != OsclErrNone)
692 {
693 cmdstatus = PVMFErrNoMemory;
694 }
695 else
696 {
697 //Process the interrupt commands.
698 switch (aCmd.iCmd)
699 {
700 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
701 cmdstatus = DoCancelAllCommands(aCmd);
702 break;
703
704 case PVMF_GENERIC_NODE_CANCELCOMMAND:
705 cmdstatus = DoCancelCommand(aCmd);
706 break;
707
708 default:
709 Assert(false);
710 cmdstatus = PVMFFailure;
711 break;
712 }
713 }
714
715 //erase the input command.
716 if (cmdstatus != PVMFPending)
717 {
718 //Request already failed-- erase from Cancel Command.
719 //Node command remains in Input Commands.
720 iCancelCommand.Erase(&iCurrentCommand.front());
721 }
722 else
723 {
724 //Node command is now stored in Cancel Command, so erase from Input Commands.
725 iInputCommands.Erase(&aCmd);
726 }
727 }
728 else
729 {
730 //save input command in current command
731 int32 err;
732 OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
733 if (err != OsclErrNone)
734 {
735 cmdstatus = PVMFErrNoMemory;
736 }
737 else
738 {
739 //Process the normal pri commands.
740 switch (aCmd.iCmd)
741 {
742 case PVMF_GENERIC_NODE_QUERYUUID:
743 cmdstatus = DoQueryUuid(aCmd);
744 break;
745
746 case PVMF_GENERIC_NODE_QUERYINTERFACE:
747 cmdstatus = DoQueryInterface(aCmd);
748 break;
749
750 case PVMF_GENERIC_NODE_REQUESTPORT:
751 cmdstatus = DoRequestPort(aCmd, aEventData);
752 break;
753
754 case PVMF_GENERIC_NODE_RELEASEPORT:
755 cmdstatus = DoReleasePort(aCmd);
756 break;
757
758 case PVMF_GENERIC_NODE_INIT:
759 cmdstatus = DoInit(aCmd);
760 break;
761
762 case PVMF_GENERIC_NODE_PREPARE:
763 cmdstatus = DoPrepare(aCmd);
764 break;
765
766 case PVMF_GENERIC_NODE_START:
767 cmdstatus = DoStart(aCmd);
768 break;
769
770 case PVMF_GENERIC_NODE_STOP:
771 cmdstatus = DoStop(aCmd);
772 break;
773
774 case PVMF_GENERIC_NODE_FLUSH:
775 cmdstatus = DoFlush(aCmd);
776 break;
777
778 case PVMF_GENERIC_NODE_PAUSE:
779 cmdstatus = DoPause(aCmd);
780 break;
781
782 case PVMF_GENERIC_NODE_RESET:
783 cmdstatus = DoReset(aCmd);
784 break;
785
786 default://unknown command type
787 Assert(false);
788 cmdstatus = PVMFFailure;
789 break;
790 }
791 }
792
793 //erase the input command.
794 if (cmdstatus != PVMFPending)
795 {
796 //Request already failed/succeeded-- erase from Current Command.
797 //Node command remains in Input Commands.
798 iCurrentCommand.Erase(&iCurrentCommand.front());
799 }
800 else
801 {
802 //Node command is now stored in Current Command, so erase from Input Commands.
803 //The DoXXX() routines will modify the command object, so we
804 //need to update the command object in the current command queue
805 iCurrentCommand[iCurrentCommand.size()-1] = aCmd;
806 iInputCommands.Erase(&aCmd);
807 }
808 }
809
810 if (cmdstatus != PVMFPending)
811 CommandComplete(iInputCommands, aCmd, cmdstatus, aEventData);
812
813 }
814
815 ////////////////////////////////////////////////////////////////////////////
CommandComplete(PVCommsIONodeCmdQ & aCmdQ,PVCommsIONodeCmd & aCmd,PVMFStatus aStatus,OsclAny * aEventData)816 void PVCommsIONode::CommandComplete(PVCommsIONodeCmdQ& aCmdQ, PVCommsIONodeCmd& aCmd, PVMFStatus aStatus, OsclAny*aEventData)
817 {
818 if (aStatus == PVMFSuccess)
819 {
820 LOGINFO((0, "PVCommsIONode:CommandComplete Id %d Cmd %d Status %d Context %d EVData %d EVCode %d"
821 , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData, aCmd.iEventCode));
822 }
823 else
824 {
825 LOGERROR((0, "PVCommsIONode:CommandComplete Error! Id %d Cmd %d Status %d Context %d EVData %d EVCode %d"
826 , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData, aCmd.iEventCode));
827 }
828
829 //do state transitions and any final command completion.
830 if (aStatus == PVMFSuccess)
831 {
832 switch (aCmd.iCmd)
833 {
834 case PVMF_GENERIC_NODE_INIT:
835 SetState(EPVMFNodeInitialized);
836 break;
837 case PVMF_GENERIC_NODE_PREPARE:
838 SetState(EPVMFNodePrepared);
839 break;
840 case PVMF_GENERIC_NODE_START:
841 SetState(EPVMFNodeStarted);
842 break;
843 case PVMF_GENERIC_NODE_PAUSE:
844 SetState(EPVMFNodePaused);
845 break;
846 case PVMF_GENERIC_NODE_STOP:
847 SetState(EPVMFNodePrepared);
848 //clear the message queues of any unprocessed data now.
849 {
850 uint32 i;
851 for (i = 0; i < iPortVector.size(); i++)
852 iPortVector[i]->ClearMsgQueues();
853 }
854 break;
855 case PVMF_GENERIC_NODE_FLUSH:
856 SetState(EPVMFNodePrepared);
857 //Stop the ports
858 {
859 for (uint32 i = 0; i < iPortVector.size(); i++)
860 iPortVector[i]->Stop();
861 }
862 break;
863 default:
864 break;
865 }
866 }
867
868 //Reset the media I/O request
869 iMediaIORequest = ENone;
870
871
872 //The "startmio" command originated from port activity,
873 //not from the node controller, so no command complete event
874 //is needed.
875 if (aCmd.iCmd == PVMF_COMMSIONODE_STARTMIO)
876 {
877 //Erase the command from the queue.
878 aCmdQ.Erase(&aCmd);
879 }
880 else
881 {
882 //Extract parameters needed for command response.
883 PVMFCommandId cmdId = aCmd.iId;
884 const OsclAny* cmdContext = aCmd.iContext;
885 PVMFSessionId cmdSess = aCmd.iSession;
886 PVMFStatus eventCode = aCmd.iEventCode;
887
888 //Erase the command from the queue.
889 aCmdQ.Erase(&aCmd);
890
891 if (eventCode != PVCommsIONodeErr_First)
892 {
893 //create extended response.
894
895 PVMFBasicErrorInfoMessage*eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (eventCode, iEventUuid, NULL));
896
897 PVMFCmdResp resp(cmdId
898 , cmdContext
899 , aStatus
900 , OSCL_STATIC_CAST(PVInterface*, eventmsg)
901 , aEventData);
902
903 //report to the session observers.
904 PVMFNodeInterface::ReportCmdCompleteEvent(cmdSess, resp);
905
906 //remove the ref to the extended response
907 if (eventmsg)
908 eventmsg->removeRef();
909 }
910 else
911 {
912 //create basic response
913 PVMFCmdResp resp(cmdId, cmdContext, aStatus, aEventData);
914
915 //report to the session observers.
916 PVMFNodeInterface::ReportCmdCompleteEvent(cmdSess, resp);
917 }
918 }
919 //re-schedule if there are more commands and node isn't logged off
920 if (!iInputCommands.empty()
921 && IsAdded())
922 RunIfNotReady();
923 }
924
925 ////////////////////////////////////////////////////////////////////////////
DoQueryUuid(PVCommsIONodeCmd & aCmd)926 PVMFStatus PVCommsIONode::DoQueryUuid(PVCommsIONodeCmd& aCmd)
927 {
928 //This node supports Query UUID from any state
929
930 OSCL_String* mimetype;
931 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
932 bool exactmatch;
933 aCmd.PVCommsIONodeCmdBase::Parse(mimetype, uuidvec, exactmatch);
934
935 uuidvec->push_back(PvmfNodesSyncControlUuid);
936
937 return PVMFSuccess;
938 }
939
940 ////////////////////////////////////////////////////////////////////////////
DoQueryInterface(PVCommsIONodeCmd & aCmd)941 PVMFStatus PVCommsIONode::DoQueryInterface(PVCommsIONodeCmd& aCmd)
942 {
943 PVUuid* uuid;
944 PVInterface** ptr;
945 aCmd.PVCommsIONodeCmdBase::Parse(uuid, ptr);
946 if (uuid && ptr)
947 {
948 if (queryInterface(*uuid, *ptr))
949 return PVMFSuccess;
950 }
951 return PVMFFailure;
952 }
953
954 ////////////////////////////////////////////////////////////////////////////
DoRequestPort(PVCommsIONodeCmd & aCmd,OsclAny * & aEventData)955 PVMFStatus PVCommsIONode::DoRequestPort(PVCommsIONodeCmd& aCmd, OsclAny*&aEventData)
956 {
957 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
958 (0, "PVCommsIONode::DoRequestPort"));
959 //This node supports port request from any state
960
961 //retrieve port tag & mimetype
962 int32 tag;
963 OSCL_String* mimetype;
964 aCmd.PVCommsIONodeCmdBase::Parse(tag, mimetype);
965
966 switch (tag)
967 {
968
969 case PVMF_COMMSIO_NODE_OUTPUT_PORT_TAG:
970 case PVMF_COMMSIO_NODE_INPUT_PORT_TAG:
971 case PVMF_COMMSIO_NODE_IO_PORT_TAG:
972 {
973 //Allocate a new port
974 OsclAny *ptr = NULL;
975 int32 err;
976 if (!ValidatePortTagRequest(tag))
977 return PVMFErrNotSupported;
978
979 OSCL_TRY(err, ptr = iPortVector.Allocate(););
980 if (err != OsclErrNone || !ptr)
981 {
982 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
983 (0, "PVCommsIONode::DoRequestPort: Error - iPortVector Out of memory"));
984 return PVMFErrNoMemory;
985 }
986 PVCommsIONodePort *port = OSCL_PLACEMENT_NEW(ptr, PVCommsIONodePort(tag, this));
987
988 //set the format from the mimestring.
989 if (mimetype)
990 {
991 PVMFFormatType fmt = mimetype->get_str();
992 if (fmt != PVMF_MIME_FORMAT_UNKNOWN)
993 port->Configure(fmt);
994 }
995
996 //Add the port to the port vector.
997 OSCL_TRY(err, iPortVector.AddL(port););
998 if (err != OsclErrNone)
999 {
1000 iPortVector.DestructAndDealloc(port);
1001 return PVMFErrNoMemory;
1002 }
1003 aEventData = (OsclAny*)port;
1004
1005 //cast the port to the generic interface before returning.
1006 PVMFPortInterface*retval = port;
1007 aEventData = (OsclAny*)retval;
1008 return PVMFSuccess;
1009 }
1010 break;
1011
1012 default:
1013 {
1014 //bad port tag
1015 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1016 (0, "PVCommsIONode::DoRequestPort: Error - Invalid port tag"));
1017 return PVMFFailure;
1018 }
1019 break;
1020 }
1021 }
1022
1023 ////////////////////////////////////////////////////////////////////////////
DoReleasePort(PVCommsIONodeCmd & aCmd)1024 PVMFStatus PVCommsIONode::DoReleasePort(PVCommsIONodeCmd& aCmd)
1025 {
1026 //This node supports release port from any state
1027
1028 PVMFPortInterface* p;
1029 aCmd.PVCommsIONodeCmdBase::Parse(p);
1030 //search the output port vector
1031 {
1032 PVCommsIONodePort* port = (PVCommsIONodePort*)p;
1033 PVCommsIONodePort** portPtr = iPortVector.FindByValue(port);
1034 if (portPtr)
1035 {
1036 (*portPtr)->Disconnect();
1037 iPortVector.Erase(portPtr);
1038 return PVMFSuccess;
1039 }
1040 }
1041 aCmd.iEventCode = PVCommsIONodeErr_PortNotExist;
1042 return PVMFFailure;
1043 }
1044
1045 ////////////////////////////////////////////////////////////////////////////
DoInit(PVCommsIONodeCmd & aCmd)1046 PVMFStatus PVCommsIONode::DoInit(PVCommsIONodeCmd& aCmd)
1047 {
1048 OSCL_UNUSED_ARG(aCmd);
1049 bool haveNewContext;
1050
1051 if (iInterfaceState != EPVMFNodeIdle)
1052 return PVMFErrInvalidState;
1053
1054 if (!(haveNewContext = GetNextContextInSequence(aCmd)) && aCmd.iControlContext == NULL)
1055 {
1056 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1057 (0, "PVCommsIONode::DoInit: Error - All media controls are NULL"));
1058 aCmd.iEventCode = PVCommsIONodeErr_MediaIONotExist;
1059 return PVMFFailure;
1060 }
1061 else if (aCmd.iControlContext->iControl->connect(aCmd.iControlContext->iMediaSession, this) != PVMFSuccess)
1062 {
1063 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1064 (0, "PVCommsIONode::DoInit: Error - iMediaIOControl->connect failed"));
1065 aCmd.iEventCode = PVCommsIONodeErr_MediaIOConnect;
1066 return PVMFFailure;
1067 }
1068
1069 //Query for MIO capability and config interface
1070 return SendMioRequest(aCmd, EQueryCapability);
1071 }
1072
1073 ////////////////////////////////////////////////////////////////////////////
DoPrepare(PVCommsIONodeCmd & aCmd)1074 PVMFStatus PVCommsIONode::DoPrepare(PVCommsIONodeCmd& aCmd)
1075 {
1076 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1077 (0, "PVCommsIONode::DoPrepare"));
1078
1079 if (iInterfaceState != EPVMFNodeInitialized)
1080 return PVMFErrInvalidState;
1081
1082 if (aCmd.iControlContext == NULL)
1083 GetNextContextInSequence(aCmd);
1084 return SendMioRequest(aCmd, EInit);
1085 }
1086
1087 ////////////////////////////////////////////////////////////////////////////
DoStart(PVCommsIONodeCmd & aCmd)1088 PVMFStatus PVCommsIONode::DoStart(PVCommsIONodeCmd& aCmd)
1089 {
1090 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1091 (0, "PVCommsIONode::DoStart"));
1092
1093 if (iInterfaceState != EPVMFNodePrepared
1094 && iInterfaceState != EPVMFNodePaused)
1095 return PVMFErrInvalidState;
1096
1097 //Start the MIO
1098 if (aCmd.iControlContext == NULL)
1099 GetNextContextInSequence(aCmd);
1100
1101 PVMFStatus status = SendMioRequest(aCmd, EStart);
1102
1103 if (status != PVMFPending)
1104 return status;
1105
1106 // don't start ports until last MIO start has been sent
1107 PVCommsIONodeCmd tempCmd = aCmd;
1108 if (!GetNextContextInSequence(tempCmd))
1109 {
1110 uint32 i = 0;
1111 for (i = 0; i < iPortVector.size(); i++)
1112 iPortVector[i]->Start();
1113 }
1114
1115 return status;
1116 }
1117
1118 ////////////////////////////////////////////////////////////////////////////
DoStop(PVCommsIONodeCmd & aCmd)1119 PVMFStatus PVCommsIONode::DoStop(PVCommsIONodeCmd& aCmd)
1120 {
1121 if (iInterfaceState != EPVMFNodeStarted
1122 && iInterfaceState != EPVMFNodePaused)
1123 return PVMFErrInvalidState;
1124
1125 //Stop the MIO
1126 if (aCmd.iControlContext == NULL)
1127 GetNextContextInSequence(aCmd);
1128
1129 PVMFStatus status = SendMioRequest(aCmd, EStop);
1130
1131 //Stop the ports
1132 for (uint32 i = 0; i < iPortVector.size(); i++)
1133 iPortVector[i]->Stop();
1134
1135 return status;
1136 }
1137
1138 ////////////////////////////////////////////////////////////////////////////
DoFlush(PVCommsIONodeCmd & aCmd)1139 PVMFStatus PVCommsIONode::DoFlush(PVCommsIONodeCmd& aCmd)
1140 {
1141 if (iInterfaceState != EPVMFNodeStarted
1142 && iInterfaceState != EPVMFNodePaused)
1143 return PVMFErrInvalidState;
1144
1145 //Disable the input.
1146 if (iPortVector.size() > 0)
1147 {
1148 //Stop the MIO input
1149 if (aCmd.iControlContext == NULL)
1150 GetNextContextInSequence(aCmd);
1151
1152 SendMioRequest(aCmd, EStop);
1153 //ignore returned error.
1154 }
1155 //wait for all data to be consumed
1156 return PVMFPending;
1157 }
1158
1159 ////////////////////////////////////////////////////////////////////////////
IsFlushPending()1160 bool PVCommsIONode::IsFlushPending()
1161 {
1162 return (iCurrentCommand.size() > 0
1163 && iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
1164 }
1165
1166 ////////////////////////////////////////////////////////////////////////////
FlushComplete()1167 void PVCommsIONode::FlushComplete()
1168 {
1169 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1170 (0, "PVMFVideoEncNode::FlushComplete"));
1171
1172 if (iMediaIORequest != ENone)
1173 {
1174 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1175 (0, "PVMFVideoEncNode::FlushComplete: Media IO request is pending"));
1176 return;
1177 }
1178
1179 if (!PortQueuesEmpty())
1180 {
1181 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1182 (0, "PVMFVideoEncNode::FlushComplete: Port queues are not empty"));
1183 return;
1184 }
1185
1186 //Flush is complete.
1187 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1188 (0, "PVMFVideoEncNode::FlushComplete: Done"));
1189 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
1190 }
1191
1192 ////////////////////////////////////////////////////////////////////////////
DoPause(PVCommsIONodeCmd & aCmd)1193 PVMFStatus PVCommsIONode::DoPause(PVCommsIONodeCmd& aCmd)
1194 {
1195 if (iInterfaceState != EPVMFNodeStarted)
1196 return PVMFErrInvalidState;
1197
1198 if (aCmd.iControlContext == NULL)
1199 GetNextContextInSequence(aCmd);
1200
1201 return SendMioRequest(aCmd, EPause);
1202 }
1203
1204 ////////////////////////////////////////////////////////////////////////////
DoReset(PVCommsIONodeCmd & aCmd)1205 PVMFStatus PVCommsIONode::DoReset(PVCommsIONodeCmd& aCmd)
1206 {
1207 OSCL_UNUSED_ARG(aCmd);
1208
1209 switch (iInterfaceState)
1210 {
1211 case EPVMFNodeCreated:
1212 case EPVMFNodeIdle:
1213 case EPVMFNodeInitialized:
1214 case EPVMFNodePrepared:
1215 {
1216 //delete all ports and notify observer.
1217 while (!iPortVector.empty())
1218 iPortVector.Erase(&iPortVector.front());
1219
1220 //restore original port vector reserve.
1221 iPortVector.Reconstruct();
1222
1223 //logoff & go back to Created state.
1224 SetState(EPVMFNodeIdle);
1225
1226 return PVMFSuccess;
1227 }
1228 break;
1229
1230 default:
1231 return PVMFErrInvalidState;
1232 break;
1233 }
1234 }
1235
1236 ////////////////////////////////////////////////////////////////////////////
DoCancelAllCommands(PVCommsIONodeCmd & aCmd)1237 PVMFStatus PVCommsIONode::DoCancelAllCommands(PVCommsIONodeCmd& aCmd)
1238 {
1239 //first cancel any MIO commmand in progress.
1240 if (iMediaIORequest != ENone)
1241 {
1242 return CancelMioRequest(aCmd);
1243 }
1244
1245 //first cancel the current command if any
1246 {
1247 while (!iCurrentCommand.empty())
1248 CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
1249 }
1250
1251 //next cancel all queued commands
1252 {
1253 //start at element 1 since this cancel command is element 0.
1254 while (iInputCommands.size() > 1)
1255 CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
1256 }
1257
1258 //finally, report cancel complete.
1259 return PVMFSuccess;
1260 }
1261
1262 ////////////////////////////////////////////////////////////////////////////
DoCancelCommand(PVCommsIONodeCmd & aCmd)1263 PVMFStatus PVCommsIONode::DoCancelCommand(PVCommsIONodeCmd& aCmd)
1264 {
1265 //tbd, need to cancel the MIO
1266
1267 //extract the command ID from the parameters.
1268 PVMFCommandId id;
1269 aCmd.PVCommsIONodeCmdBase::Parse(id);
1270
1271 //first check "current" command if any
1272 {
1273 PVCommsIONodeCmd* cmd = iCurrentCommand.FindById(id);
1274 if (cmd)
1275 {
1276 //first cancel any MIO commmand in progress.
1277 if (iMediaIORequest != ENone)
1278 {
1279 return CancelMioRequest(aCmd);
1280 }
1281 else
1282 {
1283 //cancel the queued command
1284 CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
1285 //report cancel success
1286 return PVMFSuccess;
1287 }
1288 }
1289 }
1290
1291 //next check input queue.
1292 {
1293 //start at element 1 since this cancel command is element 0.
1294 PVCommsIONodeCmd* cmd = iInputCommands.FindById(id, 1);
1295 if (cmd)
1296 {
1297 //cancel the queued command
1298 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
1299 //report cancel success
1300 return PVMFSuccess;
1301 }
1302 }
1303 //if we get here the command isn't queued so the cancel fails.
1304 aCmd.iEventCode = PVCommsIONodeErr_CmdNotQueued;
1305 return PVMFFailure;
1306 }
1307
1308 ////////////////////////////////////////////////////////////////////////////
SendMioRequest(PVCommsIONodeCmd & aCmd,EMioRequest aRequest)1309 PVMFStatus PVCommsIONode::SendMioRequest(PVCommsIONodeCmd& aCmd, EMioRequest aRequest)
1310 {
1311 //Make an asynchronous request to MIO component
1312 //and save the request in iMediaIORequest.
1313
1314
1315 //there should not be a MIO command in progress..
1316 Assert(iMediaIORequest == ENone);
1317
1318 //save media io request.
1319 iMediaIORequest = aRequest;
1320
1321 PVMFStatus status;
1322
1323 //Issue the command to the MIO.
1324 switch (aRequest)
1325 {
1326 case EQueryCapability:
1327 {
1328 int32 err ;
1329
1330 OSCL_TRY(err,
1331 iMediaIOCmdId = aCmd.iControlContext->iControl->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID,
1332 iTempCapConfigInterface , NULL);
1333 );
1334 if (err != OsclErrNone)
1335 {
1336 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1337 (0, "PVCommsIONode::DoInit: Error - iMediaIOControl->QueryInterface failed"));
1338 aCmd.iEventCode = PVCommsIONodeErr_MediaIOQueryCapConfigInterface;
1339 status = PVMFFailure;
1340 }
1341 else
1342 {
1343 status = PVMFPending;
1344 }
1345 }
1346 break;
1347
1348 case EInit:
1349 {
1350 if (iMediaIOState != MIO_STATE_IDLE)
1351 {
1352 aCmd.iEventCode = PVCommsIONodeErr_MediaIOWrongState;
1353 status = PVMFFailure;
1354 break;
1355 }
1356
1357 int32 err ;
1358 OSCL_TRY(err, iMediaIOCmdId = aCmd.iControlContext->iControl->Init(););
1359
1360 if (err != OsclErrNone)
1361 {
1362 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1363 (0, "PVCommsIONode::DoInit: Error - iMediaIOControl->Init failed"));
1364 aCmd.iEventCode = PVCommsIONodeErr_MediaIOInit;
1365 status = PVMFFailure;
1366 }
1367 else
1368 {
1369 status = PVMFPending;
1370 }
1371 }
1372 break;
1373
1374 case EStart:
1375 {
1376 if (iMediaIOState != MIO_STATE_INITIALIZED
1377 && iMediaIOState != MIO_STATE_PAUSED)
1378 {
1379 aCmd.iEventCode = PVCommsIONodeErr_MediaIOWrongState;
1380 status = PVMFFailure;
1381 break;
1382 }
1383
1384 int32 err ;
1385 OSCL_TRY(err, iMediaIOCmdId = aCmd.iControlContext->iControl->Start(););
1386
1387 if (err != OsclErrNone)
1388 {
1389 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1390 (0, "PVCommsIONode::DoInit: Error - iMediaIOControl->Start failed"));
1391 aCmd.iEventCode = PVCommsIONodeErr_MediaIOStart;
1392 status = PVMFFailure;
1393 }
1394 else
1395 {
1396 status = PVMFPending;
1397 }
1398 }
1399 break;
1400
1401 case EPause:
1402 {
1403 if (iMediaIOState != MIO_STATE_STARTED)
1404 {
1405 aCmd.iEventCode = PVCommsIONodeErr_MediaIOWrongState;
1406 status = PVMFFailure;
1407 break;
1408 }
1409
1410 int32 err ;
1411 OSCL_TRY(err, iMediaIOCmdId = aCmd.iControlContext->iControl->Pause(););
1412
1413 if (err != OsclErrNone)
1414 {
1415 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1416 (0, "PVCommsIONode::DoInit: Error - iMediaIOControl->Pause failed"));
1417 aCmd.iEventCode = PVCommsIONodeErr_MediaIOPause;
1418 status = PVMFFailure;
1419 }
1420 else
1421 {
1422 status = PVMFPending;
1423 }
1424 }
1425 break;
1426
1427 case EStop:
1428 {
1429 if (iMediaIOState != MIO_STATE_STARTED
1430 && iMediaIOState != MIO_STATE_PAUSED)
1431 {
1432 aCmd.iEventCode = PVCommsIONodeErr_MediaIOWrongState;
1433 status = PVMFFailure;
1434 break;
1435 }
1436
1437 int32 err ;
1438 OSCL_TRY(err, iMediaIOCmdId = aCmd.iControlContext->iControl->Stop(););
1439
1440 if (err != OsclErrNone)
1441 {
1442 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1443 (0, "PVCommsIONode::DoInit: Error - iMediaIOControl->Stop failed"));
1444 aCmd.iEventCode = PVCommsIONodeErr_MediaIOStop;
1445 status = PVMFFailure;
1446 }
1447 else
1448 {
1449 status = PVMFPending;
1450 }
1451 }
1452 break;
1453
1454 default:
1455 Assert(false);//unrecognized command.
1456 status = PVMFFailure;
1457 break;
1458 }
1459
1460 if (status == PVMFPending)
1461 {
1462 LOGINFOHI((0, "PVCommsIONode:SendMIORequest: Command Issued to MIO component, waiting on response..."));
1463 }
1464
1465 return status;
1466 }
1467
1468 ////////////////////////////////////////////////////////////////////////////
CancelMioRequest(PVCommsIONodeCmd & aCmd)1469 PVMFStatus PVCommsIONode::CancelMioRequest(PVCommsIONodeCmd& aCmd)
1470 {
1471 Assert(iMediaIORequest != ENone);
1472
1473 Assert(!iMediaIOCancelPending);
1474
1475 //Issue the cancel to the MIO.
1476 iMediaIOCancelPending = true;
1477 int32 err;
1478 OSCL_TRY(err, iMediaIOCancelCmdId = aCmd.iControlContext->iControl->CancelCommand(iMediaIOCmdId););
1479 if (err != OsclErrNone)
1480 {
1481 aCmd.iEventCode = PVCommsIONodeErr_MediaIOCancelCommand;
1482 iMediaIOCancelPending = false;
1483 return PVMFFailure;
1484 }
1485 LOGINFOHI((0, "PVCommsIONode:SendMIORequest: Cancel Command Issued to MIO component, waiting on response..."));
1486 return PVMFPending;//wait on request to cancel.
1487 }
1488
1489 ////////////////////////////////////////////////////////////////////////////
MioConfigured(int32 aPortTag)1490 void PVCommsIONode::MioConfigured(int32 aPortTag)
1491 //called by the port when the MIO was just configured.
1492 //only called for ports that need to wait on config before starting
1493 //the MIO.
1494 //RH Note: probably not need for Comms right now, and the port
1495 //does not call this method.
1496 {
1497 OSCL_UNUSED_ARG(aPortTag);
1498
1499 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1500 (0, "PVCommsIONode::MioConfigured() called"));
1501 if (iInterfaceState == EPVMFNodeStarted)
1502 {
1503 PVCommsIONodeCmd cmd;
1504 // cmd.iControlContext = ContextFromTag(aPortTag);
1505 cmd.PVCommsIONodeCmdBase::Construct(0, PVMF_COMMSIONODE_STARTMIO, NULL);
1506 QueueCommandL(cmd);
1507 }
1508 }
1509
1510 ////////////////////////////////////////////////////////////////////////////
1511 // Event reporting routines.
1512 ////////////////////////////////////////////////////////////////////////////
SetState(TPVMFNodeInterfaceState s)1513 void PVCommsIONode::SetState(TPVMFNodeInterfaceState s)
1514 {
1515 LOGINFO((0, "PVCommsIONode:SetState %d", s));
1516 PVMFNodeInterface::SetState(s);
1517 }
1518
1519 ////////////////////////////////////////////////////////////////////////////
ReportErrorEvent(PVMFEventType aEventType,OsclAny * aEventData,PVMFStatus aEventCode)1520 void PVCommsIONode::ReportErrorEvent(PVMFEventType aEventType, OsclAny* aEventData, PVMFStatus aEventCode)
1521 {
1522 LOGERROR((0, "PVCommsIONode:NodeErrorEvent Type %d EVData %d EVCode %d"
1523 , aEventType, aEventData, aEventCode));
1524
1525 //create the extension message if any.
1526 if (aEventCode != PVCommsIONodeErr_First)
1527 {
1528 PVMFBasicErrorInfoMessage* eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, iEventUuid, NULL));
1529 PVMFAsyncEvent asyncevent(PVMFErrorEvent, aEventType, NULL, OSCL_STATIC_CAST(PVInterface*, eventmsg), aEventData, NULL, 0);
1530 PVMFNodeInterface::ReportErrorEvent(asyncevent);
1531 eventmsg->removeRef();
1532 }
1533 else
1534 PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
1535 }
1536
1537 ////////////////////////////////////////////////////////////////////////////
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData,PVMFStatus aEventCode)1538 void PVCommsIONode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData, PVMFStatus aEventCode)
1539 {
1540 LOGINFO((0, "PVCommsIONode:NodeInfoEvent Type %d EVData %d EVCode %d"
1541 , aEventType, aEventData, aEventCode));
1542
1543 //create the extension message if any.
1544 if (aEventCode != PVCommsIONodeErr_First)
1545 {
1546 PVMFBasicErrorInfoMessage* eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, iEventUuid, NULL));
1547 PVMFAsyncEvent asyncevent(PVMFErrorEvent, aEventType, NULL, OSCL_STATIC_CAST(PVInterface*, eventmsg), aEventData, NULL, 0);
1548 PVMFNodeInterface::ReportInfoEvent(asyncevent);
1549 eventmsg->removeRef();
1550 }
1551 else
1552 PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
1553 }
1554
1555 ////////////////////////////////////////////////////////////////////////////
PortQueuesEmpty()1556 bool PVCommsIONode::PortQueuesEmpty()
1557 {
1558 uint32 i;
1559 for (i = 0; i < iPortVector.size(); i++)
1560 {
1561 if (iPortVector[i]->IncomingMsgQueueSize() > 0
1562 || iPortVector[i]->OutgoingMsgQueueSize() > 0)
1563 {
1564 return false;
1565 }
1566 }
1567 return true;
1568 }
1569
1570 ////////////////////////////////////////////////////////////////////////////
Assert(bool condition)1571 void PVCommsIONode::Assert(bool condition)
1572 {
1573 if (!condition)
1574 {
1575 LOGERROR((0, "PVCommsIONode::Assert Failed!"));
1576 OSCL_ASSERT(0);
1577 }
1578 }
1579
ContextSetFromTag(int32 aTag)1580 MIOControlContextSet PVCommsIONode::ContextSetFromTag(int32 aTag)
1581 {
1582 MIOControlContextSet contextSet;
1583
1584 switch (aTag)
1585 {
1586 case PVMF_COMMSIO_NODE_OUTPUT_PORT_TAG:
1587 if (iMediaInputContext.isValid())
1588 contextSet.iMediaInputElement = &iMediaInputContext;
1589 break;
1590 case PVMF_COMMSIO_NODE_INPUT_PORT_TAG:
1591 if (iMediaOutputContext.isValid())
1592 contextSet.iMediaOutputElement = &iMediaOutputContext;
1593 break;
1594 case PVMF_COMMSIO_NODE_IO_PORT_TAG:
1595 if (iMediaOutputContext.isValid() && iMediaInputContext.isValid())
1596 {
1597 contextSet.iMediaInputElement = &iMediaInputContext;
1598 contextSet.iMediaOutputElement = &iMediaOutputContext;
1599 }
1600 break;
1601 default:
1602 break;
1603 }
1604 return contextSet;
1605 }
1606 /*
1607 PvmiCapabilityAndConfig *PVCommsIONode::GetConfig(int32 aPortTag)
1608 {
1609 MIOControlContextElement *context = ContextSetFromTag(aPortTag);
1610 if (context)
1611 return context->iMediaIOConfig;
1612 return NULL;
1613 }
1614 */
CreateMediaTransfer(int32 aPortTag,PvmiMediaTransfer * & aInputTransfer,PvmiMediaTransfer * & aOutputTransfer)1615 bool PVCommsIONode::CreateMediaTransfer(int32 aPortTag, PvmiMediaTransfer *&aInputTransfer, PvmiMediaTransfer *&aOutputTransfer)
1616 {
1617 MIOControlContextSet set = ContextSetFromTag(aPortTag);
1618
1619 if (set.isEmpty())
1620 return false;
1621
1622 if (set.iMediaInputElement)
1623 {
1624 aInputTransfer = set.iMediaInputElement->iControl->createMediaTransfer(set.iMediaInputElement->iMediaSession);
1625 if (!aInputTransfer)
1626 return false;
1627 }
1628 if (set.iMediaOutputElement)
1629 {
1630 aOutputTransfer = set.iMediaOutputElement->iControl->createMediaTransfer(set.iMediaOutputElement->iMediaSession);
1631 if (!aOutputTransfer)
1632 return false;
1633 }
1634
1635 return true;
1636 }
1637
DeleteMediaTransfer(int32 aPortTag,PvmiMediaTransfer * aInputTransfer,PvmiMediaTransfer * aOutputTransfer)1638 void PVCommsIONode::DeleteMediaTransfer(int32 aPortTag, PvmiMediaTransfer *aInputTransfer, PvmiMediaTransfer *aOutputTransfer)
1639 {
1640 MIOControlContextSet set = ContextSetFromTag(aPortTag);
1641
1642 if (set.isEmpty())
1643 return;
1644
1645 if (set.iMediaInputElement && aInputTransfer)
1646 {
1647 set.iMediaInputElement->iControl->deleteMediaTransfer(set.iMediaInputElement->iMediaSession, aInputTransfer);
1648 }
1649 else if (set.iMediaOutputElement && aOutputTransfer)
1650 {
1651 set.iMediaOutputElement->iControl->deleteMediaTransfer(set.iMediaOutputElement->iMediaSession, aOutputTransfer);
1652 }
1653 }
1654
GetNextContextInSequence(PVCommsIONodeCmd & aCmd)1655 bool PVCommsIONode::GetNextContextInSequence(PVCommsIONodeCmd &aCmd)
1656 {
1657 // We need to determine which IO controls to start
1658 // the init with
1659 if (aCmd.iControlContext == NULL)
1660 {
1661 if (iMediaInputContext.isValid())
1662 aCmd.iControlContext = &iMediaInputContext;
1663 else if (iMediaOutputContext.isValid())
1664 aCmd.iControlContext = &iMediaOutputContext;
1665 else
1666 return false;
1667 }
1668 else if ((aCmd.iControlContext == &iMediaInputContext) &&
1669 iMediaOutputContext.isValid() &&
1670 (iMediaOutputContext.iControl != iMediaInputContext.iControl))
1671 {
1672 aCmd.iControlContext = &iMediaOutputContext;
1673 }
1674 else
1675 return false;
1676
1677 return true;
1678 }
1679
ReRunCommandForNextMIO(PVCommsIONodeCmd & aCmd)1680 bool PVCommsIONode::ReRunCommandForNextMIO(PVCommsIONodeCmd &aCmd)
1681 {
1682 // This method should only be called from the
1683 // RequestCompleted method, and allows us to re-use
1684 // command objects to asynchronously initialize more than
1685 // one MIO component under the context of a single node
1686 // command id.
1687
1688 // The force parameter will force the command to be re run for
1689 // an output context even if its MIO component is a reference to
1690 // the input context component. This is useful for the query interface
1691 // portion of initialization.
1692
1693 PVCommsIONodeCmd newCmd = aCmd;
1694
1695 if (GetNextContextInSequence(newCmd))
1696 {
1697 iCurrentCommand.Erase(&aCmd);
1698 // Don't use AddL because that overwrites the iId
1699 // which must remain the same.
1700 iInputCommands.StoreL(newCmd);
1701 RunIfNotReady();
1702 iMediaIORequest = ENone;
1703 return true;
1704 }
1705 return false;
1706 }
1707
MIOSupportsPortTag(int32 aTag,MIOControlContextSet & aSet)1708 bool PVCommsIONode::MIOSupportsPortTag(int32 aTag, MIOControlContextSet &aSet)
1709 {
1710 PvmiKvp* kvp ;
1711 int numParams ;
1712
1713 // Get input formats capability from media IO
1714 kvp = NULL;
1715 numParams = 0;
1716
1717 if (aTag & PVMF_COMMSIO_NODE_OUTPUT_PORT_TAG)
1718 {
1719 if (!aSet.iMediaInputElement->hasConfig() ||
1720 aSet.iMediaInputElement->iMediaIOConfig->getParametersSync(NULL,
1721 OSCL_CONST_CAST(char*, OUTPUT_FORMATS_CAP_QUERY),
1722 kvp, numParams, NULL) != PVMFSuccess)
1723 return false;
1724 aSet.iMediaInputElement->iMediaIOConfig->releaseParameters(0, kvp, numParams);
1725 if (numParams == 0)
1726 return false;
1727 }
1728 if (aTag & PVMF_COMMSIO_NODE_INPUT_PORT_TAG)
1729 {
1730 if (!aSet.iMediaOutputElement->hasConfig() ||
1731 aSet.iMediaOutputElement->iMediaIOConfig->getParametersSync(NULL,
1732 OSCL_CONST_CAST(char*, INPUT_FORMATS_CAP_QUERY),
1733 kvp, numParams, NULL) != PVMFSuccess)
1734 return false;
1735 aSet.iMediaOutputElement->iMediaIOConfig->releaseParameters(0, kvp, numParams);
1736 if (numParams == 0)
1737 return false;
1738 }
1739
1740 return true;
1741 }
1742
1743 // Check some stuff to determine if we can hand out
1744 // a port of this type...
1745
ValidatePortTagRequest(int32 aTag)1746 bool PVCommsIONode::ValidatePortTagRequest(int32 aTag)
1747 {
1748 uint32 curPorts = iPortVector.size();
1749
1750 switch (aTag)
1751 {
1752 case PVMF_COMMSIO_NODE_IO_PORT_TAG:
1753 if (curPorts > 0)
1754 return false; // can have only one I/O port
1755 break;
1756
1757 case PVMF_COMMSIO_NODE_OUTPUT_PORT_TAG:
1758 if (curPorts > 1 ||
1759 (curPorts == 1 && iPortVector[0]->GetPortTag() != PVMF_COMMSIO_NODE_INPUT_PORT_TAG))
1760 return false;
1761 break;
1762 case PVMF_COMMSIO_NODE_INPUT_PORT_TAG:
1763 if (curPorts > 1 ||
1764 (curPorts == 1 && iPortVector[0]->GetPortTag() != PVMF_COMMSIO_NODE_OUTPUT_PORT_TAG))
1765 return false;
1766 break;
1767 default:
1768 return false;
1769 }
1770
1771 MIOControlContextSet set = ContextSetFromTag(aTag);
1772
1773 if (set.isEmpty() || !MIOSupportsPortTag(aTag, set))
1774 return false;
1775
1776 return true;
1777 }
1778