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