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