1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 /** 19 * @file pvmp4ffcn_node.cpp 20 * @brief Node for PV MPEG4 file format composer 21 */ 22 23 /* 24 * FIXME: 25 * The current implementation of the file writer is NOT 26 * thread-safe. 27 * 28 * A separate delete queue should be used to 29 * pass back the fragments from the file writer thread 30 * to the composer node and to let the composer node 31 * handle the deallocation of any fragments; otherwise, 32 * race condition may occur. Some lost free chunk 33 * notification has been found due to this race 34 * condition. 35 * 36 * The reason why there is race condition is that the 37 * rest of the OpenCore assumes a single-thread model. 38 * In other words, everything is scheduled to 39 * run within a single omx thread. A separate file writer 40 * thread breaks this model, and deallocate fragments 41 * here may cause deallocate() be called within two 42 * separate thread, and thus the free chunk available 43 * flag can be corrupted. 44 * 45 * Don't remove the following #undef line unless you 46 * fix the above issue. 47 */ 48 #undef ANDROID 49 50 #ifdef ANDROID 51 // #define LOG_NDEBUG 0 52 #define LOG_TAG "PvMp4Composer" 53 #include <utils/Log.h> 54 #include <utils/Errors.h> 55 #include <utils/threads.h> 56 #endif // ANDROID 57 58 #ifndef PVMP4FFCN_NODE_H_INCLUDED 59 #include "pvmp4ffcn_node.h" 60 #endif 61 #ifndef PVMP4FFCN_FACTORY_H_INCLUDED 62 #include "pvmp4ffcn_factory.h" 63 #endif 64 #ifndef PVMP4FFCN_PORT_H_INCLUDED 65 #include "pvmp4ffcn_port.h" 66 #endif 67 #ifndef OSCL_DLL_H_INCLUDED 68 #include "oscl_dll.h" 69 #endif 70 #ifndef OSCL_MEM_BASIC_FUNCTIONS_H 71 #include "oscl_mem_basic_functions.h" 72 #endif 73 74 #ifdef ANDROID 75 namespace android 76 { 77 78 // FragmentWriter is a queue of media fragment to be written in the 79 // media file. The caller enqueues the next fragment and returns 80 // immediately. An separate thread dequeues the fragment and writes it. 81 // 82 // This class is friend with the composer node it belongs to, in order 83 // to be able to call the original AddMemFragToTrack which does all 84 // the work. 85 86 #define FRAME_QUEUE_DEFAULT_SIZE 20 87 88 class FragmentWriter: public Thread 89 { 90 public: 91 FragmentWriter(PVMp4FFComposerNode *composer) : 92 Thread(kThreadCallJava), mComposer(composer), 93 mPrevWriteStatus(PVMFSuccess), mTid(NULL), mExitRequested(false) 94 { 95 mQueue.reserve(FRAME_QUEUE_DEFAULT_SIZE); 96 } 97 98 virtual ~FragmentWriter() 99 { 100 Mutex::Autolock l(mRequestMutex); 101 102 LOG_ASSERT(mExitRequested, "Deleting an active instance."); 103 LOGD_IF(!mQueue.empty(), "Releasing %d fragments in dtor", mQueue.size()); 104 105 while (!mQueue.empty()) // make sure we are flushed 106 { 107 releaseQueuedFrame(mQueue.begin()); 108 } 109 } 110 111 // Mark the thread as exiting and kick it so it can see the 112 // exitPending state. 113 virtual void requestExit() 114 { 115 mExitRequested = true; 116 Thread::requestExit(); 117 118 mRequestMutex.lock(); 119 mRequestCv.signal(); 120 mRequestMutex.unlock(); 121 } 122 123 // Wait for all the fragment to be written. 124 virtual void flush() 125 { 126 LOG_ASSERT(androidGetThreadId() != mTid, "Reentrant call"); 127 128 bool done = false; 129 size_t iter = 0; 130 while (!done) 131 { 132 mRequestMutex.lock(); 133 done = mQueue.empty(); 134 if (!done) mRequestCv.signal(); 135 mRequestMutex.unlock(); 136 if (!done) { 137 usleep(kFlushSleepMicros); 138 if ((++iter % kMaxFlushAttemptsWarning) == 0) { 139 if (iter >= kMaxFlushAttemptsCrashing) { 140 LOGE("Fragment flush takes way too long!"); 141 // Crash media server! 142 *((char *) 0) = 0x01; 143 } else { 144 LOGW("Fragement writer flush takes %d us", iter * kFlushSleepMicros); 145 } 146 } 147 } 148 } 149 } 150 151 // Called by the ProcessIncomingMsg method from the 152 // PVMp4FFComposerNode to append the fragment to the track. 153 // @return The result of the *previous* fragment written. Since the call 154 // is asynch we cannot wait. 155 PVMFStatus enqueueMemFragToTrack(Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> aFrame, 156 OsclRefCounterMemFrag& aMemFrag, PVMFFormatType aFormat, 157 uint32& aTimestamp, int32 aTrackId, PVMp4FFComposerPort *aPort) 158 { 159 if (mExitRequested) { 160 LOGW("Enqueue fragment after exit request!"); 161 aFrame.clear(); // Release the frame 162 return PVMFErrCancelled; 163 } 164 165 Mutex::Autolock lock(mRequestMutex); 166 Request frame = {aFrame, aMemFrag, aFormat, aTimestamp, aTrackId, aPort}; 167 mQueue.push_back(frame); 168 mRequestCv.signal(); 169 return mPrevWriteStatus; 170 } 171 172 private: 173 static const bool kThreadCallJava = false; 174 static const OsclRefCounterMemFrag kEmptyFrag; 175 static const int kFlushSleepMicros = 200 * 1000; // 200 ms 176 static const size_t kMaxFlushAttemptsWarning = 10; // 2 seconds 177 static const size_t kMaxFlushAttemptsCrashing = 30; // 6 seconds 178 179 struct Request 180 { 181 Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> mFrame; 182 OsclRefCounterMemFrag mFrag; 183 PVMFFormatType mFormat; 184 uint32 mTimestamp; 185 uint32 mTrackId; 186 PVMp4FFComposerPort *mPort; 187 }; 188 189 void releaseQueuedFrame(Request *frame) 190 { 191 if (!frame) { 192 LOGE("Frame not valid"); 193 return; 194 } 195 frame->mFrame.clear(); 196 // Release the memory fragment tracked using a refcount 197 // class. Need to assign an empty frag to release the memory 198 // fragment. We cannot wait for the array to wrap around. 199 frame->mFrag = kEmptyFrag; // FIXME: This assignement to decr the ref count is ugly. 200 mQueue.erase(frame); 201 } 202 203 // Called by the base class Thread. 204 // @return true if there more work to do. false when done. 205 // @Override Thread 206 virtual bool threadLoop() 207 { 208 if (!mTid) mTid = androidGetThreadId(); 209 210 LOG_ASSERT(androidGetThreadId() == mTid, 211 "Thread id has changed!: %p != %p", mTid, androidGetThreadId()); 212 if (mExitRequested) 213 return false; 214 215 mRequestMutex.lock(); 216 if (mQueue.empty()) 217 mRequestCv.wait(mRequestMutex); 218 219 if (!mQueue.empty()) { 220 // Hold the lock while writing the fragment 221 Request frame = mQueue[0]; // Make a local copy 222 mPrevWriteStatus = mComposer->AddMemFragToTrack( 223 frame.mFrame, frame.mFrag, frame.mFormat, 224 frame.mTimestamp, frame.mTrackId, frame.mPort); 225 if (!mQueue.empty()) { 226 releaseQueuedFrame(mQueue.begin()); 227 } 228 } 229 mRequestMutex.unlock(); 230 231 return true; 232 } 233 234 235 Mutex mRequestMutex; // Protects mRequestCv, mQueue 236 Condition mRequestCv; 237 Oscl_Vector<Request, OsclMemAllocator> mQueue; 238 // mComposer with the real implementation of the AddMemFragToTrack method. 239 PVMp4FFComposerNode *mComposer; 240 // TODO: lock needed for mPrevWriteStatus? Are int assignement atomic on arm? 241 PVMFStatus mPrevWriteStatus; 242 243 android_thread_id_t mTid; 244 // Unlike exitPending(), stays to true once exit has been called. 245 bool mExitRequested; 246 }; 247 const OsclRefCounterMemFrag FragmentWriter::kEmptyFrag; 248 } 249 #endif // ANDROID 250 251 #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m); 252 #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m); 253 #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m); 254 #define LOGDATATRAFFIC(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_INFO,m); 255 256 #ifdef _TEST_AE_ERROR_HANDLING 257 const uint32 FAIL_NODE_CMD_START = 2; 258 const uint32 FAIL_NODE_CMD_STOP = 3; 259 const uint32 FAIL_NODE_CMD_FLUSH = 4; 260 const uint32 FAIL_NODE_CMD_PAUSE = 5; 261 const uint32 FAIL_NODE_CMD_RELEASE_PORT = 7; 262 #endif 263 264 #define SLASH '/' 265 266 #define LANG_CODE_SIZE 3 267 268 // Define entry point for this DLL 269 OSCL_DLL_ENTRY_POINT_DEFAULT() 270 271 272 273 //////////////////////////////////////////////////////////////////////////// 274 OSCL_EXPORT_REF PVMFNodeInterface* PVMp4FFComposerNodeFactory::CreateMp4FFComposer(int32 aPriority) 275 { 276 int32 err = 0; 277 PVMFNodeInterface* node = NULL; 278 279 OSCL_TRY(err, 280 node = (PVMFNodeInterface*)OSCL_NEW(PVMp4FFComposerNode, (aPriority)); 281 if (!node) 282 OSCL_LEAVE(OsclErrNoMemory); 283 ); 284 285 OSCL_FIRST_CATCH_ANY(err, return NULL;); 286 return node; 287 } 288 289 //////////////////////////////////////////////////////////////////////////// 290 OSCL_EXPORT_REF bool PVMp4FFComposerNodeFactory::DeleteMp4FFComposer(PVMFNodeInterface* aComposer) 291 { 292 if (aComposer) 293 { 294 PVMp4FFComposerNode* node = (PVMp4FFComposerNode*)aComposer; 295 OSCL_DELETE(node); 296 return true; 297 } 298 299 return false; 300 } 301 302 //////////////////////////////////////////////////////////////////////////// 303 PVMp4FFComposerNode::PVMp4FFComposerNode(int32 aPriority) 304 : OsclActiveObject(aPriority, "PVMp4FFComposerNode") 305 , iMpeg4File(NULL) 306 , iFileType(0) 307 , iAuthoringMode(PVMP4FF_3GPP_DOWNLOAD_MODE) 308 , iPresentationTimescale(1000) 309 , iMovieFragmentDuration(2000) 310 , iRecordingYear(0) 311 , iClockConverter(8000) 312 , iExtensionRefCount(0) 313 , iRealTimeTS(false) 314 , iInitTSOffset(false) 315 , iTSOffset(0) 316 , iMaxFileSizeEnabled(false) 317 , iMaxDurationEnabled(false) 318 , iMaxFileSize(0) 319 , iMaxTimeDuration(0) 320 , iFileSizeReportEnabled(false) 321 , iDurationReportEnabled(false) 322 , iFileSizeReportFreq(0) 323 , iDurationReportFreq(0) 324 , iNextDurationReport(0) 325 , iNextFileSizeReport(0) 326 , iCacheSize(0) 327 , iConfigSize(0) 328 , pConfig(NULL) 329 , iTrackId_H264(0) 330 , iTrackId_Text(0) 331 , iSyncSample(0) 332 , iformat_h264(PVMF_MIME_FORMAT_UNKNOWN) 333 , iformat_text(PVMF_MIME_FORMAT_UNKNOWN) 334 , iNodeEndOfDataReached(false) 335 , iSampleInTrack(false) 336 , iFileRendered(false) 337 { 338 iInterfaceState = EPVMFNodeCreated; 339 iNum_PPS_Set = 0; 340 iNum_SPS_Set = 0; 341 iText_sdIndex = 0; 342 iFileObject = NULL; 343 #if PROFILING_ON 344 iMaxSampleAddTime = 0; 345 iMinSampleAddTime = 0; 346 iMinSampleSize = 0; 347 iMaxSampleSize = 0; 348 iNumSamplesAdded = 0; 349 oDiagnosticsLogged = false; 350 iDiagnosticsLogger = PVLogger::GetLoggerObject("pvauthordiagnostics.composer.mp4"); 351 // Statistics 352 for (uint32 i = 0; i < 3; i++) 353 oscl_memset(&(iStats[i]), 0, sizeof(PVMp4FFCNStats)); 354 #endif 355 356 iLogger = PVLogger::GetLoggerObject("PVMp4FFComposerNode"); 357 iDataPathLogger = PVLogger::GetLoggerObject("datapath.sinknode.mp4composer"); 358 int32 err; 359 OSCL_TRY(err, 360 //Create the input command queue. Use a reserve to avoid lots of 361 //dynamic memory allocation. 362 iCmdQueue.Construct(PVMF_MP4FFCN_COMMAND_ID_START, PVMF_MP4FFCN_COMMAND_VECTOR_RESERVE); 363 iCurrentCmd.Construct(0, 1); // There's only 1 current command 364 365 366 //Create the port vector. 367 iInPorts.Construct(PVMF_MP4FFCN_PORT_VECTOR_RESERVE); 368 ); 369 370 OSCL_FIRST_CATCH_ANY(err, 371 //if a leave happened, cleanup and re-throw the error 372 iCmdQueue.clear(); 373 iCurrentCmd.clear(); 374 iInPorts.clear(); 375 memvector_sps.clear(); 376 memvector_pps.clear(); 377 OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface); 378 OSCL_CLEANUP_BASE_CLASS(OsclActiveObject); 379 OSCL_LEAVE(err); 380 ); 381 382 #ifdef ANDROID 383 iMaxReachedEvent = 0; 384 iMaxReachedReported = false; 385 iFragmentWriter = new android::FragmentWriter(this); 386 iFragmentWriter->run(LOG_TAG); 387 #endif 388 389 #ifdef _TEST_AE_ERROR_HANDLING 390 iErrorHandlingAddMemFrag = false; 391 iErrorHandlingAddTrack = false; 392 iErrorCreateComposer = false; 393 iErrorRenderToFile = false; 394 iErrorAddTrack = PVMF_MIME_FORMAT_UNKNOWN; 395 iErrorNodeCmd = 0; 396 iTestFileSize = 0; 397 iTestTimeStamp = 0; 398 iErrorAddSample = 0; 399 iFileSize = 0; 400 iFileDuration = 0; 401 iErrorDataPathStall = 0; 402 #endif 403 } 404 405 //////////////////////////////////////////////////////////////////////////// 406 PVMp4FFComposerNode::~PVMp4FFComposerNode() 407 { 408 #if PROFILING_ON 409 if (!oDiagnosticsLogged) 410 { 411 LogDiagnostics(); 412 } 413 #endif 414 415 #ifdef ANDROID 416 if (iFragmentWriter != NULL) 417 { 418 iFragmentWriter->requestExit(); // kick the thread 419 iFragmentWriter->requestExitAndWait(); 420 } 421 #endif 422 423 if (iMpeg4File) 424 { 425 PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File); 426 427 if (!iFileRendered) 428 { 429 iFs.Connect(); 430 iFs.Oscl_DeleteFile(iFileName.get_cstr()); 431 iFs.Close(); 432 } 433 } 434 if (iFileObject) 435 { 436 iFileObject->Close(); 437 OSCL_DELETE(iFileObject); 438 iFileObject = NULL; 439 } 440 for (uint32 i = 0; i < iKeyWordVector.size() ; i++) 441 { 442 if (iKeyWordVector[i] != NULL) 443 { 444 OSCL_DELETE(iKeyWordVector[i]); 445 iKeyWordVector[i] = NULL; 446 } 447 448 } 449 450 if (pConfig != NULL) 451 { 452 OSCL_FREE(pConfig); 453 iConfigSize = 0; 454 } 455 456 if (iLocationInfo._location_name != NULL) 457 { 458 OSCL_FREE(iLocationInfo._location_name); 459 } 460 461 if (iLocationInfo._astronomical_body != NULL) 462 { 463 OSCL_FREE(iLocationInfo._astronomical_body); 464 } 465 466 if (iLocationInfo._additional_notes != NULL) 467 { 468 OSCL_FREE(iLocationInfo._additional_notes); 469 } 470 // Cleanup allocated ports 471 while (!iInPorts.empty()) 472 { 473 iInPorts.Erase(&iInPorts.front()); 474 475 } 476 //Cleanup commands 477 //The command queues are self-deleting, but we want to 478 //notify the observer of unprocessed commands. 479 while (!iCmdQueue.empty()) 480 { 481 CommandComplete(iCmdQueue, iCmdQueue[0], PVMFFailure); 482 } 483 484 while (!iCurrentCmd.empty()) 485 { 486 CommandComplete(iCurrentCmd, iCurrentCmd[0], PVMFFailure); 487 } 488 iNodeEndOfDataReached = false; 489 490 Cancel(); 491 if (iInterfaceState != EPVMFNodeCreated) 492 iInterfaceState = EPVMFNodeIdle; 493 494 } 495 496 //////////////////////////////////////////////////////////////////////////// 497 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::ThreadLogon() 498 { 499 switch (iInterfaceState) 500 { 501 case EPVMFNodeCreated: 502 if (!IsAdded()) 503 AddToScheduler(); 504 SetState(EPVMFNodeIdle); 505 return PVMFSuccess; 506 default: 507 return PVMFErrInvalidState; 508 } 509 } 510 511 //////////////////////////////////////////////////////////////////////////// 512 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::ThreadLogoff() 513 { 514 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMp4FFComposerNode:ThreadLogoff")); 515 switch (iInterfaceState) 516 { 517 case EPVMFNodeIdle: 518 if (IsAdded()) 519 RemoveFromScheduler(); 520 iLogger = NULL; 521 iDataPathLogger = NULL; 522 SetState(EPVMFNodeCreated); 523 return PVMFSuccess; 524 525 default: 526 return PVMFErrInvalidState; 527 } 528 } 529 530 //////////////////////////////////////////////////////////////////////////// 531 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::GetCapability(PVMFNodeCapability& aNodeCapability) 532 { 533 aNodeCapability.iCanSupportMultipleInputPorts = true; 534 aNodeCapability.iCanSupportMultipleOutputPorts = false; 535 aNodeCapability.iHasMaxNumberOfPorts = true; 536 aNodeCapability.iMaxNumberOfPorts = PVMF_MP4FFCN_MAX_INPUT_PORT + PVMF_MP4FFCN_MAX_OUTPUT_PORT; 537 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_M4V); 538 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_MP4); 539 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H2631998); 540 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H2632000); 541 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IETF); 542 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB_IETF); 543 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_3GPP_TIMEDTEXT); 544 aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_MPEG4_AUDIO); 545 return PVMFSuccess; 546 } 547 548 //////////////////////////////////////////////////////////////////////////// 549 OSCL_EXPORT_REF PVMFPortIter* PVMp4FFComposerNode::GetPorts(const PVMFPortFilter* aFilter) 550 { 551 OSCL_UNUSED_ARG(aFilter); 552 iInPorts.Reset(); 553 return &iInPorts; 554 } 555 556 //////////////////////////////////////////////////////////////////////////// 557 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::QueryUUID(PVMFSessionId aSession, const PvmfMimeString& aMimeType, 558 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids, 559 bool aExactUuidsOnly, const OsclAny* aContext) 560 { 561 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::QueryUUID")); 562 563 PVMp4FFCNCmd cmd; 564 cmd.Construct(aSession, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext); 565 return QueueCommandL(cmd); 566 } 567 568 //////////////////////////////////////////////////////////////////////////// 569 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::QueryInterface(PVMFSessionId aSession, const PVUuid& aUuid, 570 PVInterface*& aInterfacePtr, 571 const OsclAny* aContext) 572 { 573 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 574 (0, "PVMp4FFComposerNode::QueryInterface")); 575 PVMp4FFCNCmd cmd; 576 cmd.Construct(aSession, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext); 577 return QueueCommandL(cmd); 578 } 579 580 //////////////////////////////////////////////////////////////////////////// 581 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Init(PVMFSessionId aSession, const OsclAny* aContext) 582 { 583 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Init")); 584 PVMp4FFCNCmd cmd; 585 cmd.Construct(aSession, PVMF_GENERIC_NODE_INIT, aContext); 586 return QueueCommandL(cmd); 587 } 588 589 //////////////////////////////////////////////////////////////////////////// 590 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Prepare(PVMFSessionId aSession, const OsclAny* aContext) 591 { 592 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Prepare")); 593 PVMp4FFCNCmd cmd; 594 cmd.Construct(aSession, PVMF_GENERIC_NODE_PREPARE, aContext); 595 return QueueCommandL(cmd); 596 } 597 598 //////////////////////////////////////////////////////////////////////////// 599 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::RequestPort(PVMFSessionId aSession, 600 int32 aPortTag, 601 const PvmfMimeString* aPortConfig, 602 const OsclAny* aContext) 603 { 604 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::RequestPort")); 605 PVMp4FFCNCmd cmd; 606 cmd.Construct(aSession, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext); 607 return QueueCommandL(cmd); 608 } 609 610 //////////////////////////////////////////////////////////////////////////// 611 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::ReleasePort(PVMFSessionId aSession, 612 PVMFPortInterface& aPort, 613 const OsclAny* aContext) 614 { 615 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::ReleasePort")); 616 PVMp4FFCNCmd cmd; 617 cmd.Construct(aSession, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext); 618 return QueueCommandL(cmd); 619 } 620 621 //////////////////////////////////////////////////////////////////////////// 622 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Start(PVMFSessionId aSession, const OsclAny* aContext) 623 { 624 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Start")); 625 PVMp4FFCNCmd cmd; 626 cmd.Construct(aSession, PVMF_GENERIC_NODE_START, aContext); 627 return QueueCommandL(cmd); 628 } 629 630 //////////////////////////////////////////////////////////////////////////// 631 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Stop(PVMFSessionId aSession, const OsclAny* aContext) 632 { 633 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Stop")); 634 PVMp4FFCNCmd cmd; 635 cmd.Construct(aSession, PVMF_GENERIC_NODE_STOP, aContext); 636 return QueueCommandL(cmd); 637 } 638 639 //////////////////////////////////////////////////////////////////////////// 640 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Pause(PVMFSessionId aSession, const OsclAny* aContext) 641 { 642 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Pause")); 643 PVMp4FFCNCmd cmd; 644 cmd.Construct(aSession, PVMF_GENERIC_NODE_PAUSE, aContext); 645 return QueueCommandL(cmd); 646 } 647 648 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Flush(PVMFSessionId aSession, const OsclAny* aContext) 649 { 650 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Flush")); 651 PVMp4FFCNCmd cmd; 652 cmd.Construct(aSession, PVMF_GENERIC_NODE_FLUSH, aContext); 653 return QueueCommandL(cmd); 654 } 655 656 //////////////////////////////////////////////////////////////////////////// 657 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Reset(PVMFSessionId aSession, const OsclAny* aContext) 658 { 659 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Reset")); 660 PVMp4FFCNCmd cmd; 661 cmd.Construct(aSession, PVMF_GENERIC_NODE_RESET, aContext); 662 return QueueCommandL(cmd); 663 } 664 665 //////////////////////////////////////////////////////////////////////////// 666 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::CancelAllCommands(PVMFSessionId aSession, const OsclAny* aContext) 667 { 668 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::CancelAllCommands")); 669 PVMp4FFCNCmd cmd; 670 cmd.Construct(aSession, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext); 671 return QueueCommandL(cmd); 672 } 673 674 //////////////////////////////////////////////////////////////////////////// 675 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::CancelCommand(PVMFSessionId aSession, PVMFCommandId aCmdId, const OsclAny* aContext) 676 { 677 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::CancelCommand")); 678 PVMp4FFCNCmd cmd; 679 cmd.Construct(aSession, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext); 680 return QueueCommandL(cmd); 681 } 682 683 //////////////////////////////////////////////////////////////////////////// 684 OSCL_EXPORT_REF void PVMp4FFComposerNode::addRef() 685 { 686 ++iExtensionRefCount; 687 } 688 689 //////////////////////////////////////////////////////////////////////////// 690 OSCL_EXPORT_REF void PVMp4FFComposerNode::removeRef() 691 { 692 if (iExtensionRefCount > 0) 693 --iExtensionRefCount; 694 } 695 696 //////////////////////////////////////////////////////////////////////////// 697 OSCL_EXPORT_REF bool PVMp4FFComposerNode::queryInterface(const PVUuid& uuid, PVInterface*& iface) 698 { 699 if (uuid == KPVMp4FFCNClipConfigUuid) 700 { 701 PVMp4FFCNClipConfigInterface* myInterface = OSCL_STATIC_CAST(PVMp4FFCNClipConfigInterface*, this); 702 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 703 ++iExtensionRefCount; 704 } 705 else if (uuid == KPVMp4FFCNTrackConfigUuid) 706 { 707 PVMp4FFCNTrackConfigInterface* myInterface = OSCL_STATIC_CAST(PVMp4FFCNTrackConfigInterface*, this); 708 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 709 ++iExtensionRefCount; 710 } 711 else if (uuid == PvmfComposerSizeAndDurationUuid) 712 { 713 PvmfComposerSizeAndDurationInterface* myInterface = OSCL_STATIC_CAST(PvmfComposerSizeAndDurationInterface*, this); 714 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 715 ++iExtensionRefCount; 716 } 717 else if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID) 718 { 719 PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this); 720 iface = OSCL_STATIC_CAST(PVInterface*, myInterface); 721 ++iExtensionRefCount; 722 } 723 else 724 { 725 iface = NULL; 726 return false; 727 } 728 729 return true; 730 } 731 732 //////////////////////////////////////////////////////////////////////////// 733 // PVMp4FFCNClipConfigInterface routines 734 //////////////////////////////////////////////////////////////////////////// 735 OSCL_EXPORT_REF uint16 PVMp4FFComposerNode::ConvertLangCode(const OSCL_String & aLang) 736 { 737 int i = 0; 738 char lang[LANG_CODE_SIZE] = {0}; 739 oscl_strncpy(lang, aLang.get_cstr(), LANG_CODE_SIZE); 740 741 uint16 lang_code = ((((uint16)lang[i] - 0x60) << 10) | (((uint16)lang[i+1] - 0x60) << 5) | ((uint16)lang[i+2] - 0x60)); 742 743 return lang_code; 744 } 745 ///////////////////////////////////////////////////////////////////////////// 746 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFileName(const OSCL_wString& aFileName) 747 { 748 if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized) 749 return false; 750 751 iFileName = aFileName; 752 return PVMFSuccess; 753 } 754 ////////////////////////////////////////////////////////////////////////////// 755 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFileDescriptor(const OsclFileHandle* aFileHandle) 756 { 757 if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized) 758 return false; 759 760 iFileObject = OSCL_NEW(Oscl_File, (0, (OsclFileHandle *)aFileHandle)); 761 iFileObject->SetPVCacheSize(0); 762 iFileObject->SetAsyncReadBufferSize(0); 763 iFileObject->SetNativeBufferSize(0); 764 iFileObject->SetLoggingEnable(false); 765 iFileObject->SetSummaryStatsLoggingEnable(false); 766 iFileObject->SetFileHandle((OsclFileHandle*)aFileHandle); 767 768 //call open 769 int32 retval = iFileObject->Open(_STRLIT_CHAR("dummy"), 770 Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY, 771 iFs); 772 773 if (retval == 0) 774 { 775 return PVMFSuccess; 776 } 777 return PVMFFailure; 778 } 779 //////////////////////////////////////////////////////////////////////////// 780 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAuthoringMode(PVMp4FFCN_AuthoringMode aAuthoringMode) 781 { 782 if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized) 783 return PVMFErrInvalidState; 784 785 iAuthoringMode = aAuthoringMode; 786 return PVMFSuccess; 787 } 788 789 //////////////////////////////////////////////////////////////////////////// 790 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetPresentationTimescale(uint32 aTimescale) 791 { 792 if (iInterfaceState != EPVMFNodeIdle && 793 iInterfaceState != EPVMFNodeInitialized && 794 iInterfaceState != EPVMFNodePrepared) 795 return PVMFErrInvalidState; 796 797 iPresentationTimescale = aTimescale; 798 return PVMFSuccess; 799 } 800 801 //////////////////////////////////////////////////////////////////////////// 802 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetVersion(const OSCL_wString& aVersion, const OSCL_String& aLangCode) 803 { 804 if (iInterfaceState != EPVMFNodeIdle && 805 iInterfaceState != EPVMFNodeInitialized && 806 iInterfaceState != EPVMFNodePrepared) 807 return PVMFErrInvalidState; 808 809 iVersion.iDataString = aVersion; 810 iVersion.iLangCode = ConvertLangCode(aLangCode); 811 return PVMFSuccess; 812 } 813 814 //////////////////////////////////////////////////////////////////////////// 815 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetTitle(const OSCL_wString& aTitle, const OSCL_String& aLangCode) 816 { 817 if (iInterfaceState != EPVMFNodeIdle && 818 iInterfaceState != EPVMFNodeInitialized && 819 iInterfaceState != EPVMFNodePrepared) 820 return PVMFErrInvalidState; 821 822 iTitle.iDataString = aTitle; 823 iTitle.iLangCode = ConvertLangCode(aLangCode); 824 return PVMFSuccess; 825 } 826 827 //////////////////////////////////////////////////////////////////////////// 828 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAuthor(const OSCL_wString& aAuthor, const OSCL_String& aLangCode) 829 { 830 if (iInterfaceState != EPVMFNodeIdle && 831 iInterfaceState != EPVMFNodeInitialized && 832 iInterfaceState != EPVMFNodePrepared) 833 return PVMFErrInvalidState; 834 835 iAuthor.iDataString = aAuthor; 836 iAuthor.iLangCode = ConvertLangCode(aLangCode); 837 return PVMFSuccess; 838 } 839 840 //////////////////////////////////////////////////////////////////////////// 841 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCopyright(const OSCL_wString& aCopyright, const OSCL_String& aLangCode) 842 { 843 if (iInterfaceState != EPVMFNodeIdle && 844 iInterfaceState != EPVMFNodeInitialized && 845 iInterfaceState != EPVMFNodePrepared) 846 return PVMFErrInvalidState; 847 848 iCopyright.iDataString = aCopyright; 849 iCopyright.iLangCode = ConvertLangCode(aLangCode); 850 return PVMFSuccess; 851 } 852 853 //////////////////////////////////////////////////////////////////////////// 854 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetDescription(const OSCL_wString& aDescription, const OSCL_String& aLangCode) 855 { 856 if (iInterfaceState != EPVMFNodeIdle && 857 iInterfaceState != EPVMFNodeInitialized && 858 iInterfaceState != EPVMFNodePrepared) 859 return PVMFErrInvalidState; 860 861 iDescription.iDataString = aDescription; 862 iDescription.iLangCode = ConvertLangCode(aLangCode); 863 return PVMFSuccess; 864 } 865 866 //////////////////////////////////////////////////////////////////////////// 867 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetRating(const OSCL_wString& aRating, const OSCL_String& aLangCode) 868 { 869 if (iInterfaceState != EPVMFNodeIdle && 870 iInterfaceState != EPVMFNodeInitialized && 871 iInterfaceState != EPVMFNodePrepared) 872 return PVMFErrInvalidState; 873 874 iRating.iDataString = aRating; 875 iRating.iLangCode = ConvertLangCode(aLangCode); 876 return PVMFSuccess; 877 } 878 879 //////////////////////////////////////////////////////////////////////////// 880 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCreationDate(const OSCL_wString& aCreationDate) 881 { 882 if (iInterfaceState != EPVMFNodeIdle && 883 iInterfaceState != EPVMFNodeInitialized && 884 iInterfaceState != EPVMFNodePrepared) 885 return PVMFErrInvalidState; 886 887 iCreationDate = aCreationDate; 888 return PVMFSuccess; 889 } 890 891 //////////////////////////////////////////////////////////////////////////// 892 PVMFStatus PVMp4FFComposerNode::SetRealTimeAuthoring(const bool aRealTime) 893 { 894 if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized) 895 return PVMFErrInvalidState; 896 897 iRealTimeTS = aRealTime; 898 return PVMFSuccess; 899 } 900 901 //////////////////////////////////////////////////////////////////////////// 902 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAlbumInfo(const OSCL_wString& aAlbumTitle, const OSCL_String& aLangCode) 903 { 904 if (iInterfaceState != EPVMFNodeIdle && 905 iInterfaceState != EPVMFNodeInitialized && 906 iInterfaceState != EPVMFNodePrepared) 907 return PVMFErrInvalidState; 908 909 iAlbumTitle.iDataString = aAlbumTitle; 910 iAlbumTitle.iLangCode = ConvertLangCode(aLangCode); 911 return PVMFSuccess; 912 } 913 914 915 //////////////////////////////////////////////////////////////////////////// 916 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetRecordingYear(uint16 aRecordingYear) 917 { 918 if (iInterfaceState != EPVMFNodeIdle && 919 iInterfaceState != EPVMFNodeInitialized && 920 iInterfaceState != EPVMFNodePrepared) 921 return PVMFErrInvalidState; 922 923 iRecordingYear = aRecordingYear; 924 return PVMFSuccess; 925 } 926 927 //////////////////////////////////////////////////////////////////////////// 928 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetPerformer(const OSCL_wString& aPerformer, const OSCL_String& aLangCode) 929 { 930 if (iInterfaceState != EPVMFNodeIdle && 931 iInterfaceState != EPVMFNodeInitialized && 932 iInterfaceState != EPVMFNodePrepared) 933 return PVMFErrInvalidState; 934 935 iPerformer.iDataString = aPerformer; 936 iPerformer.iLangCode = ConvertLangCode(aLangCode); 937 return PVMFSuccess; 938 } 939 940 //////////////////////////////////////////////////////////////////////////// 941 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetGenre(const OSCL_wString& aGenre, const OSCL_String& aLangCode) 942 { 943 if (iInterfaceState != EPVMFNodeIdle && 944 iInterfaceState != EPVMFNodeInitialized && 945 iInterfaceState != EPVMFNodePrepared) 946 return PVMFErrInvalidState; 947 948 iGenre.iDataString = aGenre; 949 iGenre.iLangCode = ConvertLangCode(aLangCode); 950 return PVMFSuccess; 951 } 952 //////////////////////////////////////////////////////////////////////////// 953 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetClassification(const OSCL_wString& aClassificationInfo, uint32 aClassificationEntity, uint16 aClassificationTable, const OSCL_String& aLangCode) 954 { 955 if (iInterfaceState != EPVMFNodeIdle && 956 iInterfaceState != EPVMFNodeInitialized && 957 iInterfaceState != EPVMFNodePrepared) 958 return PVMFErrInvalidState; 959 960 iClassification.iDataString = aClassificationInfo; 961 iClassification.iClassificationEntity = aClassificationEntity; 962 iClassification.iClassificationTable = aClassificationTable; 963 iClassification.iLangCode = ConvertLangCode(aLangCode); 964 return PVMFSuccess; 965 } 966 //////////////////////////////////////////////////////////////////////////// 967 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetKeyWord(const OSCL_wString& aKeyWordInfo, const OSCL_String& aLangCode) 968 { 969 if (iInterfaceState != EPVMFNodeIdle && 970 iInterfaceState != EPVMFNodeInitialized && 971 iInterfaceState != EPVMFNodePrepared) 972 return PVMFErrInvalidState; 973 974 PVMP4FFCN_KeyWord *KeyWord = NULL; 975 976 uint16 langCode = ConvertLangCode(aLangCode); 977 KeyWord = OSCL_NEW(PVMP4FFCN_KeyWord, (aKeyWordInfo, aKeyWordInfo.get_size(), langCode)); 978 979 iKeyWordVector.push_back(KeyWord); 980 981 982 return PVMFSuccess; 983 } 984 985 //////////////////////////////////////////////////////////////////////////// 986 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetLocationInfo(PvmfAssetInfo3GPPLocationStruct& aLocation_info) 987 { 988 if (iInterfaceState != EPVMFNodeIdle && 989 iInterfaceState != EPVMFNodeInitialized && 990 iInterfaceState != EPVMFNodePrepared) 991 return PVMFErrInvalidState; 992 993 iLocationInfo._location_name = NULL; 994 uint32 size = oscl_strlen(aLocation_info._location_name); 995 iLocationInfo._location_name = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10); 996 oscl_strncpy(iLocationInfo._location_name, aLocation_info._location_name, size); 997 iLocationInfo._location_name[size+1] = 0; 998 999 iLocationInfo._astronomical_body = NULL; 1000 size = oscl_strlen(aLocation_info._astronomical_body); 1001 iLocationInfo._astronomical_body = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10); 1002 oscl_strncpy(iLocationInfo._astronomical_body, aLocation_info._astronomical_body, size); 1003 iLocationInfo._astronomical_body[size+1] = 0; 1004 1005 iLocationInfo._additional_notes = NULL; 1006 size = oscl_strlen(aLocation_info._additional_notes); 1007 iLocationInfo._additional_notes = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10); 1008 oscl_strncpy(iLocationInfo._additional_notes, aLocation_info._additional_notes, size); 1009 iLocationInfo._additional_notes[size+1] = 0; 1010 1011 iLocationInfo._role = aLocation_info._role; 1012 iLocationInfo._longitude = aLocation_info._longitude; 1013 iLocationInfo._latitude = aLocation_info._latitude; 1014 iLocationInfo._altitude = aLocation_info._altitude; 1015 iLocationInfo._langCode = ConvertLangCode(aLocation_info.Lang_code); 1016 1017 return PVMFSuccess; 1018 } 1019 1020 1021 //////////////////////////////////////////////////////////////////////////// 1022 // PVMp4FFCNTrackConfigInterface routines 1023 //////////////////////////////////////////////////////////////////////////// 1024 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetTrackReference(const PVMFPortInterface& aPort, 1025 const PVMFPortInterface& aReferencePort) 1026 { 1027 if (iInterfaceState != EPVMFNodeInitialized) 1028 return PVMFErrInvalidState; 1029 1030 int32 portIndex = -1; 1031 int32 refPortIndex = -1; 1032 PVMp4FFComposerPort* port = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, &aPort); 1033 PVMp4FFComposerPort* refPort = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, &aReferencePort); 1034 1035 for (uint32 i = 0; i < iInPorts.size(); i++) 1036 { 1037 if (iInPorts[i] == port) 1038 portIndex = i; 1039 if (iInPorts[i] == refPort) 1040 refPortIndex = i; 1041 } 1042 1043 if (portIndex > 0 && refPortIndex > 0) 1044 { 1045 iInPorts[portIndex]->SetReferencePort(iInPorts[refPortIndex]); 1046 return PVMFSuccess; 1047 } 1048 else 1049 return PVMFFailure; 1050 } 1051 1052 //////////////////////////////////////////////////////////////////////////// 1053 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCodecSpecificInfo(const PVMFPortInterface& aPort, 1054 uint8* aInfo, int32 aSize) 1055 { 1056 PVMFStatus status = PVMFFailure; 1057 1058 if ((status == PVMFSuccess) && 1059 (iInterfaceState == EPVMFNodeStarted)) 1060 { 1061 PVMp4FFComposerPort* port = OSCL_STATIC_CAST(PVMp4FFComposerPort*, &aPort); 1062 iMpeg4File->setDecoderSpecificInfo(aInfo, aSize, port->GetTrackId()); 1063 } 1064 1065 return status; 1066 } 1067 1068 //////////////////////////////////////////////////////////////////////////// 1069 // PvmfComposerSizeAndDurationInterface routines 1070 //////////////////////////////////////////////////////////////////////////// 1071 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetMaxFileSize(bool aEnable, uint32 aMaxFileSizeBytes) 1072 { 1073 iMaxFileSizeEnabled = aEnable; 1074 if (iMaxFileSizeEnabled) 1075 { 1076 iMaxFileSize = aMaxFileSizeBytes; 1077 } 1078 else 1079 { 1080 iMaxFileSize = 0; 1081 } 1082 1083 return PVMFSuccess; 1084 } 1085 1086 //////////////////////////////////////////////////////////////////////////// 1087 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetMaxFileSizeConfig(bool& aEnable, uint32& aMaxFileSizeBytes) 1088 { 1089 aEnable = iMaxFileSizeEnabled; 1090 aMaxFileSizeBytes = iMaxFileSize; 1091 } 1092 1093 //////////////////////////////////////////////////////////////////////////// 1094 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetMaxDuration(bool aEnable, uint32 aMaxDurationMilliseconds) 1095 { 1096 iMaxDurationEnabled = aEnable; 1097 if (iMaxDurationEnabled) 1098 { 1099 iMaxTimeDuration = aMaxDurationMilliseconds; 1100 } 1101 else 1102 { 1103 iMaxTimeDuration = 0; 1104 } 1105 1106 return PVMFSuccess; 1107 } 1108 1109 //////////////////////////////////////////////////////////////////////////// 1110 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetMaxDurationConfig(bool& aEnable, uint32& aMaxDurationMilliseconds) 1111 { 1112 aEnable = iMaxDurationEnabled; 1113 aMaxDurationMilliseconds = iMaxTimeDuration; 1114 } 1115 1116 //////////////////////////////////////////////////////////////////////////// 1117 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetFileSizeProgressReport(bool aEnable, uint32 aReportFrequency) 1118 { 1119 iFileSizeReportEnabled = aEnable; 1120 if (iFileSizeReportEnabled) 1121 { 1122 iFileSizeReportFreq = aReportFrequency; 1123 } 1124 1125 return PVMFSuccess; 1126 } 1127 1128 //////////////////////////////////////////////////////////////////////////// 1129 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetFileSizeProgressReportConfig(bool& aEnable, uint32& aReportFrequency) 1130 { 1131 aEnable = iFileSizeReportEnabled; 1132 aReportFrequency = iFileSizeReportFreq; 1133 } 1134 1135 //////////////////////////////////////////////////////////////////////////// 1136 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetDurationProgressReport(bool aEnable, uint32 aReportFrequency) 1137 { 1138 iDurationReportEnabled = aEnable; 1139 if (iDurationReportEnabled) 1140 { 1141 iDurationReportFreq = aReportFrequency; 1142 } 1143 1144 return PVMFSuccess; 1145 } 1146 1147 //////////////////////////////////////////////////////////////////////////// 1148 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetDurationProgressReportConfig(bool& aEnable, uint32& aReportFrequency) 1149 { 1150 aEnable = iDurationReportEnabled; 1151 aReportFrequency = iDurationReportFreq; 1152 } 1153 1154 //////////////////////////////////////////////////////////////////////////// 1155 // PVMFPortActivityHandler routines 1156 //////////////////////////////////////////////////////////////////////////// 1157 void PVMp4FFComposerNode::HandlePortActivity(const PVMFPortActivity& aActivity) 1158 { 1159 OSCL_UNUSED_ARG(aActivity); 1160 // Scheduling to process port activities are handled in the port itself 1161 } 1162 1163 //////////////////////////////////////////////////////////////////////////// 1164 // OsclActiveObject routines 1165 //////////////////////////////////////////////////////////////////////////// 1166 void PVMp4FFComposerNode::Run() 1167 { 1168 LOG_STACK_TRACE((0, "PVMp4FFComposerNode::Run: iInterfaceState=%d", iInterfaceState)); 1169 1170 if (!iCmdQueue.empty()) 1171 { 1172 if (ProcessCommand(iCmdQueue.front())) 1173 { 1174 //note: need to check the state before re-scheduling 1175 //since the node could have been reset in the ProcessCommand 1176 //call. 1177 if (iInterfaceState != EPVMFNodeCreated) 1178 RunIfNotReady(); 1179 return; 1180 } 1181 } 1182 1183 LOG_STACK_TRACE((0, "PVMp4FFComposerNode::Run: Out. iInterfaceState=%d", iInterfaceState)); 1184 } 1185 1186 1187 //////////////////////////////////////////////////////////////////////////// 1188 // Command Processing routines 1189 //////////////////////////////////////////////////////////////////////////// 1190 PVMFCommandId PVMp4FFComposerNode::QueueCommandL(PVMp4FFCNCmd& aCmd) 1191 { 1192 int32 err = 0; 1193 PVMFCommandId id = 0; 1194 1195 OSCL_TRY(err, id = iCmdQueue.AddL(aCmd);); 1196 OSCL_FIRST_CATCH_ANY(err, 1197 OSCL_LEAVE(err); 1198 return 0; 1199 ); 1200 1201 // Wakeup the AO 1202 RunIfNotReady(); 1203 return id; 1204 } 1205 1206 //////////////////////////////////////////////////////////////////////////// 1207 bool PVMp4FFComposerNode::ProcessCommand(PVMp4FFCNCmd& aCmd) 1208 { 1209 //normally this node will not start processing one command 1210 //until the prior one is finished. However, a hi priority 1211 //command such as Cancel must be able to interrupt a command 1212 //in progress. 1213 if (!iCurrentCmd.empty() && !aCmd.hipri()) 1214 return false; 1215 1216 switch (aCmd.iCmd) 1217 { 1218 case PVMF_GENERIC_NODE_QUERYUUID: 1219 DoQueryUuid(aCmd); 1220 break; 1221 1222 case PVMF_GENERIC_NODE_QUERYINTERFACE: 1223 DoQueryInterface(aCmd); 1224 break; 1225 1226 case PVMF_GENERIC_NODE_REQUESTPORT: 1227 DoRequestPort(aCmd); 1228 break; 1229 1230 case PVMF_GENERIC_NODE_RELEASEPORT: 1231 DoReleasePort(aCmd); 1232 break; 1233 1234 case PVMF_GENERIC_NODE_INIT: 1235 DoInit(aCmd); 1236 break; 1237 1238 case PVMF_GENERIC_NODE_PREPARE: 1239 DoPrepare(aCmd); 1240 break; 1241 1242 case PVMF_GENERIC_NODE_START: 1243 DoStart(aCmd); 1244 break; 1245 1246 case PVMF_GENERIC_NODE_STOP: 1247 DoStop(aCmd); 1248 break; 1249 1250 case PVMF_GENERIC_NODE_FLUSH: 1251 DoFlush(aCmd); 1252 break; 1253 1254 case PVMF_GENERIC_NODE_PAUSE: 1255 DoPause(aCmd); 1256 break; 1257 1258 case PVMF_GENERIC_NODE_RESET: 1259 DoReset(aCmd); 1260 break; 1261 1262 case PVMF_GENERIC_NODE_CANCELALLCOMMANDS: 1263 DoCancelAllCommands(aCmd); 1264 break; 1265 1266 case PVMF_GENERIC_NODE_CANCELCOMMAND: 1267 DoCancelCommand(aCmd); 1268 break; 1269 1270 default://unknown command type 1271 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1272 break; 1273 } 1274 1275 return true; 1276 } 1277 1278 //////////////////////////////////////////////////////////////////////////// 1279 void PVMp4FFComposerNode::CommandComplete(PVMp4FFCNCmdQueue& aCmdQueue, PVMp4FFCNCmd& aCmd, 1280 PVMFStatus aStatus, OsclAny* aEventData) 1281 { 1282 LOG_STACK_TRACE((0, "PVMp4FFComposerNode:CommandComplete: Id %d Cmd %d Status %d Context %d Data %d" 1283 , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData)); 1284 1285 //create response 1286 PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData); 1287 PVMFSessionId session = aCmd.iSession; 1288 1289 //Erase the command from the queue. 1290 aCmdQueue.Erase(&aCmd); 1291 1292 //Report completion to the session observer. 1293 ReportCmdCompleteEvent(session, resp); 1294 } 1295 1296 ////////////////////////////////////////////////////////////////////////////////// 1297 void PVMp4FFComposerNode::DoQueryUuid(PVMp4FFCNCmd& aCmd) 1298 { 1299 OSCL_String* mimetype; 1300 Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec; 1301 bool exactmatch; 1302 aCmd.Parse(mimetype, uuidvec, exactmatch); 1303 1304 uuidvec->push_back(KPVMp4FFCNClipConfigUuid); 1305 uuidvec->push_back(KPVMp4FFCNTrackConfigUuid); 1306 uuidvec->push_back(PvmfComposerSizeAndDurationUuid); 1307 1308 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1309 } 1310 1311 ////////////////////////////////////////////////////////////////////////////////// 1312 void PVMp4FFComposerNode::DoQueryInterface(PVMp4FFCNCmd& aCmd) 1313 { 1314 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1315 (0, "PVMp4FFComposerNode::DoQueryInterface")); 1316 1317 PVUuid* uuid; 1318 PVInterface** ptr; 1319 aCmd.Parse(uuid, ptr); 1320 1321 if (queryInterface(*uuid, *ptr)) 1322 { 1323 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1324 } 1325 else 1326 { 1327 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1328 } 1329 } 1330 1331 1332 ////////////////////////////////////////////////////////////////////////////////// 1333 void PVMp4FFComposerNode::DoRequestPort(PVMp4FFCNCmd& aCmd) 1334 { 1335 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 1336 (0, "PVMp4FFComposerNode::DoRequestPort() In")); 1337 1338 int32 tag; 1339 OSCL_String* portconfig; 1340 aCmd.Parse(tag, portconfig); 1341 1342 //validate the tag... 1343 switch (tag) 1344 { 1345 case PVMF_MP4FFCN_PORT_TYPE_SINK: 1346 if (iInPorts.size() >= PVMF_MP4FFCN_MAX_INPUT_PORT) 1347 { 1348 LOG_ERR((0, "PVMp4FFComposerNode::DoRequestPort: Error - Max number of input port already allocated")); 1349 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1350 return; 1351 } 1352 break; 1353 1354 default: 1355 //bad port tag 1356 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1357 (0, "PVMp4FFComposerNode::DoRequestPort: Error - Invalid port tag")); 1358 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1359 return; 1360 } 1361 1362 //Allocate a new port 1363 OsclAny *ptr = NULL; 1364 int32 err; 1365 OSCL_TRY(err, 1366 ptr = iInPorts.Allocate(); 1367 if (!ptr) 1368 OSCL_LEAVE(OsclErrNoMemory); 1369 ); 1370 1371 OSCL_FIRST_CATCH_ANY(err, 1372 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, 1373 (0, "PVMp4FFComposerNode::DoRequestPort: Error - iInPorts Out of memory")); 1374 CommandComplete(iCmdQueue, aCmd, PVMFErrNoMemory); 1375 return; 1376 ); 1377 1378 OSCL_StackString<20> portname; 1379 portname = "PVMP4ComposerIn"; 1380 1381 PVMp4FFComposerPort* port = OSCL_PLACEMENT_NEW(ptr, PVMp4FFComposerPort(tag, this, Priority(), portname.get_cstr())); 1382 1383 // if format was provided in mimestring, set it now. 1384 if (portconfig) 1385 { 1386 PVMFFormatType format = portconfig->get_str(); 1387 if (format == PVMF_MIME_3GPP_TIMEDTEXT || 1388 format == PVMF_MIME_H264_VIDEO_MP4 || 1389 format == PVMF_MIME_M4V || 1390 format == PVMF_MIME_H2631998 || 1391 format == PVMF_MIME_H2632000 || 1392 format == PVMF_MIME_AMR_IETF || 1393 format == PVMF_MIME_AMRWB_IETF || 1394 format == PVMF_MIME_ADIF || 1395 format == PVMF_MIME_ADTS || 1396 format == PVMF_MIME_MPEG4_AUDIO) 1397 { 1398 port->SetFormat(format); 1399 } 1400 else 1401 { 1402 CommandComplete(iCmdQueue, aCmd, PVMFErrNotSupported); 1403 return; 1404 } 1405 } 1406 1407 //Add the port to the port vector. 1408 OSCL_TRY(err, iInPorts.AddL(port);); 1409 OSCL_FIRST_CATCH_ANY(err, 1410 iInPorts.DestructAndDealloc(port); 1411 CommandComplete(iCmdQueue, aCmd, PVMFErrNoMemory); 1412 return; 1413 ); 1414 1415 // Return the port pointer to the caller. 1416 CommandComplete(iCmdQueue, aCmd, PVMFSuccess, (OsclAny*)port); 1417 } 1418 1419 ////////////////////////////////////////////////////////////////////////////////// 1420 void PVMp4FFComposerNode::DoReleasePort(PVMp4FFCNCmd& aCmd) 1421 { 1422 //Find the port in the port vector 1423 PVMFPortInterface* p = NULL; 1424 1425 for (uint32 i = 0; i < iInPorts.size(); i++) 1426 { 1427 aCmd.Parse(p); 1428 1429 PVMp4FFComposerPort* port = (PVMp4FFComposerPort*)p; 1430 1431 PVMp4FFComposerPort** portPtr = iInPorts.FindByValue(port); 1432 if (portPtr) 1433 { 1434 //delete the port. 1435 iInPorts.Erase(portPtr); 1436 1437 #ifdef _TEST_AE_ERROR_HANDLING 1438 if (FAIL_NODE_CMD_RELEASE_PORT == iErrorNodeCmd) 1439 { 1440 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1441 1442 } 1443 else 1444 { 1445 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1446 } 1447 #else 1448 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1449 #endif 1450 1451 } 1452 else 1453 { 1454 //port not found. 1455 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1456 } 1457 1458 } 1459 } 1460 1461 ////////////////////////////////////////////////////////////////////////////////// 1462 void PVMp4FFComposerNode::DoInit(PVMp4FFCNCmd& aCmd) 1463 { 1464 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::DoInitNode() In")); 1465 1466 switch (iInterfaceState) 1467 { 1468 case EPVMFNodeIdle: 1469 // Creation of file format library is done in DoStart. Nothing to do here. 1470 SetState(EPVMFNodeInitialized); 1471 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1472 break; 1473 case EPVMFNodeInitialized: 1474 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1475 break; 1476 1477 default: 1478 CommandComplete(iCmdQueue, aCmd, PVMFErrInvalidState); 1479 break; 1480 } 1481 } 1482 1483 ////////////////////////////////////////////////////////////////////////////////// 1484 void PVMp4FFComposerNode::DoPrepare(PVMp4FFCNCmd& aCmd) 1485 { 1486 switch (iInterfaceState) 1487 { 1488 case EPVMFNodeInitialized: 1489 // Creation of file format library is done in DoStart. Nothing to do here. 1490 SetState(EPVMFNodePrepared); 1491 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1492 break; 1493 case EPVMFNodePrepared: 1494 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 1495 break; 1496 1497 default: 1498 CommandComplete(iCmdQueue, aCmd, PVMFErrInvalidState); 1499 break; 1500 } 1501 } 1502 1503 ////////////////////////////////////////////////////////////////////////////////// 1504 void PVMp4FFComposerNode::DoStart(PVMp4FFCNCmd& aCmd) 1505 { 1506 PVMFStatus status = PVMFSuccess; 1507 uint32 i = 0; 1508 #ifdef _TEST_AE_ERROR_HANDLING 1509 if (FAIL_NODE_CMD_START == iErrorNodeCmd) 1510 { 1511 iInterfaceState = EPVMFNodeError; 1512 } 1513 #endif 1514 switch (iInterfaceState) 1515 { 1516 case EPVMFNodePrepared: 1517 { 1518 iPostfix = _STRLIT("00"); 1519 iOutputPath = _STRLIT(""); 1520 int32 pos = 0; 1521 for (pos = iFileName.get_size() - 1; pos >= 0; pos--) 1522 { 1523 if (iFileName[pos] == SLASH) 1524 break; 1525 } 1526 1527 if (pos == -1) 1528 { 1529 iOutputPath = _STRLIT("."); 1530 } 1531 else 1532 { 1533 for (i = 0; i <= (uint32) pos; i++) 1534 iOutputPath += iFileName[i]; 1535 } 1536 1537 1538 1539 iFileType = 0; 1540 for (i = 0; i < iInPorts.size(); i++) 1541 { 1542 if (iInPorts[i]->GetFormat() == PVMF_MIME_H264_VIDEO_MP4 || 1543 iInPorts[i]->GetFormat() == PVMF_MIME_M4V || 1544 iInPorts[i]->GetFormat() == PVMF_MIME_H2631998 || 1545 iInPorts[i]->GetFormat() == PVMF_MIME_H2632000) 1546 { 1547 iFileType |= FILE_TYPE_VIDEO; 1548 } 1549 else if (iInPorts[i]->GetFormat() == PVMF_MIME_AMR_IETF || 1550 iInPorts[i]->GetFormat() == PVMF_MIME_AMRWB_IETF || 1551 iInPorts[i]->GetFormat() == PVMF_MIME_MPEG4_AUDIO) 1552 { 1553 iFileType |= FILE_TYPE_AUDIO; 1554 } 1555 else if (iInPorts[i]->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT) 1556 { 1557 iFileType |= FILE_TYPE_TIMED_TEXT; 1558 } 1559 else 1560 { 1561 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 1562 (0, "PVMp4FFComposerNode::DoStart: Error - Unsupported format")); 1563 return; 1564 } 1565 } 1566 1567 if (iMpeg4File) 1568 { 1569 LOG_ERR((0, "PVMp4FFComposerNode::DoStart: Error - File format library already exists")); 1570 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1571 return; 1572 } 1573 1574 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1575 (0, "PVMp4FFComposerNode::DoStart: Calling PVA_FF_IMpeg4File::createMP4File(%d,0x%x,%d)", 1576 iFileType, &iFs, iAuthoringMode)); 1577 #ifdef _TEST_AE_ERROR_HANDLING //test case to fail mp4 file parser 1578 if (iErrorCreateComposer) 1579 { 1580 //to fail createMP4File() 1581 OSCL_wHeapString<OsclMemAllocator> ErrFileName; 1582 1583 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix, 1584 (void*) & iFs, iAuthoringMode, ErrFileName, iCacheSize); 1585 1586 } 1587 else 1588 { 1589 if (iFileObject != NULL) 1590 { 1591 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iAuthoringMode, iFileObject, iCacheSize); 1592 1593 } 1594 else 1595 { 1596 1597 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix, 1598 (void*) & iFs, iAuthoringMode, iFileName, iCacheSize); 1599 1600 } 1601 } 1602 #else 1603 if (iFileObject != NULL) 1604 { 1605 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iAuthoringMode, iFileObject, iCacheSize); 1606 1607 } 1608 else 1609 { 1610 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix, 1611 (void*) & iFs, iAuthoringMode, iFileName, iCacheSize); 1612 } 1613 #endif 1614 if (!iMpeg4File) 1615 { 1616 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 1617 (0, "PVMp4FFComposerNode::DoStart: Error - PVA_FF_IMpeg4File::createMP4File failed")); 1618 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 1619 return; 1620 } 1621 1622 iMpeg4File->setPresentationTimescale(iPresentationTimescale); 1623 iMpeg4File->setVersion(iVersion.iDataString, iVersion.iLangCode); 1624 iMpeg4File->setTitle(iTitle.iDataString, iTitle.iLangCode); 1625 iMpeg4File->setAuthor(iAuthor.iDataString, iAuthor.iLangCode); 1626 iMpeg4File->setCopyright(iCopyright.iDataString, iCopyright.iLangCode); 1627 iMpeg4File->setDescription(iDescription.iDataString, iDescription.iLangCode); 1628 iMpeg4File->setRating(iRating.iDataString, iRating.iLangCode); 1629 if(iCreationDate.get_size() > 0) 1630 { 1631 iMpeg4File->setCreationDate(iCreationDate); 1632 } 1633 iMpeg4File->setMovieFragmentDuration(iMovieFragmentDuration); 1634 iMpeg4File->setAlbumInfo(iAlbumTitle.iDataString, iAlbumTitle.iLangCode); 1635 iMpeg4File->setRecordingYear(iRecordingYear); 1636 1637 iMpeg4File->setPerformer(iPerformer.iDataString, iPerformer.iLangCode); 1638 iMpeg4File->setGenre(iGenre.iDataString, iGenre.iLangCode); 1639 iMpeg4File->setClassification(iClassification.iDataString, iClassification.iClassificationEntity, iClassification.iClassificationTable, iClassification.iLangCode); 1640 1641 for (i = 0; i < iKeyWordVector.size() ; i++) 1642 { 1643 iMpeg4File->setKeyWord(iKeyWordVector[i]->iKeyWordSize, iKeyWordVector[i]->iData_String, iKeyWordVector[i]->iLang_Code); 1644 } 1645 1646 iMpeg4File->setLocationInfo(&iLocationInfo); 1647 for (i = 0; i < iInPorts.size(); i++) 1648 { 1649 status = AddTrack(iInPorts[i]); 1650 if (status != PVMFSuccess) 1651 { 1652 CommandComplete(iCmdQueue, aCmd, status); 1653 return; 1654 } 1655 } 1656 1657 // Check for and set reference tracks after track IDs are assigned 1658 PVMp4FFComposerPort* refPort = NULL; 1659 for (i = 0; i < iInPorts.size(); i++) 1660 { 1661 refPort = OSCL_STATIC_CAST(PVMp4FFComposerPort*, iInPorts[i]->GetReferencePort()); 1662 if (refPort) 1663 { 1664 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1665 (0, "PVMp4FFComposerNode::DoStart: Calling addTrackReference(%d, %d)", 1666 iInPorts[i]->GetTrackId(), refPort->GetTrackId())); 1667 iMpeg4File->addTrackReference(iInPorts[i]->GetTrackId(), refPort->GetTrackId()); 1668 } 1669 } 1670 1671 iMpeg4File->prepareToEncode(); 1672 1673 iInitTSOffset = true; 1674 iTSOffset = 0; 1675 SetState(EPVMFNodeStarted); 1676 break; 1677 } 1678 1679 case EPVMFNodePaused: 1680 SetState(EPVMFNodeStarted); 1681 for (i = 0; i < iInPorts.size(); i++) 1682 ((PVMp4FFComposerPort*)iInPorts[i])->ProcessIncomingMsgReady(); 1683 break; 1684 case EPVMFNodeStarted: 1685 status = PVMFSuccess; 1686 break; 1687 default: 1688 status = PVMFErrInvalidState; 1689 break; 1690 } 1691 1692 CommandComplete(iCmdQueue, aCmd, status); 1693 } 1694 1695 ////////////////////////////////////////////////////////////////////////////////// 1696 PVMFStatus PVMp4FFComposerNode::AddTrack(PVMp4FFComposerPort *aPort) 1697 { 1698 int32 codecType = 0; 1699 int32 mediaType = 0; 1700 int32 trackId = 0; 1701 PVMP4FFCNFormatSpecificConfig* config = aPort->GetFormatSpecificConfig(); 1702 if (!config) 1703 { 1704 LOG_ERR((0, "PVMp4FFComposerNode::AddTrack: Error - GetFormatSpecificConfig failed")); 1705 return PVMFFailure; 1706 } 1707 1708 if (aPort->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT) 1709 { 1710 codecType = CODEC_TYPE_TIMED_TEXT; 1711 mediaType = MEDIA_TYPE_TEXT; 1712 } 1713 else if (aPort->GetFormat() == PVMF_MIME_H264_VIDEO_MP4) 1714 { 1715 codecType = CODEC_TYPE_AVC_VIDEO; 1716 mediaType = MEDIA_TYPE_VISUAL; 1717 } 1718 else if (aPort->GetFormat() == PVMF_MIME_M4V) 1719 { 1720 codecType = CODEC_TYPE_MPEG4_VIDEO; 1721 mediaType = MEDIA_TYPE_VISUAL; 1722 } 1723 else if (aPort->GetFormat() == PVMF_MIME_H2631998 || 1724 aPort->GetFormat() == PVMF_MIME_H2632000) 1725 { 1726 codecType = CODEC_TYPE_BASELINE_H263_VIDEO; 1727 mediaType = MEDIA_TYPE_VISUAL; 1728 } 1729 else if (aPort->GetFormat() == PVMF_MIME_AMR_IETF) 1730 { 1731 codecType = CODEC_TYPE_AMR_AUDIO; 1732 mediaType = MEDIA_TYPE_AUDIO; 1733 } 1734 else if (aPort->GetFormat() == PVMF_MIME_AMRWB_IETF) 1735 { 1736 codecType = CODEC_TYPE_AMR_WB_AUDIO; 1737 mediaType = MEDIA_TYPE_AUDIO; 1738 } 1739 else if (aPort->GetFormat() == PVMF_MIME_MPEG4_AUDIO) 1740 { 1741 codecType = CODEC_TYPE_AAC_AUDIO; 1742 mediaType = MEDIA_TYPE_AUDIO; 1743 } 1744 else 1745 { 1746 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 1747 (0, "PVMp4FFComposerNode::AddTrack: Error - Unsupported format")); 1748 return PVMFFailure; 1749 } 1750 1751 aPort->SetCodecType(codecType); 1752 1753 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1754 (0, "PVMp4FFComposerNode::AddTrack: Calling PVA_FF_IMpeg4File::addTrack(0x%x,0x%x)", 1755 mediaType, codecType)); 1756 #ifdef _TEST_AE_ERROR_HANDLING 1757 if (aPort->GetFormat() == iErrorAddTrack) 1758 { 1759 return PVMFFailure; 1760 } 1761 #endif 1762 trackId = iMpeg4File->addTrack(mediaType, codecType); 1763 #ifdef _TEST_AE_ERROR_HANDLING 1764 if (iErrorHandlingAddTrack) 1765 { 1766 trackId = 0; 1767 } 1768 #endif 1769 if (trackId == 0) 1770 { 1771 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 1772 (0, "PVMp4FFComposerNode::AddTrack: Error - PVA_FF_IMpeg4File::addTrack failed")); 1773 return PVMFFailure; 1774 } 1775 aPort->SetTrackId(trackId); 1776 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1777 (0, "PVMp4FFComposerNode::AddTrack: PVA_FF_IMpeg4File::addTrack success. trackID=%d", trackId)); 1778 #if PROFILING_ON 1779 1780 for (uint32 k = 0; k < 3; k++) 1781 { 1782 if (iStats[k].iTrackId == 0) 1783 { 1784 iStats[k].iTrackId = trackId; 1785 break; 1786 } 1787 } 1788 #endif 1789 1790 switch (mediaType) 1791 { 1792 case MEDIA_TYPE_AUDIO: 1793 { 1794 iMpeg4File->setTargetBitrate(trackId, config->iBitrate); 1795 iMpeg4File->setTimeScale(trackId, config->iTimescale); 1796 PVMP4FFComposerAudioEncodeParams audioParams; 1797 audioParams.numberOfChannels = config->iNumberOfChannels; 1798 audioParams.samplingRate = config->iSamplingRate; 1799 audioParams.bitsPerSample = config->iBitsPerSample; 1800 iMpeg4File->setAudioEncodeParams(trackId, audioParams); 1801 break; 1802 } 1803 1804 case MEDIA_TYPE_VISUAL: 1805 switch (codecType) 1806 { 1807 case CODEC_TYPE_BASELINE_H263_VIDEO: 1808 iMpeg4File->setH263ProfileLevel(trackId, config->iH263Profile, config->iH263Level); 1809 // Don't break here. Continue to set other video properties 1810 case CODEC_TYPE_AVC_VIDEO: 1811 case CODEC_TYPE_MPEG4_VIDEO: 1812 iMpeg4File->setTargetBitrate(trackId, config->iBitrate, config->iBitrate, 0); 1813 iMpeg4File->setTimeScale(trackId, config->iTimescale); 1814 iMpeg4File->setVideoParams(trackId, (float)config->iFrameRate, 1815 (uint16)config->iIFrameInterval, config->iWidth, config->iHeight); 1816 break; 1817 } 1818 break; 1819 case MEDIA_TYPE_TEXT: 1820 iMpeg4File->setTargetBitrate(trackId, config->iBitrate); 1821 iMpeg4File->setTimeScale(trackId, config->iTimescale); 1822 break; 1823 1824 } 1825 1826 return PVMFSuccess; 1827 } 1828 1829 ////////////////////////////////////////////////////////////////////////////////// 1830 void PVMp4FFComposerNode::DoStop(PVMp4FFCNCmd& aCmd) 1831 { 1832 PVMFStatus status = PVMFSuccess; 1833 #if PROFILING_ON 1834 if (!oDiagnosticsLogged) 1835 { 1836 LogDiagnostics(); 1837 } 1838 #endif 1839 #ifdef _TEST_AE_ERROR_HANDLING 1840 if (FAIL_NODE_CMD_STOP == iErrorNodeCmd) 1841 { 1842 iInterfaceState = EPVMFNodeError; 1843 } 1844 #endif 1845 switch (iInterfaceState) 1846 { 1847 case EPVMFNodeStarted: 1848 case EPVMFNodePaused: 1849 { 1850 #ifdef ANDROID 1851 iFragmentWriter->flush(); 1852 #endif 1853 if (!iNodeEndOfDataReached) 1854 { 1855 WriteDecoderSpecificInfo(); 1856 if (iSampleInTrack) 1857 { 1858 status = RenderToFile(); 1859 } 1860 1861 iSampleInTrack = false; 1862 } 1863 1864 iNodeEndOfDataReached = false; 1865 for (uint32 ii = 0; ii < iInPorts.size(); ii++) 1866 { 1867 iInPorts[ii]->iEndOfDataReached = false; 1868 } 1869 } 1870 SetState(EPVMFNodePrepared); 1871 break; 1872 case EPVMFNodePrepared: 1873 status = PVMFSuccess; 1874 break; 1875 default: 1876 status = PVMFErrInvalidState; 1877 break; 1878 } 1879 1880 CommandComplete(iCmdQueue, aCmd, status); 1881 } 1882 1883 ////////////////////////////////////////////////////////////////////////////////// 1884 void PVMp4FFComposerNode::WriteDecoderSpecificInfo() 1885 { 1886 uint32 i; 1887 uint32 offset = 0; 1888 iConfigSize = 0; 1889 int32 trackId; 1890 1891 if (iformat_h264 == PVMF_MIME_H264_VIDEO_MP4) 1892 { 1893 trackId = iTrackId_H264; 1894 1895 for (i = 0; i < memvector_sps.size(); i++) 1896 { 1897 iConfigSize += 2;//2 bytes for SPS_len 1898 iConfigSize += memvector_sps[i]->len; 1899 } 1900 1901 for (i = 0; i < memvector_pps.size(); i++) 1902 { 1903 iConfigSize += 2;//2 bytes for PPS_len 1904 iConfigSize += memvector_pps[i]->len; 1905 } 1906 iConfigSize = iConfigSize + 2;//extra two bytes for nunSPS and NumPPS 1907 pConfig = (uint8*)(OSCL_MALLOC(sizeof(uint8) * iConfigSize)); 1908 1909 1910 //currently we are ignoring NAL Length information 1911 oscl_memcpy((void*)(pConfig + offset), (const void*)&iNum_SPS_Set, 1);//Writing Number of SPS sets 1912 offset += 1; 1913 1914 for (i = 0; i < memvector_sps.size(); i++) 1915 { 1916 oscl_memcpy((void*)(pConfig + offset), (const void*)&memvector_sps[i]->len, 2);//Writing length of SPS 1917 offset += 2; 1918 oscl_memcpy((void*)(pConfig + offset), memvector_sps[i]->ptr, memvector_sps[i]->len); 1919 offset = offset + memvector_sps[i]->len; 1920 } 1921 1922 oscl_memcpy((void*)(pConfig + offset), (const void*)&iNum_PPS_Set, 1);//Writing Number of PPS sets 1923 offset += 1; 1924 1925 for (i = 0; i < memvector_pps.size(); i++) 1926 { 1927 oscl_memcpy((void*)(pConfig + offset), (const void*)&memvector_pps[i]->len, 2);//Writing length of PPS 1928 offset += 2;//2 bytes for PPS Length 1929 oscl_memcpy((void*)(pConfig + offset), memvector_pps[i]->ptr, memvector_pps[i]->len); 1930 offset = offset + memvector_pps[i]->len; 1931 } 1932 iMpeg4File->setDecoderSpecificInfo(pConfig, iConfigSize, trackId); 1933 } 1934 1935 if (iformat_text == PVMF_MIME_3GPP_TIMEDTEXT) 1936 { 1937 for (uint32 ii = 0; ii < textdecodervector.size(); ii++) 1938 { 1939 trackId = iTrackId_Text; 1940 iMpeg4File->setTextDecoderSpecificInfo(textdecodervector[ii], trackId); 1941 } 1942 } 1943 1944 } 1945 ////////////////////////////////////////////////////////////////////////////////// 1946 PVMFStatus PVMp4FFComposerNode::RenderToFile() 1947 { 1948 PVMFStatus status = PVMFSuccess; 1949 1950 // Clear queued messages in ports 1951 uint32 i; 1952 for (i = 0; i < iInPorts.size(); i++) 1953 iInPorts[i]->ClearMsgQueues(); 1954 #ifdef _TEST_AE_ERROR_HANDLING //to fail renderToFile 1955 if (iErrorRenderToFile) 1956 { 1957 if (iMpeg4File) 1958 { 1959 PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File); 1960 iMpeg4File = NULL; 1961 } 1962 } 1963 #endif 1964 1965 #ifdef ANDROID 1966 iFragmentWriter->flush(); 1967 #endif 1968 1969 if (!iMpeg4File || !iMpeg4File->renderToFile(iFileName)) 1970 { 1971 LOG_ERR((0, "PVMp4FFComposerNode::RenderToFile: Error - renderToFile failed")); 1972 ReportErrorEvent(PVMF_MP4FFCN_ERROR_FINALIZE_OUTPUT_FILE_FAILED); 1973 status = PVMFFailure; 1974 } 1975 else 1976 { 1977 #if PROFILING_ON 1978 // Statistics 1979 1980 for (i = 0; i < 3; i++) 1981 { 1982 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, 1983 (0, "PVMp4FFComposerNode Stats: TrackId=%d, NumFrame=%d, Duration=%d", 1984 iStats[i].iTrackId, iStats[i].iNumFrames, iStats[i].iDuration)); 1985 oscl_memset(&(iStats[i]), 0, sizeof(PVMp4FFCNStats)); 1986 } 1987 #endif 1988 1989 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::RenderToFile() Done")); 1990 // Delete file format library 1991 if (iMpeg4File) 1992 { 1993 PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File); 1994 iMpeg4File = NULL; 1995 } 1996 1997 // Change state 1998 SetState(EPVMFNodePrepared); 1999 status = PVMFSuccess; 2000 } 2001 2002 if (PVMFSuccess == status) 2003 { 2004 iFileRendered = true; 2005 } 2006 return status; 2007 } 2008 2009 ////////////////////////////////////////////////////////////////////////////////// 2010 void PVMp4FFComposerNode::DoFlush(PVMp4FFCNCmd& aCmd) 2011 { 2012 LOG_STACK_TRACE((0, "PVMp4FFComposerNode::DoFlush() iInterfaceState:%d", iInterfaceState)); 2013 #ifdef _TEST_AE_ERROR_HANDLING 2014 if (FAIL_NODE_CMD_FLUSH == iErrorNodeCmd) 2015 { 2016 iInterfaceState = EPVMFNodeError; 2017 } 2018 #endif 2019 switch (iInterfaceState) 2020 { 2021 case EPVMFNodeStarted: 2022 case EPVMFNodePaused: 2023 int32 err; 2024 uint32 i; 2025 bool msgPending; 2026 msgPending = false; 2027 2028 for (i = 0; i < iInPorts.size(); i++) 2029 { 2030 if (iInPorts[i]->IncomingMsgQueueSize() > 0) 2031 msgPending = true; 2032 iInPorts[i]->SuspendInput(); 2033 if (iInterfaceState != EPVMFNodeStarted) 2034 { 2035 // Port is in idle if node state is not started. Call ProcessIncomingMsgReady 2036 // to wake up port AO 2037 ((PVMp4FFComposerPort*)iInPorts[i])->ProcessIncomingMsgReady(); 2038 } 2039 } 2040 2041 // Move the command from the input command queue to the current command, where 2042 // it will remain until the flush completes. 2043 err = StoreCurrentCommand(iCurrentCmd, aCmd, iCmdQueue); 2044 if (0 != err) 2045 return; 2046 2047 iCmdQueue.Erase(&aCmd); 2048 2049 if (!msgPending) 2050 { 2051 FlushComplete(); 2052 return; 2053 } 2054 break; 2055 2056 default: 2057 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 2058 break; 2059 } 2060 } 2061 2062 //////////////////////////////////////////////////////////////////////////// 2063 bool PVMp4FFComposerNode::IsFlushPending() 2064 { 2065 return (iCurrentCmd.size() > 0 2066 && iCurrentCmd.front().iCmd == PVMF_GENERIC_NODE_FLUSH); 2067 } 2068 2069 //////////////////////////////////////////////////////////////////////////// 2070 void PVMp4FFComposerNode::FlushComplete() 2071 { 2072 LOG_STACK_TRACE((0, "PVMp4FFComposerNode::FlushComplete")); 2073 uint32 i = 0; 2074 PVMFStatus status = PVMFSuccess; 2075 // Flush is complete only when all queues of all ports are clear. 2076 // Other wise, just return from this method and wait for FlushComplete 2077 // from the remaining ports. 2078 for (i = 0; i < iInPorts.size(); i++) 2079 { 2080 if (iInPorts[i]->IncomingMsgQueueSize() > 0 || 2081 iInPorts[i]->OutgoingMsgQueueSize() > 0) 2082 { 2083 return; 2084 } 2085 } 2086 #ifdef ANDROID 2087 iFragmentWriter->flush(); 2088 #endif 2089 if (!iNodeEndOfDataReached) 2090 { 2091 WriteDecoderSpecificInfo(); 2092 // Finalize output file 2093 if (iSampleInTrack) 2094 { 2095 status = RenderToFile(); 2096 } 2097 2098 iSampleInTrack = false; 2099 2100 if (status != PVMFSuccess) 2101 LOG_ERR((0, "PVMp4FFComposerNode::FlushComplete: Error - RenderToFile failed")); 2102 } 2103 2104 // Resume port input so the ports can be re-started. 2105 for (i = 0; i < iInPorts.size(); i++) 2106 iInPorts[i]->ResumeInput(); 2107 2108 SetState(EPVMFNodePrepared); 2109 2110 if (!iCurrentCmd.empty()) 2111 { 2112 CommandComplete(iCurrentCmd, iCurrentCmd[0], status); 2113 } 2114 2115 if (!iCmdQueue.empty()) 2116 { 2117 // If command queue is not empty, schedule to process the next command 2118 RunIfNotReady(); 2119 } 2120 2121 2122 } 2123 2124 ////////////////////////////////////////////////////////////////////////////////// 2125 void PVMp4FFComposerNode::DoPause(PVMp4FFCNCmd& aCmd) 2126 { 2127 PVMFStatus status = PVMFSuccess; 2128 2129 #ifdef _TEST_AE_ERROR_HANDLING 2130 if (FAIL_NODE_CMD_PAUSE == iErrorNodeCmd) 2131 { 2132 iInterfaceState = EPVMFNodeError; 2133 } 2134 #endif 2135 switch (iInterfaceState) 2136 { 2137 case EPVMFNodeStarted: 2138 SetState(EPVMFNodePaused); 2139 break; 2140 case EPVMFNodePaused: 2141 break; 2142 default: 2143 status = PVMFErrInvalidState; 2144 break; 2145 } 2146 2147 CommandComplete(iCmdQueue, aCmd, status); 2148 } 2149 2150 ////////////////////////////////////////////////////////////////////////////////// 2151 void PVMp4FFComposerNode::DoReset(PVMp4FFCNCmd& aCmd) 2152 { 2153 PVMFStatus status = PVMFSuccess; 2154 #if PROFILING_ON 2155 if (!oDiagnosticsLogged) 2156 { 2157 LogDiagnostics(); 2158 } 2159 #endif 2160 2161 if (IsAdded()) 2162 { 2163 if (iSampleInTrack) 2164 { 2165 WriteDecoderSpecificInfo(); 2166 status = RenderToFile(); 2167 iSampleInTrack = false; 2168 } 2169 2170 //delete all ports and notify observer. 2171 while (!iInPorts.empty()) 2172 iInPorts.Erase(&iInPorts.front()); 2173 2174 //restore original port vector reserve. 2175 iInPorts.Reconstruct(); 2176 iNodeEndOfDataReached = false; 2177 2178 //logoff & go back to Created state. 2179 SetState(EPVMFNodeIdle); 2180 status = PVMFSuccess; 2181 } 2182 else 2183 { 2184 OSCL_LEAVE(OsclErrInvalidState); 2185 } 2186 2187 CommandComplete(iCmdQueue, aCmd, status); 2188 } 2189 2190 ////////////////////////////////////////////////////////////////////////////////// 2191 void PVMp4FFComposerNode::DoCancelAllCommands(PVMp4FFCNCmd& aCmd) 2192 { 2193 //first cancel the current command if any 2194 while (!iCurrentCmd.empty()) 2195 CommandComplete(iCurrentCmd, iCurrentCmd[0], PVMFErrCancelled); 2196 2197 //next cancel all queued commands 2198 //start at element 1 since this cancel command is element 0. 2199 while (iCmdQueue.size() > 1) 2200 CommandComplete(iCmdQueue, iCmdQueue[1], PVMFErrCancelled); 2201 2202 //finally, report cancel complete. 2203 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 2204 } 2205 2206 ////////////////////////////////////////////////////////////////////////////////// 2207 void PVMp4FFComposerNode::DoCancelCommand(PVMp4FFCNCmd& aCmd) 2208 { 2209 //extract the command ID from the parameters. 2210 PVMFCommandId id; 2211 aCmd.Parse(id); 2212 2213 //first check "current" command if any 2214 PVMp4FFCNCmd* cmd = iCurrentCmd.FindById(id); 2215 if (cmd) 2216 { 2217 //cancel the queued command 2218 CommandComplete(iCurrentCmd, *cmd, PVMFErrCancelled); 2219 //report cancel success 2220 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 2221 return; 2222 } 2223 2224 //next check input queue. 2225 //start at element 1 since this cancel command is element 0. 2226 cmd = iCmdQueue.FindById(id, 1); 2227 if (cmd) 2228 { 2229 //cancel the queued command 2230 CommandComplete(iCmdQueue, *cmd, PVMFErrCancelled); 2231 //report cancel success 2232 CommandComplete(iCmdQueue, aCmd, PVMFSuccess); 2233 return; 2234 } 2235 2236 //if we get here the command isn't queued so the cancel fails. 2237 CommandComplete(iCmdQueue, aCmd, PVMFFailure); 2238 } 2239 2240 ////////////////////////////////////////////////////////////////////////////////// 2241 // Port activity processing routines 2242 ////////////////////////////////////////////////////////////////////////////////// 2243 bool PVMp4FFComposerNode::IsProcessIncomingMsgReady() 2244 { 2245 if (iInterfaceState == EPVMFNodeStarted || IsFlushPending()) 2246 return true; 2247 else 2248 return false; 2249 } 2250 2251 //////////////////////////////////////////////////////////////////////////// 2252 PVMFStatus PVMp4FFComposerNode::ProcessIncomingMsg(PVMFPortInterface* aPort) 2253 { 2254 LOG_STACK_TRACE((0, "PVMp4FFComposerNode::ProcessIncomingMsg: aPort=0x%x", aPort)); 2255 PVMFStatus status = PVMFSuccess; 2256 2257 switch (aPort->GetPortTag()) 2258 { 2259 case PVMF_MP4FFCN_PORT_TYPE_SINK: 2260 { 2261 PVMp4FFComposerPort* port = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, aPort); 2262 if (!IsProcessIncomingMsgReady()) 2263 { 2264 LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - Not ready.")); 2265 return PVMFErrBusy; 2266 } 2267 2268 PVMFSharedMediaMsgPtr msg; 2269 status = port->DequeueIncomingMsg(msg); 2270 if (status != PVMFSuccess) 2271 { 2272 LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - DequeueIncomingMsg failed")); 2273 return status; 2274 } 2275 if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID) 2276 { 2277 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::ProcessIncomingMsg: EOS Recvd - TrackID=%d, StreamID=%d, TS=%d, Mime=%s", 2278 port->GetTrackId(), msg->getStreamID(), msg->getTimestamp(), port->GetMimeType().get_cstr())); 2279 2280 port->iEndOfDataReached = true; 2281 //check if EOS has been received on all connected ports. 2282 uint32 ii = 0; 2283 iNodeEndOfDataReached = true; 2284 for (ii = 0; ii < iInPorts.size(); ii++) 2285 { 2286 if (!iInPorts[ii]->iEndOfDataReached) 2287 { 2288 iNodeEndOfDataReached = false; 2289 } 2290 } 2291 2292 if (iNodeEndOfDataReached) 2293 { 2294 //Close the file since EOS is received on every connected port 2295 WriteDecoderSpecificInfo(); 2296 if (iSampleInTrack) 2297 { 2298 status = RenderToFile(); 2299 iSampleInTrack = false; 2300 } 2301 2302 //report EOS info to engine 2303 ReportInfoEvent(PVMF_COMPOSER_EOS_REACHED); 2304 } 2305 2306 //since we do not have data to process, we can safely break here. 2307 break; 2308 } 2309 2310 PVMFSharedMediaDataPtr mediaDataPtr; 2311 convertToPVMFMediaData(mediaDataPtr, msg); 2312 2313 int32 trackId = port->GetTrackId(); 2314 if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_M4V)) 2315 { 2316 // Set VOL Header 2317 OsclRefCounterMemFrag volHeader; 2318 if (mediaDataPtr->getFormatSpecificInfo(volHeader) == false || 2319 volHeader.getMemFragSize() == 0) 2320 { 2321 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2322 (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - VOL Header not available")); 2323 return PVMFFailure; 2324 } 2325 2326 iMpeg4File->setDecoderSpecificInfo((uint8*)volHeader.getMemFragPtr(), 2327 (int32)volHeader.getMemFragSize(), trackId); 2328 } 2329 if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_H264_VIDEO_MP4)) 2330 { 2331 iTrackId_H264 = port->GetTrackId(); 2332 iformat_h264 = port->GetFormat(); 2333 } 2334 if (port->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT) 2335 { 2336 iTrackId_Text = port->GetTrackId(); 2337 iformat_text = port->GetFormat(); 2338 GetTextSDIndex(mediaDataPtr->getSeqNum(), iText_sdIndex); 2339 } 2340 if (((port->GetFormat() == PVMF_MIME_AMR_IETF) || 2341 (port->GetFormat() == PVMF_MIME_AMRWB_IETF)) && mediaDataPtr->getErrorsFlag()) 2342 { 2343 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE, 2344 (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error flag set for AMR!")); 2345 return PVMFSuccess; 2346 } 2347 2348 if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_MPEG4_AUDIO)) 2349 { 2350 // Set AAC Config 2351 OsclRefCounterMemFrag decSpecInfo; 2352 if (mediaDataPtr->getFormatSpecificInfo(decSpecInfo) == false || 2353 decSpecInfo.getMemFragSize() == 0) 2354 { 2355 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2356 (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - Decoder Specific not available")); 2357 return PVMFFailure; 2358 } 2359 2360 iMpeg4File->setDecoderSpecificInfo((uint8*)decSpecInfo.getMemFragPtr(), 2361 (int32)decSpecInfo.getMemFragSize(), trackId); 2362 } 2363 2364 // Retrieve data from incoming queue 2365 OsclRefCounterMemFrag memFrag; 2366 uint32 numFrags = mediaDataPtr->getNumFragments(); 2367 uint32 timestamp = mediaDataPtr->getTimestamp(); 2368 iSyncSample = 0; 2369 if (mediaDataPtr->getMarkerInfo()&PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT) 2370 { 2371 iSyncSample = 1; 2372 } 2373 2374 Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> pFrame; //vector to store the nals in the particular case of AVC 2375 for (uint32 i = 0; (i < numFrags) && status == PVMFSuccess; i++) 2376 { 2377 if (!mediaDataPtr->getMediaFragment(i, memFrag)) 2378 { 2379 status = PVMFFailure; 2380 } 2381 else 2382 { 2383 OsclMemoryFragment memfragment; 2384 memfragment.len = memFrag.getMemFragSize(); 2385 memfragment.ptr = memFrag.getMemFragPtr(); 2386 pFrame.push_back(memfragment); 2387 } 2388 } 2389 2390 #ifdef ANDROID 2391 if (!iMaxReachedEvent) 2392 { 2393 // TODO: We are passing port and port->GetFormat(), should pass port only. 2394 status = iFragmentWriter->enqueueMemFragToTrack( 2395 pFrame, memFrag, port->GetFormat(), timestamp, 2396 trackId, (PVMp4FFComposerPort*)aPort); 2397 } 2398 else if (!iMaxReachedReported) 2399 { 2400 iMaxReachedReported = true; 2401 ReportInfoEvent(static_cast<PVMFComposerSizeAndDurationEvent>(iMaxReachedEvent), NULL); 2402 status = PVMFSuccess; 2403 } 2404 #else 2405 status = AddMemFragToTrack(pFrame, memFrag, port->GetFormat(), timestamp, 2406 trackId, (PVMp4FFComposerPort*)aPort); 2407 #endif 2408 if (status == PVMFFailure) 2409 ReportErrorEvent(PVMF_MP4FFCN_ERROR_ADD_SAMPLE_TO_TRACK_FAILED, (OsclAny*)aPort); 2410 } 2411 break; 2412 2413 default: 2414 LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - Invalid port tag")); 2415 ReportErrorEvent(PVMF_MP4FFCN_ERROR_ADD_SAMPLE_TO_TRACK_FAILED, (OsclAny*)aPort); 2416 status = PVMFFailure; 2417 break; 2418 } 2419 2420 return status; 2421 } 2422 2423 ////////////////////////////////////////////////////////////////////////////////// 2424 PVMFStatus PVMp4FFComposerNode::AddMemFragToTrack(Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> aFrame, OsclRefCounterMemFrag& aMemFrag, 2425 PVMFFormatType aFormat, 2426 uint32& aTimestamp, 2427 int32 aTrackId, 2428 PVMp4FFComposerPort *aPort) 2429 { 2430 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2431 (0, "PVMp4FFComposerNode::AddMemFragToTrack: aFormat=%s, aTimestamp=%d, aTrackId=%d", 2432 aFormat.getMIMEStrPtr(), aTimestamp, aTrackId)); 2433 2434 if (iRealTimeTS) 2435 { 2436 if (iInitTSOffset && (aMemFrag.getMemFragSize() > 0)) 2437 { 2438 iTSOffset = aTimestamp; 2439 iInitTSOffset = false; 2440 } 2441 2442 aTimestamp = aTimestamp - iTSOffset; 2443 } 2444 2445 uint32 timeScale = 0; 2446 PVMP4FFCNFormatSpecificConfig* config = aPort->GetFormatSpecificConfig(); 2447 if (config) 2448 { 2449 timeScale = config->iTimescale; 2450 } 2451 2452 uint32 i = 0; 2453 #if PROFILING_ON 2454 PVMp4FFCNStats* stats = NULL; 2455 for (i = 0; i < 3; i++) 2456 { 2457 if (aTrackId == iStats[i].iTrackId) 2458 { 2459 stats = &(iStats[i]); 2460 break; 2461 } 2462 } 2463 #endif 2464 2465 PVMFStatus status = PVMFSuccess; 2466 uint8 flags = 0; 2467 uint32 size = 0; 2468 uint8* data = NULL; 2469 for (i = 0; i < aFrame.size(); i++) 2470 { 2471 size = aFrame[i].len; 2472 data = OSCL_REINTERPRET_CAST(uint8*, aFrame[i].ptr); 2473 if (!data || size == 0) 2474 { 2475 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2476 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - Invalid data or data size")); 2477 return PVMFFailure; 2478 } 2479 } 2480 2481 if (aFormat == PVMF_MIME_3GPP_TIMEDTEXT || 2482 aFormat == PVMF_MIME_H264_VIDEO_MP4 || 2483 aFormat == PVMF_MIME_M4V || 2484 aFormat == PVMF_MIME_H2631998 || 2485 aFormat == PVMF_MIME_H2632000) 2486 { 2487 status = CheckMaxDuration(aTimestamp); 2488 if (status == PVMFFailure) 2489 { 2490 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2491 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxDuration failed")); 2492 return status; 2493 } 2494 else if (status == PVMFSuccess) 2495 { 2496 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG, 2497 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum duration reached")); 2498 return status; 2499 } 2500 2501 for (i = 0; i < aFrame.size(); i++) 2502 { 2503 size = aFrame[i].len; 2504 status = CheckMaxFileSize(size); 2505 if (status == PVMFFailure) 2506 { 2507 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2508 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxFileSize failed")); 2509 return status; 2510 } 2511 else if (status == PVMFSuccess) 2512 { 2513 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG, 2514 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum file size reached")); 2515 return status; 2516 } 2517 2518 //No data for some reason. 2519 if (size == 0) 2520 { 2521 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_NOTICE, 2522 (0, "PVMp4FFComposerNode::AddMemFragToTrack: no data in frag!")); 2523 return PVMFSuccess; 2524 } 2525 } 2526 uint8 codingType = CODING_TYPE_P; 2527 2528 if (iRealTimeTS) 2529 { 2530 if (aTimestamp <= aPort->GetLastTS()) 2531 { 2532 aTimestamp = aPort->GetLastTS() + 1; 2533 } 2534 2535 aPort->SetLastTS(aTimestamp); 2536 } 2537 2538 //iSyncSample is obtained from the marker info 2539 //to identify the I Frame 2540 if (iSyncSample) 2541 { 2542 codingType = CODING_TYPE_I; 2543 } 2544 2545 // Format: mtb (1) | layer_id (3) | coding_type (2) | ref_select_code (2) 2546 // flags |= ((stream->iHintTrack.MTB & 0x01) << 7); 2547 // flags |= ((stream->iHintTrack.LayerID & 0x07) << 4); 2548 flags |= ((codingType & 0x03) << 2); 2549 // flags |= (stream->iHintTrack.RefSelCode & 0x03); 2550 2551 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2552 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Calling addSampleToTrack(%d, 0x%x, %d, %d, %d)", 2553 aTrackId, data, size, aTimestamp, flags)); 2554 2555 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::AddMemFragToTrack: TrackID=%d, Size=%d, TS=%d, Flags=%d, Mime=%s", 2556 aTrackId, size, aTimestamp, flags, aPort->GetMimeType().get_cstr())); 2557 2558 if (aFormat == PVMF_MIME_3GPP_TIMEDTEXT) 2559 { 2560 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2561 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Calling addtextSampleToTrack(%d, 0x%x, %d, %d, %d)", 2562 aTrackId, data, size, aTimestamp, flags)); 2563 int32 index = iText_sdIndex; 2564 2565 if (index >= 0) 2566 { 2567 #if PROFILING_ON 2568 uint32 start = OsclTickCount::TickCount(); 2569 #endif 2570 if (!iMpeg4File->addTextSampleToTrack(aTrackId, aFrame, aTimestamp, flags, index, NULL)) 2571 { 2572 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2573 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addTextSampleToTrack for Timed Text failed")); 2574 return PVMFFailure; 2575 } 2576 iSampleInTrack = true; 2577 #if PROFILING_ON 2578 uint32 stop = OsclTickCount::TickCount(); 2579 uint32 comptime = OsclTickCount::TicksToMsec(stop - start); 2580 uint32 dataSize = 0; 2581 for (uint32 ii = 0; ii < aFrame.size(); ii++) 2582 { 2583 dataSize += aFrame[ii].len; 2584 } 2585 GenerateDiagnostics(comptime, dataSize); 2586 #endif 2587 } 2588 } 2589 else 2590 { 2591 2592 #if PROFILING_ON 2593 uint32 start = OsclTickCount::TickCount(); 2594 #endif 2595 2596 #ifdef _TEST_AE_ERROR_HANDLING 2597 2598 if (1 == iErrorAddSample) 2599 { 2600 if (iTestFileSize <= iFileSize) //iTestFileSize set in sendProgressReport() 2601 { 2602 if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags)) 2603 { 2604 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2605 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed")); 2606 return PVMFFailure; 2607 } 2608 } 2609 } 2610 else if (2 == iErrorAddSample) 2611 { 2612 2613 if (aTimestamp <= iFileDuration) 2614 { 2615 if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags)) 2616 { 2617 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2618 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed")); 2619 return PVMFFailure; 2620 } 2621 } 2622 } 2623 else 2624 { 2625 if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags)) 2626 { 2627 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2628 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed")); 2629 return PVMFFailure; 2630 } 2631 } 2632 2633 #else 2634 if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags)) 2635 { 2636 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2637 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed")); 2638 return PVMFFailure; 2639 } 2640 #endif 2641 iSampleInTrack = true; 2642 #ifdef _TEST_AE_ERROR_HANDLING 2643 if (iErrorHandlingAddMemFrag == true) 2644 { 2645 return PVMFFailure; //Just to trigger error handling 2646 } 2647 #endif 2648 2649 #if PROFILING_ON 2650 uint32 stop = OsclTickCount::TickCount(); 2651 uint32 comptime = OsclTickCount::TicksToMsec(stop - start); 2652 uint32 dataSize = 0; 2653 for (uint32 ii = 0; ii < aFrame.size(); ii++) 2654 { 2655 dataSize += aFrame[ii].len; 2656 } 2657 GenerateDiagnostics(comptime, dataSize); 2658 #endif 2659 } 2660 2661 2662 // Send progress report after sample is successfully added 2663 SendProgressReport(aTimestamp); 2664 2665 #if PROFILING_ON 2666 ++(stats->iNumFrames); 2667 stats->iDuration = aTimestamp; 2668 #endif 2669 } 2670 2671 else if ((aFormat == PVMF_MIME_AMR_IETF) || 2672 (aFormat == PVMF_MIME_AMRWB_IETF)) 2673 { 2674 if (iRealTimeTS) 2675 { 2676 if (((int32) aTimestamp - (int32) aPort->GetLastTS()) < 20) 2677 { 2678 aTimestamp = aPort->GetLastTS() + 20; 2679 } 2680 2681 aPort->SetLastTS(aTimestamp); 2682 } 2683 2684 uint32 bytesProcessed = 0; 2685 uint32 frameSize = 0; 2686 Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> amrfrags; 2687 for (i = 0; i < aFrame.size(); i++) 2688 { 2689 bytesProcessed = 0; 2690 size = aFrame[i].len; 2691 data = OSCL_REINTERPRET_CAST(uint8*, aFrame[i].ptr); 2692 // Parse audio data and add one 20ms frame to track at a time 2693 while (bytesProcessed < size) 2694 { 2695 // Check for max duration 2696 status = CheckMaxDuration(aTimestamp); 2697 if (status == PVMFFailure) 2698 { 2699 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2700 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxDuration failed")); 2701 return status; 2702 } 2703 else if (status == PVMFSuccess) 2704 { 2705 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG, 2706 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum duration reached")); 2707 return status; 2708 } 2709 2710 // Update clock converter 2711 iClockConverter.set_timescale(timeScale); 2712 iClockConverter.set_clock_other_timescale(aTimestamp, 1000); 2713 2714 // Check max file size 2715 int32 frSize = GetIETFFrameSize(data[0], aPort->GetCodecType()); 2716 if (frSize == -1) 2717 { 2718 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2719 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - Frame Type Not Supported - Skipping")); 2720 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::AddMemFragToTrack - Invalid Frame: TrackID=%d, Byte=0x%x, Mime=%s", 2721 aTrackId, data[0], aPort->GetMimeType().get_cstr())); 2722 return PVMFFailure; 2723 } 2724 frameSize = (uint32)frSize; 2725 2726 status = CheckMaxFileSize(frameSize); 2727 if (status == PVMFFailure) 2728 { 2729 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2730 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxFileSize failed")); 2731 return status; 2732 } 2733 else if (status == PVMFSuccess) 2734 { 2735 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG, 2736 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum file size reached")); 2737 return status; 2738 } 2739 2740 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, 2741 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Calling addSampleToTrack(%d, 0x%x, %d, %d, %d)", 2742 aTrackId, data, frameSize, iClockConverter.get_current_timestamp(), flags)); 2743 2744 2745 OsclMemoryFragment amr_memfrag; 2746 amr_memfrag.len = frameSize; 2747 amr_memfrag.ptr = data; 2748 amrfrags.push_back(amr_memfrag); 2749 2750 #if PROFILING_ON 2751 uint32 start = OsclTickCount::TickCount(); 2752 #endif 2753 uint32 amrts = iClockConverter.get_current_timestamp(); 2754 2755 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::AddMemFragToTrack: TrackID=%d, Size=%d, TS=%d, Flags=%d, Mime=%s", 2756 aTrackId, frameSize, amrts, flags, aPort->GetMimeType().get_cstr())); 2757 2758 if (!iMpeg4File->addSampleToTrack(aTrackId, amrfrags, amrts, flags)) 2759 { 2760 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2761 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed")); 2762 return PVMFFailure; 2763 } 2764 iSampleInTrack = true; 2765 #if PROFILING_ON 2766 uint32 stop = OsclTickCount::TickCount(); 2767 uint32 comptime = OsclTickCount::TicksToMsec(stop - start); 2768 uint32 dataSize = 0; 2769 for (uint32 ii = 0; ii < amrfrags.size(); ii++) 2770 { 2771 dataSize += amrfrags[ii].len; 2772 } 2773 GenerateDiagnostics(comptime, dataSize); 2774 2775 #endif 2776 2777 // Send progress report after sample is successfully added 2778 SendProgressReport(aTimestamp); 2779 2780 #if PROFILING_ON 2781 ++(stats->iNumFrames); 2782 stats->iDuration = aTimestamp; 2783 #endif 2784 data += frameSize; 2785 bytesProcessed += frameSize; 2786 aTimestamp += 20; 2787 amrfrags.clear(); 2788 } 2789 } 2790 if (iRealTimeTS) 2791 { 2792 aPort->SetLastTS(aTimestamp - 20); 2793 } 2794 } 2795 2796 else if (aFormat == PVMF_MIME_MPEG4_AUDIO) 2797 { 2798 status = CheckMaxDuration(aTimestamp); 2799 if (status == PVMFFailure) 2800 { 2801 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2802 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxDuration failed")); 2803 return status; 2804 } 2805 else if (status == PVMFSuccess) 2806 { 2807 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG, 2808 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum duration reached")); 2809 return status; 2810 } 2811 2812 for (i = 0; i < aFrame.size(); i++) 2813 { 2814 size = aFrame[i].len; 2815 status = CheckMaxFileSize(size); 2816 if (status == PVMFFailure) 2817 { 2818 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2819 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxFileSize failed")); 2820 return status; 2821 } 2822 else if (status == PVMFSuccess) 2823 { 2824 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG, 2825 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum file size reached")); 2826 return status; 2827 } 2828 2829 //No data for some reason. 2830 if (size == 0) 2831 { 2832 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_NOTICE, 2833 (0, "PVMp4FFComposerNode::AddMemFragToTrack: no data in frag!")); 2834 return PVMFSuccess; 2835 } 2836 } 2837 2838 if (iRealTimeTS) 2839 { 2840 if (aTimestamp <= aPort->GetLastTS()) 2841 { 2842 aTimestamp = aPort->GetLastTS() + 1; 2843 } 2844 2845 aPort->SetLastTS(aTimestamp); 2846 } 2847 2848 iClockConverter.set_timescale(timeScale); 2849 iClockConverter.set_clock_other_timescale(aTimestamp, 1000); 2850 uint32 aacTS = iClockConverter.get_current_timestamp(); 2851 2852 if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aacTS, flags)) 2853 { 2854 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, 2855 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed")); 2856 return PVMFFailure; 2857 } 2858 iSampleInTrack = true; 2859 // Send progress report after sample is successfully added 2860 SendProgressReport(aTimestamp); 2861 2862 #if PROFILING_ON 2863 ++(stats->iNumFrames); 2864 stats->iDuration = aTimestamp; 2865 #endif 2866 } 2867 2868 return PVMFSuccess; 2869 } 2870 2871 2872 void PVMp4FFComposerNode::GenerateDiagnostics(uint32 aTime, uint32 aSize) 2873 { 2874 #if PROFILING_ON 2875 if ((iMinSampleAddTime > aTime) || (0 == iMinSampleAddTime)) 2876 { 2877 iMinSampleAddTime = aTime; 2878 } 2879 if (iMaxSampleAddTime < aTime) 2880 { 2881 iMaxSampleAddTime = aTime; 2882 } 2883 2884 if ((iMinSampleSize > aSize) || (0 == iMinSampleSize)) 2885 { 2886 iMinSampleSize = aSize; 2887 } 2888 if (iMaxSampleSize < aSize) 2889 { 2890 iMaxSampleSize = aSize; 2891 } 2892 iNumSamplesAdded++; 2893 #endif 2894 OSCL_UNUSED_ARG(aTime); 2895 OSCL_UNUSED_ARG(aSize); 2896 } 2897 ////////////////////////////////////////////////////////////////////////////////// 2898 int32 PVMp4FFComposerNode::GetIETFFrameSize(uint8 aFrameType, 2899 int32 aCodecType) 2900 { 2901 uint8 frameType = (uint8)(aFrameType >> 3) & 0x0f; 2902 if (aCodecType == CODEC_TYPE_AMR_AUDIO) 2903 { 2904 // Find frame size for each frame type 2905 switch (frameType) 2906 { 2907 case 0: // AMR 4.75 Kbps 2908 return 13; 2909 case 1: // AMR 5.15 Kbps 2910 return 14; 2911 case 2: // AMR 5.90 Kbps 2912 return 16; 2913 case 3: // AMR 6.70 Kbps 2914 return 18; 2915 case 4: // AMR 7.40 Kbps 2916 return 20; 2917 case 5: // AMR 7.95 Kbps 2918 return 21; 2919 case 6: // AMR 10.2 Kbps 2920 return 27; 2921 case 7: // AMR 12.2 Kbps 2922 return 32; 2923 case 8: // AMR Frame SID 2924 return 6; 2925 case 9: // AMR Frame GSM EFR SID 2926 return 7; 2927 case 10:// AMR Frame TDMA EFR SID 2928 case 11:// AMR Frame PDC EFR SID 2929 return 6; 2930 case 15: // AMR Frame No Data 2931 return 1; 2932 default: // Error - For Future Use 2933 return -1; 2934 } 2935 } 2936 else if (aCodecType == CODEC_TYPE_AMR_WB_AUDIO) 2937 { 2938 // Find frame size for each frame type 2939 switch (frameType) 2940 { 2941 case 0: // AMR-WB 6.60 Kbps 2942 return 18; 2943 case 1: // AMR-WB 8.85 Kbps 2944 return 24; 2945 case 2: // AMR-WB 12.65 Kbps 2946 return 33; 2947 case 3: // AMR-WB 14.25 Kbps 2948 return 37; 2949 case 4: // AMR-WB 15.85 Kbps 2950 return 41; 2951 case 5: // AMR-WB 18.25 Kbps 2952 return 47; 2953 case 6: // AMR-WB 19.85 Kbps 2954 return 51; 2955 case 7: // AMR-WB 23.05 Kbps 2956 return 59; 2957 case 8: // AMR-WB 23.85 Kbps 2958 return 61; 2959 case 9: // AMR-WB SID Frame 2960 return 6; 2961 case 10: //Reserved 2962 case 11: //Reserved 2963 case 12: //Reserved 2964 case 13: //Reserved 2965 return -1; 2966 case 14: // AMR-WB Frame Lost 2967 case 15: // AMR-WB Frame No Data 2968 return 1; 2969 default: // Error - For Future Use 2970 return -1; 2971 } 2972 } 2973 return -1; 2974 } 2975 2976 ////////////////////////////////////////////////////////////////////////////////// 2977 // Progress and max size / duration routines 2978 ////////////////////////////////////////////////////////////////////////////////// 2979 PVMFStatus PVMp4FFComposerNode::SendProgressReport(uint32 aTimestamp) 2980 { 2981 if (iDurationReportEnabled && 2982 aTimestamp >= iNextDurationReport) 2983 { 2984 iNextDurationReport = aTimestamp - (aTimestamp % iDurationReportFreq) + iDurationReportFreq; 2985 ReportInfoEvent(PVMF_COMPOSER_DURATION_PROGRESS, (OsclAny*)aTimestamp); 2986 } 2987 else if (iFileSizeReportEnabled) 2988 { 2989 uint32 metaDataSize = 0; 2990 uint32 mediaDataSize = 0; 2991 uint32 fileSize = 0; 2992 2993 iMpeg4File->getTargetFileSize(metaDataSize, mediaDataSize); 2994 fileSize = metaDataSize + mediaDataSize; 2995 2996 if (fileSize >= iNextFileSizeReport) 2997 { 2998 iNextFileSizeReport = fileSize - (fileSize % iFileSizeReportFreq) + iFileSizeReportFreq; 2999 ReportInfoEvent(PVMF_COMPOSER_FILESIZE_PROGRESS, (OsclAny*)fileSize); 3000 } 3001 #ifdef _TEST_AE_ERROR_HANDLING 3002 iTestFileSize = fileSize; //iTestTimeStamp to fail the addSampleTrack() once a particulare time duration is reached as specified in testapp. 3003 #endif 3004 } 3005 3006 return PVMFSuccess; 3007 } 3008 3009 ////////////////////////////////////////////////////////////////////////////////// 3010 PVMFStatus PVMp4FFComposerNode::CheckMaxFileSize(uint32 aFrameSize) 3011 { 3012 if (iMaxFileSizeEnabled) 3013 { 3014 uint32 metaDataSize = 0; 3015 uint32 mediaDataSize = 0; 3016 iMpeg4File->getTargetFileSize(metaDataSize, mediaDataSize); 3017 3018 if ((metaDataSize + mediaDataSize + aFrameSize) >= iMaxFileSize) 3019 { 3020 #ifdef ANDROID 3021 // This code is executed on the fragment writer thread, we 3022 // don't want to call RenderToFile since it will call 3023 // flush() on the writer from this very same 3024 // thread. Instead, we use a marker to report an event to 3025 // the author node next time a new fragment is processed. 3026 iMaxReachedEvent = PVMF_COMPOSER_MAXFILESIZE_REACHED; 3027 #else 3028 // Finalized output file 3029 if (iSampleInTrack) 3030 { 3031 WriteDecoderSpecificInfo(); 3032 iSampleInTrack = false; 3033 if (RenderToFile() != PVMFSuccess) 3034 return PVMFFailure; 3035 } 3036 3037 ReportInfoEvent(PVMF_COMPOSER_MAXFILESIZE_REACHED, NULL); 3038 return PVMFSuccess; 3039 #endif 3040 } 3041 3042 return PVMFPending; 3043 } 3044 3045 return PVMFErrNotSupported; 3046 } 3047 3048 ////////////////////////////////////////////////////////////////////////////////// 3049 PVMFStatus PVMp4FFComposerNode::CheckMaxDuration(uint32 aTimestamp) 3050 { 3051 //if(!iInfoObserver) 3052 // return PVMFFailure; 3053 3054 if (iMaxDurationEnabled) 3055 { 3056 if (aTimestamp >= iMaxTimeDuration) 3057 { 3058 #ifdef ANDROID 3059 // This code is executed on the fragment writer thread, we 3060 // don't want to call RenderToFile since it will call 3061 // flush() on the writer from this very same 3062 // thread. Instead, we use a marker to report an event to 3063 // the author node next time a new fragment is processed. 3064 iMaxReachedEvent = PVMF_COMPOSER_MAXDURATION_REACHED; 3065 #else 3066 3067 // Finalize output file 3068 if (iSampleInTrack) 3069 { 3070 WriteDecoderSpecificInfo(); 3071 iSampleInTrack = false; 3072 if (RenderToFile() != PVMFSuccess) 3073 return PVMFFailure; 3074 } 3075 3076 ReportInfoEvent(PVMF_COMPOSER_MAXDURATION_REACHED, NULL); 3077 return PVMFSuccess; 3078 #endif 3079 } 3080 3081 return PVMFPending; 3082 } 3083 3084 return PVMFErrNotSupported; 3085 } 3086 3087 //////////////////////////////////////////////////////////////////////////// 3088 // Event reporting routines. 3089 //////////////////////////////////////////////////////////////////////////// 3090 void PVMp4FFComposerNode::SetState(TPVMFNodeInterfaceState aState) 3091 { 3092 LOG_STACK_TRACE((0, "PVMp4FFComposerNode::SetState: aState=%d", aState)); 3093 PVMFNodeInterface::SetState(aState); 3094 } 3095 3096 void PVMp4FFComposerNode::ReportErrorEvent(PvmfMp4FFCNError aErrorEvent, OsclAny* aEventData) 3097 { 3098 LOG_ERR((0, "PVMp4FFComposerNode:ReportErrorEvent: aEventType=%d, aEventData=0x%x", aErrorEvent, aEventData)); 3099 switch (aErrorEvent) 3100 { 3101 case PVMF_MP4FFCN_ERROR_FINALIZE_OUTPUT_FILE_FAILED: 3102 case PVMF_MP4FFCN_ERROR_ADD_SAMPLE_TO_TRACK_FAILED: 3103 PVMFNodeInterface::ReportErrorEvent(PVMFErrResourceConfiguration, aEventData); 3104 break; 3105 default: 3106 PVMFNodeInterface::ReportErrorEvent(PVMFFailure, aEventData); 3107 break; 3108 } 3109 } 3110 3111 void PVMp4FFComposerNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData) 3112 { 3113 LOG_STACK_TRACE((0, "PVMp4FFComposerNode:ReportInfoEvent: aEventType=%d, aEventData=0x%x", aEventType, aEventData)); 3114 PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData); 3115 } 3116 3117 3118 3119 void PVMp4FFComposerNode::LogDiagnostics() 3120 { 3121 #if PROFILING_ON 3122 oDiagnosticsLogged = true; 3123 PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iDiagnosticsLogger, PVLOGMSG_DEBUG, (0, "PVMp4FFComposerNode Stats:Sample Add time (Min:%d, Max:%d), Sample Size(Min:%d, Max:%d), number of samples added:%d\n", iMinSampleAddTime, iMaxSampleAddTime, iMinSampleSize, iMaxSampleSize, iNumSamplesAdded)); 3124 #endif 3125 } 3126 3127 int32 PVMp4FFComposerNode::StoreCurrentCommand(PVMp4FFCNCmdQueue& aCurrentCmd, PVMp4FFCNCmd& aCmd, PVMp4FFCNCmdQueue& aCmdQueue) 3128 { 3129 int32 err = 0; 3130 OSCL_TRY(err, aCurrentCmd.StoreL(aCmd);); 3131 OSCL_FIRST_CATCH_ANY(err, 3132 CommandComplete(aCmdQueue, aCmd, PVMFErrNoMemory); 3133 return err; 3134 ); 3135 return err; 3136 } 3137 3138 void PVMp4FFComposerNode::GetTextSDIndex(uint32 aSampleNum, int32& aIndex) 3139 { 3140 //default index is zero 3141 aIndex = 0; 3142 Oscl_Vector<PVA_FF_TextSampleDescInfo*, OsclMemAllocator>::iterator it; 3143 for (it = textdecodervector.begin(); it != textdecodervector.end(); it++) 3144 { 3145 if ((aSampleNum >= (*it)->start_sample_num) && 3146 (aSampleNum <= (*it)->end_sample_num)) 3147 { 3148 aIndex = (*it)->sdindex; 3149 break; 3150 } 3151 } 3152 } 3153 3154 3155 3156