Home | History | Annotate | Download | only in src
      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 #include "pvmf_wavffparser_node.h"
     19 #include "pvmf_wavffparser_defs.h"
     20 #include "wav_parsernode_tunables.h"
     21 #include "pvmf_wavffparser_port.h"
     22 #include "pvwavfileparser.h"
     23 #include "media_clock_converter.h"
     24 #include "pv_gau.h"
     25 #include "pvlogger.h"
     26 #include "oscl_error_codes.h"
     27 #include "pvmf_fileformat_events.h"
     28 #include "pvmf_basic_errorinfomessage.h"
     29 #include "pvmf_media_cmd.h"
     30 #include "pvmf_media_msg_format_ids.h"
     31 #include "pv_mime_string_utils.h"
     32 #include "oscl_stdstring.h"
     33 #include "oscl_snprintf.h"
     34 #include "pvmi_kvp_util.h"
     35 
     36 
     37 static const char PVWAVMETADATA_ALL_METADATA_KEY[] = "all";
     38 
     39 #define PVMF_WAV_NUM_METADATA_VALUES 7
     40 // Constant character strings for metadata keys
     41 static const char PVWAVMETADATA_DURATION_KEY[] = "duration";
     42 static const char PVWAVMETADATA_NUMTRACKS_KEY[] = "num-tracks";
     43 static const char PVWAVMETADATA_TRACKINFO_BITRATE_KEY[] = "track-info/bit-rate";
     44 static const char PVWAVMETADATA_TRACKINFO_SAMPLERATE_KEY[] = "track-info/sample-rate";
     45 static const char PVWAVMETADATA_TRACKINFO_AUDIO_CHANNELS_KEY[] = "track-info/audio/channels";
     46 static const char PVWAVMETADATA_TRACKINFO_AUDIO_FORMAT_KEY[] = "track-info/audio/format";
     47 static const char PVWAVMETADATA_TRACKINFO_AUDIO_BITSPERSAMPLE_KEY[] = "track-info/audio/bits-per-sample";
     48 static const char PVWAVMETADATA_SEMICOLON[] = ";";
     49 static const char PVWAVMETADATA_TIMESCALE1000[] = "timescale=1000";
     50 static const char PVWAVMETADATA_INDEX0[] = "index=0";
     51 
     52 
     53 PVMFWAVFFParserNode::PVMFWAVFFParserNode(int32 aPriority) :
     54         OsclTimerObject(aPriority, "PVMFWAVFFParserNode"),
     55         iStreamID(0),
     56         iOutPort(NULL),
     57         iLogger(NULL),
     58         iCmdRespPort(NULL),
     59         iWAVParser(NULL),
     60         iExtensionRefCount(0)
     61 {
     62     int32 err;
     63     OSCL_TRY(err,
     64 
     65              //Create the input command queue.  Use a reserve to avoid lots of dynamic memory allocation.
     66              iInputCommands.Construct(PVMF_WAVFFPARSER_NODE_COMMAND_ID_START, PVMF_WAVFFPARSER_NODE_COMMAND_VECTOR_RESERVE);
     67 
     68              //Create the "current command" queue.  It will only contain one
     69              //command at a time, so use a reserve of 1.
     70              iCurrentCommand.Construct(0, 1);
     71 
     72              //Set the node capability data.
     73              //This node can support an unlimited number of ports.
     74              iCapability.iCanSupportMultipleInputPorts = false;
     75              iCapability.iCanSupportMultipleOutputPorts = false;
     76              iCapability.iHasMaxNumberOfPorts = true;
     77              iCapability.iMaxNumberOfPorts = 2;//no maximum
     78              iCapability.iInputFormatCapability.push_back(PVMF_MIME_WAVFF);
     79              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_PCM8);
     80              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_PCM16);
     81             );
     82 
     83     if (err != OsclErrNone)
     84     {
     85         //if a leave happened, cleanup and re-throw the error
     86         iInputCommands.clear();
     87         iCurrentCommand.clear();
     88         iCapability.iInputFormatCapability.clear();
     89         iCapability.iOutputFormatCapability.clear();
     90         OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
     91         OSCL_CLEANUP_BASE_CLASS(OsclTimerObject);
     92         OSCL_LEAVE(err);
     93     }
     94 
     95     Construct();
     96 }
     97 
     98 PVMFWAVFFParserNode::~PVMFWAVFFParserNode()
     99 {
    100     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::~PVMFWAVFFParserNode() called"));
    101     //Cleanup commands
    102     //The command queues are self-deleting, but we want to
    103     //notify the observer of unprocessed commands.
    104 
    105     while (!iCurrentCommand.empty())
    106     {
    107         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
    108     }
    109 
    110     while (!iInputCommands.empty())
    111     {
    112         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
    113     }
    114 
    115     //cleanup port activity events
    116     iPortActivityQueue.clear();
    117 
    118     Cancel();
    119 
    120     //Cleanup allocated ports
    121     ReleaseAllPorts();
    122     CleanupFileSource();
    123     iFileServer.Close();
    124 }
    125 
    126 
    127 /**
    128  //Do thread-specific node creation and go to "Idle" state.
    129  */
    130 PVMFStatus PVMFWAVFFParserNode::ThreadLogon()
    131 {
    132 
    133     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:ThreadLogon"));
    134     switch (iInterfaceState)
    135     {
    136         case EPVMFNodeCreated:
    137             if (!IsAdded())
    138                 AddToScheduler();
    139 
    140             iLogger = PVLogger::GetLoggerObject("PVMFWAVFFParserNode");
    141             SetState(EPVMFNodeIdle);
    142             return PVMFSuccess;
    143 
    144         default:
    145             return PVMFErrInvalidState;
    146     }
    147 }
    148 
    149 
    150 /**
    151  //Do thread-specific node cleanup and go to "Created" state.
    152  */
    153 PVMFStatus PVMFWAVFFParserNode::ThreadLogoff()
    154 {
    155     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:ThreadLogoff"));
    156 
    157     switch (iInterfaceState)
    158     {
    159         case EPVMFNodeIdle:
    160             if (IsAdded())
    161                 RemoveFromScheduler();
    162 
    163             iLogger = NULL;
    164             SetState(EPVMFNodeCreated);
    165             return PVMFSuccess;
    166 
    167         default:
    168             return PVMFErrInvalidState;
    169     }
    170 }
    171 
    172 
    173 PVMFStatus PVMFWAVFFParserNode::GetCapability(PVMFNodeCapability& aNodeCapability)
    174 {
    175     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::GetCapability() called"));
    176 
    177     // TODO: Return the appropriate format capability
    178     aNodeCapability = iCapability;
    179     return PVMFSuccess;
    180 }
    181 
    182 
    183 PVMFPortIter* PVMFWAVFFParserNode::GetPorts(const PVMFPortFilter* aFilter)
    184 {
    185     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::GetPorts() called"));
    186 
    187     OSCL_UNUSED_ARG(aFilter);
    188     // TODO: Return the currently available ports
    189     return NULL;
    190 }
    191 
    192 /**
    193  //Queue an asynchronous node command
    194  */
    195 PVMFCommandId PVMFWAVFFParserNode::QueryUUID(PVMFSessionId s, const PvmfMimeString& aMimeType,
    196         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    197         bool aExactUuidsOnly, const OsclAny* aContext)
    198 {
    199     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:QueryUUID"));
    200     PVMFWAVFFNodeCommand cmd;
    201     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
    202     return QueueCommandL(cmd);
    203 }
    204 
    205 /**
    206  //Queue an asynchronous node command
    207  */
    208 PVMFCommandId PVMFWAVFFParserNode::QueryInterface(PVMFSessionId s, const PVUuid& aUuid,
    209         PVInterface*& aInterfacePtr,
    210         const OsclAny* aContext)
    211 {
    212     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:QueryInterface"));
    213     PVMFWAVFFNodeCommand cmd;
    214     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
    215     return QueueCommandL(cmd);
    216 }
    217 
    218 /**
    219  //Queue an asynchronous node command
    220  */
    221 PVMFCommandId PVMFWAVFFParserNode::RequestPort(PVMFSessionId s, int32 aPortTag, const PvmfMimeString* aPortConfig, const OsclAny* aContext)
    222 {
    223     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:RequestPort"));
    224     PVMFWAVFFNodeCommand cmd;
    225     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
    226     return QueueCommandL(cmd);
    227 }
    228 
    229 
    230 /**
    231  //Queue an asynchronous node command
    232  */
    233 PVMFCommandId PVMFWAVFFParserNode::ReleasePort(PVMFSessionId s, PVMFPortInterface& aPort, const OsclAny* aContext)
    234 {
    235     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:ReleasePort"));
    236     PVMFWAVFFNodeCommand cmd;
    237     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
    238     return QueueCommandL(cmd);
    239 }
    240 
    241 /**
    242  //Queue an asynchronous node command
    243  */
    244 PVMFCommandId PVMFWAVFFParserNode::Init(PVMFSessionId s, const OsclAny* aContext)
    245 {
    246     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:Init"));
    247     PVMFWAVFFNodeCommand cmd;
    248     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_INIT, aContext);
    249     return QueueCommandL(cmd);
    250 }
    251 
    252 /**
    253  //Queue an asynchronous node command
    254  */
    255 PVMFCommandId PVMFWAVFFParserNode::Prepare(PVMFSessionId s, const OsclAny* aContext)
    256 {
    257     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:Prepare"));
    258     PVMFWAVFFNodeCommand cmd;
    259     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PREPARE, aContext);
    260     return QueueCommandL(cmd);
    261 }
    262 
    263 /**
    264  //Queue an asynchronous node command
    265  */
    266 PVMFCommandId PVMFWAVFFParserNode::Start(PVMFSessionId s, const OsclAny* aContext)
    267 {
    268     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:Start"));
    269     PVMFWAVFFNodeCommand cmd;
    270     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_START, aContext);
    271     return QueueCommandL(cmd);
    272 }
    273 
    274 /**
    275  //Queue an asynchronous node command
    276  */
    277 PVMFCommandId PVMFWAVFFParserNode::Stop(PVMFSessionId s, const OsclAny* aContext)
    278 {
    279     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:Stop"));
    280     PVMFWAVFFNodeCommand cmd;
    281     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_STOP, aContext);
    282     return QueueCommandL(cmd);
    283 }
    284 
    285 /**
    286  //Queue an asynchronous node command
    287  */
    288 PVMFCommandId PVMFWAVFFParserNode::Pause(PVMFSessionId s, const OsclAny* aContext)
    289 {
    290     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:Pause"));
    291     PVMFWAVFFNodeCommand cmd;
    292     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_PAUSE, aContext);
    293     return QueueCommandL(cmd);
    294 }
    295 
    296 /**
    297  //Queue an asynchronous node command
    298  */
    299 PVMFCommandId PVMFWAVFFParserNode::Flush(PVMFSessionId s, const OsclAny* aContext)
    300 {
    301     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:Flush"));
    302     PVMFWAVFFNodeCommand cmd;
    303     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_FLUSH, aContext);
    304     return QueueCommandL(cmd);
    305 }
    306 
    307 /**
    308  //Queue an asynchronous node command
    309  */
    310 PVMFCommandId PVMFWAVFFParserNode::Reset(PVMFSessionId s, const OsclAny* aContext)
    311 {
    312     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:Reset"));
    313     PVMFWAVFFNodeCommand cmd;
    314     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_RESET, aContext);
    315     return QueueCommandL(cmd);
    316 }
    317 
    318 /**
    319  //Queue an asynchronous node command
    320  */
    321 PVMFCommandId PVMFWAVFFParserNode::CancelAllCommands(PVMFSessionId s, const OsclAny* aContext)
    322 {
    323     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:CancelAllCommands"));
    324     PVMFWAVFFNodeCommand cmd;
    325     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
    326     return QueueCommandL(cmd);
    327 }
    328 
    329 /**
    330  //Queue an asynchronous node command
    331  */
    332 PVMFCommandId PVMFWAVFFParserNode::CancelCommand(PVMFSessionId s, PVMFCommandId aCmdId, const OsclAny* aContext)
    333 {
    334     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:CancelCommand"));
    335     PVMFWAVFFNodeCommand cmd;
    336     cmd.PVMFWAVFFNodeCommandBase::Construct(s, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
    337     return QueueCommandL(cmd);
    338 }
    339 
    340 
    341 
    342 /////////////////////
    343 // Private Section //
    344 /////////////////////
    345 void PVMFWAVFFParserNode::Construct()
    346 {
    347     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Construct()"));
    348 
    349     iFileServer.Connect();
    350 
    351     iAvailableMetadataKeys.reserve(PVMF_WAV_NUM_METADATA_VALUES);
    352     iAvailableMetadataKeys.clear();
    353 }
    354 
    355 
    356 void PVMFWAVFFParserNode::Run()
    357 {
    358     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Run() In"));
    359 
    360     //Process commands.
    361     if (!iInputCommands.empty())
    362     {
    363         if (ProcessCommand(iInputCommands.front()))
    364         {
    365             //note: need to check the state before re-scheduling
    366             //since the node could have been reset in the ProcessCommand call.
    367             if (iInterfaceState != EPVMFNodeCreated)
    368                 RunIfNotReady();
    369 
    370             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Run() Out 1"));
    371 
    372             return;
    373         }
    374     }
    375 
    376     // Process port activity
    377     if (!iPortActivityQueue.empty() &&
    378             (iInterfaceState == EPVMFNodeStarted || FlushPending()))
    379     {
    380         // If the port activity cannot be processed because a port is
    381         // busy, discard the activity and continue to process the next
    382         // activity in queue until getting to one that can be processed.
    383         while (!iPortActivityQueue.empty())
    384         {
    385             if (ProcessPortActivity())
    386                 break; //processed a port
    387         }
    388 
    389         //Re-schedule
    390         RunIfNotReady();
    391 
    392         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Run() Out 2"));
    393         return;
    394     }
    395 
    396     // Create new data and send to the output queue
    397     if (iInterfaceState == EPVMFNodeStarted && !FlushPending())
    398     {
    399         if (HandleTrackState()) // Handle track state returns true if there is more data to be sent.
    400         {
    401             // Run again if there is more data to send out
    402             RunIfNotReady();
    403             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Run() Out 33"));
    404         }
    405 
    406         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Run() Out 3"));
    407 
    408         return; // !FlushPending() = true ==> no flush
    409     }
    410 
    411     //this AO needs to monitor for node flush completion.
    412     if (FlushPending() &&
    413             iPortActivityQueue.empty())
    414     {
    415         if (iOutPort->OutgoingMsgQueueSize() > 0)
    416         {
    417             //need to wait on completion...
    418             RunIfNotReady();
    419 
    420             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Run() Out 4"));
    421 
    422             return;
    423         }
    424 
    425         //Flush is complete.  Go to prepared state.
    426         SetState(EPVMFNodePrepared);
    427         //resume port input so the ports can be re-started.
    428         iOutPort->ResumeInput();
    429         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess);
    430         RunIfNotReady();
    431     }
    432 
    433     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::Run() Out 5"));
    434 }
    435 
    436 /////////////////////////////////////////////////////
    437 // Port Processing routines
    438 /////////////////////////////////////////////////////
    439 bool PVMFWAVFFParserNode::ProcessPortActivity()
    440 {
    441     //called by the AO to process a port activity message
    442     //Pop the queue...
    443     PVMFPortActivity activity(iPortActivityQueue.front());
    444     iPortActivityQueue.erase(&iPortActivityQueue.front());
    445 
    446     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    447                     (0, "0x%x PVMFWAVFFParserNode::ProcessPortActivity: port=0x%x, type=%d",
    448                      this, activity.iPort, activity.iType));
    449 
    450     int32 err = OsclErrNone;
    451     PVMFStatus status = PVMFSuccess;
    452     switch (activity.iType)
    453     {
    454         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
    455         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
    456             status = ProcessOutgoingMsg(activity.iPort);
    457             //Re-queue the port activity event as long as there's
    458             //more data to process and it isn't in a Busy state.
    459             if (status != PVMFErrBusy
    460                     && activity.iPort->OutgoingMsgQueueSize() > 0)
    461             {
    462                 err = PushBackPortActivity(activity);
    463             }
    464             break;
    465 
    466         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
    467             err = PVMFFailure;
    468             break;
    469 
    470         default:
    471             break;
    472     }
    473 
    474     //report a failure in queueing new activity...
    475     if (err != OsclErrNone)
    476     {
    477         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    478                         (0, "0x%x PVMFWAVFFParserNode::ProcessPortActivity: Error - queue port activity failed. port=0x%x, type=%d",
    479                          this, activity.iPort, activity.iType));
    480         ReportErrorEvent(PVMFErrPortProcessing);
    481     }
    482 
    483 
    484     //Report any unexpected failure in port processing...
    485     //(the InvalidState error happens when port input is suspended,
    486     //so don't report it.)
    487     if (status != PVMFErrBusy && status != PVMFSuccess && status != PVMFErrInvalidState)
    488     {
    489         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    490                         (0, "0x%x PVMFWAVFFParserNode::ProcessPortActivity: Error - ProcessPortActivity failed. port=0x%x, type=%d",
    491                          this, activity.iPort, activity.iType));
    492         ReportErrorEvent(PVMFErrPortProcessing);
    493     }
    494 
    495     //return true if we processed an activity...
    496     return (status != PVMFErrBusy);
    497 }
    498 
    499 
    500 /////////////////////////////////////////////////////
    501 PVMFStatus PVMFWAVFFParserNode::ProcessOutgoingMsg(PVMFPortInterface* aPort)
    502 {
    503     //Called by the AO to process one message off the outgoing
    504     //message queue for the given port.  This routine will
    505     //try to send the data to the connected port.
    506 
    507     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    508                     (0, "0x%x PVMFWAVFFParserNode::ProcessOutgoingMsg: aPort=0x%x", this, aPort));
    509 
    510     PVMFStatus status = aPort->Send();
    511     if (status == PVMFErrBusy)
    512     {
    513         //If Send() fails, the destination port will send the notification
    514         //PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY later, when it is ready,
    515         // in the HandlePortActivity(). Schedule AO then.
    516         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
    517                         (0, "0x%x PVMFWAVFFParserNode::ProcessOutgoingMsg: Connected port goes into busy state", this));
    518     }
    519 
    520     return status;
    521 }
    522 
    523 
    524 bool PVMFWAVFFParserNode::HandleTrackState()
    525 {
    526     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::HandleTrackState() In"));
    527 
    528     // Flag to be active again or not
    529     bool ret_status = false;
    530 
    531     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::HandleTrackState track list size = %d", iSelectedTrackList.size()));
    532     for (uint32 i = 0; i < iSelectedTrackList.size(); ++i)
    533     {
    534         switch (iSelectedTrackList[i].iState)
    535         {
    536             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED:
    537                 iSelectedTrackList[i].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
    538                 // Continue on to retrieve the first frame
    539 
    540             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA:
    541                 // First do check for the availability of getting new data
    542                 if (!CheckAvailabilityForSendingNewTrackData(iSelectedTrackList[i]))
    543                 {
    544                     return false; // Not available to get data and send data
    545                 }
    546 
    547                 if (!RetrieveTrackData(iSelectedTrackList[i]))
    548                 {
    549                     if (iSelectedTrackList[i].iState == PVWAVFFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK)
    550                     {
    551                         ReportInfoEvent(PVMFInfoEndOfData);
    552                     }
    553                     break;
    554                 }
    555 
    556                 iSelectedTrackList[i].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA;
    557                 // Continue on to send the frame
    558 
    559             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA:
    560                 if (iSelectedTrackList[i].iSendBOS)
    561                 {
    562                     if (!SendBeginOfMediaStreamCommand(iSelectedTrackList[i]))
    563                         return true;
    564 
    565                     if (!iSelectedTrackList[i].iMediaData)
    566                     {
    567                         iSelectedTrackList[i].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
    568                         break;
    569                     }
    570                 }
    571 
    572                 if (SendTrackData(iSelectedTrackList[i]))
    573                 {
    574                     iSelectedTrackList[i].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
    575                     ret_status = true;
    576                 }
    577                 break;
    578 
    579             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK:
    580                 if (iSelectedTrackList[i].iSendBOS)
    581                 {
    582                     if (!SendBeginOfMediaStreamCommand(iSelectedTrackList[i]))
    583                         return true;
    584                 }
    585 
    586                 if (SendEndOfTrackCommand(iSelectedTrackList[i]))
    587                 {
    588                     // EOS sent successfully.
    589                     iSelectedTrackList[i].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK;
    590                     ReportInfoEvent(PVMFInfoEndOfData);
    591                 }
    592                 else
    593                 {
    594                     // EOS command sending failed -- wait on outgoing queue ready notice
    595                     // before trying again.
    596                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFWAVFFParserNode::HandleTrackState EOS media command sending failed"));
    597                     ret_status = true;
    598                 }
    599 
    600             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_MEDIADATAPOOLEMPTY:
    601             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_INITIALIZED:
    602             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK:
    603             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_DESTFULL:
    604             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_SOURCEEMPTY:
    605             case PVWAVFFNodeTrackPortInfo::TRACKSTATE_ERROR:
    606 
    607             default:
    608                 // Do nothing for these states for now
    609                 break;
    610         }
    611     }
    612 
    613     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::HandleTrackState() Out"));
    614     return ret_status;
    615 }
    616 
    617 
    618 bool PVMFWAVFFParserNode::RetrieveTrackData(PVWAVFFNodeTrackPortInfo& aTrackPortInfo)
    619 {
    620     // Create a data buffer from pool
    621     int32 errcode = OsclErrNone;
    622     OsclSharedPtr<PVMFMediaDataImpl> mediaDataImplOut;
    623     OSCL_TRY(errcode, mediaDataImplOut = aTrackPortInfo.iMediaDataImplAlloc->allocate(trackdata_bufsize));
    624 
    625     if (errcode != OsclErrNone)
    626     {
    627         if (errcode == OsclErrNoResources)
    628         {
    629             aTrackPortInfo.iTrackDataMemoryPool->notifyfreechunkavailable(aTrackPortInfo);  // Enable flag to receive event when next deallocate() is called on pool
    630             return false;
    631         }
    632         else if (errcode == OsclErrNoMemory)
    633         {
    634             // Memory allocation for the pool failed
    635             aTrackPortInfo.iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_ERROR;
    636             ReportErrorEvent(PVMFErrNoMemory, NULL);
    637             return false;
    638         }
    639         else if (errcode == OsclErrArgument)
    640         {
    641             // Invalid parameters passed to mempool
    642             aTrackPortInfo.iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_ERROR;
    643             ReportErrorEvent(PVMFErrArgument, NULL);
    644             return false;
    645         }
    646         else
    647         {
    648             // General error
    649             aTrackPortInfo.iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_ERROR;
    650             ReportErrorEvent(PVMFFailure, NULL);
    651             return false;
    652         }
    653     }
    654 
    655 
    656     // Now create a PVMF media data from pool
    657     errcode = OsclErrNoResources;
    658     PVMFSharedMediaDataPtr mediadataout;
    659     mediadataout = PVMFMediaData::createMediaData(mediaDataImplOut, aTrackPortInfo.iMediaDataMemPool);
    660 
    661     if (mediadataout.GetRep() != NULL)
    662     {
    663         errcode = OsclErrNone;
    664     }
    665 
    666     else
    667     {
    668         aTrackPortInfo.iMediaDataMemPool->notifyfreechunkavailable(aTrackPortInfo);     // Enable flag to receive event when next deallocate() is called on pool
    669         return false;
    670     }
    671 
    672     // Retrieve memory fragment to write to
    673     OsclRefCounterMemFrag refCtrMemFragOut;
    674     OsclMemoryFragment memFragOut;
    675     mediadataout->getMediaFragment(0, refCtrMemFragOut);
    676     memFragOut.ptr = refCtrMemFragOut.getMemFrag().ptr;
    677 
    678     uint32 samplesread = 0;
    679     PVWavParserReturnCode retcode = iWAVParser->GetPCMData((uint8*)memFragOut.ptr, refCtrMemFragOut.getCapacity(), trackdata_num_samples, samplesread);
    680 
    681     if ((retcode == PVWAVPARSER_OK) || (retcode == PVWAVPARSER_END_OF_FILE))
    682     {
    683         if (samplesread == 0)
    684         {
    685             // Only partial sample so return and set active to call HandleTrackState() again
    686             if (retcode != PVWAVPARSER_END_OF_FILE)
    687             {
    688                 RunIfNotReady();
    689                 return false;
    690             }
    691         }
    692         else
    693         {
    694             memFragOut.len = samplesread * wavinfo.BytesPerSample * wavinfo.NumChannels;
    695             mediadataout->setMediaFragFilledLen(0, memFragOut.len);
    696 
    697             // set the timestamp
    698             uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(COMMON_PLAYBACK_CLOCK_TIMESCALE);
    699 
    700             // set the timestamp
    701             mediadataout->setTimestamp(timestamp);
    702 
    703             // set the sequence number
    704             mediadataout->setSeqNum(aTrackPortInfo.iSeqNum++);
    705 
    706             // set the stream id
    707             mediadataout->setStreamID(iStreamID);
    708 
    709             aTrackPortInfo.iMediaData = mediadataout;
    710 
    711             // increment the clock based on this sample duration
    712             timestamp = aTrackPortInfo.iClockConverter->get_current_timestamp();
    713             timestamp += samplesread;
    714             aTrackPortInfo.iClockConverter->update_clock(timestamp);
    715         }
    716         if (retcode == PVWAVPARSER_END_OF_FILE)
    717         {
    718             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::RetrieveTrackData() WAV Parser END_OF_FILE"));
    719 
    720             if (SendEndOfTrackCommand(aTrackPortInfo))
    721             {
    722                 // EOS message sent so change state
    723                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFWAVFFParserNode::RetrieveTrackData() Sending EOS message succeeded"));
    724                 aTrackPortInfo.iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
    725                 return false;
    726             }
    727             else
    728             {
    729                 // EOS message could not be queued so keep in same state and try again later
    730                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFWAVFFParserNode::RetrieveTrackData() Sending EOS message failed"));
    731                 return true;
    732             }
    733         }
    734 
    735     }
    736     else
    737     {
    738         // Parser read error
    739         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFWAVFFParserNode::RetrieveTrackData() Read error returned by parser"));
    740         aTrackPortInfo.iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_ERROR;
    741 
    742         // Determine error code
    743         PVUuid eventuuid;
    744         int32 eventcode;
    745         if (!MapWAVErrorCodeToEventCode(retcode, eventuuid, eventcode))
    746         {
    747             eventuuid = PVMFFileFormatEventTypesUUID;
    748             eventcode = PVMFFFErrMisc;
    749         }
    750 
    751         // Report error event
    752         PVMFBasicErrorInfoMessage* eventmsg = NULL;
    753         errcode = 0;
    754         OSCL_TRY(errcode, eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (eventcode, eventuuid, NULL)));
    755         if (errcode == 0)
    756         {
    757             PVMFAsyncEvent asyncevent(PVMFErrorEvent, PVMFErrResource, NULL, OSCL_STATIC_CAST(PVInterface*, eventmsg), NULL, NULL, 0);
    758             PVMFNodeInterface::ReportErrorEvent(asyncevent);
    759             eventmsg->removeRef();
    760         }
    761     }
    762 
    763     return true;
    764 }
    765 
    766 bool PVMFWAVFFParserNode::SendTrackData(PVWAVFFNodeTrackPortInfo& aTrackPortInfo)
    767 {
    768     // Send frame to downstream node via port
    769     PVMFSharedMediaMsgPtr mediaMsgOut;
    770     convertToPVMFMediaMsg(mediaMsgOut, aTrackPortInfo.iMediaData);
    771     if (aTrackPortInfo.iPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
    772     {
    773         // output queue is busy, so wait for the output queue being ready
    774         return false;
    775     }
    776 
    777     // Don't need the ref to iMediaData so unbind it
    778     aTrackPortInfo.iMediaData.Unbind();
    779     return true;
    780 }
    781 
    782 bool PVMFWAVFFParserNode::CheckAvailabilityForSendingNewTrackData(PVWAVFFNodeTrackPortInfo& aTrackPortInfo)
    783 {
    784 
    785     // check if the output queue of output port is not full
    786     if (aTrackPortInfo.iPort && aTrackPortInfo.iPort->IsOutgoingQueueBusy())
    787     {
    788         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
    789                         (0, "0x%x PVMFMP3DecNode::CheckAvailabilityForSendingNewTrackData: output queue of the output port is busy", this));
    790         return false;
    791     }
    792 
    793     return true;
    794 }
    795 
    796 
    797 
    798 /////////////////////////////////////////////////////
    799 // Port Processing routines
    800 /////////////////////////////////////////////////////
    801 void PVMFWAVFFParserNode::HandlePortActivity(const PVMFPortActivity &aActivity)
    802 {
    803 
    804     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    805                     (0, "0x%x PVMFWAVFFParserNode::PortActivity: port=0x%x, type=%d",
    806                      this, aActivity.iPort, aActivity.iType));
    807 
    808     switch (aActivity.iType)
    809     {
    810         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
    811             //An outgoing message was queued on this port.
    812             //We only need to queue a port activity event on the
    813             //first message.  Additional events will be queued during
    814             //the port processing as needed.
    815             if (aActivity.iPort->OutgoingMsgQueueSize() == 1)
    816                 QueuePortActivity(aActivity);
    817 
    818             break;
    819 
    820         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
    821             if (aActivity.iPort->IncomingMsgQueueSize() == 1)
    822                 QueuePortActivity(aActivity);
    823             break;
    824 
    825         case PVMF_PORT_ACTIVITY_CONNECT:
    826             //nothing needed.
    827             //get the capability and config interface and set the parameter
    828             break;
    829 
    830         case PVMF_PORT_ACTIVITY_DISCONNECT:
    831             //nothing needed.
    832 
    833         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
    834             //This message is send by destination port to notify that the earlier Send
    835             //call that failed due to its busy status can be resumed now.
    836             if (aActivity.iPort->OutgoingMsgQueueSize() > 0)
    837                 QueuePortActivity(aActivity);
    838             break;
    839 
    840         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
    841             //this message is sent by the OutgoingQueue when it recovers from
    842             //the queue full status
    843             HandleOutgoingQueueReady(aActivity.iPort);
    844 
    845         default:
    846             break;
    847     }
    848 }
    849 
    850 void PVMFWAVFFParserNode::QueuePortActivity(const PVMFPortActivity &aActivity)
    851 {
    852     //queue a new port activity event
    853     int32 err = 0;
    854     OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
    855     if (err != OsclErrNone)
    856     {
    857         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
    858                         (0, "0x%x PVMFWAVFFParserNode::PortActivity: Error - iPortActivityQueue.push_back() failed", this));
    859         ReportErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
    860     }
    861     else
    862     {
    863         //wake up the AO to process the port activity event.
    864         RunIfNotReady();
    865     }
    866 }
    867 
    868 bool PVMFWAVFFParserNode::ProcessCommand(PVMFWAVFFNodeCommand& aCmd)
    869 {
    870     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    871                     (0, "0x%x PVMFWAVFFParserNode::ProcessCommand: cmd %d",
    872                      this, aCmd.iCmd));
    873 
    874     //normally this node will not start processing one command
    875     //until the prior one is finished.  However, a hi priority
    876     //command such as Cancel must be able to interrupt a command
    877     //in progress.
    878     if (!iCurrentCommand.empty() && !aCmd.hipri())
    879         return false;
    880 
    881     switch (aCmd.iCmd)
    882     {
    883         case PVMF_GENERIC_NODE_QUERYUUID:
    884             DoQueryUuid(aCmd);
    885             break;
    886 
    887         case PVMF_GENERIC_NODE_QUERYINTERFACE:
    888             DoQueryInterface(aCmd);
    889             break;
    890 
    891         case PVMF_GENERIC_NODE_REQUESTPORT:
    892             DoRequestPort(aCmd);
    893             break;
    894 
    895         case PVMF_GENERIC_NODE_RELEASEPORT:
    896             DoReleasePort(aCmd);
    897             break;
    898 
    899         case PVMF_GENERIC_NODE_INIT:
    900             DoInit(aCmd);
    901             break;
    902 
    903         case PVMF_GENERIC_NODE_PREPARE:
    904             DoPrepare(aCmd);
    905             break;
    906 
    907         case PVMF_GENERIC_NODE_START:
    908             DoStart(aCmd);
    909             break;
    910 
    911         case PVMF_GENERIC_NODE_STOP:
    912             DoStop(aCmd);
    913             break;
    914 
    915         case PVMF_GENERIC_NODE_FLUSH:
    916             DoFlush(aCmd);
    917             break;
    918 
    919         case PVMF_GENERIC_NODE_PAUSE:
    920             DoPause(aCmd);
    921             break;
    922 
    923         case PVMF_GENERIC_NODE_RESET:
    924             DoReset(aCmd);
    925             break;
    926 
    927         case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
    928             DoCancelAllCommands(aCmd);
    929             break;
    930 
    931         case PVMF_GENERIC_NODE_CANCELCOMMAND:
    932             DoCancelCommand(aCmd);
    933             break;
    934 
    935         case PVWAVFF_NODE_CMD_SETDATASOURCEPOSITION:
    936             DoSetDataSourcePosition(aCmd);
    937             break;
    938 
    939         case PVWAVFF_NODE_CMD_QUERYDATASOURCEPOSITION:
    940             DoQueryDataSourcePosition(aCmd);
    941             break;
    942 
    943         case PVWAVFF_NODE_CMD_SETDATASOURCERATE:
    944             DoSetDataSourceRate(aCmd);
    945             break;
    946 
    947         case PVWAVFF_NODE_CMD_GETNODEMETADATAKEY:
    948         {
    949             PVMFStatus retval = DoGetNodeMetadataKey(aCmd);
    950             CommandComplete(iInputCommands, aCmd, retval);
    951         }
    952         break;
    953 
    954         case PVWAVFF_NODE_CMD_GETNODEMETADATAVALUE:
    955         {
    956             PVMFStatus retval = DoGetNodeMetadataValue(aCmd);
    957             CommandComplete(iInputCommands, aCmd, retval);
    958         }
    959         break;
    960 
    961         default://unknown command type
    962             CommandComplete(iInputCommands, aCmd, PVMFFailure);
    963             break;
    964     }
    965 
    966     return true;
    967 }
    968 
    969 /////////////////////////////////////////////////////
    970 // Event reporting routines.
    971 /////////////////////////////////////////////////////
    972 void PVMFWAVFFParserNode::SetState(TPVMFNodeInterfaceState s)
    973 {
    974     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:SetState %d", s));
    975     PVMFNodeInterface::SetState(s);
    976 }
    977 
    978 
    979 void PVMFWAVFFParserNode::ReportErrorEvent(PVMFEventType aEventType, OsclAny* aEventData)
    980 {
    981     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:ReportErrorEvent Type %d Data %d"
    982                     , aEventType, aEventData));
    983 
    984     PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData);
    985 }
    986 
    987 void PVMFWAVFFParserNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData)
    988 {
    989     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:ReportInfoEvent Type %d Data %d"
    990                     , aEventType, aEventData));
    991 
    992     PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
    993 }
    994 
    995 void PVMFWAVFFParserNode::DoQueryUuid(PVMFWAVFFNodeCommand& aCmd)
    996 {
    997 
    998     //This node supports Query UUID from any state
    999     OSCL_String* mimetype;
   1000     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
   1001     bool exactmatch;
   1002     aCmd.PVMFWAVFFNodeCommandBase::Parse(mimetype, uuidvec, exactmatch);
   1003 
   1004     //right now, supported UUID is pushed directly. It needs to check for MIME type first
   1005     if (*mimetype == PVMF_DATA_SOURCE_INIT_INTERFACE_MIMETYPE)
   1006     {
   1007         PVUuid uuid(PVMF_DATA_SOURCE_INIT_INTERFACE_UUID);
   1008         uuidvec->push_back(uuid);
   1009     }
   1010     else if (*mimetype == PVMF_TRACK_SELECTION_INTERFACE_MIMETYPE)
   1011     {
   1012         PVUuid uuid(PVMF_TRACK_SELECTION_INTERFACE_UUID);
   1013         uuidvec->push_back(uuid);
   1014     }
   1015     else if (*mimetype == PVMF_DATA_SOURCE_PLAYBACK_CONTROL_INTERFACE_MIMETYPE)
   1016     {
   1017         PVUuid uuid(PvmfDataSourcePlaybackControlUuid);
   1018         uuidvec->push_back(uuid);
   1019     }
   1020     else if (*mimetype == PVMF_META_DATA_EXTENSION_INTERFACE_MIMETYPE)
   1021     {
   1022         PVUuid uuid(KPVMFMetadataExtensionUuid);
   1023         uuidvec->push_back(uuid);
   1024     }
   1025     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1026 }
   1027 
   1028 void PVMFWAVFFParserNode::DoQueryInterface(PVMFWAVFFNodeCommand&  aCmd)
   1029 {
   1030     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1031                     (0, "PVMFWAVFFParserNode::DoQueryInterface"));
   1032 
   1033     PVUuid* uuid;
   1034     PVInterface** ptr;
   1035     aCmd.PVMFWAVFFNodeCommandBase::Parse(uuid, ptr);
   1036 
   1037     if (queryInterface(*uuid, *ptr))
   1038     {
   1039         (*ptr)->addRef();
   1040         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1041     }
   1042     else
   1043     {
   1044         CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1045     }
   1046 }
   1047 
   1048 void PVMFWAVFFParserNode::DoInit(PVMFWAVFFNodeCommand& aCmd)
   1049 {
   1050     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoInitNode() In"));
   1051 
   1052     PVMFStatus iRet = PVMFSuccess;
   1053     // initialize the nextState to error
   1054     TPVMFNodeInterfaceState nextState = EPVMFNodeError;
   1055     switch (iInterfaceState)
   1056     {
   1057         case EPVMFNodeIdle:
   1058 
   1059             // first initialize the state to error
   1060             //this node doesn't need to do anything to get ready
   1061             //to start.
   1062 
   1063             break;
   1064 
   1065         default:
   1066             iRet = PVMFErrInvalidState;
   1067             CommandComplete(iInputCommands, aCmd, iRet);
   1068             return;
   1069     }
   1070 
   1071     if (iWAVParser != NULL)
   1072     {
   1073         iRet = PVMFFailure;
   1074         SetState(EPVMFNodeError);
   1075         CommandComplete(iInputCommands, aCmd, iRet);
   1076         return;
   1077     }
   1078 
   1079     int32 leavecode = 0;
   1080     OSCL_TRY(leavecode, iWAVParser = OSCL_NEW(PV_Wav_Parser, ()));
   1081     OSCL_FIRST_CATCH_ANY(leavecode,
   1082                          SetState(EPVMFNodeError);
   1083                          CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
   1084                          return;);
   1085     if (iWAVParser)
   1086     {
   1087         if (iWAVParser->InitWavParser(iFilename, &iFileServer) != PVWAVPARSER_OK)
   1088         {
   1089             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1090                             (0, "PVMFWAVFFParserNode::DoInit Error attempting to initialize the WAV parser"));
   1091             OSCL_DELETE(iWAVParser);
   1092             iWAVParser = NULL;
   1093             iRet = PVMFFailure;
   1094             CommandComplete(iInputCommands, aCmd, iRet);
   1095             return;
   1096         }
   1097         else if (!iWAVParser->RetrieveFileInfo(wavinfo))
   1098         {
   1099             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1100                             (0, "PVMFWAVFFParserNode::DoInit Error attempting to retrieve the WAV file info"));
   1101             OSCL_DELETE(iWAVParser);
   1102             iWAVParser = NULL;
   1103             iRet = PVMFFailure;
   1104         }
   1105         else if (!verify_supported_format())
   1106         {
   1107             OSCL_DELETE(iWAVParser);
   1108             iWAVParser = NULL;
   1109             iRet = PVMFErrNotSupported;
   1110         }
   1111         else
   1112         {
   1113             if ((wavinfo.AudioFormat == PVWAV_ITU_G711_ALAW) || (wavinfo.AudioFormat == PVWAV_ITU_G711_ULAW))
   1114             {
   1115                 if (iWAVParser->SetOutputToUncompressedPCM())
   1116                 {
   1117                     wavinfo.AudioFormat = PVWAV_PCM_AUDIO_FORMAT;
   1118                     wavinfo.BitsPerSample = 16;
   1119                     wavinfo.BytesPerSample = 2;
   1120                 }
   1121             }
   1122             if (iSelectedTrackList.size() ==  0)
   1123             {
   1124                 // save the port information in the selected track list
   1125                 PVWAVFFNodeTrackPortInfo trackportinfo;
   1126                 trackportinfo.iTrackId = 0;  // Only support 1 track
   1127                 trackportinfo.iTag = PVMF_WAVFFPARSER_NODE_PORT_TYPE_SOURCE;
   1128                 trackportinfo.iPort = iOutPort;
   1129                 trackportinfo.iClockConverter = NULL;
   1130                 trackportinfo.iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED;
   1131                 trackportinfo.iTrackDataMemoryPool = NULL;
   1132                 trackportinfo.iMediaDataImplAlloc = NULL;
   1133                 trackportinfo.iMediaDataMemPool = NULL;
   1134                 trackportinfo.iNode = this;
   1135                 iSelectedTrackList.push_back(trackportinfo);
   1136             }
   1137 
   1138             int error;
   1139             OSCL_TRY(error, InitializeTrackStructure());
   1140             OSCL_FIRST_CATCH_ANY(error,
   1141                                  PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFWAVFFParserNode::DoInitNode: Error - initializing tracks"));
   1142                                  OSCL_DELETE(iOutPort);
   1143                                  iOutPort = NULL;
   1144                                  iSelectedTrackList.erase(iSelectedTrackList.begin());
   1145                                  OSCL_DELETE(iWAVParser);
   1146                                  iWAVParser = NULL;
   1147                                  iRet = PVMFFailure;
   1148                                  SetState(EPVMFNodeError);
   1149                                  CommandComplete(iInputCommands, aCmd, iRet);
   1150                                  return;);
   1151 
   1152 
   1153             if (iOutPort && iOutPort->IsConnected())
   1154             {
   1155                 // set the new parameters on the connected port
   1156 
   1157                 OsclAny* temp = NULL;
   1158                 iOutPort->iConnectedPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, temp);
   1159                 PvmiCapabilityAndConfig *config = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, temp);
   1160 
   1161                 if (!config)
   1162                 {
   1163                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1164                                     (0, "PVMFWAVFFParserNode::DoInitNode: Error - Peer port does not support capability interface"));
   1165 
   1166                     iRet = PVMFFailure;
   1167                     SetState(EPVMFNodeError);
   1168                     CommandComplete(iInputCommands, aCmd, iRet);
   1169                     return;
   1170                 }
   1171                 PVMFStatus status = PVMFSuccess;
   1172 
   1173                 status = NegotiateSettings(config);
   1174 
   1175                 if (status != PVMFSuccess)
   1176                 {
   1177                     iRet = PVMFFailure;
   1178                     SetState(EPVMFNodeError);
   1179                     CommandComplete(iInputCommands, aCmd, iRet);
   1180                     return;
   1181                 }
   1182 
   1183             }
   1184 
   1185             // Add the available metadata keys to the vector
   1186             iAvailableMetadataKeys.clear();
   1187 
   1188             if (wavinfo.NumSamples > 0 && wavinfo.SampleRate > 0)
   1189             {
   1190                 leavecode = 0;
   1191                 OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVWAVMETADATA_DURATION_KEY));
   1192             }
   1193 
   1194             leavecode = 0;
   1195             OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVWAVMETADATA_NUMTRACKS_KEY));
   1196 
   1197             if (wavinfo.BitsPerSample > 0 && wavinfo.SampleRate > 0)
   1198             {
   1199                 leavecode = 0;
   1200                 OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVWAVMETADATA_TRACKINFO_BITRATE_KEY));
   1201             }
   1202 
   1203             if (wavinfo.SampleRate > 0)
   1204             {
   1205                 leavecode = 0;
   1206                 OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVWAVMETADATA_TRACKINFO_SAMPLERATE_KEY));
   1207             }
   1208 
   1209             if (wavinfo.NumChannels > 0)
   1210             {
   1211                 leavecode = 0;
   1212                 OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVWAVMETADATA_TRACKINFO_AUDIO_CHANNELS_KEY));
   1213             }
   1214 
   1215             if (wavinfo.AudioFormat != PVWAV_UNKNOWN_AUDIO_FORMAT)
   1216             {
   1217                 leavecode = 0;
   1218                 OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVWAVMETADATA_TRACKINFO_AUDIO_FORMAT_KEY));
   1219             }
   1220 
   1221             if (wavinfo.BytesPerSample > 0)
   1222             {
   1223                 leavecode = 0;
   1224                 OSCL_TRY(leavecode, iAvailableMetadataKeys.push_back(PVWAVMETADATA_TRACKINFO_AUDIO_BITSPERSAMPLE_KEY));
   1225             }
   1226 
   1227             nextState = EPVMFNodeInitialized;
   1228             iRet = PVMFSuccess;
   1229         }
   1230     }
   1231     else
   1232     {
   1233         iRet = PVMFErrNoMemory;
   1234     }
   1235 
   1236     SetState(nextState);
   1237     CommandComplete(iInputCommands, aCmd, iRet);
   1238 }
   1239 
   1240 // verify that the format is supported
   1241 bool PVMFWAVFFParserNode::verify_supported_format()
   1242 {
   1243     switch (wavinfo.AudioFormat)
   1244     {
   1245         case PVWAV_PCM_AUDIO_FORMAT:
   1246         case PVWAV_ITU_G711_ALAW:
   1247         case PVWAV_ITU_G711_ULAW:
   1248             return true;
   1249 
   1250         default:
   1251             break;
   1252     }
   1253     return false;
   1254 }
   1255 
   1256 /**
   1257  //Called by the command handler AO to do the node Prepare
   1258  */
   1259 void PVMFWAVFFParserNode::DoPrepare(PVMFWAVFFNodeCommand& aCmd)
   1260 {
   1261     switch (iInterfaceState)
   1262     {
   1263         case EPVMFNodeInitialized:
   1264             //this node doesn't need to do anything to get ready
   1265             //to start.
   1266             SetState(EPVMFNodePrepared);
   1267             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1268             break;
   1269 
   1270         default:
   1271             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1272                             (0, "PVMFWAVFFParserNode::DoPrepare: Error -- wrong state %d\n", iInterfaceState));
   1273             CommandComplete(iInputCommands, aCmd, PVMFErrInvalidState);
   1274             break;
   1275     }
   1276 }
   1277 
   1278 void PVMFWAVFFParserNode::DoStart(PVMFWAVFFNodeCommand& aCmd)
   1279 {
   1280     PVMFStatus status = PVMFSuccess;
   1281     switch (iInterfaceState)
   1282     {
   1283         case EPVMFNodePrepared:
   1284         case EPVMFNodePaused:
   1285             SetState(EPVMFNodeStarted);
   1286             break;
   1287 
   1288         default:
   1289             status = PVMFErrInvalidState;
   1290             break;
   1291     }
   1292 
   1293     RunIfNotReady(1);
   1294     CommandComplete(iInputCommands, aCmd, status);
   1295 }
   1296 
   1297 void PVMFWAVFFParserNode::DoStop(PVMFWAVFFNodeCommand& aCmd)
   1298 {
   1299     PVMFStatus status = PVMFSuccess;
   1300     switch (iInterfaceState)
   1301     {
   1302         case EPVMFNodeStarted:
   1303         case EPVMFNodePaused:
   1304             // stop and reset position to beginning
   1305             ResetAllTracks();
   1306 
   1307             // Reset the WAV FF to beginning
   1308             if (iWAVParser)
   1309             {
   1310                 iWAVParser->SeekPCMSample(0);
   1311             }
   1312 
   1313             //clear msg queue
   1314             if (iOutPort)
   1315                 iOutPort->ClearMsgQueues();
   1316             // Clear scheduled port activities
   1317             iPortActivityQueue.clear();
   1318 
   1319             //transition to Prepared state
   1320             SetState(EPVMFNodePrepared);
   1321             break;
   1322 
   1323         default:
   1324             status = PVMFErrInvalidState;
   1325             break;
   1326     }
   1327 
   1328     CommandComplete(iInputCommands, aCmd, status);
   1329 }
   1330 
   1331 
   1332 void PVMFWAVFFParserNode::DoPause(PVMFWAVFFNodeCommand& aCmd)
   1333 {
   1334     PVMFStatus status = PVMFSuccess;
   1335     switch (iInterfaceState)
   1336     {
   1337         case EPVMFNodeStarted:
   1338             SetState(EPVMFNodePaused);
   1339             break;
   1340 
   1341         default:
   1342             status = PVMFErrInvalidState;
   1343             break;
   1344     }
   1345 
   1346     CommandComplete(iInputCommands, aCmd, status);
   1347 }
   1348 
   1349 void PVMFWAVFFParserNode::DoFlush(PVMFWAVFFNodeCommand& aCmd)
   1350 {
   1351     PVMFStatus status = PVMFSuccess;
   1352     switch (iInterfaceState)
   1353     {
   1354         case EPVMFNodeStarted:
   1355         case EPVMFNodePaused:
   1356             //the flush is asynchronous.  move the command from
   1357             //the input command queue to the current command, where
   1358             //it will remain until the flush completes.
   1359 
   1360             int32 err;
   1361             OSCL_TRY(err, iCurrentCommand.StoreL(aCmd););
   1362             if (err != OsclErrNone)
   1363             {
   1364                 CommandComplete(iInputCommands, aCmd, PVMFErrNoMemory);
   1365                 return;
   1366             }
   1367             iInputCommands.Erase(&aCmd);
   1368             break;
   1369 
   1370         default:
   1371             status = PVMFErrInvalidState;
   1372             break;
   1373     }
   1374 
   1375     CommandComplete(iInputCommands, aCmd, status);
   1376 }
   1377 
   1378 
   1379 /**
   1380  //A routine to tell if a flush operation is in progress.
   1381  */
   1382 bool PVMFWAVFFParserNode::FlushPending()
   1383 {
   1384     return (iCurrentCommand.size() > 0
   1385             && iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
   1386 }
   1387 
   1388 void PVMFWAVFFParserNode::DoReset(PVMFWAVFFNodeCommand& aCmd)
   1389 {
   1390     ReleaseAllPorts();
   1391     //discard any port activity events
   1392     iPortActivityQueue.clear();
   1393     CleanupFileSource();
   1394     SetState(EPVMFNodeIdle);
   1395     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1396 
   1397 }
   1398 
   1399 void PVMFWAVFFParserNode::DoCancelAllCommands(PVMFWAVFFNodeCommand& aCmd)
   1400 {
   1401     //first cancel the current command if any
   1402     {
   1403         while (!iCurrentCommand.empty())
   1404             CommandComplete(iCurrentCommand, iCurrentCommand[0], PVMFErrCancelled);
   1405     }
   1406 
   1407     //next cancel all queued commands
   1408     {
   1409         //start at element 1 since this cancel command is element 0.
   1410         while (iInputCommands.size() > 1)
   1411             CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled);
   1412     }
   1413 
   1414     //finally, report cancel complete.
   1415     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1416 }
   1417 
   1418 /**
   1419  //Called by the command handler AO to do the Cancel single command
   1420  */
   1421 void PVMFWAVFFParserNode::DoCancelCommand(PVMFWAVFFNodeCommand& aCmd)
   1422 {
   1423     //extract the command ID from the parameters.
   1424     PVMFCommandId id;
   1425     aCmd.PVMFWAVFFNodeCommandBase::Parse(id);
   1426 
   1427     //first check "current" command if any
   1428     {
   1429         PVMFWAVFFNodeCommand* cmd = iCurrentCommand.FindById(id);
   1430         if (cmd)
   1431         {
   1432             //cancel the queued command
   1433             CommandComplete(iCurrentCommand, *cmd, PVMFErrCancelled);
   1434             //report cancel success
   1435             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1436             return;
   1437         }
   1438     }
   1439 
   1440     //next check input queue.
   1441     {
   1442         //start at element 1 since this cancel command is element 0.
   1443         PVMFWAVFFNodeCommand* cmd = iInputCommands.FindById(id, 1);
   1444         if (cmd)
   1445         {
   1446             //cancel the queued command
   1447             CommandComplete(iInputCommands, *cmd, PVMFErrCancelled);
   1448             //report cancel success
   1449             CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1450             return;
   1451         }
   1452     }
   1453     //if we get here the command isn't queued so the cancel fails.
   1454     CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1455 }
   1456 
   1457 
   1458 void PVMFWAVFFParserNode::InitializeTrackStructure()
   1459 {
   1460     // compute the number samples and buffer size that will be used for each message
   1461     trackdata_num_samples = (wavinfo.SampleRate * PVWAV_MSEC_PER_BUFFER) / 1000; // samples in buffer
   1462     trackdata_bufsize = trackdata_num_samples * wavinfo.BytesPerSample * wavinfo.NumChannels;
   1463 
   1464     iSelectedTrackList[0].iClockConverter = OSCL_NEW(MediaClockConverter, (wavinfo.SampleRate));
   1465     iSelectedTrackList[0].iTrackDataMemoryPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (PVWAVFF_MEDIADATA_POOLNUM));
   1466     iSelectedTrackList[0].iMediaDataImplAlloc = OSCL_NEW(PVMFSimpleMediaBufferCombinedAlloc, (iSelectedTrackList[0].iTrackDataMemoryPool));
   1467     iSelectedTrackList[0].iMediaDataMemPool = OSCL_NEW(PVMFMemPoolFixedChunkAllocator, ("WavFFPar", PVWAVFF_MEDIADATA_POOLNUM, PVWAVFF_MEDIADATA_CHUNKSIZE));
   1468     if (iSelectedTrackList[0].iMediaDataMemPool)
   1469     {
   1470         iSelectedTrackList[0].iMediaDataMemPool->enablenullpointerreturn();
   1471     }
   1472 
   1473 }
   1474 
   1475 
   1476 void PVMFWAVFFParserNode::DoRequestPort(PVMFWAVFFNodeCommand& aCmd)
   1477 {
   1478     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoRequestPort() In"));
   1479 
   1480     //retrieve port tag.
   1481     int32 tag;
   1482     OSCL_String* portconfig;
   1483     aCmd.PVMFWAVFFNodeCommandBase::Parse(tag, portconfig);
   1484 
   1485     //validate the tag...
   1486     if (tag != PVMF_WAVFFPARSER_NODE_PORT_TYPE_SOURCE)
   1487     {
   1488         //bad port tag
   1489         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1490                         (0, "PVMFWAVFFParserNode::DoRequestPort: Error - Invalid port tag"));
   1491         CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1492         return;
   1493     }
   1494 
   1495 
   1496     // Allocate a port based on the request
   1497     // Return the pointer to the port in the command complete message
   1498     iCmdRespPort = NULL;
   1499 
   1500     //check the tag
   1501     if ((int32)aCmd.iParam1 == PVMF_WAVFFPARSER_NODE_PORT_TYPE_SOURCE)
   1502     {
   1503 
   1504         if (iOutPort)
   1505         {
   1506             // only supporting one track
   1507             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1508                             (0, "PVMFWAVFFParserNode::DoRequestPort: Only supporting one output port"));
   1509             CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1510             return;
   1511         }
   1512 
   1513         iOutPort = OSCL_NEW(PVMFWAVFFParserOutPort, (PVMF_WAVFFPARSER_NODE_PORT_TYPE_SOURCE, this));
   1514         if (!iOutPort)
   1515         {
   1516             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1517                             (0, "PVMFWAVFFParserNode::DoRequestPort: Error - Can't create output port"));
   1518             CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1519             return;
   1520         }
   1521 
   1522         if (iSelectedTrackList.size() > 0)
   1523         {
   1524             iSelectedTrackList[0].iTag = PVMF_WAVFFPARSER_NODE_PORT_TYPE_SOURCE;
   1525             iSelectedTrackList[0].iPort = iOutPort;
   1526         }
   1527         else if (iWAVParser)
   1528         {
   1529             // this is the case if the port is destroyed and re-created after init
   1530             // save the port information in the selected track list
   1531             PVWAVFFNodeTrackPortInfo trackportinfo;
   1532             trackportinfo.iTrackId = 0;  // Only support 1 track
   1533             trackportinfo.iTag = PVMF_WAVFFPARSER_NODE_PORT_TYPE_SOURCE;
   1534             trackportinfo.iPort = iOutPort;
   1535             trackportinfo.iClockConverter = NULL;
   1536             trackportinfo.iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED;
   1537             trackportinfo.iTrackDataMemoryPool = NULL;
   1538             trackportinfo.iMediaDataImplAlloc = NULL;
   1539             trackportinfo.iMediaDataMemPool = NULL;
   1540             trackportinfo.iNode = this;
   1541             iSelectedTrackList.push_back(trackportinfo);
   1542 
   1543             int error;
   1544             OSCL_TRY(error, InitializeTrackStructure());
   1545             OSCL_FIRST_CATCH_ANY(error, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFWAVFFParserNode::RequestPort: Error - initializing tracks"));
   1546                                  OSCL_DELETE(iOutPort);
   1547                                  iOutPort = NULL;
   1548                                  iSelectedTrackList.erase(iSelectedTrackList.begin());
   1549                                  OSCL_DELETE(iWAVParser);
   1550                                  iWAVParser = NULL;
   1551                                  SetState(EPVMFNodeError);
   1552                                  CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1553                                  return;);
   1554 
   1555         }
   1556 
   1557         iPortActivityQueue.reserve(PVMF_WAVFFPARSER_NODE_COMMAND_VECTOR_RESERVE);
   1558 
   1559         iCmdRespPort = iOutPort;
   1560 
   1561     }
   1562     else
   1563     {
   1564         // don't support other types yet
   1565         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
   1566                         (0, "PVMFWAVFFParserNode::DoRequestPort: Error - unsupported port type"));
   1567         CommandComplete(iInputCommands, aCmd, PVMFFailure);
   1568         return;
   1569     }
   1570 
   1571     CommandComplete(iInputCommands, aCmd, PVMFSuccess, (OsclAny*)iCmdRespPort);
   1572 }
   1573 
   1574 void PVMFWAVFFParserNode::DoReleasePort(PVMFWAVFFNodeCommand& aCmd)
   1575 {
   1576 
   1577     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1578                     (0, "PVMFWAVFFParserNode::DoReleasePort"));
   1579 
   1580     // search for the matching port address
   1581     // disconnect it, if needed
   1582     // cleanup the buffers associated with it
   1583     // delete the port
   1584     // set the address to NULL
   1585 
   1586     // Remove the selected track from the track list
   1587     int32 i = 0;
   1588     int32 maxtrack = iSelectedTrackList.size();
   1589     while (i < maxtrack)
   1590     {
   1591         if (iSelectedTrackList[i].iPort == aCmd.iParam1)
   1592         {
   1593             // Found the element. So erase it
   1594             iSelectedTrackList[i].iMediaData.Unbind();
   1595             if (iSelectedTrackList[i].iPort)
   1596             {
   1597                 iSelectedTrackList[i].iPort->Disconnect();
   1598                 OSCL_DELETE(((PVMFWAVFFParserOutPort*)iSelectedTrackList[i].iPort));
   1599                 iSelectedTrackList[i].iPort = NULL;
   1600                 iOutPort = NULL;
   1601             }
   1602             OSCL_DELETE(iSelectedTrackList[i].iClockConverter);
   1603             OSCL_DELETE(iSelectedTrackList[i].iTrackDataMemoryPool);
   1604             OSCL_DELETE(iSelectedTrackList[i].iMediaDataImplAlloc);
   1605             OSCL_DELETE(iSelectedTrackList[i].iMediaDataMemPool);
   1606             iSelectedTrackList.erase(iSelectedTrackList.begin() + i);
   1607             break;
   1608         }
   1609         ++i;
   1610     }
   1611 
   1612     if (i >= maxtrack)
   1613     {
   1614         CommandComplete(iInputCommands, aCmd, PVMFErrBadHandle);
   1615     }
   1616 
   1617     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   1618 }
   1619 
   1620 
   1621 void PVMFWAVFFParserNode::ResetAllTracks()
   1622 {
   1623     for (uint32 i = 0; i < iSelectedTrackList.size(); ++i)
   1624     {
   1625         iSelectedTrackList[i].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED;
   1626         iSelectedTrackList[i].iMediaData.Unbind();
   1627         iSelectedTrackList[i].iSeqNum = 0;
   1628     }
   1629 }
   1630 
   1631 bool PVMFWAVFFParserNode::ReleaseAllPorts()
   1632 {
   1633 
   1634     while (!iSelectedTrackList.empty())
   1635     {
   1636         if (iSelectedTrackList[0].iPort)
   1637         {
   1638             iSelectedTrackList[0].iPort->Disconnect();
   1639         }
   1640         iSelectedTrackList[0].iMediaData.Unbind();
   1641         OSCL_DELETE(iSelectedTrackList[0].iClockConverter);
   1642         OSCL_DELETE(iSelectedTrackList[0].iTrackDataMemoryPool);
   1643         OSCL_DELETE(iSelectedTrackList[0].iMediaDataImplAlloc);
   1644         OSCL_DELETE(iSelectedTrackList[0].iMediaDataMemPool);
   1645         iSelectedTrackList.erase(iSelectedTrackList.begin());
   1646     }
   1647 
   1648     if (iOutPort)
   1649     {
   1650         OSCL_DELETE(iOutPort);
   1651         iOutPort = NULL;
   1652     }
   1653 
   1654     return true;
   1655 }
   1656 
   1657 void PVMFWAVFFParserNode::CleanupFileSource()
   1658 {
   1659     iAvailableMetadataKeys.clear();
   1660 
   1661     if (iWAVParser)
   1662     {
   1663         OSCL_DELETE(iWAVParser);
   1664         iWAVParser = NULL;
   1665     }
   1666 }
   1667 
   1668 
   1669 void PVMFWAVFFParserNode::CommandComplete(PVMFWAVFFNodeCmdQ& aCmdQ, PVMFWAVFFNodeCommand& aCmd, PVMFStatus aStatus, OsclAny* aEventData, PVUuid* aEventUUID, int32* aEventCode)
   1670 {
   1671     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode:CommandComplete Id %d Cmd %d Status %d Context %d Data %d"
   1672                     , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
   1673 
   1674     PVInterface* extif = NULL;
   1675     PVMFBasicErrorInfoMessage* errormsg = NULL;
   1676     if (aEventUUID && aEventCode)
   1677     {
   1678         int32 leavecode = 0;
   1679         OSCL_TRY(leavecode, errormsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL)));
   1680         if (leavecode == 0)
   1681         {
   1682             extif = OSCL_STATIC_CAST(PVInterface*, errormsg);
   1683         }
   1684     }
   1685 
   1686     //create response
   1687     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, extif, aEventData);
   1688     PVMFSessionId session = aCmd.iSession;
   1689 
   1690     //Erase the command from the queue.
   1691     aCmdQ.Erase(&aCmd);
   1692 
   1693     //Report completion to the session observer.
   1694     ReportCmdCompleteEvent(session, resp);
   1695 
   1696     if (errormsg)
   1697     {
   1698         errormsg->removeRef();
   1699     }
   1700 }
   1701 
   1702 
   1703 PVMFCommandId PVMFWAVFFParserNode::QueueCommandL(PVMFWAVFFNodeCommand& aCmd)
   1704 {
   1705     if (IsAdded())
   1706     {
   1707         PVMFCommandId id;
   1708         id = iInputCommands.AddL(aCmd);
   1709         /* Wakeup the AO */
   1710         RunIfNotReady();
   1711         return id;
   1712     }
   1713     OSCL_LEAVE(OsclErrInvalidState);
   1714     return -1;
   1715 }
   1716 
   1717 
   1718 bool PVMFWAVFFParserNode::HandleOutgoingQueueReady(PVMFPortInterface* aPortInterface)
   1719 {
   1720     uint32 i = 0;
   1721     while (i++ < iSelectedTrackList.size())
   1722     {
   1723         if (iSelectedTrackList[i].iPort == aPortInterface &&
   1724                 iSelectedTrackList[i].iState == PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA)
   1725         {
   1726             // Found the element and right state
   1727             // re-send the data
   1728             if (!SendTrackData(iSelectedTrackList[i]))
   1729             {
   1730                 return false;
   1731             }
   1732 
   1733             // Success in re-sending the data, and change state to getdata
   1734             iSelectedTrackList[i].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
   1735             return true;
   1736         }
   1737     }
   1738 
   1739     // No match found.
   1740     return false;
   1741 }
   1742 
   1743 
   1744 /**
   1745 //////////////////////////////////////////////////
   1746 // Extension interface implementation
   1747 //////////////////////////////////////////////////
   1748 */
   1749 
   1750 void PVMFWAVFFParserNode::addRef()
   1751 {
   1752     ++iExtensionRefCount;
   1753 }
   1754 
   1755 void PVMFWAVFFParserNode::removeRef()
   1756 {
   1757     --iExtensionRefCount;
   1758 }
   1759 
   1760 PVMFStatus PVMFWAVFFParserNode::QueryInterfaceSync(PVMFSessionId aSession,
   1761         const PVUuid& aUuid,
   1762         PVInterface*& aInterfacePtr)
   1763 {
   1764     OSCL_UNUSED_ARG(aSession);
   1765     aInterfacePtr = NULL;
   1766     if (queryInterface(aUuid, aInterfacePtr))
   1767     {
   1768         aInterfacePtr->addRef();
   1769         return PVMFSuccess;
   1770     }
   1771     return PVMFErrNotSupported;
   1772 }
   1773 
   1774 bool PVMFWAVFFParserNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
   1775 {
   1776     if (PVMF_DATA_SOURCE_INIT_INTERFACE_UUID == uuid)
   1777     {
   1778         PVMFDataSourceInitializationExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this);
   1779         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
   1780     }
   1781     else if (PVMF_TRACK_SELECTION_INTERFACE_UUID == uuid)
   1782     {
   1783         PVMFTrackSelectionExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this);
   1784         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
   1785     }
   1786     else if (KPVMFMetadataExtensionUuid == uuid)
   1787     {
   1788         PVMFMetadataExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this);
   1789         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
   1790     }
   1791     else if (PvmfDataSourcePlaybackControlUuid == uuid)
   1792     {
   1793         PvmfDataSourcePlaybackControlInterface* myInterface = OSCL_STATIC_CAST(PvmfDataSourcePlaybackControlInterface*, this);
   1794         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
   1795     }
   1796     else
   1797     {
   1798         return false;
   1799     }
   1800     return true;
   1801 }
   1802 
   1803 PVMFStatus PVMFWAVFFParserNode::SetSourceInitializationData(OSCL_wString& aSourceURL, PVMFFormatType& aSourceFormat, OsclAny* aSourceData)
   1804 {
   1805     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::SetSourceInitializationData() called"));
   1806 
   1807     OSCL_UNUSED_ARG(aSourceData);
   1808 
   1809     if (aSourceFormat != PVMF_MIME_WAVFF)
   1810     {
   1811         return PVMFFailure;
   1812     }
   1813 
   1814     iFilename = aSourceURL;
   1815     return PVMFSuccess;
   1816 }
   1817 
   1818 PVMFStatus PVMFWAVFFParserNode::SetClientPlayBackClock(PVMFMediaClock* aClientClock)
   1819 {
   1820     OSCL_UNUSED_ARG(aClientClock);
   1821     return PVMFSuccess;
   1822 }
   1823 
   1824 PVMFStatus PVMFWAVFFParserNode::SetEstimatedServerClock(PVMFMediaClock* aClientClock)
   1825 {
   1826     OSCL_UNUSED_ARG(aClientClock);
   1827     return PVMFSuccess;
   1828 }
   1829 
   1830 //From PVMFTrackSelectionExtensionInterface
   1831 PVMFStatus PVMFWAVFFParserNode::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo)
   1832 {
   1833     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::GetMediaPresentationInfo() called"));
   1834 
   1835     // Check to make sure the WAV file has been parsed
   1836     if (!iWAVParser)
   1837     {
   1838         return PVMFFailure;
   1839     }
   1840 
   1841     uint32 duration_sec = wavinfo.NumSamples / wavinfo.SampleRate;
   1842     uint32 duration_msec = wavinfo.NumSamples % wavinfo.SampleRate;
   1843     uint32 duration = (duration_msec * 1000) / wavinfo.SampleRate + duration_sec * 1000 ;
   1844 
   1845     aInfo.setDurationValue(duration);
   1846     // Current version of WAV parser is limited to 1 channel
   1847     PVMFTrackInfo tmpTrackInfo;
   1848 
   1849     // set the port tag for this track
   1850     tmpTrackInfo.setPortTag(PVMF_WAVFFPARSER_NODE_PORT_TYPE_SOURCE);
   1851 
   1852     // track id
   1853     tmpTrackInfo.setTrackID(0);
   1854 
   1855     // check supported formats
   1856 
   1857     // bitrate
   1858     tmpTrackInfo.setTrackBitRate(wavinfo.ByteRate*8 /* convert bytes to bits */);
   1859 
   1860     // timescale
   1861     tmpTrackInfo.setTrackDurationTimeScale((uint64)wavinfo.SampleRate);
   1862 
   1863     // config info
   1864 
   1865     // mime type
   1866     OSCL_FastString mime_type;
   1867 
   1868     if (wavinfo.AudioFormat == PVWAV_PCM_AUDIO_FORMAT)
   1869     {
   1870         if (wavinfo.BitsPerSample == 8)
   1871         {
   1872             mime_type = _STRLIT_CHAR(PVMF_MIME_PCM8);
   1873         }
   1874         else if (wavinfo.isLittleEndian)
   1875         {
   1876             mime_type = _STRLIT_CHAR(PVMF_MIME_PCM16);
   1877         }
   1878         else
   1879         {
   1880             mime_type = _STRLIT_CHAR(PVMF_MIME_PCM16_BE);
   1881         }
   1882     }
   1883     else if (wavinfo.AudioFormat == PVWAV_ITU_G711_ALAW)
   1884     {
   1885         mime_type =  _STRLIT_CHAR(PVMF_MIME_ALAW);
   1886     }
   1887     else if (wavinfo.AudioFormat == PVWAV_ITU_G711_ULAW)
   1888     {
   1889         mime_type = _STRLIT_CHAR(PVMF_MIME_ULAW);
   1890     }
   1891     else
   1892     {
   1893         return PVMFFailure;
   1894     }
   1895 
   1896     tmpTrackInfo.setTrackMimeType(mime_type);
   1897 
   1898     // add the track
   1899     aInfo.addTrackInfo(tmpTrackInfo);
   1900 
   1901     return PVMFSuccess;
   1902 }
   1903 
   1904 PVMFStatus PVMFWAVFFParserNode::SelectTracks(PVMFMediaPresentationInfo& aInfo)
   1905 {
   1906     OSCL_UNUSED_ARG(aInfo);
   1907     return PVMFSuccess;
   1908 }
   1909 
   1910 ///////////// Implementation of PVWAVFFNodeTrackPortInfo //////////////////////
   1911 void PVWAVFFNodeTrackPortInfo::freechunkavailable(OsclAny*)
   1912 {
   1913     // Activate the parent node if necessary
   1914     if (iNode)
   1915     {
   1916         if (iNode->IsAdded())
   1917         {
   1918             iNode->RunIfNotReady();
   1919         }
   1920     }
   1921 }
   1922 
   1923 
   1924 // From PvmfDataSourcePlaybackControlInterface
   1925 PVMFCommandId PVMFWAVFFParserNode::SetDataSourcePosition(PVMFSessionId aSessionId, PVMFTimestamp aTargetNPT, PVMFTimestamp& aActualNPT, PVMFTimestamp& aActualMediaDataTS, bool aSeekToSyncPoint, uint32 aStreamID, OsclAny* aContext)
   1926 {
   1927     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1928                     (0, "PVMFWAVParserNode::SetDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x",
   1929                      aTargetNPT, aSeekToSyncPoint, aContext));
   1930 
   1931     PVMFWAVFFNodeCommand cmd;
   1932     cmd.PVMFWAVFFNodeCommand::Construct(aSessionId, PVWAVFF_NODE_CMD_SETDATASOURCEPOSITION, aTargetNPT, &aActualNPT,  &aActualMediaDataTS, aSeekToSyncPoint, aStreamID, aContext);
   1933     return QueueCommandL(cmd);
   1934 }
   1935 
   1936 
   1937 PVMFCommandId PVMFWAVFFParserNode::QueryDataSourcePosition(PVMFSessionId aSessionId, PVMFTimestamp aTargetNPT, PVMFTimestamp& aActualNPT, bool aSeekToSyncPoint, OsclAny* aContext)
   1938 {
   1939     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1940                     (0, "PVMFWAVParserNode::QueryDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x",
   1941                      aTargetNPT, aSeekToSyncPoint, aContext));
   1942 
   1943     PVMFWAVFFNodeCommand cmd;
   1944     cmd.PVMFWAVFFNodeCommand::Construct(aSessionId, PVWAVFF_NODE_CMD_QUERYDATASOURCEPOSITION, aTargetNPT, &aActualNPT, aSeekToSyncPoint, aContext);
   1945     return QueueCommandL(cmd);
   1946 }
   1947 
   1948 PVMFCommandId PVMFWAVFFParserNode::QueryDataSourcePosition(PVMFSessionId aSessionId,
   1949         PVMFTimestamp aTargetNPT,
   1950         PVMFTimestamp& aSeekPointBeforeTargetNPT,
   1951         PVMFTimestamp& aSeekPointAfterTargetNPT,
   1952         OsclAny* aContext,
   1953         bool aSeekToSyncPoint)
   1954 {
   1955     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1956                     (0, "PVMFWAVParserNode::QueryDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x",
   1957                      aTargetNPT, aSeekToSyncPoint,  aContext));
   1958     OSCL_UNUSED_ARG(aSeekPointAfterTargetNPT);
   1959 
   1960     PVMFWAVFFNodeCommand cmd;
   1961     // Construct not changed, aSeekPointBeforeTargetNPThas replace aAcutalNPT
   1962     cmd.PVMFWAVFFNodeCommand::Construct(aSessionId, PVWAVFF_NODE_CMD_QUERYDATASOURCEPOSITION, aTargetNPT, &aSeekPointBeforeTargetNPT, aSeekToSyncPoint, aContext);
   1963     return QueueCommandL(cmd);
   1964 }
   1965 
   1966 
   1967 PVMFCommandId PVMFWAVFFParserNode::SetDataSourceRate(PVMFSessionId aSessionId, int32 aRate, PVMFTimebase* aTimebase, OsclAny* aContext)
   1968 {
   1969     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::SetDataSourceRate() called"));
   1970 
   1971     PVMFWAVFFNodeCommand cmd;
   1972     cmd.PVMFWAVFFNodeCommand::Construct(aSessionId, PVWAVFF_NODE_CMD_SETDATASOURCERATE, aRate, aTimebase, aContext);
   1973     return QueueCommandL(cmd);
   1974 }
   1975 
   1976 void PVMFWAVFFParserNode::DoSetDataSourcePosition(PVMFWAVFFNodeCommand& aCmd)
   1977 {
   1978     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoSetDataSourcePosition() In"));
   1979 
   1980     uint32 targetNPT = 0;
   1981     uint32* actualNPT = NULL;
   1982     uint32* actualMediaDataTS = NULL;
   1983     bool jumpToIFrame = false;
   1984     uint32 streamID = 0;
   1985     aCmd.PVMFWAVFFNodeCommand::Parse(targetNPT, actualNPT, actualMediaDataTS, jumpToIFrame, streamID);
   1986 
   1987     uint32 i = 0;
   1988     for (i = 0; i < iSelectedTrackList.size(); ++i)
   1989     {
   1990         iSelectedTrackList[i].iSendBOS = true;
   1991     }
   1992     //save the stream id for next media segment
   1993     iStreamID = streamID;
   1994 
   1995 
   1996     *actualMediaDataTS = iSelectedTrackList[0].iClockConverter->get_converted_ts(COMMON_PLAYBACK_CLOCK_TIMESCALE);
   1997 
   1998     // see if targetNPT is greater than or equal to clip duration.
   1999     uint32 duration_sec = wavinfo.NumSamples / wavinfo.SampleRate;
   2000     uint32 duration_msec = wavinfo.NumSamples % wavinfo.SampleRate;
   2001     uint32 duration = (duration_msec * 1000) / wavinfo.SampleRate + duration_sec * 1000 ;
   2002     uint32 tempTargetNPT = targetNPT;
   2003     if (tempTargetNPT >= duration)
   2004     {
   2005         // need to reset the tracks to zero.
   2006         targetNPT = 0;
   2007         // reset the track to zero and then report EOS for the tracks.
   2008     }
   2009 
   2010     // compute the sample corresponding to the target NPT
   2011     // NPT is in milliseconds so divide by 1000
   2012     uint32 target_sec = targetNPT / 1000;
   2013     uint32 target_millisec = targetNPT % 1000;
   2014     uint32 target_sample = (target_millisec * wavinfo.SampleRate) / 1000 + target_sec * wavinfo.SampleRate;
   2015 
   2016     if (target_sample > wavinfo.NumSamples)
   2017     {
   2018         // limit it to the end of the clip
   2019         target_sample = wavinfo.NumSamples;
   2020     }
   2021 
   2022     {
   2023         uint32 position_sec = target_sample / wavinfo.SampleRate;
   2024         uint32 position_msec = target_sample % wavinfo.SampleRate;
   2025         *actualNPT = (position_msec * 1000) / wavinfo.NumSamples + position_sec * 1000;
   2026         if (tempTargetNPT >= duration)
   2027         {
   2028             // need to send duration in *actualNPT
   2029             *actualNPT = duration;
   2030         }
   2031     }
   2032 
   2033     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode::DoSetDataSourcePosition() targetNPT=%d, target sample=%d, actualNPT=%d, actualMediaTS=%d", targetNPT, target_sample, *actualNPT, *actualMediaDataTS));
   2034 
   2035 
   2036     PVWavParserReturnCode retval = iWAVParser->SeekPCMSample(target_sample);
   2037     // reposition the file
   2038     if (PVWAVPARSER_OK != retval)
   2039     {
   2040         PVUuid eventuuid;
   2041         int32 eventcode;
   2042         if (!MapWAVErrorCodeToEventCode(retval, eventuuid, eventcode))
   2043         {
   2044             eventuuid = PVMFFileFormatEventTypesUUID;
   2045             eventcode = PVMFFFErrMisc;
   2046         }
   2047         CommandComplete(iInputCommands, aCmd, PVMFErrResource, NULL, &eventuuid, &eventcode);
   2048     }
   2049     else
   2050     {
   2051         if (tempTargetNPT >= duration)
   2052         {
   2053             // we need to send EOS for the tracks. Change the trackstate to EndOftrack.
   2054             for (uint32 ii = 0; ii < iSelectedTrackList.size(); ++ii)
   2055             {
   2056                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode::DoSetDataSourcePosition targetNPT >= duration , report BOS-EOS"));
   2057                 iSelectedTrackList[ii].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
   2058             }
   2059         }
   2060         else
   2061         {
   2062             // reset the state of the track if they are currently at the end of the file
   2063             for (uint32 ii = 0; ii < iSelectedTrackList.size(); ++ii)
   2064             {
   2065                 if ((PVWAVFFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK == iSelectedTrackList[ii].iState) ||
   2066                         (PVWAVFFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK == iSelectedTrackList[ii].iState))
   2067                 {
   2068                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFWAVFFParserNode::DoSetDataSourcePosition() reseting track state of track %d from endoftrack", ii));
   2069                     iSelectedTrackList[ii].iState = PVWAVFFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
   2070                 }
   2071             }
   2072         }
   2073         CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   2074     }
   2075     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoSetDataSourcePosition() Out"));
   2076 
   2077 }
   2078 
   2079 
   2080 void PVMFWAVFFParserNode::DoQueryDataSourcePosition(PVMFWAVFFNodeCommand& aCmd)
   2081 {
   2082     uint32 targetNPT = 0;
   2083     uint32* actualNPT = NULL;
   2084     bool seektosyncpoint = false;
   2085 
   2086     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoQueryDataSourcePosition() In"));
   2087 
   2088     aCmd.PVMFWAVFFNodeCommand::Parse(targetNPT, actualNPT, seektosyncpoint);
   2089     if (actualNPT == NULL)
   2090     {
   2091         CommandComplete(iInputCommands, aCmd, PVMFErrArgument);
   2092         return;
   2093     }
   2094 
   2095     // compute the sample corresponding to the target NPT
   2096     // NPT is in milliseconds so divide by 1000
   2097     uint32 target_sec = targetNPT / 1000;
   2098     uint32 target_millisec = targetNPT % 1000;
   2099     uint32 target_sample = (target_millisec * wavinfo.SampleRate) / 1000 + target_sec * wavinfo.SampleRate;
   2100 
   2101     if (target_sample > wavinfo.NumSamples)
   2102     {
   2103         // limit it to the end of the clip
   2104         target_sample = wavinfo.NumSamples;
   2105     }
   2106 
   2107     {
   2108         uint32 position_sec = target_sample / wavinfo.SampleRate;
   2109         uint32 position_msec = target_sample % wavinfo.SampleRate;
   2110         *actualNPT = (position_msec * 1000) / wavinfo.NumSamples + position_sec * 1000;
   2111     }
   2112 
   2113     CommandComplete(iInputCommands, aCmd, PVMFSuccess);
   2114 
   2115     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoQueryDataSourcePosition() Out"));
   2116 }
   2117 
   2118 
   2119 void PVMFWAVFFParserNode::DoSetDataSourceRate(PVMFWAVFFNodeCommand& aCmd)
   2120 {
   2121 
   2122     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoSetDataSourceRate() In"));
   2123 
   2124     // Retrieve the new rate
   2125     int32 rate;
   2126     PVMFTimebase* timebase = NULL;
   2127     PVMFStatus cmdstatus = PVMFSuccess;
   2128     aCmd.PVMFWAVFFNodeCommand::Parse(rate, timebase);
   2129 
   2130     if (timebase == NULL)
   2131     {
   2132         if (rate < MIN_WAVFFPARSER_RATE || rate > MAX_WAVFFPARSER_RATE)
   2133         {
   2134             // Limit to MIN and MAX RATES for now.
   2135             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFWAVFFParserNode::DoSetDataSourceRate() Invalid playback rate %d valid range is [%d, %d]", rate, MIN_WAVFFPARSER_RATE, MAX_WAVFFPARSER_RATE));
   2136             cmdstatus = PVMFErrNotSupported;
   2137         }
   2138     }
   2139     else
   2140     {
   2141         // Allow outside timebase
   2142     }
   2143 
   2144     // complete the command
   2145     CommandComplete(iInputCommands, aCmd, cmdstatus);
   2146 
   2147     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoSetDataSourceRate() Out"));
   2148 
   2149 }
   2150 
   2151 
   2152 bool PVMFWAVFFParserNode::MapWAVErrorCodeToEventCode(int32 aWAVErrCode, PVUuid& aEventUUID, int32& aEventCode)
   2153 {
   2154 
   2155     switch (aWAVErrCode)
   2156     {
   2157         case PVWAVPARSER_UNSUPPORTED_FORMAT:
   2158             aEventUUID = PVMFFileFormatEventTypesUUID;
   2159             aEventCode = PVMFFFErrFileRead;
   2160             break;
   2161 
   2162         case PVWAVPARSER_READ_ERROR:
   2163             aEventUUID = PVMFFileFormatEventTypesUUID;
   2164             aEventCode = PVMFFFErrFileRead;
   2165             break;
   2166 
   2167         case PVWAVPARSER_MISC_ERROR:
   2168             aEventUUID = PVMFFileFormatEventTypesUUID;
   2169             aEventCode = PVMFFFErrNotSupported;
   2170             break;
   2171 
   2172         case PVWAVPARSER_OK:
   2173             OSCL_ASSERT(false); // Should not pass this "error" code to this function
   2174 
   2175         default:
   2176             return false;
   2177     }
   2178 
   2179     return true;
   2180 }
   2181 
   2182 
   2183 
   2184 bool PVMFWAVFFParserNode::SendEndOfTrackCommand(PVWAVFFNodeTrackPortInfo& aTrackPortInfo)
   2185 {
   2186     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::SendEndOfTrackCommand() In"));
   2187 
   2188     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
   2189 
   2190     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);
   2191 
   2192     sharedMediaCmdPtr->setStreamID(iStreamID);
   2193 
   2194     // Set timestamp
   2195     uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(COMMON_PLAYBACK_CLOCK_TIMESCALE);
   2196     sharedMediaCmdPtr->setTimestamp(timestamp);
   2197 
   2198     // Set the sequence number
   2199     sharedMediaCmdPtr->setSeqNum(aTrackPortInfo.iSeqNum++);
   2200 
   2201     PVMFSharedMediaMsgPtr mediaMsgOut;
   2202     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
   2203 
   2204     if (aTrackPortInfo.iPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
   2205     {
   2206         // Output queue is busy, so wait for the output queue being ready
   2207         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
   2208                         (0, "PVMFWAVFFParserNode::SendEndOfTrackCommand: Outgoing queue busy. "));
   2209         return false;
   2210     }
   2211 
   2212     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::SendEndOfTrackCommand() Out"));
   2213     return true;
   2214 }
   2215 
   2216 
   2217 bool PVMFWAVFFParserNode::SendBeginOfMediaStreamCommand(PVWAVFFNodeTrackPortInfo& aTrackPortInfo)
   2218 {
   2219     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
   2220     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID);
   2221 
   2222     uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(COMMON_PLAYBACK_CLOCK_TIMESCALE);
   2223     sharedMediaCmdPtr->setTimestamp(timestamp);
   2224 
   2225     uint32 seqNum = 0;
   2226     sharedMediaCmdPtr->setSeqNum(seqNum);
   2227 
   2228     PVMFSharedMediaMsgPtr mediaMsgOut;
   2229     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
   2230     mediaMsgOut->setStreamID(iStreamID);
   2231 
   2232     if (aTrackPortInfo.iPort->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
   2233     {
   2234         // Output queue is busy, so wait for the output queue being ready
   2235         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
   2236                         (0, "PVMFWAVFFParserNode::SendBeginOfMediaStreamCommand: Outgoing queue busy. "));
   2237         return false;
   2238     }
   2239     aTrackPortInfo.iSendBOS = false;
   2240     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::SendBeginOfMediaStreamCommand() Out StreamId %d ", iStreamID));
   2241     return true;
   2242 }
   2243 
   2244 
   2245 // Metadata handling
   2246 
   2247 uint32 PVMFWAVFFParserNode::GetNumMetadataKeys(char* aQueryKeyString)
   2248 {
   2249     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::GetNumMetadataKeys() called"));
   2250 
   2251     uint32 num_entries = 0;
   2252 
   2253     if (aQueryKeyString == NULL)
   2254     {
   2255         // No query key so just return all the available keys
   2256         num_entries = iAvailableMetadataKeys.size();
   2257     }
   2258     else
   2259     {
   2260         // Determine the number of metadata keys based on the query key string provided
   2261         for (uint32 i = 0; i < iAvailableMetadataKeys.size(); i++)
   2262         {
   2263             // Check if the key matches the query key
   2264             if (pv_mime_strcmp(iAvailableMetadataKeys[i].get_cstr(), aQueryKeyString) >= 0)
   2265             {
   2266                 num_entries++;
   2267             }
   2268         }
   2269     }
   2270 
   2271     return num_entries;
   2272 }
   2273 
   2274 
   2275 uint32 PVMFWAVFFParserNode::GetNumMetadataValues(PVMFMetadataList& aKeyList)
   2276 {
   2277     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::GetNumMetadataValues() called"));
   2278 
   2279     uint32 numkeys = aKeyList.size();
   2280 
   2281     if (iWAVParser == NULL || numkeys == 0)
   2282     {
   2283         return 0;
   2284     }
   2285 
   2286     // Count the number of metadata value entries based on the key list provided
   2287     uint32 numvalentries = 0;
   2288     for (uint32 lcv = 0; lcv < numkeys; lcv++)
   2289     {
   2290         if (oscl_strcmp(aKeyList[lcv].get_cstr(), PVWAVMETADATA_DURATION_KEY) == 0 &&
   2291                 wavinfo.NumSamples > 0 && wavinfo.SampleRate > 0)
   2292         {
   2293             // Duration
   2294             ++numvalentries;
   2295         }
   2296         else if (oscl_strcmp(aKeyList[lcv].get_cstr(), PVWAVMETADATA_NUMTRACKS_KEY) == 0)
   2297         {
   2298             // Number of tracks
   2299             ++numvalentries;
   2300         }
   2301         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_BITRATE_KEY) == 0) &&
   2302                  wavinfo.BitsPerSample > 0 && wavinfo.SampleRate > 0)
   2303         {
   2304             // Bitrate
   2305             ++numvalentries;
   2306         }
   2307         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_AUDIO_CHANNELS_KEY) == 0) &&
   2308                  wavinfo.NumChannels > 0)
   2309         {
   2310             // Number of channels
   2311             ++numvalentries;
   2312         }
   2313         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_SAMPLERATE_KEY) == 0) &&
   2314                  wavinfo.SampleRate > 0)
   2315         {
   2316             // Sampling rate
   2317             ++numvalentries;
   2318         }
   2319         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_AUDIO_BITSPERSAMPLE_KEY) == 0) &&
   2320                  wavinfo.BitsPerSample > 0)
   2321         {
   2322             // Bits per sample
   2323             ++numvalentries;
   2324         }
   2325         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_AUDIO_FORMAT_KEY) == 0) &&
   2326                  wavinfo.AudioFormat != 0)
   2327         {
   2328             // Format
   2329             ++numvalentries;
   2330         }
   2331     }
   2332 
   2333     return numvalentries;
   2334 }
   2335 
   2336 
   2337 PVMFCommandId PVMFWAVFFParserNode::GetNodeMetadataKeys(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, uint32 starting_index, int32 max_entries, char* query_key, const OsclAny* aContext)
   2338 {
   2339     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::GetNodeMetadataKeys() called"));
   2340 
   2341     PVMFWAVFFNodeCommand cmd;
   2342     cmd.PVMFWAVFFNodeCommand::Construct(aSessionId, PVWAVFF_NODE_CMD_GETNODEMETADATAKEY, aKeyList, starting_index, max_entries, query_key, aContext);
   2343     return QueueCommandL(cmd);
   2344 }
   2345 
   2346 
   2347 PVMFCommandId PVMFWAVFFParserNode::GetNodeMetadataValues(PVMFSessionId aSessionId, PVMFMetadataList& aKeyList, Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList, uint32 starting_index, int32 max_entries, const OsclAny* aContext)
   2348 {
   2349     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::GetNodeMetadataValue() called"));
   2350 
   2351     PVMFWAVFFNodeCommand cmd;
   2352     cmd.PVMFWAVFFNodeCommand::Construct(aSessionId, PVWAVFF_NODE_CMD_GETNODEMETADATAVALUE, aKeyList, aValueList, starting_index, max_entries, aContext);
   2353     return QueueCommandL(cmd);
   2354 }
   2355 
   2356 // From PVMFMetadataExtensionInterface
   2357 PVMFStatus PVMFWAVFFParserNode::ReleaseNodeMetadataKeys(PVMFMetadataList& ,
   2358         uint32 ,
   2359         uint32)
   2360 {
   2361     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::ReleaseNodeMetadataKeys() called"));
   2362     //nothing needed-- there's no dynamic allocation in this node's key list
   2363     return PVMFSuccess;
   2364 }
   2365 
   2366 // From PVMFMetadataExtensionInterface
   2367 PVMFStatus PVMFWAVFFParserNode::ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList,
   2368         uint32 start,
   2369         uint32 end)
   2370 {
   2371     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::ReleaseNodeMetadataValues() called"));
   2372 
   2373     if (start > end || aValueList.size() == 0)
   2374     {
   2375         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFWAVFFParserNode::ReleaseNodeMetadataValues() Invalid start/end index"));
   2376         return PVMFErrArgument;
   2377     }
   2378 
   2379     if (end >= aValueList.size())
   2380     {
   2381         end = aValueList.size() - 1;
   2382     }
   2383 
   2384     for (uint32 i = start; i <= end; i++)
   2385     {
   2386         if (aValueList[i].key != NULL)
   2387         {
   2388             switch (GetValTypeFromKeyString(aValueList[i].key))
   2389             {
   2390                 case PVMI_KVPVALTYPE_WCHARPTR:
   2391                     if (aValueList[i].value.pWChar_value != NULL)
   2392                     {
   2393                         OSCL_ARRAY_DELETE(aValueList[i].value.pWChar_value);
   2394                         aValueList[i].value.pWChar_value = NULL;
   2395                     }
   2396                     break;
   2397 
   2398                 case PVMI_KVPVALTYPE_CHARPTR:
   2399                     if (aValueList[i].value.pChar_value != NULL)
   2400                     {
   2401                         OSCL_ARRAY_DELETE(aValueList[i].value.pChar_value);
   2402                         aValueList[i].value.pChar_value = NULL;
   2403                     }
   2404                     break;
   2405 
   2406                 case PVMI_KVPVALTYPE_UINT32:
   2407                 case PVMI_KVPVALTYPE_UINT8:
   2408                     // No memory to free for these valtypes
   2409                     break;
   2410 
   2411                 default:
   2412                     // Should not get a value that wasn't created from here
   2413                     break;
   2414             }
   2415 
   2416             OSCL_ARRAY_DELETE(aValueList[i].key);
   2417             aValueList[i].key = NULL;
   2418         }
   2419     }
   2420 
   2421     return PVMFSuccess;
   2422 }
   2423 
   2424 PVMFStatus PVMFWAVFFParserNode::DoGetNodeMetadataKey(PVMFWAVFFNodeCommand& aCmd)
   2425 {
   2426     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoGetNodeMetadataKey() In"));
   2427 
   2428     PVMFMetadataList* keylistptr = NULL;
   2429     uint32 starting_index;
   2430     int32 max_entries;
   2431     char* query_key;
   2432 
   2433     aCmd.PVMFWAVFFNodeCommand::Parse(keylistptr, starting_index, max_entries, query_key);
   2434 
   2435     // Check parameters
   2436     if (keylistptr == NULL)
   2437     {
   2438         // The list pointer is invalid
   2439         return PVMFErrArgument;
   2440     }
   2441 
   2442     if ((starting_index > (iAvailableMetadataKeys.size() - 1)) || max_entries == 0)
   2443     {
   2444         // Invalid starting index and/or max entries
   2445         return PVMFErrArgument;
   2446     }
   2447 
   2448     // Copy the requested keys
   2449     uint32 num_entries = 0;
   2450     int32 num_added = 0;
   2451 
   2452     for (uint32 lcv = 0; lcv < iAvailableMetadataKeys.size(); lcv++)
   2453     {
   2454         if (query_key == NULL)
   2455         {
   2456             // No query key so this key is counted
   2457             ++num_entries;
   2458             if (num_entries > starting_index)
   2459             {
   2460                 // Past the starting index so copy the key
   2461                 PVMFStatus status = PushBackMetadataKeys(keylistptr, lcv);
   2462                 if (PVMFErrNoMemory == status)
   2463                 {
   2464                     return status;
   2465                 }
   2466                 num_added++;
   2467             }
   2468         }
   2469         else
   2470         {
   2471             // Check if the key matche the query key
   2472             if (pv_mime_strcmp(iAvailableMetadataKeys[lcv].get_cstr(), query_key) >= 0)
   2473             {
   2474                 // This key is counted
   2475                 ++num_entries;
   2476                 if (num_entries > starting_index)
   2477                 {
   2478                     // Past the starting index so copy the key
   2479                     PVMFStatus status = PushBackMetadataKeys(keylistptr, lcv);
   2480                     if (PVMFErrNoMemory == status)
   2481                     {
   2482                         return status;
   2483                     }
   2484                     num_added++;
   2485                 }
   2486             }
   2487         }
   2488 
   2489         // Check if max number of entries have been copied
   2490         if (max_entries > 0 && num_added >= max_entries)
   2491         {
   2492             break;
   2493         }
   2494     }
   2495     return PVMFSuccess;
   2496 }
   2497 
   2498 
   2499 
   2500 PVMFStatus PVMFWAVFFParserNode::DoGetNodeMetadataValue(PVMFWAVFFNodeCommand& aCmd)
   2501 {
   2502     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::DoGetMetadataValue() In"));
   2503 
   2504     if (iWAVParser == NULL)
   2505     {
   2506         return PVMFErrInvalidState;
   2507     }
   2508 
   2509     PVMFMetadataList* keylistptr_in = NULL;
   2510     PVMFMetadataList* keylistptr = NULL;
   2511     Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL;
   2512     uint32 starting_index;
   2513     int32 max_entries;
   2514 
   2515     aCmd.PVMFWAVFFNodeCommand::Parse(keylistptr_in, valuelistptr, starting_index, max_entries);
   2516 
   2517     // Check the parameters
   2518     if (keylistptr_in == NULL || valuelistptr == NULL)
   2519     {
   2520         return PVMFErrArgument;
   2521     }
   2522 
   2523     keylistptr = keylistptr_in;
   2524     //If numkeys is one, just check to see if the request
   2525     //is for ALL metadata
   2526     if (keylistptr_in->size() == 1)
   2527     {
   2528         if (oscl_strncmp((*keylistptr)[0].get_cstr(),
   2529                          PVWAVMETADATA_ALL_METADATA_KEY,
   2530                          oscl_strlen(PVWAVMETADATA_ALL_METADATA_KEY)) == 0)
   2531         {
   2532             //use the complete metadata key list
   2533             keylistptr = &iAvailableMetadataKeys;
   2534         }
   2535     }
   2536     uint32 numkeys = keylistptr->size();
   2537 
   2538     if (starting_index > (numkeys - 1) || numkeys <= 0 || max_entries == 0)
   2539     {
   2540         // Don't do anything
   2541         return PVMFErrArgument;
   2542     }
   2543 
   2544     uint32 numvalentries = 0;
   2545     int32 numentriesadded = 0;
   2546     for (uint32 lcv = 0; lcv < numkeys; lcv++)
   2547     {
   2548         int32 leavecode = 0;
   2549         PvmiKvp KeyVal;
   2550         KeyVal.key = NULL;
   2551         uint32 KeyLen = 0;
   2552 
   2553         if (oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVWAVMETADATA_DURATION_KEY) == 0 &&
   2554                 wavinfo.NumSamples > 0 && wavinfo.SampleRate > 0)
   2555         {
   2556             // Duration
   2557             // Increment the counter for the number of values found so far
   2558             ++numvalentries;
   2559 
   2560             // Create a value entry if past the starting index
   2561             if (numvalentries > starting_index)
   2562             {
   2563                 KeyLen = oscl_strlen(PVWAVMETADATA_DURATION_KEY) + 1; // for "duration;"
   2564                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
   2565                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32;"
   2566                 KeyLen += oscl_strlen(PVWAVMETADATA_TIMESCALE1000) + 1; // for "timescale=1000" and NULL terminator
   2567 
   2568                 // Allocate memory for the string
   2569                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
   2570                 if (leavecode == 0)
   2571                 {
   2572                     // Copy the key string
   2573                     oscl_strncpy(KeyVal.key, PVWAVMETADATA_DURATION_KEY, oscl_strlen(PVWAVMETADATA_DURATION_KEY) + 1);
   2574                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2575                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
   2576                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
   2577                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2578                     oscl_strncat(KeyVal.key, PVWAVMETADATA_TIMESCALE1000, oscl_strlen(PVWAVMETADATA_TIMESCALE1000));
   2579                     KeyVal.key[KeyLen-1] = 0;
   2580                     // Copy the value- use uint64 in case of large sample count
   2581                     {
   2582                         uint32 duration_sec = wavinfo.NumSamples / wavinfo.SampleRate;
   2583                         uint32 duration_msec = wavinfo.NumSamples % wavinfo.SampleRate;
   2584                         uint32 duration = (duration_msec * 1000) / wavinfo.SampleRate + duration_sec * 1000 ;
   2585                         KeyVal.value.uint32_value = duration;
   2586                     }
   2587                     // Set the length and capacity
   2588                     KeyVal.length = 1;
   2589                     KeyVal.capacity = 1;
   2590                 }
   2591                 else
   2592                 {
   2593                     // Memory allocation failed
   2594                     KeyVal.key = NULL;
   2595                     break;
   2596                 }
   2597             }
   2598         }
   2599         else if (oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVWAVMETADATA_NUMTRACKS_KEY) == 0)
   2600         {
   2601             // Number of tracks
   2602             // Increment the counter for the number of values found so far
   2603             ++numvalentries;
   2604 
   2605             // Create a value entry if past the starting index
   2606             if (numvalentries > starting_index)
   2607             {
   2608                 KeyLen = oscl_strlen(PVWAVMETADATA_NUMTRACKS_KEY) + 1; // for "num-tracks;"
   2609                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
   2610                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
   2611 
   2612                 // Allocate memory for the string
   2613                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
   2614                 if (leavecode == 0)
   2615                 {
   2616                     // Copy the key string
   2617                     oscl_strncpy(KeyVal.key, PVWAVMETADATA_NUMTRACKS_KEY, oscl_strlen(PVWAVMETADATA_NUMTRACKS_KEY) + 1);
   2618                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2619                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
   2620                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
   2621                     KeyVal.key[KeyLen-1] = 0;
   2622                     // Copy the value
   2623                     KeyVal.value.uint32_value = 1;  // Currently only one track WAV files are supported
   2624                     // Set the length and capacity
   2625                     KeyVal.length = 1;
   2626                     KeyVal.capacity = 1;
   2627                 }
   2628                 else
   2629                 {
   2630                     // Memory allocation failed
   2631                     KeyVal.key = NULL;
   2632                     break;
   2633                 }
   2634             }
   2635         }
   2636         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_BITRATE_KEY) == 0) &&
   2637                  wavinfo.BitsPerSample > 0 && wavinfo.SampleRate > 0)
   2638         {
   2639             // Bitrate
   2640             // Increment the counter for the number of values found so far
   2641             ++numvalentries;
   2642 
   2643             // Create a value entry if past the starting index
   2644             if (numvalentries > starting_index)
   2645             {
   2646                 KeyLen = oscl_strlen(PVWAVMETADATA_TRACKINFO_BITRATE_KEY) + 1; // for "track-info/bit-rate;"
   2647                 KeyLen += oscl_strlen(PVWAVMETADATA_INDEX0) + 1; // for "index=0;"
   2648                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
   2649                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
   2650 
   2651                 // Allocate memory for the string
   2652                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
   2653 
   2654                 if (leavecode == 0)
   2655                 {
   2656                     // Copy the key string
   2657                     oscl_strncpy(KeyVal.key, PVWAVMETADATA_TRACKINFO_BITRATE_KEY, oscl_strlen(PVWAVMETADATA_TRACKINFO_BITRATE_KEY) + 1);
   2658                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2659                     oscl_strncat(KeyVal.key, PVWAVMETADATA_INDEX0, oscl_strlen(PVWAVMETADATA_INDEX0));
   2660                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2661                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
   2662                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
   2663                     KeyVal.key[KeyLen-1] = 0;
   2664                     // Copy the value
   2665                     KeyVal.value.uint32_value = wavinfo.BitsPerSample * wavinfo.SampleRate; // Convert to bitrate in bits per sec
   2666                     // Set the length and capacity
   2667                     KeyVal.length = 1;
   2668                     KeyVal.capacity = 1;
   2669                 }
   2670                 else
   2671                 {
   2672                     // Memory allocation failed
   2673                     KeyVal.key = NULL;
   2674                     break;
   2675                 }
   2676             }
   2677         }
   2678         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_AUDIO_CHANNELS_KEY) == 0) &&
   2679                  wavinfo.NumChannels > 0)
   2680         {
   2681             // Number of channels
   2682             // Increment the counter for the number of values found so far
   2683             ++numvalentries;
   2684 
   2685             // Create a value entry if past the starting index
   2686             if (numvalentries > starting_index)
   2687             {
   2688                 KeyLen = oscl_strlen(PVWAVMETADATA_TRACKINFO_AUDIO_CHANNELS_KEY) + 1; // for "track-info/audio/channels;"
   2689                 KeyLen += oscl_strlen(PVWAVMETADATA_INDEX0) + 1; // for "index=0;"
   2690                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
   2691                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
   2692 
   2693                 // Allocate memory for the string
   2694                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
   2695                 if (leavecode == 0)
   2696                 {
   2697                     // Copy the key string
   2698                     oscl_strncpy(KeyVal.key, PVWAVMETADATA_TRACKINFO_AUDIO_CHANNELS_KEY, oscl_strlen(PVWAVMETADATA_TRACKINFO_AUDIO_CHANNELS_KEY) + 1);
   2699                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2700                     oscl_strncat(KeyVal.key, PVWAVMETADATA_INDEX0, oscl_strlen(PVWAVMETADATA_INDEX0));
   2701                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2702                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
   2703                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
   2704                     KeyVal.key[KeyLen-1] = 0;
   2705                     // Copy the value
   2706                     KeyVal.value.uint32_value = wavinfo.NumChannels;
   2707                     // Set the length and capacity
   2708                     KeyVal.length = 1;
   2709                     KeyVal.capacity = 1;
   2710                 }
   2711                 else
   2712                 {
   2713                     // Memory allocation failed
   2714                     KeyVal.key = NULL;
   2715                     break;
   2716                 }
   2717             }
   2718         }
   2719         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_SAMPLERATE_KEY) == 0) &&
   2720                  wavinfo.SampleRate > 0)
   2721         {
   2722             // Sampling rate
   2723             // Increment the counter for the number of values found so far
   2724             ++numvalentries;
   2725 
   2726             // Create a value entry if past the starting index
   2727             if (numvalentries > starting_index)
   2728             {
   2729                 KeyLen = oscl_strlen(PVWAVMETADATA_TRACKINFO_SAMPLERATE_KEY) + 1; // for "track-info/sample-rate;"
   2730                 KeyLen += oscl_strlen(PVWAVMETADATA_INDEX0) + 1; // for "index=0;"
   2731                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
   2732                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
   2733 
   2734                 // Allocate memory for the string
   2735                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
   2736                 if (leavecode == 0)
   2737                 {
   2738                     // Copy the key string
   2739                     oscl_strncpy(KeyVal.key, PVWAVMETADATA_TRACKINFO_SAMPLERATE_KEY, oscl_strlen(PVWAVMETADATA_TRACKINFO_SAMPLERATE_KEY) + 1);
   2740                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2741                     oscl_strncat(KeyVal.key, PVWAVMETADATA_INDEX0, oscl_strlen(PVWAVMETADATA_INDEX0));
   2742                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2743                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
   2744                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
   2745                     KeyVal.key[KeyLen-1] = 0;
   2746                     // Copy the value
   2747                     KeyVal.value.uint32_value = wavinfo.SampleRate;
   2748                     // Set the length and capacity
   2749                     KeyVal.length = 1;
   2750                     KeyVal.capacity = 1;
   2751                 }
   2752                 else
   2753                 {
   2754                     // Memory allocation failed
   2755                     KeyVal.key = NULL;
   2756                     break;
   2757                 }
   2758             }
   2759         }
   2760         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_AUDIO_BITSPERSAMPLE_KEY) == 0) &&
   2761                  wavinfo.BitsPerSample > 0)
   2762         {
   2763             // Bits per sample
   2764             // Increment the counter for the number of values found so far
   2765             ++numvalentries;
   2766 
   2767             // Create a value entry if past the starting index
   2768             if (numvalentries > starting_index)
   2769             {
   2770                 KeyLen = oscl_strlen(PVWAVMETADATA_TRACKINFO_AUDIO_BITSPERSAMPLE_KEY) + 1; // for "track-info/audio/bits-per-sample;"
   2771                 KeyLen += oscl_strlen(PVWAVMETADATA_INDEX0) + 1; // for "index=0;"
   2772                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
   2773                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
   2774 
   2775                 // Allocate memory for the string
   2776                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
   2777 
   2778                 if (leavecode == 0)
   2779                 {
   2780                     // Copy the key string
   2781                     oscl_strncpy(KeyVal.key, PVWAVMETADATA_TRACKINFO_AUDIO_BITSPERSAMPLE_KEY, oscl_strlen(PVWAVMETADATA_TRACKINFO_AUDIO_BITSPERSAMPLE_KEY) + 1);
   2782                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2783                     oscl_strncat(KeyVal.key, PVWAVMETADATA_INDEX0, oscl_strlen(PVWAVMETADATA_INDEX0));
   2784                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2785                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
   2786                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
   2787                     KeyVal.key[KeyLen-1] = 0;
   2788                     // Copy the value
   2789                     KeyVal.value.uint32_value = wavinfo.BitsPerSample;
   2790                     // Set the length and capacity
   2791                     KeyVal.length = 1;
   2792                     KeyVal.capacity = 1;
   2793                 }
   2794                 else
   2795                 {
   2796                     // Memory allocation failed
   2797                     KeyVal.key = NULL;
   2798                     break;
   2799                 }
   2800             }
   2801         }
   2802         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVWAVMETADATA_TRACKINFO_AUDIO_FORMAT_KEY) == 0) &&
   2803                  wavinfo.AudioFormat != 0)
   2804         {
   2805             // Format
   2806             // Increment the counter for the number of values found so far
   2807             ++numvalentries;
   2808 
   2809             // Create a value entry if past the starting index
   2810             if (numvalentries > starting_index)
   2811             {
   2812                 KeyLen = oscl_strlen(PVWAVMETADATA_TRACKINFO_AUDIO_FORMAT_KEY) + 1; // for "track-info/audio/format;"
   2813                 KeyLen += oscl_strlen(PVWAVMETADATA_INDEX0) + 1; // for "index=0;"
   2814                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
   2815                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR) + 1; // for "char*" and NULL terminator
   2816 
   2817                 uint32 valuelen = 0;
   2818                 switch (wavinfo.AudioFormat)
   2819                 {
   2820                     case PVWAV_PCM_AUDIO_FORMAT:
   2821                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_PCM)) + 1; // Value string plus one for NULL terminator
   2822                         break;
   2823 
   2824                     case PVWAV_ITU_G711_ALAW:
   2825                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_ALAW)) + 1; // Value string plus one for NULL terminator
   2826                         break;
   2827 
   2828                     case PVWAV_ITU_G711_ULAW:
   2829                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_ULAW)) + 1; // Value string plus one for NULL terminator
   2830                         break;
   2831 
   2832                     default:
   2833                         // Should not enter here
   2834                         OSCL_ASSERT(false);
   2835                         valuelen = 1;
   2836                         break;
   2837                 }
   2838 
   2839                 // Allocate memory for the strings
   2840                 leavecode = CreateNewArray(KeyVal.key, KeyLen);
   2841                 if (0 == leavecode)
   2842                 {
   2843                     leavecode = CreateNewArray(KeyVal.value.pChar_value, valuelen);
   2844                 }
   2845 
   2846                 if (leavecode == 0)
   2847                 {
   2848                     // Copy the key string
   2849                     oscl_strncpy(KeyVal.key, PVWAVMETADATA_TRACKINFO_AUDIO_FORMAT_KEY, oscl_strlen(PVWAVMETADATA_TRACKINFO_AUDIO_FORMAT_KEY) + 1);
   2850                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2851                     oscl_strncat(KeyVal.key, PVWAVMETADATA_INDEX0, oscl_strlen(PVWAVMETADATA_INDEX0));
   2852                     oscl_strncat(KeyVal.key, PVWAVMETADATA_SEMICOLON, oscl_strlen(PVWAVMETADATA_SEMICOLON));
   2853                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
   2854                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR));
   2855                     KeyVal.key[KeyLen-1] = 0;
   2856                     // Copy the value
   2857                     switch (wavinfo.AudioFormat)
   2858                     {
   2859                         case PVWAV_PCM_AUDIO_FORMAT:
   2860                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_PCM), valuelen);
   2861                             break;
   2862 
   2863                         case PVWAV_ITU_G711_ALAW:
   2864                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_ALAW), valuelen);
   2865                             break;
   2866 
   2867                         case PVWAV_ITU_G711_ULAW:
   2868                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_ULAW), valuelen);
   2869                             break;
   2870 
   2871                         default:
   2872                             // Should not enter here
   2873                             OSCL_ASSERT(false);
   2874                             break;
   2875                     }
   2876                     KeyVal.value.pChar_value[valuelen-1] = 0;
   2877                     // Set the length and capacity
   2878                     KeyVal.length = valuelen;
   2879                     KeyVal.capacity = valuelen;
   2880                 }
   2881                 else
   2882                 {
   2883                     // Memory allocation failed so clean up
   2884                     if (KeyVal.key)
   2885                     {
   2886                         OSCL_ARRAY_DELETE(KeyVal.key);
   2887                         KeyVal.key = NULL;
   2888                     }
   2889                     if (KeyVal.value.pChar_value)
   2890                     {
   2891                         OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
   2892                     }
   2893                     break;
   2894                 }
   2895             }
   2896         }
   2897 
   2898         if (KeyVal.key != NULL)
   2899         {
   2900             leavecode = PushBackKeyVal(valuelistptr, KeyVal);
   2901             if (leavecode != 0)
   2902             {
   2903                 switch (GetValTypeFromKeyString(KeyVal.key))
   2904                 {
   2905                     case PVMI_KVPVALTYPE_CHARPTR:
   2906                         if (KeyVal.value.pChar_value != NULL)
   2907                         {
   2908                             OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
   2909                             KeyVal.value.pChar_value = NULL;
   2910                         }
   2911                         break;
   2912 
   2913                     default:
   2914                         // Add more case statements if other value types are returned
   2915                         break;
   2916                 }
   2917 
   2918                 OSCL_ARRAY_DELETE(KeyVal.key);
   2919                 KeyVal.key = NULL;
   2920             }
   2921             else
   2922             {
   2923                 // Increment the counter for number of value entries added to the list
   2924                 ++numentriesadded;
   2925             }
   2926 
   2927             // Check if the max number of value entries were added
   2928             if (max_entries > 0 && numentriesadded >= max_entries)
   2929             {
   2930                 // Maximum number of values added so break out of the loop
   2931                 break;
   2932             }
   2933         }
   2934     }
   2935 
   2936     return PVMFSuccess;
   2937 }
   2938 
   2939 
   2940 PVMFStatus  PVMFWAVFFParserNode::NegotiateSettings(PvmiCapabilityAndConfig* configInterface)
   2941 {
   2942     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFWAVFFParserNode::NegotiateSettings() In"));
   2943 
   2944     if (!iWAVParser)
   2945     {
   2946         // settings aren't initialized so defer this for now
   2947         return PVMFSuccess;
   2948     }
   2949 
   2950 
   2951     // setting the format, sample rate, and number of channels
   2952     PvmiKvp kvp;
   2953     PvmiKvp* retKvp = NULL; // for return value
   2954 
   2955 #define WAVFF_MAX_PARAM_KEYLEN 128
   2956 
   2957     char buf[WAVFF_MAX_PARAM_KEYLEN];
   2958     oscl_strncpy(buf, MOUT_AUDIO_FORMAT_KEY, WAVFF_MAX_PARAM_KEYLEN);
   2959     buf[WAVFF_MAX_PARAM_KEYLEN-1] = 0;
   2960 
   2961     // set the format
   2962     kvp.key = buf;
   2963 
   2964 #define WAVFF_MAX_PARAM_VALLEN 128
   2965     char valbuf[WAVFF_MAX_PARAM_VALLEN];
   2966     const char* valptr;
   2967 
   2968     if (wavinfo.AudioFormat == PVWAV_PCM_AUDIO_FORMAT)
   2969     {
   2970         if (wavinfo.BitsPerSample == 8)
   2971         {
   2972             valptr = PVMF_MIME_PCM8;
   2973         }
   2974         else if (wavinfo.isLittleEndian)
   2975         {
   2976             valptr = PVMF_MIME_PCM16;
   2977         }
   2978         else
   2979         {
   2980             valptr = PVMF_MIME_PCM16_BE;
   2981         }
   2982     }
   2983     else if (wavinfo.AudioFormat == PVWAV_ITU_G711_ALAW)
   2984     {
   2985         valptr = PVMF_MIME_ALAW;
   2986     }
   2987     else if (wavinfo.AudioFormat == PVWAV_ITU_G711_ULAW)
   2988     {
   2989         valptr = PVMF_MIME_ULAW;
   2990     }
   2991     else
   2992     {
   2993         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFWAVFFParserNode::NegotiateSettings() - unknown/unsupported format %d", wavinfo.AudioFormat));
   2994         return PVMFFailure;
   2995     }
   2996 
   2997     oscl_strncpy(valbuf, valptr, WAVFF_MAX_PARAM_VALLEN);
   2998     valbuf[WAVFF_MAX_PARAM_VALLEN-1] = 0;
   2999 
   3000     kvp.length = kvp.capacity = oscl_strlen(valbuf);
   3001 
   3002     kvp.value.pChar_value = valbuf;
   3003 
   3004     int32 err = 0;
   3005     retKvp = NULL;
   3006     OSCL_TRY(err, configInterface->setParametersSync(0, &kvp, 1, retKvp););
   3007 
   3008     if (err != OsclErrNone || retKvp)
   3009     {
   3010         return PVMFFailure;
   3011     }
   3012 
   3013     kvp.length = kvp.capacity = 0;
   3014 
   3015     // set the sample rate
   3016     kvp.value.uint32_value = wavinfo.SampleRate;
   3017 
   3018     oscl_strncpy(buf, MOUT_AUDIO_SAMPLING_RATE_KEY, WAVFF_MAX_PARAM_KEYLEN);
   3019     buf[WAVFF_MAX_PARAM_KEYLEN-1] = 0;
   3020 
   3021     kvp.key = buf;
   3022 
   3023     err = 0;
   3024     retKvp = NULL;
   3025     OSCL_TRY(err, configInterface->setParametersSync(0, &kvp, 1, retKvp););
   3026 
   3027     if (err != OsclErrNone || retKvp)
   3028     {
   3029         return PVMFFailure;
   3030     }
   3031 
   3032     // set the number of channels
   3033 
   3034     kvp.value.uint32_value = wavinfo.NumChannels;
   3035 
   3036     oscl_strncpy(buf, MOUT_AUDIO_NUM_CHANNELS_KEY, WAVFF_MAX_PARAM_KEYLEN);
   3037     buf[WAVFF_MAX_PARAM_KEYLEN-1] = 0;
   3038 
   3039     kvp.key = buf;
   3040 
   3041     err = 0;
   3042     retKvp = NULL;
   3043     OSCL_TRY(err, configInterface->setParametersSync(0, &kvp, 1, retKvp););
   3044 
   3045     if (err != OsclErrNone || retKvp)
   3046     {
   3047         return PVMFFailure;
   3048     }
   3049 
   3050     return PVMFSuccess;
   3051 }
   3052 
   3053 
   3054 int32 PVMFWAVFFParserNode::PushBackPortActivity(PVMFPortActivity &aActivity)
   3055 {
   3056     int32 err = OsclErrNone;
   3057     OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
   3058     return err;
   3059 }
   3060 
   3061 int32 PVMFWAVFFParserNode::CreateNewArray(char*& aPtr, int32 aLen)
   3062 {
   3063     int32 leavecode = 0;
   3064     OSCL_TRY(leavecode,
   3065              aPtr = OSCL_ARRAY_NEW(char, aLen););
   3066     return leavecode;
   3067 }
   3068 
   3069 int32 PVMFWAVFFParserNode::PushBackKeyVal(Oscl_Vector<PvmiKvp, OsclMemAllocator>*& aValueListPtr, PvmiKvp &aKeyVal)
   3070 {
   3071     int32 leavecode = 0;
   3072     OSCL_TRY(leavecode, (*aValueListPtr).push_back(aKeyVal));
   3073     return leavecode;
   3074 }
   3075 
   3076 PVMFStatus PVMFWAVFFParserNode::PushBackMetadataKeys(PVMFMetadataList *&aKeyListPtr, uint32 aLcv)
   3077 {
   3078     int32 leavecode = 0;
   3079     OSCL_TRY(leavecode, aKeyListPtr->push_back(iAvailableMetadataKeys[aLcv]));
   3080     OSCL_FIRST_CATCH_ANY(leavecode, PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFRMFFParserNode::DoGetMetadataKeys() Memory allocation failure when copying metadata key")); return PVMFErrNoMemory);
   3081 
   3082     return PVMFSuccess;
   3083 }
   3084 
   3085