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_mp4ffparser_node.h" 19 20 #include "pvmf_mp4ffparser_node_tuneables.h" 21 22 #include "pvmf_mp4ffparser_outport.h" 23 24 #include "impeg4file.h" 25 26 #include "media_clock_converter.h" 27 28 #include "pvlogger.h" 29 30 #include "oscl_error_codes.h" 31 32 #include "oscl_tickcount.h" 33 34 #include "oscl_base.h" 35 36 #include "pv_mime_string_utils.h" 37 38 #include "oscl_snprintf.h" 39 40 #include "pvmf_timestamp.h" 41 42 #include "pvmf_fileformat_events.h" 43 44 #include "pvmf_mp4ffparser_events.h" 45 46 #include "pvmf_errorinfomessage_extension.h" 47 48 #include "pvmf_download_progress_interface.h" 49 50 #include "pvmf_duration_infomessage.h" 51 52 #include "pvmf_durationinfomessage_extension.h" 53 54 #include "oscl_int64_utils.h" 55 56 #include "pvmf_media_cmd.h" 57 58 #include "pvmf_media_msg_format_ids.h" 59 60 #include "pvmf_local_data_source.h" 61 62 #include "pvmi_kvp_util.h" 63 64 #include "oscl_string_containers.h" 65 66 #include "oscl_string_utils.h" 67 68 #include "h263decoderspecificinfo.h" 69 70 #include "oscl_bin_stream.h" 71 72 #include "m4v_config_parser.h" 73 74 #include "getactualaacconfig.h" 75 76 #include "oscl_exclusive_ptr.h" 77 78 #define PVMF_MP4_MIME_FORMAT_AUDIO_UNKNOWN "x-pvmf/audio/unknown" 79 #define PVMF_MP4_MIME_FORMAT_VIDEO_UNKNOWN "x-pvmf/video/unknown" 80 #define PVMF_MP4_MIME_FORMAT_UNKNOWN "x-pvmf/unknown-media/unknown" 81 82 // Read Each Track Individually 83 #define TRACK_NO_PER_RESET_PLAYBACK_CALL 1 84 #define MAX_TRACK_NO 256 85 86 #define DEFAULTPROFILE 0 87 #define DEFAULTLEVEL 0 88 89 #define MILLISECOND_TIMESCALE 1000 90 91 PVMFMP4FFParserNode::PVMFMP4FFParserNode(int32 aPriority) : 92 OsclTimerObject(aPriority, "PVMFMP4FFParserNode"), 93 iMP4FileHandle(NULL), 94 iPortIter(NULL), 95 iLogger(NULL), 96 iBackwardReposFlag(false), /* To avoid backwardlooping :: A flag to remember backward repositioning */ 97 iForwardReposFlag(false), 98 iPlayBackDirection(PVMF_DATA_SOURCE_DIRECTION_FORWARD), 99 iParseAudioDuringFF(false), 100 iParseAudioDuringREW(false), 101 iParseVideoOnly(false), 102 iDataRate(NORMAL_PLAYRATE), 103 minFileOffsetTrackID(0) 104 { 105 iClientPlayBackClock = NULL; 106 iClockNotificationsInf = NULL; 107 autopaused = false; 108 iDownloadFileSize = 0; 109 download_progress_interface = NULL; 110 iExtensionRefCount = 0; 111 iThumbNailMode = false; 112 iPreviewMode = false; 113 iSourceContextDataValid = false; 114 iProtectedFile = false; 115 iCPM = NULL; 116 iCPMSessionID = 0xFFFFFFFF; 117 iCPMContentType = PVMF_CPM_CONTENT_FORMAT_UNKNOWN; 118 iCPMContentAccessFactory = NULL; 119 iDecryptionInterface = NULL; 120 iOMA2DecryptionBuffer = NULL; 121 iCPMInitCmdId = 0; 122 iCPMOpenSessionCmdId = 0; 123 iCPMRegisterContentCmdId = 0; 124 iCPMRequestUsageId = 0; 125 iCPMUsageCompleteCmdId = 0; 126 iCPMCloseSessionCmdId = 0; 127 iCPMSequenceInProgress = false; 128 iCPMResetCmdId = 0; 129 iRequestedUsage.key = NULL; 130 iApprovedUsage.key = NULL; 131 iAuthorizationDataKvp.key = NULL; 132 oWaitingOnLicense = false; 133 iPoorlyInterleavedContentEventSent = false; 134 135 136 iInterfaceState = EPVMFNodeCreated; 137 iParsingMode = PVMF_MP4FF_PARSER_NODE_ENABLE_PARSER_OPTIMIZATION; 138 oIsAACFramesFragmented = PVMFMP4FF_BREAKUP_AAC_FRAMES_INTO_MULTIPLE_MEDIA_FRAGS; 139 140 iUseCPMPluginRegistry = false; 141 iFileHandle = NULL; 142 143 iMP4HeaderSize = 0; 144 iDataStreamInterface = NULL; 145 iDataStreamFactory = NULL; 146 iDataStreamReadCapacityObserver = NULL; 147 iDownloadComplete = false; 148 iProgressivelyDownlodable = false; 149 iFastTrackSession = false; 150 151 iLastNPTCalcInConvertSizeToTime = 0; 152 iFileSizeLastConvertedToTime = 0; 153 154 iExternalDownload = false; 155 iUnderFlowEventReported = false; 156 iUnderFlowCheckTimer = NULL; 157 158 iCPMMetaDataExtensionInterface = NULL; 159 iCPMLicenseInterface = NULL; 160 iCPMLicenseInterfacePVI = NULL; 161 iCPMGetMetaDataKeysCmdId = 0; 162 iCPMGetMetaDataValuesCmdId = 0; 163 iMP4ParserNodeMetadataValueCount = 0; 164 iCPMGetLicenseInterfaceCmdId = 0; 165 iCPMGetLicenseCmdId = 0; 166 iCPMCancelGetLicenseCmdId = 0; 167 168 minTime = 0; 169 avgTime = 0; 170 maxTime = 0; 171 sumTime = 0; 172 iDiagnosticsLogged = false; 173 iPortDataLog = false; 174 iTimeTakenInReadMP4File = 0; 175 iCurPos = 0; 176 iDelayAddToNextTextSample = 0; 177 iTextInvalidTSAfterReposition = false; 178 iEOTForTextSentToMIO = false; 179 iSetTextSampleDurationZero = false; 180 181 iCacheSize = DEFAULT_CAHCE_SIZE; 182 iAsyncReadBuffSize = DEFAULT_ASYNC_READ_BUFFER_SIZE; 183 iPVLoggerEnableFlag = false; 184 iPVLoggerStateEnableFlag = false; 185 iNativeAccessMode = DEFAULT_NATIVE_ACCESS_MODE; 186 187 iStreamID = 0; 188 189 iDataStreamRequestPending = false; 190 191 iJitterBufferDurationInMs = PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS; 192 iBaseKey = INVALID; 193 iJitterBufferDurationInMs = PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS; 194 iBaseKey = INVALID; 195 196 int32 err; 197 OSCL_TRY(err, 198 //Create the input command queue. Use a reserve to avoid lots of 199 //dynamic memory allocation. 200 iInputCommands.Construct(1000/*Starting command ID*/, 10/*Number slots to reserve in queue*/); 201 202 //Create the "current command" queue. It will only contain one 203 //command at a time, so use a reserve of 1. 204 iCurrentCommand.Construct(0, 1); 205 iCancelCommand.Construct(0, 1); 206 207 //Set the node capability data. 208 iCapability.iCanSupportMultipleInputPorts = false; 209 iCapability.iCanSupportMultipleOutputPorts = true; 210 iCapability.iHasMaxNumberOfPorts = true; 211 iCapability.iMaxNumberOfPorts = 6; 212 iCapability.iInputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_MPEG4FF)); 213 iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_AMR_IETF)); 214 iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_AMRWB_IETF)); 215 iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_MPEG4_AUDIO)); 216 iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_M4V)); 217 iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_H2631998)); 218 iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_H2632000)); 219 iCapability.iOutputFormatCapability.push_back(PVMFFormatType(PVMF_MIME_H264_VIDEO_MP4)); 220 221 iAvailableMetadataKeys.clear(); 222 223 iUnderFlowCheckTimer = OSCL_NEW(OsclTimer<OsclMemAllocator>, 224 ("PVMFMP4FFNodeUnderFlowTimer")); 225 226 iUnderFlowCheckTimer->SetObserver(this); 227 iUnderFlowCheckTimer->SetFrequency(PVMP4FF_UNDERFLOW_STATUS_EVENT_FREQUENCY); 228 ); 229 230 iPortIter = OSCL_NEW(PVMFMP4FFPortIter, (iNodeTrackPortList)); 231 if (iPortIter == NULL) 232 { 233 err = OsclErrNoMemory; 234 } 235 236 if (err != OsclErrNone) 237 { 238 //if a leave happened, cleanup and re-throw the error 239 iInputCommands.clear(); 240 iCurrentCommand.clear(); 241 iCancelCommand.clear(); 242 iCapability.iInputFormatCapability.clear(); 243 iCapability.iOutputFormatCapability.clear(); 244 OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface); 245 OSCL_CLEANUP_BASE_CLASS(OsclTimerObject); 246 OSCL_LEAVE(err); 247 } 248 } 249 250 251 PVMFMP4FFParserNode::~PVMFMP4FFParserNode() 252 { 253 //remove the clock observer 254 if (iClientPlayBackClock != NULL) 255 { 256 if (iClockNotificationsInf != NULL) 257 { 258 iClockNotificationsInf->RemoveClockStateObserver(*this); 259 iClientPlayBackClock->DestroyMediaClockNotificationsInterface(iClockNotificationsInf); 260 iClockNotificationsInf = NULL; 261 } 262 } 263 264 LogDiagnostics(); 265 Cancel(); 266 if (IsAdded()) 267 { 268 RemoveFromScheduler(); 269 } 270 271 if (iUnderFlowCheckTimer != NULL) 272 { 273 iUnderFlowCheckTimer->Clear(); 274 } 275 OSCL_DELETE(iUnderFlowCheckTimer); 276 277 // release the download progress interface if any 278 if (download_progress_interface != NULL) 279 { 280 download_progress_interface->cancelResumeNotification(); 281 download_progress_clock.Unbind(); 282 download_progress_interface->removeRef(); 283 download_progress_interface = NULL; 284 } 285 286 iPortActivityQueue.clear(); 287 ReleaseAllPorts(); 288 RemoveAllCommands(); 289 290 OSCL_DELETE(iPortIter); 291 iPortIter = NULL; 292 293 CleanupFileSource(); 294 iFileServer.Close(); 295 296 if (iRequestedUsage.key) 297 { 298 OSCL_ARRAY_DELETE(iRequestedUsage.key); 299 iRequestedUsage.key = NULL; 300 } 301 302 if (iApprovedUsage.key) 303 { 304 OSCL_ARRAY_DELETE(iApprovedUsage.key); 305 iApprovedUsage.key = NULL; 306 } 307 308 if (iAuthorizationDataKvp.key) 309 { 310 OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key); 311 iAuthorizationDataKvp.key = NULL; 312 } 313 314 if (iCPM != NULL) 315 { 316 iCPM->ThreadLogoff(); 317 PVMFCPMFactory::DestroyContentPolicyManager(iCPM); 318 iCPM = NULL; 319 } 320 321 if (iExtensionRefCount > 0) 322 { 323 OSCL_ASSERT(false); 324 } 325 326 //The command queues are self-deleting, but we want to 327 //notify the observer of unprocessed commands. 328 while (!iCurrentCommand.empty()) 329 { 330 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure, NULL, NULL); 331 } 332 while (!iCancelCommand.empty()) 333 { 334 CommandComplete(iCancelCommand, iCancelCommand.front(), PVMFFailure, NULL, NULL); 335 } 336 while (!iInputCommands.empty()) 337 { 338 CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure, NULL, NULL); 339 } 340 } 341 342 343 PVMFStatus PVMFMP4FFParserNode::ThreadLogon() 344 { 345 if (iInterfaceState == EPVMFNodeCreated) 346 { 347 if (!IsAdded()) 348 { 349 AddToScheduler(); 350 } 351 iLogger = PVLogger::GetLoggerObject("PVMFMP4FFParserNode"); 352 iDataPathLogger = PVLogger::GetLoggerObject("datapath.sourcenode.mp4parsernode"); 353 iAVCDataPathLogger = PVLogger::GetLoggerObject("datapath.sourcenode.mp4parsernode.avc"); 354 if (iAVCDataPathLogger != NULL) 355 { 356 iAVCDataPathLogger->DisableAppenderInheritance(); 357 } 358 iClockLogger = PVLogger::GetLoggerObject("clock"); 359 iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.mp4parsernode"); 360 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ThreadLogon() called")); 361 362 iFileServer.Connect(); 363 ChangeNodeState(EPVMFNodeIdle); 364 return PVMFSuccess; 365 } 366 367 return PVMFErrInvalidState; 368 } 369 370 371 PVMFStatus PVMFMP4FFParserNode::ThreadLogoff() 372 { 373 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ThreadLogoff() called")); 374 375 if (iInterfaceState == EPVMFNodeIdle) 376 { 377 CleanupFileSource(); 378 iFileServer.Close(); 379 380 if (IsAdded()) 381 { 382 RemoveFromScheduler(); 383 } 384 iLogger = NULL; 385 iDataPathLogger = NULL; 386 iAVCDataPathLogger = NULL; 387 iClockLogger = NULL; 388 iDiagnosticsLogger = NULL; 389 390 ChangeNodeState(EPVMFNodeCreated); 391 return PVMFSuccess; 392 } 393 394 return PVMFErrInvalidState; 395 } 396 397 398 PVMFStatus PVMFMP4FFParserNode::GetCapability(PVMFNodeCapability& aNodeCapability) 399 { 400 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetCapability() called")); 401 402 aNodeCapability = iCapability; 403 404 return PVMFSuccess; 405 } 406 407 408 PVMFPortIter* PVMFMP4FFParserNode::GetPorts(const PVMFPortFilter* aFilter) 409 { 410 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetPorts() called")); 411 412 OSCL_UNUSED_ARG(aFilter); 413 iPortIter->Reset(); 414 return iPortIter; 415 } 416 417 418 PVMFCommandId PVMFMP4FFParserNode::QueryUUID(PVMFSessionId aSessionId, const PvmfMimeString& aMimeType, 419 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids, bool aExactUuidsOnly, const OsclAny* aContext) 420 { 421 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::QueryUUID() called")); 422 423 PVMFMP4FFParserNodeCommand cmd; 424 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext); 425 return QueueCommandL(cmd); 426 } 427 428 429 PVMFCommandId PVMFMP4FFParserNode::QueryInterface(PVMFSessionId aSessionId, const PVUuid& aUuid, 430 PVInterface*& aInterfacePtr, const OsclAny* aContext) 431 { 432 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::QueryInterface() called")); 433 434 PVMFMP4FFParserNodeCommand cmd; 435 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext); 436 return QueueCommandL(cmd); 437 } 438 439 440 PVMFCommandId PVMFMP4FFParserNode::RequestPort(PVMFSessionId aSessionId, int32 aPortTag, 441 const PvmfMimeString* aPortConfig, const OsclAny* aContext) 442 { 443 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::RequestPort() called")); 444 445 PVMFMP4FFParserNodeCommand cmd; 446 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext); 447 return QueueCommandL(cmd); 448 } 449 450 451 PVMFStatus PVMFMP4FFParserNode::ReleasePort(PVMFSessionId aSessionId, PVMFPortInterface& aPort, const OsclAny* aContext) 452 { 453 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ReleasePort() called")); 454 455 PVMFMP4FFParserNodeCommand cmd; 456 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext); 457 return QueueCommandL(cmd); 458 } 459 460 461 PVMFCommandId PVMFMP4FFParserNode::Init(PVMFSessionId aSessionId, const OsclAny* aContext) 462 { 463 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::Init() called")); 464 465 PVMFMP4FFParserNodeCommand cmd; 466 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_INIT, aContext); 467 return QueueCommandL(cmd); 468 } 469 470 471 PVMFCommandId PVMFMP4FFParserNode::Prepare(PVMFSessionId aSessionId, const OsclAny* aContext) 472 { 473 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::Prepare() called")); 474 475 PVMFMP4FFParserNodeCommand cmd; 476 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_PREPARE, aContext); 477 return QueueCommandL(cmd); 478 } 479 480 481 PVMFCommandId PVMFMP4FFParserNode::Start(PVMFSessionId aSessionId, const OsclAny* aContext) 482 { 483 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::Start() called")); 484 485 PVMFMP4FFParserNodeCommand cmd; 486 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_START, aContext); 487 return QueueCommandL(cmd); 488 } 489 490 491 PVMFCommandId PVMFMP4FFParserNode::Stop(PVMFSessionId aSessionId, const OsclAny* aContext) 492 { 493 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::Stop() called")); 494 495 PVMFMP4FFParserNodeCommand cmd; 496 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_STOP, aContext); 497 return QueueCommandL(cmd); 498 } 499 500 501 PVMFCommandId PVMFMP4FFParserNode::Flush(PVMFSessionId aSessionId, const OsclAny* aContext) 502 { 503 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::Flush() called")); 504 505 PVMFMP4FFParserNodeCommand cmd; 506 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_FLUSH, aContext); 507 return QueueCommandL(cmd); 508 } 509 510 511 PVMFCommandId PVMFMP4FFParserNode::Pause(PVMFSessionId aSessionId, const OsclAny* aContext) 512 { 513 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::Pause() called")); 514 515 PVMFMP4FFParserNodeCommand cmd; 516 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_PAUSE, aContext); 517 return QueueCommandL(cmd); 518 } 519 520 521 PVMFCommandId PVMFMP4FFParserNode::Reset(PVMFSessionId aSessionId, const OsclAny* aContext) 522 { 523 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::Reset() called")); 524 525 PVMFMP4FFParserNodeCommand cmd; 526 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_RESET, aContext); 527 return QueueCommandL(cmd); 528 } 529 530 531 PVMFCommandId PVMFMP4FFParserNode::CancelAllCommands(PVMFSessionId aSessionId, const OsclAny* aContext) 532 { 533 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::CancelAllCommands() called")); 534 535 PVMFMP4FFParserNodeCommand cmd; 536 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext); 537 return QueueCommandL(cmd); 538 } 539 540 541 PVMFCommandId PVMFMP4FFParserNode::CancelCommand(PVMFSessionId aSessionId, PVMFCommandId aCmdId, const OsclAny* aContext) 542 { 543 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::CancelCommand() called")); 544 545 PVMFMP4FFParserNodeCommand cmd; 546 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext); 547 return QueueCommandL(cmd); 548 } 549 550 551 void PVMFMP4FFParserNode::addRef() 552 { 553 ++iExtensionRefCount; 554 } 555 556 557 void PVMFMP4FFParserNode::removeRef() 558 { 559 --iExtensionRefCount; 560 } 561 562 563 PVMFStatus PVMFMP4FFParserNode::QueryInterfaceSync(PVMFSessionId aSession, 564 const PVUuid& aUuid, 565 PVInterface*& aInterfacePtr) 566 { 567 OSCL_UNUSED_ARG(aSession); 568 aInterfacePtr = NULL; 569 if (queryInterface(aUuid, aInterfacePtr)) 570 { 571 aInterfacePtr->addRef(); 572 return PVMFSuccess; 573 } 574 return PVMFErrNotSupported; 575 } 576 577 bool PVMFMP4FFParserNode::queryInterface(const PVUuid& uuid, PVInterface*& iface) 578 { 579 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::queryInterface() In")); 580 581 if (uuid == PVMF_TRACK_SELECTION_INTERFACE_UUID) 582 { 583 PVMFTrackSelectionExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackSelectionExtensionInterface*, this); 584 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 585 } 586 else if (uuid == PVMF_DATA_SOURCE_INIT_INTERFACE_UUID) 587 { 588 PVMFDataSourceInitializationExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFDataSourceInitializationExtensionInterface*, this); 589 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 590 } 591 else if (uuid == KPVMFMetadataExtensionUuid) 592 { 593 PVMFMetadataExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, this); 594 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 595 } 596 else if (uuid == PvmfDataSourcePlaybackControlUuid) 597 { 598 PvmfDataSourcePlaybackControlInterface* myInterface = OSCL_STATIC_CAST(PvmfDataSourcePlaybackControlInterface*, this); 599 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 600 } 601 else if (uuid == PVMF_TRACK_LEVEL_INFO_INTERFACE_UUID) 602 { 603 PVMFTrackLevelInfoExtensionInterface* myInterface = OSCL_STATIC_CAST(PVMFTrackLevelInfoExtensionInterface*, this); 604 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 605 } 606 else if (PVMF_FF_PROGDOWNLOAD_SUPPORT_INTERFACE_UUID == uuid) 607 { 608 PVMFFormatProgDownloadSupportInterface* myInterface = OSCL_STATIC_CAST(PVMFFormatProgDownloadSupportInterface*, this); 609 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 610 } 611 else if (uuid == PVMIDatastreamuserInterfaceUuid) 612 { 613 PVMIDatastreamuserInterface* myInterface = OSCL_STATIC_CAST(PVMIDatastreamuserInterface*, this); 614 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 615 } 616 else if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) 617 { 618 PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this); 619 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 620 } 621 else if (uuid == PVMFCPMPluginLicenseInterfaceUuid) 622 { 623 PVMFCPMPluginLicenseInterface* myInterface = OSCL_STATIC_CAST(PVMFCPMPluginLicenseInterface*, this); 624 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 625 } 626 else if (uuid == PvmfDataSourceDirectionControlUuid) 627 { 628 PvmfDataSourceDirectionControlInterface* myInterface = OSCL_STATIC_CAST(PvmfDataSourceDirectionControlInterface*, this); 629 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 630 } 631 else 632 { 633 return false; 634 } 635 return true; 636 } 637 638 639 PVMFStatus PVMFMP4FFParserNode::SetSourceInitializationData(OSCL_wString& aSourceURL, 640 PVMFFormatType& aSourceFormat, 641 OsclAny* aSourceData) 642 { 643 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SetSourceInitializationData() called")); 644 645 OSCL_UNUSED_ARG(aSourceData); 646 647 //cleanup any prior source. 648 CleanupFileSource(); 649 650 PVMFFormatType inputFormatType = aSourceFormat; 651 652 /* In case of FT we need to know about it, else init would not complete until the file is fully downloaded */ 653 if (inputFormatType == PVMF_MIME_DATA_SOURCE_PVX_FILE) 654 { 655 iFastTrackSession = true; 656 inputFormatType = PVMF_MIME_MPEG4FF; 657 } 658 659 if (inputFormatType == PVMF_MIME_MPEG4FF) 660 { 661 iFilename = aSourceURL; 662 iSourceFormat = inputFormatType; 663 iUseCPMPluginRegistry = true; 664 if (aSourceData) 665 { 666 PVInterface* pvInterface = 667 OSCL_STATIC_CAST(PVInterface*, aSourceData); 668 PVInterface* localDataSrc = NULL; 669 PVUuid localDataSrcUuid(PVMF_LOCAL_DATASOURCE_UUID); 670 if (pvInterface->queryInterface(localDataSrcUuid, localDataSrc)) 671 { 672 PVMFLocalDataSource* opaqueData = 673 OSCL_STATIC_CAST(PVMFLocalDataSource*, localDataSrc); 674 iPreviewMode = opaqueData->iPreviewMode; 675 uint32 intent = opaqueData->iIntent; 676 if (intent & BITMASK_PVMF_SOURCE_INTENT_THUMBNAILS) 677 { 678 iThumbNailMode = true; 679 } 680 iCPMSourceData.iPreviewMode = iPreviewMode; 681 iCPMSourceData.iIntent = opaqueData->iIntent; 682 if (opaqueData->iFileHandle) 683 { 684 iFileHandle = OSCL_NEW(OsclFileHandle, (*(opaqueData->iFileHandle))); 685 if (iFileHandle != NULL) 686 { 687 Oscl_File *fp = (Oscl_File*)iFileHandle; 688 fp->SetAsyncReadBufferSize(iAsyncReadBuffSize); 689 fp->SetLoggingEnable(iPVLoggerEnableFlag); 690 fp->SetNativeAccessMode(iNativeAccessMode); 691 fp->SetPVCacheSize(iCacheSize); 692 fp->SetSummaryStatsLoggingEnable(iPVLoggerStateEnableFlag); 693 } 694 iCPMSourceData.iFileHandle = iFileHandle; 695 } 696 if (opaqueData->iContentAccessFactory != NULL) 697 { 698 if (iUseCPMPluginRegistry == false) 699 { 700 iExternalDownload = true; 701 iCPMContentAccessFactory = opaqueData->iContentAccessFactory; 702 } 703 else 704 { 705 //Cannot have both plugin usage and a datastream factory 706 return PVMFErrArgument; 707 } 708 } 709 } 710 else 711 { 712 PVInterface* sourceDataContext = NULL; 713 PVInterface* commonDataContext = NULL; 714 PVUuid sourceContextUuid(PVMF_SOURCE_CONTEXT_DATA_UUID); 715 PVUuid commonContextUuid(PVMF_SOURCE_CONTEXT_DATA_COMMON_UUID); 716 if (pvInterface->queryInterface(sourceContextUuid, sourceDataContext)) 717 { 718 if (sourceDataContext->queryInterface(commonContextUuid, commonDataContext)) 719 { 720 PVMFSourceContextDataCommon* cContext = 721 OSCL_STATIC_CAST(PVMFSourceContextDataCommon*, commonDataContext); 722 iPreviewMode = cContext->iPreviewMode; 723 uint32 intent = cContext->iIntent; 724 if (intent & BITMASK_PVMF_SOURCE_INTENT_THUMBNAILS) 725 { 726 iThumbNailMode = true; 727 } 728 if (cContext->iFileHandle) 729 { 730 iFileHandle = OSCL_NEW(OsclFileHandle, (*(cContext->iFileHandle))); 731 } 732 if (cContext->iContentAccessFactory != NULL) 733 { 734 if (iUseCPMPluginRegistry == false) 735 { 736 iExternalDownload = true; 737 iCPMContentAccessFactory = cContext->iContentAccessFactory; 738 } 739 else 740 { 741 //Cannot have both plugin usage and a datastream factory 742 return PVMFErrArgument; 743 } 744 } 745 PVMFSourceContextData* sContext = 746 OSCL_STATIC_CAST(PVMFSourceContextData*, sourceDataContext); 747 iSourceContextData = *sContext; 748 iSourceContextDataValid = true; 749 } 750 } 751 } 752 } 753 //create a CPM object here... 754 if (iUseCPMPluginRegistry) 755 { 756 iCPM = PVMFCPMFactory::CreateContentPolicyManager(*this); 757 //thread logon may leave if there are no plugins 758 int32 err; 759 OSCL_TRY(err, iCPM->ThreadLogon();); 760 OSCL_FIRST_CATCH_ANY(err, 761 iCPM->ThreadLogoff(); 762 PVMFCPMFactory::DestroyContentPolicyManager(iCPM); 763 iCPM = NULL; 764 iUseCPMPluginRegistry = false; 765 ); 766 } 767 return PVMFSuccess; 768 } 769 return PVMFFailure; 770 } 771 772 PVMFStatus PVMFMP4FFParserNode::SetClientPlayBackClock(PVMFMediaClock* aClock) 773 { 774 if (aClock == NULL) 775 { 776 return PVMFErrArgument; 777 } 778 779 if (iClockNotificationsInf && iClientPlayBackClock) 780 { 781 iClockNotificationsInf->RemoveClockStateObserver(*this); 782 iClientPlayBackClock->DestroyMediaClockNotificationsInterface(iClockNotificationsInf); 783 iClockNotificationsInf = NULL; 784 } 785 iClientPlayBackClock = aClock; 786 iClientPlayBackClock->ConstructMediaClockNotificationsInterface(iClockNotificationsInf, *this); 787 788 if (NULL == iClockNotificationsInf) 789 { 790 return PVMFErrNoMemory; 791 } 792 793 iClockNotificationsInf->SetClockStateObserver(*this); 794 795 return PVMFSuccess; 796 } 797 798 PVMFStatus PVMFMP4FFParserNode::SetEstimatedServerClock(PVMFMediaClock* /*aClientClock*/) 799 { 800 return PVMFErrNotSupported; 801 } 802 803 PVMFStatus PVMFMP4FFParserNode::GetMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo) 804 { 805 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetMediaPresentationInfo() called")); 806 807 // Check to make sure the MP4 file has been parsed 808 if (!iMP4FileHandle) 809 { 810 return PVMFFailure; 811 } 812 813 int32 iNumTracks = iMP4FileHandle->getNumTracks(); 814 // Protection 815 if (iNumTracks > PVMFFFPARSERNODE_MAX_NUM_TRACKS) 816 { 817 iNumTracks = PVMFFFPARSERNODE_MAX_NUM_TRACKS; 818 } 819 820 aInfo.setDurationValue(iMP4FileHandle->getMovieDuration()); 821 aInfo.setDurationTimeScale(iMP4FileHandle->getMovieTimescale()); 822 823 uint32 iIdList[16]; 824 if (iNumTracks != iMP4FileHandle->getTrackIDList(iIdList, iNumTracks)) 825 { 826 return PVMFFailure; 827 } 828 829 for (int32 i = iNumTracks - 1; i >= 0; i--) 830 { 831 PVMFTrackInfo tmpTrackInfo; 832 833 tmpTrackInfo.setTrackID(iIdList[i]); 834 // Set the port tag to the track ID 835 tmpTrackInfo.setPortTag(iIdList[i]); 836 837 uint32 aBitRate = iMP4FileHandle->getTrackAverageBitrate(iIdList[i]); 838 tmpTrackInfo.setTrackBitRate(aBitRate); 839 840 uint64 timescale = iMP4FileHandle->getTrackMediaTimescale(iIdList[i]); 841 tmpTrackInfo.setTrackDurationTimeScale(timescale); 842 843 // in movie timescale 844 uint64 trackDuration = iMP4FileHandle->getTrackMediaDuration(iIdList[i]); 845 tmpTrackInfo.setTrackDurationValue(trackDuration); 846 847 OSCL_HeapString<OsclMemAllocator> trackMIMEType; 848 iMP4FileHandle->getTrackMIMEType(iIdList[i], trackMIMEType); 849 850 OSCL_FastString iMime; 851 iMime.set(trackMIMEType.get_str(), oscl_strlen(trackMIMEType.get_str())); 852 853 PVMFFormatType trackformattype = trackMIMEType.get_str(); 854 855 tmpTrackInfo.setTrackMimeType(iMime); 856 857 OsclRefCounterMemFrag config; 858 if (!RetrieveTrackConfigInfo(iIdList[i], trackformattype, config)) 859 { 860 return PVMFFailure; 861 } 862 tmpTrackInfo.setTrackConfigInfo(config); 863 864 aInfo.addTrackInfo(tmpTrackInfo); 865 866 } 867 return PVMFSuccess; 868 } 869 870 871 PVMFStatus PVMFMP4FFParserNode::SelectTracks(PVMFMediaPresentationInfo& aInfo) 872 { 873 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SelectTracks() called")); 874 875 // Copy the selected tracks to internal list 876 iSelectedTrackInfoList.clear(); 877 878 uint32 i; 879 for (i = 0; i < aInfo.getNumTracks(); ++i) 880 { 881 iSelectedTrackInfoList.push_back(*(aInfo.getTrackInfo(i))); 882 } 883 884 return PVMFSuccess; 885 } 886 887 888 PVMFCommandId PVMFMP4FFParserNode::SetDataSourcePosition(PVMFSessionId aSessionId, 889 PVMFTimestamp aTargetNPT, 890 PVMFTimestamp& aActualNPT, 891 PVMFTimestamp& aActualMediaDataTS, 892 bool aSeekToSyncPoint, 893 uint32 aStreamID, 894 OsclAny* aContext) 895 { 896 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 897 (0, "PVMFMP4FFParserNode::SetDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x", 898 aTargetNPT, aSeekToSyncPoint, aContext)); 899 900 PVMFMP4FFParserNodeCommand cmd; 901 cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId, PVMP4FF_NODE_CMD_SETDATASOURCEPOSITION, aTargetNPT, aActualNPT, 902 aActualMediaDataTS, aSeekToSyncPoint, aStreamID, aContext); 903 return QueueCommandL(cmd); 904 } 905 906 907 PVMFCommandId PVMFMP4FFParserNode::QueryDataSourcePosition(PVMFSessionId aSessionId, PVMFTimestamp aTargetNPT, 908 PVMFTimestamp& aActualNPT, 909 bool aSeekToSyncPoint, 910 OsclAny* aContext) 911 { 912 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 913 (0, "PVMFMP4FFParserNode::QueryDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x", 914 aTargetNPT, aSeekToSyncPoint, aContext)); 915 916 if (aActualNPT > aTargetNPT) /* eg of backward aActualNPT (CurrentPos) = 10, aTargetNPT (NewPos) = 2 */ 917 { 918 iBackwardReposFlag = true; /* To avoid backwardlooping */ 919 aActualNPT = 0; 920 } 921 else 922 { 923 iForwardReposFlag = true; 924 iCurPos = aActualNPT; 925 aActualNPT = 0; 926 } 927 928 PVMFMP4FFParserNodeCommand cmd; 929 cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId, PVMP4FF_NODE_CMD_QUERYDATASOURCEPOSITION, aTargetNPT, aActualNPT, 930 aSeekToSyncPoint, aContext); 931 return QueueCommandL(cmd); 932 } 933 934 PVMFCommandId PVMFMP4FFParserNode::QueryDataSourcePosition(PVMFSessionId aSessionId, PVMFTimestamp aTargetNPT, 935 PVMFTimestamp& aSeekPointBeforeTargetNPT, 936 PVMFTimestamp& aSeekPointAfterTargetNPT, 937 OsclAny* aContext, 938 bool aSeekToSyncPoint) 939 { 940 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 941 (0, "PVMFMP4FFParserNode::QueryDataSourcePosition: aTargetNPT=%d, aSeekToSyncPoint=%d, aContext=0x%x", 942 aTargetNPT, aSeekToSyncPoint, aContext)); 943 944 PVMFMP4FFParserNodeCommand cmd; 945 cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId, PVMP4FF_NODE_CMD_QUERYDATASOURCEPOSITION, aTargetNPT, 946 aSeekPointBeforeTargetNPT, aSeekPointAfterTargetNPT, aContext, aSeekToSyncPoint); 947 return QueueCommandL(cmd); 948 } 949 950 PVMFCommandId PVMFMP4FFParserNode::SetDataSourceRate(PVMFSessionId aSessionId, int32 aRate, PVMFTimebase* aTimebase, OsclAny* aContext) 951 { 952 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SetDataSourceRate() called")); 953 954 PVMFMP4FFParserNodeCommand cmd; 955 cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId, PVMP4FF_NODE_CMD_SETDATASOURCERATE, aRate, aTimebase, aContext); 956 return QueueCommandL(cmd); 957 } 958 959 PVMFCommandId PVMFMP4FFParserNode::SetDataSourceDirection(PVMFSessionId aSessionId, int32 aDirection, PVMFTimestamp& aActualNPT, 960 PVMFTimestamp& aActualMediaDataTS, PVMFTimebase* aTimebase, OsclAny* aContext) 961 { 962 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SetDataSourceDirection() called")); 963 964 PVMFMP4FFParserNodeCommand cmd; 965 cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId, PVMP4FF_NODE_CMD_SETDATASOURCEDIRECTION, aDirection, aActualNPT, aActualMediaDataTS, 966 aTimebase, aContext); 967 968 return QueueCommandL(cmd); 969 } 970 971 PVMFStatus PVMFMP4FFParserNode::GetAvailableTracks(Oscl_Vector<PVMFTrackInfo, OsclMemAllocator>& aTracks) 972 { 973 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetAvailableTracks() called")); 974 975 PVMFMediaPresentationInfo mediainfo; 976 mediainfo.Reset(); 977 PVMFStatus retval = GetMediaPresentationInfo(mediainfo); 978 if (retval != PVMFSuccess) 979 { 980 return retval; 981 } 982 983 for (uint32 i = 0; i < mediainfo.getNumTracks(); ++i) 984 { 985 PVMFTrackInfo* trackinfo = mediainfo.getTrackInfo(i); 986 if (trackinfo) 987 { 988 aTracks.push_back(*trackinfo); 989 } 990 else 991 { 992 // This shouldn't happen 993 OSCL_ASSERT(false); 994 return PVMFFailure; 995 } 996 } 997 998 return PVMFSuccess; 999 } 1000 1001 1002 PVMFStatus PVMFMP4FFParserNode::GetTimestampForSampleNumber(PVMFTrackInfo& aTrackInfo, uint32 aSampleNum, PVMFTimestamp& aTimestamp) 1003 { 1004 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetTimestampForSampleNumber() called")); 1005 1006 if (iMP4FileHandle == NULL) 1007 { 1008 return PVMFErrInvalidState; 1009 } 1010 1011 // Retrieve the timestamp in track media timescale for the specified sample number 1012 uint32 ts = iMP4FileHandle->getTimestampForSampleNumber(aTrackInfo.getTrackID(), aSampleNum); 1013 if (ts == 0xFFFFFFFF) 1014 { 1015 return PVMFFailure; 1016 } 1017 1018 // Convert the timestamp from media timescale to milliseconds 1019 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(aTrackInfo.getTrackID())); 1020 mcc.update_clock(ts); 1021 aTimestamp = mcc.get_converted_ts(1000); 1022 1023 return PVMFSuccess; 1024 } 1025 1026 1027 PVMFStatus PVMFMP4FFParserNode::GetSampleNumberForTimestamp(PVMFTrackInfo& aTrackInfo, PVMFTimestamp aTimestamp, uint32& aSampleNum) 1028 { 1029 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetSampleNumberForTimestamp() called")); 1030 1031 if (iMP4FileHandle == NULL) 1032 { 1033 return PVMFErrInvalidState; 1034 } 1035 1036 // Convert the timestamp to media timescale value 1037 MediaClockConverter mcc(1000); 1038 mcc.update_clock(aTimestamp); 1039 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(aTrackInfo.getTrackID())); 1040 1041 // Retrieve the sample number corresponding to the specified timestamp 1042 uint32 samplenum = 0; 1043 MP4_ERROR_CODE retval = iMP4FileHandle->getSampleNumberClosestToTimeStamp(aTrackInfo.getTrackID(), samplenum, mediats); 1044 if (retval == EVERYTHING_FINE || retval == END_OF_TRACK) 1045 { 1046 // Conversion worked 1047 aSampleNum = samplenum; 1048 } 1049 else 1050 { 1051 // Error 1052 aSampleNum = 0; 1053 return PVMFFailure; 1054 } 1055 1056 return PVMFSuccess; 1057 } 1058 1059 1060 PVMFStatus PVMFMP4FFParserNode::GetNumberOfSyncSamples(PVMFTrackInfo& aTrackInfo, int32& aNumSyncSamples) 1061 { 1062 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetNumberOfSyncSamples() called")); 1063 1064 if (iMP4FileHandle == NULL) 1065 { 1066 return PVMFErrInvalidState; 1067 } 1068 1069 // Use the MP4 FF API to retrieve the number of sync samples in a track 1070 uint32 numsamples = 0; 1071 int32 retval = iMP4FileHandle->getTimestampForRandomAccessPoints(aTrackInfo.getTrackID(), &numsamples, NULL, NULL); 1072 1073 if (retval == 2) 1074 { 1075 // All samples are sync samples. 1076 aNumSyncSamples = -1; 1077 } 1078 else if (retval == 1) 1079 { 1080 // OK 1081 aNumSyncSamples = (int32)numsamples; 1082 } 1083 else 1084 { 1085 // Error 1086 aNumSyncSamples = 0; 1087 return PVMFFailure; 1088 } 1089 1090 return PVMFSuccess; 1091 } 1092 1093 1094 PVMFStatus PVMFMP4FFParserNode::GetSyncSampleInfo(PVMFTrackInfo& aTrackInfo, PVMFSampleNumTSList& aList, uint32 aStartIndex, int32 aMaxEntries) 1095 { 1096 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetSyncSampleInfo() called")); 1097 1098 if (aMaxEntries == 0 || aMaxEntries < -1) 1099 { 1100 // max number of entries must be more than 1 and only -1 has special meaning 1101 return PVMFErrArgument; 1102 } 1103 if (iMP4FileHandle == NULL) 1104 { 1105 return PVMFErrInvalidState; 1106 } 1107 1108 // Determine the total number of sync samples 1109 int32 totalnum = 0; 1110 PVMFStatus status = GetNumberOfSyncSamples(aTrackInfo, totalnum); 1111 if (status != PVMFSuccess) 1112 { 1113 // Can't determine the total number of sync samples so error out 1114 return status; 1115 } 1116 if (totalnum < 1) 1117 { 1118 // There are no sync samples or all frames are sync samples so error out 1119 return PVMFFailure; 1120 } 1121 if (aStartIndex >= (uint32)totalnum) 1122 { 1123 // The starting index is more than the total number of sync samples 1124 return PVMFErrArgument; 1125 } 1126 1127 // Determine the number of sync sample info to retrieve 1128 uint32 numsamplestoget = (uint32)totalnum; 1129 if ((aMaxEntries > 0) && (aStartIndex + aMaxEntries) < (uint32)totalnum) 1130 { 1131 // Reduce the amount 1132 numsamplestoget = aStartIndex + aMaxEntries; 1133 } 1134 1135 // Allocate memory for the info 1136 uint32* syncts = OSCL_ARRAY_NEW(uint32, numsamplestoget); 1137 uint32* syncfrnum = OSCL_ARRAY_NEW(uint32, numsamplestoget); 1138 if (syncts == NULL || syncfrnum == NULL) 1139 { 1140 if (syncts) 1141 { 1142 OSCL_ARRAY_DELETE(syncts); 1143 } 1144 if (syncfrnum) 1145 { 1146 OSCL_ARRAY_DELETE(syncfrnum); 1147 } 1148 return PVMFErrNoMemory; 1149 } 1150 1151 // Retrieve the list of timestamp and frame numbers for sync samples. 1152 int32 retval = iMP4FileHandle->getTimestampForRandomAccessPoints(aTrackInfo.getTrackID(), &numsamplestoget, syncts, syncfrnum); 1153 if (retval != 1) 1154 { 1155 // Error 1156 if (syncts) 1157 { 1158 OSCL_ARRAY_DELETE(syncts); 1159 } 1160 if (syncfrnum) 1161 { 1162 OSCL_ARRAY_DELETE(syncfrnum); 1163 } 1164 return PVMFFailure; 1165 } 1166 1167 // Copy the info 1168 aList.clear(); 1169 uint32 ii; 1170 PVMFSampleNumTS syncnumts; 1171 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(aTrackInfo.getTrackID())); 1172 for (ii = aStartIndex; ii < numsamplestoget; ++ii) // numsamplestoget does incorporate the aMaxEntries limit 1173 { 1174 syncnumts.iSampleNumber = syncfrnum[ii]; 1175 // Use the media clock converter to convert from timestamp in media timescale to millisec 1176 mcc.update_clock(syncts[ii]); 1177 syncnumts.iTimestamp = mcc.get_converted_ts(1000); 1178 // Add to provided list 1179 aList.push_back(syncnumts); 1180 } 1181 1182 if (syncts) 1183 { 1184 OSCL_ARRAY_DELETE(syncts); 1185 } 1186 if (syncfrnum) 1187 { 1188 OSCL_ARRAY_DELETE(syncfrnum); 1189 } 1190 return PVMFSuccess; 1191 } 1192 1193 PVMFStatus PVMFMP4FFParserNode::GetSyncSampleInfo(PVMFSampleNumTSList& aList, PVMFTrackInfo& aTrackInfo, int32 aTargetTimeInMS, uint32 aHowManySamples) 1194 { 1195 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetSyncSampleInfo() called")); 1196 1197 if (iMP4FileHandle == NULL) 1198 { 1199 return PVMFErrInvalidState; 1200 } 1201 1202 MediaClockConverter mcc1(1000); 1203 mcc1.update_clock(aTargetTimeInMS); 1204 uint32 targetTimestamp = 1205 mcc1.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(aTrackInfo.getTrackID())); 1206 1207 int32 totalnum = 0; 1208 PVMFStatus status = GetNumberOfSyncSamples(aTrackInfo, totalnum); 1209 if (status != PVMFSuccess) 1210 { 1211 // Can't determine the total number of sync samples so error out 1212 return status; 1213 } 1214 if (totalnum < 1) 1215 { 1216 // There are no sync samples or all frames are sync samples so error out 1217 return PVMFFailure; 1218 } 1219 if (aTargetTimeInMS < 0) 1220 return PVMFErrArgument; 1221 1222 uint32 numsamplestoget = (2 * aHowManySamples); //multiply by 2 for after and before 1223 if (numsamplestoget > (uint32)totalnum) 1224 { 1225 aHowManySamples = 1; 1226 numsamplestoget = 2; 1227 } 1228 // Allocate memory for the info 1229 uint32* syncts = OSCL_ARRAY_NEW(uint32, numsamplestoget + 1); 1230 uint32* syncfrnum = OSCL_ARRAY_NEW(uint32, numsamplestoget + 1); 1231 oscl_memset(syncts, 0, numsamplestoget + 1); 1232 oscl_memset(syncfrnum, 0, numsamplestoget + 1); 1233 1234 if (syncts == NULL || syncfrnum == NULL) 1235 { 1236 if (syncts) 1237 { 1238 OSCL_ARRAY_DELETE(syncts); 1239 } 1240 if (syncfrnum) 1241 { 1242 OSCL_ARRAY_DELETE(syncfrnum); 1243 } 1244 return PVMFErrNoMemory; 1245 } 1246 1247 // Retrieve the list of timestamp and frame numbers for sync samples. 1248 int32 retval = iMP4FileHandle->getTimestampForRandomAccessPointsBeforeAfter(aTrackInfo.getTrackID(), targetTimestamp, syncts, 1249 syncfrnum, numsamplestoget, aHowManySamples); 1250 if (retval != 1) 1251 { 1252 // Error 1253 if (syncts) 1254 { 1255 OSCL_ARRAY_DELETE(syncts); 1256 } 1257 if (syncfrnum) 1258 { 1259 OSCL_ARRAY_DELETE(syncfrnum); 1260 } 1261 return PVMFFailure; 1262 } 1263 1264 // Copy the info 1265 aList.clear(); 1266 uint32 ii; 1267 1268 PVMFSampleNumTS syncnumts; 1269 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(aTrackInfo.getTrackID())); 1270 for (ii = 0; ii < numsamplestoget; ++ii) // numsamplestoget does incorporate the aMaxEntries limit 1271 { 1272 syncnumts.iSampleNumber = syncfrnum[ii]; 1273 // Use the media clock converter to convert from timestamp in media timescale to millisec 1274 mcc.update_clock(syncts[ii]); 1275 syncnumts.iTimestamp = mcc.get_converted_ts(1000); 1276 // Add to provided list 1277 aList.push_back(syncnumts); 1278 } 1279 if (syncts) 1280 { 1281 OSCL_ARRAY_DELETE(syncts); 1282 } 1283 if (syncfrnum) 1284 { 1285 OSCL_ARRAY_DELETE(syncfrnum); 1286 } 1287 return PVMFSuccess; 1288 } 1289 1290 PVMFStatus PVMFMP4FFParserNode::GetTimestampForDataPosition(PVMFTrackInfo& aTrackInfo, uint32 aDataPosition, PVMFTimestamp& aTimestamp) 1291 { 1292 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetTimestampForDataPosition() called")); 1293 OSCL_UNUSED_ARG(aTrackInfo); 1294 OSCL_UNUSED_ARG(aDataPosition); 1295 OSCL_UNUSED_ARG(aTimestamp); 1296 1297 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::GetTimestampForDataPosition() Conversion from data position to timestamp is not supported!")); 1298 return PVMFErrNotSupported; 1299 } 1300 1301 1302 PVMFStatus PVMFMP4FFParserNode::GetDataPositionForTimestamp(PVMFTrackInfo& aTrackInfo, PVMFTimestamp aTimestamp, uint32& aDataPosition) 1303 { 1304 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::GetDataPositionForTimestamp() called")); 1305 1306 if (iMP4FileHandle == NULL) 1307 { 1308 return PVMFErrInvalidState; 1309 } 1310 1311 // Convert the timestamp to media timescale value 1312 MediaClockConverter mcc(1000); 1313 mcc.update_clock(aTimestamp); 1314 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(aTrackInfo.getTrackID())); 1315 1316 // Retrieve the sample number corresponding to the specified timestamp 1317 int32 fileoffset = 0; 1318 int32 retVal = iMP4FileHandle->getOffsetByTime(aTrackInfo.getTrackID(), mediats, &fileoffset, 0); 1319 1320 if (retVal == EVERYTHING_FINE || retVal == END_OF_TRACK) 1321 { 1322 // Conversion worked 1323 aDataPosition = fileoffset; 1324 } 1325 else 1326 { 1327 // Error 1328 aDataPosition = 0; 1329 return PVMFFailure; 1330 } 1331 1332 return PVMFSuccess; 1333 } 1334 1335 1336 ///////////////////// 1337 // Private Section // 1338 ///////////////////// 1339 1340 void PVMFMP4FFParserNode::Run() 1341 { 1342 //Process commands. 1343 if (!iInputCommands.empty()) 1344 { 1345 ProcessCommand(); 1346 } 1347 1348 // Process port activity 1349 while (!iPortActivityQueue.empty() && (iInterfaceState == EPVMFNodeStarted || FlushPending())) 1350 { 1351 ProcessPortActivity(); 1352 } 1353 1354 // Send out media data when started and not flushing 1355 if (iInterfaceState == EPVMFNodeStarted && !FlushPending()) 1356 { 1357 HandleTrackState(); 1358 } 1359 1360 //Check for completion of a flush command... 1361 if (FlushPending() && iPortActivityQueue.empty()) 1362 { 1363 //Flush is complete. 1364 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFSuccess); 1365 } 1366 } 1367 1368 1369 PVMFCommandId PVMFMP4FFParserNode::QueueCommandL(PVMFMP4FFParserNodeCommand& aCmd) 1370 { 1371 if (IsAdded()) 1372 { 1373 PVMFCommandId id; 1374 id = iInputCommands.AddL(aCmd); 1375 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::QueueCommandL() called id=%d", id)); 1376 /* Wakeup the AO */ 1377 RunIfNotReady(); 1378 return id; 1379 } 1380 OSCL_LEAVE(OsclErrInvalidState); 1381 return -1; 1382 } 1383 1384 void PVMFMP4FFParserNode::MoveCmdToCurrentQueue(PVMFMP4FFParserNodeCommand& aCmd) 1385 { 1386 //note: the StoreL cannot fail since the queue is never more than 1 deep 1387 //and we reserved space. 1388 iCurrentCommand.StoreL(aCmd); 1389 iInputCommands.Erase(&aCmd); 1390 } 1391 1392 void PVMFMP4FFParserNode::MoveCmdToCancelQueue(PVMFMP4FFParserNodeCommand& aCmd) 1393 { 1394 //note: the StoreL cannot fail since the queue is never more than 1 deep 1395 //and we reserved space. 1396 iCancelCommand.StoreL(aCmd); 1397 iInputCommands.Erase(&aCmd); 1398 } 1399 1400 void PVMFMP4FFParserNode::ProcessCommand() 1401 { 1402 //can't do anything while an asynchronous cancel is in progress... 1403 if (!iCancelCommand.empty()) 1404 return; 1405 1406 PVMFMP4FFParserNodeCommand& aCmd = iInputCommands.front(); 1407 1408 //normally this node will not start processing one command 1409 //until the prior one is finished. However, a hi priority 1410 //command such as Cancel must be able to interrupt a command 1411 //in progress. 1412 if (!iCurrentCommand.empty() && !aCmd.hipri() && aCmd.iCmd != PVMP4FF_NODE_CMD_CANCEL_GET_LICENSE) 1413 { 1414 return ; 1415 } 1416 1417 PVMFStatus cmdstatus; 1418 switch (aCmd.iCmd) 1419 { 1420 case PVMF_GENERIC_NODE_QUERYUUID: 1421 cmdstatus = DoQueryUuid(aCmd); 1422 CommandComplete(iInputCommands, aCmd, cmdstatus); 1423 break; 1424 1425 case PVMF_GENERIC_NODE_QUERYINTERFACE: 1426 cmdstatus = DoQueryInterface(aCmd); 1427 CommandComplete(iInputCommands, aCmd, cmdstatus); 1428 break; 1429 1430 case PVMF_GENERIC_NODE_REQUESTPORT: 1431 { 1432 PVMFPortInterface*port; 1433 cmdstatus = DoRequestPort(aCmd, port); 1434 CommandComplete(iInputCommands, aCmd, cmdstatus, (OsclAny*)port); 1435 } 1436 break; 1437 1438 case PVMF_GENERIC_NODE_RELEASEPORT: 1439 cmdstatus = DoReleasePort(aCmd); 1440 CommandComplete(iInputCommands, aCmd, cmdstatus); 1441 break; 1442 1443 case PVMF_GENERIC_NODE_INIT: 1444 cmdstatus = DoInit(aCmd); 1445 switch (cmdstatus) 1446 { 1447 case PVMFPending: 1448 MoveCmdToCurrentQueue(aCmd); 1449 //wait on CPM or data stream callback. 1450 break; 1451 case PVMFSuccess: 1452 //This means that init can be completed right away 1453 //without waiting on either CPM or datastream callbacks 1454 //This happens if: 1455 //1) Local playback of unprotected content 1456 //2) FT / PDL /PPB of unprotected content where in movieatom 1457 //is complete when init was processed 1458 CompleteInit(iInputCommands, aCmd); 1459 break; 1460 default: 1461 CommandComplete(iInputCommands, aCmd, cmdstatus); 1462 break; 1463 } 1464 break; 1465 1466 case PVMF_GENERIC_NODE_PREPARE: 1467 cmdstatus = DoPrepare(aCmd); 1468 //doprepare may complete synchronously or asynchronously. 1469 switch (cmdstatus) 1470 { 1471 case PVMFPending: 1472 //wait on DataStream callback. 1473 MoveCmdToCurrentQueue(aCmd); 1474 break; 1475 default: 1476 CommandComplete(iInputCommands, aCmd, cmdstatus); 1477 break; 1478 } 1479 break; 1480 1481 case PVMF_GENERIC_NODE_START: 1482 cmdstatus = DoStart(aCmd); 1483 CommandComplete(iInputCommands, aCmd, cmdstatus); 1484 break; 1485 1486 case PVMF_GENERIC_NODE_STOP: 1487 cmdstatus = DoStop(aCmd); 1488 CommandComplete(iInputCommands, aCmd, cmdstatus); 1489 break; 1490 1491 case PVMF_GENERIC_NODE_FLUSH: 1492 cmdstatus = DoFlush(aCmd); 1493 switch (cmdstatus) 1494 { 1495 case PVMFPending: 1496 MoveCmdToCurrentQueue(aCmd); 1497 break; 1498 default: 1499 CommandComplete(iInputCommands, aCmd, cmdstatus); 1500 break; 1501 } 1502 break; 1503 1504 case PVMF_GENERIC_NODE_PAUSE: 1505 cmdstatus = DoPause(aCmd); 1506 CommandComplete(iInputCommands, aCmd, cmdstatus); 1507 break; 1508 1509 case PVMF_GENERIC_NODE_RESET: 1510 cmdstatus = DoReset(aCmd); 1511 //reset may complete synchronously or asynchronously. 1512 switch (cmdstatus) 1513 { 1514 case PVMFPending: 1515 MoveCmdToCurrentQueue(aCmd); 1516 //wait on CPM callback. 1517 break; 1518 case PVMFSuccess: 1519 CompleteReset(iInputCommands, aCmd); 1520 break; 1521 default: 1522 CommandComplete(iInputCommands, aCmd, cmdstatus); 1523 break; 1524 } 1525 break; 1526 1527 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS: 1528 cmdstatus = DoCancelAllCommands(aCmd); 1529 switch (cmdstatus) 1530 { 1531 case PVMFPending: 1532 MoveCmdToCancelQueue(aCmd); 1533 //wait on CPM callback. 1534 break; 1535 default: 1536 CommandComplete(iInputCommands, aCmd, cmdstatus); 1537 break; 1538 } 1539 break; 1540 1541 case PVMF_GENERIC_NODE_CANCELCOMMAND: 1542 cmdstatus = DoCancelCommand(aCmd); 1543 switch (cmdstatus) 1544 { 1545 case PVMFPending: 1546 MoveCmdToCancelQueue(aCmd); 1547 //wait on CPM callback. 1548 break; 1549 default: 1550 CommandComplete(iInputCommands, aCmd, cmdstatus); 1551 break; 1552 } 1553 break; 1554 1555 case PVMP4FF_NODE_CMD_GETNODEMETADATAKEYS: 1556 cmdstatus = DoGetMetadataKeys(aCmd); 1557 if (cmdstatus != PVMFPending) 1558 { 1559 CommandComplete(iInputCommands, aCmd, cmdstatus); 1560 } 1561 else 1562 { 1563 MoveCmdToCurrentQueue(aCmd); 1564 } 1565 break; 1566 1567 case PVMP4FF_NODE_CMD_GETNODEMETADATAVALUES: 1568 cmdstatus = DoGetMetadataValues(aCmd); 1569 if (cmdstatus != PVMFPending) 1570 { 1571 CommandComplete(iInputCommands, aCmd, cmdstatus); 1572 } 1573 else 1574 { 1575 MoveCmdToCurrentQueue(aCmd); 1576 } 1577 break; 1578 1579 case PVMP4FF_NODE_CMD_SETDATASOURCEPOSITION: 1580 { 1581 PVUuid eventuuid; 1582 PVMFStatus eventcode; 1583 cmdstatus = DoSetDataSourcePosition(aCmd, eventcode, eventuuid); 1584 if (eventcode == PVMFSuccess) 1585 { 1586 CommandComplete(iInputCommands, aCmd, cmdstatus); 1587 } 1588 else 1589 { 1590 CommandComplete(iInputCommands, aCmd, cmdstatus, NULL, &eventuuid, &eventcode); 1591 } 1592 } 1593 break; 1594 1595 case PVMP4FF_NODE_CMD_QUERYDATASOURCEPOSITION: 1596 cmdstatus = DoQueryDataSourcePosition(aCmd); 1597 CommandComplete(iInputCommands, aCmd, cmdstatus); 1598 break; 1599 1600 case PVMP4FF_NODE_CMD_SETDATASOURCERATE: 1601 cmdstatus = DoSetDataSourceRate(aCmd); 1602 CommandComplete(iInputCommands, aCmd, cmdstatus); 1603 break; 1604 1605 case PVMF_MP4_PARSER_NODE_CAPCONFIG_SETPARAMS: 1606 { 1607 PvmiMIOSession session; 1608 PvmiKvp* aParameters; 1609 int num_elements; 1610 PvmiKvp** ppRet_kvp; 1611 aCmd.Parse(session, aParameters, num_elements, ppRet_kvp); 1612 setParametersSync(NULL, aParameters, num_elements, *ppRet_kvp); 1613 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 1614 } 1615 break; 1616 1617 case PVMP4FF_NODE_CMD_GET_LICENSE_W: 1618 { 1619 PVMFStatus status = DoGetLicense(aCmd, true); 1620 if (status == PVMFPending) 1621 { 1622 MoveCmdToCurrentQueue(aCmd); 1623 } 1624 else 1625 { 1626 CommandComplete(iInputCommands, aCmd, status); 1627 } 1628 } 1629 break; 1630 1631 case PVMP4FF_NODE_CMD_GET_LICENSE: 1632 { 1633 PVMFStatus status = DoGetLicense(aCmd); 1634 if (status == PVMFPending) 1635 { 1636 MoveCmdToCurrentQueue(aCmd); 1637 } 1638 else 1639 { 1640 CommandComplete(iInputCommands, aCmd, status); 1641 } 1642 } 1643 break; 1644 1645 case PVMP4FF_NODE_CMD_CANCEL_GET_LICENSE: 1646 cmdstatus = DoCancelGetLicense(aCmd); 1647 switch (cmdstatus) 1648 { 1649 case PVMFPending: 1650 MoveCmdToCancelQueue(aCmd); 1651 //wait on CPM callback. 1652 break; 1653 default: 1654 CommandComplete(iInputCommands, aCmd, cmdstatus); 1655 break; 1656 } 1657 break; 1658 1659 case PVMP4FF_NODE_CMD_SETDATASOURCEDIRECTION: 1660 cmdstatus = DoSetDataSourceDirection(aCmd); 1661 CommandComplete(iInputCommands, aCmd, cmdstatus); 1662 break; 1663 1664 default://unknown command type 1665 CommandComplete(iInputCommands, aCmd, PVMFErrNotSupported); 1666 break; 1667 } 1668 } 1669 1670 void PVMFMP4FFParserNode::CommandComplete(PVMFMP4FFParserNodeCmdQueue& aCmdQ, PVMFMP4FFParserNodeCommand& aCmd, PVMFStatus aStatus, OsclAny* aEventData, PVUuid* aEventUUID, int32* aEventCode) 1671 { 1672 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::CommandComplete() In Id %d Cmd %d Status %d Context %d Data %d", 1673 aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData)); 1674 1675 bool oCompleteCancel = false; 1676 if ((aCmd.iCmd == PVMF_GENERIC_NODE_INIT) && 1677 (iCancelCommand.empty() == false)) 1678 { 1679 //cancel has been waiting on init 1680 oCompleteCancel = true; 1681 } 1682 //Do standard node command state changes. 1683 if (aStatus == PVMFSuccess) 1684 { 1685 switch (aCmd.iCmd) 1686 { 1687 case PVMF_GENERIC_NODE_INIT: 1688 ChangeNodeState(EPVMFNodeInitialized); 1689 break; 1690 case PVMF_GENERIC_NODE_PREPARE: 1691 ChangeNodeState(EPVMFNodePrepared); 1692 break; 1693 case PVMF_GENERIC_NODE_START: 1694 ChangeNodeState(EPVMFNodeStarted); 1695 //wakeup the AO when started... 1696 RunIfNotReady(); 1697 break; 1698 case PVMF_GENERIC_NODE_PAUSE: 1699 ChangeNodeState(EPVMFNodePaused); 1700 break; 1701 case PVMF_GENERIC_NODE_STOP: 1702 ChangeNodeState(EPVMFNodePrepared); 1703 break; 1704 case PVMF_GENERIC_NODE_FLUSH: 1705 ChangeNodeState(EPVMFNodePrepared); 1706 break; 1707 case PVMF_GENERIC_NODE_RESET: 1708 ChangeNodeState(EPVMFNodeIdle); 1709 break; 1710 } 1711 } 1712 1713 if (aStatus != PVMFSuccess) 1714 { 1715 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::CommandComplete() In Id %d Cmd %d Status %d Context %d Data %d", 1716 aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData)); 1717 } 1718 1719 PVInterface* extif = NULL; 1720 PVMFBasicErrorInfoMessage* errormsg = NULL; 1721 if (aEventUUID && aEventCode) 1722 { 1723 int32 leavecode = CreateErrorInfoMsg(&errormsg, *aEventUUID, *aEventCode); 1724 if (leavecode == 0 && errormsg) 1725 { 1726 extif = OSCL_STATIC_CAST(PVInterface*, errormsg); 1727 } 1728 1729 } 1730 //create response 1731 PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, extif, aEventData); 1732 PVMFSessionId session = aCmd.iSession; 1733 1734 //Erase the command from the queue. 1735 aCmdQ.Erase(&aCmd); 1736 1737 //Report completion to the session observer. 1738 ReportCmdCompleteEvent(session, resp); 1739 1740 if (errormsg) 1741 { 1742 errormsg->removeRef(); 1743 } 1744 1745 if (oCompleteCancel) 1746 { 1747 CompleteCancelAfterInit(); 1748 } 1749 1750 //Re-schedule if there are additional commands 1751 if (!iInputCommands.empty() 1752 && IsAdded()) 1753 { 1754 RunIfNotReady(); 1755 } 1756 } 1757 1758 void PVMFMP4FFParserNode::CompleteCancelAfterInit() 1759 { 1760 // cancel commands were pending, but not processed. return failed cancel 1761 while (!iCancelCommand.empty()) 1762 { 1763 PVMFMP4FFParserNodeCommand& cmdCancel = iCancelCommand.front(); 1764 PVMFCmdResp resp(cmdCancel.iId, cmdCancel.iContext, PVMFFailure); 1765 PVMFSessionId session = cmdCancel.iSession; 1766 1767 //Erase the command from the queue. 1768 iCancelCommand.Erase(&cmdCancel); 1769 1770 //Report completion to the session observer. 1771 ReportCmdCompleteEvent(session, resp); 1772 } 1773 } 1774 1775 void PVMFMP4FFParserNode::ReportMP4FFParserErrorEvent(PVMFEventType aEventType, OsclAny* aEventData, PVUuid* aEventUUID, int32* aEventCode) 1776 { 1777 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ReportMP4FFParserErrorEvent() In Type %d Data %d", 1778 aEventType, aEventData)); 1779 1780 if (aEventUUID && aEventCode) 1781 { 1782 int32 leavecode = 0; 1783 PVMFBasicErrorInfoMessage* eventmsg = NULL; 1784 OSCL_TRY(leavecode, eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL))); 1785 PVMFAsyncEvent asyncevent(PVMFErrorEvent, aEventType, NULL, OSCL_STATIC_CAST(PVInterface*, eventmsg), aEventData, NULL, 0); 1786 PVMFNodeInterface::ReportErrorEvent(asyncevent); 1787 if (eventmsg) 1788 { 1789 eventmsg->removeRef(); 1790 } 1791 } 1792 else 1793 { 1794 PVMFNodeInterface::ReportErrorEvent(aEventType, aEventData); 1795 } 1796 } 1797 1798 1799 void PVMFMP4FFParserNode::ReportMP4FFParserInfoEvent(PVMFEventType aEventType, OsclAny* aEventData, PVUuid* aEventUUID, int32* aEventCode) 1800 { 1801 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ReportMP4FFParserInfoEvent() In Type %d Data %d", 1802 aEventType, aEventData)); 1803 1804 if (aEventUUID && aEventCode) 1805 { 1806 int32 leavecode = 0; 1807 PVMFBasicErrorInfoMessage* eventmsg = NULL; 1808 OSCL_TRY(leavecode, eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (*aEventCode, *aEventUUID, NULL))); 1809 PVMFAsyncEvent asyncevent(PVMFInfoEvent, aEventType, NULL, OSCL_STATIC_CAST(PVInterface*, eventmsg), aEventData, NULL, 0); 1810 PVMFNodeInterface::ReportInfoEvent(asyncevent); 1811 if (eventmsg) 1812 { 1813 eventmsg->removeRef(); 1814 } 1815 } 1816 else 1817 { 1818 PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData); 1819 } 1820 } 1821 1822 1823 void PVMFMP4FFParserNode::ChangeNodeState(TPVMFNodeInterfaceState aNewState) 1824 { 1825 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ChangeNodeState() Old %d New %d", iInterfaceState, aNewState)); 1826 1827 SetState(aNewState); 1828 } 1829 1830 1831 PVMFStatus PVMFMP4FFParserNode::DoQueryUuid(PVMFMP4FFParserNodeCommand& aCmd) 1832 { 1833 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoQueryUuid() In")); 1834 1835 OSCL_String* mimetype; 1836 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec; 1837 bool exactmatch; 1838 aCmd.PVMFMP4FFParserNodeCommandBase::Parse(mimetype, uuidvec, exactmatch); 1839 1840 // @TODO Add MIME string matching 1841 // For now just return all available extension interface UUID 1842 uuidvec->push_back(PVMF_TRACK_SELECTION_INTERFACE_UUID); 1843 uuidvec->push_back(PVMF_DATA_SOURCE_INIT_INTERFACE_UUID); 1844 uuidvec->push_back(KPVMFMetadataExtensionUuid); 1845 uuidvec->push_back(PvmfDataSourcePlaybackControlUuid); 1846 uuidvec->push_back(PVMF_TRACK_LEVEL_INFO_INTERFACE_UUID); 1847 uuidvec->push_back(PVMF_MP4_PROGDOWNLOAD_SUPPORT_INTERFACE_UUID); 1848 uuidvec->push_back(PvmfDataSourceDirectionControlUuid); 1849 1850 return PVMFSuccess; 1851 } 1852 1853 1854 PVMFStatus PVMFMP4FFParserNode::DoQueryInterface(PVMFMP4FFParserNodeCommand& aCmd) 1855 { 1856 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoQueryInterface() In")); 1857 1858 PVUuid* uuid; 1859 PVInterface** ptr; 1860 aCmd.PVMFMP4FFParserNodeCommandBase::Parse(uuid, ptr); 1861 1862 if (queryInterface(*uuid, *ptr)) 1863 { 1864 (*ptr)->addRef(); 1865 return PVMFSuccess; 1866 } 1867 else 1868 { 1869 //not supported 1870 *ptr = NULL; 1871 return PVMFFailure; 1872 } 1873 } 1874 1875 1876 PVMFStatus PVMFMP4FFParserNode::DoRequestPort(PVMFMP4FFParserNodeCommand& aCmd, PVMFPortInterface*&aPort) 1877 { 1878 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoRequestPort() In")); 1879 1880 aPort = NULL; 1881 1882 // Check to make sure the MP4 file has been parsed 1883 if (!iMP4FileHandle) 1884 { 1885 return PVMFFailure; 1886 } 1887 1888 //retrieve port tag. 1889 int32 tag; 1890 PvmfMimeString* mimetype; 1891 aCmd.PVMFMP4FFParserNodeCommandBase::Parse(tag, mimetype); 1892 if (!mimetype) 1893 { 1894 return PVMFErrArgument;//no mimetype supplied. 1895 } 1896 1897 // Allocate a port based on the request 1898 // Return the pointer to the port in the command complete message 1899 1900 // Determine the format type from the MIME type string 1901 PVMFFormatType formattype = mimetype->get_cstr(); 1902 if (formattype == PVMF_MIME_FORMAT_UNKNOWN) 1903 { 1904 // Unknown track type 1905 return PVMFErrArgument; 1906 } 1907 1908 // Determine the maximum track data size and queue depth based on the format type 1909 uint32 trackmaxdatasize = 0; 1910 uint32 trackmaxqueuedepth = 0; 1911 GetTrackMaxParameters(formattype, trackmaxdatasize, trackmaxqueuedepth); 1912 OSCL_ASSERT(trackmaxdatasize > 0 && trackmaxqueuedepth > 0); 1913 1914 // Track ID is the port tag 1915 // @TODO might need validation on the port tag==track ID. 1916 int32 trackid = tag; 1917 if (trackid < 0) 1918 { 1919 return PVMFErrArgument; 1920 } 1921 1922 //timestamp for tracks need not always start with zero 1923 //initialize the ts value to track timestamp start offset 1924 uint32 tsStartOffset = 0; 1925 if (iMP4FileHandle->getTrackTSStartOffset(tsStartOffset, (uint32)trackid) != EVERYTHING_FINE) 1926 { 1927 return PVMFErrArgument; 1928 } 1929 1930 //set the names for datapath logging 1931 OSCL_StackString<20> portname; 1932 OSCL_StackString<20> mempoolname; 1933 bool oTextTrack = false; 1934 if (formattype.isAudio()) 1935 { 1936 portname = "PVMFMP4FFParOut(Audio)"; 1937 mempoolname = "PVMFMP4FFPar(Audio)"; 1938 } 1939 else if (formattype.isVideo()) 1940 { 1941 portname = "PVMFMP4FFParOut(Video)"; 1942 mempoolname = "PVMFMP4FFPar(Video)"; 1943 } 1944 else if (formattype.isText()) 1945 { 1946 oTextTrack = true; 1947 portname = "PVMFMP4FFParOut(Misc)"; 1948 mempoolname = "PVMFMP4FFPar(Misc)"; 1949 } 1950 1951 int32 leavecode = 0; 1952 PVMFPortInterface* outport = NULL; 1953 MediaClockConverter* clockconv = NULL; 1954 OsclMemPoolResizableAllocator* trackdatamempool = NULL; 1955 PVMFResizableSimpleMediaMsgAlloc* mediadataimplalloc = NULL; 1956 PVMFTimedTextMediaDataAlloc* textmediadataimplalloc = NULL; 1957 PVMFMemPoolFixedChunkAllocator* mediadatamempool = NULL; 1958 OsclMemPoolFixedChunkAllocator* mediadatagroupimplmempool = NULL; 1959 PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>* mediadatagroupalloc = NULL; 1960 if (oTextTrack == false) 1961 { 1962 OSCL_TRY(leavecode, 1963 outport = OSCL_NEW(PVMFMP4FFParserOutPort, (tag, this, portname.get_str())); 1964 clockconv = OSCL_NEW(MediaClockConverter, (iMP4FileHandle->getTrackMediaTimescale(trackid))); 1965 trackdatamempool = OSCL_NEW(OsclMemPoolResizableAllocator, (trackmaxqueuedepth * trackmaxdatasize, PVMF_MP4FF_PARSER_NODE_MEM_POOL_GROWTH_LIMIT)); 1966 mediadataimplalloc = OSCL_NEW(PVMFResizableSimpleMediaMsgAlloc, (trackdatamempool)); 1967 mediadatamempool = OSCL_NEW(PVMFMemPoolFixedChunkAllocator, (mempoolname.get_str(), PVMP4FF_MEDIADATA_POOLNUM, PVMP4FF_MEDIADATA_CHUNKSIZE)); 1968 mediadatagroupimplmempool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (PVMP4FF_MEDIADATA_POOLNUM)); 1969 mediadatagroupalloc = OSCL_NEW(PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>, (PVMP4FF_MEDIADATA_POOLNUM, 20, mediadatagroupimplmempool)); 1970 ); 1971 } 1972 else 1973 { 1974 OSCL_TRY(leavecode, 1975 outport = OSCL_NEW(PVMFMP4FFParserOutPort, (tag, this, portname.get_str())); 1976 clockconv = OSCL_NEW(MediaClockConverter, (iMP4FileHandle->getTrackMediaTimescale(trackid))); 1977 trackdatamempool = OSCL_NEW(OsclMemPoolResizableAllocator, (trackmaxqueuedepth * trackmaxdatasize, PVMF_MP4FF_PARSER_NODE_MEM_POOL_GROWTH_LIMIT)); 1978 textmediadataimplalloc = OSCL_NEW(PVMFTimedTextMediaDataAlloc, (trackdatamempool)); 1979 mediadatamempool = OSCL_NEW(PVMFMemPoolFixedChunkAllocator, (mempoolname.get_str(), PVMP4FF_TEXT_TRACK_MEDIADATA_POOLNUM, PVMP4FF_MEDIADATA_CHUNKSIZE)); 1980 mediadatagroupimplmempool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (PVMP4FF_MEDIADATA_POOLNUM)); 1981 mediadatagroupalloc = OSCL_NEW(PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>, (PVMP4FF_TEXT_TRACK_MEDIADATA_POOLNUM, 20, mediadatagroupimplmempool)); 1982 ); 1983 } 1984 1985 bool memerr = false; 1986 if (oTextTrack == false) 1987 { 1988 if (leavecode || !outport || !clockconv || !trackdatamempool || !mediadataimplalloc || 1989 !mediadatamempool || !mediadatagroupimplmempool || !mediadatagroupalloc) 1990 { 1991 memerr = true; 1992 } 1993 } 1994 else 1995 { 1996 if (leavecode || !outport || !clockconv || !trackdatamempool || 1997 !textmediadataimplalloc || !mediadatamempool || !mediadatagroupimplmempool || !mediadatagroupalloc) 1998 { 1999 memerr = true; 2000 } 2001 } 2002 if (memerr == true) 2003 { 2004 if (outport) 2005 { 2006 OSCL_DELETE(((PVMFMP4FFParserOutPort*)outport)); 2007 } 2008 if (clockconv) 2009 { 2010 OSCL_DELETE(clockconv); 2011 } 2012 if (trackdatamempool) 2013 { 2014 trackdatamempool->removeRef(); 2015 trackdatamempool = NULL; 2016 } 2017 if (mediadataimplalloc) 2018 { 2019 OSCL_DELETE(mediadataimplalloc); 2020 } 2021 if (textmediadataimplalloc) 2022 { 2023 OSCL_DELETE(textmediadataimplalloc); 2024 } 2025 if (mediadatamempool) 2026 { 2027 OSCL_DELETE(mediadatamempool); 2028 } 2029 if (mediadatagroupalloc) 2030 { 2031 mediadatagroupalloc->removeRef(); 2032 } 2033 if (mediadatagroupimplmempool) 2034 { 2035 mediadatagroupimplmempool->removeRef(); 2036 } 2037 return PVMFErrNoMemory; 2038 } 2039 2040 mediadatagroupimplmempool->enablenullpointerreturn(); 2041 trackdatamempool->enablenullpointerreturn(); 2042 mediadatamempool->enablenullpointerreturn(); 2043 2044 mediadatagroupalloc->create(); 2045 2046 // Add the selected track/port to track list 2047 PVMP4FFNodeTrackPortInfo trackportinfo; 2048 trackportinfo.iTrackId = trackid; 2049 trackportinfo.iPortInterface = outport; 2050 trackportinfo.iFormatType = formattype; 2051 // assign the integer format type based on the format type recieved 2052 // these are formats being used during media data flow, so just assign 2053 // integer values to these types, others defined as unknown. 2054 if (formattype == PVMF_MIME_MPEG4_AUDIO) 2055 { 2056 trackportinfo.iFormatTypeInteger = PVMF_MP4_PARSER_NODE_MPEG4_AUDIO; 2057 } 2058 else if (formattype == PVMF_MIME_H264_VIDEO_MP4) 2059 { 2060 trackportinfo.iFormatTypeInteger = PVMF_MP4_PARSER_NODE_H264_MP4; 2061 } 2062 else if (formattype == PVMF_MIME_3GPP_TIMEDTEXT) 2063 { 2064 trackportinfo.iFormatTypeInteger = PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT; 2065 } 2066 else 2067 { 2068 trackportinfo.iFormatTypeInteger = PVMF_MP4_PARSER_NODE_FORMAT_UNKNOWN; 2069 } 2070 RetrieveTrackConfigInfo(trackid, 2071 formattype, 2072 trackportinfo.iFormatSpecificConfig); 2073 if (formattype == PVMF_MIME_MPEG4_AUDIO) 2074 { 2075 RetrieveTrackConfigInfoAndFirstSample(trackid, 2076 formattype, 2077 trackportinfo.iFormatSpecificConfigAndFirstSample); 2078 2079 } 2080 trackportinfo.iMimeType = (*mimetype); 2081 trackportinfo.iClockConverter = clockconv; 2082 trackportinfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED; 2083 trackportinfo.iTrackMaxDataSize = trackmaxdatasize; 2084 trackportinfo.iTrackMaxQueueDepth = trackmaxqueuedepth; 2085 trackportinfo.iTrackDataMemoryPool = trackdatamempool; 2086 trackportinfo.iMediaDataImplAlloc = mediadataimplalloc; 2087 trackportinfo.iTextMediaDataImplAlloc = textmediadataimplalloc; 2088 trackportinfo.iMediaDataMemPool = mediadatamempool; 2089 trackportinfo.iMediaDataGroupImplMemPool = mediadatagroupimplmempool; 2090 trackportinfo.iMediaDataGroupAlloc = mediadatagroupalloc; 2091 trackportinfo.iNode = OSCL_STATIC_CAST(OsclTimerObject* , this); 2092 trackportinfo.iTimestamp = tsStartOffset; 2093 trackportinfo.iSeqNum = 0; 2094 2095 // TEMP: Number of samples to retrieve should be negotiated between 2096 // the nodes but for now hardcode the values 2097 // By default retrieve one bundle of samples from the file format parser 2098 if (formattype == PVMF_MIME_M4V) 2099 { 2100 trackportinfo.iNumSamples = M4V_NUMSAMPLES; 2101 } 2102 else if (formattype == PVMF_MIME_H2631998 || 2103 formattype == PVMF_MIME_H2632000) 2104 { 2105 trackportinfo.iNumSamples = H263_NUMSAMPLES; 2106 } 2107 else if (formattype == PVMF_MIME_H264_VIDEO_MP4) 2108 { 2109 trackportinfo.iNumSamples = H264_MP4_NUMSAMPLES; 2110 } 2111 else if (formattype == PVMF_MIME_MPEG4_AUDIO) 2112 { 2113 trackportinfo.iNumSamples = MPEG4_AUDIO_NUMSAMPLES; 2114 } 2115 else if (formattype == PVMF_MIME_AMR_IETF) 2116 { 2117 if (trackportinfo.iNumAMRSamplesToRetrieve > 0) 2118 { 2119 trackportinfo.iNumSamples = trackportinfo.iNumAMRSamplesToRetrieve; 2120 } 2121 else 2122 { 2123 // Need to determine the number of AMR samples to get based on 2124 // number of frames to get and number of frames per sample 2125 int32 framespersample = iMP4FileHandle->getNumAMRFramesPerSample(trackid); 2126 if (framespersample > 0) 2127 { 2128 trackportinfo.iNumAMRSamplesToRetrieve = AMR_IETF_NUMFRAMES / framespersample; 2129 if (trackportinfo.iNumAMRSamplesToRetrieve == 0 || (AMR_IETF_NUMFRAMES % framespersample > 0)) 2130 { 2131 // Increment if 0 or if there is a remainder 2132 ++trackportinfo.iNumAMRSamplesToRetrieve; 2133 } 2134 } 2135 else 2136 { 2137 // Assume 1 AMR frame per sample 2138 trackportinfo.iNumAMRSamplesToRetrieve = AMR_IETF_NUMFRAMES; 2139 } 2140 } 2141 trackportinfo.iNumSamples = trackportinfo.iNumAMRSamplesToRetrieve; 2142 } 2143 else if (formattype == PVMF_MIME_AMRWB_IETF) 2144 { 2145 if (trackportinfo.iNumAMRSamplesToRetrieve > 0) 2146 { 2147 trackportinfo.iNumSamples = trackportinfo.iNumAMRSamplesToRetrieve; 2148 } 2149 else 2150 { 2151 // Need to determine the number of AMR samples to get based on 2152 // number of frames to get and number of frames per sample 2153 int32 framespersample = iMP4FileHandle->getNumAMRFramesPerSample(trackid); 2154 if (framespersample > 0) 2155 { 2156 trackportinfo.iNumAMRSamplesToRetrieve = AMRWB_IETF_NUMFRAMES / framespersample; 2157 if (trackportinfo.iNumAMRSamplesToRetrieve == 0 || (AMRWB_IETF_NUMFRAMES % framespersample > 0)) 2158 { 2159 // Increment if 0 or if there is a remainder 2160 ++trackportinfo.iNumAMRSamplesToRetrieve; 2161 } 2162 } 2163 else 2164 { 2165 // Assume 1 AMRWB frame per sample 2166 trackportinfo.iNumAMRSamplesToRetrieve = AMRWB_IETF_NUMFRAMES; 2167 } 2168 } 2169 trackportinfo.iNumSamples = trackportinfo.iNumAMRSamplesToRetrieve; 2170 } 2171 else if (formattype == PVMF_MIME_3GPP_TIMEDTEXT) 2172 { 2173 trackportinfo.iNumSamples = TIMEDTEXT_NUMSAMPLES; 2174 } 2175 else 2176 { 2177 trackportinfo.iNumSamples = UNKNOWN_NUMSAMPLES; 2178 } 2179 2180 if (iPortDataLog) 2181 { 2182 OSCL_StackString<512> portLoggerTag(_STRLIT_CHAR("PVMFMP4ParserNode")); 2183 portLoggerTag += iLogFileIndex; 2184 iLogFileIndex += 1; 2185 if (formattype.isAudio()) 2186 { 2187 portLoggerTag += _STRLIT_CHAR("audio"); 2188 } 2189 else if (formattype.isVideo()) 2190 { 2191 portLoggerTag += _STRLIT_CHAR("video"); 2192 } 2193 else 2194 { 2195 portLoggerTag += _STRLIT_CHAR("misc"); 2196 } 2197 trackportinfo.iPortLogger = PVLogger::GetLoggerObject(portLoggerTag.get_cstr()); 2198 OSCL_StackString<512> portLogFile; 2199 portLogFile = portLogPath; 2200 portLogFile += portLoggerTag.get_cstr(); 2201 trackportinfo.iLogFile = portLogFile; 2202 2203 PVLoggerAppender *binAppender = 2204 BinaryFileAppender::CreateAppender((char*)(trackportinfo.iLogFile.get_cstr())); 2205 2206 if (binAppender == NULL) 2207 { 2208 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::DoRequestPort: Error - Binary Appender Create failed", this)); 2209 return PVMFErrNoResources; 2210 } 2211 OsclRefCounterSA<PVMFMP4ParserNodeLoggerDestructDealloc>* binAppenderRefCounter = 2212 new OsclRefCounterSA<PVMFMP4ParserNodeLoggerDestructDealloc>(binAppender); 2213 2214 OsclSharedPtr<PVLoggerAppender> appenderSharedPtr(binAppender, binAppenderRefCounter); 2215 trackportinfo.iBinAppenderPtr = appenderSharedPtr; 2216 trackportinfo.iPortLogger->AddAppender(trackportinfo.iBinAppenderPtr); 2217 } 2218 2219 iNodeTrackPortList.push_back(trackportinfo); 2220 aPort = outport; 2221 2222 return PVMFSuccess; 2223 } 2224 2225 2226 void PVMFMP4FFParserNode::GetTrackMaxParameters(PVMFFormatType aFormatType, uint32& aMaxDataSize, uint32& aMaxQueueDepth) 2227 { 2228 if (aFormatType == PVMF_MIME_M4V) 2229 { 2230 aMaxDataSize = M4V_MAXTRACKDATASIZE; 2231 aMaxQueueDepth = M4V_MAXTRACKQUEUEDEPTH; 2232 } 2233 else if (aFormatType == PVMF_MIME_H2631998 || 2234 aFormatType == PVMF_MIME_H2632000) 2235 { 2236 aMaxDataSize = H263_MAXTRACKDATASIZE; 2237 aMaxQueueDepth = H263_MAXTRACKQUEUEDEPTH; 2238 } 2239 else if (aFormatType == PVMF_MIME_H264_VIDEO_MP4) 2240 { 2241 aMaxDataSize = H264_MP4_MAXTRACKDATASIZE; 2242 aMaxQueueDepth = H264_MP4_MAXTRACKQUEUEDEPTH; 2243 } 2244 else if (aFormatType == PVMF_MIME_MPEG4_AUDIO) 2245 { 2246 aMaxDataSize = MPEG4_AUDIO_MAXTRACKDATASIZE; 2247 aMaxQueueDepth = MPEG4_AUDIO_MAXTRACKQUEUEDEPTH; 2248 } 2249 else if (aFormatType == PVMF_MIME_AMR_IETF) 2250 { 2251 aMaxDataSize = AMR_IETF_MAXTRACKDATASIZE; 2252 aMaxQueueDepth = AMR_IETF_MAXTRACKQUEUEDEPTH; 2253 } 2254 else if (aFormatType == PVMF_MIME_AMRWB_IETF) 2255 { 2256 aMaxDataSize = AMRWB_IETF_MAXTRACKDATASIZE; 2257 aMaxQueueDepth = AMRWB_IETF_MAXTRACKQUEUEDEPTH; 2258 } 2259 else if (aFormatType == PVMF_MIME_3GPP_TIMEDTEXT) 2260 { 2261 aMaxDataSize = TIMEDTEXT_MAXTRACKDATASIZE; 2262 aMaxQueueDepth = TIMEDTEXT_MAXTRACKQUEUEDEPTH; 2263 } 2264 else 2265 { 2266 aMaxDataSize = UNKNOWN_MAXTRACKDATASIZE; 2267 aMaxQueueDepth = UNKNOWN_MAXTRACKQUEUEDEPTH; 2268 } 2269 } 2270 2271 2272 PVMFStatus PVMFMP4FFParserNode::DoReleasePort(PVMFMP4FFParserNodeCommand& aCmd) 2273 { 2274 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoReleasePort() In")); 2275 2276 LogDiagnostics(); 2277 //Find the port in the port vector 2278 PVMFPortInterface* port; 2279 aCmd.PVMFMP4FFParserNodeCommandBase::Parse(port); 2280 2281 // Remove the selected track from the track list 2282 int32 i = 0; 2283 int32 maxtrack = iNodeTrackPortList.size(); 2284 while (i < maxtrack) 2285 { 2286 if (iNodeTrackPortList[i].iPortInterface == port) 2287 { 2288 // Found the element. So erase it 2289 iNodeTrackPortList[i].iMediaData.Unbind(); 2290 if (iNodeTrackPortList[i].iPortInterface) 2291 { 2292 OSCL_DELETE(((PVMFMP4FFParserOutPort*)iNodeTrackPortList[i].iPortInterface)); 2293 } 2294 if (iNodeTrackPortList[i].iClockConverter) 2295 { 2296 OSCL_DELETE(iNodeTrackPortList[i].iClockConverter); 2297 } 2298 if (iNodeTrackPortList[i].iTrackDataMemoryPool) 2299 { 2300 iNodeTrackPortList[i].iTrackDataMemoryPool->CancelFreeChunkAvailableCallback(); 2301 iNodeTrackPortList[i].iTrackDataMemoryPool->removeRef(); 2302 iNodeTrackPortList[i].iTrackDataMemoryPool = NULL; 2303 } 2304 if (iNodeTrackPortList[i].iMediaDataImplAlloc) 2305 { 2306 OSCL_DELETE(iNodeTrackPortList[i].iMediaDataImplAlloc); 2307 } 2308 if (iNodeTrackPortList[i].iTextMediaDataImplAlloc) 2309 { 2310 OSCL_DELETE(iNodeTrackPortList[i].iTextMediaDataImplAlloc); 2311 } 2312 if (iNodeTrackPortList[i].iMediaDataMemPool) 2313 { 2314 iNodeTrackPortList[i].iMediaDataMemPool->CancelFreeChunkAvailableCallback(); 2315 iNodeTrackPortList[i].iMediaDataMemPool->removeRef(); 2316 } 2317 if (iNodeTrackPortList[i].iMediaDataGroupAlloc) 2318 { 2319 iNodeTrackPortList[i].iMediaDataGroupAlloc->removeRef(); 2320 } 2321 if (iNodeTrackPortList[i].iMediaDataGroupImplMemPool) 2322 { 2323 iNodeTrackPortList[i].iMediaDataGroupImplMemPool->removeRef(); 2324 } 2325 if (iPortDataLog) 2326 { 2327 if (iNodeTrackPortList[i].iBinAppenderPtr.GetRep() != NULL) 2328 { 2329 iNodeTrackPortList[i].iPortLogger->RemoveAppender(iNodeTrackPortList[i].iBinAppenderPtr); 2330 iNodeTrackPortList[i].iBinAppenderPtr.Unbind(); 2331 } 2332 } 2333 iNodeTrackPortList.erase(iNodeTrackPortList.begin() + i); 2334 return PVMFSuccess; 2335 } 2336 ++i; 2337 } 2338 2339 if (i >= maxtrack) 2340 { 2341 return PVMFErrBadHandle; 2342 } 2343 2344 // Unknown port 2345 return PVMFFailure; 2346 } 2347 2348 2349 PVMFStatus PVMFMP4FFParserNode::InitOMA2DRMInfo() 2350 { 2351 if (iMP4FileHandle == NULL) 2352 { 2353 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::InitOMA2DRMInfo - Invalid iMP4FileHandle")); 2354 return PVMFErrNoResources; 2355 } 2356 2357 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 2358 { 2359 if (iOMA2DecryptionBuffer == NULL) 2360 { 2361 iOMA2DecryptionBuffer = OSCL_ARRAY_NEW(uint8, PVMP4FF_OMA2_DECRYPTION_BUFFER_SIZE); 2362 } 2363 2364 int32 iNumTracks = iMP4FileHandle->getNumTracks(); 2365 uint32 iIdList[16]; 2366 if (iNumTracks != iMP4FileHandle->getTrackIDList(iIdList, iNumTracks)) 2367 { 2368 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::InitOMA2DRMInfo - Couldnt Get Track List")); 2369 return PVMFFailure; 2370 } 2371 2372 for (int32 i = 0; i < iNumTracks; i++) 2373 { 2374 uint32 trackID = iIdList[i]; 2375 PVMP4FFNodeTrackOMA2DRMInfo oma2TrackInfo; 2376 oma2TrackInfo.iTrackId = trackID; 2377 uint32 odkmBoxSize = iMP4FileHandle->getTrackLevelOMA2DRMInfoSize(trackID); 2378 uint8* odkmBox = iMP4FileHandle->getTrackLevelOMA2DRMInfo(trackID); 2379 if (odkmBoxSize > 0) 2380 { 2381 MediaMetaInfo info; 2382 uint32 numSamples = 1; 2383 int32 retval = EVERYTHING_FINE; 2384 retval = iMP4FileHandle->peekNextBundledAccessUnits(trackID, 2385 &numSamples, 2386 &info); 2387 if ((retval == EVERYTHING_FINE || END_OF_TRACK == retval) && numSamples > 0) 2388 { 2389 uint32 sampleSize = info.len; 2390 if (sampleSize > 0) 2391 { 2392 uint8* sampleBuf = OSCL_ARRAY_NEW(uint8, (sizeof(sampleSize) + 2393 sampleSize + 2394 sizeof(odkmBoxSize) + 2395 odkmBoxSize)); 2396 uint8* destBuf = sampleBuf; 2397 oscl_memcpy((OsclAny*)destBuf, (const OsclAny*)(&odkmBoxSize), sizeof(odkmBoxSize)); 2398 destBuf += sizeof(odkmBoxSize); 2399 oscl_memcpy((OsclAny*)destBuf, (const OsclAny*)(odkmBox), odkmBoxSize); 2400 destBuf += odkmBoxSize; 2401 oscl_memcpy((OsclAny*)destBuf, (const OsclAny*)(&sampleSize), sizeof(sampleSize)); 2402 destBuf += sizeof(sampleSize); 2403 2404 oscl_memset(&iGau.buf, 0, sizeof(iGau.buf)); 2405 oscl_memset(&iGau.info, 0, sizeof(iGau.info)); 2406 iGau.free_buffer_states_when_done = 0; 2407 iGau.numMediaSamples = 1; 2408 iGau.buf.num_fragments = 1; 2409 iGau.buf.buf_states[0] = NULL; 2410 iGau.buf.fragments[0].ptr = (OsclAny*)destBuf; 2411 iGau.buf.fragments[0].len = sampleSize; 2412 retval = 2413 iMP4FileHandle->getNextBundledAccessUnits(trackID, 2414 &numSamples, 2415 &iGau); 2416 iMP4FileHandle->resetPlayback(); 2417 2418 oma2TrackInfo.iDRMInfoSize = (sizeof(sampleSize) + sampleSize + 2419 sizeof(odkmBoxSize) + odkmBoxSize); 2420 oma2TrackInfo.iDRMInfo = sampleBuf; 2421 } 2422 } 2423 } 2424 iOMA2DRMInfoVec.push_back(oma2TrackInfo); 2425 } 2426 } 2427 return PVMFSuccess; 2428 } 2429 2430 2431 PVMFStatus PVMFMP4FFParserNode::DoInit(PVMFMP4FFParserNodeCommand& aCmd) 2432 { 2433 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoInitNode() In")); 2434 2435 OSCL_UNUSED_ARG(aCmd); 2436 2437 if (iInterfaceState != EPVMFNodeIdle) 2438 { 2439 // Wrong state 2440 return PVMFErrInvalidState; 2441 } 2442 2443 if (iCPM) 2444 { 2445 /* 2446 * Go thru CPM commands before parsing the file 2447 * - Init CPM 2448 * - Open Session 2449 * - Register Content 2450 * - Get Content Type 2451 * - Approve Usage 2452 */ 2453 if (oWaitingOnLicense == false) 2454 { 2455 InitCPM(); 2456 } 2457 else 2458 { 2459 if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) || 2460 (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS)) 2461 { 2462 RequestUsage(NULL); 2463 } 2464 else if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 2465 { 2466 PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL; 2467 if (CheckForOMA2AuthorizationComplete(oma2trackInfo) == PVMFPending) 2468 { 2469 RequestUsage(oma2trackInfo); 2470 } 2471 } 2472 } 2473 return PVMFPending; 2474 } 2475 else 2476 { 2477 return (CheckForMP4HeaderAvailability()); 2478 } 2479 } 2480 2481 bool PVMFMP4FFParserNode::ParseMP4File(PVMFMP4FFParserNodeCmdQueue& aCmdQ, 2482 PVMFMP4FFParserNodeCommand& aCmd) 2483 { 2484 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ParseMP4File() In")); 2485 2486 bool oRet = false; 2487 PVUuid eventuuid; 2488 PVMFStatus eventcode; 2489 2490 PVMF_MP4FFPARSERNODE_LOGINFO((0, "IMpeg4File::readMP4File - iCPMContentAccessFactory = 0x%x", iCPMContentAccessFactory)); 2491 PVMF_MP4FFPARSERNODE_LOGINFO((0, "IMpeg4File::readMP4File - iFileHandle = 0x%x", iFileHandle)); 2492 PVMF_MP4FFPARSERNODE_LOGINFO((0, "IMpeg4File::readMP4File - iParsingMode = 0x%x", iParsingMode)); 2493 2494 uint32 currticks = OsclTickCount::TickCount(); 2495 uint32 StartTime = OsclTickCount::TicksToMsec(currticks); 2496 2497 PVMFDataStreamFactory* dsFactory = iCPMContentAccessFactory; 2498 if ((dsFactory == NULL) && (iDataStreamFactory != NULL)) 2499 { 2500 dsFactory = iDataStreamFactory; 2501 } 2502 2503 iMP4FileHandle = IMpeg4File::readMP4File(iFilename, 2504 dsFactory, 2505 iFileHandle, 2506 iParsingMode, 2507 &iFileServer); 2508 2509 currticks = OsclTickCount::TickCount(); 2510 uint32 EndTime = OsclTickCount::TicksToMsec(currticks); 2511 2512 iTimeTakenInReadMP4File = EndTime - StartTime; 2513 2514 if (iMP4FileHandle == NULL) 2515 { 2516 PVMF_MP4FFPARSERNODE_LOGERROR((0, "IMpeg4File::readMP4File returns NULL")); 2517 CommandComplete(aCmdQ, 2518 aCmd, 2519 PVMFErrNoMemory, 2520 NULL, NULL, NULL); 2521 return oRet; 2522 } 2523 2524 if (!iMP4FileHandle->MP4Success()) 2525 { 2526 int32 mp4errcode = iMP4FileHandle->GetMP4Error(); 2527 PVMF_MP4FFPARSERNODE_LOGERROR((0, "IMpeg4File::readMP4File Failed - Err=%d", mp4errcode)); 2528 if (!MapMP4ErrorCodeToEventCode(mp4errcode, eventuuid, eventcode)) 2529 { 2530 eventuuid = PVMFFileFormatEventTypesUUID; 2531 eventcode = PVMFFFErrMisc; 2532 } 2533 2534 IMpeg4File::DestroyMP4FileObject(iMP4FileHandle); 2535 2536 iMP4FileHandle = NULL; 2537 2538 CommandComplete(aCmdQ, 2539 aCmd, 2540 PVMFErrResource, 2541 NULL, 2542 &eventuuid, 2543 &eventcode); 2544 return oRet; 2545 } 2546 if (iExternalDownload == true) 2547 { 2548 oRet = iMP4FileHandle->CreateDataStreamSessionForExternalDownload(iFilename, 2549 dsFactory, 2550 iFileHandle, 2551 &iFileServer); 2552 if (!oRet) 2553 return oRet; 2554 } 2555 2556 PVMFStatus status = InitMetaData(); 2557 2558 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 2559 { 2560 status = InitOMA2DRMInfo(); 2561 if (status == PVMFSuccess) 2562 { 2563 oRet = true; 2564 } 2565 } 2566 else 2567 { 2568 if (status == PVMFSuccess) 2569 { 2570 oRet = true; 2571 } 2572 2573 CommandComplete(aCmdQ, 2574 aCmd, 2575 status, 2576 NULL, 2577 NULL, 2578 NULL); 2579 } 2580 return oRet; 2581 } 2582 2583 void PVMFMP4FFParserNode::CompleteInit(PVMFMP4FFParserNodeCmdQueue& aCmdQ, 2584 PVMFMP4FFParserNodeCommand& aCmd) 2585 { 2586 if (iCPM) 2587 { 2588 if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) || 2589 (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS)) 2590 { 2591 if (iApprovedUsage.value.uint32_value != 2592 iRequestedUsage.value.uint32_value) 2593 { 2594 if (iCPMSourceData.iIntent & BITMASK_PVMF_SOURCE_INTENT_GETMETADATA) 2595 { 2596 CommandComplete(aCmdQ, 2597 aCmd, 2598 PVMFSuccess, 2599 NULL, NULL, NULL); 2600 return; 2601 } 2602 else 2603 { 2604 CommandComplete(aCmdQ, 2605 aCmd, 2606 PVMFErrAccessDenied, 2607 NULL, NULL, NULL); 2608 return; 2609 } 2610 } 2611 else 2612 { 2613 ParseMP4File(aCmdQ, aCmd); 2614 } 2615 } 2616 else if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 2617 { 2618 if (iCPMSourceData.iIntent & BITMASK_PVMF_SOURCE_INTENT_GETMETADATA) 2619 { 2620 CommandComplete(aCmdQ, 2621 aCmd, 2622 PVMFSuccess, 2623 NULL, NULL, NULL); 2624 return; 2625 } 2626 else 2627 { 2628 if (CheckForOMA2UsageApproval() == true) 2629 { 2630 PVUuid uuid = PVMFCPMPluginDecryptionInterfaceUuid; 2631 PVInterface* intf = 2632 iCPMContentAccessFactory->CreatePVMFCPMPluginAccessInterface(uuid); 2633 PVMFCPMPluginAccessInterface* interimPtr = 2634 OSCL_STATIC_CAST(PVMFCPMPluginAccessInterface*, intf); 2635 iDecryptionInterface = OSCL_STATIC_CAST(PVMFCPMPluginAccessUnitDecryptionInterface*, interimPtr); 2636 if (iDecryptionInterface != NULL) 2637 { 2638 iDecryptionInterface->Init(); 2639 CommandComplete(aCmdQ, 2640 aCmd, 2641 PVMFSuccess, 2642 NULL, NULL, NULL); 2643 return; 2644 } 2645 } 2646 CommandComplete(aCmdQ, 2647 aCmd, 2648 PVMFErrAccessDenied, 2649 NULL, NULL, NULL); 2650 } 2651 } 2652 else 2653 { 2654 /* CPM doesnt care about MP4 / 3GP files */ 2655 ParseMP4File(aCmdQ, aCmd); 2656 } 2657 } 2658 else 2659 { 2660 ParseMP4File(aCmdQ, aCmd); 2661 } 2662 return; 2663 } 2664 2665 PVMFStatus PVMFMP4FFParserNode::DoPrepare(PVMFMP4FFParserNodeCommand& /*aCmd*/) 2666 { 2667 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoPrepareNode() In")); 2668 2669 if (iInterfaceState != EPVMFNodeInitialized) 2670 { 2671 return PVMFErrInvalidState; 2672 } 2673 /* Do initial buffering in case of PDL / FT or in case of External Download */ 2674 if ((iExternalDownload == true) && (iMP4FileHandle != NULL)) 2675 { 2676 uint32 offset = 0; 2677 PVMFStatus status = GetFileOffsetForAutoResume(offset, false); 2678 if (status == PVMFSuccess) 2679 { 2680 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoPrepare - Calling RequestReadCapacityNotification With Offset=%d", offset)); 2681 //Request for callback 2682 MP4_ERROR_CODE retVal = 2683 iMP4FileHandle->RequestReadCapacityNotification(*this, offset); 2684 if (retVal == EVERYTHING_FINE) 2685 { 2686 // parser node will not report underflow in this case but will set the 2687 // variables so that data ready event can be send to engine once datastream 2688 // downloads requested data. 2689 autopaused = true; 2690 iUnderFlowEventReported = true; 2691 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoPrepare - Holding off on Prepare Complete because of Insufficient Downloaded Data")); 2692 return PVMFPending; 2693 } 2694 else if (retVal == SUFFICIENT_DATA_IN_FILE) 2695 { 2696 // report prepare success and send data ready event to engine. 2697 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoPrepare - Sufficient data in file, send success and data ready event")); 2698 ReportMP4FFParserInfoEvent(PVMFInfoDataReady); 2699 return PVMFSuccess; 2700 } 2701 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::DoPrepare - RequestReadCapacityNotification Failed - Ret=%d", retVal)); 2702 } 2703 else 2704 { 2705 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::DoPrepare - GetFileOffsetForAutoResume Failed - Status=%d", status)); 2706 } 2707 return PVMFErrArgument; 2708 } 2709 else 2710 { 2711 if ((download_progress_interface != NULL) && (iDownloadComplete == false) && (iFastTrackSession == false)) 2712 { 2713 if (0 == iLastNPTCalcInConvertSizeToTime) 2714 { 2715 uint32 ts = 0; 2716 2717 if ((NULL != iDataStreamInterface) && (0 != iDataStreamInterface->QueryBufferingCapacity())) 2718 { 2719 uint32 bytesReady = 0; 2720 PvmiDataStreamStatus status = iDataStreamInterface->QueryReadCapacity(iDataStreamSessionID, bytesReady); 2721 if (status == PVDS_END_OF_STREAM) 2722 { 2723 return PVMFSuccess; 2724 } 2725 // if progressive streaming, playResumeNotifcation is guaranteed to be called 2726 // with the proper download complete state, ignore the current download status 2727 bool dlcomplete = false; 2728 download_progress_interface->requestResumeNotification(ts, dlcomplete); 2729 } 2730 else 2731 { 2732 download_progress_interface->requestResumeNotification(ts, iDownloadComplete); 2733 } 2734 autopaused = true; 2735 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoPrepare() - Auto Pause Triggered, TS = %d", ts)); 2736 } 2737 } 2738 } 2739 return PVMFSuccess; 2740 } 2741 2742 void PVMFMP4FFParserNode::CompletePrepare(PVMFStatus aStatus) 2743 { 2744 CommandComplete(iCurrentCommand, iCurrentCommand.front(), aStatus); 2745 } 2746 2747 2748 PVMFStatus PVMFMP4FFParserNode::DoStart(PVMFMP4FFParserNodeCommand& /*aCmd*/) 2749 { 2750 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoStartNode() In")); 2751 if (iInterfaceState != EPVMFNodePrepared && 2752 iInterfaceState != EPVMFNodePaused) 2753 { 2754 return PVMFErrInvalidState; 2755 } 2756 2757 // If resuming, do not reset the auto-pause variables 2758 // parser node should send InfoReadyEvent to Engine 2759 // if in underflow condition. 2760 2761 return PVMFSuccess; 2762 } 2763 2764 2765 PVMFStatus PVMFMP4FFParserNode::DoStop(PVMFMP4FFParserNodeCommand& aCmd) 2766 { 2767 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoStopNode() In")); 2768 OSCL_UNUSED_ARG(aCmd); 2769 2770 LogDiagnostics(); 2771 iStreamID = 0; 2772 if (iInterfaceState != EPVMFNodeStarted && 2773 iInterfaceState != EPVMFNodePaused) 2774 { 2775 return PVMFErrInvalidState; 2776 } 2777 2778 // stop and reset position to beginning 2779 ResetAllTracks(); 2780 2781 // reset direction rate state variables 2782 iPlayBackDirection = PVMF_DATA_SOURCE_DIRECTION_FORWARD; 2783 iParseAudioDuringFF = false; 2784 iParseAudioDuringREW = false; 2785 iParseVideoOnly = false; 2786 iDataRate = NORMAL_PLAYRATE; 2787 2788 // Reset the MP4 FF to beginning 2789 if (iMP4FileHandle) 2790 { 2791 for (uint32 i = 0; i < iNodeTrackPortList.size(); i++) 2792 { 2793 iNodeTrackPortList[i].iTimestamp = 0; 2794 } 2795 iMP4FileHandle->resetPlayback(); 2796 } 2797 2798 return PVMFSuccess; 2799 } 2800 2801 2802 PVMFStatus PVMFMP4FFParserNode::DoFlush(PVMFMP4FFParserNodeCommand& aCmd) 2803 { 2804 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoFlushNode() In")); 2805 2806 OSCL_UNUSED_ARG(aCmd); 2807 2808 if (iInterfaceState != EPVMFNodeStarted && 2809 iInterfaceState != EPVMFNodePaused) 2810 { 2811 return PVMFErrInvalidState; 2812 } 2813 2814 //the flush is asynchronous. Completion is detected in the Run. 2815 //Make sure the AO is active to finish the flush.. 2816 RunIfNotReady(); 2817 return PVMFPending; 2818 } 2819 2820 2821 bool PVMFMP4FFParserNode::FlushPending() 2822 { 2823 return (iCurrentCommand.size() > 0 && iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH); 2824 } 2825 2826 2827 PVMFStatus PVMFMP4FFParserNode::DoPause(PVMFMP4FFParserNodeCommand& aCmd) 2828 { 2829 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoPauseNode() In")); 2830 2831 OSCL_UNUSED_ARG(aCmd); 2832 2833 if (iInterfaceState != EPVMFNodeStarted) 2834 { 2835 return PVMFErrInvalidState; 2836 } 2837 2838 if (!iUnderFlowEventReported && iExternalDownload) 2839 { 2840 /* 2841 * Since sourcenode is in paused state, so .. 2842 * Reset all PS related variable, 2843 * Cancel the underflow timer so that no underflow event could be sent in paused state, 2844 * Set all tracks state to GETDATA. 2845 */ 2846 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DoPause() - SN is paused, cancel UF timer, reset all PS variables")); 2847 for (uint32 i = 0; i < iNodeTrackPortList.size(); ++i) 2848 { 2849 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 2850 } 2851 autopaused = false; 2852 iUnderFlowCheckTimer->Cancel(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID); 2853 2854 // Cancel any DS callback since Sourcenode is Paused. 2855 MP4_ERROR_CODE retVal = iMP4FileHandle->CancelNotificationSync(); 2856 2857 if (retVal != EVERYTHING_FINE) 2858 { 2859 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DoPause() - Error in Cancelling, Logging this.")); 2860 OSCL_ASSERT(retVal); 2861 } 2862 2863 } 2864 return PVMFSuccess; 2865 } 2866 2867 2868 PVMFStatus PVMFMP4FFParserNode::DoReset(PVMFMP4FFParserNodeCommand& aCmd) 2869 { 2870 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoResetNode() In")); 2871 2872 OSCL_UNUSED_ARG(aCmd); 2873 2874 LogDiagnostics(); 2875 2876 //remove the clock observer 2877 if (iClientPlayBackClock != NULL) 2878 { 2879 if (iClockNotificationsInf != NULL) 2880 { 2881 iClockNotificationsInf->RemoveClockStateObserver(*this); 2882 iClientPlayBackClock->DestroyMediaClockNotificationsInterface(iClockNotificationsInf); 2883 iClockNotificationsInf = NULL; 2884 } 2885 } 2886 2887 if (iUnderFlowCheckTimer != NULL) 2888 { 2889 iUnderFlowCheckTimer->Clear(); 2890 } 2891 2892 // reset direction rate state variables 2893 iPlayBackDirection = PVMF_DATA_SOURCE_DIRECTION_FORWARD; 2894 iParseAudioDuringFF = false; 2895 iParseAudioDuringREW = false; 2896 iParseVideoOnly = false; 2897 iDataRate = NORMAL_PLAYRATE; 2898 2899 if (download_progress_interface != NULL) 2900 { 2901 download_progress_interface->cancelResumeNotification(); 2902 } 2903 2904 if (iMP4FileHandle != NULL) 2905 { 2906 /* Indicates that the init was successfull */ 2907 if (iCPM) 2908 { 2909 if (iProtectedFile == false) 2910 { 2911 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::DoReset - Unprotected Content - Skipping Usage Complete - Doing CPM Reset")); 2912 ResetCPM(); 2913 } 2914 else 2915 { 2916 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 2917 { 2918 ResetOMA2Flags(); 2919 } 2920 SendUsageComplete(); 2921 } 2922 return PVMFPending; 2923 } 2924 else 2925 { 2926 ReleaseAllPorts(); 2927 CleanupFileSource(); 2928 iSelectedTrackInfoList.clear(); 2929 SetState(EPVMFNodeIdle); 2930 return PVMFSuccess; 2931 2932 } 2933 } 2934 else 2935 { 2936 /* 2937 * Reset without init completing, so just reset the parser node, 2938 * no CPM stuff necessary 2939 */ 2940 return PVMFSuccess; 2941 2942 } 2943 } 2944 2945 void PVMFMP4FFParserNode::CompleteReset(PVMFMP4FFParserNodeCmdQueue& aCmdQ, PVMFMP4FFParserNodeCommand& aCmd) 2946 { 2947 // stop and cleanup 2948 // release the download_progress_clock if any 2949 download_progress_clock.Unbind(); 2950 // release the download progress interface if any 2951 if (download_progress_interface) 2952 { 2953 download_progress_interface->removeRef(); 2954 download_progress_interface = NULL; 2955 } 2956 autopaused = false; 2957 iDownloadFileSize = 0; 2958 2959 ReleaseAllPorts(); 2960 CleanupFileSource(); 2961 iSelectedTrackInfoList.clear(); 2962 2963 CommandComplete(aCmdQ, aCmd, PVMFSuccess); 2964 2965 return; 2966 } 2967 2968 2969 PVMFStatus PVMFMP4FFParserNode::DoCancelAllCommands(PVMFMP4FFParserNodeCommand& /*aCmd*/) 2970 { 2971 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoCancelAllCommands() In")); 2972 2973 // The "current command" queue is used to hold different asynchronous commands 2974 // 1) Init command during Local Playback or when there is no DS cmd pending, we will have to wait for 2975 // CPM to be initalised. All asynchronous CPM cmds needs to be completed to complete Init. 2976 // 2) Init command when partial MOOV is downlaoded during PDL and PS - can be cancelled. 2977 // 3) Prepare command when parser node requests for 4 secs of data to datastream before 2978 // sending prepare complete - can be cancelled. 2979 if (!iCurrentCommand.empty()) 2980 { 2981 PVMFStatus retVal = PVMFSuccess; 2982 retVal = DoCancelCurrentCommand(iCurrentCommand[0]); 2983 if (retVal == PVMFPending) 2984 { 2985 return retVal; 2986 } 2987 } 2988 2989 //cancel all queued commands 2990 //start at element 1 since this cancel command is element 0. 2991 while (iInputCommands.size() > 1) 2992 { 2993 CommandComplete(iInputCommands, iInputCommands[1], PVMFErrCancelled); 2994 } 2995 2996 return PVMFSuccess; 2997 } 2998 2999 3000 PVMFStatus PVMFMP4FFParserNode::DoCancelCommand(PVMFMP4FFParserNodeCommand& aCmd) 3001 { 3002 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoCancelCommand() In")); 3003 3004 //extract the command ID from the parameters. 3005 PVMFCommandId id; 3006 aCmd.PVMFMP4FFParserNodeCommandBase::Parse(id); 3007 3008 //first check "current" command if any 3009 PVMFMP4FFParserNodeCommand* cmd = iCurrentCommand.FindById(id); 3010 // The "current command" queue is used to hold different asynchronous commands 3011 // 1) Init command during Local Playback or when there is no DS cmd pending, we will have to wait for 3012 // CPM to be initalised. All asynchronous CPM cmds needs to be completed to complete Init. 3013 // 2) Init command when partial MOOV is downlaoded during PDL and PS - can be cancelled. 3014 // 3) Prepare command when parser node requests for 4 secs of data to datastream before 3015 // sending prepare complete - can be cancelled. 3016 if (cmd) 3017 { 3018 PVMFStatus retVal = PVMFSuccess; 3019 retVal = DoCancelCurrentCommand(*cmd); 3020 if (retVal == PVMFPending) 3021 { 3022 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoCancelCommand() Return Pending")); 3023 return retVal; 3024 } 3025 } 3026 3027 //next check input queue. 3028 //start at element 1 since this cancel command is element 0. 3029 cmd = iInputCommands.FindById(id, 1); 3030 if (cmd) 3031 { 3032 //cancel the queued command 3033 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled); 3034 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoCancelCommand() Return Success")); 3035 //report cancel success 3036 return PVMFSuccess; 3037 } 3038 3039 //if we get here the command isn't queued so the cancel fails. 3040 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoCancelCommand() Return Failure")); 3041 return PVMFSuccess; 3042 } 3043 3044 PVMFStatus PVMFMP4FFParserNode::DoCancelCurrentCommand(PVMFMP4FFParserNodeCommand& aCmd) 3045 { 3046 if (aCmd.iCmd == PVMF_GENERIC_NODE_INIT) 3047 { 3048 if (iDataStreamInterface != NULL) 3049 { 3050 if (iCPMSequenceInProgress) 3051 { 3052 return PVMFPending; 3053 } 3054 if (iProgressivelyDownlodable == true && iDataStreamRequestPending) 3055 { 3056 // send a cancel notification to datastream module. 3057 iDataStreamRequestPending = false; 3058 3059 PvmiDataStreamStatus retVal = iDataStreamInterface->CancelNotificationSync(iDataStreamSessionID); 3060 3061 if (retVal == PVDS_SUCCESS) 3062 { 3063 // Complete Init as cancelled. 3064 CommandComplete(iCurrentCommand, aCmd, PVMFErrCancelled); 3065 } 3066 else 3067 { 3068 // Not a valid DataStream Session, Complete Init as failure. 3069 CommandComplete(iCurrentCommand, aCmd, PVMFFailure); 3070 } 3071 } 3072 else if (download_progress_interface != NULL && iProgressivelyDownlodable == false) 3073 { 3074 // call cancel resume notification and complete Init as cancelled. 3075 download_progress_interface->cancelResumeNotification(); 3076 CommandComplete(iCurrentCommand, aCmd, PVMFErrCancelled); 3077 } 3078 else 3079 { 3080 // wait on cpm commands completion. 3081 return PVMFPending; 3082 } 3083 } 3084 else 3085 { 3086 // wait on cpm commands completion. 3087 return PVMFPending; 3088 } 3089 } 3090 else if (aCmd.iCmd == PVMF_GENERIC_NODE_PREPARE) 3091 { 3092 if (autopaused) 3093 { 3094 autopaused = false; 3095 // Prepare in case of PDL would complete imediately, only case need to be handled here 3096 // is for Pseudo Streaming. There will no command in current queue in case of PDL so no 3097 // cancel. 3098 if ((iExternalDownload == true) && (iMP4FileHandle != NULL)) 3099 { 3100 //Cancel the callback 3101 MP4_ERROR_CODE retVal = iMP4FileHandle->CancelNotificationSync(); 3102 3103 if (retVal == EVERYTHING_FINE) 3104 { 3105 // Complete Prepare as cancelled. 3106 CommandComplete(iCurrentCommand, aCmd, PVMFErrCancelled); 3107 } 3108 else 3109 { 3110 // Not a valid DataStream Session, Complete Prepare as failure. 3111 CommandComplete(iCurrentCommand, aCmd, PVMFFailure); 3112 } 3113 } 3114 } 3115 } 3116 else 3117 { 3118 return PVMFPending; 3119 } 3120 return PVMFSuccess; 3121 } 3122 3123 PVMFStatus PVMFMP4FFParserNode::DoSetDataSourcePosition(PVMFMP4FFParserNodeCommand& aCmd, PVMFStatus &aEventCode, PVUuid &aEventUuid) 3124 { 3125 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() In")); 3126 3127 aEventCode = PVMFSuccess; 3128 3129 int32 err = 0; 3130 uint32* trackList = NULL; 3131 uint32 i = 0; 3132 OSCL_TRY(err, trackList = OSCL_ARRAY_NEW(uint32, MAX_TRACK_NO);); 3133 OSCL_FIRST_CATCH_ANY(err, return PVMFErrNoMemory); 3134 for (i = 0; i < MAX_TRACK_NO; i++) 3135 { 3136 trackList[i] = 0; // MPEG4 Specification: TrackId will start from 1. Init to 0 is OK. 3137 } 3138 if (!trackList || iNodeTrackPortList.empty()) 3139 { 3140 OSCL_ARRAY_DELETE(trackList); 3141 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Memory for track list could not be allocated or no tracks to position")); 3142 return PVMFFailure; 3143 } 3144 3145 // if progressive streaming, reset download complete flag 3146 if ((NULL != iDataStreamInterface) && (0 != iDataStreamInterface->QueryBufferingCapacity())) 3147 { 3148 iDownloadComplete = false; 3149 } 3150 3151 uint32 targetNPT = 0; 3152 uint32* actualNPT = NULL; 3153 uint32* actualMediaDataTS = NULL; 3154 bool seektosyncpoint = false; 3155 uint32 streamID = 0; 3156 3157 aCmd.PVMFMP4FFParserNodeCommand::Parse(targetNPT, actualNPT, actualMediaDataTS, seektosyncpoint, streamID); 3158 3159 // Validate the parameters 3160 if (actualNPT == NULL || actualMediaDataTS == NULL) 3161 { 3162 OSCL_ARRAY_DELETE(trackList); 3163 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Invalid parameters")); 3164 return PVMFErrArgument; 3165 } 3166 3167 for (i = 0; i < iNodeTrackPortList.size(); ++i) 3168 { 3169 iNodeTrackPortList[i].iSendBOS = true; 3170 } 3171 //save the stream id for next media segment 3172 iStreamID = streamID; 3173 3174 // this will guarantee that reverse mode starts from a valid TS 3175 if (PVMF_DATA_SOURCE_DIRECTION_REVERSE == iPlayBackDirection) 3176 { 3177 iStartForNextTSSearch = targetNPT; 3178 for (uint32 i = 0; i < iNodeTrackPortList.size(); i++) 3179 { 3180 if (iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_VISUAL) 3181 { 3182 iPrevSampleTS = iMP4FileHandle->getMediaTimestampForCurrentSample(iNodeTrackPortList[i].iTrackId); 3183 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 3184 } 3185 } 3186 } 3187 // First check if MP4 file is being downloaded to make sure the requested position is before amount downloaded 3188 if (download_progress_clock.GetRep()) 3189 { 3190 // Get the amount downloaded so far 3191 bool tmpbool = false; 3192 uint32 dltime = 0; 3193 download_progress_clock->GetCurrentTime32(dltime, tmpbool, PVMF_MEDIA_CLOCK_MSEC); 3194 // Check if the requested time is past that 3195 if (targetNPT >= dltime) 3196 { 3197 // For now, fail in this case. In future, we might want to reposition to somewhere valid. 3198 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Positioning past the amount downloaded so return as argument error")); 3199 OSCL_ARRAY_DELETE(trackList); 3200 return PVMFErrArgument; 3201 } 3202 } 3203 3204 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() TargetNPT %d, SeekToSyncPoint %d", targetNPT, seektosyncpoint)); 3205 3206 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() TargetNPT %d, SeekToSyncPoint %d", targetNPT, seektosyncpoint)); 3207 3208 // The media data timestamp of the next sample will start from the maximum 3209 // of timestamp on all selected tracks. This media data timestamp will 3210 // correspond to the actual NPT. 3211 // The media data timestamp of the next sample will start from the maximum of timestamp on all 3212 // selected tracks. This media data timestamp will correspond to the actual NPT. 3213 MediaMetaInfo info; 3214 3215 i = 0; 3216 *actualMediaDataTS = 0; 3217 for (i = 0; i < iNodeTrackPortList.size(); i++) 3218 { 3219 // Save the track list while in this loop 3220 // trackList[i] = iNodeTrackPortList[i].iTrackId; 3221 3222 // This is no need to peek to get the prev sample duration. 3223 // Previous gets acct for time stamp deltas of all retrieved samples 3224 3225 // For end-of-track case where there is no more samples to peek, the timestamp should be past the 3226 // last valid sample so there is no need to advance to the timestamp 3227 3228 // Retrieve the next timestamp for this track 3229 iNodeTrackPortList[i].iClockConverter->set_clock(iNodeTrackPortList[i].iTimestamp, 0); 3230 uint32 millisecTS = iNodeTrackPortList[i].iClockConverter->get_converted_ts(1000); 3231 3232 // Actual media data TS is the max timestamp of all selected tracks 3233 if (millisecTS > *actualMediaDataTS) 3234 { 3235 *actualMediaDataTS = millisecTS; 3236 } 3237 3238 // There could be more than 3 TRAK per MOOV, above loop takes first encountered different traks 3239 // into account and store the trackList[0];trackList[1];trackList[2] as video, audio and text. 3240 // even if some any track are not present the index are kept as it is. 3241 if ((iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_VISUAL) 3242 && (0 == trackList[0])) 3243 { 3244 trackList[0] = iNodeTrackPortList[i].iTrackId; 3245 } 3246 3247 if ((iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_AUDIO) 3248 && (0 == trackList[1])) 3249 { 3250 trackList[1] = iNodeTrackPortList[i].iTrackId; 3251 } 3252 3253 if ((iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_TEXT) 3254 && (0 == trackList[2])) 3255 { 3256 trackList[2] = iNodeTrackPortList[i].iTrackId; 3257 } 3258 } 3259 uint64 duration64 = iMP4FileHandle->getMovieDuration(); 3260 uint32 durationms = 0; 3261 uint32 duration = durationms = Oscl_Int64_Utils::get_uint64_lower32(duration64); 3262 uint32 timescale = iMP4FileHandle->getMovieTimescale(); 3263 if (timescale > 0 && timescale != 1000) 3264 { 3265 // Convert to milliseconds 3266 MediaClockConverter mcc(timescale); 3267 mcc.update_clock(duration); 3268 durationms = mcc.get_converted_ts(1000); 3269 } 3270 if ((targetNPT >= durationms) && (PVMF_DATA_SOURCE_DIRECTION_REVERSE != iPlayBackDirection)) 3271 { 3272 //report EOT for all streams. 3273 for (i = 0; i < iNodeTrackPortList.size(); i++) 3274 { 3275 uint32 resetNPT = 0; 3276 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 3277 // reset all tracks to zero. 3278 resetNPT = iMP4FileHandle->resetPlayback(0, (uint16)TRACK_NO_PER_RESET_PLAYBACK_CALL, 3279 &trackList[i], seektosyncpoint); 3280 iNodeTrackPortList[i].iClockConverter->set_clock_other_timescale(*actualMediaDataTS, 1000); 3281 iNodeTrackPortList[i].iTimestamp = iNodeTrackPortList[i].iClockConverter->get_current_timestamp(); 3282 } 3283 3284 // Cancel callback notifications on Datastream 3285 if (autopaused || iExternalDownload) 3286 { 3287 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition Cancel notification callback")); 3288 autopaused = false; 3289 if (download_progress_interface != NULL && iDataStreamInterface != NULL) 3290 { 3291 download_progress_interface->cancelResumeNotification(); 3292 } 3293 else if (iExternalDownload) 3294 { 3295 // Cancel the Underflow check Timer 3296 iUnderFlowCheckTimer->Cancel(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID); 3297 3298 //Cancel the callback. This should also succeed if there is nothing to cancel 3299 MP4_ERROR_CODE retVal = iMP4FileHandle->CancelNotificationSync(); 3300 if (retVal != EVERYTHING_FINE) 3301 { 3302 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition Wrong Datastream SessionID")); 3303 OSCL_ASSERT(false); 3304 } 3305 } 3306 } 3307 3308 *actualNPT = durationms; 3309 OSCL_ARRAY_DELETE(trackList); 3310 return PVMFSuccess; 3311 } 3312 3313 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() *actualMediaDataTS %d", 3314 *actualMediaDataTS)); 3315 3316 // Change of logic: Individual track will call separate resetPlayback 3317 // Sequence of call is video->audio->text.If a few is not available that call will be skipped. 3318 // Ony One track id is provided in tempTrackId. Updated targetNPT is passed into next resetPlayback 3319 // More than 3 TRAK per MOOV not handled, first occurance of individual Track will be considered. 3320 3321 *actualNPT = targetNPT; // init *actualNPT to targetNPT 3322 uint32 tempNPT = 0; 3323 uint32 tempTrackId = 0; 3324 3325 // Rest the video present before calling the resetPlayback Individually 3326 iMP4FileHandle->ResetVideoTrackPresentFlag(); 3327 3328 int32 minFileOffset = 0x7FFFFFFF; 3329 if (0 != trackList[0]) 3330 { 3331 tempNPT = targetNPT; // For logging Purpose 3332 tempTrackId = trackList[0]; 3333 targetNPT = iMP4FileHandle->resetPlayback(targetNPT, (uint16)TRACK_NO_PER_RESET_PLAYBACK_CALL, 3334 &tempTrackId, seektosyncpoint); 3335 3336 MediaClockConverter mcc(1000); 3337 mcc.update_clock(targetNPT); 3338 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(tempTrackId)); 3339 3340 int32 offset = 0; 3341 int32 ret = iMP4FileHandle->getOffsetByTime(tempTrackId, mediats, &offset, 0); 3342 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() getOffsetByTime ret %d Track %d NPT %d Offset %d", 3343 ret, trackList[0], targetNPT, offset)); 3344 OSCL_UNUSED_ARG(ret); 3345 3346 minFileOffset = offset; 3347 minFileOffsetTrackID = tempTrackId; 3348 3349 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Video targetNPT = %d returns actualNPT=%d for trackId=%d", 3350 tempNPT, targetNPT, trackList[0])); 3351 } 3352 3353 if (0 != trackList[1]) 3354 { 3355 tempNPT = targetNPT; 3356 tempTrackId = trackList[1]; 3357 targetNPT = iMP4FileHandle->resetPlayback(targetNPT, (uint16)TRACK_NO_PER_RESET_PLAYBACK_CALL, 3358 &tempTrackId, seektosyncpoint); 3359 3360 MediaClockConverter mcc(1000); 3361 mcc.update_clock(targetNPT); 3362 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(tempTrackId)); 3363 3364 int32 offset = 0; 3365 int32 ret = iMP4FileHandle->getOffsetByTime(tempTrackId, mediats, &offset, 0); 3366 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() getOffsetByTime ret %d Track %d NPT %d Offset %d", 3367 ret, trackList[1], targetNPT, offset)); 3368 OSCL_UNUSED_ARG(ret); 3369 3370 if (minFileOffset > offset) 3371 { 3372 minFileOffset = offset; 3373 minFileOffsetTrackID = tempTrackId; 3374 } 3375 3376 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Audio targetNPT = %d returns actualNPT=%d for trackId=%d", 3377 tempNPT, targetNPT, trackList[1])); 3378 } 3379 3380 // Resetting Text Track might send 0 NPT, *actualNPT will be decided from audio and video. 3381 *actualNPT = targetNPT; 3382 3383 if (0 != trackList[2]) 3384 { 3385 tempNPT = targetNPT; 3386 tempTrackId = trackList[2]; 3387 tempNPT = iMP4FileHandle->resetPlayback(targetNPT, (uint16)TRACK_NO_PER_RESET_PLAYBACK_CALL, 3388 &tempTrackId, seektosyncpoint); 3389 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Text targetNPT = %d returns actualNPT=%d for trackId=%d", 3390 targetNPT, tempNPT, trackList[2])); 3391 3392 MediaClockConverter mcc(1000); 3393 mcc.update_clock(tempNPT); 3394 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(tempTrackId)); 3395 3396 int32 offset = 0; 3397 int32 ret = iMP4FileHandle->getOffsetByTime(tempTrackId, mediats, &offset, 0); 3398 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() getOffsetByTime ret %d Track %d NPT %d Offset %d", 3399 ret, trackList[2], tempNPT, offset)); 3400 OSCL_UNUSED_ARG(ret); 3401 3402 if (minFileOffset > offset) 3403 { 3404 minFileOffset = offset; 3405 minFileOffsetTrackID = tempTrackId; 3406 } 3407 3408 // Use case, Text Only Track, *actualNPT will be set to output of Text resetPlayback. 3409 if ((0 == trackList[0]) && (0 == trackList[1])) 3410 { 3411 *actualNPT = tempNPT; 3412 } 3413 3414 } 3415 3416 // There is no guarantee that each track is lined up at the same timestamp after repositioning. 3417 // So we need to find the track with the minimum NPT timestamp which will be set as the starting 3418 // media data timestamp after repositioning. Then the other tracks will need to offset from that time 3419 3420 // First determine the track with the minimum timestamp after repositioning 3421 uint32 numSamples = 1; 3422 uint32 mints = 0xFFFFFFFF; 3423 int32 retval = EVERYTHING_FINE; 3424 int32 *retValPerTrack = NULL; 3425 uint32 *retNumSamplesPerTrack = NULL; 3426 uint32 *trackTSAfterRepo = NULL; 3427 //array to keep the timestamp of those samples from where playback has to be started i.e. timestamp of current samples to be played back. 3428 trackTSAfterRepo = (uint32*) OSCL_MALLOC(iNodeTrackPortList.size() * sizeof(uint32)); 3429 retValPerTrack = (int32*) OSCL_MALLOC(iNodeTrackPortList.size() * sizeof(int32)); 3430 retNumSamplesPerTrack = (uint32*) OSCL_MALLOC(iNodeTrackPortList.size() * sizeof(uint32)); 3431 3432 if ((trackTSAfterRepo == NULL) || (retValPerTrack == NULL) || (retNumSamplesPerTrack == NULL)) 3433 { 3434 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, 3435 (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Memory alloc for array to keep the timestamp of the samples failed")); 3436 OSCL_FREE(trackTSAfterRepo); 3437 trackTSAfterRepo = NULL; 3438 OSCL_FREE(retValPerTrack); 3439 retValPerTrack = NULL; 3440 OSCL_FREE(retNumSamplesPerTrack); 3441 retNumSamplesPerTrack = NULL; 3442 return PVMFErrNoMemory; 3443 } 3444 3445 for (i = 0; i < iNodeTrackPortList.size(); i++) 3446 { 3447 // Peek the next sample to get the duration of the last sample 3448 numSamples = 1; 3449 retval = iMP4FileHandle->peekNextBundledAccessUnits(iNodeTrackPortList[i].iTrackId, &numSamples, &info); 3450 trackTSAfterRepo[i] = info.ts; 3451 retNumSamplesPerTrack[i] = numSamples; 3452 retValPerTrack[i] = retval; 3453 3454 if (((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK)) 3455 && (numSamples > 0)) 3456 { 3457 // Check if sample info was returned. Only use valid 3458 // samples for this search 3459 // Set the new starting timestamp to the clock convert 3460 iNodeTrackPortList[i].iClockConverter->set_clock(info.ts, 0); 3461 3462 // Check if this is the minimum 3463 if (iNodeTrackPortList[i].iFormatType != PVMF_MIME_3GPP_TIMEDTEXT) 3464 { 3465 uint32 trackstartts = iNodeTrackPortList[i].iClockConverter->get_converted_ts(1000); 3466 if (trackstartts < mints) 3467 { 3468 mints = trackstartts; 3469 } 3470 } 3471 } 3472 else if (retval == END_OF_TRACK) 3473 { 3474 // do nothing. No need to use the track to calculate mints, as next sample is EOT. 3475 } 3476 else if (retval == INSUFFICIENT_DATA) 3477 { 3478 iNodeTrackPortList[i].iClockConverter->set_clock_other_timescale(*actualMediaDataTS, 1000); 3479 if (iNodeTrackPortList[i].iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK 3480 || iNodeTrackPortList[i].iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK) 3481 { 3482 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 3483 } 3484 3485 iNodeTrackPortList[i].iTimestamp = iNodeTrackPortList[i].iClockConverter->get_current_timestamp(); 3486 iNodeTrackPortList[i].iFirstFrameAfterRepositioning = true; 3487 iNodeTrackPortList[i].iCurrentTextSampleEntry.Unbind(); 3488 // convert target NPT to media timescale 3489 MediaClockConverter mcc(1000); 3490 mcc.update_clock(targetNPT); 3491 uint32 targetNPTtInMediaTimeScale = 3492 mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(iNodeTrackPortList[i].iTrackId)); 3493 iNodeTrackPortList[i].iTargetNPTInMediaTimeScale = targetNPTtInMediaTimeScale; 3494 } 3495 else 3496 { 3497 // Return as error 3498 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Peeking next sample failed while determining the min timestamp after repositioning")); 3499 if (!MapMP4ErrorCodeToEventCode(retval, aEventUuid, aEventCode)) 3500 { 3501 aEventUuid = PVMFFileFormatEventTypesUUID; 3502 aEventCode = PVMFFFErrMisc; 3503 } 3504 OSCL_ARRAY_DELETE(trackList); 3505 OSCL_FREE(trackTSAfterRepo); 3506 trackTSAfterRepo = NULL; 3507 OSCL_FREE(retValPerTrack); 3508 retValPerTrack = NULL; 3509 OSCL_FREE(retNumSamplesPerTrack); 3510 retNumSamplesPerTrack = NULL; 3511 return PVMFErrResource; 3512 } 3513 } 3514 3515 if (mints == 0xFFFFFFFF) 3516 { 3517 mints = *actualNPT; 3518 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Minimum timestamp could not be determined so using the actual NPT %d", mints)); 3519 } 3520 else if (mints != *actualNPT) 3521 { 3522 *actualNPT = mints; 3523 } 3524 3525 // Now adjust the timestamp of each track in reference to this minimum 3526 for (i = 0; i < iNodeTrackPortList.size(); i++) 3527 { 3528 // now no need to call 2nd peek, we have timestamp of current sample and retValPerTrack[i] by 1st peek call. 3529 if (retValPerTrack[i] == EVERYTHING_FINE || retValPerTrack[i] == END_OF_TRACK) 3530 { 3531 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, \ 3532 (0, "PVMFMP4FFParserNode::DoSetDataSourcePositionA: targetNPT1 =%d, TrackId=%d, State =%d,\ 3533 Timestamp = %d,TargetNPTInMediaTimeScale=%d", targetNPT, iNodeTrackPortList[i].iTrackId, \ 3534 iNodeTrackPortList[i].iState, iNodeTrackPortList[i].iTimestamp, \ 3535 iNodeTrackPortList[i].iTargetNPTInMediaTimeScale)); 3536 3537 if (retNumSamplesPerTrack[i] > 0) 3538 { 3539 iNodeTrackPortList[i].iClockConverter->set_clock(trackTSAfterRepo[i], 0); 3540 uint32 trackts = iNodeTrackPortList[i].iClockConverter->get_converted_ts(1000); 3541 if (iNodeTrackPortList[i].iFormatType == PVMF_MIME_3GPP_TIMEDTEXT && trackts < mints) 3542 { 3543 uint32 diffMintsTrackts = mints - trackts; 3544 3545 /********************************************************************** 3546 * As trackts is smaller than mints, we will reduce the text sample duration 3547 * by diffMintsTrackts and assign text sample ts as actualMediaDataTS. 3548 * if (*actualMediaDataTS + (trackts-mints)) has a negative value, then we will 3549 * have a negative value for TS which is incorrect. So setting TS to actualMediaTS instead 3550 * of negative value and accordingly adjusting its duration. 3551 ***********************************************************************/ 3552 iTextInvalidTSAfterReposition = true; 3553 iDelayAddToNextTextSample = diffMintsTrackts; 3554 iNodeTrackPortList[i].iClockConverter->set_clock_other_timescale(*actualMediaDataTS, 1000); 3555 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFMP4FFParserNode::DoSetDataSourcePositionA:iTextInvalidTSAfterReposition")); 3556 } 3557 else 3558 { 3559 if (retValPerTrack[i] == END_OF_TRACK) 3560 { 3561 // if next sample is EOT then just assign actualMediaDataTS as the TS for the sample. 3562 iNodeTrackPortList[i].iClockConverter->set_clock_other_timescale(*actualMediaDataTS, 1000); 3563 } 3564 else 3565 { 3566 // Set the timestamp with offset from minimum TS to the TS for the next sample 3567 iNodeTrackPortList[i].iClockConverter->set_clock_other_timescale(*actualMediaDataTS + (trackts - mints), 1000); 3568 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFMP4FFParserNode::DoSetDataSourcePositionA: TimeADJ2 *actualMediaDataTS %d, trackts%d, mints %d, TrackId %d Adj to %d", *actualMediaDataTS, trackts, mints, iNodeTrackPortList[i].iTrackId, (*actualMediaDataTS + (trackts - mints)))); 3569 3570 } 3571 } 3572 } 3573 else 3574 { 3575 // Since sample is not available, just set the track timestamp to the calculated starting media data TS 3576 iNodeTrackPortList[i].iClockConverter->set_clock_other_timescale(*actualMediaDataTS, 1000); 3577 } 3578 3579 3580 if (autopaused || iExternalDownload) 3581 { 3582 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition Cancel notification callback")); 3583 autopaused = false; 3584 if (download_progress_interface != NULL && iDataStreamInterface != NULL) 3585 { 3586 download_progress_interface->cancelResumeNotification(); 3587 } 3588 else if (iExternalDownload) 3589 { 3590 // Cancel the Underflow check Timer 3591 iUnderFlowCheckTimer->Cancel(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID); 3592 3593 //Cancel the callback. This should also succeed if there is nothing to cancel 3594 MP4_ERROR_CODE retval = iMP4FileHandle->CancelNotificationSync(); 3595 if (retval != EVERYTHING_FINE) 3596 { 3597 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition Wrong Datastream SessionID")); 3598 OSCL_ASSERT(false); 3599 } 3600 } 3601 } 3602 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 3603 3604 iNodeTrackPortList[i].iTimestamp = iNodeTrackPortList[i].iClockConverter->get_current_timestamp(); 3605 iNodeTrackPortList[i].iFirstFrameAfterRepositioning = true; 3606 iNodeTrackPortList[i].iCurrentTextSampleEntry.Unbind(); 3607 // convert target NPT to media timescale 3608 MediaClockConverter mcc(1000); 3609 mcc.update_clock(targetNPT); 3610 uint32 targetNPTtInMediaTimeScale = 3611 mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(iNodeTrackPortList[i].iTrackId)); 3612 iNodeTrackPortList[i].iTargetNPTInMediaTimeScale = targetNPTtInMediaTimeScale; 3613 3614 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, \ 3615 (0, "PVMFMP4FFParserNode::DoSetDataSourcePositionA: targetNPT2 =%d, TrackId=%d, State =%d,\ 3616 Timestamp = %d,TargetNPTInMediaTimeScale=%d", targetNPT, iNodeTrackPortList[i].iTrackId, \ 3617 iNodeTrackPortList[i].iState, iNodeTrackPortList[i].iTimestamp, \ 3618 iNodeTrackPortList[i].iTargetNPTInMediaTimeScale)); 3619 } 3620 } 3621 3622 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 3623 (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition: targetNPT=%d, actualNPT=%d, actualTS=%d", 3624 targetNPT, *actualNPT, *actualMediaDataTS)); 3625 3626 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoSetDataSourcePosition: targetNPT=%d, actualNPT=%d, actualTS=%d", 3627 targetNPT, *actualNPT, *actualMediaDataTS)); 3628 3629 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoSetDataSourcePosition() Out")); 3630 OSCL_ARRAY_DELETE(trackList); 3631 OSCL_FREE(trackTSAfterRepo); 3632 trackTSAfterRepo = NULL; 3633 OSCL_FREE(retValPerTrack); 3634 retValPerTrack = NULL; 3635 OSCL_FREE(retNumSamplesPerTrack); 3636 retNumSamplesPerTrack = NULL; 3637 return PVMFSuccess; 3638 } 3639 3640 3641 PVMFStatus PVMFMP4FFParserNode::DoQueryDataSourcePosition(PVMFMP4FFParserNodeCommand& aCmd) 3642 { 3643 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoQueryDataSourcePosition() In")); 3644 3645 uint32 targetNPT = 0; 3646 uint32* seekPointBeforeTargetNPT = NULL; 3647 uint32* seekPointAfterTargetNPT = NULL; 3648 bool seektosyncpoint = false; 3649 3650 aCmd.PVMFMP4FFParserNodeCommand::Parse(targetNPT, seekPointBeforeTargetNPT, 3651 seektosyncpoint, seekPointAfterTargetNPT); 3652 3653 // Check the passed-in parameters 3654 if ((seekPointBeforeTargetNPT == NULL) || (seekPointBeforeTargetNPT == NULL)) 3655 { 3656 return PVMFErrArgument; 3657 } 3658 3659 // First check if MP4 file is being downloaded to make sure the requested position is before amount downloaded 3660 if (download_progress_clock.GetRep()) 3661 { 3662 // Get the amount downloaded so far 3663 bool tmpbool = false; 3664 uint32 dltime = 0; 3665 download_progress_clock->GetCurrentTime32(dltime, tmpbool, PVMF_MEDIA_CLOCK_MSEC); 3666 // Check if the requested time is past that 3667 if (targetNPT >= dltime) 3668 { 3669 // For now, fail in this case. In future, we might want to return a position that is valid. 3670 return PVMFErrArgument; 3671 } 3672 } 3673 3674 // Make sure track list is available 3675 if (iNodeTrackPortList.empty()) 3676 { 3677 return PVMFFailure; 3678 } 3679 3680 // Copy the track IDs into track list array 3681 int32 err = 0; 3682 uint32* trackList = NULL; 3683 OSCL_TRY(err, trackList = (uint32*)oscl_malloc(iNodeTrackPortList.size() * sizeof(uint32));); 3684 OSCL_FIRST_CATCH_ANY(err, return PVMFErrNoMemory); 3685 if (trackList == NULL) 3686 { 3687 return PVMFErrNoMemory; 3688 } 3689 3690 for (uint32 i = 0; i < iNodeTrackPortList.size(); i++) 3691 { 3692 trackList[i] = iNodeTrackPortList[i].iTrackId; 3693 } 3694 3695 // See if targetNPT is greater than or equal to clip duration. 3696 uint64 duration64 = iMP4FileHandle->getMovieDuration(); 3697 uint32 durationms = 0; 3698 uint32 duration = durationms = Oscl_Int64_Utils::get_uint64_lower32(duration64); 3699 uint32 timescale = iMP4FileHandle->getMovieTimescale(); 3700 if (timescale > 0 && timescale != 1000) 3701 { 3702 // Convert to milliseconds 3703 MediaClockConverter mcc(timescale); 3704 mcc.update_clock(duration); 3705 durationms = mcc.get_converted_ts(1000); 3706 } 3707 if (targetNPT >= durationms) 3708 { 3709 *seekPointBeforeTargetNPT = targetNPT; 3710 *seekPointAfterTargetNPT = targetNPT; 3711 3712 oscl_free(trackList); 3713 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoQueryDataSourcePosition: targetNPT=%d, closestNPTBefore=%d, closestNPTAfter=%d", 3714 targetNPT, *seekPointBeforeTargetNPT, *seekPointAfterTargetNPT)); 3715 return PVMFSuccess; 3716 } 3717 3718 // Determine the sync point - forwards and backwards 3719 bool oBeforeTargetNPT; 3720 3721 oBeforeTargetNPT = true; 3722 *seekPointBeforeTargetNPT = 3723 iMP4FileHandle->queryRepositionTime(targetNPT, 3724 (uint16)(iNodeTrackPortList.size()), 3725 trackList, 3726 seektosyncpoint, 3727 oBeforeTargetNPT); 3728 3729 oBeforeTargetNPT = false; 3730 *seekPointAfterTargetNPT = 3731 iMP4FileHandle->queryRepositionTime(targetNPT, 3732 (uint16)(iNodeTrackPortList.size()), 3733 trackList, 3734 seektosyncpoint, 3735 oBeforeTargetNPT); 3736 3737 // Calculations of actual NPT will be done by Engine Now; not here 3738 3739 oscl_free(trackList); 3740 3741 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoQueryDataSourcePosition: targetNPT=%d, closestNPTBefore=%d, closestNPTAfter=%d", 3742 targetNPT, *seekPointBeforeTargetNPT, *seekPointAfterTargetNPT)); 3743 3744 3745 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoQueryDataSourcePosition() Out")); 3746 return PVMFSuccess; 3747 } 3748 3749 3750 PVMFStatus PVMFMP4FFParserNode::DoSetDataSourceRate(PVMFMP4FFParserNodeCommand& aCmd) 3751 { 3752 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoSetDataSourceRate() In")); 3753 3754 // Retrieve the new rate 3755 int32 rate; 3756 PVMFTimebase* timebase = NULL; 3757 aCmd.PVMFMP4FFParserNodeCommand::Parse(rate, timebase); 3758 3759 if (timebase == NULL) 3760 { 3761 if (rate < 10000 || rate > 500000) 3762 { 3763 // Limit to 0.1X to 5X for now. 3764 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DoSetDataSourceRate() Invalid playback rate %d", rate)); 3765 return PVMFErrNotSupported; 3766 } 3767 } 3768 3769 // if we are going ff to normal or vice versa, we need to set the node to disable non-video 3770 if (!iParseAudioDuringFF && (iDataRate != rate) && (PVMF_DATA_SOURCE_DIRECTION_FORWARD == iPlayBackDirection)) 3771 { 3772 // coming to normal rate? 3773 if (rate == NORMAL_PLAYRATE) 3774 { 3775 iParseVideoOnly = false; 3776 } 3777 // switching to FF or rew? 3778 else 3779 { 3780 // since we know ff will not have audio, just disable audio now. 3781 // If it is going to REW, DoSetDataSourceDirection will modify it there 3782 iParseVideoOnly = true; 3783 } 3784 } 3785 3786 3787 iDataRate = rate; 3788 3789 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DoSetDataSourceRate() Out")); 3790 return PVMFSuccess; 3791 } 3792 3793 PVMFStatus PVMFMP4FFParserNode::DoSetDataSourceDirection(PVMFMP4FFParserNodeCommand& aCmd) 3794 { 3795 int32 direction = -1; 3796 uint32* actualNPT = NULL; 3797 uint32* actualMediaDataTS = NULL; 3798 PVMFTimebase* timebase; 3799 3800 aCmd.PVMFMP4FFParserNodeCommand::Parse(direction, actualNPT, actualMediaDataTS, timebase); 3801 3802 /* Validate the parameters */ 3803 if ((actualNPT == NULL) || (actualMediaDataTS == NULL)) 3804 { 3805 CommandComplete(iInputCommands, aCmd, PVMFErrArgument); 3806 return PVMFFailure; 3807 } 3808 3809 *actualMediaDataTS = 0; 3810 3811 /* 3812 * The media data timestamp of the next sample will start from the maximum 3813 * of timestamp on all selected tracks. This media data timestamp will 3814 * correspond to the actual NPT. 3815 */ 3816 uint32 i; 3817 for (i = 0; i < iNodeTrackPortList.size(); i++) 3818 { 3819 uint32 timeStamp = 0; 3820 /* Use an arbitary delta */ 3821 timeStamp = iNodeTrackPortList[i].iTimestamp; 3822 3823 iNodeTrackPortList[i].iClockConverter->set_clock(timeStamp, 0); 3824 timeStamp = iNodeTrackPortList[i].iClockConverter->get_converted_ts(1000); 3825 3826 /* 3827 * Actual media data TS is the max timestamp of all selected tracks 3828 */ 3829 if (timeStamp > *actualMediaDataTS) 3830 { 3831 *actualMediaDataTS = timeStamp; 3832 } 3833 } 3834 3835 /* ensure all current track TS starts after max of selected track */ 3836 //In MP4, TS could be max of selected track, but here we need to 3837 //have it more than max of selected track because the duration of 3838 //sample in asf is not set.Therefore comparison in the sync util 3839 //(aDataTimeStamp + aDuration)> iResumeTimeStamp fails for the 3840 //first valid packet send out from the parser node to the sync util 3841 //and is discarded. 3842 3843 MediaClockConverter mcc(1000); 3844 mcc.update_clock(*actualMediaDataTS); 3845 for (i = 0; i < iNodeTrackPortList.size(); i++) 3846 { 3847 uint32 actualMediaDataTSInMediaTimeScale = 3848 mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(iNodeTrackPortList[i].iTrackId)); 3849 iNodeTrackPortList[i].iTimestamp = actualMediaDataTSInMediaTimeScale; 3850 } 3851 3852 *actualNPT = 0; 3853 /* 3854 * If SetDataSourceDirection call made in prepared state, with fwd direction 3855 * do nothing. 3856 */ 3857 if ((iInterfaceState == EPVMFNodePrepared) && 3858 (direction == PVMF_DATA_SOURCE_DIRECTION_FORWARD)) 3859 { 3860 CommandComplete(iInputCommands, aCmd, PVMFSuccess); 3861 return PVMFSuccess; 3862 } 3863 3864 /* 3865 * If direction is reverse then actual NPT is the max of all track NPTs. 3866 * If direction is forward then actual NPT is the min of all track NPTs. 3867 * iPrevSampleTimeStamp is the NPT TS of the last retrieved sample 3868 */ 3869 uint32 actualNPT32 = 0; 3870 if (direction == PVMF_DATA_SOURCE_DIRECTION_FORWARD) 3871 { 3872 // if switching back to forward at 100000, make sure everything is set to parse 3873 // othrewise check what ff should be for non-video tracks and set it 3874 3875 iParseVideoOnly = ((iDataRate == NORMAL_PLAYRATE) || iParseAudioDuringFF) ? false : true; 3876 3877 actualNPT32 = 0x7FFFFFFF; 3878 for (i = 0; i < iNodeTrackPortList.size(); i++) 3879 { 3880 uint32 lastTS = iMP4FileHandle->getMediaTimestampForCurrentSample(iNodeTrackPortList[i].iTrackId); 3881 iNodeTrackPortList[i].iClockConverter->set_clock(lastTS, 0); 3882 lastTS = iNodeTrackPortList[i].iClockConverter->get_converted_ts(1000); 3883 if (lastTS < actualNPT32) 3884 { 3885 actualNPT32 = lastTS; 3886 } 3887 3888 // temporarily disable all tracks until the next setdatasourceposition comes in 3889 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK; 3890 } 3891 } 3892 else if (PVMF_DATA_SOURCE_DIRECTION_REVERSE == direction) 3893 { 3894 iParseVideoOnly = iParseAudioDuringREW ? false : true; 3895 3896 actualNPT32 = 0; 3897 for (i = 0; i < iNodeTrackPortList.size(); i++) 3898 { 3899 uint32 lastTS = iMP4FileHandle->getMediaTimestampForCurrentSample(iNodeTrackPortList[i].iTrackId); 3900 iNodeTrackPortList[i].iClockConverter->set_clock(lastTS, 0); 3901 lastTS = iNodeTrackPortList[i].iClockConverter->get_converted_ts(1000); 3902 if (lastTS > actualNPT32) 3903 actualNPT32 = lastTS; 3904 3905 // stop transmitting until after repositioning 3906 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK; 3907 } 3908 } 3909 else 3910 { 3911 OSCL_ASSERT(false); 3912 } 3913 3914 *actualNPT = actualNPT32; 3915 3916 iPlayBackDirection = direction; 3917 3918 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::DoSetDataSourceDirection: direction=%d, actualNPT=%d, actualTS=%d", 3919 direction, *actualNPT, *actualMediaDataTS)); 3920 3921 return PVMFSuccess; 3922 } 3923 3924 3925 void PVMFMP4FFParserNode::HandleTrackState() 3926 { 3927 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::HandleTrackState() In")); 3928 3929 for (uint32 i = 0; i < iNodeTrackPortList.size(); ++i) 3930 { 3931 switch (iNodeTrackPortList[i].iState) 3932 { 3933 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED: 3934 if (RetrieveTrackConfigInfo(iNodeTrackPortList[i].iTrackId, iNodeTrackPortList[i].iFormatType, iNodeTrackPortList[i].iFormatSpecificConfig) == false) 3935 { 3936 // Failed 3937 break; 3938 } 3939 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 3940 // Continue on to retrieve the first frame 3941 3942 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA: 3943 if (iNodeTrackPortList[i].iSendBOS) 3944 { 3945 if (!SendBeginOfMediaStreamCommand(iNodeTrackPortList[i])) 3946 break; 3947 } 3948 if (iNodeTrackPortList[i].iFirstFrameAfterRepositioning) 3949 { 3950 //after repo, let the track with min file offset retrieve data first 3951 uint32 j = 0; 3952 for (j = 0; j < iNodeTrackPortList.size(); ++j) 3953 { 3954 if (minFileOffsetTrackID == iNodeTrackPortList[j].iTrackId) 3955 { 3956 break; 3957 } 3958 } 3959 if ((i != j) && (iNodeTrackPortList[j].iFirstFrameAfterRepositioning)) 3960 { 3961 //LOGE("Ln %d UGLY? Yes. minFileOffsetTrackID %d Skipped iTrackId %d", __LINE__, minFileOffsetTrackID , iNodeTrackPortList[j].iTrackId); 3962 break; 3963 } 3964 } 3965 3966 if (!RetrieveTrackData(iNodeTrackPortList[i])) 3967 { 3968 if (iNodeTrackPortList[i].iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK) 3969 { 3970 RunIfNotReady(); 3971 } 3972 if (iNodeTrackPortList[i].iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_SKIP_CORRUPT_SAMPLE) 3973 { 3974 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 3975 RunIfNotReady(); 3976 } 3977 break; 3978 } 3979 if (iNodeTrackPortList[i].iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRACKMAXDATASIZE_RESIZE) 3980 { 3981 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 3982 RunIfNotReady(); 3983 break; 3984 } 3985 else 3986 { 3987 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA; 3988 } 3989 // Continue on to send the frame 3990 3991 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA: 3992 if (SendTrackData(iNodeTrackPortList[i])) 3993 { 3994 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 3995 RunIfNotReady(); 3996 } 3997 break; 3998 3999 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK: 4000 if (iNodeTrackPortList[i].iSendBOS) 4001 { 4002 if (!SendBeginOfMediaStreamCommand(iNodeTrackPortList[i])) 4003 break; 4004 } 4005 if (SendEndOfTrackCommand(iNodeTrackPortList[i])) 4006 { 4007 // EOS command sent successfully 4008 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFMP4FFParserNode::HandleTrackState() EOS media command sent successfully")); 4009 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK; 4010 ReportMP4FFParserInfoEvent(PVMFInfoEndOfData); 4011 } 4012 else 4013 { 4014 // EOS command sending failed -- wait on outgoing queue ready notice 4015 // before trying again. 4016 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, (0, "PVMFMP4FFParserNode::HandleTrackState() EOS media command sending failed")); 4017 } 4018 break; 4019 4020 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRACKDATAPOOLEMPTY: 4021 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_MEDIADATAPOOLEMPTY: 4022 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_INITIALIZED: 4023 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_DESTFULL: 4024 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA: 4025 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK: 4026 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR: 4027 default: 4028 // Do nothing for these states for now 4029 break; 4030 } 4031 } 4032 4033 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::HandleTrackState() Out")); 4034 } 4035 4036 bool PVMFMP4FFParserNode::RetrieveTrackConfigInfo(uint32 aTrackId, PVMFFormatType aFormatType, OsclRefCounterMemFrag &aConfig) 4037 { 4038 if (aFormatType == PVMF_MIME_3GPP_TIMEDTEXT) 4039 { 4040 // For timed text 4041 // Create refcounted mem frag for text track's format specific info 4042 OsclMemAllocDestructDealloc<uint8> fsi_alloc; 4043 uint32 aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); 4044 uint32 aligned_textfsi_size = oscl_mem_aligned_size(sizeof(PVMFTimedTextFormatSpecificInfo)); 4045 uint8* fsi_ptr = NULL; 4046 int32 errcode = 0; 4047 OSCL_TRY(errcode, fsi_ptr = (uint8*) fsi_alloc.ALLOCATE(aligned_refcnt_size + aligned_textfsi_size)); 4048 OSCL_FIRST_CATCH_ANY(errcode, 4049 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackConfigInfo() Format specific info for text could not be allocated")); 4050 return false); 4051 4052 OsclRefCounter* fsi_refcnt = OSCL_PLACEMENT_NEW(fsi_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(fsi_ptr)); 4053 fsi_ptr += aligned_refcnt_size; 4054 4055 OsclMemoryFragment memfrag; 4056 memfrag.len = aligned_textfsi_size; 4057 memfrag.ptr = fsi_ptr; 4058 oscl_memset(fsi_ptr, 0, aligned_textfsi_size); 4059 4060 // Copy the data from the text sample entry 4061 PVMFTimedTextFormatSpecificInfo* textfsi = (PVMFTimedTextFormatSpecificInfo*)fsi_ptr; 4062 textfsi->iUID32 = PVMFTimedTextFormatSpecificInfo_UID; 4063 textfsi->iLayer = iMP4FileHandle->getLayer(aTrackId); 4064 textfsi->iTranslationMatrix[0] = (int32)(iMP4FileHandle->getTextTrackXOffset(aTrackId)); 4065 textfsi->iTranslationMatrix[1] = (int32)(iMP4FileHandle->getTextTrackYOffset(aTrackId)); 4066 textfsi->iWidth = (uint32)(iMP4FileHandle->getTextTrackWidth(aTrackId)); 4067 textfsi->iHeight = (uint32)(iMP4FileHandle->getTextTrackHeight(aTrackId)); 4068 4069 // Save the text track's format specific info 4070 aConfig = OsclRefCounterMemFrag(memfrag, fsi_refcnt, aligned_textfsi_size); 4071 } 4072 else 4073 { 4074 // For other formats 4075 // Check if the track has decoder config info 4076 uint32 specinfosize = iMP4FileHandle->getTrackDecoderSpecificInfoSize(aTrackId); 4077 if (specinfosize == 0) 4078 { 4079 // There is no decoder specific info so return and continue on. Not an error 4080 return true; 4081 } 4082 4083 // Retrieve the decoder specific info from file parser 4084 uint8* specinfoptr = iMP4FileHandle->getTrackDecoderSpecificInfoContent(aTrackId); 4085 if (specinfoptr == NULL) 4086 { 4087 // Error 4088 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackConfigInfo: Error - getTrackDecoderSpecificInfoContent failed")); 4089 return false; 4090 } 4091 4092 // Create mem frag for decoder specific config 4093 OsclMemAllocDestructDealloc<uint8> my_alloc; 4094 OsclRefCounter* my_refcnt; 4095 uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); 4096 uint8* my_ptr = NULL; 4097 int32 errcode = 0; 4098 OSCL_TRY(errcode, my_ptr = (uint8*) my_alloc.ALLOCATE(aligned_refcnt_size + specinfosize)); 4099 OSCL_FIRST_CATCH_ANY(errcode, 4100 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackConfigInfo() Memory allocation failed size = %d", aligned_refcnt_size + specinfosize)); 4101 return false; 4102 ); 4103 4104 my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr)); 4105 my_ptr += aligned_refcnt_size; 4106 4107 OsclMemoryFragment memfrag; 4108 memfrag.len = specinfosize; 4109 memfrag.ptr = my_ptr; 4110 4111 // Copy the decoder specific info to the memory fragment 4112 oscl_memcpy(memfrag.ptr, specinfoptr, specinfosize); 4113 4114 // Save format specific info 4115 aConfig = OsclRefCounterMemFrag(memfrag, my_refcnt, specinfosize); 4116 } 4117 return true; 4118 } 4119 4120 bool PVMFMP4FFParserNode::RetrieveTrackConfigInfoAndFirstSample(uint32 aTrackId, 4121 PVMFFormatType aFormatType, 4122 OsclRefCounterMemFrag &aConfig) 4123 { 4124 if (aFormatType == PVMF_MIME_MPEG4_AUDIO) 4125 { 4126 // Check if the track has decoder config info 4127 uint32 specinfosize = 4128 iMP4FileHandle->getTrackDecoderSpecificInfoSize(aTrackId); 4129 if (specinfosize == 0) 4130 { 4131 // There is no decoder specific info so return and continue on. Not an error 4132 return true; 4133 } 4134 4135 // Retrieve the decoder specific info from file parser 4136 uint8* specinfoptr = 4137 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aTrackId); 4138 if (specinfoptr == NULL) 4139 { 4140 // Error 4141 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackConfigInfoAndFirstSample: Error - getTrackDecoderSpecificInfoContent failed")); 4142 return false; 4143 } 4144 4145 //get height from the first frame 4146 MediaMetaInfo info; 4147 uint32 numSamples = 1; 4148 int32 retval = EVERYTHING_FINE; 4149 retval = iMP4FileHandle->peekNextBundledAccessUnits(aTrackId, 4150 &numSamples, 4151 &info); 4152 if ((retval == EVERYTHING_FINE || END_OF_TRACK == retval) && numSamples > 0) 4153 { 4154 uint32 sampleSize = info.len; 4155 if (sampleSize > 0) 4156 { 4157 uint8* sampleBuf = OSCL_ARRAY_NEW(uint8, sampleSize); 4158 4159 oscl_memset(&iGau.buf, 0, sizeof(iGau.buf)); 4160 oscl_memset(&iGau.info, 0, sizeof(iGau.info)); 4161 iGau.free_buffer_states_when_done = 0; 4162 iGau.numMediaSamples = 1; 4163 iGau.buf.num_fragments = 1; 4164 iGau.buf.buf_states[0] = NULL; 4165 iGau.buf.fragments[0].ptr = (OsclAny*)sampleBuf; 4166 iGau.buf.fragments[0].len = sampleSize; 4167 retval = 4168 iMP4FileHandle->getNextBundledAccessUnits(aTrackId, 4169 &numSamples, 4170 &iGau); 4171 iMP4FileHandle->resetPlayback(); 4172 4173 // Create mem frag for decoder specific config 4174 OsclMemAllocDestructDealloc<uint8> my_alloc; 4175 OsclRefCounter* my_refcnt; 4176 uint aligned_refcnt_size = 4177 oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >)); 4178 uint8* my_ptr = NULL; 4179 int32 errcode = 0; 4180 OSCL_TRY(errcode, my_ptr = (uint8*) my_alloc.ALLOCATE(aligned_refcnt_size + specinfosize + sampleSize)); 4181 OSCL_FIRST_CATCH_ANY(errcode, 4182 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackConfigInfo() Memory allocation failed size = %d", aligned_refcnt_size + specinfosize + sampleSize)); 4183 return false; 4184 ); 4185 4186 my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr)); 4187 my_ptr += aligned_refcnt_size; 4188 4189 OsclMemoryFragment memfrag; 4190 memfrag.len = (specinfosize + sampleSize); 4191 memfrag.ptr = my_ptr; 4192 4193 // Copy the decoder specific info to the memory fragment 4194 oscl_memcpy(my_ptr, specinfoptr, specinfosize); 4195 my_ptr += specinfosize; 4196 // Copy the first sample into the memory fragment 4197 oscl_memcpy(my_ptr, sampleBuf, sampleSize); 4198 4199 // Save format specific info plus first sample 4200 aConfig = OsclRefCounterMemFrag(memfrag, my_refcnt, (specinfosize + sampleSize)); 4201 OSCL_ARRAY_DELETE(sampleBuf); 4202 return true; 4203 } 4204 } 4205 } 4206 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackConfigInfoAndFirstSample: Error - Incorrect Format Type")); 4207 return false; 4208 } 4209 4210 4211 bool PVMFMP4FFParserNode::checkTrackPosition(PVMP4FFNodeTrackPortInfo& aTrackPortInfo, uint32 numsamples) 4212 { 4213 // This function should use the peek calls to determine if the data is available in the file. 4214 4215 // Check the time on num_samples+1 to make sure there is enough data in the file 4216 ++numsamples; 4217 4218 MediaMetaInfo *info = (MediaMetaInfo*) OSCL_MALLOC(numsamples * sizeof(MediaMetaInfo)); 4219 if (NULL == info) 4220 { 4221 // If we get here, an error has occurred 4222 ReportMP4FFParserErrorEvent(PVMFErrProcessing, NULL, NULL, NULL); 4223 return false; 4224 } 4225 4226 int32 retval = iMP4FileHandle->peekNextBundledAccessUnits(aTrackPortInfo.iTrackId, &numsamples, info); 4227 if (numsamples == 0) 4228 { 4229 if (retval == END_OF_TRACK) 4230 { 4231 OSCL_FREE(info); 4232 //set track state to send end of track 4233 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 4234 return false; 4235 } 4236 else 4237 { 4238 // If we get here, an error has occurred 4239 OSCL_FREE(info); 4240 ReportMP4FFParserErrorEvent(PVMFErrProcessing, NULL, NULL, NULL); 4241 return false; 4242 } 4243 } 4244 4245 // create a temporary clock converter to convert the timestamp 4246 MediaClockConverter clock_conv(*aTrackPortInfo.iClockConverter); 4247 4248 clock_conv.update_clock(info[numsamples-1].ts); 4249 4250 uint32 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE); 4251 4252 // get the download progress clock time 4253 uint32 clock_msec32; 4254 bool overload = 0; 4255 download_progress_clock->GetCurrentTime32(clock_msec32, overload, PVMF_MEDIA_CLOCK_MSEC); 4256 4257 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 4258 (0, "PVMFMP4FFParserNode:: P/R checkTrackPosition() Track[%d] numsamples=%d, availTS=%d, reqTS=%d, playedTS=%d", \ 4259 aTrackPortInfo.iTrackId, numsamples, clock_msec32, msec, (*aTrackPortInfo.iClockConverter).get_converted_ts(MILLISECOND_TIMESCALE))); 4260 4261 bool status = true; 4262 if ((clock_msec32 - msec) > WRAP_THRESHOLD) 4263 { 4264 // This condition indicates that the read position is getting ahead of the download data 4265 // Note that since the computation is based on 32-bit values, it has a limitation that 4266 // it will not work for durations exceeding 2^32 milliseconds = 49+ days which is an acceptable 4267 // limit for this application. 4268 4269 if (!autopaused) 4270 { 4271 // Request to be notified when to resume 4272 bool dlcomplete = false; 4273 download_progress_interface->requestResumeNotification(msec, dlcomplete); 4274 if (!dlcomplete) 4275 { 4276 // Change the state and report underflow event 4277 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE; 4278 status = false; 4279 autopaused = true; 4280 } 4281 else 4282 { 4283 // Download has completed so ignore check and return true 4284 status = true; 4285 // Get rid of the download progress clock to disable this check 4286 download_progress_clock.Unbind(); 4287 } 4288 } 4289 else 4290 { 4291 // It is already auto-paused so set to autopause state and return false 4292 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE; 4293 status = false; 4294 } 4295 } 4296 4297 OSCL_FREE(info); 4298 return status; 4299 } 4300 4301 bool PVMFMP4FFParserNode::RetrieveTrackData(PVMP4FFNodeTrackPortInfo& aTrackPortInfo) 4302 { 4303 if (aTrackPortInfo.iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE) 4304 { 4305 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RetrieveTrackData() - Auto Pause")); 4306 return false; 4307 } 4308 4309 // Get the track ID 4310 uint32 trackid = aTrackPortInfo.iTrackId; 4311 4312 // Create a data buffer from pool 4313 int errcode = OsclErrNoResources; 4314 4315 OsclSharedPtr<PVMFMediaDataImpl> mediaDataImplOut; 4316 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT) 4317 { 4318 mediaDataImplOut = aTrackPortInfo.iTextMediaDataImplAlloc->allocate(aTrackPortInfo.iTrackMaxDataSize); 4319 } 4320 else 4321 { 4322 mediaDataImplOut = aTrackPortInfo.iMediaDataImplAlloc->allocate(aTrackPortInfo.iTrackMaxDataSize); 4323 } 4324 4325 if (mediaDataImplOut.GetRep() != NULL) 4326 { 4327 errcode = OsclErrNone; 4328 } 4329 else 4330 { 4331 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFMP4FFParserNode::RetrieveTrackData() No Resource Found")); 4332 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRACKDATAPOOLEMPTY; 4333 aTrackPortInfo.iTrackDataMemoryPool->notifyfreeblockavailable(aTrackPortInfo, aTrackPortInfo.iTrackMaxDataSize); // Enable flag to receive event when next deallocate() is called on pool 4334 return false; 4335 } 4336 4337 // Now create a PVMF media data from pool 4338 errcode = OsclErrNoResources; 4339 PVMFSharedMediaDataPtr mediadataout; 4340 mediadataout = PVMFMediaData::createMediaData(mediaDataImplOut, aTrackPortInfo.iMediaDataMemPool); 4341 if (mediadataout.GetRep() != NULL) 4342 { 4343 errcode = OsclErrNone; 4344 } 4345 4346 else 4347 { 4348 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFMP4FFParserNode::RetrieveTrackData() Memory allocation for media data memory pool failed")); 4349 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_MEDIADATAPOOLEMPTY; 4350 aTrackPortInfo.iMediaDataMemPool->notifyfreechunkavailable(aTrackPortInfo); // Enable flag to receive event when next deallocate() is called on pool 4351 return false; 4352 } 4353 4354 // Try creating a PVMF media frag group if H.264 4355 OsclSharedPtr<PVMFMediaDataImpl> mediadatafraggroup; 4356 if ((aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_H264_MP4) || 4357 ((aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_MPEG4_AUDIO) && 4358 (oIsAACFramesFragmented))) 4359 { 4360 errcode = OsclErrNoResources; 4361 mediadatafraggroup = aTrackPortInfo.iMediaDataGroupAlloc->allocate(); 4362 if (mediadatafraggroup.GetRep() != NULL) 4363 { 4364 errcode = OsclErrNone; 4365 } 4366 4367 else 4368 { 4369 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::RetrieveTrackData() Allocating from media data group alloc failed")); 4370 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_MEDIADATAFRAGGROUPPOOLEMPTY; 4371 aTrackPortInfo.iMediaDataGroupAlloc->notifyfreechunkavailable(aTrackPortInfo); 4372 return false; 4373 } 4374 4375 } 4376 4377 uint32 numsamples = aTrackPortInfo.iNumSamples; 4378 4379 // If download progress clock is available then make sure that we're not reading beyond the 4380 // end of the file 4381 if (download_progress_clock.GetRep()) 4382 { 4383 if (!checkTrackPosition(aTrackPortInfo, numsamples)) 4384 { 4385 return false; 4386 } 4387 } 4388 4389 // Retrieve memory fragment to write to 4390 OsclRefCounterMemFrag refCtrMemFragOut; 4391 mediadataout->getMediaFragment(0, refCtrMemFragOut); 4392 4393 // Resets GAU structure. 4394 oscl_memset(&iGau.buf, 0, sizeof(iGau.buf)); 4395 oscl_memset(&iGau.info, 0, sizeof(iGau.info)); 4396 iGau.free_buffer_states_when_done = 0; 4397 4398 iGau.numMediaSamples = numsamples; 4399 iGau.buf.num_fragments = 1; 4400 iGau.buf.buf_states[0] = NULL; 4401 4402 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 4403 { 4404 iGau.buf.fragments[0].ptr = iOMA2DecryptionBuffer; 4405 iGau.buf.fragments[0].len = PVMP4FF_OMA2_DECRYPTION_BUFFER_SIZE; 4406 } 4407 else 4408 { 4409 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT) 4410 { 4411 PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*) refCtrMemFragOut.getMemFrag().ptr; 4412 iGau.buf.fragments[0].ptr = textmediadata->iTextSample; 4413 iGau.buf.fragments[0].len = textmediadata->iTextSampleCapacity; 4414 } 4415 else 4416 { 4417 iGau.buf.fragments[0].ptr = refCtrMemFragOut.getMemFrag().ptr; 4418 iGau.buf.fragments[0].len = refCtrMemFragOut.getCapacity(); 4419 } 4420 } 4421 4422 uint32 currticks = OsclTickCount::TickCount(); 4423 uint32 StartTime = OsclTickCount::TicksToMsec(currticks); 4424 4425 // Retrieve the data from the parser 4426 int32 retval; 4427 if (iThumbNailMode) 4428 { 4429 if (aTrackPortInfo.iThumbSampleDone == false) 4430 { 4431 numsamples = 0; 4432 PVMFStatus status = PVMFFailure; 4433 uint32 keySampleNum = PVMFFF_DEFAULT_THUMB_NAIL_SAMPLE_NUMBER; 4434 if (!iMP4FileHandle->IsMovieFragmentsPresent()) 4435 { 4436 status = FindBestThumbnailKeyFrame(trackid, keySampleNum); 4437 } 4438 if (PVMFSuccess == status) 4439 { 4440 retval = iMP4FileHandle->getKeyMediaSampleNumAt(trackid, keySampleNum, &iGau); 4441 } 4442 else 4443 { 4444 // No keyframe available. 4445 // Go for the best possible solution if no key frames are available in stss atom. 4446 // Just try to retrieve the first video frame, this could result in a distorted frame 4447 // if first video frame is not a sync sample but it might be still better than no thumbnail. 4448 // Before retrieving the frame just make sure that there are samples in video track, 4449 // if there are no samples in the video track just report failure from here. No thumbnail possible 4450 if (iMP4FileHandle->getSampleCountInTrack(trackid) > 0) 4451 { 4452 // Just retrieve the first video sample 4453 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC( 4454 (0, "PVMFMP4FFParserNode:RetrieveTrackData - FindBestThumbnailKeyFrame failed, best possible solution fetch the first video sample")); 4455 numsamples = 1; 4456 retval = iMP4FileHandle->getNextBundledAccessUnits(trackid, &numsamples, &iGau); 4457 } 4458 else 4459 { 4460 // no sample in the video track. 4461 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC( 4462 (0, "PVMFMP4FFParserNode:RetrieveTrackData - FindBestThumbnailKeyFrame failed, No sample in video track just return EndOfTrack")); 4463 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 4464 return false; 4465 } 4466 } 4467 4468 if (retval == EVERYTHING_FINE || retval == END_OF_TRACK) 4469 { 4470 numsamples = 1; 4471 aTrackPortInfo.iThumbSampleDone = true; 4472 } 4473 } 4474 else 4475 { 4476 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 4477 return false; 4478 } 4479 } 4480 else if ((PVMF_DATA_SOURCE_DIRECTION_REVERSE == iPlayBackDirection) && 4481 (iMP4FileHandle->getTrackMediaType(aTrackPortInfo.iTrackId) == MEDIA_TYPE_VISUAL)) 4482 { 4483 uint32 numSamples = 1; 4484 uint32 keySampleNumber; 4485 if (aTrackPortInfo.iFirstFrameAfterRepositioning) 4486 { 4487 iPrevSampleTS = iMP4FileHandle->getMediaTimestampForCurrentSample(trackid); 4488 retval = iMP4FileHandle->getPrevKeyMediaSample(iPrevSampleTS, keySampleNumber, trackid, 4489 &numSamples, &iGau); 4490 iStartForNextTSSearch = iMP4FileHandle->getMediaTimestampForCurrentSample(trackid) - 2 * iGau.info[0].ts_delta; 4491 } 4492 else 4493 { 4494 if (iStartForNextTSSearch <= 0) 4495 { 4496 retval = END_OF_TRACK; 4497 } 4498 else 4499 { 4500 retval = iMP4FileHandle->getPrevKeyMediaSample(iStartForNextTSSearch, keySampleNumber, trackid, 4501 &numSamples, &iGau); 4502 iStartForNextTSSearch = iMP4FileHandle->getMediaTimestampForCurrentSample(trackid) - 2 * iGau.info[0].ts_delta; 4503 } 4504 } 4505 4506 } 4507 else 4508 { 4509 retval = iMP4FileHandle->getNextBundledAccessUnits(trackid, &numsamples, &iGau); 4510 } 4511 4512 if (retval == NO_SAMPLE_IN_CURRENT_MOOF && numsamples == 0) 4513 { 4514 // no sample was retrieved, try to retrieve in next getNextBundledAccessUnits call 4515 // return false without modifying the state. 4516 mediadataout->~PVMFMediaData(); 4517 return false; 4518 } 4519 4520 currticks = OsclTickCount::TickCount(); 4521 uint32 EndTime = OsclTickCount::TicksToMsec(currticks); 4522 4523 aTrackPortInfo.iNumTimesMediaSampleRead++; 4524 4525 // Determine actual size of the retrieved data by summing each sample length in GAU 4526 4527 uint32 DeltaTime = EndTime - StartTime; 4528 4529 if (DeltaTime >= maxTime) 4530 { 4531 maxTime = DeltaTime; 4532 } 4533 if (DeltaTime <= minTime) 4534 { 4535 minTime = DeltaTime; 4536 } 4537 sumTime += DeltaTime; 4538 4539 aTrackPortInfo.iMaxTime = maxTime; 4540 aTrackPortInfo.iMinTime = minTime; 4541 aTrackPortInfo.iSumTime = sumTime; 4542 4543 uint32 actualdatasize = 0; 4544 uint32 tsDelta = 0; 4545 uint32 duration_text_msec = 0; 4546 bool oSetNoRenderBit = false; 4547 bool textOnlyClip = false; 4548 for (uint32 i = 0; i < iGau.numMediaSamples; ++i) 4549 { 4550 actualdatasize += iGau.info[i].len; 4551 if ((PVMF_DATA_SOURCE_DIRECTION_REVERSE == iPlayBackDirection) && 4552 (iMP4FileHandle->getTrackMediaType(aTrackPortInfo.iTrackId) == MEDIA_TYPE_VISUAL)) 4553 { 4554 // for reverse we are just using I frames so need to get delta from total differnece in time 4555 tsDelta += oscl_abs(iGau.info[0].ts - iPrevSampleTS); 4556 if (0 == tsDelta) 4557 tsDelta += iGau.info[i].ts_delta; 4558 4559 iPrevSampleTS = iGau.info[0].ts; 4560 4561 // in the case of backwards playback, dont render if ts greater than targetnpt. 4562 if (iGau.info[i].ts > aTrackPortInfo.iTargetNPTInMediaTimeScale) 4563 { 4564 oSetNoRenderBit = true; 4565 } 4566 else 4567 { 4568 //we are past the no render point, so reset to zero 4569 aTrackPortInfo.iTargetNPTInMediaTimeScale = 0x7FFFFFFF; 4570 } 4571 } 4572 else 4573 { 4574 tsDelta += iGau.info[i].ts_delta; 4575 4576 if (iGau.info[i].ts < aTrackPortInfo.iTargetNPTInMediaTimeScale) 4577 { 4578 oSetNoRenderBit = true; 4579 } 4580 else 4581 { 4582 //we are past the no render point, so reset to zero 4583 aTrackPortInfo.iTargetNPTInMediaTimeScale = 0; 4584 } 4585 } 4586 } 4587 4588 // Save the first frame flag for output media data's random access point flag 4589 bool israndomaccesspt = aTrackPortInfo.iFirstFrameAfterRepositioning; 4590 if (aTrackPortInfo.iFirstFrameAfterRepositioning) 4591 { 4592 // If it is first frame after repositioning, media data timestamp should be 4593 // at the spot set when SetDataSourcePosition was processed and doesn't need to 4594 // consider the delta of the current frame from previous one. 4595 aTrackPortInfo.iFirstFrameAfterRepositioning = false; 4596 } 4597 4598 if (retval == EVERYTHING_FINE || retval == END_OF_TRACK) 4599 { 4600 // Truly is end of track when return value is END_OF_TRACK and number of samples 4601 // returned is 0 or length of data is 0 4602 if (retval == END_OF_TRACK && (numsamples < 1 || actualdatasize == 0)) 4603 { 4604 if (aTrackPortInfo.iSendBOS == true) 4605 { 4606 // If BOS has not been sent, it needs to be send before EOS. 4607 // E.g., In case the first call to RetrieveTrack produces END_OF_TRACK. 4608 SendBeginOfMediaStreamCommand(aTrackPortInfo); 4609 } 4610 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 4611 // End of track reached so send EOS media command 4612 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT) 4613 { 4614 iEOTForTextSentToMIO = true; 4615 iSetTextSampleDurationZero = false; 4616 } 4617 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RetrieveTrackData() EOS LOC 3 track ID %d", aTrackPortInfo.iTrackId)); 4618 return false; 4619 } 4620 4621 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 4622 { 4623 if (iDecryptionInterface != NULL) 4624 { 4625 uint32 inSize = actualdatasize; 4626 uint32 outSize = actualdatasize; 4627 4628 uint32 currticks = OsclTickCount::TickCount(); 4629 uint32 StartTime; 4630 StartTime = OsclTickCount::TicksToMsec(currticks); 4631 4632 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT) 4633 { 4634 PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*) refCtrMemFragOut.getMemFrag().ptr; 4635 iDecryptionInterface->DecryptAccessUnit(iOMA2DecryptionBuffer, 4636 inSize, 4637 textmediadata->iTextSample, 4638 outSize, trackid); 4639 } 4640 else 4641 { 4642 uint8* memfrag = (uint8*)(refCtrMemFragOut.getMemFrag().ptr); 4643 4644 iDecryptionInterface->DecryptAccessUnit(iOMA2DecryptionBuffer, 4645 inSize, 4646 memfrag, 4647 outSize, trackid); 4648 } 4649 currticks = OsclTickCount::TickCount(); 4650 uint32 EndTime; 4651 EndTime = OsclTickCount::TicksToMsec(currticks); 4652 4653 actualdatasize = outSize; 4654 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RetrieveTrackData - DecryptAccessUnit - Mime=%s, TrackID=%d, InSize=%d, OutSize=%d, DecryptTime=%d", aTrackPortInfo.iMimeType.get_cstr(), aTrackPortInfo.iTrackId, inSize, outSize, EndTime - StartTime)); 4655 } 4656 else 4657 { 4658 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR; 4659 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData Text sample is less than 2 bytes (size=%d). ReportMP4FFParserErrorEvent(PVMFErrCorrupt)", actualdatasize)); 4660 ReportMP4FFParserErrorEvent(PVMFErrInvalidState); 4661 return false; 4662 } 4663 } 4664 4665 // Retrieve the output media data impl to set some properties 4666 OsclSharedPtr<PVMFMediaDataImpl> media_data_impl; 4667 mediadataout->getMediaDataImpl(media_data_impl); 4668 4669 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT) 4670 { 4671 PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*) refCtrMemFragOut.getMemFrag().ptr; 4672 4673 // Check if the text sample duration read by parser is zero, then send EOT. 4674 textmediadata->iTextSampleDuration = iGau.info[0].ts_delta; 4675 if (textmediadata->iTextSampleDuration == 0) 4676 { 4677 iSetTextSampleDurationZero = true; 4678 iEOTForTextSentToMIO = true; 4679 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 4680 return false; 4681 } 4682 4683 // Adjust the duration of Text Sample (if clip is not textOnlyClip) as per new time-stamp. 4684 // Retrieve timestamp and convert to milliseconds 4685 4686 textOnlyClip = true; 4687 for (uint32 i = 0; i < iNodeTrackPortList.size(); i++) 4688 { 4689 if ((iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_VISUAL) || 4690 (iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_AUDIO)) 4691 { 4692 textOnlyClip = false; 4693 } 4694 } 4695 4696 if (!textOnlyClip) 4697 { 4698 if (iGau.info[0].ts_delta >= aTrackPortInfo.iTimestamp) 4699 { 4700 iGau.info[0].ts_delta = iGau.info[0].ts_delta - aTrackPortInfo.iTimestamp; 4701 } 4702 } 4703 4704 aTrackPortInfo.iClockConverter->set_clock(iGau.info[0].ts_delta, 0); 4705 duration_text_msec = aTrackPortInfo.iClockConverter->get_converted_ts(1000); 4706 4707 aTrackPortInfo.iClockConverter->set_clock(aTrackPortInfo.iTimestamp, 0); 4708 // Set sample duration, In media timescale. 4709 // The duration will always be reduced from text sample after reposition. Value 4710 // of adjustment would be different and is calculated in DoSetDataSourcePosition. 4711 if (iTextInvalidTSAfterReposition) 4712 { 4713 iTextInvalidTSAfterReposition = false; 4714 MediaClockConverter mcc(1000); 4715 mcc.update_clock(iDelayAddToNextTextSample); 4716 uint32 durationDelayInMediaTimeScale = 4717 mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(trackid)); 4718 if (tsDelta > durationDelayInMediaTimeScale) 4719 { 4720 iGau.info[0].ts_delta -= durationDelayInMediaTimeScale; 4721 tsDelta -= durationDelayInMediaTimeScale; 4722 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode - RetrieveTrackData(): iTextInvalidTSAfterReposition true")); 4723 } 4724 else 4725 { 4726 iGau.info[0].ts_delta = 0; 4727 tsDelta = 0; 4728 } 4729 4730 textmediadata->iTextSampleDuration = iGau.info[0].ts_delta; 4731 } 4732 4733 // Set sample timestamp in NPT 4734 aTrackPortInfo.iClockConverter->set_clock(iGau.info[0].ts, 0); 4735 textmediadata->iTextSampleTimestampNPT = aTrackPortInfo.iClockConverter->get_converted_ts(1000); 4736 4737 // Set the length of the text sample 4738 textmediadata->iTextSampleLength = actualdatasize; 4739 if (actualdatasize < 2) 4740 { 4741 // Sample corrupt 4742 // A text sample should at least be 2 bytes in size for the text string size 4743 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR; 4744 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 4745 int32 errcode = PVMFFFErrInvalidData; 4746 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData Text sample is less than 2 bytes (size=%d). ReportMP4FFParserErrorEvent(PVMFErrCorrupt)", actualdatasize)); 4747 4748 ReportMP4FFParserErrorEvent(PVMFErrCorrupt, NULL, &erruuid, &errcode); 4749 return false; 4750 } 4751 4752 // Return the unused space from mempool back 4753 if (textmediadata->iTextSampleCapacity > actualdatasize) 4754 { 4755 // Need to go to the resizable memory pool and free some memory 4756 uint32 bytestofree = textmediadata->iTextSampleCapacity - actualdatasize; 4757 // Update the capacity 4758 media_data_impl->setCapacity(media_data_impl->getCapacity() - bytestofree); 4759 textmediadata->iTextSampleCapacity -= bytestofree; 4760 // Set buffer size 4761 mediadataout->setMediaFragFilledLen(0, refCtrMemFragOut.getCapacity() - bytestofree); 4762 //resize the fragment 4763 aTrackPortInfo.iTextMediaDataImplAlloc->ResizeMemoryFragment(mediaDataImplOut); 4764 } 4765 4766 OsclBinIStreamBigEndian textSampleStream; 4767 textSampleStream.Attach((void *)(textmediadata->iTextSample), textmediadata->iTextSampleLength); 4768 4769 uint16 textSampleLengthFromSample = 0; 4770 textSampleStream >> textSampleLengthFromSample; 4771 4772 // Check that the text sample length is less than (total sample length -2) 4773 if (textSampleLengthFromSample > (textmediadata->iTextSampleLength - 2)) 4774 { 4775 // Sample corrupt 4776 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR; 4777 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 4778 int32 errcode = PVMFFFErrInvalidData; 4779 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData Text sample length is bigger than (total sample size-2) (len=%d, total=%d). ReportMP4FFParserErrorEvent(PVMFErrCorrupt)", textSampleLengthFromSample, textmediadata->iTextSampleLength)); 4780 4781 ReportMP4FFParserErrorEvent(PVMFErrCorrupt, NULL, &erruuid, &errcode); 4782 return false; 4783 } 4784 4785 //Set string format type, skip first two bytes, they represent 4786 //text sample length 4787 uint8 byte1 = 0; 4788 uint8 byte2 = 0; 4789 if (textmediadata->iTextSampleLength >= 4) 4790 { 4791 // Only check the marker if there is at least 4 bytes in the text sample 4792 byte1 = textmediadata->iTextSample[2]; 4793 byte2 = textmediadata->iTextSample[3]; 4794 } 4795 4796 if ((byte1 == PVMF_TIMED_TEXT_UTF_16_MARKER_BYTE_1) && 4797 (byte2 == PVMF_TIMED_TEXT_UTF_16_MARKER_BYTE_2)) 4798 { 4799 textmediadata->iFormatType = PVMF_TIMED_TEXT_STRING_FORMAT_UTF16; 4800 // Skip size & utf-16 marker 4801 // By being within this IF block, the text sample length should be greater or equal to 4. 4802 OSCL_ASSERT(textmediadata->iTextSampleLength >= 4); 4803 if (textmediadata->iTextSampleLength == 4) 4804 { 4805 // If there are only 4 bytes and it is UTF-16, the text string is not available 4806 textmediadata->iTextSample = NULL; 4807 } 4808 else 4809 { 4810 textmediadata->iTextSample += 4; 4811 } 4812 textmediadata->iTextSampleLength -= 4; 4813 textmediadata->iTextSampleCapacity -= 4; 4814 // text sample length includes the 0xFEFF marker 4815 textSampleLengthFromSample -= 2; 4816 } 4817 else 4818 { 4819 textmediadata->iFormatType = PVMF_TIMED_TEXT_STRING_FORMAT_UTF8; 4820 // Skip size only 4821 // By being within this IF block, the text sample length should be greater or equal to 2. 4822 OSCL_ASSERT(textmediadata->iTextSampleLength >= 2); 4823 if (textmediadata->iTextSampleLength == 2) 4824 { 4825 textmediadata->iTextSample = NULL; 4826 } 4827 else 4828 { 4829 textmediadata->iTextSample += 2; 4830 } 4831 textmediadata->iTextSampleLength -= 2; 4832 textmediadata->iTextSampleCapacity -= 2; 4833 } 4834 4835 textmediadata->iTextStringLengthInBytes = textSampleLengthFromSample; 4836 } 4837 else 4838 { 4839 // Set buffer size 4840 mediadataout->setMediaFragFilledLen(0, actualdatasize); 4841 media_data_impl->setCapacity(actualdatasize); 4842 // Return the unused space from mempool back 4843 if (refCtrMemFragOut.getCapacity() > actualdatasize) 4844 { 4845 // Need to go to the resizable memory pool and free some memory 4846 aTrackPortInfo.iMediaDataImplAlloc->ResizeMemoryFragment(mediaDataImplOut); 4847 } 4848 } 4849 4850 // Set the random access point flag if this is the first frame after repositioning 4851 uint32 markerInfo = 0; 4852 if (israndomaccesspt) 4853 { 4854 markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT; 4855 } 4856 4857 // Save the media data in the trackport info 4858 aTrackPortInfo.iMediaData = mediadataout; 4859 4860 // Retrieve duration and convert to milliseconds 4861 aTrackPortInfo.iClockConverter->set_clock(tsDelta, 0); 4862 4863 // Set duration bit in marker info 4864 markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_DURATION_AVAILABLE_BIT; 4865 // Set M bit to 1 always - MP4 FF only outputs complete frames 4866 markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_M_BIT; 4867 // Set No Render bit where applicable 4868 if (oSetNoRenderBit == true) 4869 { 4870 markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_NO_RENDER_BIT; 4871 } 4872 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_H264_MP4) 4873 { 4874 // Set End-of-NAL bit to 1 always - no NAL fragmentation for now 4875 markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT; 4876 } 4877 4878 media_data_impl->setMarkerInfo(markerInfo); 4879 4880 // Retrieve timestamp and convert to milliseconds 4881 aTrackPortInfo.iClockConverter->set_clock(aTrackPortInfo.iTimestamp, 0); 4882 uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000); 4883 4884 // Set the media data's timestamp 4885 aTrackPortInfo.iMediaData->setTimestamp(timestamp); 4886 4887 // Set the media data sequence number 4888 aTrackPortInfo.iMediaData->setSeqNum(aTrackPortInfo.iSeqNum); 4889 4890 //for logging 4891 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(aTrackPortInfo.iTrackId)); 4892 mcc.update_clock(iGau.info[0].ts); 4893 4894 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RetrieveTrackData - Mime=%s, TrackID=%d, Size=%d, NPT=%d, MediaTS=%d, SEQNUM=%d, DUR=%d, Marker=0x%x", aTrackPortInfo.iMimeType.get_cstr(), aTrackPortInfo.iTrackId, actualdatasize, mcc.get_converted_ts(1000), timestamp, aTrackPortInfo.iSeqNum, tsDelta, markerInfo)); 4895 4896 // Advance aTrackPortInfo.iTimestamp to the timestamp at the end of the 4897 // all samples in the group, i.e. current duration. 4898 aTrackPortInfo.iTimestamp += tsDelta; 4899 aTrackPortInfo.iClockConverter->set_clock(aTrackPortInfo.iTimestamp, 0); 4900 uint32 timestamp_next = aTrackPortInfo.iClockConverter->get_converted_ts(1000); 4901 uint32 duration_msec = timestamp_next - timestamp; 4902 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT) 4903 { 4904 aTrackPortInfo.iMediaData->setDuration(duration_text_msec); 4905 } 4906 else 4907 { 4908 aTrackPortInfo.iMediaData->setDuration(duration_msec); 4909 } 4910 // increment media data sequence number 4911 aTrackPortInfo.iSeqNum++; 4912 } 4913 else if (retval == READ_FAILED) 4914 { 4915 // Data could not be read from file 4916 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 4917 int32 errcode = PVMFFFErrFileRead; 4918 ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode); 4919 // Treat this as EOS 4920 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 4921 return false; 4922 } 4923 else if (retval == INSUFFICIENT_DATA) 4924 { 4925 /* 4926 * We have run out data during playback. This could mean a few things: 4927 * - A pseudo streaming session that has hit a data limit 4928 * - A regular playback session with a sample that has a bad offset. 4929 */ 4930 if (download_progress_interface != NULL) 4931 { 4932 if (iDownloadComplete) 4933 { 4934 // Data could not be read from file 4935 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 4936 int32 errcode = PVMFFFErrFileRead; 4937 ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode); 4938 // Treat this as EOS 4939 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 4940 return false; 4941 } 4942 4943 if (!autopaused) 4944 { 4945 uint32 requestedTimestamp = aTrackPortInfo.iTimestamp; 4946 // If Parser library reported Insufficient data after seek, the requested 4947 // timestamp here should be TS of sample from new position, so peek the 4948 // sample. 4949 if (israndomaccesspt) 4950 { 4951 uint32 numSamples = 1; 4952 MediaMetaInfo info; 4953 4954 retval = iMP4FileHandle->peekNextBundledAccessUnits(aTrackPortInfo.iTrackId, &numSamples, &info); 4955 if (((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK)) 4956 && (numSamples > 0)) 4957 { 4958 aTrackPortInfo.iClockConverter->set_clock(info.ts, 0); 4959 requestedTimestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000); 4960 } 4961 } 4962 4963 if ((NULL != iDataStreamInterface) && (0 != iDataStreamInterface->QueryBufferingCapacity())) 4964 { 4965 // if progressive streaming, playResumeNotifcation is guaranteed to be called 4966 // with the proper download complete state, ignore the current download status 4967 bool dlcomplete = false; 4968 download_progress_interface->requestResumeNotification(requestedTimestamp, dlcomplete); 4969 } 4970 else 4971 { 4972 download_progress_interface->requestResumeNotification(requestedTimestamp, iDownloadComplete); 4973 } 4974 } 4975 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE; 4976 autopaused = true; 4977 uint32 currentFileSize = 0; 4978 iMP4FileHandle->GetCurrentFileSize(currentFileSize); 4979 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RetrieveTrackData() - Auto Pause Triggered, TS = %d, FileSize=%d", 4980 aTrackPortInfo.iTimestamp, currentFileSize)); 4981 4982 4983 // check if content is poorly interleaved only for PS 4984 // After repositioning, parser will get INSUFFICIENT_DATA immediately and then the poorlyinterleavedcontent event logic will be excercised. 4985 // To make sure that the reposition behaviour and the playback without interruption behavior are consistent, disable the check for first INSUFFICIENT_DATA after repositioning. 4986 if ((NULL != iDataStreamInterface) && (iPoorlyInterleavedContentEventSent == false) && (!israndomaccesspt)) 4987 { 4988 uint32 cacheSize = 0; 4989 cacheSize = iDataStreamInterface->QueryBufferingCapacity(); 4990 if (cacheSize) 4991 { 4992 uint32 *trackOffset = NULL; 4993 trackOffset = (uint32*) OSCL_MALLOC(iNodeTrackPortList.size() * sizeof(uint32)); 4994 if (trackOffset == NULL) 4995 { 4996 return false; 4997 } 4998 int32 retval = EVERYTHING_FINE; 4999 int32 err = 0; 5000 OSCL_TRY(err, 5001 for (uint32 i = 0; i < iNodeTrackPortList.size(); i++) 5002 { 5003 // Peek the next sample to get the duration of the last sample 5004 uint32 numSamples = iNodeTrackPortList[i].iNumSamples; 5005 MediaMetaInfo* info = NULL; 5006 info = (MediaMetaInfo*) OSCL_MALLOC(numSamples * sizeof(MediaMetaInfo)); 5007 if (info == NULL) 5008 { 5009 OSCL_FREE(trackOffset); 5010 return false; 5011 } 5012 retval = iMP4FileHandle->peekNextBundledAccessUnits(iNodeTrackPortList[i].iTrackId, &numSamples, info); 5013 if (((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK)) 5014 && (numSamples > 0)) 5015 { 5016 int32 offset = 0; 5017 5018 if ((iMP4FileHandle->getOffsetByTime(iNodeTrackPortList[i].iTrackId, info[numSamples-1].ts, &offset, 0)) == EVERYTHING_FINE) 5019 { 5020 trackOffset[i] = offset; 5021 } 5022 else 5023 { 5024 trackOffset[i] = 0x7FFFFFFF; 5025 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 5026 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 5027 int32 errcode = PVMFFFErrFileRead; 5028 ReportMP4FFParserErrorEvent(PVMFErrResource, NULL, &erruuid, &errcode); 5029 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::RetrieveTrackData - getOffsetByTime Failed - TrackId=%d, TS=%d", iNodeTrackPortList[i].iTrackId, info[numSamples-1].ts)); 5030 OSCL_FREE(info); 5031 OSCL_FREE(trackOffset); 5032 return false; 5033 } 5034 } 5035 else 5036 { 5037 trackOffset[i] = 0x7FFFFFFF; 5038 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData Peeking next sample failed while determining the min timestamp after repositioning")); 5039 } 5040 OSCL_FREE(info); 5041 } 5042 ); 5043 OSCL_FIRST_CATCH_ANY(err, return PVMFErrNoMemory); 5044 5045 uint32 maxOffsetDiff = 0; 5046 for (uint32 ii = 0; ii < iNodeTrackPortList.size(); ii++) 5047 { 5048 if (trackOffset[ii] != 0x7FFFFFFF) 5049 { 5050 uint32 offsetDiff = 0; 5051 for (uint32 j = ii + 1; j < iNodeTrackPortList.size(); j++) 5052 { 5053 if (trackOffset[j] != 0x7FFFFFFF) 5054 { 5055 if (trackOffset[ii] > trackOffset[j]) 5056 { 5057 offsetDiff = trackOffset[ii] - trackOffset[j]; 5058 } 5059 else 5060 { 5061 offsetDiff = trackOffset[j] - trackOffset[ii]; 5062 } 5063 } 5064 5065 if (offsetDiff > maxOffsetDiff) 5066 { 5067 maxOffsetDiff = offsetDiff; 5068 } 5069 } 5070 } 5071 } 5072 5073 if (maxOffsetDiff > cacheSize) 5074 { 5075 // The content is poorly interleaved. 5076 ReportMP4FFParserInfoEvent(PVMFInfoPoorlyInterleavedContent); 5077 iPoorlyInterleavedContentEventSent = true; 5078 // @TODO - For now, don't treat this as EOS. 5079 // aTrackPortInfo.iState=PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 5080 } 5081 OSCL_FREE(trackOffset); 5082 } 5083 } 5084 5085 return false; 5086 } 5087 else 5088 { 5089 uint32 offset = 0; 5090 #if PVMP4FF_UNDERFLOW_REQUST_READSIZE_NOTIFICATION_PER_TRACK 5091 PVMFStatus status = GetFileOffsetForAutoResume(offset, &aTrackPortInfo); 5092 #else 5093 PVMFStatus status = GetFileOffsetForAutoResume(offset); 5094 #endif 5095 if (status == PVMFSuccess) 5096 { 5097 //Request for callback 5098 MP4_ERROR_CODE retVal = 5099 iMP4FileHandle->RequestReadCapacityNotification(*this, offset); 5100 if (retVal == EVERYTHING_FINE) 5101 { 5102 if (iDownloadComplete == false) 5103 { 5104 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA; 5105 if (CheckForUnderFlow(&aTrackPortInfo) == PVMFSuccess && iUnderFlowEventReported == false) 5106 { 5107 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE; 5108 autopaused = true; 5109 if (ReportUnderFlow() != PVMFSuccess) 5110 { 5111 return false; 5112 } 5113 } 5114 } 5115 else 5116 { 5117 // Data could not be read from file 5118 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 5119 int32 errcode = PVMFFFErrFileRead; 5120 ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode); 5121 // Treat this as EOS 5122 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 5123 return false; 5124 } 5125 } 5126 else 5127 { 5128 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 5129 int32 errcode = PVMFFFErrFileRead; 5130 5131 ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode); 5132 // Treat this as EOS 5133 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 5134 } 5135 return false; 5136 } 5137 // Data could not be read from file 5138 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR; 5139 PVUuid erruuid = PVMFFileFormatEventTypesUUID; 5140 int32 errcode = PVMFFFErrFileRead; 5141 ReportMP4FFParserErrorEvent(PVMFErrResource, NULL, &erruuid, &errcode); 5142 return false; 5143 } 5144 } 5145 else if (retval == INSUFFICIENT_BUFFER_SIZE) 5146 { 5147 /* Reset the actual size */ 5148 if (actualdatasize > aTrackPortInfo.iTrackMaxDataSize) 5149 { 5150 /* We will attempt to retrieve this sample again with a new max size */ 5151 aTrackPortInfo.iTrackMaxDataSize = actualdatasize; 5152 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRACKMAXDATASIZE_RESIZE; 5153 return true; 5154 } 5155 /* Error */ 5156 return false; 5157 } 5158 else 5159 { 5160 // Parsing error 5161 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR; 5162 PVUuid erruuid; 5163 int32 errcode; 5164 if (!MapMP4ErrorCodeToEventCode(retval, erruuid, errcode)) 5165 { 5166 erruuid = PVMFFileFormatEventTypesUUID; 5167 errcode = PVMFFFErrInvalidData; 5168 } 5169 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData ReportMP4FFParserErrorEvent(PVMFErrCorrupt)")); 5170 5171 ReportMP4FFParserErrorEvent(PVMFErrCorrupt, NULL, &erruuid, &errcode); 5172 return false; 5173 } 5174 5175 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_H264_MP4) 5176 { 5177 // Check that the media frag group has been allocated 5178 OSCL_ASSERT(mediadatafraggroup.GetRep() != NULL); 5179 if (GenerateAVCNALGroup(aTrackPortInfo, mediadatafraggroup) == false) 5180 { 5181 //This means that this AVC frame is corrupt, do not send it downstream 5182 //We do not need to declare EOS here, let us keep going 5183 //may be succeeding samples are ok 5184 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SKIP_CORRUPT_SAMPLE; 5185 return false; 5186 } 5187 else 5188 { 5189 return true; 5190 } 5191 } 5192 else if ((aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_MPEG4_AUDIO) 5193 && (oIsAACFramesFragmented)) 5194 { 5195 // Check that the media frag group has been allocated 5196 OSCL_ASSERT(mediadatafraggroup.GetRep() != NULL); 5197 return GenerateAACFrameFrags(aTrackPortInfo, mediadatafraggroup); 5198 } 5199 else if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT) 5200 { 5201 // Check if the text sample entry needs to be set 5202 PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*) refCtrMemFragOut.getMemFrag().ptr; 5203 UpdateTextSampleEntry(aTrackPortInfo, iGau.info[0].sample_info, *textmediadata); 5204 return true; 5205 } 5206 else 5207 { 5208 return true; 5209 } 5210 } 5211 5212 5213 bool PVMFMP4FFParserNode::SendTrackData(PVMP4FFNodeTrackPortInfo& aTrackPortInfo) 5214 { 5215 if (iPortDataLog) 5216 { 5217 LogMediaData(aTrackPortInfo.iMediaData, aTrackPortInfo.iPortInterface); 5218 } 5219 5220 // if going reverse, dump all non-video data. 5221 if (iParseVideoOnly && (iMP4FileHandle->getTrackMediaType(aTrackPortInfo.iTrackId) != MEDIA_TYPE_VISUAL)) 5222 { 5223 // Don't need the ref to iMediaData so unbind it 5224 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK; 5225 aTrackPortInfo.iMediaData.Unbind(); 5226 return false; 5227 } 5228 5229 // Set the track specific config info 5230 aTrackPortInfo.iMediaData->setFormatSpecificInfo(aTrackPortInfo.iFormatSpecificConfig); 5231 5232 aTrackPortInfo.iMediaData->setStreamID(iStreamID); 5233 5234 // Send frame to downstream node via port 5235 PVMFSharedMediaMsgPtr mediaMsgOut; 5236 convertToPVMFMediaMsg(mediaMsgOut, aTrackPortInfo.iMediaData); 5237 if (aTrackPortInfo.iPortInterface->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess) 5238 { 5239 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DESTFULL; 5240 return false; 5241 } 5242 5243 // Don't need the ref to iMediaData so unbind it 5244 aTrackPortInfo.iMediaData.Unbind(); 5245 return true; 5246 } 5247 5248 bool PVMFMP4FFParserNode::GenerateAACFrameFrags(PVMP4FFNodeTrackPortInfo& aTrackPortInfo, OsclSharedPtr<PVMFMediaDataImpl>& aMediaFragGroup) 5249 { 5250 OSCL_ASSERT(aTrackPortInfo.iMediaData.GetRep() != NULL); 5251 OsclSharedPtr<PVMFMediaDataImpl> mediaDataIn; 5252 if (aTrackPortInfo.iMediaData->getMediaDataImpl(mediaDataIn) == false) 5253 { 5254 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::GenerateAACFrameFrags() Retrieving media data impl failed")); 5255 return false; 5256 } 5257 5258 OSCL_ASSERT(aMediaFragGroup.GetRep() != NULL); 5259 aMediaFragGroup->setMarkerInfo(mediaDataIn->getMarkerInfo()); 5260 5261 OsclRefCounterMemFrag memFragIn; 5262 aTrackPortInfo.iMediaData->getMediaFragment(0, memFragIn); 5263 OsclRefCounter* refCntIn = memFragIn.getRefCounter(); 5264 5265 uint8* sample = (uint8*)(memFragIn.getMemFrag().ptr); 5266 int32 samplesize = (int32)(memFragIn.getMemFrag().len); 5267 5268 OsclBinIStreamBigEndian sampleStream; 5269 sampleStream.Attach(memFragIn.getMemFrag().ptr, memFragIn.getMemFrag().len); 5270 5271 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GenerateAACFrameFrags - SeqNum=%d, samplesize=%d, TS=%d, PTR=0x%x, RC=%d", aTrackPortInfo.iMediaData->getSeqNum(), samplesize, aTrackPortInfo.iMediaData->getTimestamp(), sample, memFragIn.getRefCounter()->getCount())); 5272 5273 MediaMetaInfo *iInfo = NULL; 5274 bool appended_data = false; 5275 uint32 ii = 0; 5276 5277 // While we still have data to append AND we haven't run out of media samples 5278 while ((samplesize > 0) && (ii < iGau.numMediaSamples)) 5279 { 5280 iInfo = iGau.getInfo(ii); 5281 if (iInfo) 5282 { 5283 if (iInfo->len > 0) 5284 { 5285 // Subtract the current sample from the total size 5286 samplesize -= iInfo->len; 5287 5288 // Create memory frag to append 5289 OsclMemoryFragment memFrag; 5290 memFrag.ptr = sample; 5291 memFrag.len = iInfo->len; 5292 5293 // Append the frag to the group 5294 refCntIn->addRef(); 5295 OsclRefCounterMemFrag refCountMemFragOut(memFrag, refCntIn, 0); 5296 aMediaFragGroup->appendMediaFragment(refCountMemFragOut); 5297 5298 sampleStream.seekFromCurrentPosition(memFrag.len); 5299 sample += memFrag.len; 5300 5301 // Set flag to show that that we have appended at least one frag 5302 appended_data = true; 5303 5304 } // End of if (iInfo->len > 0) 5305 } // End of if (iInfo) not NULL 5306 ii++; 5307 iInfo = NULL; 5308 } 5309 5310 if (appended_data) // If we have appended at least one frag to this group, then package and send 5311 { 5312 PVMFSharedMediaDataPtr aacFragGroup; 5313 aacFragGroup = PVMFMediaData::createMediaData(aMediaFragGroup, aTrackPortInfo.iMediaData->getMessageHeader()); 5314 aacFragGroup->setSeqNum(aTrackPortInfo.iMediaData->getSeqNum()); 5315 aacFragGroup->setTimestamp(aTrackPortInfo.iMediaData->getTimestamp()); 5316 aacFragGroup->setFormatSpecificInfo(aTrackPortInfo.iFormatSpecificConfig); 5317 5318 // Replace the track's output media data with the frag group one 5319 aTrackPortInfo.iMediaData = aacFragGroup; 5320 5321 // Return success 5322 return true; 5323 } 5324 else 5325 { 5326 return false; // No frag's appended ... 5327 } 5328 } 5329 5330 bool PVMFMP4FFParserNode::GenerateAVCNALGroup(PVMP4FFNodeTrackPortInfo& aTrackPortInfo, OsclSharedPtr<PVMFMediaDataImpl>& aMediaFragGroup) 5331 { 5332 OSCL_ASSERT(aTrackPortInfo.iMediaData.GetRep() != NULL); 5333 OsclSharedPtr<PVMFMediaDataImpl> mediaDataIn; 5334 if (aTrackPortInfo.iMediaData->getMediaDataImpl(mediaDataIn) == false) 5335 { 5336 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::GenerateAVCNALGroup() Retrieving media data impl failed")); 5337 return false; 5338 } 5339 5340 OSCL_ASSERT(aMediaFragGroup.GetRep() != NULL); 5341 5342 // Set End-of-NAL bit to 1 always - no NAL fragmentation for now 5343 uint32 markerInfo = (mediaDataIn->getMarkerInfo()) | PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT; 5344 aMediaFragGroup->setMarkerInfo(markerInfo); 5345 5346 OsclRefCounterMemFrag memFragIn; 5347 aTrackPortInfo.iMediaData->getMediaFragment(0, memFragIn); 5348 OsclRefCounter* refCntIn = memFragIn.getRefCounter(); 5349 5350 uint8* sample = (uint8*)(memFragIn.getMemFrag().ptr); 5351 int32 samplesize = (int32)(memFragIn.getMemFrag().len); 5352 uint32 nallengthsize = iMP4FileHandle->getAVCNALLengthSize(aTrackPortInfo.iTrackId); 5353 5354 OsclBinIStreamBigEndian sampleStream; 5355 sampleStream.Attach(memFragIn.getMemFrag().ptr, memFragIn.getMemFrag().len); 5356 5357 int32 numNAL = 0; 5358 while (samplesize > 0) 5359 { 5360 int32 nallen = 0; 5361 if (GetAVCNALLength(sampleStream, nallengthsize, nallen)) 5362 { 5363 sample += nallengthsize; 5364 samplesize -= nallengthsize; 5365 5366 if ((nallen < 0) || (nallen > samplesize)) 5367 { 5368 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - Corrupt Sample - SeqNum=%d, SampleSize=%d, NALSize=%d, TS=%d", 5369 aTrackPortInfo.iMediaData->getSeqNum(), samplesize, nallen, 5370 aTrackPortInfo.iMediaData->getTimestamp())); 5371 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - SeqNum=%d, Size=%d, TS=%d, PTR=0x%x, RC=%d", aTrackPortInfo.iMediaData->getSeqNum(), samplesize, aTrackPortInfo.iMediaData->getTimestamp(), sample, memFragIn.getRefCounter()->getCount())); 5372 //ignore corrupt samples / nals 5373 return true; 5374 } 5375 5376 if (nallen > 0) 5377 { 5378 OsclMemoryFragment memFrag; 5379 memFrag.ptr = sample; 5380 memFrag.len = nallen; 5381 5382 refCntIn->addRef(); 5383 OsclRefCounterMemFrag refCountMemFragOut(memFrag, refCntIn, 0); 5384 aMediaFragGroup->appendMediaFragment(refCountMemFragOut); 5385 5386 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, " PVMFMP4FFParserNode::GenerateAVCNALGroup - SN=%d, TS=%d, SS-NALSize=%d, NALSize=%d, NALNum=%d", 5387 aTrackPortInfo.iMediaData->getSeqNum(), 5388 aTrackPortInfo.iMediaData->getTimestamp(), 5389 samplesize - nallen, 5390 nallen, 5391 numNAL)); 5392 5393 sampleStream.seekFromCurrentPosition(nallen); 5394 numNAL++; 5395 } 5396 sample += nallen; 5397 samplesize -= nallen; 5398 } 5399 else 5400 { 5401 return false; 5402 } 5403 } 5404 5405 //check to see if we added any memfrags 5406 if (aMediaFragGroup->getNumFragments() == 0) 5407 { 5408 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - No Valid NALs - SeqNum=%d, SampleSize=%d, TS=%d", 5409 aTrackPortInfo.iMediaData->getSeqNum(), memFragIn.getMemFrag().len, 5410 aTrackPortInfo.iMediaData->getTimestamp())); 5411 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - No Valid NALs - SeqNum=%d, Size=%d, TS=%d", 5412 aTrackPortInfo.iMediaData->getSeqNum(), 5413 memFragIn.getMemFrag().len, 5414 aTrackPortInfo.iMediaData->getTimestamp())); 5415 //ignore corrupt samples / nals 5416 return false; 5417 } 5418 5419 PVMFSharedMediaDataPtr avcNALGroup; 5420 avcNALGroup = PVMFMediaData::createMediaData(aMediaFragGroup, aTrackPortInfo.iMediaData->getMessageHeader()); 5421 avcNALGroup->setSeqNum(aTrackPortInfo.iMediaData->getSeqNum()); 5422 avcNALGroup->setTimestamp(aTrackPortInfo.iMediaData->getTimestamp()); 5423 avcNALGroup->setFormatSpecificInfo(aTrackPortInfo.iFormatSpecificConfig); 5424 5425 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - SN=%d, SS=%d, NumNAL=%d, TS=%d, Marker=0x%x", 5426 avcNALGroup->getSeqNum(), 5427 memFragIn.getMemFrag().len, 5428 numNAL, 5429 avcNALGroup->getTimestamp(), 5430 avcNALGroup->getMarkerInfo())); 5431 5432 // Replace the track's output media data with the frag group one 5433 aTrackPortInfo.iMediaData = avcNALGroup; 5434 5435 return true; 5436 } 5437 5438 bool PVMFMP4FFParserNode::GetAVCNALLength(OsclBinIStreamBigEndian& stream, uint32& lengthSize, int32& len) 5439 { 5440 len = 0; 5441 if (lengthSize == 1) 5442 { 5443 uint8 len8 = 0; 5444 stream >> len8; 5445 len = (int32)(len8); 5446 return true; 5447 } 5448 else if (lengthSize == 2) 5449 { 5450 uint16 len16 = 0; 5451 stream >> len16; 5452 len = (int32)(len16); 5453 return true; 5454 } 5455 else if (lengthSize == 4) 5456 { 5457 stream >> len; 5458 return true; 5459 } 5460 return false; 5461 } 5462 5463 bool PVMFMP4FFParserNode::UpdateTextSampleEntry(PVMP4FFNodeTrackPortInfo& aTrackPortInfo, uint32 aEntryIndex, PVMFTimedTextMediaData& aTextMediaData) 5464 { 5465 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() In")); 5466 5467 // Check if the text sample entry hasn't be set or 5468 // it is different from the previous one 5469 if (aTrackPortInfo.iCurrentTextSampleEntry.GetRep() == NULL || aTrackPortInfo.iCurrentTextSampleEntryIndex != aEntryIndex) 5470 { 5471 // Retrieve the text sample entry and save as this track's format specific info 5472 TextSampleEntry* textsampleentry = NULL; 5473 // NOTE: MP4 API returns the base class pointer SampleEntry but doing a cast since the pointer returned 5474 // is a pointer to a TextSampleEntry. Dangerous but needs to be fixed first in the MP4 FF lib. 5475 textsampleentry = (TextSampleEntry*)iMP4FileHandle->getTextSampleEntryAt(aTrackPortInfo.iTrackId, aEntryIndex); 5476 5477 if (textsampleentry == NULL) 5478 { 5479 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Text sample sample index %d could not be retrieved", aEntryIndex)); 5480 return false; 5481 } 5482 5483 // Create shared pointer for the text sample entry using OsclMemAllocator 5484 int32 errcode = 0; 5485 OsclSharedPtr<PVMFTimedTextSampleEntry> tmp_shared_tse; 5486 OSCL_TRY(errcode, tmp_shared_tse = PVMFTimedTextSampleEntryUtil::CreatePVMFTimedTextSampleEntry()); 5487 OSCL_FIRST_CATCH_ANY(errcode, 5488 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Memory for PVMFTimedTextSampleEntry shared pointer could not be allocated")); 5489 return false); 5490 5491 OSCL_ASSERT(tmp_shared_tse.GetRep() != NULL); 5492 PVMFTimedTextSampleEntry* textse_ptr = tmp_shared_tse.GetRep(); 5493 5494 // Copy the data from the text sample entry 5495 textse_ptr->iDisplayFlags = textsampleentry->getDisplayFlags(); 5496 textse_ptr->iHorizontalJustification = textsampleentry->getHorzJustification(); 5497 textse_ptr->iVerticalJustification = textsampleentry->getVertJustification(); 5498 uint8* backcolor = textsampleentry->getBackgroundColourRGBA(); 5499 if (backcolor) 5500 { 5501 oscl_memcpy(textse_ptr->iBackgroundRGBA, backcolor, PVMFTIMEDTEXT_RGBA_ARRAYSIZE*sizeof(uint8)); 5502 } 5503 5504 // Copy box info 5505 textse_ptr->iBoxTop = textsampleentry->getBoxTop(); 5506 textse_ptr->iBoxLeft = textsampleentry->getBoxLeft(); 5507 textse_ptr->iBoxBottom = textsampleentry->getBoxBottom(); 5508 textse_ptr->iBoxRight = textsampleentry->getBoxRight(); 5509 5510 // Copy style info 5511 textse_ptr->iStyleStartChar = textsampleentry->getStartChar(); 5512 textse_ptr->iStyleEndChar = textsampleentry->getEndChar(); 5513 textse_ptr->iStyleFontID = textsampleentry->getFontID(); 5514 textse_ptr->iStyleFontStyleFlags = textsampleentry->getFontStyleFlags(); 5515 textse_ptr->iStyleFontSize = textsampleentry->getfontSize(); 5516 uint8* textcolor = textsampleentry->getTextColourRGBA(); 5517 if (textcolor) 5518 { 5519 oscl_memcpy(textse_ptr->iStyleTextColorRGBA, textcolor, PVMFTIMEDTEXT_RGBA_ARRAYSIZE*sizeof(uint8)); 5520 } 5521 5522 // Copy font record info 5523 textse_ptr->iFontEntryCount = textsampleentry->getFontListSize(); 5524 5525 if (textse_ptr->iFontEntryCount > 0) 5526 { 5527 // Allocate memory for the font record list 5528 errcode = 0; 5529 OSCL_TRY(errcode, textse_ptr->iFontRecordList = OSCL_ARRAY_NEW(PVMFTimedTextFontRecord, textse_ptr->iFontEntryCount)); 5530 OSCL_FIRST_CATCH_ANY(errcode, 5531 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Memory for PVMFTimedTextFontRecord list could not be allocated")); 5532 return false); 5533 errcode = 0; 5534 OSCL_TRY(errcode, 5535 for (uint16 i = 0; i < textse_ptr->iFontEntryCount; ++i) 5536 { 5537 FontRecord* fontrec = textsampleentry->getFontRecordAt(i); 5538 if (fontrec) 5539 { 5540 textse_ptr->iFontRecordList[i].iFontID = fontrec->getFontID(); 5541 textse_ptr->iFontRecordList[i].iFontNameLength = fontrec->getFontLength(); 5542 if (textse_ptr->iFontRecordList[i].iFontNameLength > 0) 5543 { 5544 // Allocate memory for the font name 5545 textse_ptr->iFontRecordList[i].iFontName = OSCL_ARRAY_NEW(uint8, textse_ptr->iFontRecordList[i].iFontNameLength + 1); 5546 5547 // Copy the font name string 5548 oscl_strncpy((char*)(textse_ptr->iFontRecordList[i].iFontName), (char*)(fontrec->getFontName()), textse_ptr->iFontRecordList[i].iFontNameLength + 1); 5549 textse_ptr->iFontRecordList[i].iFontName[textse_ptr->iFontRecordList[i].iFontNameLength] = '\0'; 5550 } 5551 } 5552 else 5553 { 5554 textse_ptr->iFontRecordList[i].iFontID = 0; 5555 textse_ptr->iFontRecordList[i].iFontNameLength = 0; 5556 textse_ptr->iFontRecordList[i].iFontName = NULL; 5557 } 5558 } 5559 ); 5560 OSCL_FIRST_CATCH_ANY(errcode, 5561 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Memory for font name could not be allocated")); 5562 return false); 5563 } 5564 // Save the text track's text sample entry 5565 aTrackPortInfo.iCurrentTextSampleEntry = tmp_shared_tse; 5566 // Save the state so text sample entry is only read when changed or not set yet 5567 aTrackPortInfo.iCurrentTextSampleEntryIndex = aEntryIndex; 5568 } 5569 5570 // Set the text sample entry to current one for this track 5571 aTextMediaData.iTextSampleEntry = aTrackPortInfo.iCurrentTextSampleEntry; 5572 5573 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Out")); 5574 return true; 5575 } 5576 5577 bool PVMFMP4FFParserNode::SendEndOfTrackCommand(PVMP4FFNodeTrackPortInfo& aTrackPortInfo) 5578 { 5579 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SendEndOfTrackCommand() In")); 5580 5581 PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd(); 5582 5583 sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID); 5584 5585 // Set the sequence number 5586 uint32 seqNum = aTrackPortInfo.iSeqNum; 5587 sharedMediaCmdPtr->setSeqNum(seqNum); 5588 aTrackPortInfo.iSeqNum++; 5589 5590 //set stream id 5591 sharedMediaCmdPtr->setStreamID(iStreamID); 5592 5593 // Set the timestamp 5594 // Retrieve timestamp and convert to milliseconds 5595 aTrackPortInfo.iClockConverter->update_clock(aTrackPortInfo.iTimestamp); 5596 uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000); 5597 sharedMediaCmdPtr->setTimestamp(timestamp); 5598 //EOS timestamp(aTrackPortInfo.iTimestamp)is considered while deciding the iResumeTimeStamp in the mediaoutput node 5599 //therefore its length should also be considered while making decision to forward or drop the packet 5600 //at the mediaoutput node. 5601 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT && 5602 iEOTForTextSentToMIO) 5603 { 5604 iEOTForTextSentToMIO = false; 5605 if (iSetTextSampleDurationZero) 5606 { 5607 sharedMediaCmdPtr->setDuration(0); 5608 } 5609 } 5610 else 5611 { 5612 //EOS timestamp(aTrackPortInfo.iTimestamp)is considered while deciding the iResumeTimeStamp in the mediaoutput node 5613 //therefore its length should also be considered while making decision to forward or drop the packet 5614 //at the mediaoutput node. 5615 sharedMediaCmdPtr->setDuration(PVMP4FF_DEFAULT_EOS_DURATION_IN_SEC *(aTrackPortInfo.iClockConverter->get_timescale())); 5616 } 5617 5618 PVMFSharedMediaMsgPtr mediaMsgOut; 5619 convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr); 5620 if (aTrackPortInfo.iPortInterface->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess) 5621 { 5622 return false; 5623 } 5624 5625 aTrackPortInfo.iTimestamp += (PVMP4FF_DEFAULT_EOS_DURATION_IN_SEC * aTrackPortInfo.iClockConverter->get_timescale()); 5626 5627 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::SendEndOfTrackCommand - Mime=%s, StreamID=%d, TrackID=%d, TS=%d, SEQNUM=%d", 5628 aTrackPortInfo.iMimeType.get_cstr(), 5629 iStreamID, 5630 aTrackPortInfo.iTrackId, 5631 timestamp, 5632 seqNum)); 5633 5634 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SendEndOfTrackCommand() Out")); 5635 return true; 5636 } 5637 5638 5639 void PVMFMP4FFParserNode::QueuePortActivity(const PVMFPortActivity &aActivity) 5640 { 5641 //queue a new port activity event 5642 int32 err; 5643 OSCL_TRY(err, iPortActivityQueue.push_back(aActivity);); 5644 if (err != OsclErrNone) 5645 { 5646 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::QueuePortActivity() Error push_back to queue failed")); 5647 ReportMP4FFParserErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort)); 5648 } 5649 else 5650 { 5651 //wake up the AO to process the port activity event. 5652 RunIfNotReady(); 5653 } 5654 } 5655 5656 5657 void PVMFMP4FFParserNode::HandlePortActivity(const PVMFPortActivity &aActivity) 5658 { 5659 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::HandlePortActivity() In")); 5660 5661 //A port is reporting some activity or state change. This code 5662 //figures out whether we need to queue a processing event 5663 //for the AO, and/or report a node event to the observer. 5664 5665 switch (aActivity.iType) 5666 { 5667 case PVMF_PORT_ACTIVITY_CREATED: 5668 //Report port created info event to the node. 5669 ReportMP4FFParserInfoEvent(PVMFInfoPortCreated, (OsclAny*)aActivity.iPort); 5670 break; 5671 5672 case PVMF_PORT_ACTIVITY_DELETED: 5673 //Report port deleted info event to the node. 5674 ReportMP4FFParserInfoEvent(PVMFInfoPortDeleted, (OsclAny*)aActivity.iPort); 5675 //Purge any port activity events already queued 5676 //for this port. 5677 { 5678 for (uint32 i = 0; i < iPortActivityQueue.size();) 5679 { 5680 if (iPortActivityQueue[i].iPort == aActivity.iPort) 5681 { 5682 iPortActivityQueue.erase(&iPortActivityQueue[i]); 5683 } 5684 else 5685 { 5686 i++; 5687 } 5688 } 5689 } 5690 break; 5691 5692 case PVMF_PORT_ACTIVITY_CONNECT: 5693 //nothing needed. 5694 break; 5695 5696 case PVMF_PORT_ACTIVITY_DISCONNECT: 5697 //nothing needed. 5698 break; 5699 5700 case PVMF_PORT_ACTIVITY_OUTGOING_MSG: 5701 //An outgoing message was queued on this port. 5702 //We only need to queue a port activity event on the 5703 //first message. Additional events will be queued during 5704 //the port processing as needed. 5705 if (aActivity.iPort->OutgoingMsgQueueSize() == 1) 5706 { 5707 QueuePortActivity(aActivity); 5708 } 5709 break; 5710 5711 case PVMF_PORT_ACTIVITY_INCOMING_MSG: 5712 // Incoming msg not supported 5713 break; 5714 5715 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY: 5716 //Outgoing queue is now busy. 5717 //No action is needed here-- the node checks for 5718 //outgoing queue busy as needed during data processing. 5719 break; 5720 5721 case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY: 5722 //Outgoing queue was previously busy, but is now ready. 5723 //We may need to schedule new processing events depending on the port type. 5724 5725 switch (aActivity.iPort->GetPortTag()) 5726 { 5727 case PVMF_MP4FFPARSERNODE_PORT_TYPE_OUTPUT: 5728 { 5729 // Find the trackportinfo for the port 5730 int32 i = 0; 5731 int32 maxtrack = iNodeTrackPortList.size(); 5732 while (i < maxtrack) 5733 { 5734 if (iNodeTrackPortList[i].iPortInterface == aActivity.iPort) 5735 { 5736 // Found the element. 5737 switch (iNodeTrackPortList[i].iState) 5738 { 5739 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_DESTFULL: 5740 { 5741 // Change the track state to only send the data 5742 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA; 5743 // Activate the node to process the track state change 5744 RunIfNotReady(); 5745 } 5746 break; 5747 5748 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK: 5749 { 5750 //wakeup the AO to try and send the end-of-track again. 5751 RunIfNotReady(); 5752 } 5753 break; 5754 5755 default: 5756 break; 5757 } 5758 } 5759 ++i; 5760 } 5761 } 5762 break; 5763 5764 default: 5765 break; 5766 } 5767 break; 5768 5769 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY: 5770 // The connected port has become busy (its incoming queue is 5771 // busy). 5772 // No action is needed here-- the port processing code 5773 // checks for connected port busy during data processing. 5774 break; 5775 5776 case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY: 5777 // The connected port has transitioned from Busy to Ready. 5778 // It's time to start processing outgoing messages again. 5779 if (aActivity.iPort->OutgoingMsgQueueSize() > 0) 5780 { 5781 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 5782 (0, "PVMFMP4FFParserNode::HandlePortActivity() Connected port is now ready Port=0x%x", 5783 aActivity.iPort)); 5784 5785 PVMFPortActivity activity(aActivity.iPort, PVMF_PORT_ACTIVITY_OUTGOING_MSG); 5786 QueuePortActivity(activity); 5787 } 5788 break; 5789 5790 default: 5791 break; 5792 } 5793 } 5794 5795 5796 void PVMFMP4FFParserNode::ProcessPortActivity() 5797 { 5798 //called by the AO to process a port activity message 5799 //Pop the queue... 5800 PVMFPortActivity activity(iPortActivityQueue.front()); 5801 iPortActivityQueue.erase(&iPortActivityQueue.front()); 5802 5803 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ProcessPortActivity() In")); 5804 5805 PVMFStatus status = PVMFSuccess; 5806 switch (activity.iType) 5807 { 5808 case PVMF_PORT_ACTIVITY_OUTGOING_MSG: 5809 status = ProcessOutgoingMsg(activity.iPort); 5810 //Re-queue the port activity event as long as there's 5811 //more data to process and it isn't in a Busy state. 5812 if (status != PVMFErrBusy && activity.iPort->OutgoingMsgQueueSize() > 0) 5813 { 5814 QueuePortActivity(activity); 5815 } 5816 break; 5817 5818 default: 5819 break; 5820 5821 } 5822 5823 //Report any unexpected failure in port processing... 5824 //(the InvalidState error happens when port input is suspended, 5825 //so don't report it.) 5826 if (status != PVMFErrBusy && status != PVMFSuccess && status != PVMFErrInvalidState) 5827 { 5828 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::ProcessPortActivity() Error unexpected failure Port=0x%x Type=0x%x", 5829 activity.iPort, activity.iType)); 5830 5831 ReportMP4FFParserErrorEvent(PVMFErrPortProcessing); 5832 } 5833 } 5834 5835 5836 PVMFStatus PVMFMP4FFParserNode::ProcessIncomingMsg(PVMFPortInterface* /*aPort*/) 5837 { 5838 // No incoming msg supported 5839 return PVMFSuccess; 5840 } 5841 5842 5843 PVMFStatus PVMFMP4FFParserNode::ProcessOutgoingMsg(PVMFPortInterface* aPort) 5844 { 5845 //Called by the AO to process one message off the outgoing 5846 //message queue for the given port. This routine will 5847 //try to send the data to the connected port. 5848 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ProcessOutgoingMsg() In aPort=0x%x", aPort)); 5849 5850 PVMFStatus status = aPort->Send(); 5851 if (status == PVMFErrBusy) 5852 { 5853 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFMP4FFParserNode::ProcessOutgoingMsg() Connected port is in busy state")); 5854 } 5855 5856 return status; 5857 } 5858 5859 void PVMFMP4FFParserNode::ResetAllTracks() 5860 { 5861 for (uint32 i = 0; i < iNodeTrackPortList.size(); ++i) 5862 { 5863 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED; 5864 iNodeTrackPortList[i].iMediaData.Unbind(); 5865 iNodeTrackPortList[i].iSeqNum = 0; 5866 iNodeTrackPortList[i].iPortInterface->ClearMsgQueues(); 5867 iNodeTrackPortList[i].iCurrentTextSampleEntry.Unbind(); 5868 } 5869 iPortActivityQueue.clear(); 5870 } 5871 5872 5873 bool PVMFMP4FFParserNode::ReleaseAllPorts() 5874 { 5875 while (!iNodeTrackPortList.empty()) 5876 { 5877 iNodeTrackPortList[0].iPortInterface->Disconnect(); 5878 iNodeTrackPortList[0].iMediaData.Unbind(); 5879 if (iNodeTrackPortList[0].iPortInterface) 5880 { 5881 OSCL_DELETE(((PVMFMP4FFParserOutPort*)iNodeTrackPortList[0].iPortInterface)); 5882 } 5883 if (iNodeTrackPortList[0].iClockConverter) 5884 { 5885 OSCL_DELETE(iNodeTrackPortList[0].iClockConverter); 5886 } 5887 if (iNodeTrackPortList[0].iTrackDataMemoryPool) 5888 { 5889 iNodeTrackPortList[0].iTrackDataMemoryPool->CancelFreeChunkAvailableCallback(); 5890 iNodeTrackPortList[0].iTrackDataMemoryPool->removeRef(); 5891 iNodeTrackPortList[0].iTrackDataMemoryPool = NULL; 5892 } 5893 if (iNodeTrackPortList[0].iMediaDataImplAlloc) 5894 { 5895 OSCL_DELETE(iNodeTrackPortList[0].iMediaDataImplAlloc); 5896 } 5897 if (iNodeTrackPortList[0].iTextMediaDataImplAlloc) 5898 { 5899 OSCL_DELETE(iNodeTrackPortList[0].iTextMediaDataImplAlloc); 5900 } 5901 if (iNodeTrackPortList[0].iMediaDataMemPool) 5902 { 5903 iNodeTrackPortList[0].iMediaDataMemPool->CancelFreeChunkAvailableCallback(); 5904 iNodeTrackPortList[0].iMediaDataMemPool->removeRef(); 5905 } 5906 if (iNodeTrackPortList[0].iMediaDataGroupAlloc) 5907 { 5908 iNodeTrackPortList[0].iMediaDataGroupAlloc->removeRef(); 5909 } 5910 if (iNodeTrackPortList[0].iMediaDataGroupImplMemPool) 5911 { 5912 iNodeTrackPortList[0].iMediaDataGroupImplMemPool->removeRef(); 5913 } 5914 if (iPortDataLog) 5915 { 5916 if (iNodeTrackPortList[0].iBinAppenderPtr.GetRep() != NULL) 5917 { 5918 iNodeTrackPortList[0].iPortLogger->RemoveAppender(iNodeTrackPortList[0].iBinAppenderPtr); 5919 iNodeTrackPortList[0].iBinAppenderPtr.Unbind(); 5920 } 5921 } 5922 iNodeTrackPortList.erase(iNodeTrackPortList.begin()); 5923 } 5924 5925 return true; 5926 } 5927 5928 5929 void PVMFMP4FFParserNode::RemoveAllCommands() 5930 { 5931 //The command queues are self-deleting, but we want to 5932 //notify the observer of unprocessed commands. 5933 while (!iCurrentCommand.empty()) 5934 { 5935 CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure); 5936 } 5937 5938 while (!iInputCommands.empty()) 5939 { 5940 CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure); 5941 } 5942 } 5943 5944 5945 void PVMFMP4FFParserNode::CleanupFileSource() 5946 { 5947 iAvailableMetadataKeys.clear(); 5948 iMP4ParserNodeMetadataValueCount = 0; 5949 iCPMMetadataKeys.clear(); 5950 iVideoDimensionInfoVec.clear(); 5951 5952 if (iDataStreamInterface != NULL) 5953 { 5954 PVInterface* iFace = OSCL_STATIC_CAST(PVInterface*, iDataStreamInterface); 5955 PVUuid uuid = PVMIDataStreamSyncInterfaceUuid; 5956 iDataStreamFactory->DestroyPVMFCPMPluginAccessInterface(uuid, iFace); 5957 iDataStreamInterface = NULL; 5958 } 5959 5960 if (iOMA2DecryptionBuffer != NULL) 5961 { 5962 OSCL_ARRAY_DELETE(iOMA2DecryptionBuffer); 5963 iOMA2DecryptionBuffer = NULL; 5964 } 5965 5966 iDownloadComplete = false; 5967 iMP4HeaderSize = 0; 5968 iProgressivelyDownlodable = false; 5969 iCPMSequenceInProgress = false; 5970 iFastTrackSession = false; 5971 iProtectedFile = false; 5972 iExternalDownload = false; 5973 iThumbNailMode = false; 5974 5975 if (iMP4FileHandle) 5976 { 5977 if (iExternalDownload == true) 5978 { 5979 iMP4FileHandle->DestroyDataStreamForExternalDownload(); 5980 } 5981 IMpeg4File::DestroyMP4FileObject(iMP4FileHandle); 5982 iMP4FileHandle = NULL; 5983 } 5984 5985 if (iFileHandle) 5986 { 5987 OSCL_DELETE(iFileHandle); 5988 iFileHandle = NULL; 5989 } 5990 5991 iSourceContextDataValid = false; 5992 iUseCPMPluginRegistry = false; 5993 iCPMSourceData.iFileHandle = NULL; 5994 if (iCPMContentAccessFactory != NULL) 5995 { 5996 if (iDecryptionInterface != NULL) 5997 { 5998 iDecryptionInterface->Reset(); 5999 /* Remove the decrpytion interface */ 6000 PVUuid uuid = PVMFCPMPluginDecryptionInterfaceUuid; 6001 iCPMContentAccessFactory->DestroyPVMFCPMPluginAccessInterface(uuid, iDecryptionInterface); 6002 iDecryptionInterface = NULL; 6003 } 6004 iCPMContentAccessFactory->removeRef(); 6005 iCPMContentAccessFactory = NULL; 6006 } 6007 if (iDataStreamFactory != NULL) 6008 { 6009 iDataStreamFactory->removeRef(); 6010 iDataStreamFactory = NULL; 6011 } 6012 6013 oWaitingOnLicense = false; 6014 iPoorlyInterleavedContentEventSent = false; 6015 } 6016 6017 // From PVMFMP4ProgDownloadSupportInterface 6018 int32 PVMFMP4FFParserNode::convertSizeToTime(uint32 fileSize, uint32& timeStamp) 6019 { 6020 if (iMP4FileHandle == NULL) 6021 { 6022 return DEFAULT_ERROR; 6023 } 6024 timeStamp = 0xFFFFFFFF; 6025 if (iNodeTrackPortList.size() <= 0) 6026 {//if track selection is not done, use all the tracks for calculation to avoid deadlock. 6027 int32 iNumTracks = iMP4FileHandle->getNumTracks(); 6028 uint32 iIdList[16]; 6029 if (iNumTracks != iMP4FileHandle->getTrackIDList(iIdList, iNumTracks)) 6030 { 6031 return DEFAULT_ERROR;//PVMFFailure; 6032 } 6033 uint32 track_timestamp = 0xFFFFFFFF; 6034 for (int32 i = 0; i < iNumTracks; i++) 6035 { 6036 uint32 trackID = iIdList[i]; 6037 int32 result = iMP4FileHandle->getMaxTrackTimeStamp(trackID, fileSize, track_timestamp); 6038 if (EVERYTHING_FINE == result) 6039 { 6040 // Convert the timestamp from media timescale to milliseconds 6041 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(trackID)); 6042 mcc.update_clock(track_timestamp); 6043 uint32 track_timeStamp = mcc.get_converted_ts(1000); 6044 if (track_timeStamp < timeStamp) 6045 { 6046 timeStamp = track_timeStamp; 6047 } 6048 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp, NPT[%d]=%d, TrackTS=%d", 6049 trackID, 6050 timeStamp, 6051 track_timestamp)); 6052 } 6053 else 6054 { 6055 return DEFAULT_ERROR;//PVMFFailure; 6056 } 6057 } 6058 iLastNPTCalcInConvertSizeToTime = timeStamp; 6059 iFileSizeLastConvertedToTime = fileSize; 6060 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime(), FileSize=%d, NPT=%d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime)); 6061 return EVERYTHING_FINE;//PVMFSuccess; 6062 } 6063 6064 //we do not count tracks that have reached EOS 6065 uint32 track_timestamp = 0xFFFFFFFF; 6066 int32 result = EVERYTHING_FINE; 6067 bool oAllTracksHaveReachedEOS = true; 6068 6069 if (iNodeTrackPortList[0].iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK) 6070 { 6071 //there is atleast one track that has not reached EOS 6072 oAllTracksHaveReachedEOS = false; 6073 result = iMP4FileHandle->getMaxTrackTimeStamp(iNodeTrackPortList[0].iTrackId, 6074 fileSize, 6075 track_timestamp); 6076 6077 if (result) 6078 { 6079 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp Failed, TrackID=%d, Mime=%s", 6080 iNodeTrackPortList[0].iTrackId, 6081 iNodeTrackPortList[0].iMimeType.get_cstr())); 6082 return result; 6083 } 6084 else 6085 { 6086 // Convert the timestamp from media timescale to milliseconds 6087 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(iNodeTrackPortList[0].iTrackId)); 6088 mcc.update_clock(track_timestamp); 6089 timeStamp = mcc.get_converted_ts(1000); 6090 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp, NPT=%d, TrackID=%d, Mime=%s", 6091 timeStamp, 6092 iNodeTrackPortList[0].iTrackId, 6093 iNodeTrackPortList[0].iMimeType.get_cstr())); 6094 } 6095 } 6096 6097 6098 for (uint32 ii = 1; ii < iNodeTrackPortList.size(); ++ii) 6099 { 6100 if (iNodeTrackPortList[ii].iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK) 6101 { 6102 //there is atleast one track that has not reached EOS 6103 oAllTracksHaveReachedEOS = false; 6104 result = iMP4FileHandle->getMaxTrackTimeStamp(iNodeTrackPortList[ii].iTrackId, 6105 fileSize, 6106 track_timestamp); 6107 6108 if (result) 6109 { 6110 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp Failed, TrackID=%d, Mime=%s", 6111 iNodeTrackPortList[ii].iTrackId, 6112 iNodeTrackPortList[ii].iMimeType.get_cstr())); 6113 return result; 6114 } 6115 6116 // Convert the timestamp from media timescale to milliseconds 6117 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(iNodeTrackPortList[ii].iTrackId)); 6118 mcc.update_clock(track_timestamp); 6119 track_timestamp = mcc.get_converted_ts(1000); 6120 6121 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp, NPT=%d, TrackID=%d, Mime=%s", 6122 track_timestamp, 6123 iNodeTrackPortList[ii].iTrackId, 6124 iNodeTrackPortList[ii].iMimeType.get_cstr())); 6125 6126 timeStamp = (track_timestamp < timeStamp) ? track_timestamp : timeStamp; 6127 } 6128 } 6129 if (oAllTracksHaveReachedEOS) 6130 { 6131 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - All Tracks have Reached EOS")); 6132 //if there are no playing tracks then this method should not even be called 6133 return DEFAULT_ERROR; 6134 } 6135 6136 iLastNPTCalcInConvertSizeToTime = timeStamp; 6137 iFileSizeLastConvertedToTime = fileSize; 6138 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime(), FileSize=%d, NPT=%d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime)); 6139 return EVERYTHING_FINE; 6140 } 6141 6142 void PVMFMP4FFParserNode::setFileSize(const uint32 aFileSize) 6143 { 6144 iDownloadFileSize = aFileSize; 6145 } 6146 6147 void PVMFMP4FFParserNode::setDownloadProgressInterface(PVMFDownloadProgressInterface* download_progress) 6148 { 6149 if (download_progress_interface) 6150 { 6151 download_progress_interface->removeRef(); 6152 } 6153 6154 download_progress_interface = download_progress; 6155 6156 // get the progress clock 6157 download_progress_clock = download_progress_interface->getDownloadProgressClock(); 6158 } 6159 6160 6161 void PVMFMP4FFParserNode::playResumeNotification(bool aDownloadComplete) 6162 { 6163 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() In")); 6164 6165 // If download has completed, unbind the DL progress clock so no more checks occur 6166 iDownloadComplete = aDownloadComplete; 6167 if (aDownloadComplete) 6168 { 6169 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() Download complete to unbind DL progress clock")); 6170 download_progress_clock.Unbind(); 6171 } 6172 6173 // resume playback 6174 if (autopaused) 6175 { 6176 autopaused = false; 6177 for (uint32 ii = 0; ii < iNodeTrackPortList.size(); ++ii) 6178 { 6179 switch (iNodeTrackPortList[ii].iState) 6180 { 6181 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE: 6182 iNodeTrackPortList[ii].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 6183 break; 6184 6185 default: 6186 // nothing to do 6187 break; 6188 } 6189 } 6190 6191 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::playResumeNotification() - Auto Resume Triggered, FileSize = %d, NPT = %d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime)); 6192 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() Sending PVMFInfoDataReady event")); 6193 // Schedule AO to run again 6194 RunIfNotReady(); 6195 } 6196 else if ((iCurrentCommand.empty() == false) && 6197 (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_INIT)) 6198 { 6199 /* Callbacks intiated as part of node init */ 6200 if (iDownloadComplete == true) 6201 { 6202 if (iCPMSequenceInProgress == false) 6203 { 6204 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::playResumeNotification() - Download Complete")); 6205 /* 6206 * Can come here only if we are doing PDL / PPB. 6207 * Init is still pending and download has completed. 6208 * A few possible scenarios here: 6209 * - Non-PDL, Non-DRM clip - we are waiting for the complete 6210 * file to be downloaded before we can parse the movie atom. 6211 * - OMA1 DRM clip - CPM seq complete, and 6212 * we were waiting on more data. 6213 * - OMA2 PDCF DRM clip - were waiting on more data to parse the movie atom, 6214 * CPM seq not complete since we need contents of movie atom to authorize 6215 * with CPM 6216 * - PDL, Non-DRM clip - we were waiting on more data and 6217 * download has completed 6218 */ 6219 if (iCPM) 6220 { 6221 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 6222 { 6223 PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL; 6224 if (ParseMP4File(iCurrentCommand, 6225 iCurrentCommand.front())) 6226 { 6227 if (CheckForOMA2AuthorizationComplete(oma2trackInfo) == PVMFPending) 6228 { 6229 RequestUsage(oma2trackInfo); 6230 return; 6231 } 6232 } 6233 } 6234 } 6235 CompleteInit(iCurrentCommand, iCurrentCommand.front()); 6236 } 6237 } 6238 //Ignore this callback we are waiting on notifydownload complete 6239 } 6240 6241 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() Out")); 6242 } 6243 6244 void PVMFMP4FFParserNode::notifyDownloadComplete() 6245 { 6246 if (!iProgressivelyDownlodable) 6247 { 6248 //in case of non-PDL files, we have to hold back on init complete 6249 //till donwnload is fully complete. So if that is the case, call 6250 //playResumeNotification and this will complete the pending init cmd 6251 playResumeNotification(true); 6252 } 6253 } 6254 6255 6256 bool PVMFMP4FFParserNode::MapMP4ErrorCodeToEventCode(int32 aMP4ErrCode, PVUuid& aEventUUID, int32& aEventCode) 6257 { 6258 // Set the UUID to the MP4 FF specific one and change to 6259 // file format one if necessary in the switch statement 6260 aEventUUID = PVMFMP4FFParserEventTypesUUID; 6261 6262 switch (aMP4ErrCode) 6263 { 6264 case READ_FAILED: 6265 aEventUUID = PVMFFileFormatEventTypesUUID; 6266 aEventCode = PVMFFFErrFileRead; 6267 break; 6268 6269 case DEFAULT_ERROR: 6270 aEventUUID = PVMFFileFormatEventTypesUUID; 6271 aEventCode = PVMFFFErrMisc; 6272 break; 6273 6274 case READ_USER_DATA_ATOM_FAILED: 6275 aEventCode = PVMFMP4FFParserErrUserDataAtomReadFailed; 6276 break; 6277 6278 case READ_MEDIA_DATA_ATOM_FAILED: 6279 aEventCode = PVMFMP4FFParserErrMediaDataAtomReadFailed; 6280 break; 6281 6282 case READ_MOVIE_ATOM_FAILED: 6283 aEventCode = PVMFMP4FFParserErrMovieAtomReadFailed; 6284 break; 6285 6286 case READ_MOVIE_HEADER_ATOM_FAILED: 6287 aEventCode = PVMFMP4FFParserErrMovieHeaderAtomReadFailed; 6288 break; 6289 6290 case READ_TRACK_ATOM_FAILED: 6291 aEventCode = PVMFMP4FFParserErrTrackAtomReadFailed; 6292 break; 6293 6294 case READ_TRACK_HEADER_ATOM_FAILED: 6295 aEventCode = PVMFMP4FFParserErrTrackHeaderAtomReadFailed; 6296 break; 6297 6298 case READ_TRACK_REFERENCE_ATOM_FAILED: 6299 aEventCode = PVMFMP4FFParserErrTrackReferenceAtomReadFailed; 6300 break; 6301 6302 case READ_TRACK_REFERENCE_TYPE_ATOM_FAILED: 6303 aEventCode = PVMFMP4FFParserErrTrackReferenceTypeAtomReadFailed; 6304 break; 6305 6306 case READ_OBJECT_DESCRIPTOR_ATOM_FAILED: 6307 aEventCode = PVMFMP4FFParserErrObjectDescriptorAtomReadFailed; 6308 break; 6309 6310 case READ_INITIAL_OBJECT_DESCRIPTOR_FAILED: 6311 aEventCode = PVMFMP4FFParserErrInitialObjectDescriptorReadFailed; 6312 break; 6313 6314 case READ_OBJECT_DESCRIPTOR_FAILED: 6315 aEventCode = PVMFMP4FFParserErrObjectDescriptorReadFailed; 6316 break; 6317 6318 case READ_MEDIA_ATOM_FAILED: 6319 aEventCode = PVMFMP4FFParserErrMediaAtomReadFailed; 6320 break; 6321 6322 case READ_MEDIA_HEADER_ATOM_FAILED: 6323 aEventCode = PVMFMP4FFParserErrMediaHeaderAtomReadFailed; 6324 break; 6325 6326 case READ_HANDLER_ATOM_FAILED: 6327 aEventCode = PVMFMP4FFParserErrHandlerAtomReadFailed; 6328 break; 6329 6330 case READ_MEDIA_INFORMATION_ATOM_FAILED: 6331 aEventCode = PVMFMP4FFParserErrMediaInformationAtomReadFailed; 6332 break; 6333 6334 case READ_MEDIA_INFORMATION_HEADER_ATOM_FAILED: 6335 aEventCode = PVMFMP4FFParserErrMediaInformationHeaderAtomReadFailed; 6336 break; 6337 6338 case READ_VIDEO_MEDIA_HEADER_ATOM_FAILED: 6339 aEventCode = PVMFMP4FFParserErrVideoMediaHeaderAtomReadFailed; 6340 break; 6341 6342 case READ_SOUND_MEDIA_HEADER_ATOM_FAILED: 6343 aEventCode = PVMFMP4FFParserErrSoundMediaHeaderAtomReadFailed; 6344 break; 6345 6346 case READ_HINT_MEDIA_HEADER_ATOM_FAILED: 6347 aEventCode = PVMFMP4FFParserErrHintMediaHeaderAtomReadFailed; 6348 break; 6349 6350 case READ_MPEG4_MEDIA_HEADER_ATOM_FAILED: 6351 aEventCode = PVMFMP4FFParserErrMPEG4MediaHeaderAtomReadFailed; 6352 break; 6353 6354 case READ_DATA_INFORMATION_ATOM_FAILED: 6355 aEventCode = PVMFMP4FFParserErrDataInformationAtomReadFailed; 6356 break; 6357 6358 case READ_DATA_REFERENCE_ATOM_FAILED: 6359 aEventCode = PVMFMP4FFParserErrDataReferenceAtomReadFailed; 6360 break; 6361 6362 case READ_DATA_ENTRY_URL_ATOM_FAILED: 6363 aEventCode = PVMFMP4FFParserErrDataEntryURLAtomReadFailed; 6364 break; 6365 6366 case READ_DATA_ENTRY_URN_ATOM_FAILED: 6367 aEventCode = PVMFMP4FFParserErrDataEntryURNAtomReadFailed; 6368 break; 6369 6370 case READ_SAMPLE_TABLE_ATOM_FAILED: 6371 aEventCode = PVMFMP4FFParserErrSampleTableAtomReadFailed; 6372 break; 6373 6374 case READ_TIME_TO_SAMPLE_ATOM_FAILED: 6375 aEventCode = PVMFMP4FFParserErrTimeToSampleAtomReadFailed; 6376 break; 6377 6378 case READ_SAMPLE_DESCRIPTION_ATOM_FAILED: 6379 aEventCode = PVMFMP4FFParserErrSampleDescriptionAtomReadFailed; 6380 break; 6381 6382 case READ_SAMPLE_SIZE_ATOM_FAILED: 6383 aEventCode = PVMFMP4FFParserErrSampleSizeAtomReadFailed; 6384 break; 6385 6386 case READ_SAMPLE_TO_CHUNK_ATOM_FAILED: 6387 aEventCode = PVMFMP4FFParserErrSampleToChunkAtomReadFailed; 6388 break; 6389 6390 case READ_CHUNK_OFFSET_ATOM_FAILED: 6391 aEventCode = PVMFMP4FFParserErrChunkOffsetAtomReadFailed; 6392 break; 6393 6394 case READ_SYNC_SAMPLE_ATOM_FAILED: 6395 aEventCode = PVMFMP4FFParserErrSyncSampleAtomReadFailed; 6396 break; 6397 6398 case READ_SAMPLE_ENTRY_FAILED: 6399 aEventCode = PVMFMP4FFParserErrSampleEntryReadFailed; 6400 break; 6401 6402 case READ_AUDIO_SAMPLE_ENTRY_FAILED: 6403 aEventCode = PVMFMP4FFParserErrAudioSampleEntryReadFailed; 6404 break; 6405 6406 case READ_VISUAL_SAMPLE_ENTRY_FAILED: 6407 aEventCode = PVMFMP4FFParserErrVisualSampleEntryReadFailed; 6408 break; 6409 6410 case READ_HINT_SAMPLE_ENTRY_FAILED: 6411 aEventCode = PVMFMP4FFParserErrHintSampleEntryReadFailed; 6412 break; 6413 6414 case READ_MPEG_SAMPLE_ENTRY_FAILED: 6415 aEventCode = PVMFMP4FFParserErrMPEGSampleEntryReadFailed; 6416 break; 6417 6418 case READ_AUDIO_HINT_SAMPLE_FAILED: 6419 aEventCode = PVMFMP4FFParserErrAudioHintSampleReadFailed; 6420 break; 6421 6422 case READ_VIDEO_HINT_SAMPLE_FAILED: 6423 aEventCode = PVMFMP4FFParserErrVideoHintSampleReadFailed; 6424 break; 6425 6426 case READ_ESD_ATOM_FAILED: 6427 aEventCode = PVMFMP4FFParserErrESDAtomReadFailed; 6428 break; 6429 6430 case READ_ES_DESCRIPTOR_FAILED: 6431 aEventCode = PVMFMP4FFParserErrESDescriptorReadFailed; 6432 break; 6433 6434 case READ_SL_CONFIG_DESCRIPTOR_FAILED: 6435 aEventCode = PVMFMP4FFParserErrSLConfigDescriptorReadFailed; 6436 break; 6437 6438 case READ_DECODER_CONFIG_DESCRIPTOR_FAILED: 6439 aEventCode = PVMFMP4FFParserErrDecoderConfigDescriptorReadFailed; 6440 break; 6441 6442 case READ_DECODER_SPECIFIC_INFO_FAILED: 6443 aEventCode = PVMFMP4FFParserErrDecoderSpecificInfoReadFailed; 6444 break; 6445 6446 case DUPLICATE_MOVIE_ATOMS: 6447 aEventCode = PVMFMP4FFParserErrDuplicateMovieAtoms; 6448 break; 6449 6450 case NO_MOVIE_ATOM_PRESENT: 6451 aEventCode = PVMFMP4FFParserErrNoMovieAtomPresent; 6452 break; 6453 6454 case DUPLICATE_OBJECT_DESCRIPTORS: 6455 aEventCode = PVMFMP4FFParserErrDuplicateObjectDescriptors; 6456 break; 6457 6458 case NO_OBJECT_DESCRIPTOR_ATOM_PRESENT: 6459 aEventCode = PVMFMP4FFParserErrNoObjectDescriptorAtomPresent; 6460 break; 6461 6462 case DUPLICATE_MOVIE_HEADERS: 6463 aEventCode = PVMFMP4FFParserErrDuplicateMovieHeaders; 6464 break; 6465 6466 case NO_MOVIE_HEADER_ATOM_PRESENT: 6467 aEventCode = PVMFMP4FFParserErrNoMovieHeaderAtomPresent; 6468 break; 6469 6470 case DUPLICATE_TRACK_REFERENCE_ATOMS: 6471 aEventCode = PVMFMP4FFParserErrDuplicateTrackReferenceAtoms; 6472 break; 6473 6474 case DUPLICATE_TRACK_HEADER_ATOMS: 6475 aEventCode = PVMFMP4FFParserErrDuplicateTrackHeaderAtoms; 6476 break; 6477 6478 case NO_TRACK_HEADER_ATOM_PRESENT: 6479 aEventCode = PVMFMP4FFParserErrNoTrackHeaderAtomPresent; 6480 break; 6481 6482 case DUPLICATE_MEDIA_ATOMS: 6483 aEventCode = PVMFMP4FFParserErrDuplicateMediaAtoms; 6484 break; 6485 6486 case NO_MEDIA_ATOM_PRESENT: 6487 aEventCode = PVMFMP4FFParserErrNoMediaAtomPresent; 6488 break; 6489 6490 case READ_UNKNOWN_ATOM: 6491 aEventCode = PVMFMP4FFParserErrUnknownAtom; 6492 break; 6493 6494 case NON_PV_CONTENT: 6495 aEventCode = PVMFMP4FFParserErrNonPVContent; 6496 break; 6497 6498 case FILE_NOT_STREAMABLE: 6499 aEventCode = PVMFMP4FFParserErrFileNotStreamable; 6500 break; 6501 6502 case INSUFFICIENT_BUFFER_SIZE: 6503 aEventUUID = PVMFFileFormatEventTypesUUID; 6504 aEventCode = PVMFFFErrInsufficientBuffer; 6505 break; 6506 6507 case INVALID_SAMPLE_SIZE: 6508 aEventCode = PVMFMP4FFParserErrInvalidSampleSize; 6509 break; 6510 6511 case INVALID_CHUNK_OFFSET: 6512 aEventCode = PVMFMP4FFParserErrInvalidChunkOffset; 6513 break; 6514 6515 case MEMORY_ALLOCATION_FAILED: 6516 aEventCode = PVMFMP4FFParserErrMemoryAllocationFailed; 6517 break; 6518 6519 case READ_FILE_TYPE_ATOM_FAILED: 6520 aEventCode = PVMFMP4FFParserErrFileTypeAtomReadFailed; 6521 break; 6522 6523 case ZERO_OR_NEGATIVE_ATOM_SIZE: 6524 aEventCode = PVMFMP4FFParserErrZeroOrNegativeAtomSize; 6525 break; 6526 6527 case NO_MEDIA_TRACKS_IN_FILE: 6528 aEventCode = PVMFMP4FFParserErrNoMediaTracksInFile; 6529 break; 6530 6531 case NO_META_DATA_FOR_MEDIA_TRACKS: 6532 aEventCode = PVMFMP4FFParserErrNoMetadataForMediaTracks; 6533 break; 6534 6535 case MEDIA_DATA_NOT_SELF_CONTAINED: 6536 aEventCode = PVMFMP4FFParserErrMediaDataNotSelfContained; 6537 break; 6538 6539 case READ_PVTI_SESSION_INFO_FAILED: 6540 aEventCode = PVMFMP4FFParserErrPVTISessionInfoReadFailed; 6541 break; 6542 6543 case READ_PVTI_MEDIA_INFO_FAILED: 6544 aEventCode = PVMFMP4FFParserErrPVTIMediaInfoReadFailed; 6545 break; 6546 6547 case READ_CONTENT_VERSION_FAILED: 6548 aEventCode = PVMFMP4FFParserErrContentVersionReadFailed; 6549 break; 6550 6551 case READ_DOWNLOAD_ATOM_FAILED: 6552 aEventCode = PVMFMP4FFParserErrDownloadAtomReadFailed; 6553 break; 6554 6555 case READ_TRACK_INFO_ATOM_FAILED: 6556 aEventCode = PVMFMP4FFParserErrTrackInfoAtomReadFailed; 6557 break; 6558 6559 case READ_REQUIREMENTS_ATOM_FAILED: 6560 aEventCode = PVMFMP4FFParserErrRequirementsAtomReadFailed; 6561 break; 6562 6563 case READ_WMF_SET_MEDIA_ATOM_FAILED: 6564 aEventCode = PVMFMP4FFParserErrWMFSetMediaAtomReadFailed; 6565 break; 6566 6567 case READ_WMF_SET_SESSION_ATOM_FAILED: 6568 aEventCode = PVMFMP4FFParserErrWMFSetSessionAtomReadFailed; 6569 break; 6570 6571 case READ_PV_USER_DATA_ATOM_FAILED: 6572 aEventCode = PVMFMP4FFParserErrPVUserDataAtomReadFailed; 6573 break; 6574 6575 case READ_VIDEO_INFORMATION_ATOM_FAILED: 6576 aEventCode = PVMFMP4FFParserErrVideoInformationAtomReadFailed; 6577 break; 6578 6579 case READ_RANDOM_ACCESS_ATOM_FAILED: 6580 aEventCode = PVMFMP4FFParserErrRandomAccessAtomReadFailed; 6581 break; 6582 6583 case READ_AMR_SAMPLE_ENTRY_FAILED: 6584 aEventCode = PVMFMP4FFParserErrAMRSampleEntryReadFailed; 6585 break; 6586 6587 case READ_H263_SAMPLE_ENTRY_FAILED: 6588 aEventCode = PVMFMP4FFParserErrH263SampleEntryReadFailed; 6589 break; 6590 6591 case FILE_OPEN_FAILED: 6592 aEventUUID = PVMFFileFormatEventTypesUUID; 6593 aEventCode = PVMFFFErrFileOpen; 6594 break; 6595 6596 case READ_UUID_ATOM_FAILED: 6597 aEventCode = PVMFMP4FFParserErrUUIDAtomReadFailed; 6598 break; 6599 6600 case FILE_VERSION_NOT_SUPPORTED: 6601 aEventCode = PVMFMP4FFParserErrFileVersionNotSupported; 6602 break; 6603 6604 case TRACK_VERSION_NOT_SUPPORTED: 6605 aEventCode = PVMFMP4FFParserErrTrackVersioNotSupported; 6606 break; 6607 6608 6609 case READ_COPYRIGHT_ATOM_FAILED: 6610 aEventCode = PVMFMP4FFParserErrCopyrightAtomReadFailed; 6611 break; 6612 6613 case READ_FONT_TABLE_ATOM_FAILED: 6614 aEventCode = PVMFMP4FFParserErrFontTableAtomReadFailed; 6615 break; 6616 6617 case READ_FONT_RECORD_FAILED: 6618 aEventCode = PVMFMP4FFParserErrFontRecordReadFailed; 6619 break; 6620 6621 case FILE_PSEUDO_STREAMABLE: 6622 aEventCode = PVMFMP4FFParserErrPseudostreamableFile; 6623 break; 6624 6625 case FILE_NOT_PSEUDO_STREAMABLE: 6626 aEventCode = PVMFMP4FFParserErrNotPseudostreamableFile; 6627 break; 6628 6629 case READ_PV_ENTITY_TAG_ATOM_FAILED: 6630 aEventCode = PVMFMP4FFParserErrPVEntityTagAtomReadFailed; 6631 break; 6632 6633 case DUPLICATE_FILE_TYPE_ATOMS: 6634 aEventCode = PVMFMP4FFParserErrDuplicateFileTypeAtoms; 6635 break; 6636 6637 case UNSUPPORTED_FILE_TYPE: 6638 aEventCode = PVMFMP4FFParserErrUnsupportedFileType; 6639 break; 6640 6641 case FILE_TYPE_ATOM_NOT_FOUND: 6642 aEventCode = PVMFMP4FFParserErrFileTypeAtomNotFound; 6643 break; 6644 6645 case READ_EDIT_ATOM_FAILED: 6646 aEventCode = PVMFMP4FFParserErrEditAtomReadFailed; 6647 break; 6648 6649 case READ_EDITLIST_ATOM_FAILED: 6650 aEventCode = PVMFMP4FFParserErrEditlistAtomReadFailed; 6651 break; 6652 6653 case ATOM_VERSION_NOT_SUPPORTED: 6654 aEventCode = PVMFMP4FFParserErrAtomVersionNotSupported; 6655 break; 6656 6657 case READ_UDTA_TITL_FAILED: 6658 aEventCode = PVMFMP4FFParserErrUDTATITLReadFailed; 6659 break; 6660 6661 case READ_UDTA_DSCP_FAILED: 6662 aEventCode = PVMFMP4FFParserErrUDTADSCPReadFailed; 6663 break; 6664 6665 case READ_UDTA_CPRT_FAILED: 6666 aEventCode = PVMFMP4FFParserErrUDTACPRTReadFailed; 6667 break; 6668 6669 case READ_UDTA_PERF_FAILED: 6670 aEventCode = PVMFMP4FFParserErrUDTAPERFReadFailed; 6671 break; 6672 6673 case READ_UDTA_AUTH_FAILED: 6674 aEventCode = PVMFMP4FFParserErrUDTAUTHReadFailed; 6675 break; 6676 6677 case READ_UDTA_GNRE_FAILED: 6678 aEventCode = PVMFMP4FFParserErrUDTAGNREReadFailed; 6679 break; 6680 6681 case READ_UDTA_RTNG_FAILED: 6682 aEventCode = PVMFMP4FFParserErrUDTARTNGReadFailed; 6683 break; 6684 6685 case READ_UDTA_CLSF_FAILED: 6686 aEventCode = PVMFMP4FFParserErrUDTACLSFReadFailed; 6687 break; 6688 6689 case READ_UDTA_KYWD_FAILED: 6690 aEventCode = PVMFMP4FFParserErrUDTAKYWDReadFailed; 6691 break; 6692 6693 case READ_PV_CONTENT_TYPE_ATOM_FAILED: 6694 aEventCode = PVMFMP4FFParserErrPVContentTypeAtomReadFailed; 6695 break; 6696 6697 case INSUFFICIENT_DATA: 6698 aEventUUID = PVMFFileFormatEventTypesUUID; 6699 aEventCode = PVMFFFErrInsufficientData; 6700 break; 6701 6702 case NOT_SUPPORTED: 6703 aEventUUID = PVMFFileFormatEventTypesUUID; 6704 aEventCode = PVMFFFErrNotSupported; 6705 break; 6706 6707 case READ_AVC_SAMPLE_ENTRY_FAILED: 6708 aEventUUID = PVMFFileFormatEventTypesUUID; 6709 aEventCode = PVMFMP4FFParserErrReadAVCSampleEntryFailed; 6710 break; 6711 6712 case READ_AVC_CONFIG_BOX_FAILED: 6713 aEventUUID = PVMFFileFormatEventTypesUUID; 6714 aEventCode = PVMFMP4FFParserErrReadAVCConfigBoxFailed; 6715 break; 6716 6717 case READ_MPEG4_BITRATE_BOX_FAILED: 6718 aEventUUID = PVMFFileFormatEventTypesUUID; 6719 aEventCode = PVMFMP4FFParserErrReadMPEG4BitRateBoxFailed; 6720 break; 6721 6722 case EVERYTHING_FINE: 6723 OSCL_ASSERT(false); // Should not pass this "error" code to this function 6724 default: 6725 return false; 6726 } 6727 6728 return true; 6729 } 6730 6731 /* CPM related */ 6732 void PVMFMP4FFParserNode::InitCPM() 6733 { 6734 iCPMSequenceInProgress = true; 6735 iCPMInitCmdId = iCPM->Init(); 6736 } 6737 6738 void PVMFMP4FFParserNode::OpenCPMSession() 6739 { 6740 iCPMSequenceInProgress = true; 6741 iCPMOpenSessionCmdId = iCPM->OpenSession(iCPMSessionID); 6742 } 6743 6744 void PVMFMP4FFParserNode::GetCPMLicenseInterface() 6745 { 6746 iCPMSequenceInProgress = true; 6747 iCPMLicenseInterfacePVI = NULL; 6748 iCPMGetLicenseInterfaceCmdId = 6749 iCPM->QueryInterface(iCPMSessionID, 6750 PVMFCPMPluginLicenseInterfaceUuid, 6751 iCPMLicenseInterfacePVI); 6752 } 6753 6754 bool PVMFMP4FFParserNode::GetCPMContentAccessFactory() 6755 { 6756 iCPMSequenceInProgress = true; 6757 PVMFStatus status = iCPM->GetContentAccessFactory(iCPMSessionID, 6758 iCPMContentAccessFactory); 6759 if (status != PVMFSuccess) 6760 { 6761 return false; 6762 } 6763 return true; 6764 } 6765 6766 void PVMFMP4FFParserNode::CPMRegisterContent() 6767 { 6768 iCPMSequenceInProgress = true; 6769 if (iSourceContextDataValid == true) 6770 { 6771 iCPMRegisterContentCmdId = iCPM->RegisterContent(iCPMSessionID, 6772 iFilename, 6773 iSourceFormat, 6774 (OsclAny*) & iSourceContextData); 6775 } 6776 else 6777 { 6778 iCPMRegisterContentCmdId = iCPM->RegisterContent(iCPMSessionID, 6779 iFilename, 6780 iSourceFormat, 6781 (OsclAny*) & iCPMSourceData); 6782 } 6783 } 6784 6785 void PVMFMP4FFParserNode::GetCPMContentType() 6786 { 6787 iCPMContentType = iCPM->GetCPMContentType(iCPMSessionID); 6788 } 6789 6790 bool PVMFMP4FFParserNode::GetCPMMetaDataExtensionInterface() 6791 { 6792 iCPMSequenceInProgress = true; 6793 PVInterface* temp = NULL; 6794 bool retVal = 6795 iCPM->queryInterface(KPVMFMetadataExtensionUuid, temp); 6796 iCPMMetaDataExtensionInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, temp); 6797 return retVal; 6798 } 6799 6800 PVMP4FFNodeTrackOMA2DRMInfo* 6801 PVMFMP4FFParserNode::LookUpOMA2TrackInfoForTrack(uint32 aTrackID) 6802 { 6803 Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it; 6804 for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++) 6805 { 6806 if (it->iTrackId == aTrackID) 6807 { 6808 return it; 6809 } 6810 } 6811 return NULL; 6812 } 6813 6814 PVMFStatus PVMFMP4FFParserNode::CheckForOMA2AuthorizationComplete(PVMP4FFNodeTrackOMA2DRMInfo*& aInfo) 6815 { 6816 aInfo = NULL; 6817 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 6818 { 6819 /* Look for a track that needs authorization */ 6820 Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it; 6821 for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++) 6822 { 6823 if (it->iOMA2TrackAuthorizationComplete == false) 6824 { 6825 aInfo = it; 6826 return PVMFPending; 6827 } 6828 } 6829 } 6830 else 6831 { 6832 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForOMA2AuthorizationComplete - Invalid CPM ContentType")); 6833 return PVMFFailure; 6834 } 6835 return PVMFSuccess; 6836 } 6837 6838 void PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete() 6839 { 6840 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 6841 { 6842 /* Look for a track that needs authorization */ 6843 Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it; 6844 for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++) 6845 { 6846 if (it->iOMA2TrackAuthorizationInProgress == true) 6847 { 6848 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete - TrackId=%d", it->iTrackId)); 6849 it->iOMA2TrackAuthorizationComplete = true; 6850 it->iOMA2TrackAuthorizationInProgress = false; 6851 if (iApprovedUsage.value.uint32_value == 6852 iRequestedUsage.value.uint32_value) 6853 { 6854 it->iOMA2TrackAuthorized = true; 6855 } 6856 return; 6857 } 6858 } 6859 } 6860 else 6861 { 6862 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete - Invalid CPM ContentType")); 6863 OSCL_ASSERT(false); 6864 } 6865 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete - Couldn't Find Track")); 6866 } 6867 6868 bool PVMFMP4FFParserNode::CheckForOMA2UsageApproval() 6869 { 6870 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 6871 { 6872 /* Look for a track that needs authorization */ 6873 Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it; 6874 for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++) 6875 { 6876 if (it->iOMA2TrackAuthorized == false) 6877 { 6878 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForOMA2UsageApproval - Not Authorized - TrackId=%d", it->iTrackId)); 6879 return false; 6880 } 6881 } 6882 } 6883 else 6884 { 6885 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForOMA2UsageApproval - Invalid CPM ContentType")); 6886 OSCL_ASSERT(false); 6887 } 6888 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForOMA2UsageApproval - All Tracks Authorized")); 6889 return true; 6890 } 6891 6892 void PVMFMP4FFParserNode::ResetOMA2Flags() 6893 { 6894 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 6895 { 6896 /* Look for a track that needs authorization */ 6897 Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it; 6898 for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++) 6899 { 6900 it->iOMA2TrackAuthorized = false; 6901 it->iOMA2TrackAuthorizationComplete = false; 6902 it->iOMA2TrackAuthorizationInProgress = false; 6903 } 6904 } 6905 else 6906 { 6907 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::ResetOMA2Flags - Invalid CPM ContentType")); 6908 OSCL_ASSERT(false); 6909 } 6910 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ResetOMA2Flags - Complete")); 6911 return; 6912 } 6913 6914 void PVMFMP4FFParserNode::RequestUsage(PVMP4FFNodeTrackOMA2DRMInfo* aInfo) 6915 { 6916 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 6917 { 6918 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RequestUsage - TrackId=%d", aInfo->iTrackId)); 6919 aInfo->iOMA2TrackAuthorizationInProgress = true; 6920 PopulateOMA2DRMInfo(aInfo); 6921 } 6922 else if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) || 6923 (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS)) 6924 { 6925 PopulateOMA1DRMInfo(); 6926 } 6927 else 6928 { 6929 /* Error */ 6930 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::RequestUsage - Invalid CPM Type")); 6931 OSCL_LEAVE(PVMFErrNotSupported); 6932 } 6933 6934 iCPM->GetContentAccessFactory(iCPMSessionID, iCPMContentAccessFactory); 6935 6936 if (iDataStreamReadCapacityObserver != NULL) 6937 { 6938 int32 leavecode = 0; 6939 OSCL_TRY(leavecode, 6940 iCPMContentAccessFactory->SetStreamReadCapacityObserver(iDataStreamReadCapacityObserver);); 6941 if (leavecode != 0) 6942 { 6943 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetCPMContentAccessFactory: SetStreamReadCapacityObserver failed")); 6944 } 6945 } 6946 6947 iCPMSequenceInProgress = true; 6948 iCPMRequestUsageId = iCPM->ApproveUsage(iCPMSessionID, 6949 iRequestedUsage, 6950 iApprovedUsage, 6951 iAuthorizationDataKvp, 6952 iUsageID); 6953 oWaitingOnLicense = true; 6954 } 6955 6956 void PVMFMP4FFParserNode::PopulateOMA2DRMInfo(PVMP4FFNodeTrackOMA2DRMInfo* aInfo) 6957 { 6958 //Cleanup any old key. 6959 if (iRequestedUsage.key) 6960 { 6961 OSCL_ARRAY_DELETE(iRequestedUsage.key); 6962 iRequestedUsage.key = NULL; 6963 } 6964 6965 if (iApprovedUsage.key) 6966 { 6967 OSCL_ARRAY_DELETE(iApprovedUsage.key); 6968 iApprovedUsage.key = NULL; 6969 } 6970 6971 if (iAuthorizationDataKvp.key) 6972 { 6973 OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key); 6974 iAuthorizationDataKvp.key = NULL; 6975 } 6976 6977 int32 UseKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING)) + oscl_strlen(_STRLIT_CHAR(";track_id=0")); 6978 int32 AuthKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING)) + oscl_strlen(_STRLIT_CHAR(";track_id=0")); 6979 int32 leavecode = 0; 6980 6981 OSCL_TRY(leavecode, 6982 iRequestedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1); 6983 iApprovedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1); 6984 iAuthorizationDataKvp.key = OSCL_ARRAY_NEW(char, AuthKeyLen + 1); 6985 ); 6986 if (leavecode || !iRequestedUsage.key || !iApprovedUsage.key || !iAuthorizationDataKvp.key) 6987 { 6988 if (iRequestedUsage.key) 6989 { 6990 OSCL_ARRAY_DELETE(iRequestedUsage.key); 6991 iRequestedUsage.key = NULL; 6992 } 6993 if (iApprovedUsage.key) 6994 { 6995 OSCL_ARRAY_DELETE(iApprovedUsage.key); 6996 iApprovedUsage.key = NULL; 6997 } 6998 if (iAuthorizationDataKvp.key) 6999 { 7000 OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key); 7001 iAuthorizationDataKvp.key = NULL; 7002 } 7003 7004 return; 7005 } 7006 7007 char trackID[16]; 7008 oscl_snprintf(trackID, 16, ";track_id=%d", aInfo->iTrackId); 7009 trackID[15] = '\0'; 7010 7011 OSCL_StackString<256> requestUsageKey; 7012 requestUsageKey += _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING); 7013 requestUsageKey += trackID; 7014 7015 oscl_strncpy(iRequestedUsage.key, 7016 requestUsageKey.get_cstr(), 7017 UseKeyLen); 7018 iRequestedUsage.key[UseKeyLen] = 0; 7019 iRequestedUsage.length = 0; 7020 iRequestedUsage.capacity = 0; 7021 iRequestedUsage.value.uint32_value = 7022 (BITMASK_PVMF_CPM_DRM_INTENT_PLAY | 7023 BITMASK_PVMF_CPM_DRM_INTENT_PAUSE | 7024 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD | 7025 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK); 7026 7027 oscl_strncpy(iApprovedUsage.key, 7028 requestUsageKey.get_cstr(), 7029 UseKeyLen); 7030 iApprovedUsage.key[UseKeyLen] = 0; 7031 iApprovedUsage.length = 0; 7032 iApprovedUsage.capacity = 0; 7033 iApprovedUsage.value.uint32_value = 0; 7034 7035 OSCL_StackString<512> authorizationKey; 7036 authorizationKey += _STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING); 7037 authorizationKey += trackID; 7038 7039 oscl_strncpy(iAuthorizationDataKvp.key, 7040 authorizationKey.get_cstr(), 7041 AuthKeyLen); 7042 iAuthorizationDataKvp.key[AuthKeyLen] = 0; 7043 7044 iAuthorizationDataKvp.length = aInfo->iDRMInfoSize; 7045 iAuthorizationDataKvp.capacity = aInfo->iDRMInfoSize; 7046 iAuthorizationDataKvp.value.pUint8_value = aInfo->iDRMInfo; 7047 } 7048 7049 void PVMFMP4FFParserNode::PopulateOMA1DRMInfo() 7050 { 7051 //Cleanup any old key. 7052 if (iRequestedUsage.key) 7053 { 7054 OSCL_ARRAY_DELETE(iRequestedUsage.key); 7055 iRequestedUsage.key = NULL; 7056 } 7057 7058 if (iApprovedUsage.key) 7059 { 7060 OSCL_ARRAY_DELETE(iApprovedUsage.key); 7061 iApprovedUsage.key = NULL; 7062 } 7063 7064 if (iAuthorizationDataKvp.key) 7065 { 7066 OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key); 7067 iAuthorizationDataKvp.key = NULL; 7068 } 7069 7070 int32 UseKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING)); 7071 int32 AuthKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING)); 7072 int32 leavecode = 0; 7073 7074 OSCL_TRY(leavecode, 7075 iRequestedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1); 7076 iApprovedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1); 7077 iAuthorizationDataKvp.key = OSCL_ARRAY_NEW(char, AuthKeyLen + 1); 7078 ); 7079 if (leavecode || !iRequestedUsage.key || !iApprovedUsage.key || !iAuthorizationDataKvp.key) 7080 { 7081 if (iRequestedUsage.key) 7082 { 7083 OSCL_ARRAY_DELETE(iRequestedUsage.key); 7084 iRequestedUsage.key = NULL; 7085 } 7086 if (iApprovedUsage.key) 7087 { 7088 OSCL_ARRAY_DELETE(iApprovedUsage.key); 7089 iApprovedUsage.key = NULL; 7090 } 7091 if (iAuthorizationDataKvp.key) 7092 { 7093 OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key); 7094 iAuthorizationDataKvp.key = NULL; 7095 } 7096 7097 return; 7098 } 7099 7100 oscl_strncpy(iRequestedUsage.key, 7101 _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING), 7102 UseKeyLen); 7103 iRequestedUsage.key[UseKeyLen] = 0; 7104 iRequestedUsage.length = 0; 7105 iRequestedUsage.capacity = 0; 7106 if (iPreviewMode) 7107 { 7108 iRequestedUsage.value.uint32_value = 7109 (BITMASK_PVMF_CPM_DRM_INTENT_PREVIEW | 7110 BITMASK_PVMF_CPM_DRM_INTENT_PAUSE | 7111 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD | 7112 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK); 7113 } 7114 else 7115 { 7116 iRequestedUsage.value.uint32_value = 7117 (BITMASK_PVMF_CPM_DRM_INTENT_PLAY | 7118 BITMASK_PVMF_CPM_DRM_INTENT_PAUSE | 7119 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD | 7120 BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK); 7121 } 7122 oscl_strncpy(iApprovedUsage.key, 7123 _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING), 7124 UseKeyLen); 7125 iApprovedUsage.key[UseKeyLen] = 0; 7126 iApprovedUsage.length = 0; 7127 iApprovedUsage.capacity = 0; 7128 iApprovedUsage.value.uint32_value = 0; 7129 7130 oscl_strncpy(iAuthorizationDataKvp.key, 7131 _STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING), 7132 AuthKeyLen); 7133 iAuthorizationDataKvp.key[AuthKeyLen] = 0; 7134 iAuthorizationDataKvp.length = 0; 7135 iAuthorizationDataKvp.capacity = 0; 7136 iAuthorizationDataKvp.value.pUint8_value = NULL; 7137 } 7138 7139 void PVMFMP4FFParserNode::SendUsageComplete() 7140 { 7141 iCPMSequenceInProgress = true; 7142 iCPMUsageCompleteCmdId = iCPM->UsageComplete(iCPMSessionID, iUsageID); 7143 } 7144 7145 void PVMFMP4FFParserNode::CloseCPMSession() 7146 { 7147 iCPMCloseSessionCmdId = iCPM->CloseSession(iCPMSessionID); 7148 } 7149 7150 void PVMFMP4FFParserNode::ResetCPM() 7151 { 7152 iCPMResetCmdId = iCPM->Reset(); 7153 } 7154 7155 void PVMFMP4FFParserNode::GetCPMMetaDataKeys() 7156 { 7157 if (iCPMMetaDataExtensionInterface != NULL) 7158 { 7159 iCPMMetadataKeys.clear(); 7160 iCPMGetMetaDataKeysCmdId = 7161 iCPMMetaDataExtensionInterface->GetNodeMetadataKeys(iCPMSessionID, 7162 iCPMMetadataKeys, 7163 0, 7164 PVMF_MP4FFPARSERNODE_MAX_CPM_METADATA_KEYS); 7165 } 7166 } 7167 7168 PVMFStatus 7169 PVMFMP4FFParserNode::CheckCPMCommandCompleteStatus(PVMFCommandId aID, 7170 PVMFStatus aStatus) 7171 { 7172 PVMFStatus status = aStatus; 7173 if (aID == iCPMGetLicenseInterfaceCmdId) 7174 { 7175 if (aStatus == PVMFErrNotSupported) 7176 { 7177 /* License Interface is Optional */ 7178 status = PVMFSuccess; 7179 } 7180 } 7181 else if (aID == iCPMRegisterContentCmdId) 7182 { 7183 if (aStatus == PVMFErrNotSupported) 7184 { 7185 /* CPM doesnt care about this content */ 7186 status = PVMFErrNotSupported; 7187 } 7188 } 7189 else if (aID == iCPMRequestUsageId) 7190 { 7191 if (iCPMSourceData.iIntent & BITMASK_PVMF_SOURCE_INTENT_GETMETADATA) 7192 { 7193 if (aStatus != PVMFSuccess) 7194 { 7195 /* 7196 * If we are doing metadata only then we don't care 7197 * if license is not available 7198 */ 7199 status = PVMFSuccess; 7200 } 7201 } 7202 } 7203 return status; 7204 } 7205 7206 void PVMFMP4FFParserNode::CPMCommandCompleted(const PVMFCmdResp& aResponse) 7207 { 7208 iCPMSequenceInProgress = false; 7209 PVMFCommandId id = aResponse.GetCmdId(); 7210 PVMFStatus status = 7211 CheckCPMCommandCompleteStatus(id, aResponse.GetCmdStatus()); 7212 7213 if (id == iCPMCancelGetLicenseCmdId) 7214 { 7215 /* 7216 * if this command is CancelGetLicense, we will return success or fail here. 7217 */ 7218 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM CancelGetLicense complete")); 7219 OSCL_ASSERT(!iCancelCommand.empty()); 7220 CommandComplete(iCancelCommand, 7221 iCancelCommand.front(), 7222 status); 7223 return; 7224 } 7225 //if CPM comes back as PVMFErrNotSupported then by pass rest of the CPM 7226 //sequence. Fake success here so that node doesnt treat this as an error 7227 else if (id == iCPMRegisterContentCmdId && status == PVMFErrNotSupported) 7228 { 7229 /* Unsupported format - Treat it like unprotected content */ 7230 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Unknown CPM Format - Ignoring CPM")); 7231 if (CheckForMP4HeaderAvailability() == PVMFSuccess) 7232 { 7233 CompleteInit(iCurrentCommand, iCurrentCommand.front()); 7234 } 7235 return; 7236 } 7237 7238 if (status != PVMFSuccess) 7239 { 7240 /* 7241 * If any command fails, the sequence fails. 7242 */ 7243 if (aResponse.GetEventData() == NULL) 7244 { 7245 // If any command fails, the sequence fails. 7246 CommandComplete(iCurrentCommand, 7247 iCurrentCommand.front(), 7248 aResponse.GetCmdStatus()); 7249 } 7250 else 7251 { 7252 // Need to pass EventData (=License URL) up to UI. 7253 CommandComplete(iCurrentCommand, 7254 iCurrentCommand.front(), 7255 aResponse.GetCmdStatus(), 7256 aResponse.GetEventData()); 7257 } 7258 /* 7259 * if there was any pending cancel, it was waiting on 7260 * this command to complete-- so the cancel is now done. 7261 */ 7262 if (!iCancelCommand.empty()) 7263 { 7264 if (iCancelCommand.front().iCmd != PVMP4FF_NODE_CMD_CANCEL_GET_LICENSE) 7265 { 7266 CommandComplete(iCancelCommand, 7267 iCancelCommand.front(), 7268 PVMFSuccess); 7269 } 7270 } 7271 } 7272 else 7273 { 7274 //process the response, and issue the next command in 7275 //the sequence. 7276 7277 PVMFCommandId id = aResponse.GetCmdId(); 7278 7279 if (id == iCPMInitCmdId) 7280 { 7281 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM Init complete")); 7282 OpenCPMSession(); 7283 } 7284 else if (id == iCPMOpenSessionCmdId) 7285 { 7286 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM OpenSession complete")); 7287 CPMRegisterContent(); 7288 } 7289 else if (id == iCPMRegisterContentCmdId) 7290 { 7291 GetCPMLicenseInterface(); 7292 } 7293 else if (id == iCPMGetLicenseInterfaceCmdId) 7294 { 7295 iCPMLicenseInterface = OSCL_STATIC_CAST(PVMFCPMPluginLicenseInterface*, iCPMLicenseInterfacePVI); 7296 iCPMLicenseInterfacePVI = NULL; 7297 GetCPMContentType(); 7298 if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) || 7299 (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS)) 7300 { 7301 iProtectedFile = true; 7302 GetCPMMetaDataExtensionInterface(); 7303 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - OMA1 - Register content complete")); 7304 RequestUsage(NULL); 7305 } 7306 else if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 7307 { 7308 iProtectedFile = true; 7309 GetCPMMetaDataExtensionInterface(); 7310 if (CheckForMP4HeaderAvailability() == PVMFSuccess) 7311 { 7312 PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL; 7313 if (ParseMP4File(iCurrentCommand, 7314 iCurrentCommand.front())) 7315 { 7316 if (CheckForOMA2AuthorizationComplete(oma2trackInfo) == PVMFPending) 7317 { 7318 RequestUsage(oma2trackInfo); 7319 } 7320 } 7321 } 7322 } 7323 else 7324 { 7325 /* Unsupported format - Treat it like unprotected content */ 7326 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Unknown CPM Format - Ignoring CPM")); 7327 if (CheckForMP4HeaderAvailability() == PVMFSuccess) 7328 { 7329 CompleteInit(iCurrentCommand, iCurrentCommand.front()); 7330 } 7331 } 7332 } 7333 else if (id == iCPMRequestUsageId) 7334 { 7335 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Request Usage complete")); 7336 //End of Node Init sequence. 7337 OSCL_ASSERT(!iCurrentCommand.empty()); 7338 OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_INIT); 7339 oWaitingOnLicense = false; 7340 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 7341 { 7342 //for OMA2 PDCF we need to authorize track by track 7343 OMA2TrackAuthorizationComplete(); 7344 PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL; 7345 PVMFStatus status = CheckForOMA2AuthorizationComplete(oma2trackInfo); 7346 if (status == PVMFPending) 7347 { 7348 RequestUsage(oma2trackInfo); 7349 } 7350 else if (status == PVMFSuccess) 7351 { 7352 //All tracks authorized, complete init 7353 CompleteInit(iCurrentCommand, iCurrentCommand.front()); 7354 } 7355 else 7356 { 7357 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CheckForOMA2AuthorizationComplete Failed")); 7358 OSCL_ASSERT(false); 7359 } 7360 } 7361 else 7362 { 7363 if (aResponse.GetCmdStatus() == PVMFSuccess) 7364 { 7365 //OMA1 content - Authorization complete 7366 if (CheckForMP4HeaderAvailability() == PVMFSuccess) 7367 { 7368 CompleteInit(iCurrentCommand, iCurrentCommand.front()); 7369 } 7370 } 7371 else 7372 { 7373 //we are just doing metadata (not necessarily from mp4 file header, 7374 // say just drm metadata), so complete init from here 7375 CompleteInit(iCurrentCommand, iCurrentCommand.front()); 7376 } 7377 } 7378 } 7379 else if (id == iCPMUsageCompleteCmdId) 7380 { 7381 if (iProtectedFile == true) 7382 { 7383 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM Usage Complete done")); 7384 CloseCPMSession(); 7385 } 7386 else 7387 { 7388 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Unprotected Content - Can't Send Usage Complete")); 7389 OSCL_ASSERT(false); 7390 } 7391 } 7392 else if (id == iCPMCloseSessionCmdId) 7393 { 7394 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Close CPM Session complete")); 7395 ResetCPM(); 7396 } 7397 else if (id == iCPMResetCmdId) 7398 { 7399 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM Reset complete")); 7400 //End of Node Reset sequence 7401 OSCL_ASSERT(!iCurrentCommand.empty()); 7402 OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_RESET); 7403 CompleteReset(iCurrentCommand, iCurrentCommand.front()); 7404 } 7405 else if (id == iCPMGetMetaDataKeysCmdId) 7406 { 7407 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM GetMetaDataKeys complete")); 7408 /* End of GetNodeMetaDataKeys */ 7409 PVMFStatus status = 7410 CompleteGetMetadataKeys(iCurrentCommand.front()); 7411 CommandComplete(iCurrentCommand, 7412 iCurrentCommand.front(), 7413 status); 7414 } 7415 else if (id == iCPMGetMetaDataValuesCmdId) 7416 { 7417 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM GetMetaDataValues complete")); 7418 /* End of GetNodeMetaDataValues */ 7419 OSCL_ASSERT(!iCurrentCommand.empty()); 7420 OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMP4FF_NODE_CMD_GETNODEMETADATAVALUES); 7421 CompleteGetMetaDataValues(); 7422 } 7423 else if (id == iCPMGetLicenseCmdId) 7424 { 7425 CompleteGetLicense(); 7426 } 7427 else 7428 { 7429 /* Unknown cmd - error */ 7430 CommandComplete(iCurrentCommand, 7431 iCurrentCommand.front(), 7432 PVMFFailure); 7433 } 7434 } 7435 } 7436 7437 PVMFStatus PVMFMP4FFParserNode::GetFileOffsetForAutoResume(uint32& aOffset, bool aPortsAvailable) 7438 { 7439 uint32 offset = 0; 7440 if (aPortsAvailable == false) 7441 { 7442 int32 iNumTracks = iMP4FileHandle->getNumTracks(); 7443 uint32 iIdList[16]; 7444 if (iNumTracks != iMP4FileHandle->getTrackIDList(iIdList, iNumTracks)) 7445 { 7446 return PVMFFailure; 7447 } 7448 for (int32 i = 0; i < iNumTracks; i++) 7449 { 7450 uint32 trackID = iIdList[i]; 7451 /* Convert PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS to media timescale */ 7452 MediaClockConverter mcc(1000); 7453 mcc.update_clock(iJitterBufferDurationInMs); 7454 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(trackID)); 7455 7456 int32 trackOffset = 0; 7457 PVMFTimestamp ts = mediats; 7458 int32 retVal = 7459 iMP4FileHandle->getOffsetByTime(trackID, ts, &trackOffset, iJitterBufferDurationInMs); 7460 7461 if (retVal != EVERYTHING_FINE) 7462 { 7463 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetFileOffsetForAutoResume1 - getOffsetByTime Failed - TrackId=%d, TS=%d, RetVal=%d", trackID, ts, retVal)); 7464 return PVMFFailure; 7465 } 7466 7467 if ((uint32)trackOffset > offset) 7468 { 7469 offset = trackOffset; 7470 } 7471 } 7472 } 7473 else 7474 { 7475 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 7476 7477 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 7478 { 7479 /* Convert PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS to media timescale */ 7480 MediaClockConverter mcc(1000); 7481 mcc.update_clock(iJitterBufferDurationInMs); 7482 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(it->iTrackId)); 7483 7484 int32 trackOffset = 0; 7485 PVMFTimestamp ts = it->iTimestamp + mediats; 7486 int32 retVal = 7487 iMP4FileHandle->getOffsetByTime(it->iTrackId, ts, &trackOffset, iJitterBufferDurationInMs); 7488 7489 if (retVal != EVERYTHING_FINE) 7490 { 7491 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetFileOffsetForAutoResume2 - getOffsetByTime Failed - TrackId=%d, TS=%d, RetVal=%d", it->iTrackId, ts, retVal)); 7492 return PVMFFailure; 7493 } 7494 7495 if ((uint32)trackOffset > offset) 7496 { 7497 offset = trackOffset; 7498 } 7499 } 7500 } 7501 aOffset = offset; 7502 return PVMFSuccess; 7503 } 7504 7505 PVMFStatus PVMFMP4FFParserNode::GetFileOffsetForAutoResume(uint32& aOffset, PVMP4FFNodeTrackPortInfo* aInfo) 7506 { 7507 uint32 offset = 0; 7508 /* Convert PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS to media timescale */ 7509 MediaClockConverter mcc(1000); 7510 mcc.update_clock(iJitterBufferDurationInMs); 7511 uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(aInfo->iTrackId)); 7512 7513 int32 trackOffset = 0; 7514 PVMFTimestamp ts = aInfo->iTimestamp + mediats; 7515 int32 retVal = 7516 iMP4FileHandle->getOffsetByTime(aInfo->iTrackId, ts, &trackOffset, iJitterBufferDurationInMs); 7517 7518 if (retVal != EVERYTHING_FINE) 7519 { 7520 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetFileOffsetForAutoResume by port - getOffsetByTime Failed - TrackId=%d, TS=%d, RetVal=%d", aInfo->iTrackId, ts, retVal)); 7521 return PVMFFailure; 7522 } 7523 7524 if ((uint32)trackOffset > offset) 7525 { 7526 offset = trackOffset; 7527 } 7528 aOffset = offset; 7529 return PVMFSuccess; 7530 } 7531 7532 7533 void PVMFMP4FFParserNode::DataStreamCommandCompleted(const PVMFCmdResp& aResponse) 7534 { 7535 for (uint32 i = 0; i < iNodeTrackPortList.size(); ++i) 7536 { 7537 switch (iNodeTrackPortList[i].iState) 7538 { 7539 /* 7540 ** Its possible that track reports inufficient data but does not report Underflow and 7541 ** justs sets the timer. If we receive DataStreamCommandComplete means we need not report 7542 ** underflow now, so set track state as GETDATA, cancel the timer and schedule Node to 7543 ** retrieve data. This case will only happen if CheckForUnderflow returns Pending for 7544 ** any track. 7545 */ 7546 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA: 7547 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 7548 iUnderFlowCheckTimer->Cancel(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID); 7549 RunIfNotReady(); 7550 break; 7551 7552 default: 7553 // nothing to do 7554 break; 7555 } 7556 7557 } 7558 if (autopaused) 7559 { 7560 if (aResponse.GetCmdStatus() == PVMFSuccess) 7561 { 7562 autopaused = false; 7563 for (uint32 ii = 0; ii < iNodeTrackPortList.size(); ++ii) 7564 { 7565 switch (iNodeTrackPortList[ii].iState) 7566 { 7567 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE: 7568 iNodeTrackPortList[ii].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA; 7569 break; 7570 7571 default: 7572 // nothing to do 7573 break; 7574 } 7575 RunIfNotReady(); 7576 } 7577 7578 // report data ready only if underflow was not suppressed earlier 7579 if (iUnderFlowEventReported == true) 7580 { 7581 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DataStreamReadCapacityNotificationCallBack() Sending PVMFInfoDataReady event")); 7582 ReportMP4FFParserInfoEvent(PVMFInfoDataReady); 7583 iUnderFlowEventReported = false; 7584 } 7585 if (iExternalDownload == true) 7586 { 7587 if ((iCurrentCommand.empty() == false) && 7588 (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_PREPARE)) 7589 { 7590 //we could be waiting on this call back to complete prepare 7591 CompletePrepare(aResponse.GetCmdStatus()); 7592 } 7593 } 7594 // Schedule AO to run again 7595 RunIfNotReady(); 7596 return; 7597 } 7598 else 7599 { 7600 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DataStreamReadCapacityNotificationCallBack() Reporting failure")); 7601 if (iExternalDownload == true) 7602 { 7603 if ((iCurrentCommand.empty() == false) && 7604 (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_PREPARE)) 7605 { 7606 //we could be waiting on this call back to complete prepare 7607 CompletePrepare(aResponse.GetCmdStatus()); 7608 } 7609 else 7610 { 7611 ReportMP4FFParserErrorEvent(PVMFErrResource); 7612 } 7613 } 7614 else 7615 { 7616 ReportMP4FFParserErrorEvent(PVMFErrResource); 7617 } 7618 } 7619 } 7620 else if ((iCurrentCommand.empty() == false) && 7621 (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_INIT)) 7622 { 7623 /* Callbacks intiated as part of node init */ 7624 if (aResponse.GetCmdId() == iRequestReadCapacityNotificationID) 7625 { 7626 iDataStreamRequestPending = false; 7627 /* 7628 * Can come here only if we are doing PDL / PPB. 7629 * Init is still pending and datastream callback has completed. 7630 * A few possible scenarios here: 7631 * - PDL/PPB (DRM/Non-DRM) - We are waiting on movie atom to be downloaded. 7632 * - OMA2 PDCF DRM clip - were waiting on more data to parse the movie atom, 7633 * CPM seq not complete since we need contents of movie atom to authorize 7634 * with CPM 7635 */ 7636 if (iCPM) 7637 { 7638 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2) 7639 { 7640 PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL; 7641 if (ParseMP4File(iCurrentCommand, 7642 iCurrentCommand.front())) 7643 { 7644 if (CheckForOMA2AuthorizationComplete(oma2trackInfo) == PVMFPending) 7645 { 7646 RequestUsage(oma2trackInfo); 7647 return; 7648 } 7649 } 7650 } 7651 } 7652 if (PVMFSuccess == CheckForMP4HeaderAvailability()) 7653 { 7654 CompleteInit(iCurrentCommand, iCurrentCommand.front()); 7655 } 7656 } 7657 else 7658 { 7659 /* unrecognized callback */ 7660 OSCL_ASSERT(false); 7661 } 7662 } 7663 else 7664 { 7665 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DataStreamReadCapacityNotificationCallBack() in non-autopaused state")); 7666 ReportMP4FFParserErrorEvent(PVMFErrInvalidState); 7667 } 7668 return; 7669 } 7670 7671 7672 void PVMFMP4FFParserNode::DataStreamInformationalEvent(const PVMFAsyncEvent& aEvent) 7673 { 7674 //if Datadownload is complete then send PVMFInfoBufferingComplete event from DS to parser node 7675 if (aEvent.GetEventType() == PVMFInfoBufferingComplete) 7676 { 7677 iDownloadComplete = true; 7678 } 7679 } 7680 7681 void PVMFMP4FFParserNode::DataStreamErrorEvent(const PVMFAsyncEvent& aEvent) 7682 { 7683 OSCL_UNUSED_ARG(aEvent); 7684 OSCL_ASSERT(false); 7685 } 7686 7687 void PVMFMP4FFParserNode::getBrand(uint32 aBrandVal, char *BrandVal) 7688 { 7689 BrandVal[0] = (aBrandVal >> 24); 7690 BrandVal[1] = (aBrandVal >> 16); 7691 BrandVal[2] = (aBrandVal >> 8); 7692 BrandVal[3] = aBrandVal; 7693 } 7694 7695 bool PVMFMP4FFParserNode::GetTrackPortInfoForTrackID(PVMP4FFNodeTrackPortInfo*& aInfo, 7696 uint32 aTrackID) 7697 { 7698 aInfo = NULL; 7699 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 7700 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 7701 { 7702 if (it->iTrackId == (int32)aTrackID) 7703 { 7704 aInfo = it; 7705 return true; 7706 } 7707 } 7708 return false; 7709 } 7710 7711 bool PVMFMP4FFParserNode::GetTrackPortInfoForPort(PVMP4FFNodeTrackPortInfo*& aInfo, 7712 PVMFPortInterface* aPort) 7713 { 7714 aInfo = NULL; 7715 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 7716 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 7717 { 7718 if (it->iPortInterface == aPort) 7719 { 7720 aInfo = it; 7721 return true; 7722 } 7723 } 7724 return false; 7725 } 7726 7727 void PVMFMP4FFParserNode::PassDatastreamFactory(PVMFDataStreamFactory& aFactory, 7728 int32 aFactoryTag, 7729 const PvmfMimeString* aFactoryConfig) 7730 { 7731 OSCL_UNUSED_ARG(aFactoryTag); 7732 OSCL_UNUSED_ARG(aFactoryConfig); 7733 7734 // Fasttrack download does not use data streams 7735 if (iFastTrackSession) 7736 return; 7737 7738 if (iDataStreamFactory == NULL) 7739 { 7740 iDataStreamFactory = &aFactory; 7741 PVUuid uuid = PVMIDataStreamSyncInterfaceUuid; 7742 PVInterface* iFace = 7743 iDataStreamFactory->CreatePVMFCPMPluginAccessInterface(uuid); 7744 if (iFace != NULL) 7745 { 7746 iDataStreamInterface = OSCL_STATIC_CAST(PVMIDataStreamSyncInterface*, iFace); 7747 iDataStreamInterface->OpenSession(iDataStreamSessionID, PVDS_READ_ONLY); 7748 } 7749 } 7750 else 7751 { 7752 OSCL_ASSERT(false); 7753 } 7754 } 7755 7756 void 7757 PVMFMP4FFParserNode::PassDatastreamReadCapacityObserver(PVMFDataStreamReadCapacityObserver* aObserver) 7758 { 7759 iDataStreamReadCapacityObserver = aObserver; 7760 } 7761 7762 7763 PVMFStatus PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() 7764 { 7765 if (iFastTrackSession == true) return PVMFSuccess; 7766 7767 if (iDataStreamInterface != NULL) 7768 { 7769 /* 7770 * First check if we have minimum number of bytes to recognize 7771 * the file and determine the header size. 7772 */ 7773 uint32 currCapacity = 0; 7774 iDataStreamInterface->QueryReadCapacity(iDataStreamSessionID, 7775 currCapacity); 7776 7777 if (currCapacity < MP4_MIN_BYTES_FOR_GETTING_MOVIE_HDR_SIZE) 7778 { 7779 iRequestReadCapacityNotificationID = 7780 iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID, 7781 *this, 7782 MP4_MIN_BYTES_FOR_GETTING_MOVIE_HDR_SIZE); 7783 iDataStreamRequestPending = true; 7784 return PVMFPending; 7785 } 7786 7787 7788 bool isProgressiveDownloadable = false; 7789 MP4_ERROR_CODE retCode = 7790 IMpeg4File::GetMetaDataSize(iDataStreamFactory, 7791 isProgressiveDownloadable, 7792 iMP4HeaderSize); 7793 7794 if (retCode == EVERYTHING_FINE) 7795 { 7796 if (isProgressiveDownloadable == true) 7797 { 7798 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - MetaData ends at file offset %d", iMP4HeaderSize)); 7799 iProgressivelyDownlodable = true; 7800 // inform data stream that a range of bytes needs to be cached persistently (offset 0, size of moov atom) 7801 iDataStreamInterface->MakePersistent(0, iMP4HeaderSize); 7802 7803 if (currCapacity < iMP4HeaderSize) 7804 { 7805 iRequestReadCapacityNotificationID = 7806 iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID, 7807 *this, 7808 iMP4HeaderSize); 7809 iDataStreamRequestPending = true; 7810 return PVMFPending; 7811 } 7812 else 7813 { 7814 return PVMFSuccess; 7815 } 7816 } 7817 else 7818 { 7819 iProgressivelyDownlodable = false; 7820 7821 PVUuid uuid = PVMFFileFormatEventTypesUUID; 7822 int32 infocode = PVMFMP4FFParserInfoNotPseudostreamableFile; 7823 ReportMP4FFParserInfoEvent(PVMFInfoRemoteSourceNotification, NULL, &uuid, &infocode); 7824 /* 7825 * Wait for download complete 7826 */ 7827 if (download_progress_interface != NULL) 7828 { 7829 uint32 nptTsinMS = 0xFFFFFFFF; 7830 7831 if ((NULL != iDataStreamInterface) && (0 != iDataStreamInterface->QueryBufferingCapacity())) 7832 { 7833 // if progressive streaming, playResumeNotifcation is guaranteed to be called 7834 // with the proper download complete state, ignore the current download status 7835 bool dlcomplete = false; 7836 download_progress_interface->requestResumeNotification(nptTsinMS, dlcomplete); 7837 } 7838 else 7839 { 7840 download_progress_interface->requestResumeNotification(nptTsinMS, iDownloadComplete); 7841 } 7842 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - Auto Pause Triggered, TS = %d", nptTsinMS)); 7843 return PVMFPending; 7844 } 7845 else 7846 { 7847 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - download_progress_interface not available")); 7848 } 7849 } 7850 } 7851 else if (retCode == INSUFFICIENT_DATA) 7852 { 7853 iRequestReadCapacityNotificationID = 7854 iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID, 7855 *this, 7856 (iMP4HeaderSize + MP4_MIN_BYTES_FOR_GETTING_MOVIE_HDR_SIZE)); 7857 iDataStreamRequestPending = true; 7858 return PVMFPending; 7859 } 7860 else if (retCode == NOT_PROGRESSIVE_STREAMABLE) 7861 { 7862 // progressive playback and no movie atom found 7863 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - Moov atom not found, needed for progressive playback")); 7864 return PVMFErrContentInvalidForProgressivePlayback; 7865 } 7866 else 7867 { 7868 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - GetMetaDataSize Failed %d", retCode)); 7869 } 7870 7871 return PVMFFailure; 7872 } 7873 return PVMFSuccess; 7874 } 7875 7876 PVMFStatus PVMFMP4FFParserNode::CheckForUnderFlow(PVMP4FFNodeTrackPortInfo* aInfo) 7877 { 7878 uint32 timebase32 = 0; 7879 uint32 clientClock32 = 0; 7880 bool overload = 0; 7881 if (iClientPlayBackClock != NULL) 7882 { 7883 iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32); 7884 } 7885 else 7886 { 7887 return PVMFFailure; 7888 } 7889 7890 MediaClockConverter clock_conv(*(aInfo->iClockConverter)); 7891 clock_conv.update_clock(aInfo->iTimestamp); 7892 uint32 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE); 7893 if (clientClock32 <= msec) 7894 { 7895 uint32 diff32 = (msec - clientClock32); 7896 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Diff Bet Client Clock(%d) and Track Media TS(%d) = %d", clientClock32, msec, diff32)); 7897 if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS || aInfo->iFormatType == PVMF_MIME_AMR_IETF || aInfo->iFormatType == PVMF_MIME_MPEG4_AUDIO) 7898 { 7899 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Time To Auto Pause")); 7900 return PVMFSuccess; 7901 } 7902 else 7903 { 7904 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Setting UnderFlow Timer")); 7905 iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID, 7906 0, 7907 PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES, 7908 this); 7909 } 7910 } 7911 else 7912 { 7913 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Client Clock Greater than Media TS, Clock=%d, MaxMTS=%d", clientClock32, msec)); 7914 OSCL_ASSERT(false); 7915 } 7916 7917 /* Check if all tracks are autopaused. If so, it is time to autopause the node */ 7918 bool oAllTracksAutoPaused = true; 7919 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 7920 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 7921 { 7922 if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE) 7923 { 7924 oAllTracksAutoPaused = false; 7925 } 7926 } 7927 if (oAllTracksAutoPaused == true) 7928 { 7929 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - All Tracks AutoPaused - Time To Auto Pause")); 7930 return PVMFSuccess; 7931 } 7932 //not yet time to autopause 7933 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Wait on player clock for Auto Pause")); 7934 return PVMFPending; 7935 } 7936 7937 7938 PVMFStatus PVMFMP4FFParserNode::ReportUnderFlow() 7939 { 7940 /* Check if all tracks are autopaused. If so, it is time to autopause the node */ 7941 bool oAllTracksAutoPaused = true; 7942 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 7943 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 7944 { 7945 if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE) 7946 { 7947 oAllTracksAutoPaused = false; 7948 } 7949 } 7950 if (oAllTracksAutoPaused == true) 7951 { 7952 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Reporting UnderFlow")); 7953 ReportInfoEvent(PVMFInfoUnderflow); 7954 iUnderFlowEventReported = true; 7955 return PVMFSuccess; 7956 } 7957 7958 7959 uint32 minTS = 0xFFFFFFFF; 7960 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 7961 { 7962 if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE) 7963 { 7964 MediaClockConverter clock_conv(*(it->iClockConverter)); 7965 clock_conv.update_clock(it->iTimestamp); 7966 uint32 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE); 7967 if (msec < minTS) 7968 { 7969 minTS = msec; 7970 } 7971 } 7972 } 7973 uint32 timebase32 = 0; 7974 uint32 clientClock32 = 0; 7975 bool overload = 0; 7976 7977 if (iClientPlayBackClock != NULL) 7978 iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32); 7979 7980 7981 uint32 currentFileSize = 0; 7982 MP4_ERROR_CODE code = iMP4FileHandle->GetCurrentFileSize(currentFileSize); 7983 if (code != EVERYTHING_FINE) 7984 { 7985 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::ReportUnderFlow - GetCurrentFileSize Failed - Ret=%d", code)); 7986 return PVMFFailure; 7987 } 7988 7989 iUnderFlowEventReported = false; 7990 uint32 currNPT = 0; 7991 convertSizeToTime(currentFileSize, currNPT); 7992 7993 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - ClientClock = %d", clientClock32)); 7994 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - NPTInMS = %d, FileSize = %d", currNPT, currentFileSize)); 7995 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Min Media TS = %d", minTS)); 7996 7997 if (clientClock32 <= minTS) 7998 { 7999 uint32 diff32 = (minTS - clientClock32); 8000 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Diff Bet Client Clock and Min Media TS = %d", diff32)); 8001 if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS) 8002 { 8003 /* If parserNode is reporting Underflow, all tracks should be in auto-paused state */ 8004 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 8005 { 8006 if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE) 8007 { 8008 it->iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE; 8009 } 8010 } 8011 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Reporting UnderFlow")); 8012 ReportInfoEvent(PVMFInfoUnderflow); 8013 iUnderFlowEventReported = true; 8014 } 8015 else 8016 { 8017 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Setting UnderFlow Timer")); 8018 iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID, 8019 0, 8020 PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES, 8021 this); 8022 } 8023 } 8024 else 8025 { 8026 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::ReportUnderFlow - Client Clock Greater than Min Media TS, Clock=%d, MaxMTS=%d", clientClock32, minTS)); 8027 OSCL_ASSERT(false); 8028 } 8029 return PVMFSuccess; 8030 } 8031 8032 void PVMFMP4FFParserNode::TimeoutOccurred(int32 timerID, 8033 int32 timeoutInfo) 8034 { 8035 OSCL_UNUSED_ARG(timeoutInfo); 8036 8037 if (timerID == PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID) 8038 { 8039 if (autopaused == true && iUnderFlowEventReported == false) 8040 { 8041 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - UnderFlow TimeOut - Still AutoPaused")); 8042 uint32 currentFileSize = 0; 8043 MP4_ERROR_CODE code = iMP4FileHandle->GetCurrentFileSize(currentFileSize); 8044 if (code == EVERYTHING_FINE) 8045 { 8046 uint32 currNPT = 0; 8047 convertSizeToTime(currentFileSize, currNPT); 8048 8049 uint32 minTS = 0xFFFFFFFF; 8050 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 8051 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 8052 { 8053 if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE) 8054 { 8055 MediaClockConverter clock_conv(*(it->iClockConverter)); 8056 clock_conv.update_clock(it->iTimestamp); 8057 uint32 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE); 8058 if (msec < minTS) 8059 { 8060 minTS = msec; 8061 } 8062 } 8063 } 8064 uint32 timebase32 = 0; 8065 uint32 clientClock32 = 0; 8066 bool overload = 0; 8067 if (iClientPlayBackClock != NULL) 8068 iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32); 8069 8070 8071 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - ClientClock = %d", clientClock32)); 8072 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - NPTInMS = %d, FileSize = %d", currNPT, currentFileSize)); 8073 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Min Media TS = %d", minTS)); 8074 8075 if (clientClock32 <= minTS) 8076 { 8077 uint32 diff32 = (minTS - clientClock32); 8078 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Diff Bet Client Clock and Min Media TS = %d", diff32)); 8079 if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS) 8080 { 8081 /* If parserNode is reporting Underflow, all tracks should be in auto-paused state */ 8082 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 8083 { 8084 if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE) 8085 { 8086 it->iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE; 8087 } 8088 } 8089 8090 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Reporting UnderFlow")); 8091 ReportInfoEvent(PVMFInfoUnderflow); 8092 iUnderFlowEventReported = true; 8093 } 8094 else 8095 { 8096 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Requesting Additional Time Out")); 8097 iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID, 8098 0, 8099 PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES, 8100 this); 8101 } 8102 } 8103 else 8104 { 8105 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::TimeoutOccurred - Client Clock Greater than Min Media TS, Clock=%d, MaxMTS=%d", clientClock32, minTS)); 8106 OSCL_ASSERT(false); 8107 } 8108 8109 } 8110 else 8111 { 8112 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::TimeoutOccurred - GetCurrentFileSize Failed - Ret=%d", code)); 8113 ReportErrorEvent(PVMFErrResource); 8114 } 8115 } 8116 else if (iDownloadComplete == false && iUnderFlowEventReported == false) 8117 { 8118 uint32 timebase32 = 0; 8119 uint32 clientClock32 = 0; 8120 bool overload = 0; 8121 uint32 msec = 0; 8122 if (iClientPlayBackClock != NULL) 8123 { 8124 iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32); 8125 } 8126 8127 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 8128 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 8129 { 8130 if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA) 8131 { 8132 MediaClockConverter clock_conv(*(it->iClockConverter)); 8133 clock_conv.update_clock(it->iTimestamp); 8134 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE); 8135 } 8136 } 8137 8138 if (clientClock32 <= msec) 8139 { 8140 uint32 diff32 = (msec - clientClock32); 8141 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Diff Bet Client Clock(%d) and Track Media TS(%d) = %d", clientClock32, msec, diff32)); 8142 if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS) 8143 { 8144 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Time To Auto Pause")); 8145 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 8146 { 8147 if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA) 8148 { 8149 it->iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE; 8150 } 8151 } 8152 autopaused = true; 8153 ReportUnderFlow(); 8154 } 8155 else 8156 { 8157 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Setting UnderFlow Timer")); 8158 iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID, 8159 0, 8160 PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES, 8161 this); 8162 } 8163 } 8164 else 8165 { 8166 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::TimeoutOccurred - Client Clock Greater than Media TS, Clock=%d, MaxMTS=%d", clientClock32, msec)); 8167 //should never happen 8168 OSCL_ASSERT(false); 8169 } 8170 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - UnderFlow TimeOut - After AutoResume")); 8171 } 8172 } 8173 return; 8174 } 8175 8176 void 8177 PVMFMP4FFParserNode::LogMediaData(PVMFSharedMediaDataPtr data, 8178 PVMFPortInterface* aPort) 8179 { 8180 PVMP4FFNodeTrackPortInfo* trackInfoPtr = NULL; 8181 if (!GetTrackPortInfoForPort(trackInfoPtr, aPort)) 8182 { 8183 return; 8184 } 8185 8186 bool ologSizeTS = false; 8187 8188 /* Get Format Specific Info, if any */ 8189 if (trackInfoPtr->oFormatSpecificInfoLogged == false) 8190 { 8191 uint32 size = trackInfoPtr->iFormatSpecificConfig.getMemFragSize(); 8192 if (size > 0) 8193 { 8194 PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, size, trackInfoPtr->iFormatSpecificConfig.getMemFragPtr())); 8195 } 8196 trackInfoPtr->oFormatSpecificInfoLogged = true; 8197 } 8198 8199 ologSizeTS = false; 8200 8201 PVMFMediaData* mediaData = data.GetRep(); 8202 if (mediaData != NULL) 8203 { 8204 /* Log Media Fragments */ 8205 uint32 numMediaFragments = mediaData->getNumFragments(); 8206 for (uint32 i = 0; i < numMediaFragments; i++) 8207 { 8208 OsclRefCounterMemFrag memFrag; 8209 mediaData->getMediaFragment(i, memFrag); 8210 if (ologSizeTS) 8211 { 8212 PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, sizeof(uint32), memFrag.getMemFragSize())); 8213 PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, sizeof(uint32), data->getTimestamp())); 8214 } 8215 PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, memFrag.getMemFragSize(), memFrag.getMemFragPtr())); 8216 } 8217 } 8218 } 8219 8220 void PVMFMP4FFParserNode::LogDiagnostics() 8221 { 8222 if (iDiagnosticsLogged == false) 8223 { 8224 iDiagnosticsLogged = true; 8225 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it; 8226 8227 if (&iNodeTrackPortList) 8228 { 8229 it = iNodeTrackPortList.begin(); 8230 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++) 8231 { 8232 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")); 8233 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Time Taken in Read MP4 File =%d", iTimeTakenInReadMP4File)); 8234 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Minimum Time =%2d", it->iMinTime)); 8235 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Maximum Time =%2d", it->iMaxTime)); 8236 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Total Time =%2d", it->iSumTime)); 8237 8238 uint64 avg_time = 0; 8239 if ((it->iNumTimesMediaSampleRead) > 0) 8240 avg_time = Oscl_Int64_Utils::get_uint64_lower32(it->iSumTime) / (it->iNumTimesMediaSampleRead); 8241 8242 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Avg Time =%2d", avg_time)); 8243 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Number of Sample Read each time =%d", it->iNumSamples)); 8244 8245 8246 } 8247 } 8248 } 8249 } 8250 8251 PVMFStatus PVMFMP4FFParserNode::GetVideoFrameWidth(uint32 aId, int32& aWidth, int32& aDisplayWidth) 8252 { 8253 int32 height = 0; 8254 int32 width = 0; 8255 int32 display_width = 0; 8256 int32 display_height = 0; 8257 8258 OSCL_HeapString<OsclMemAllocator> trackMIMEType; 8259 8260 iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType); 8261 8262 if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H2632000, oscl_strlen(PVMF_MIME_H2632000)) == 0) 8263 { 8264 H263DecoderSpecificInfo *ptr = 8265 (H263DecoderSpecificInfo *)iMP4FileHandle->getTrackDecoderSpecificInfoAtSDI(aId, 0); 8266 8267 //In case of H263 display dimension and decode dimesnion cannot be different,so pass 8268 //aDisplayHeight as parser level info and Height from decoder utility 8269 8270 if (ptr != NULL) 8271 { 8272 if (ptr->getMaxWidth() > 0) 8273 { 8274 aDisplayWidth = display_width = (int32)(ptr->getMaxWidth()); 8275 } 8276 } 8277 8278 if (width == 0) 8279 { 8280 //get width from the first frame 8281 MediaMetaInfo info; 8282 uint32 numSamples = 1; 8283 int32 retval = EVERYTHING_FINE; 8284 retval = iMP4FileHandle->peekNextBundledAccessUnits(aId, 8285 &numSamples, 8286 &info); 8287 if ((retval == EVERYTHING_FINE || END_OF_TRACK == retval) && numSamples > 0) 8288 { 8289 uint32 sampleSize = info.len; 8290 if (sampleSize > 0) 8291 { 8292 uint8* sampleBuf = OSCL_ARRAY_NEW(uint8, sampleSize); 8293 8294 oscl_memset(&iGau.buf, 0, sizeof(iGau.buf)); 8295 oscl_memset(&iGau.info, 0, sizeof(iGau.info)); 8296 iGau.free_buffer_states_when_done = 0; 8297 iGau.numMediaSamples = 1; 8298 iGau.buf.num_fragments = 1; 8299 iGau.buf.buf_states[0] = NULL; 8300 iGau.buf.fragments[0].ptr = (OsclAny*)sampleBuf; 8301 iGau.buf.fragments[0].len = sampleSize; 8302 retval = 8303 iMP4FileHandle->getNextBundledAccessUnits(aId, 8304 &numSamples, 8305 &iGau); 8306 if ((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK)) 8307 { 8308 mp4StreamType streamType; 8309 streamType.data = sampleBuf; 8310 streamType.numBytes = sampleSize; 8311 streamType.bytePos = 0; 8312 streamType.bitBuf = 0; 8313 streamType.dataBitPos = 0; 8314 streamType.bitPos = 32; 8315 8316 int16 status = 8317 iDecodeShortHeader(&streamType, 8318 (int32*) & width, 8319 (int32*) & height, 8320 (int32*) & display_width, 8321 (int32*) & display_height); 8322 if (status != 0) 8323 { 8324 return PVMFFailure; 8325 } 8326 8327 aWidth = width; 8328 if (aDisplayWidth == 0) 8329 { 8330 aDisplayWidth = display_width; 8331 } 8332 } 8333 iMP4FileHandle->resetPlayback(); 8334 OSCL_ARRAY_DELETE(sampleBuf); 8335 } 8336 } 8337 } 8338 8339 } 8340 else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H264_VIDEO_MP4, oscl_strlen(PVMF_MIME_H264_VIDEO_MP4)) == 0) 8341 { 8342 display_width = iMP4FileHandle->getVideoFrameWidth(aId); 8343 if (display_width > 0) 8344 { 8345 aDisplayWidth = display_width; 8346 } 8347 8348 uint32 specinfosize = 8349 iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId); 8350 if (specinfosize != 0) 8351 { 8352 // Retrieve the decoder specific info from file parser 8353 uint8* specinfoptr = 8354 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId); 8355 int32 profile, level = 0;// this info is discarded 8356 int16 status = 8357 iGetAVCConfigInfo(specinfoptr, 8358 (int32)specinfosize, 8359 (int32*) & width, 8360 (int32*) & height, 8361 (int32*) & display_width, 8362 (int32*) & display_height, 8363 (int32*) & profile, 8364 (int32*) & level); 8365 if (status != 0) 8366 { 8367 return PVMFFailure; 8368 } 8369 8370 aWidth = width; 8371 8372 if (aDisplayWidth == 0) 8373 aDisplayWidth = display_width; 8374 } 8375 } 8376 else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_M4V, oscl_strlen(PVMF_MIME_M4V)) == 0) 8377 { 8378 display_width = iMP4FileHandle->getVideoFrameWidth(aId); 8379 if (display_width > 0) 8380 { 8381 aDisplayWidth = display_width; 8382 } 8383 8384 uint32 specinfosize = 8385 iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId); 8386 if (specinfosize != 0) 8387 { 8388 // Retrieve the decoder specific info from file parser 8389 uint8* specinfoptr = 8390 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId); 8391 int16 status = 8392 iGetM4VConfigInfo(specinfoptr, 8393 (int32)specinfosize, 8394 (int32*) & width, 8395 (int32*) & height, 8396 (int32*) & display_width, 8397 (int32*) & display_height); 8398 if (status != 0) 8399 { 8400 return PVMFFailure; 8401 } 8402 8403 aWidth = width; 8404 8405 if (aDisplayWidth == 0) 8406 aDisplayWidth = display_width; 8407 } 8408 } 8409 8410 return PVMFSuccess; 8411 } 8412 8413 PVMFStatus PVMFMP4FFParserNode::GetVideoFrameHeight(uint32 aId, int32& aHeight, int32& aDisplayHeight) 8414 { 8415 int32 height = 0; 8416 int32 width = 0; 8417 int32 display_width = 0; 8418 int32 display_height = 0; 8419 8420 OSCL_HeapString<OsclMemAllocator> trackMIMEType; 8421 iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType); 8422 8423 if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H2632000, oscl_strlen(PVMF_MIME_H2632000)) == 0) 8424 { 8425 H263DecoderSpecificInfo *ptr = 8426 (H263DecoderSpecificInfo *)iMP4FileHandle->getTrackDecoderSpecificInfoAtSDI(aId, 0); 8427 8428 //In case of H263 display dimension and decode dimesnion cannot be different,so pass 8429 //aDisplayHeight as parser level info and Height from decoder utility 8430 if (ptr != NULL) 8431 { 8432 if (ptr->getMaxHeight() > 0) 8433 { 8434 aDisplayHeight = display_height = (int32)(ptr->getMaxHeight()); 8435 } 8436 } 8437 if (height == 0) 8438 { 8439 //get height from the first frame 8440 MediaMetaInfo info; 8441 uint32 numSamples = 1; 8442 int32 retval = EVERYTHING_FINE; 8443 retval = iMP4FileHandle->peekNextBundledAccessUnits(aId, 8444 &numSamples, 8445 &info); 8446 if ((retval == EVERYTHING_FINE || END_OF_TRACK == retval) && numSamples > 0) 8447 { 8448 uint32 sampleSize = info.len; 8449 if (sampleSize > 0) 8450 { 8451 uint8* sampleBuf = OSCL_ARRAY_NEW(uint8, sampleSize); 8452 8453 oscl_memset(&iGau.buf, 0, sizeof(iGau.buf)); 8454 oscl_memset(&iGau.info, 0, sizeof(iGau.info)); 8455 iGau.free_buffer_states_when_done = 0; 8456 iGau.numMediaSamples = 1; 8457 iGau.buf.num_fragments = 1; 8458 iGau.buf.buf_states[0] = NULL; 8459 iGau.buf.fragments[0].ptr = (OsclAny*)sampleBuf; 8460 iGau.buf.fragments[0].len = sampleSize; 8461 retval = 8462 iMP4FileHandle->getNextBundledAccessUnits(aId, 8463 &numSamples, 8464 &iGau); 8465 if ((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK)) 8466 { 8467 mp4StreamType streamType; 8468 streamType.data = sampleBuf; 8469 streamType.numBytes = sampleSize; 8470 streamType.bytePos = 0; 8471 streamType.bitBuf = 0; 8472 streamType.dataBitPos = 0; 8473 streamType.bitPos = 32; 8474 8475 int16 status = 8476 iDecodeShortHeader(&streamType, 8477 (int32*) & width, 8478 (int32*) & height, 8479 (int32*) & display_width, 8480 (int32*) & display_height); 8481 if (status != 0) 8482 { 8483 return PVMFFailure; 8484 } 8485 8486 if (aDisplayHeight == 0) 8487 { 8488 aDisplayHeight = display_height; 8489 } 8490 aHeight = height; 8491 } 8492 iMP4FileHandle->resetPlayback(); 8493 OSCL_ARRAY_DELETE(sampleBuf); 8494 } 8495 } 8496 } 8497 } 8498 if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H264_VIDEO_MP4, oscl_strlen(PVMF_MIME_H264_VIDEO_MP4)) == 0) 8499 { 8500 display_height = iMP4FileHandle->getVideoFrameHeight(aId); 8501 if (display_height > 0) 8502 { 8503 aDisplayHeight = display_height; 8504 } 8505 8506 uint32 specinfosize = 8507 iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId); 8508 if (specinfosize != 0) 8509 { 8510 // Retrieve the decoder specific info from file parser 8511 uint8* specinfoptr = 8512 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId); 8513 int profile, level = 0; // this info is discarded here 8514 int16 status = 8515 iGetAVCConfigInfo(specinfoptr, 8516 (int32)specinfosize, 8517 (int32*) & width, 8518 (int32*) & height, 8519 (int32*) & display_width, 8520 (int32*) & display_height, 8521 (int32*) & profile, 8522 (int32*) & level); 8523 if (status != 0) 8524 { 8525 return PVMFFailure; 8526 } 8527 8528 aHeight = height; 8529 8530 if (aDisplayHeight == 0) 8531 aDisplayHeight = display_height; 8532 } 8533 } 8534 else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_M4V, oscl_strlen(PVMF_MIME_M4V)) == 0) 8535 { 8536 display_height = iMP4FileHandle->getVideoFrameHeight(aId); 8537 if (display_height > 0) 8538 { 8539 aDisplayHeight = display_height; 8540 } 8541 8542 uint32 specinfosize = 8543 iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId); 8544 if (specinfosize != 0) 8545 { 8546 // Retrieve the decoder specific info from file parser 8547 uint8* specinfoptr = 8548 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId); 8549 int16 status = 8550 iGetM4VConfigInfo(specinfoptr, 8551 (int32)specinfosize, 8552 (int32*) & width, 8553 (int32*) & height, 8554 (int32*) & display_width, 8555 (int32*) & display_height); 8556 if (status != 0) 8557 { 8558 return PVMFFailure; 8559 } 8560 8561 aHeight = height; 8562 8563 if (aDisplayHeight == 0) 8564 aDisplayHeight = display_height; 8565 8566 } 8567 } 8568 8569 return PVMFSuccess; 8570 } 8571 8572 PVMFStatus PVMFMP4FFParserNode::PopulateVideoDimensions(uint32 aId) 8573 { 8574 VideoTrackDimensionInfo vidDimInfo; 8575 vidDimInfo.iTrackId = aId; 8576 if (PVMFSuccess != GetVideoFrameWidth(aId, vidDimInfo.iWidth, vidDimInfo.iDisplayWidth)) 8577 { 8578 return PVMFFailure; 8579 } 8580 if (PVMFSuccess != GetVideoFrameHeight(aId, vidDimInfo.iHeight, vidDimInfo.iDisplayHeight)) 8581 { 8582 return PVMFFailure; 8583 } 8584 iVideoDimensionInfoVec.push_back(vidDimInfo); 8585 return PVMFSuccess; 8586 } 8587 8588 int32 PVMFMP4FFParserNode::FindVideoWidth(uint32 aId) 8589 { 8590 int32 width = 0; 8591 Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it; 8592 for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++) 8593 { 8594 if (it->iTrackId == aId) 8595 { 8596 width = it->iWidth; 8597 } 8598 } 8599 return width; 8600 } 8601 8602 int32 PVMFMP4FFParserNode::FindVideoHeight(uint32 aId) 8603 { 8604 int32 height = 0; 8605 Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it; 8606 for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++) 8607 { 8608 if (it->iTrackId == aId) 8609 { 8610 height = it->iHeight; 8611 } 8612 } 8613 return height; 8614 } 8615 8616 int32 PVMFMP4FFParserNode::FindVideoDisplayWidth(uint32 aId) 8617 { 8618 int32 display_width = 0; 8619 Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it; 8620 for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++) 8621 { 8622 if (it->iTrackId == aId) 8623 { 8624 display_width = it->iDisplayWidth; 8625 } 8626 } 8627 return display_width; 8628 } 8629 8630 int32 PVMFMP4FFParserNode::FindVideoDisplayHeight(uint32 aId) 8631 { 8632 int32 display_height = 0; 8633 Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it; 8634 for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++) 8635 { 8636 if (it->iTrackId == aId) 8637 { 8638 display_height = it->iDisplayHeight; 8639 } 8640 } 8641 return display_height; 8642 } 8643 8644 uint32 PVMFMP4FFParserNode::GetNumAudioChannels(uint32 aId) 8645 { 8646 uint32 num_channels = 0; 8647 uint8 audioObjectType; 8648 uint8 sampleRateIndex; 8649 8650 OSCL_HeapString<OsclMemAllocator> trackMIMEType; 8651 iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType); 8652 8653 if ((oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR, oscl_strlen(PVMF_MIME_AMR)) == 0) || 8654 (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR_IETF, oscl_strlen(PVMF_MIME_AMR_IETF)) == 0) || 8655 (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMRWB_IETF, oscl_strlen(PVMF_MIME_AMRWB_IETF)) == 0)) 8656 { 8657 //always mono 8658 num_channels = 1; 8659 } 8660 else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_MPEG4_AUDIO, oscl_strlen(PVMF_MIME_MPEG4_AUDIO)) == 0) 8661 { 8662 int32 specinfosize = 8663 (int32)(iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId)); 8664 if (specinfosize != 0) 8665 { 8666 // Retrieve the decoder specific info from file parser 8667 uint8* specinfoptr = 8668 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId); 8669 8670 GetActualAacConfig(specinfoptr, 8671 &audioObjectType, 8672 &specinfosize, 8673 &sampleRateIndex, 8674 &num_channels); 8675 } 8676 } 8677 8678 return num_channels; 8679 } 8680 8681 uint32 PVMFMP4FFParserNode::GetAudioSampleRate(uint32 aId) 8682 { 8683 uint32 sample_rate = 0; 8684 uint32 num_channels; 8685 uint8 audioObjectType; 8686 uint8 sampleRateIndex; 8687 8688 const uint32 sample_freq_table[13] = 8689 {96000, 88200, 64000, 48000, 8690 44100, 32000, 24000, 22050, 8691 16000, 12000, 11025, 8000, 8692 7350 8693 }; 8694 8695 OSCL_HeapString<OsclMemAllocator> trackMIMEType; 8696 iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType); 8697 8698 if ((oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR, oscl_strlen(PVMF_MIME_AMR)) == 0) || 8699 (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR_IETF, oscl_strlen(PVMF_MIME_AMR_IETF)) == 0)) 8700 { 8701 //always 8KHz 8702 sample_rate = 8000; 8703 } 8704 else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMRWB_IETF, oscl_strlen(PVMF_MIME_AMRWB_IETF)) == 0) 8705 { 8706 //always 16KHz 8707 sample_rate = 16000; 8708 } 8709 else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_MPEG4_AUDIO, oscl_strlen(PVMF_MIME_MPEG4_AUDIO)) == 0) 8710 { 8711 int32 specinfosize = 8712 (int32)(iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId)); 8713 if (specinfosize != 0) 8714 { 8715 // Retrieve the decoder specific info from file parser 8716 uint8* specinfoptr = 8717 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId); 8718 8719 GetActualAacConfig(specinfoptr, 8720 &audioObjectType, 8721 &specinfosize, 8722 &sampleRateIndex, 8723 &num_channels); 8724 if (sampleRateIndex < 13) 8725 { 8726 sample_rate = sample_freq_table[(uint32)sampleRateIndex]; 8727 } 8728 } 8729 } 8730 return sample_rate; 8731 } 8732 8733 uint32 PVMFMP4FFParserNode::GetAudioBitsPerSample(uint32 aId) 8734 { 8735 OSCL_UNUSED_ARG(aId); 8736 //always 16 bits per samples 8737 return 16; 8738 } 8739 8740 PVMFStatus PVMFMP4FFParserNode::FindBestThumbnailKeyFrame(uint32 aId, uint32& aKeyFrameNum) 8741 { 8742 aKeyFrameNum = PVMFFF_DEFAULT_THUMB_NAIL_SAMPLE_NUMBER; 8743 8744 // Use the MP4 FF API to retrieve the number of sync samples in a track 8745 uint32 numsamples = 0; 8746 int32 retval = iMP4FileHandle->getTimestampForRandomAccessPoints(aId, 8747 &numsamples, 8748 NULL, 8749 NULL); 8750 if (retval == 1 && numsamples > 0) 8751 { 8752 /* It is possible that for some big contents the number of sync samples is a very big 8753 ** value. For these contents retrieval of timesatamps and frame numbers of sync sample 8754 ** will take long time. With NUMSAMPLES_BEST_THUMBNAIL_MODE Parser will try to find 8755 ** best thumbnail frame out of first 10 sync samples. 8756 */ 8757 if (numsamples > NUMSAMPLES_BEST_THUMBNAIL_MODE) 8758 { 8759 numsamples = NUMSAMPLES_BEST_THUMBNAIL_MODE; 8760 } 8761 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - NumKeySamples=%d, TrackID=%d", numsamples, aId)); 8762 8763 // Allocate memory for the info 8764 uint32* syncts = OSCL_ARRAY_NEW(uint32, numsamples); 8765 uint32* syncfrnum = OSCL_ARRAY_NEW(uint32, numsamples); 8766 if (syncts == NULL || syncfrnum == NULL) 8767 { 8768 if (syncts) 8769 { 8770 OSCL_ARRAY_DELETE(syncts); 8771 } 8772 if (syncfrnum) 8773 { 8774 OSCL_ARRAY_DELETE(syncfrnum); 8775 } 8776 return PVMFErrNoMemory; 8777 } 8778 8779 // Retrieve the list of timestamp and frame numbers for sync samples. 8780 retval = 8781 iMP4FileHandle->getTimestampForRandomAccessPoints(aId, 8782 &numsamples, 8783 syncts, 8784 syncfrnum); 8785 if (retval != 1) 8786 { 8787 // Error 8788 if (syncts) 8789 { 8790 OSCL_ARRAY_DELETE(syncts); 8791 } 8792 if (syncfrnum) 8793 { 8794 OSCL_ARRAY_DELETE(syncfrnum); 8795 } 8796 numsamples = 0; 8797 aKeyFrameNum = 0; 8798 return PVMFSuccess; 8799 } 8800 8801 uint64 trackduration; 8802 uint32 samplecount; 8803 trackduration = iMP4FileHandle->getTrackMediaDuration(aId); 8804 samplecount = iMP4FileHandle->getSampleCountInTrack(aId); 8805 8806 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - TrackDuration=%2d", trackduration)); 8807 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - TotalNumSamples=%d", samplecount)); 8808 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - BitRate=%d", (uint32)iMP4FileHandle->getTrackAverageBitrate(aId))); 8809 8810 //go thru the key frame list and determine the optimal key frame 8811 uint32 keySampleNum = syncfrnum[0]; 8812 int32 keySampleSize = 8813 iMP4FileHandle->getSampleSizeAt(aId, (int32)keySampleNum); 8814 aKeyFrameNum = 0; 8815 for (uint32 i = 1; i < numsamples; i++) 8816 { 8817 uint32 keySampleNumNext = syncfrnum[i]; 8818 int32 keySampleSizeNext = 8819 iMP4FileHandle->getSampleSizeAt(aId, (int32)keySampleNumNext); 8820 8821 if (keySampleSizeNext > keySampleSize) 8822 { 8823 keySampleSize = keySampleSizeNext; 8824 aKeyFrameNum = i; 8825 } 8826 } 8827 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - Picked Best KeyFrame=%d", aKeyFrameNum)); 8828 if (syncts) 8829 { 8830 OSCL_ARRAY_DELETE(syncts); 8831 } 8832 if (syncfrnum) 8833 { 8834 OSCL_ARRAY_DELETE(syncfrnum); 8835 } 8836 } 8837 else if (retval == 2) 8838 { 8839 // All samples are sync samples 8840 if (numsamples > NUMSAMPLES_BEST_THUMBNAIL_MODE) 8841 { 8842 numsamples = NUMSAMPLES_BEST_THUMBNAIL_MODE; 8843 } 8844 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - NumKeySamples=%d, TrackID=%d", numsamples, aId)); 8845 8846 //go thru the key frame list and determine the optimal key frame 8847 int32 maxKeySampleSize = 0; 8848 int32 keySampleSize = 0; 8849 aKeyFrameNum = 0; 8850 for (uint32 i = 0; i < numsamples; i++) 8851 { 8852 keySampleSize = iMP4FileHandle->getSampleSizeAt(aId, i); 8853 8854 if (keySampleSize > maxKeySampleSize) 8855 { 8856 maxKeySampleSize = keySampleSize; 8857 aKeyFrameNum = i; 8858 } 8859 } 8860 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - Picked Best KeyFrame=%d", aKeyFrameNum)); 8861 } 8862 else 8863 { 8864 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - No Samples present in SyncSample Table")); 8865 numsamples = 0; 8866 aKeyFrameNum = 0; 8867 return PVMFFailure; 8868 } 8869 return PVMFSuccess; 8870 } 8871 8872 PVMFCommandId 8873 PVMFMP4FFParserNode::GetLicense(PVMFSessionId aSessionId, 8874 OSCL_wString& aContentName, 8875 OsclAny* aData, 8876 uint32 aDataSize, 8877 int32 aTimeoutMsec, 8878 OsclAny* aContextData) 8879 { 8880 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::GetLicense - Wide called")); 8881 PVMFMP4FFParserNodeCommand cmd; 8882 cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId, 8883 PVMP4FF_NODE_CMD_GET_LICENSE_W, 8884 aContentName, 8885 aData, 8886 aDataSize, 8887 aTimeoutMsec, 8888 aContextData); 8889 return QueueCommandL(cmd); 8890 } 8891 8892 PVMFCommandId 8893 PVMFMP4FFParserNode::GetLicense(PVMFSessionId aSessionId, 8894 OSCL_String& aContentName, 8895 OsclAny* aData, 8896 uint32 aDataSize, 8897 int32 aTimeoutMsec, 8898 OsclAny* aContextData) 8899 { 8900 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::GetLicense - Wide called")); 8901 PVMFMP4FFParserNodeCommand cmd; 8902 cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId, 8903 PVMP4FF_NODE_CMD_GET_LICENSE, 8904 aContentName, 8905 aData, 8906 aDataSize, 8907 aTimeoutMsec, 8908 aContextData); 8909 return QueueCommandL(cmd); 8910 } 8911 8912 PVMFCommandId 8913 PVMFMP4FFParserNode::CancelGetLicense(PVMFSessionId aSessionId, PVMFCommandId aCmdId, OsclAny* aContextData) 8914 { 8915 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CancelGetLicense - called")); 8916 PVMFMP4FFParserNodeCommand cmd; 8917 cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMP4FF_NODE_CMD_CANCEL_GET_LICENSE, aCmdId, aContextData); 8918 return QueueCommandL(cmd); 8919 } 8920 8921 PVMFStatus PVMFMP4FFParserNode::GetLicenseStatus( 8922 PVMFCPMLicenseStatus& aStatus) 8923 { 8924 if (iCPMLicenseInterface) 8925 return iCPMLicenseInterface->GetLicenseStatus(aStatus); 8926 return PVMFFailure; 8927 } 8928 8929 PVMFStatus PVMFMP4FFParserNode::DoGetLicense(PVMFMP4FFParserNodeCommand& aCmd, 8930 bool aWideCharVersion) 8931 { 8932 if (iCPMLicenseInterface == NULL) 8933 { 8934 return PVMFErrNotSupported; 8935 } 8936 8937 if (aWideCharVersion == true) 8938 { 8939 OSCL_wString* contentName = NULL; 8940 OsclAny* data = NULL; 8941 uint32 dataSize = 0; 8942 int32 timeoutMsec = 0; 8943 aCmd.PVMFMP4FFParserNodeCommand::Parse(contentName, 8944 data, 8945 dataSize, 8946 timeoutMsec); 8947 iCPMGetLicenseCmdId = 8948 iCPMLicenseInterface->GetLicense(iCPMSessionID, 8949 *contentName, 8950 data, 8951 dataSize, 8952 timeoutMsec); 8953 } 8954 else 8955 { 8956 OSCL_String* contentName = NULL; 8957 OsclAny* data = NULL; 8958 uint32 dataSize = 0; 8959 int32 timeoutMsec = 0; 8960 aCmd.PVMFMP4FFParserNodeCommand::Parse(contentName, 8961 data, 8962 dataSize, 8963 timeoutMsec); 8964 iCPMGetLicenseCmdId = 8965 iCPMLicenseInterface->GetLicense(iCPMSessionID, 8966 *contentName, 8967 data, 8968 dataSize, 8969 timeoutMsec); 8970 } 8971 return PVMFPending; 8972 } 8973 8974 void PVMFMP4FFParserNode::CompleteGetLicense() 8975 { 8976 CommandComplete(iCurrentCommand, 8977 iCurrentCommand.front(), 8978 PVMFSuccess); 8979 } 8980 8981 PVMFStatus PVMFMP4FFParserNode::DoCancelGetLicense(PVMFMP4FFParserNodeCommand& aCmd) 8982 { 8983 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoCancelGetLicense() Called")); 8984 PVMFStatus status = PVMFErrArgument; 8985 8986 if (iCPMLicenseInterface == NULL) 8987 { 8988 status = PVMFErrNotSupported; 8989 } 8990 else 8991 { 8992 /* extract the command ID from the parameters.*/ 8993 PVMFCommandId id; 8994 aCmd.PVMFMP4FFParserNodeCommandBase::Parse(id); 8995 8996 /* first check "current" command if any */ 8997 PVMFMP4FFParserNodeCommand* cmd = iCurrentCommand.FindById(id); 8998 if (cmd) 8999 { 9000 if (cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE_W || cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE) 9001 { 9002 iCPMCancelGetLicenseCmdId = 9003 iCPMLicenseInterface->CancelGetLicense(iCPMSessionID, iCPMGetLicenseCmdId); 9004 9005 /* 9006 * the queued commands are all asynchronous commands to the 9007 * CPM module. CancelGetLicense can cancel only for GetLicense cmd. 9008 * We need to wait CPMCommandCompleted. 9009 */ 9010 return PVMFPending; 9011 } 9012 } 9013 9014 /* 9015 * next check input queue. 9016 * start at element 1 since this cancel command is element 0. 9017 */ 9018 cmd = iInputCommands.FindById(id, 1); 9019 if (cmd) 9020 { 9021 if (cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE_W || cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE) 9022 { 9023 /* cancel the queued command */ 9024 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled, NULL, NULL); 9025 /* report cancel success */ 9026 return PVMFSuccess; 9027 } 9028 } 9029 } 9030 /* if we get here the command isn't queued so the cancel fails */ 9031 return status; 9032 } 9033 9034 bool PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand(PVMP4FFNodeTrackPortInfo& aTrackPortInfo) 9035 { 9036 PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd(); 9037 sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID); 9038 9039 aTrackPortInfo.iClockConverter->update_clock(aTrackPortInfo.iTimestamp); 9040 uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000); 9041 sharedMediaCmdPtr->setTimestamp(timestamp); 9042 9043 PVMFSharedMediaMsgPtr mediaMsgOut; 9044 convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr); 9045 mediaMsgOut->setStreamID(iStreamID); 9046 mediaMsgOut->setSeqNum(aTrackPortInfo.iSeqNum); 9047 9048 if (aTrackPortInfo.iPortInterface->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess) 9049 { 9050 // Output queue is busy, so wait for the output queue being ready 9051 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 9052 (0, "PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand: Outgoing queue busy. ")); 9053 if (aTrackPortInfo.iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA) 9054 { 9055 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DESTFULL; 9056 } 9057 return false; 9058 } 9059 aTrackPortInfo.iSendBOS = false; 9060 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand() BOS sent - Mime=%s, StreamId=%d, TS=%d", 9061 aTrackPortInfo.iMimeType.get_cstr(), 9062 iStreamID, 9063 timestamp)); 9064 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand() BOS sent StreamId=%d ", iStreamID)); 9065 return true; 9066 } 9067 9068 void PVMFMP4FFParserNode::NotificationsInterfaceDestroyed() 9069 { 9070 iClockNotificationsInf = NULL; 9071 } 9072 9073 void PVMFMP4FFParserNode::ClockStateUpdated() 9074 { 9075 if ((iExternalDownload && iUnderFlowEventReported) || 9076 (autopaused && download_progress_interface != NULL)) 9077 { 9078 // Don't let anyone start the clock while the source node is in underflow 9079 if (iClientPlayBackClock != NULL) 9080 { 9081 if (iClientPlayBackClock->GetState() == PVMFMediaClock::RUNNING) 9082 { 9083 iClientPlayBackClock->Pause(); 9084 } 9085 } 9086 } 9087 } 9088 9089 9090 int32 PVMFMP4FFParserNode::CreateErrorInfoMsg(PVMFBasicErrorInfoMessage** aErrorMsg, PVUuid aEventUUID, int32 aEventCode) 9091 { 9092 int32 leavecode = 0; 9093 OSCL_TRY(leavecode, *aErrorMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, aEventUUID, NULL))); 9094 return leavecode; 9095 } 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110