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