• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /**
19  * @file 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