• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PVMFMP4FFParserNode(int32 aPriority)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 
~PVMFMP4FFParserNode()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 
ThreadLogon()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 
ThreadLogoff()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 
GetCapability(PVMFNodeCapability & aNodeCapability)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 
GetPorts(const PVMFPortFilter * aFilter)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 
QueryUUID(PVMFSessionId aSessionId,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)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 
QueryInterface(PVMFSessionId aSessionId,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)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 
RequestPort(PVMFSessionId aSessionId,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)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 
ReleasePort(PVMFSessionId aSessionId,PVMFPortInterface & aPort,const OsclAny * aContext)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 
Init(PVMFSessionId aSessionId,const OsclAny * aContext)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 
Prepare(PVMFSessionId aSessionId,const OsclAny * aContext)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 
Start(PVMFSessionId aSessionId,const OsclAny * aContext)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 
Stop(PVMFSessionId aSessionId,const OsclAny * aContext)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 
Flush(PVMFSessionId aSessionId,const OsclAny * aContext)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 
Pause(PVMFSessionId aSessionId,const OsclAny * aContext)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 
Reset(PVMFSessionId aSessionId,const OsclAny * aContext)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 
CancelAllCommands(PVMFSessionId aSessionId,const OsclAny * aContext)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 
CancelCommand(PVMFSessionId aSessionId,PVMFCommandId aCmdId,const OsclAny * aContext)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 
addRef()551 void PVMFMP4FFParserNode::addRef()
552 {
553     ++iExtensionRefCount;
554 }
555 
556 
removeRef()557 void PVMFMP4FFParserNode::removeRef()
558 {
559     --iExtensionRefCount;
560 }
561 
562 
QueryInterfaceSync(PVMFSessionId aSession,const PVUuid & aUuid,PVInterface * & aInterfacePtr)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 
queryInterface(const PVUuid & uuid,PVInterface * & iface)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 
SetSourceInitializationData(OSCL_wString & aSourceURL,PVMFFormatType & aSourceFormat,OsclAny * aSourceData)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 
SetClientPlayBackClock(PVMFMediaClock * aClock)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 
SetEstimatedServerClock(PVMFMediaClock *)798 PVMFStatus PVMFMP4FFParserNode::SetEstimatedServerClock(PVMFMediaClock* /*aClientClock*/)
799 {
800     return PVMFErrNotSupported;
801 }
802 
GetMediaPresentationInfo(PVMFMediaPresentationInfo & aInfo)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 
SelectTracks(PVMFMediaPresentationInfo & aInfo)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 
SetDataSourcePosition(PVMFSessionId aSessionId,PVMFTimestamp aTargetNPT,PVMFTimestamp & aActualNPT,PVMFTimestamp & aActualMediaDataTS,bool aSeekToSyncPoint,uint32 aStreamID,OsclAny * aContext)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 
QueryDataSourcePosition(PVMFSessionId aSessionId,PVMFTimestamp aTargetNPT,PVMFTimestamp & aActualNPT,bool aSeekToSyncPoint,OsclAny * aContext)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 
QueryDataSourcePosition(PVMFSessionId aSessionId,PVMFTimestamp aTargetNPT,PVMFTimestamp & aSeekPointBeforeTargetNPT,PVMFTimestamp & aSeekPointAfterTargetNPT,OsclAny * aContext,bool aSeekToSyncPoint)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 
SetDataSourceRate(PVMFSessionId aSessionId,int32 aRate,PVMFTimebase * aTimebase,OsclAny * aContext)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 
SetDataSourceDirection(PVMFSessionId aSessionId,int32 aDirection,PVMFTimestamp & aActualNPT,PVMFTimestamp & aActualMediaDataTS,PVMFTimebase * aTimebase,OsclAny * aContext)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 
GetAvailableTracks(Oscl_Vector<PVMFTrackInfo,OsclMemAllocator> & aTracks)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 
GetTimestampForSampleNumber(PVMFTrackInfo & aTrackInfo,uint32 aSampleNum,PVMFTimestamp & aTimestamp)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 
GetSampleNumberForTimestamp(PVMFTrackInfo & aTrackInfo,PVMFTimestamp aTimestamp,uint32 & aSampleNum)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 
GetNumberOfSyncSamples(PVMFTrackInfo & aTrackInfo,int32 & aNumSyncSamples)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 
GetSyncSampleInfo(PVMFTrackInfo & aTrackInfo,PVMFSampleNumTSList & aList,uint32 aStartIndex,int32 aMaxEntries)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 
GetSyncSampleInfo(PVMFSampleNumTSList & aList,PVMFTrackInfo & aTrackInfo,int32 aTargetTimeInMS,uint32 aHowManySamples)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 
GetTimestampForDataPosition(PVMFTrackInfo & aTrackInfo,uint32 aDataPosition,PVMFTimestamp & aTimestamp)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 
GetDataPositionForTimestamp(PVMFTrackInfo & aTrackInfo,PVMFTimestamp aTimestamp,uint32 & aDataPosition)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 
Run()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 
QueueCommandL(PVMFMP4FFParserNodeCommand & aCmd)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 
MoveCmdToCurrentQueue(PVMFMP4FFParserNodeCommand & aCmd)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 
MoveCmdToCancelQueue(PVMFMP4FFParserNodeCommand & aCmd)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 
ProcessCommand()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 
CommandComplete(PVMFMP4FFParserNodeCmdQueue & aCmdQ,PVMFMP4FFParserNodeCommand & aCmd,PVMFStatus aStatus,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)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 
CompleteCancelAfterInit()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 
ReportMP4FFParserErrorEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)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 
ReportMP4FFParserInfoEvent(PVMFEventType aEventType,OsclAny * aEventData,PVUuid * aEventUUID,int32 * aEventCode)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 
ChangeNodeState(TPVMFNodeInterfaceState aNewState)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 
DoQueryUuid(PVMFMP4FFParserNodeCommand & aCmd)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 
DoQueryInterface(PVMFMP4FFParserNodeCommand & aCmd)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 
DoRequestPort(PVMFMP4FFParserNodeCommand & aCmd,PVMFPortInterface * & aPort)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 
GetTrackMaxParameters(PVMFFormatType aFormatType,uint32 & aMaxDataSize,uint32 & aMaxQueueDepth)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 
DoReleasePort(PVMFMP4FFParserNodeCommand & aCmd)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 
InitOMA2DRMInfo()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 
DoInit(PVMFMP4FFParserNodeCommand & aCmd)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 
ParseMP4File(PVMFMP4FFParserNodeCmdQueue & aCmdQ,PVMFMP4FFParserNodeCommand & aCmd)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 
CompleteInit(PVMFMP4FFParserNodeCmdQueue & aCmdQ,PVMFMP4FFParserNodeCommand & aCmd)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 
DoPrepare(PVMFMP4FFParserNodeCommand &)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 
CompletePrepare(PVMFStatus aStatus)2742 void PVMFMP4FFParserNode::CompletePrepare(PVMFStatus aStatus)
2743 {
2744     CommandComplete(iCurrentCommand, iCurrentCommand.front(), aStatus);
2745 }
2746 
2747 
DoStart(PVMFMP4FFParserNodeCommand &)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 
DoStop(PVMFMP4FFParserNodeCommand & aCmd)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 
DoFlush(PVMFMP4FFParserNodeCommand & aCmd)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 
FlushPending()2821 bool PVMFMP4FFParserNode::FlushPending()
2822 {
2823     return (iCurrentCommand.size() > 0 && iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
2824 }
2825 
2826 
DoPause(PVMFMP4FFParserNodeCommand & aCmd)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 
DoReset(PVMFMP4FFParserNodeCommand & aCmd)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 
CompleteReset(PVMFMP4FFParserNodeCmdQueue & aCmdQ,PVMFMP4FFParserNodeCommand & aCmd)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 
DoCancelAllCommands(PVMFMP4FFParserNodeCommand &)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 
DoCancelCommand(PVMFMP4FFParserNodeCommand & aCmd)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 
DoCancelCurrentCommand(PVMFMP4FFParserNodeCommand & aCmd)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 
DoSetDataSourcePosition(PVMFMP4FFParserNodeCommand & aCmd,PVMFStatus & aEventCode,PVUuid & aEventUuid)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 
DoQueryDataSourcePosition(PVMFMP4FFParserNodeCommand & aCmd)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 
DoSetDataSourceRate(PVMFMP4FFParserNodeCommand & aCmd)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 
DoSetDataSourceDirection(PVMFMP4FFParserNodeCommand & aCmd)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 
HandleTrackState()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 
RetrieveTrackConfigInfo(uint32 aTrackId,PVMFFormatType aFormatType,OsclRefCounterMemFrag & aConfig)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 
RetrieveTrackConfigInfoAndFirstSample(uint32 aTrackId,PVMFFormatType aFormatType,OsclRefCounterMemFrag & aConfig)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 
checkTrackPosition(PVMP4FFNodeTrackPortInfo & aTrackPortInfo,uint32 numsamples)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 
RetrieveTrackData(PVMP4FFNodeTrackPortInfo & aTrackPortInfo)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                 // no keyframe exists in the file, hence thumbnail could not
4441                 // be retrieved, Treat this as EOS
4442                 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
4443                 return false;
4444             }
4445             retval = iMP4FileHandle->getKeyMediaSampleNumAt(trackid, keySampleNum, &iGau);
4446             if (retval == EVERYTHING_FINE || retval == END_OF_TRACK)
4447             {
4448                 numsamples = 1;
4449                 aTrackPortInfo.iThumbSampleDone = true;
4450             }
4451         }
4452         else
4453         {
4454             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
4455             return false;
4456         }
4457     }
4458     else if ((PVMF_DATA_SOURCE_DIRECTION_REVERSE == iPlayBackDirection) &&
4459              (iMP4FileHandle->getTrackMediaType(aTrackPortInfo.iTrackId) == MEDIA_TYPE_VISUAL))
4460     {
4461         uint32 numSamples = 1;
4462         uint32 keySampleNumber;
4463         if (aTrackPortInfo.iFirstFrameAfterRepositioning)
4464         {
4465             iPrevSampleTS = iMP4FileHandle->getMediaTimestampForCurrentSample(trackid);
4466             retval = iMP4FileHandle->getPrevKeyMediaSample(iPrevSampleTS, keySampleNumber, trackid,
4467                      &numSamples, &iGau);
4468             iStartForNextTSSearch = iMP4FileHandle->getMediaTimestampForCurrentSample(trackid) - 2 * iGau.info[0].ts_delta;
4469         }
4470         else
4471         {
4472             if (iStartForNextTSSearch <= 0)
4473             {
4474                 retval = END_OF_TRACK;
4475             }
4476             else
4477             {
4478                 retval = iMP4FileHandle->getPrevKeyMediaSample(iStartForNextTSSearch, keySampleNumber, trackid,
4479                          &numSamples, &iGau);
4480                 iStartForNextTSSearch = iMP4FileHandle->getMediaTimestampForCurrentSample(trackid) - 2 * iGau.info[0].ts_delta;
4481             }
4482         }
4483 
4484     }
4485     else
4486     {
4487         retval = iMP4FileHandle->getNextBundledAccessUnits(trackid, &numsamples, &iGau);
4488     }
4489 
4490     if (retval == NO_SAMPLE_IN_CURRENT_MOOF && numsamples == 0)
4491     {
4492         // no sample was retrieved, try to retrieve in next getNextBundledAccessUnits call
4493         // return false without modifying the state.
4494         mediadataout->~PVMFMediaData();
4495         return false;
4496     }
4497 
4498     currticks = OsclTickCount::TickCount();
4499     uint32 EndTime = OsclTickCount::TicksToMsec(currticks);
4500 
4501     aTrackPortInfo.iNumTimesMediaSampleRead++;
4502 
4503     // Determine actual size of the retrieved data by summing each sample length in GAU
4504 
4505     uint32 DeltaTime = EndTime - StartTime;
4506 
4507     if (DeltaTime >= maxTime)
4508     {
4509         maxTime = DeltaTime;
4510     }
4511     if (DeltaTime <= minTime)
4512     {
4513         minTime = DeltaTime;
4514     }
4515     sumTime += DeltaTime;
4516 
4517     aTrackPortInfo.iMaxTime = maxTime;
4518     aTrackPortInfo.iMinTime = minTime;
4519     aTrackPortInfo.iSumTime = sumTime;
4520 
4521     uint32 actualdatasize = 0;
4522     uint32 tsDelta = 0;
4523     uint32 duration_text_msec = 0;
4524     bool oSetNoRenderBit = false;
4525     bool textOnlyClip = false;
4526     for (uint32 i = 0; i < iGau.numMediaSamples; ++i)
4527     {
4528         actualdatasize += iGau.info[i].len;
4529         if ((PVMF_DATA_SOURCE_DIRECTION_REVERSE == iPlayBackDirection) &&
4530                 (iMP4FileHandle->getTrackMediaType(aTrackPortInfo.iTrackId) == MEDIA_TYPE_VISUAL))
4531         {
4532             // for reverse we are just using I frames so need to get delta from total differnece in time
4533             tsDelta += oscl_abs(iGau.info[0].ts - iPrevSampleTS);
4534             if (0 == tsDelta)
4535                 tsDelta += iGau.info[i].ts_delta;
4536 
4537             iPrevSampleTS = iGau.info[0].ts;
4538 
4539             // in the case of backwards playback, dont render if ts greater than targetnpt.
4540             if (iGau.info[i].ts > aTrackPortInfo.iTargetNPTInMediaTimeScale)
4541             {
4542                 oSetNoRenderBit = true;
4543             }
4544             else
4545             {
4546                 //we are past the no render point, so reset to zero
4547                 aTrackPortInfo.iTargetNPTInMediaTimeScale = 0x7FFFFFFF;
4548             }
4549         }
4550         else
4551         {
4552             tsDelta += iGau.info[i].ts_delta;
4553 
4554             if (iGau.info[i].ts < aTrackPortInfo.iTargetNPTInMediaTimeScale)
4555             {
4556                 oSetNoRenderBit = true;
4557             }
4558             else
4559             {
4560                 //we are past the no render point, so reset to zero
4561                 aTrackPortInfo.iTargetNPTInMediaTimeScale = 0;
4562             }
4563         }
4564     }
4565 
4566     // Save the first frame flag for output media data's random access point flag
4567     bool israndomaccesspt = aTrackPortInfo.iFirstFrameAfterRepositioning;
4568     if (aTrackPortInfo.iFirstFrameAfterRepositioning)
4569     {
4570         // If it is first frame after repositioning, media data timestamp should be
4571         // at the spot set when SetDataSourcePosition was processed and doesn't need to
4572         // consider the delta of the current frame from previous one.
4573         aTrackPortInfo.iFirstFrameAfterRepositioning = false;
4574     }
4575 
4576     if (retval == EVERYTHING_FINE || retval == END_OF_TRACK)
4577     {
4578         // Truly is end of track when return value is END_OF_TRACK and number of samples
4579         // returned is 0 or length of data is 0
4580         if (retval == END_OF_TRACK && (numsamples < 1 || actualdatasize == 0))
4581         {
4582             if (aTrackPortInfo.iSendBOS == true)
4583             {
4584                 // If BOS has not been sent, it needs to be send before EOS.
4585                 // E.g., In case the first call to RetrieveTrack produces END_OF_TRACK.
4586                 SendBeginOfMediaStreamCommand(aTrackPortInfo);
4587             }
4588             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
4589             // End of track reached so send EOS media command
4590             if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT)
4591             {
4592                 iEOTForTextSentToMIO = true;
4593                 iSetTextSampleDurationZero = false;
4594             }
4595             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RetrieveTrackData() EOS LOC 3 track ID %d", aTrackPortInfo.iTrackId));
4596             return false;
4597         }
4598 
4599         if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
4600         {
4601             if (iDecryptionInterface != NULL)
4602             {
4603                 uint32 inSize = actualdatasize;
4604                 uint32 outSize = actualdatasize;
4605 
4606                 uint32 currticks = OsclTickCount::TickCount();
4607                 uint32 StartTime;
4608                 StartTime = OsclTickCount::TicksToMsec(currticks);
4609 
4610                 if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT)
4611                 {
4612                     PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*) refCtrMemFragOut.getMemFrag().ptr;
4613                     iDecryptionInterface->DecryptAccessUnit(iOMA2DecryptionBuffer,
4614                                                             inSize,
4615                                                             textmediadata->iTextSample,
4616                                                             outSize, trackid);
4617                 }
4618                 else
4619                 {
4620                     uint8* memfrag = (uint8*)(refCtrMemFragOut.getMemFrag().ptr);
4621 
4622                     iDecryptionInterface->DecryptAccessUnit(iOMA2DecryptionBuffer,
4623                                                             inSize,
4624                                                             memfrag,
4625                                                             outSize, trackid);
4626                 }
4627                 currticks = OsclTickCount::TickCount();
4628                 uint32 EndTime;
4629                 EndTime = OsclTickCount::TicksToMsec(currticks);
4630 
4631                 actualdatasize = outSize;
4632                 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));
4633             }
4634             else
4635             {
4636                 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR;
4637                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData Text sample is less than 2 bytes (size=%d). ReportMP4FFParserErrorEvent(PVMFErrCorrupt)", actualdatasize));
4638                 ReportMP4FFParserErrorEvent(PVMFErrInvalidState);
4639                 return false;
4640             }
4641         }
4642 
4643         // Retrieve the output media data impl to set some properties
4644         OsclSharedPtr<PVMFMediaDataImpl> media_data_impl;
4645         mediadataout->getMediaDataImpl(media_data_impl);
4646 
4647         if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT)
4648         {
4649             PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*) refCtrMemFragOut.getMemFrag().ptr;
4650 
4651             // Check if the text sample duration read by parser is zero, then send EOT.
4652             textmediadata->iTextSampleDuration = iGau.info[0].ts_delta;
4653             if (textmediadata->iTextSampleDuration == 0)
4654             {
4655                 iSetTextSampleDurationZero = true;
4656                 iEOTForTextSentToMIO = true;
4657                 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
4658                 return false;
4659             }
4660 
4661             // Adjust the duration of Text Sample (if clip is not textOnlyClip) as per new time-stamp.
4662             // Retrieve timestamp and convert to milliseconds
4663 
4664             textOnlyClip = true;
4665             for (uint32 i = 0; i < iNodeTrackPortList.size(); i++)
4666             {
4667                 if ((iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_VISUAL) ||
4668                         (iMP4FileHandle->getTrackMediaType(iNodeTrackPortList[i].iTrackId) == MEDIA_TYPE_AUDIO))
4669                 {
4670                     textOnlyClip = false;
4671                 }
4672             }
4673 
4674             if (!textOnlyClip)
4675             {
4676                 if (iGau.info[0].ts_delta >= aTrackPortInfo.iTimestamp)
4677                 {
4678                     iGau.info[0].ts_delta = iGau.info[0].ts_delta - aTrackPortInfo.iTimestamp;
4679                 }
4680             }
4681 
4682             aTrackPortInfo.iClockConverter->set_clock(iGau.info[0].ts_delta, 0);
4683             duration_text_msec = aTrackPortInfo.iClockConverter->get_converted_ts(1000);
4684 
4685             aTrackPortInfo.iClockConverter->set_clock(aTrackPortInfo.iTimestamp, 0);
4686             // Set sample duration, In media timescale.
4687             // The duration will always be reduced from text sample after reposition. Value
4688             // of adjustment would be different and is calculated in DoSetDataSourcePosition.
4689             if (iTextInvalidTSAfterReposition)
4690             {
4691                 iTextInvalidTSAfterReposition = false;
4692                 MediaClockConverter mcc(1000);
4693                 mcc.update_clock(iDelayAddToNextTextSample);
4694                 uint32 durationDelayInMediaTimeScale =
4695                     mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(trackid));
4696                 if (tsDelta > durationDelayInMediaTimeScale)
4697                 {
4698                     iGau.info[0].ts_delta -= durationDelayInMediaTimeScale;
4699                     tsDelta -= durationDelayInMediaTimeScale;
4700                     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode - RetrieveTrackData(): iTextInvalidTSAfterReposition true"));
4701                 }
4702                 else
4703                 {
4704                     iGau.info[0].ts_delta = 0;
4705                     tsDelta = 0;
4706                 }
4707 
4708                 textmediadata->iTextSampleDuration = iGau.info[0].ts_delta;
4709             }
4710 
4711             // Set sample timestamp in NPT
4712             aTrackPortInfo.iClockConverter->set_clock(iGau.info[0].ts, 0);
4713             textmediadata->iTextSampleTimestampNPT = aTrackPortInfo.iClockConverter->get_converted_ts(1000);
4714 
4715             // Set the length of the text sample
4716             textmediadata->iTextSampleLength = actualdatasize;
4717             if (actualdatasize < 2)
4718             {
4719                 // Sample corrupt
4720                 // A text sample should at least be 2 bytes in size for the text string size
4721                 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR;
4722                 PVUuid erruuid = PVMFFileFormatEventTypesUUID;
4723                 int32 errcode = PVMFFFErrInvalidData;
4724                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData Text sample is less than 2 bytes (size=%d). ReportMP4FFParserErrorEvent(PVMFErrCorrupt)", actualdatasize));
4725 
4726                 ReportMP4FFParserErrorEvent(PVMFErrCorrupt, NULL, &erruuid, &errcode);
4727                 return false;
4728             }
4729 
4730             // Return the unused space from mempool back
4731             if (textmediadata->iTextSampleCapacity > actualdatasize)
4732             {
4733                 // Need to go to the resizable memory pool and free some memory
4734                 uint32 bytestofree = textmediadata->iTextSampleCapacity - actualdatasize;
4735                 // Update the capacity
4736                 media_data_impl->setCapacity(media_data_impl->getCapacity() - bytestofree);
4737                 textmediadata->iTextSampleCapacity -= bytestofree;
4738                 // Set buffer size
4739                 mediadataout->setMediaFragFilledLen(0, refCtrMemFragOut.getCapacity() - bytestofree);
4740                 //resize the fragment
4741                 aTrackPortInfo.iTextMediaDataImplAlloc->ResizeMemoryFragment(mediaDataImplOut);
4742             }
4743 
4744             OsclBinIStreamBigEndian textSampleStream;
4745             textSampleStream.Attach((void *)(textmediadata->iTextSample), textmediadata->iTextSampleLength);
4746 
4747             uint16 textSampleLengthFromSample = 0;
4748             textSampleStream >> textSampleLengthFromSample;
4749 
4750             // Check that the text sample length is less than (total sample length -2)
4751             if (textSampleLengthFromSample > (textmediadata->iTextSampleLength - 2))
4752             {
4753                 // Sample corrupt
4754                 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR;
4755                 PVUuid erruuid = PVMFFileFormatEventTypesUUID;
4756                 int32 errcode = PVMFFFErrInvalidData;
4757                 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));
4758 
4759                 ReportMP4FFParserErrorEvent(PVMFErrCorrupt, NULL, &erruuid, &errcode);
4760                 return false;
4761             }
4762 
4763             //Set string format type, skip first two bytes, they represent
4764             //text sample length
4765             uint8 byte1 = 0;
4766             uint8 byte2 = 0;
4767             if (textmediadata->iTextSampleLength >= 4)
4768             {
4769                 // Only check the marker if there is at least 4 bytes in the text sample
4770                 byte1 = textmediadata->iTextSample[2];
4771                 byte2 = textmediadata->iTextSample[3];
4772             }
4773 
4774             if ((byte1 == PVMF_TIMED_TEXT_UTF_16_MARKER_BYTE_1) &&
4775                     (byte2 == PVMF_TIMED_TEXT_UTF_16_MARKER_BYTE_2))
4776             {
4777                 textmediadata->iFormatType = PVMF_TIMED_TEXT_STRING_FORMAT_UTF16;
4778                 // Skip size & utf-16 marker
4779                 // By being within this IF block, the text sample length should be greater or equal to 4.
4780                 OSCL_ASSERT(textmediadata->iTextSampleLength >= 4);
4781                 if (textmediadata->iTextSampleLength == 4)
4782                 {
4783                     // If there are only 4 bytes and it is UTF-16, the text string is not available
4784                     textmediadata->iTextSample = NULL;
4785                 }
4786                 else
4787                 {
4788                     textmediadata->iTextSample += 4;
4789                 }
4790                 textmediadata->iTextSampleLength -= 4;
4791                 textmediadata->iTextSampleCapacity -= 4;
4792                 // text sample length includes the 0xFEFF marker
4793                 textSampleLengthFromSample -= 2;
4794             }
4795             else
4796             {
4797                 textmediadata->iFormatType = PVMF_TIMED_TEXT_STRING_FORMAT_UTF8;
4798                 // Skip size only
4799                 // By being within this IF block, the text sample length should be greater or equal to 2.
4800                 OSCL_ASSERT(textmediadata->iTextSampleLength >= 2);
4801                 if (textmediadata->iTextSampleLength == 2)
4802                 {
4803                     textmediadata->iTextSample = NULL;
4804                 }
4805                 else
4806                 {
4807                     textmediadata->iTextSample += 2;
4808                 }
4809                 textmediadata->iTextSampleLength -= 2;
4810                 textmediadata->iTextSampleCapacity -= 2;
4811             }
4812 
4813             textmediadata->iTextStringLengthInBytes = textSampleLengthFromSample;
4814         }
4815         else
4816         {
4817             // Set buffer size
4818             mediadataout->setMediaFragFilledLen(0, actualdatasize);
4819             media_data_impl->setCapacity(actualdatasize);
4820             // Return the unused space from mempool back
4821             if (refCtrMemFragOut.getCapacity() > actualdatasize)
4822             {
4823                 // Need to go to the resizable memory pool and free some memory
4824                 aTrackPortInfo.iMediaDataImplAlloc->ResizeMemoryFragment(mediaDataImplOut);
4825             }
4826         }
4827 
4828         // Set the random access point flag if this is the first frame after repositioning
4829         uint32 markerInfo = 0;
4830         if (israndomaccesspt)
4831         {
4832             markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT;
4833         }
4834 
4835         // Save the media data in the trackport info
4836         aTrackPortInfo.iMediaData = mediadataout;
4837 
4838         // Retrieve duration and convert to milliseconds
4839         aTrackPortInfo.iClockConverter->set_clock(tsDelta, 0);
4840 
4841         // Set duration bit in marker info
4842         markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_DURATION_AVAILABLE_BIT;
4843         // Set M bit to 1 always - MP4 FF only outputs complete frames
4844         markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_M_BIT;
4845         // Set No Render bit where applicable
4846         if (oSetNoRenderBit == true)
4847         {
4848             markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_NO_RENDER_BIT;
4849         }
4850         if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_H264_MP4)
4851         {
4852             // Set End-of-NAL bit to 1 always - no NAL fragmentation for now
4853             markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT;
4854         }
4855 
4856         media_data_impl->setMarkerInfo(markerInfo);
4857 
4858         // Retrieve timestamp and convert to milliseconds
4859         aTrackPortInfo.iClockConverter->set_clock(aTrackPortInfo.iTimestamp, 0);
4860         uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000);
4861 
4862         // Set the media data's timestamp
4863         aTrackPortInfo.iMediaData->setTimestamp(timestamp);
4864 
4865         // Set the media data sequence number
4866         aTrackPortInfo.iMediaData->setSeqNum(aTrackPortInfo.iSeqNum);
4867 
4868         //for logging
4869         MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(aTrackPortInfo.iTrackId));
4870         mcc.update_clock(iGau.info[0].ts);
4871 
4872         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));
4873 
4874         // Advance aTrackPortInfo.iTimestamp to the timestamp at the end of the
4875         // all samples in the group, i.e. current duration.
4876         aTrackPortInfo.iTimestamp += tsDelta;
4877         aTrackPortInfo.iClockConverter->set_clock(aTrackPortInfo.iTimestamp, 0);
4878         uint32 timestamp_next = aTrackPortInfo.iClockConverter->get_converted_ts(1000);
4879         uint32 duration_msec = timestamp_next - timestamp;
4880         if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT)
4881         {
4882             aTrackPortInfo.iMediaData->setDuration(duration_text_msec);
4883         }
4884         else
4885         {
4886             aTrackPortInfo.iMediaData->setDuration(duration_msec);
4887         }
4888         // increment media data sequence number
4889         aTrackPortInfo.iSeqNum++;
4890     }
4891     else if (retval == READ_FAILED)
4892     {
4893         // Data could not be read from file
4894         PVUuid erruuid = PVMFFileFormatEventTypesUUID;
4895         int32 errcode = PVMFFFErrFileRead;
4896         ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode);
4897         // Treat this as EOS
4898         aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
4899         return false;
4900     }
4901     else if (retval == INSUFFICIENT_DATA)
4902     {
4903         /*
4904          * We have run out data during playback. This could mean a few things:
4905          * - A pseudo streaming session that has hit a data limit
4906          * - A regular playback session with a sample that has a bad offset.
4907          */
4908         if (download_progress_interface != NULL)
4909         {
4910             if (iDownloadComplete)
4911             {
4912                 // Data could not be read from file
4913                 PVUuid erruuid = PVMFFileFormatEventTypesUUID;
4914                 int32 errcode = PVMFFFErrFileRead;
4915                 ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode);
4916                 // Treat this as EOS
4917                 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
4918                 return false;
4919             }
4920 
4921             if (!autopaused)
4922             {
4923                 uint32 requestedTimestamp = aTrackPortInfo.iTimestamp;
4924                 // If Parser library reported Insufficient data after seek, the requested
4925                 // timestamp here should be TS of sample from new position, so peek the
4926                 // sample.
4927                 if (israndomaccesspt)
4928                 {
4929                     uint32 numSamples = 1;
4930                     MediaMetaInfo info;
4931 
4932                     retval = iMP4FileHandle->peekNextBundledAccessUnits(aTrackPortInfo.iTrackId, &numSamples, &info);
4933                     if (((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK))
4934                             && (numSamples > 0))
4935                     {
4936                         aTrackPortInfo.iClockConverter->set_clock(info.ts, 0);
4937                         requestedTimestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000);
4938                     }
4939                 }
4940 
4941                 if ((NULL != iDataStreamInterface) && (0 != iDataStreamInterface->QueryBufferingCapacity()))
4942                 {
4943                     // if progressive streaming, playResumeNotifcation is guaranteed to be called
4944                     // with the proper download complete state, ignore the current download status
4945                     bool dlcomplete = false;
4946                     download_progress_interface->requestResumeNotification(requestedTimestamp, dlcomplete);
4947                 }
4948                 else
4949                 {
4950                     download_progress_interface->requestResumeNotification(requestedTimestamp, iDownloadComplete);
4951                 }
4952             }
4953             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE;
4954             autopaused = true;
4955             uint32 currentFileSize = 0;
4956             iMP4FileHandle->GetCurrentFileSize(currentFileSize);
4957             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RetrieveTrackData() - Auto Pause Triggered, TS = %d, FileSize=%d",
4958                                                  aTrackPortInfo.iTimestamp, currentFileSize));
4959 
4960 
4961             // check if content is poorly interleaved only for PS
4962             // After repositioning, parser will get INSUFFICIENT_DATA immediately and then the poorlyinterleavedcontent event logic will be excercised.
4963             // To make sure that the reposition behaviour and the playback without interruption behavior are consistent, disable the check for first INSUFFICIENT_DATA after repositioning.
4964             if ((NULL != iDataStreamInterface) && (iPoorlyInterleavedContentEventSent == false) && (!israndomaccesspt))
4965             {
4966                 uint32 cacheSize = 0;
4967                 cacheSize = iDataStreamInterface->QueryBufferingCapacity();
4968                 if (cacheSize)
4969                 {
4970                     uint32 *trackOffset = NULL;
4971                     trackOffset = (uint32*) OSCL_MALLOC(iNodeTrackPortList.size() * sizeof(uint32));
4972                     if (trackOffset == NULL)
4973                     {
4974                         return false;
4975                     }
4976                     int32 retval = EVERYTHING_FINE;
4977                     int32 err = 0;
4978                     OSCL_TRY(err,
4979                              for (uint32 i = 0; i < iNodeTrackPortList.size(); i++)
4980                 {
4981                     // Peek the next sample to get the duration of the last sample
4982                     uint32 numSamples = iNodeTrackPortList[i].iNumSamples;
4983                         MediaMetaInfo* info = NULL;
4984                         info = (MediaMetaInfo*) OSCL_MALLOC(numSamples * sizeof(MediaMetaInfo));
4985                         if (info == NULL)
4986                         {
4987                             OSCL_FREE(trackOffset);
4988                             return false;
4989                         }
4990                         retval = iMP4FileHandle->peekNextBundledAccessUnits(iNodeTrackPortList[i].iTrackId, &numSamples, info);
4991                         if (((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK))
4992                                 && (numSamples > 0))
4993                         {
4994                             int32 offset = 0;
4995 
4996                             if ((iMP4FileHandle->getOffsetByTime(iNodeTrackPortList[i].iTrackId, info[numSamples-1].ts, &offset, 0)) == EVERYTHING_FINE)
4997                             {
4998                                 trackOffset[i] = offset;
4999                             }
5000                             else
5001                             {
5002                                 trackOffset[i] = 0x7FFFFFFF;
5003                                 aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
5004                                 PVUuid erruuid = PVMFFileFormatEventTypesUUID;
5005                                 int32 errcode = PVMFFFErrFileRead;
5006                                 ReportMP4FFParserErrorEvent(PVMFErrResource, NULL, &erruuid, &errcode);
5007                                 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::RetrieveTrackData - getOffsetByTime Failed - TrackId=%d, TS=%d",  iNodeTrackPortList[i].iTrackId, info[numSamples-1].ts));
5008                                 OSCL_FREE(info);
5009                                 OSCL_FREE(trackOffset);
5010                                 return false;
5011                             }
5012                         }
5013                         else
5014                         {
5015                             trackOffset[i] = 0x7FFFFFFF;
5016                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData Peeking next sample failed while determining the min timestamp after repositioning"));
5017                         }
5018                         OSCL_FREE(info);
5019                     }
5020                             );
5021                     OSCL_FIRST_CATCH_ANY(err, return PVMFErrNoMemory);
5022 
5023                     uint32 maxOffsetDiff = 0;
5024                     for (uint32 ii = 0; ii < iNodeTrackPortList.size(); ii++)
5025                     {
5026                         if (trackOffset[ii] != 0x7FFFFFFF)
5027                         {
5028                             uint32 offsetDiff = 0;
5029                             for (uint32 j = ii + 1; j < iNodeTrackPortList.size(); j++)
5030                             {
5031                                 if (trackOffset[j] != 0x7FFFFFFF)
5032                                 {
5033                                     if (trackOffset[ii] > trackOffset[j])
5034                                     {
5035                                         offsetDiff = trackOffset[ii] - trackOffset[j];
5036                                     }
5037                                     else
5038                                     {
5039                                         offsetDiff = trackOffset[j] - trackOffset[ii];
5040                                     }
5041                                 }
5042 
5043                                 if (offsetDiff > maxOffsetDiff)
5044                                 {
5045                                     maxOffsetDiff = offsetDiff;
5046                                 }
5047                             }
5048                         }
5049                     }
5050 
5051                     if (maxOffsetDiff > cacheSize)
5052                     {
5053                         // The content is poorly interleaved.
5054                         ReportMP4FFParserInfoEvent(PVMFInfoPoorlyInterleavedContent);
5055                         iPoorlyInterleavedContentEventSent = true;
5056                         // @TODO - For now, don't treat this as EOS.
5057                         // aTrackPortInfo.iState=PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
5058                     }
5059                     OSCL_FREE(trackOffset);
5060                 }
5061             }
5062 
5063             return false;
5064         }
5065         else
5066         {
5067             uint32 offset = 0;
5068 #if PVMP4FF_UNDERFLOW_REQUST_READSIZE_NOTIFICATION_PER_TRACK
5069             PVMFStatus status = GetFileOffsetForAutoResume(offset, &aTrackPortInfo);
5070 #else
5071             PVMFStatus status = GetFileOffsetForAutoResume(offset);
5072 #endif
5073             if (status == PVMFSuccess)
5074             {
5075                 //Request for callback
5076                 MP4_ERROR_CODE retVal =
5077                     iMP4FileHandle->RequestReadCapacityNotification(*this, offset);
5078                 if (retVal == EVERYTHING_FINE)
5079                 {
5080                     if (iDownloadComplete == false)
5081                     {
5082                         aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA;
5083                         if (CheckForUnderFlow(&aTrackPortInfo) == PVMFSuccess && iUnderFlowEventReported == false)
5084                         {
5085                             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE;
5086                             autopaused = true;
5087                             if (ReportUnderFlow() != PVMFSuccess)
5088                             {
5089                                 return false;
5090                             }
5091                         }
5092                     }
5093                     else
5094                     {
5095                         // Data could not be read from file
5096                         PVUuid erruuid = PVMFFileFormatEventTypesUUID;
5097                         int32 errcode = PVMFFFErrFileRead;
5098                         ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode);
5099                         // Treat this as EOS
5100                         aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
5101                         return false;
5102                     }
5103                 }
5104                 else
5105                 {
5106                     PVUuid erruuid = PVMFFileFormatEventTypesUUID;
5107                     int32 errcode = PVMFFFErrFileRead;
5108 
5109                     ReportMP4FFParserInfoEvent(PVMFInfoContentTruncated, NULL, &erruuid, &errcode);
5110                     // Treat this as EOS
5111                     aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
5112                 }
5113                 return false;
5114             }
5115             // Data could not be read from file
5116             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR;
5117             PVUuid erruuid = PVMFFileFormatEventTypesUUID;
5118             int32 errcode = PVMFFFErrFileRead;
5119             ReportMP4FFParserErrorEvent(PVMFErrResource, NULL, &erruuid, &errcode);
5120             return false;
5121         }
5122     }
5123     else if (retval == INSUFFICIENT_BUFFER_SIZE)
5124     {
5125         /* Reset the actual size */
5126         if (actualdatasize > aTrackPortInfo.iTrackMaxDataSize)
5127         {
5128             /* We will attempt to retrieve this sample again with a new max size */
5129             aTrackPortInfo.iTrackMaxDataSize = actualdatasize;
5130             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRACKMAXDATASIZE_RESIZE;
5131             return true;
5132         }
5133         /* Error */
5134         return false;
5135     }
5136     else
5137     {
5138         // Parsing error
5139         aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_ERROR;
5140         PVUuid erruuid;
5141         int32 errcode;
5142         if (!MapMP4ErrorCodeToEventCode(retval, erruuid, errcode))
5143         {
5144             erruuid = PVMFFileFormatEventTypesUUID;
5145             errcode = PVMFFFErrInvalidData;
5146         }
5147         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::RetrieveTrackData ReportMP4FFParserErrorEvent(PVMFErrCorrupt)"));
5148 
5149         ReportMP4FFParserErrorEvent(PVMFErrCorrupt, NULL, &erruuid, &errcode);
5150         return false;
5151     }
5152 
5153     if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_H264_MP4)
5154     {
5155         // Check that the media frag group has been allocated
5156         OSCL_ASSERT(mediadatafraggroup.GetRep() != NULL);
5157         if (GenerateAVCNALGroup(aTrackPortInfo, mediadatafraggroup) == false)
5158         {
5159             //This means that this AVC frame is corrupt, do not send it downstream
5160             //We do not need to declare EOS here, let us keep going
5161             //may be succeeding samples are ok
5162             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SKIP_CORRUPT_SAMPLE;
5163             return false;
5164         }
5165         else
5166         {
5167             return true;
5168         }
5169     }
5170     else if ((aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_MPEG4_AUDIO)
5171              && (oIsAACFramesFragmented))
5172     {
5173         // Check that the media frag group has been allocated
5174         OSCL_ASSERT(mediadatafraggroup.GetRep() != NULL);
5175         return GenerateAACFrameFrags(aTrackPortInfo, mediadatafraggroup);
5176     }
5177     else if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT)
5178     {
5179         // Check if the text sample entry needs to be set
5180         PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*) refCtrMemFragOut.getMemFrag().ptr;
5181         UpdateTextSampleEntry(aTrackPortInfo, iGau.info[0].sample_info, *textmediadata);
5182         return true;
5183     }
5184     else
5185     {
5186         return true;
5187     }
5188 }
5189 
5190 
SendTrackData(PVMP4FFNodeTrackPortInfo & aTrackPortInfo)5191 bool PVMFMP4FFParserNode::SendTrackData(PVMP4FFNodeTrackPortInfo& aTrackPortInfo)
5192 {
5193     if (iPortDataLog)
5194     {
5195         LogMediaData(aTrackPortInfo.iMediaData, aTrackPortInfo.iPortInterface);
5196     }
5197 
5198     // if going reverse, dump all non-video data.
5199     if (iParseVideoOnly && (iMP4FileHandle->getTrackMediaType(aTrackPortInfo.iTrackId) != MEDIA_TYPE_VISUAL))
5200     {
5201         // Don't need the ref to iMediaData so unbind it
5202         aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK;
5203         aTrackPortInfo.iMediaData.Unbind();
5204         return false;
5205     }
5206 
5207     // Set the track specific config info
5208     aTrackPortInfo.iMediaData->setFormatSpecificInfo(aTrackPortInfo.iFormatSpecificConfig);
5209 
5210     aTrackPortInfo.iMediaData->setStreamID(iStreamID);
5211 
5212     // Send frame to downstream node via port
5213     PVMFSharedMediaMsgPtr mediaMsgOut;
5214     convertToPVMFMediaMsg(mediaMsgOut, aTrackPortInfo.iMediaData);
5215     if (aTrackPortInfo.iPortInterface->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
5216     {
5217         aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DESTFULL;
5218         return false;
5219     }
5220 
5221     // Don't need the ref to iMediaData so unbind it
5222     aTrackPortInfo.iMediaData.Unbind();
5223     return true;
5224 }
5225 
GenerateAACFrameFrags(PVMP4FFNodeTrackPortInfo & aTrackPortInfo,OsclSharedPtr<PVMFMediaDataImpl> & aMediaFragGroup)5226 bool PVMFMP4FFParserNode::GenerateAACFrameFrags(PVMP4FFNodeTrackPortInfo& aTrackPortInfo, OsclSharedPtr<PVMFMediaDataImpl>& aMediaFragGroup)
5227 {
5228     OSCL_ASSERT(aTrackPortInfo.iMediaData.GetRep() != NULL);
5229     OsclSharedPtr<PVMFMediaDataImpl> mediaDataIn;
5230     if (aTrackPortInfo.iMediaData->getMediaDataImpl(mediaDataIn) == false)
5231     {
5232         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::GenerateAACFrameFrags() Retrieving media data impl failed"));
5233         return false;
5234     }
5235 
5236     OSCL_ASSERT(aMediaFragGroup.GetRep() != NULL);
5237     aMediaFragGroup->setMarkerInfo(mediaDataIn->getMarkerInfo());
5238 
5239     OsclRefCounterMemFrag memFragIn;
5240     aTrackPortInfo.iMediaData->getMediaFragment(0, memFragIn);
5241     OsclRefCounter* refCntIn = memFragIn.getRefCounter();
5242 
5243     uint8* sample = (uint8*)(memFragIn.getMemFrag().ptr);
5244     int32 samplesize = (int32)(memFragIn.getMemFrag().len);
5245 
5246     OsclBinIStreamBigEndian sampleStream;
5247     sampleStream.Attach(memFragIn.getMemFrag().ptr, memFragIn.getMemFrag().len);
5248 
5249     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()));
5250 
5251     MediaMetaInfo *iInfo = NULL;
5252     bool appended_data = false;
5253     uint32 ii = 0;
5254 
5255     // While we still have data to append AND we haven't run out of media samples
5256     while ((samplesize > 0) && (ii < iGau.numMediaSamples))
5257     {
5258         iInfo = iGau.getInfo(ii);
5259         if (iInfo)
5260         {
5261             if (iInfo->len > 0)
5262             {
5263                 // Subtract the current sample from the total size
5264                 samplesize -= iInfo->len;
5265 
5266                 // Create memory frag to append
5267                 OsclMemoryFragment memFrag;
5268                 memFrag.ptr = sample;
5269                 memFrag.len = iInfo->len;
5270 
5271                 // Append the frag to the group
5272                 refCntIn->addRef();
5273                 OsclRefCounterMemFrag refCountMemFragOut(memFrag, refCntIn, 0);
5274                 aMediaFragGroup->appendMediaFragment(refCountMemFragOut);
5275 
5276                 sampleStream.seekFromCurrentPosition(memFrag.len);
5277                 sample += memFrag.len;
5278 
5279                 // Set flag to show that that we have appended at least one frag
5280                 appended_data = true;
5281 
5282             }  // End of if (iInfo->len > 0)
5283         } // End of if (iInfo) not NULL
5284         ii++;
5285         iInfo = NULL;
5286     }
5287 
5288     if (appended_data)    // If we have appended at least one frag to this group, then package and send
5289     {
5290         PVMFSharedMediaDataPtr aacFragGroup;
5291         aacFragGroup = PVMFMediaData::createMediaData(aMediaFragGroup, aTrackPortInfo.iMediaData->getMessageHeader());
5292         aacFragGroup->setSeqNum(aTrackPortInfo.iMediaData->getSeqNum());
5293         aacFragGroup->setTimestamp(aTrackPortInfo.iMediaData->getTimestamp());
5294         aacFragGroup->setFormatSpecificInfo(aTrackPortInfo.iFormatSpecificConfig);
5295 
5296         // Replace the track's output media data with the frag group one
5297         aTrackPortInfo.iMediaData = aacFragGroup;
5298 
5299         // Return success
5300         return true;
5301     }
5302     else
5303     {
5304         return false; // No frag's appended ...
5305     }
5306 }
5307 
GenerateAVCNALGroup(PVMP4FFNodeTrackPortInfo & aTrackPortInfo,OsclSharedPtr<PVMFMediaDataImpl> & aMediaFragGroup)5308 bool PVMFMP4FFParserNode::GenerateAVCNALGroup(PVMP4FFNodeTrackPortInfo& aTrackPortInfo, OsclSharedPtr<PVMFMediaDataImpl>& aMediaFragGroup)
5309 {
5310     OSCL_ASSERT(aTrackPortInfo.iMediaData.GetRep() != NULL);
5311     OsclSharedPtr<PVMFMediaDataImpl> mediaDataIn;
5312     if (aTrackPortInfo.iMediaData->getMediaDataImpl(mediaDataIn) == false)
5313     {
5314         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::GenerateAVCNALGroup() Retrieving media data impl failed"));
5315         return false;
5316     }
5317 
5318     OSCL_ASSERT(aMediaFragGroup.GetRep() != NULL);
5319 
5320     // Set End-of-NAL bit to 1 always - no NAL fragmentation for now
5321     uint32  markerInfo = (mediaDataIn->getMarkerInfo()) | PVMF_MEDIA_DATA_MARKER_INFO_END_OF_NAL_BIT;
5322     aMediaFragGroup->setMarkerInfo(markerInfo);
5323 
5324     OsclRefCounterMemFrag memFragIn;
5325     aTrackPortInfo.iMediaData->getMediaFragment(0, memFragIn);
5326     OsclRefCounter* refCntIn = memFragIn.getRefCounter();
5327 
5328     uint8* sample = (uint8*)(memFragIn.getMemFrag().ptr);
5329     int32 samplesize = (int32)(memFragIn.getMemFrag().len);
5330     uint32 nallengthsize = iMP4FileHandle->getAVCNALLengthSize(aTrackPortInfo.iTrackId);
5331 
5332     OsclBinIStreamBigEndian sampleStream;
5333     sampleStream.Attach(memFragIn.getMemFrag().ptr, memFragIn.getMemFrag().len);
5334 
5335     int32 numNAL = 0;
5336     while (samplesize > 0)
5337     {
5338         int32 nallen = 0;
5339         if (GetAVCNALLength(sampleStream, nallengthsize, nallen))
5340         {
5341             sample += nallengthsize;
5342             samplesize -= nallengthsize;
5343 
5344             if ((nallen < 0) || (nallen > samplesize))
5345             {
5346                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - Corrupt Sample - SeqNum=%d, SampleSize=%d, NALSize=%d, TS=%d",
5347                                                         aTrackPortInfo.iMediaData->getSeqNum(), samplesize, nallen,
5348                                                         aTrackPortInfo.iMediaData->getTimestamp()));
5349                 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()));
5350                 //ignore corrupt samples / nals
5351                 return true;
5352             }
5353 
5354             if (nallen > 0)
5355             {
5356                 OsclMemoryFragment memFrag;
5357                 memFrag.ptr = sample;
5358                 memFrag.len = nallen;
5359 
5360                 refCntIn->addRef();
5361                 OsclRefCounterMemFrag refCountMemFragOut(memFrag, refCntIn, 0);
5362                 aMediaFragGroup->appendMediaFragment(refCountMemFragOut);
5363 
5364                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, "	PVMFMP4FFParserNode::GenerateAVCNALGroup - SN=%d, TS=%d, SS-NALSize=%d, NALSize=%d, NALNum=%d",
5365                                                         aTrackPortInfo.iMediaData->getSeqNum(),
5366                                                         aTrackPortInfo.iMediaData->getTimestamp(),
5367                                                         samplesize - nallen,
5368                                                         nallen,
5369                                                         numNAL));
5370 
5371                 sampleStream.seekFromCurrentPosition(nallen);
5372                 numNAL++;
5373             }
5374             sample += nallen;
5375             samplesize -= nallen;
5376         }
5377         else
5378         {
5379             return false;
5380         }
5381     }
5382 
5383     //check to see if we added any memfrags
5384     if (aMediaFragGroup->getNumFragments() == 0)
5385     {
5386         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - No Valid NALs - SeqNum=%d, SampleSize=%d, TS=%d",
5387                                                 aTrackPortInfo.iMediaData->getSeqNum(), memFragIn.getMemFrag().len,
5388                                                 aTrackPortInfo.iMediaData->getTimestamp()));
5389         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - No Valid NALs - SeqNum=%d, Size=%d, TS=%d",
5390                                        aTrackPortInfo.iMediaData->getSeqNum(),
5391                                        memFragIn.getMemFrag().len,
5392                                        aTrackPortInfo.iMediaData->getTimestamp()));
5393         //ignore corrupt samples / nals
5394         return false;
5395     }
5396 
5397     PVMFSharedMediaDataPtr avcNALGroup;
5398     avcNALGroup = PVMFMediaData::createMediaData(aMediaFragGroup, aTrackPortInfo.iMediaData->getMessageHeader());
5399     avcNALGroup->setSeqNum(aTrackPortInfo.iMediaData->getSeqNum());
5400     avcNALGroup->setTimestamp(aTrackPortInfo.iMediaData->getTimestamp());
5401     avcNALGroup->setFormatSpecificInfo(aTrackPortInfo.iFormatSpecificConfig);
5402 
5403     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC_AVC((0, "PVMFMP4FFParserNode::GenerateAVCNALGroup - SN=%d, SS=%d, NumNAL=%d, TS=%d, Marker=0x%x",
5404                                             avcNALGroup->getSeqNum(),
5405                                             memFragIn.getMemFrag().len,
5406                                             numNAL,
5407                                             avcNALGroup->getTimestamp(),
5408                                             avcNALGroup->getMarkerInfo()));
5409 
5410     // Replace the track's output media data with the frag group one
5411     aTrackPortInfo.iMediaData = avcNALGroup;
5412 
5413     return true;
5414 }
5415 
GetAVCNALLength(OsclBinIStreamBigEndian & stream,uint32 & lengthSize,int32 & len)5416 bool PVMFMP4FFParserNode::GetAVCNALLength(OsclBinIStreamBigEndian& stream, uint32& lengthSize, int32& len)
5417 {
5418     len = 0;
5419     if (lengthSize == 1)
5420     {
5421         uint8 len8 = 0;
5422         stream >> len8;
5423         len = (int32)(len8);
5424         return true;
5425     }
5426     else if (lengthSize == 2)
5427     {
5428         uint16 len16 = 0;
5429         stream >> len16;
5430         len = (int32)(len16);
5431         return true;
5432     }
5433     else if (lengthSize == 4)
5434     {
5435         stream >> len;
5436         return true;
5437     }
5438     return false;
5439 }
5440 
UpdateTextSampleEntry(PVMP4FFNodeTrackPortInfo & aTrackPortInfo,uint32 aEntryIndex,PVMFTimedTextMediaData & aTextMediaData)5441 bool PVMFMP4FFParserNode::UpdateTextSampleEntry(PVMP4FFNodeTrackPortInfo& aTrackPortInfo, uint32 aEntryIndex, PVMFTimedTextMediaData& aTextMediaData)
5442 {
5443     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() In"));
5444 
5445     // Check if the text sample entry hasn't be set or
5446     // it is different from the previous one
5447     if (aTrackPortInfo.iCurrentTextSampleEntry.GetRep() == NULL || aTrackPortInfo.iCurrentTextSampleEntryIndex != aEntryIndex)
5448     {
5449         // Retrieve the text sample entry and save as this track's format specific info
5450         TextSampleEntry* textsampleentry = NULL;
5451         // NOTE: MP4 API returns the base class pointer SampleEntry but doing a cast since the pointer returned
5452         // is a pointer to a TextSampleEntry. Dangerous but needs to be fixed first in the MP4 FF lib.
5453         textsampleentry = (TextSampleEntry*)iMP4FileHandle->getTextSampleEntryAt(aTrackPortInfo.iTrackId, aEntryIndex);
5454 
5455         if (textsampleentry == NULL)
5456         {
5457             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Text sample sample index %d could not be retrieved", aEntryIndex));
5458             return false;
5459         }
5460 
5461         // Create shared pointer for the text sample entry using OsclMemAllocator
5462         int32 errcode = 0;
5463         OsclSharedPtr<PVMFTimedTextSampleEntry> tmp_shared_tse;
5464         OSCL_TRY(errcode, tmp_shared_tse = PVMFTimedTextSampleEntryUtil::CreatePVMFTimedTextSampleEntry());
5465         OSCL_FIRST_CATCH_ANY(errcode,
5466                              PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Memory for PVMFTimedTextSampleEntry shared pointer could not be allocated"));
5467                              return false);
5468 
5469         OSCL_ASSERT(tmp_shared_tse.GetRep() != NULL);
5470         PVMFTimedTextSampleEntry* textse_ptr = tmp_shared_tse.GetRep();
5471 
5472         // Copy the data from the text sample entry
5473         textse_ptr->iDisplayFlags = textsampleentry->getDisplayFlags();
5474         textse_ptr->iHorizontalJustification = textsampleentry->getHorzJustification();
5475         textse_ptr->iVerticalJustification = textsampleentry->getVertJustification();
5476         uint8* backcolor = textsampleentry->getBackgroundColourRGBA();
5477         if (backcolor)
5478         {
5479             oscl_memcpy(textse_ptr->iBackgroundRGBA, backcolor, PVMFTIMEDTEXT_RGBA_ARRAYSIZE*sizeof(uint8));
5480         }
5481 
5482         // Copy box info
5483         textse_ptr->iBoxTop = textsampleentry->getBoxTop();
5484         textse_ptr->iBoxLeft = textsampleentry->getBoxLeft();
5485         textse_ptr->iBoxBottom = textsampleentry->getBoxBottom();
5486         textse_ptr->iBoxRight = textsampleentry->getBoxRight();
5487 
5488         // Copy style info
5489         textse_ptr->iStyleStartChar = textsampleentry->getStartChar();
5490         textse_ptr->iStyleEndChar = textsampleentry->getEndChar();
5491         textse_ptr->iStyleFontID = textsampleentry->getFontID();
5492         textse_ptr->iStyleFontStyleFlags = textsampleentry->getFontStyleFlags();
5493         textse_ptr->iStyleFontSize = textsampleentry->getfontSize();
5494         uint8* textcolor = textsampleentry->getTextColourRGBA();
5495         if (textcolor)
5496         {
5497             oscl_memcpy(textse_ptr->iStyleTextColorRGBA, textcolor, PVMFTIMEDTEXT_RGBA_ARRAYSIZE*sizeof(uint8));
5498         }
5499 
5500         // Copy font record info
5501         textse_ptr->iFontEntryCount = textsampleentry->getFontListSize();
5502 
5503         if (textse_ptr->iFontEntryCount > 0)
5504         {
5505             // Allocate memory for the font record list
5506             errcode = 0;
5507             OSCL_TRY(errcode, textse_ptr->iFontRecordList = OSCL_ARRAY_NEW(PVMFTimedTextFontRecord, textse_ptr->iFontEntryCount));
5508             OSCL_FIRST_CATCH_ANY(errcode,
5509                                  PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Memory for PVMFTimedTextFontRecord list could not be allocated"));
5510                                  return false);
5511             errcode = 0;
5512             OSCL_TRY(errcode,
5513                      for (uint16 i = 0; i < textse_ptr->iFontEntryCount; ++i)
5514         {
5515             FontRecord* fontrec = textsampleentry->getFontRecordAt(i);
5516                 if (fontrec)
5517                 {
5518                     textse_ptr->iFontRecordList[i].iFontID = fontrec->getFontID();
5519                     textse_ptr->iFontRecordList[i].iFontNameLength = fontrec->getFontLength();
5520                     if (textse_ptr->iFontRecordList[i].iFontNameLength > 0)
5521                     {
5522                         // Allocate memory for the font name
5523                         textse_ptr->iFontRecordList[i].iFontName = OSCL_ARRAY_NEW(uint8, textse_ptr->iFontRecordList[i].iFontNameLength + 1);
5524 
5525                         // Copy the font name string
5526                         oscl_strncpy((char*)(textse_ptr->iFontRecordList[i].iFontName), (char*)(fontrec->getFontName()), textse_ptr->iFontRecordList[i].iFontNameLength + 1);
5527                         textse_ptr->iFontRecordList[i].iFontName[textse_ptr->iFontRecordList[i].iFontNameLength] = '\0';
5528                     }
5529                 }
5530                 else
5531                 {
5532                     textse_ptr->iFontRecordList[i].iFontID = 0;
5533                     textse_ptr->iFontRecordList[i].iFontNameLength = 0;
5534                     textse_ptr->iFontRecordList[i].iFontName = NULL;
5535                 }
5536             }
5537                     );
5538             OSCL_FIRST_CATCH_ANY(errcode,
5539                                  PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Memory for font name could not be allocated"));
5540                                  return false);
5541         }
5542         // Save the text track's text sample entry
5543         aTrackPortInfo.iCurrentTextSampleEntry = tmp_shared_tse;
5544         // Save the state so text sample entry is only read when changed or not set yet
5545         aTrackPortInfo.iCurrentTextSampleEntryIndex = aEntryIndex;
5546     }
5547 
5548     // Set the text sample entry to current one for this track
5549     aTextMediaData.iTextSampleEntry = aTrackPortInfo.iCurrentTextSampleEntry;
5550 
5551     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::UpdateTextSampleEntry() Out"));
5552     return true;
5553 }
5554 
SendEndOfTrackCommand(PVMP4FFNodeTrackPortInfo & aTrackPortInfo)5555 bool PVMFMP4FFParserNode::SendEndOfTrackCommand(PVMP4FFNodeTrackPortInfo& aTrackPortInfo)
5556 {
5557     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SendEndOfTrackCommand() In"));
5558 
5559     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
5560 
5561     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);
5562 
5563     // Set the sequence number
5564     uint32 seqNum = aTrackPortInfo.iSeqNum;
5565     sharedMediaCmdPtr->setSeqNum(seqNum);
5566     aTrackPortInfo.iSeqNum++;
5567 
5568     //set stream id
5569     sharedMediaCmdPtr->setStreamID(iStreamID);
5570 
5571     // Set the timestamp
5572     // Retrieve timestamp and convert to milliseconds
5573     aTrackPortInfo.iClockConverter->update_clock(aTrackPortInfo.iTimestamp);
5574     uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000);
5575     sharedMediaCmdPtr->setTimestamp(timestamp);
5576     //EOS timestamp(aTrackPortInfo.iTimestamp)is considered while deciding the iResumeTimeStamp in the mediaoutput node
5577     //therefore its length should also be considered while making decision to forward or drop the packet
5578     //at the mediaoutput node.
5579     if (aTrackPortInfo.iFormatTypeInteger == PVMF_MP4_PARSER_NODE_3GPP_TIMED_TEXT &&
5580             iEOTForTextSentToMIO)
5581     {
5582         iEOTForTextSentToMIO = false;
5583         if (iSetTextSampleDurationZero)
5584         {
5585             sharedMediaCmdPtr->setDuration(0);
5586         }
5587     }
5588     else
5589     {
5590         //EOS timestamp(aTrackPortInfo.iTimestamp)is considered while deciding the iResumeTimeStamp in the mediaoutput node
5591         //therefore its length should also be considered while making decision to forward or drop the packet
5592         //at the mediaoutput node.
5593         sharedMediaCmdPtr->setDuration(PVMP4FF_DEFAULT_EOS_DURATION_IN_SEC *(aTrackPortInfo.iClockConverter->get_timescale()));
5594     }
5595 
5596     PVMFSharedMediaMsgPtr mediaMsgOut;
5597     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
5598     if (aTrackPortInfo.iPortInterface->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
5599     {
5600         return false;
5601     }
5602 
5603     aTrackPortInfo.iTimestamp += (PVMP4FF_DEFAULT_EOS_DURATION_IN_SEC * aTrackPortInfo.iClockConverter->get_timescale());
5604 
5605     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::SendEndOfTrackCommand - Mime=%s, StreamID=%d, TrackID=%d, TS=%d, SEQNUM=%d",
5606                                          aTrackPortInfo.iMimeType.get_cstr(),
5607                                          iStreamID,
5608                                          aTrackPortInfo.iTrackId,
5609                                          timestamp,
5610                                          seqNum));
5611 
5612     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SendEndOfTrackCommand() Out"));
5613     return true;
5614 }
5615 
5616 
QueuePortActivity(const PVMFPortActivity & aActivity)5617 void PVMFMP4FFParserNode::QueuePortActivity(const PVMFPortActivity &aActivity)
5618 {
5619     //queue a new port activity event
5620     int32 err;
5621     OSCL_TRY(err, iPortActivityQueue.push_back(aActivity););
5622     if (err != OsclErrNone)
5623     {
5624         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::QueuePortActivity() Error push_back to queue failed"));
5625         ReportMP4FFParserErrorEvent(PVMFErrPortProcessing, (OsclAny*)(aActivity.iPort));
5626     }
5627     else
5628     {
5629         //wake up the AO to process the port activity event.
5630         RunIfNotReady();
5631     }
5632 }
5633 
5634 
HandlePortActivity(const PVMFPortActivity & aActivity)5635 void PVMFMP4FFParserNode::HandlePortActivity(const PVMFPortActivity &aActivity)
5636 {
5637     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::HandlePortActivity() In"));
5638 
5639     //A port is reporting some activity or state change.  This code
5640     //figures out whether we need to queue a processing event
5641     //for the AO, and/or report a node event to the observer.
5642 
5643     switch (aActivity.iType)
5644     {
5645         case PVMF_PORT_ACTIVITY_CREATED:
5646             //Report port created info event to the node.
5647             ReportMP4FFParserInfoEvent(PVMFInfoPortCreated, (OsclAny*)aActivity.iPort);
5648             break;
5649 
5650         case PVMF_PORT_ACTIVITY_DELETED:
5651             //Report port deleted info event to the node.
5652             ReportMP4FFParserInfoEvent(PVMFInfoPortDeleted, (OsclAny*)aActivity.iPort);
5653             //Purge any port activity events already queued
5654             //for this port.
5655             {
5656                 for (uint32 i = 0; i < iPortActivityQueue.size();)
5657                 {
5658                     if (iPortActivityQueue[i].iPort == aActivity.iPort)
5659                     {
5660                         iPortActivityQueue.erase(&iPortActivityQueue[i]);
5661                     }
5662                     else
5663                     {
5664                         i++;
5665                     }
5666                 }
5667             }
5668             break;
5669 
5670         case PVMF_PORT_ACTIVITY_CONNECT:
5671             //nothing needed.
5672             break;
5673 
5674         case PVMF_PORT_ACTIVITY_DISCONNECT:
5675             //nothing needed.
5676             break;
5677 
5678         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
5679             //An outgoing message was queued on this port.
5680             //We only need to queue a port activity event on the
5681             //first message.  Additional events will be queued during
5682             //the port processing as needed.
5683             if (aActivity.iPort->OutgoingMsgQueueSize() == 1)
5684             {
5685                 QueuePortActivity(aActivity);
5686             }
5687             break;
5688 
5689         case PVMF_PORT_ACTIVITY_INCOMING_MSG:
5690             // Incoming msg not supported
5691             break;
5692 
5693         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_BUSY:
5694             //Outgoing queue is now busy.
5695             //No action is needed here-- the node checks for
5696             //outgoing queue busy as needed during data processing.
5697             break;
5698 
5699         case PVMF_PORT_ACTIVITY_OUTGOING_QUEUE_READY:
5700             //Outgoing queue was previously busy, but is now ready.
5701             //We may need to schedule new processing events depending on the port type.
5702 
5703             switch (aActivity.iPort->GetPortTag())
5704             {
5705                 case PVMF_MP4FFPARSERNODE_PORT_TYPE_OUTPUT:
5706                 {
5707                     // Find the trackportinfo for the port
5708                     int32 i = 0;
5709                     int32 maxtrack = iNodeTrackPortList.size();
5710                     while (i < maxtrack)
5711                     {
5712                         if (iNodeTrackPortList[i].iPortInterface == aActivity.iPort)
5713                         {
5714                             // Found the element.
5715                             switch (iNodeTrackPortList[i].iState)
5716                             {
5717                                 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_DESTFULL:
5718                                 {
5719                                     // Change the track state to only send the data
5720                                     iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA;
5721                                     // Activate the node to process the track state change
5722                                     RunIfNotReady();
5723                                 }
5724                                 break;
5725 
5726                                 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_SEND_ENDOFTRACK:
5727                                 {
5728                                     //wakeup the AO to try and send the end-of-track again.
5729                                     RunIfNotReady();
5730                                 }
5731                                 break;
5732 
5733                                 default:
5734                                     break;
5735                             }
5736                         }
5737                         ++i;
5738                     }
5739                 }
5740                 break;
5741 
5742                 default:
5743                     break;
5744             }
5745             break;
5746 
5747         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_BUSY:
5748             // The connected port has become busy (its incoming queue is
5749             // busy).
5750             // No action is needed here-- the port processing code
5751             // checks for connected port busy during data processing.
5752             break;
5753 
5754         case PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY:
5755             // The connected port has transitioned from Busy to Ready.
5756             // It's time to start processing outgoing messages again.
5757             if (aActivity.iPort->OutgoingMsgQueueSize() > 0)
5758             {
5759                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
5760                                 (0, "PVMFMP4FFParserNode::HandlePortActivity() Connected port is now ready Port=0x%x",
5761                                  aActivity.iPort));
5762 
5763                 PVMFPortActivity activity(aActivity.iPort, PVMF_PORT_ACTIVITY_OUTGOING_MSG);
5764                 QueuePortActivity(activity);
5765             }
5766             break;
5767 
5768         default:
5769             break;
5770     }
5771 }
5772 
5773 
ProcessPortActivity()5774 void PVMFMP4FFParserNode::ProcessPortActivity()
5775 {
5776     //called by the AO to process a port activity message
5777     //Pop the queue...
5778     PVMFPortActivity activity(iPortActivityQueue.front());
5779     iPortActivityQueue.erase(&iPortActivityQueue.front());
5780 
5781     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ProcessPortActivity() In"));
5782 
5783     PVMFStatus status = PVMFSuccess;
5784     switch (activity.iType)
5785     {
5786         case PVMF_PORT_ACTIVITY_OUTGOING_MSG:
5787             status = ProcessOutgoingMsg(activity.iPort);
5788             //Re-queue the port activity event as long as there's
5789             //more data to process and it isn't in a Busy state.
5790             if (status != PVMFErrBusy && activity.iPort->OutgoingMsgQueueSize() > 0)
5791             {
5792                 QueuePortActivity(activity);
5793             }
5794             break;
5795 
5796         default:
5797             break;
5798 
5799     }
5800 
5801     //Report any unexpected failure in port processing...
5802     //(the InvalidState error happens when port input is suspended,
5803     //so don't report it.)
5804     if (status != PVMFErrBusy && status != PVMFSuccess && status != PVMFErrInvalidState)
5805     {
5806         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::ProcessPortActivity() Error unexpected failure Port=0x%x Type=0x%x",
5807                         activity.iPort, activity.iType));
5808 
5809         ReportMP4FFParserErrorEvent(PVMFErrPortProcessing);
5810     }
5811 }
5812 
5813 
ProcessIncomingMsg(PVMFPortInterface *)5814 PVMFStatus PVMFMP4FFParserNode::ProcessIncomingMsg(PVMFPortInterface* /*aPort*/)
5815 {
5816     // No incoming msg supported
5817     return PVMFSuccess;
5818 }
5819 
5820 
ProcessOutgoingMsg(PVMFPortInterface * aPort)5821 PVMFStatus PVMFMP4FFParserNode::ProcessOutgoingMsg(PVMFPortInterface* aPort)
5822 {
5823     //Called by the AO to process one message off the outgoing
5824     //message queue for the given port.  This routine will
5825     //try to send the data to the connected port.
5826     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::ProcessOutgoingMsg() In aPort=0x%x", aPort));
5827 
5828     PVMFStatus status = aPort->Send();
5829     if (status == PVMFErrBusy)
5830     {
5831         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, (0, "PVMFMP4FFParserNode::ProcessOutgoingMsg() Connected port is in busy state"));
5832     }
5833 
5834     return status;
5835 }
5836 
ResetAllTracks()5837 void PVMFMP4FFParserNode::ResetAllTracks()
5838 {
5839     for (uint32 i = 0; i < iNodeTrackPortList.size(); ++i)
5840     {
5841         iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_UNINITIALIZED;
5842         iNodeTrackPortList[i].iMediaData.Unbind();
5843         iNodeTrackPortList[i].iSeqNum = 0;
5844         iNodeTrackPortList[i].iPortInterface->ClearMsgQueues();
5845         iNodeTrackPortList[i].iCurrentTextSampleEntry.Unbind();
5846     }
5847     iPortActivityQueue.clear();
5848 }
5849 
5850 
ReleaseAllPorts()5851 bool PVMFMP4FFParserNode::ReleaseAllPorts()
5852 {
5853     while (!iNodeTrackPortList.empty())
5854     {
5855         iNodeTrackPortList[0].iPortInterface->Disconnect();
5856         iNodeTrackPortList[0].iMediaData.Unbind();
5857         if (iNodeTrackPortList[0].iPortInterface)
5858         {
5859             OSCL_DELETE(((PVMFMP4FFParserOutPort*)iNodeTrackPortList[0].iPortInterface));
5860         }
5861         if (iNodeTrackPortList[0].iClockConverter)
5862         {
5863             OSCL_DELETE(iNodeTrackPortList[0].iClockConverter);
5864         }
5865         if (iNodeTrackPortList[0].iTrackDataMemoryPool)
5866         {
5867             iNodeTrackPortList[0].iTrackDataMemoryPool->CancelFreeChunkAvailableCallback();
5868             iNodeTrackPortList[0].iTrackDataMemoryPool->removeRef();
5869             iNodeTrackPortList[0].iTrackDataMemoryPool = NULL;
5870         }
5871         if (iNodeTrackPortList[0].iMediaDataImplAlloc)
5872         {
5873             OSCL_DELETE(iNodeTrackPortList[0].iMediaDataImplAlloc);
5874         }
5875         if (iNodeTrackPortList[0].iTextMediaDataImplAlloc)
5876         {
5877             OSCL_DELETE(iNodeTrackPortList[0].iTextMediaDataImplAlloc);
5878         }
5879         if (iNodeTrackPortList[0].iMediaDataMemPool)
5880         {
5881             iNodeTrackPortList[0].iMediaDataMemPool->CancelFreeChunkAvailableCallback();
5882             iNodeTrackPortList[0].iMediaDataMemPool->removeRef();
5883         }
5884         if (iNodeTrackPortList[0].iMediaDataGroupAlloc)
5885         {
5886             iNodeTrackPortList[0].iMediaDataGroupAlloc->removeRef();
5887         }
5888         if (iNodeTrackPortList[0].iMediaDataGroupImplMemPool)
5889         {
5890             iNodeTrackPortList[0].iMediaDataGroupImplMemPool->removeRef();
5891         }
5892         if (iPortDataLog)
5893         {
5894             if (iNodeTrackPortList[0].iBinAppenderPtr.GetRep() != NULL)
5895             {
5896                 iNodeTrackPortList[0].iPortLogger->RemoveAppender(iNodeTrackPortList[0].iBinAppenderPtr);
5897                 iNodeTrackPortList[0].iBinAppenderPtr.Unbind();
5898             }
5899         }
5900         iNodeTrackPortList.erase(iNodeTrackPortList.begin());
5901     }
5902 
5903     return true;
5904 }
5905 
5906 
RemoveAllCommands()5907 void PVMFMP4FFParserNode::RemoveAllCommands()
5908 {
5909     //The command queues are self-deleting, but we want to
5910     //notify the observer of unprocessed commands.
5911     while (!iCurrentCommand.empty())
5912     {
5913         CommandComplete(iCurrentCommand, iCurrentCommand.front(), PVMFFailure);
5914     }
5915 
5916     while (!iInputCommands.empty())
5917     {
5918         CommandComplete(iInputCommands, iInputCommands.front(), PVMFFailure);
5919     }
5920 }
5921 
5922 
CleanupFileSource()5923 void PVMFMP4FFParserNode::CleanupFileSource()
5924 {
5925     iAvailableMetadataKeys.clear();
5926     iMP4ParserNodeMetadataValueCount = 0;
5927     iCPMMetadataKeys.clear();
5928     iVideoDimensionInfoVec.clear();
5929 
5930     if (iDataStreamInterface != NULL)
5931     {
5932         PVInterface* iFace = OSCL_STATIC_CAST(PVInterface*, iDataStreamInterface);
5933         PVUuid uuid = PVMIDataStreamSyncInterfaceUuid;
5934         iDataStreamFactory->DestroyPVMFCPMPluginAccessInterface(uuid, iFace);
5935         iDataStreamInterface = NULL;
5936     }
5937 
5938     if (iOMA2DecryptionBuffer != NULL)
5939     {
5940         OSCL_ARRAY_DELETE(iOMA2DecryptionBuffer);
5941         iOMA2DecryptionBuffer = NULL;
5942     }
5943 
5944     iDownloadComplete = false;
5945     iMP4HeaderSize = 0;
5946     iProgressivelyDownlodable = false;
5947     iCPMSequenceInProgress = false;
5948     iFastTrackSession = false;
5949     iProtectedFile = false;
5950     iExternalDownload = false;
5951     iThumbNailMode = false;
5952 
5953     if (iMP4FileHandle)
5954     {
5955         if (iExternalDownload == true)
5956         {
5957             iMP4FileHandle->DestroyDataStreamForExternalDownload();
5958         }
5959         IMpeg4File::DestroyMP4FileObject(iMP4FileHandle);
5960         iMP4FileHandle = NULL;
5961     }
5962 
5963     if (iFileHandle)
5964     {
5965         OSCL_DELETE(iFileHandle);
5966         iFileHandle = NULL;
5967     }
5968 
5969     iSourceContextDataValid = false;
5970     iUseCPMPluginRegistry = false;
5971     iCPMSourceData.iFileHandle = NULL;
5972     if (iCPMContentAccessFactory != NULL)
5973     {
5974         if (iDecryptionInterface != NULL)
5975         {
5976             iDecryptionInterface->Reset();
5977             /* Remove the decrpytion interface */
5978             PVUuid uuid = PVMFCPMPluginDecryptionInterfaceUuid;
5979             iCPMContentAccessFactory->DestroyPVMFCPMPluginAccessInterface(uuid, iDecryptionInterface);
5980             iDecryptionInterface = NULL;
5981         }
5982         iCPMContentAccessFactory->removeRef();
5983         iCPMContentAccessFactory = NULL;
5984     }
5985     if (iDataStreamFactory != NULL)
5986     {
5987         iDataStreamFactory->removeRef();
5988         iDataStreamFactory = NULL;
5989     }
5990 
5991     oWaitingOnLicense = false;
5992     iPoorlyInterleavedContentEventSent = false;
5993 }
5994 
5995 // From PVMFMP4ProgDownloadSupportInterface
convertSizeToTime(uint32 fileSize,uint32 & timeStamp)5996 int32 PVMFMP4FFParserNode::convertSizeToTime(uint32 fileSize, uint32& timeStamp)
5997 {
5998     if (iMP4FileHandle == NULL)
5999     {
6000         return DEFAULT_ERROR;
6001     }
6002     timeStamp = 0xFFFFFFFF;
6003     if (iNodeTrackPortList.size() <= 0)
6004     {//if track selection is not done, use all the tracks for calculation to avoid deadlock.
6005         int32 iNumTracks = iMP4FileHandle->getNumTracks();
6006         uint32 iIdList[16];
6007         if (iNumTracks != iMP4FileHandle->getTrackIDList(iIdList, iNumTracks))
6008         {
6009             return DEFAULT_ERROR;//PVMFFailure;
6010         }
6011         uint32 track_timestamp = 0xFFFFFFFF;
6012         for (int32 i = 0; i < iNumTracks; i++)
6013         {
6014             uint32 trackID = iIdList[i];
6015             int32 result = iMP4FileHandle->getMaxTrackTimeStamp(trackID, fileSize, track_timestamp);
6016             if (EVERYTHING_FINE == result)
6017             {
6018                 // Convert the timestamp from media timescale to milliseconds
6019                 MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(trackID));
6020                 mcc.update_clock(track_timestamp);
6021                 uint32 track_timeStamp = mcc.get_converted_ts(1000);
6022                 if (track_timeStamp < timeStamp)
6023                 {
6024                     timeStamp = track_timeStamp;
6025                 }
6026                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp, NPT[%d]=%d, TrackTS=%d",
6027                                                      trackID,
6028                                                      timeStamp,
6029                                                      track_timestamp));
6030             }
6031             else
6032             {
6033                 return DEFAULT_ERROR;//PVMFFailure;
6034             }
6035         }
6036         iLastNPTCalcInConvertSizeToTime = timeStamp;
6037         iFileSizeLastConvertedToTime = fileSize;
6038         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime(), FileSize=%d, NPT=%d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime));
6039         return EVERYTHING_FINE;//PVMFSuccess;
6040     }
6041 
6042     //we do not count tracks that have reached EOS
6043     uint32 track_timestamp = 0xFFFFFFFF;
6044     int32 result = EVERYTHING_FINE;
6045     bool oAllTracksHaveReachedEOS = true;
6046 
6047     if (iNodeTrackPortList[0].iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK)
6048     {
6049         //there is atleast one track that has not reached EOS
6050         oAllTracksHaveReachedEOS = false;
6051         result = iMP4FileHandle->getMaxTrackTimeStamp(iNodeTrackPortList[0].iTrackId,
6052                  fileSize,
6053                  track_timestamp);
6054 
6055         if (result)
6056         {
6057             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp Failed, TrackID=%d, Mime=%s",
6058                                                  iNodeTrackPortList[0].iTrackId,
6059                                                  iNodeTrackPortList[0].iMimeType.get_cstr()));
6060             return result;
6061         }
6062         else
6063         {
6064             // Convert the timestamp from media timescale to milliseconds
6065             MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(iNodeTrackPortList[0].iTrackId));
6066             mcc.update_clock(track_timestamp);
6067             timeStamp = mcc.get_converted_ts(1000);
6068             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp, NPT=%d, TrackID=%d, Mime=%s",
6069                                                  timeStamp,
6070                                                  iNodeTrackPortList[0].iTrackId,
6071                                                  iNodeTrackPortList[0].iMimeType.get_cstr()));
6072         }
6073     }
6074 
6075 
6076     for (uint32 ii = 1; ii < iNodeTrackPortList.size(); ++ii)
6077     {
6078         if (iNodeTrackPortList[ii].iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_ENDOFTRACK)
6079         {
6080             //there is atleast one track that has not reached EOS
6081             oAllTracksHaveReachedEOS = false;
6082             result = iMP4FileHandle->getMaxTrackTimeStamp(iNodeTrackPortList[ii].iTrackId,
6083                      fileSize,
6084                      track_timestamp);
6085 
6086             if (result)
6087             {
6088                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp Failed, TrackID=%d, Mime=%s",
6089                                                      iNodeTrackPortList[ii].iTrackId,
6090                                                      iNodeTrackPortList[ii].iMimeType.get_cstr()));
6091                 return result;
6092             }
6093 
6094             // Convert the timestamp from media timescale to milliseconds
6095             MediaClockConverter mcc(iMP4FileHandle->getTrackMediaTimescale(iNodeTrackPortList[ii].iTrackId));
6096             mcc.update_clock(track_timestamp);
6097             track_timestamp = mcc.get_converted_ts(1000);
6098 
6099             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - getMaxTrackTimeStamp, NPT=%d, TrackID=%d, Mime=%s",
6100                                                  track_timestamp,
6101                                                  iNodeTrackPortList[ii].iTrackId,
6102                                                  iNodeTrackPortList[ii].iMimeType.get_cstr()));
6103 
6104             timeStamp = (track_timestamp < timeStamp) ? track_timestamp : timeStamp;
6105         }
6106     }
6107     if (oAllTracksHaveReachedEOS)
6108     {
6109         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime() - All Tracks have Reached EOS"));
6110         //if there are no playing tracks then this method should not even be called
6111         return DEFAULT_ERROR;
6112     }
6113 
6114     iLastNPTCalcInConvertSizeToTime = timeStamp;
6115     iFileSizeLastConvertedToTime = fileSize;
6116     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::convertSizeToTime(), FileSize=%d, NPT=%d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime));
6117     return EVERYTHING_FINE;
6118 }
6119 
setFileSize(const uint32 aFileSize)6120 void PVMFMP4FFParserNode::setFileSize(const uint32 aFileSize)
6121 {
6122     iDownloadFileSize = aFileSize;
6123 }
6124 
setDownloadProgressInterface(PVMFDownloadProgressInterface * download_progress)6125 void PVMFMP4FFParserNode::setDownloadProgressInterface(PVMFDownloadProgressInterface* download_progress)
6126 {
6127     if (download_progress_interface)
6128     {
6129         download_progress_interface->removeRef();
6130     }
6131 
6132     download_progress_interface = download_progress;
6133 
6134     // get the progress clock
6135     download_progress_clock = download_progress_interface->getDownloadProgressClock();
6136 }
6137 
6138 
playResumeNotification(bool aDownloadComplete)6139 void PVMFMP4FFParserNode::playResumeNotification(bool aDownloadComplete)
6140 {
6141     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() In"));
6142 
6143     // If download has completed, unbind the DL progress clock so no more checks occur
6144     iDownloadComplete = aDownloadComplete;
6145     if (aDownloadComplete)
6146     {
6147         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() Download complete to unbind DL progress clock"));
6148         download_progress_clock.Unbind();
6149     }
6150 
6151     // resume playback
6152     if (autopaused)
6153     {
6154         autopaused = false;
6155         for (uint32 ii = 0; ii < iNodeTrackPortList.size(); ++ii)
6156         {
6157             switch (iNodeTrackPortList[ii].iState)
6158             {
6159                 case PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE:
6160                     iNodeTrackPortList[ii].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
6161                     break;
6162 
6163                 default:
6164                     // nothing to do
6165                     break;
6166             }
6167         }
6168 
6169         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::playResumeNotification() - Auto Resume Triggered, FileSize = %d, NPT = %d", iFileSizeLastConvertedToTime, iLastNPTCalcInConvertSizeToTime));
6170         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() Sending PVMFInfoDataReady event"));
6171         // Schedule AO to run again
6172         RunIfNotReady();
6173     }
6174     else if ((iCurrentCommand.empty() == false) &&
6175              (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_INIT))
6176     {
6177         /* Callbacks intiated  as part of node init */
6178         if (iDownloadComplete == true)
6179         {
6180             if (iCPMSequenceInProgress == false)
6181             {
6182                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::playResumeNotification() - Download Complete"));
6183                 /*
6184                  * Can come here only if we are doing PDL / PPB.
6185                  * Init is still pending and download has completed.
6186                  * A few possible scenarios here:
6187                  * - Non-PDL, Non-DRM clip - we are waiting for the complete
6188                  * file to be downloaded before we can parse the movie atom.
6189                  * - OMA1 DRM clip - CPM seq complete, and
6190                  * we were waiting on more data.
6191                  * - OMA2 PDCF DRM clip - were waiting on more data to parse the movie atom,
6192                  * CPM seq not complete since we need contents of movie atom to authorize
6193                  * with CPM
6194                  * - PDL, Non-DRM clip - we were waiting on more data and
6195                  * download has completed
6196                  */
6197                 if (iCPM)
6198                 {
6199                     if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
6200                     {
6201                         PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL;
6202                         if (ParseMP4File(iCurrentCommand,
6203                                          iCurrentCommand.front()))
6204                         {
6205                             if (CheckForOMA2AuthorizationComplete(oma2trackInfo) == PVMFPending)
6206                             {
6207                                 RequestUsage(oma2trackInfo);
6208                                 return;
6209                             }
6210                         }
6211                     }
6212                 }
6213                 CompleteInit(iCurrentCommand, iCurrentCommand.front());
6214             }
6215         }
6216         //Ignore this callback we are waiting on notifydownload complete
6217     }
6218 
6219     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::playResumeNotification() Out"));
6220 }
6221 
notifyDownloadComplete()6222 void PVMFMP4FFParserNode::notifyDownloadComplete()
6223 {
6224     if (!iProgressivelyDownlodable)
6225     {
6226         //in case of non-PDL files, we have to hold back on init complete
6227         //till donwnload is fully complete. So if that is the case, call
6228         //playResumeNotification and this will complete the pending init cmd
6229         playResumeNotification(true);
6230     }
6231 }
6232 
6233 
MapMP4ErrorCodeToEventCode(int32 aMP4ErrCode,PVUuid & aEventUUID,int32 & aEventCode)6234 bool PVMFMP4FFParserNode::MapMP4ErrorCodeToEventCode(int32 aMP4ErrCode, PVUuid& aEventUUID, int32& aEventCode)
6235 {
6236     // Set the UUID to the MP4 FF specific one and change to
6237     // file format one if necessary in the switch statement
6238     aEventUUID = PVMFMP4FFParserEventTypesUUID;
6239 
6240     switch (aMP4ErrCode)
6241     {
6242         case READ_FAILED:
6243             aEventUUID = PVMFFileFormatEventTypesUUID;
6244             aEventCode = PVMFFFErrFileRead;
6245             break;
6246 
6247         case DEFAULT_ERROR:
6248             aEventUUID = PVMFFileFormatEventTypesUUID;
6249             aEventCode = PVMFFFErrMisc;
6250             break;
6251 
6252         case READ_USER_DATA_ATOM_FAILED:
6253             aEventCode = PVMFMP4FFParserErrUserDataAtomReadFailed;
6254             break;
6255 
6256         case READ_MEDIA_DATA_ATOM_FAILED:
6257             aEventCode = PVMFMP4FFParserErrMediaDataAtomReadFailed;
6258             break;
6259 
6260         case READ_MOVIE_ATOM_FAILED:
6261             aEventCode = PVMFMP4FFParserErrMovieAtomReadFailed;
6262             break;
6263 
6264         case READ_MOVIE_HEADER_ATOM_FAILED:
6265             aEventCode = PVMFMP4FFParserErrMovieHeaderAtomReadFailed;
6266             break;
6267 
6268         case READ_TRACK_ATOM_FAILED:
6269             aEventCode = PVMFMP4FFParserErrTrackAtomReadFailed;
6270             break;
6271 
6272         case READ_TRACK_HEADER_ATOM_FAILED:
6273             aEventCode = PVMFMP4FFParserErrTrackHeaderAtomReadFailed;
6274             break;
6275 
6276         case READ_TRACK_REFERENCE_ATOM_FAILED:
6277             aEventCode = PVMFMP4FFParserErrTrackReferenceAtomReadFailed;
6278             break;
6279 
6280         case READ_TRACK_REFERENCE_TYPE_ATOM_FAILED:
6281             aEventCode = PVMFMP4FFParserErrTrackReferenceTypeAtomReadFailed;
6282             break;
6283 
6284         case READ_OBJECT_DESCRIPTOR_ATOM_FAILED:
6285             aEventCode = PVMFMP4FFParserErrObjectDescriptorAtomReadFailed;
6286             break;
6287 
6288         case READ_INITIAL_OBJECT_DESCRIPTOR_FAILED:
6289             aEventCode = PVMFMP4FFParserErrInitialObjectDescriptorReadFailed;
6290             break;
6291 
6292         case READ_OBJECT_DESCRIPTOR_FAILED:
6293             aEventCode = PVMFMP4FFParserErrObjectDescriptorReadFailed;
6294             break;
6295 
6296         case READ_MEDIA_ATOM_FAILED:
6297             aEventCode = PVMFMP4FFParserErrMediaAtomReadFailed;
6298             break;
6299 
6300         case READ_MEDIA_HEADER_ATOM_FAILED:
6301             aEventCode = PVMFMP4FFParserErrMediaHeaderAtomReadFailed;
6302             break;
6303 
6304         case READ_HANDLER_ATOM_FAILED:
6305             aEventCode = PVMFMP4FFParserErrHandlerAtomReadFailed;
6306             break;
6307 
6308         case READ_MEDIA_INFORMATION_ATOM_FAILED:
6309             aEventCode = PVMFMP4FFParserErrMediaInformationAtomReadFailed;
6310             break;
6311 
6312         case READ_MEDIA_INFORMATION_HEADER_ATOM_FAILED:
6313             aEventCode = PVMFMP4FFParserErrMediaInformationHeaderAtomReadFailed;
6314             break;
6315 
6316         case READ_VIDEO_MEDIA_HEADER_ATOM_FAILED:
6317             aEventCode = PVMFMP4FFParserErrVideoMediaHeaderAtomReadFailed;
6318             break;
6319 
6320         case READ_SOUND_MEDIA_HEADER_ATOM_FAILED:
6321             aEventCode = PVMFMP4FFParserErrSoundMediaHeaderAtomReadFailed;
6322             break;
6323 
6324         case READ_HINT_MEDIA_HEADER_ATOM_FAILED:
6325             aEventCode = PVMFMP4FFParserErrHintMediaHeaderAtomReadFailed;
6326             break;
6327 
6328         case READ_MPEG4_MEDIA_HEADER_ATOM_FAILED:
6329             aEventCode = PVMFMP4FFParserErrMPEG4MediaHeaderAtomReadFailed;
6330             break;
6331 
6332         case READ_DATA_INFORMATION_ATOM_FAILED:
6333             aEventCode = PVMFMP4FFParserErrDataInformationAtomReadFailed;
6334             break;
6335 
6336         case READ_DATA_REFERENCE_ATOM_FAILED:
6337             aEventCode = PVMFMP4FFParserErrDataReferenceAtomReadFailed;
6338             break;
6339 
6340         case READ_DATA_ENTRY_URL_ATOM_FAILED:
6341             aEventCode = PVMFMP4FFParserErrDataEntryURLAtomReadFailed;
6342             break;
6343 
6344         case READ_DATA_ENTRY_URN_ATOM_FAILED:
6345             aEventCode = PVMFMP4FFParserErrDataEntryURNAtomReadFailed;
6346             break;
6347 
6348         case READ_SAMPLE_TABLE_ATOM_FAILED:
6349             aEventCode = PVMFMP4FFParserErrSampleTableAtomReadFailed;
6350             break;
6351 
6352         case READ_TIME_TO_SAMPLE_ATOM_FAILED:
6353             aEventCode = PVMFMP4FFParserErrTimeToSampleAtomReadFailed;
6354             break;
6355 
6356         case READ_SAMPLE_DESCRIPTION_ATOM_FAILED:
6357             aEventCode = PVMFMP4FFParserErrSampleDescriptionAtomReadFailed;
6358             break;
6359 
6360         case READ_SAMPLE_SIZE_ATOM_FAILED:
6361             aEventCode = PVMFMP4FFParserErrSampleSizeAtomReadFailed;
6362             break;
6363 
6364         case READ_SAMPLE_TO_CHUNK_ATOM_FAILED:
6365             aEventCode = PVMFMP4FFParserErrSampleToChunkAtomReadFailed;
6366             break;
6367 
6368         case READ_CHUNK_OFFSET_ATOM_FAILED:
6369             aEventCode = PVMFMP4FFParserErrChunkOffsetAtomReadFailed;
6370             break;
6371 
6372         case READ_SYNC_SAMPLE_ATOM_FAILED:
6373             aEventCode = PVMFMP4FFParserErrSyncSampleAtomReadFailed;
6374             break;
6375 
6376         case READ_SAMPLE_ENTRY_FAILED:
6377             aEventCode = PVMFMP4FFParserErrSampleEntryReadFailed;
6378             break;
6379 
6380         case READ_AUDIO_SAMPLE_ENTRY_FAILED:
6381             aEventCode = PVMFMP4FFParserErrAudioSampleEntryReadFailed;
6382             break;
6383 
6384         case READ_VISUAL_SAMPLE_ENTRY_FAILED:
6385             aEventCode = PVMFMP4FFParserErrVisualSampleEntryReadFailed;
6386             break;
6387 
6388         case READ_HINT_SAMPLE_ENTRY_FAILED:
6389             aEventCode = PVMFMP4FFParserErrHintSampleEntryReadFailed;
6390             break;
6391 
6392         case READ_MPEG_SAMPLE_ENTRY_FAILED:
6393             aEventCode = PVMFMP4FFParserErrMPEGSampleEntryReadFailed;
6394             break;
6395 
6396         case READ_AUDIO_HINT_SAMPLE_FAILED:
6397             aEventCode = PVMFMP4FFParserErrAudioHintSampleReadFailed;
6398             break;
6399 
6400         case READ_VIDEO_HINT_SAMPLE_FAILED:
6401             aEventCode = PVMFMP4FFParserErrVideoHintSampleReadFailed;
6402             break;
6403 
6404         case READ_ESD_ATOM_FAILED:
6405             aEventCode = PVMFMP4FFParserErrESDAtomReadFailed;
6406             break;
6407 
6408         case READ_ES_DESCRIPTOR_FAILED:
6409             aEventCode = PVMFMP4FFParserErrESDescriptorReadFailed;
6410             break;
6411 
6412         case READ_SL_CONFIG_DESCRIPTOR_FAILED:
6413             aEventCode = PVMFMP4FFParserErrSLConfigDescriptorReadFailed;
6414             break;
6415 
6416         case READ_DECODER_CONFIG_DESCRIPTOR_FAILED:
6417             aEventCode = PVMFMP4FFParserErrDecoderConfigDescriptorReadFailed;
6418             break;
6419 
6420         case READ_DECODER_SPECIFIC_INFO_FAILED:
6421             aEventCode = PVMFMP4FFParserErrDecoderSpecificInfoReadFailed;
6422             break;
6423 
6424         case DUPLICATE_MOVIE_ATOMS:
6425             aEventCode = PVMFMP4FFParserErrDuplicateMovieAtoms;
6426             break;
6427 
6428         case NO_MOVIE_ATOM_PRESENT:
6429             aEventCode = PVMFMP4FFParserErrNoMovieAtomPresent;
6430             break;
6431 
6432         case DUPLICATE_OBJECT_DESCRIPTORS:
6433             aEventCode = PVMFMP4FFParserErrDuplicateObjectDescriptors;
6434             break;
6435 
6436         case NO_OBJECT_DESCRIPTOR_ATOM_PRESENT:
6437             aEventCode = PVMFMP4FFParserErrNoObjectDescriptorAtomPresent;
6438             break;
6439 
6440         case DUPLICATE_MOVIE_HEADERS:
6441             aEventCode = PVMFMP4FFParserErrDuplicateMovieHeaders;
6442             break;
6443 
6444         case NO_MOVIE_HEADER_ATOM_PRESENT:
6445             aEventCode = PVMFMP4FFParserErrNoMovieHeaderAtomPresent;
6446             break;
6447 
6448         case DUPLICATE_TRACK_REFERENCE_ATOMS:
6449             aEventCode = PVMFMP4FFParserErrDuplicateTrackReferenceAtoms;
6450             break;
6451 
6452         case DUPLICATE_TRACK_HEADER_ATOMS:
6453             aEventCode = PVMFMP4FFParserErrDuplicateTrackHeaderAtoms;
6454             break;
6455 
6456         case NO_TRACK_HEADER_ATOM_PRESENT:
6457             aEventCode = PVMFMP4FFParserErrNoTrackHeaderAtomPresent;
6458             break;
6459 
6460         case DUPLICATE_MEDIA_ATOMS:
6461             aEventCode = PVMFMP4FFParserErrDuplicateMediaAtoms;
6462             break;
6463 
6464         case NO_MEDIA_ATOM_PRESENT:
6465             aEventCode = PVMFMP4FFParserErrNoMediaAtomPresent;
6466             break;
6467 
6468         case READ_UNKNOWN_ATOM:
6469             aEventCode = PVMFMP4FFParserErrUnknownAtom;
6470             break;
6471 
6472         case NON_PV_CONTENT:
6473             aEventCode = PVMFMP4FFParserErrNonPVContent;
6474             break;
6475 
6476         case FILE_NOT_STREAMABLE:
6477             aEventCode = PVMFMP4FFParserErrFileNotStreamable;
6478             break;
6479 
6480         case INSUFFICIENT_BUFFER_SIZE:
6481             aEventUUID = PVMFFileFormatEventTypesUUID;
6482             aEventCode = PVMFFFErrInsufficientBuffer;
6483             break;
6484 
6485         case INVALID_SAMPLE_SIZE:
6486             aEventCode = PVMFMP4FFParserErrInvalidSampleSize;
6487             break;
6488 
6489         case INVALID_CHUNK_OFFSET:
6490             aEventCode = PVMFMP4FFParserErrInvalidChunkOffset;
6491             break;
6492 
6493         case MEMORY_ALLOCATION_FAILED:
6494             aEventCode = PVMFMP4FFParserErrMemoryAllocationFailed;
6495             break;
6496 
6497         case READ_FILE_TYPE_ATOM_FAILED:
6498             aEventCode = PVMFMP4FFParserErrFileTypeAtomReadFailed;
6499             break;
6500 
6501         case ZERO_OR_NEGATIVE_ATOM_SIZE:
6502             aEventCode = PVMFMP4FFParserErrZeroOrNegativeAtomSize;
6503             break;
6504 
6505         case NO_MEDIA_TRACKS_IN_FILE:
6506             aEventCode = PVMFMP4FFParserErrNoMediaTracksInFile;
6507             break;
6508 
6509         case NO_META_DATA_FOR_MEDIA_TRACKS:
6510             aEventCode = PVMFMP4FFParserErrNoMetadataForMediaTracks;
6511             break;
6512 
6513         case MEDIA_DATA_NOT_SELF_CONTAINED:
6514             aEventCode = PVMFMP4FFParserErrMediaDataNotSelfContained;
6515             break;
6516 
6517         case READ_PVTI_SESSION_INFO_FAILED:
6518             aEventCode = PVMFMP4FFParserErrPVTISessionInfoReadFailed;
6519             break;
6520 
6521         case READ_PVTI_MEDIA_INFO_FAILED:
6522             aEventCode = PVMFMP4FFParserErrPVTIMediaInfoReadFailed;
6523             break;
6524 
6525         case READ_CONTENT_VERSION_FAILED:
6526             aEventCode = PVMFMP4FFParserErrContentVersionReadFailed;
6527             break;
6528 
6529         case READ_DOWNLOAD_ATOM_FAILED:
6530             aEventCode = PVMFMP4FFParserErrDownloadAtomReadFailed;
6531             break;
6532 
6533         case READ_TRACK_INFO_ATOM_FAILED:
6534             aEventCode = PVMFMP4FFParserErrTrackInfoAtomReadFailed;
6535             break;
6536 
6537         case READ_REQUIREMENTS_ATOM_FAILED:
6538             aEventCode = PVMFMP4FFParserErrRequirementsAtomReadFailed;
6539             break;
6540 
6541         case READ_WMF_SET_MEDIA_ATOM_FAILED:
6542             aEventCode = PVMFMP4FFParserErrWMFSetMediaAtomReadFailed;
6543             break;
6544 
6545         case READ_WMF_SET_SESSION_ATOM_FAILED:
6546             aEventCode = PVMFMP4FFParserErrWMFSetSessionAtomReadFailed;
6547             break;
6548 
6549         case READ_PV_USER_DATA_ATOM_FAILED:
6550             aEventCode = PVMFMP4FFParserErrPVUserDataAtomReadFailed;
6551             break;
6552 
6553         case READ_VIDEO_INFORMATION_ATOM_FAILED:
6554             aEventCode = PVMFMP4FFParserErrVideoInformationAtomReadFailed;
6555             break;
6556 
6557         case READ_RANDOM_ACCESS_ATOM_FAILED:
6558             aEventCode = PVMFMP4FFParserErrRandomAccessAtomReadFailed;
6559             break;
6560 
6561         case READ_AMR_SAMPLE_ENTRY_FAILED:
6562             aEventCode = PVMFMP4FFParserErrAMRSampleEntryReadFailed;
6563             break;
6564 
6565         case READ_H263_SAMPLE_ENTRY_FAILED:
6566             aEventCode = PVMFMP4FFParserErrH263SampleEntryReadFailed;
6567             break;
6568 
6569         case FILE_OPEN_FAILED:
6570             aEventUUID = PVMFFileFormatEventTypesUUID;
6571             aEventCode = PVMFFFErrFileOpen;
6572             break;
6573 
6574         case READ_UUID_ATOM_FAILED:
6575             aEventCode = PVMFMP4FFParserErrUUIDAtomReadFailed;
6576             break;
6577 
6578         case FILE_VERSION_NOT_SUPPORTED:
6579             aEventCode = PVMFMP4FFParserErrFileVersionNotSupported;
6580             break;
6581 
6582         case TRACK_VERSION_NOT_SUPPORTED:
6583             aEventCode = PVMFMP4FFParserErrTrackVersioNotSupported;
6584             break;
6585 
6586 
6587         case READ_COPYRIGHT_ATOM_FAILED:
6588             aEventCode = PVMFMP4FFParserErrCopyrightAtomReadFailed;
6589             break;
6590 
6591         case READ_FONT_TABLE_ATOM_FAILED:
6592             aEventCode = PVMFMP4FFParserErrFontTableAtomReadFailed;
6593             break;
6594 
6595         case READ_FONT_RECORD_FAILED:
6596             aEventCode = PVMFMP4FFParserErrFontRecordReadFailed;
6597             break;
6598 
6599         case FILE_PSEUDO_STREAMABLE:
6600             aEventCode = PVMFMP4FFParserErrPseudostreamableFile;
6601             break;
6602 
6603         case FILE_NOT_PSEUDO_STREAMABLE:
6604             aEventCode = PVMFMP4FFParserErrNotPseudostreamableFile;
6605             break;
6606 
6607         case READ_PV_ENTITY_TAG_ATOM_FAILED:
6608             aEventCode = PVMFMP4FFParserErrPVEntityTagAtomReadFailed;
6609             break;
6610 
6611         case DUPLICATE_FILE_TYPE_ATOMS:
6612             aEventCode = PVMFMP4FFParserErrDuplicateFileTypeAtoms;
6613             break;
6614 
6615         case UNSUPPORTED_FILE_TYPE:
6616             aEventCode = PVMFMP4FFParserErrUnsupportedFileType;
6617             break;
6618 
6619         case FILE_TYPE_ATOM_NOT_FOUND:
6620             aEventCode = PVMFMP4FFParserErrFileTypeAtomNotFound;
6621             break;
6622 
6623         case READ_EDIT_ATOM_FAILED:
6624             aEventCode = PVMFMP4FFParserErrEditAtomReadFailed;
6625             break;
6626 
6627         case READ_EDITLIST_ATOM_FAILED:
6628             aEventCode = PVMFMP4FFParserErrEditlistAtomReadFailed;
6629             break;
6630 
6631         case ATOM_VERSION_NOT_SUPPORTED:
6632             aEventCode = PVMFMP4FFParserErrAtomVersionNotSupported;
6633             break;
6634 
6635         case READ_UDTA_TITL_FAILED:
6636             aEventCode = PVMFMP4FFParserErrUDTATITLReadFailed;
6637             break;
6638 
6639         case READ_UDTA_DSCP_FAILED:
6640             aEventCode = PVMFMP4FFParserErrUDTADSCPReadFailed;
6641             break;
6642 
6643         case READ_UDTA_CPRT_FAILED:
6644             aEventCode = PVMFMP4FFParserErrUDTACPRTReadFailed;
6645             break;
6646 
6647         case READ_UDTA_PERF_FAILED:
6648             aEventCode = PVMFMP4FFParserErrUDTAPERFReadFailed;
6649             break;
6650 
6651         case READ_UDTA_AUTH_FAILED:
6652             aEventCode = PVMFMP4FFParserErrUDTAUTHReadFailed;
6653             break;
6654 
6655         case READ_UDTA_GNRE_FAILED:
6656             aEventCode = PVMFMP4FFParserErrUDTAGNREReadFailed;
6657             break;
6658 
6659         case READ_UDTA_RTNG_FAILED:
6660             aEventCode = PVMFMP4FFParserErrUDTARTNGReadFailed;
6661             break;
6662 
6663         case READ_UDTA_CLSF_FAILED:
6664             aEventCode = PVMFMP4FFParserErrUDTACLSFReadFailed;
6665             break;
6666 
6667         case READ_UDTA_KYWD_FAILED:
6668             aEventCode = PVMFMP4FFParserErrUDTAKYWDReadFailed;
6669             break;
6670 
6671         case READ_PV_CONTENT_TYPE_ATOM_FAILED:
6672             aEventCode = PVMFMP4FFParserErrPVContentTypeAtomReadFailed;
6673             break;
6674 
6675         case INSUFFICIENT_DATA:
6676             aEventUUID = PVMFFileFormatEventTypesUUID;
6677             aEventCode = PVMFFFErrInsufficientData;
6678             break;
6679 
6680         case NOT_SUPPORTED:
6681             aEventUUID = PVMFFileFormatEventTypesUUID;
6682             aEventCode = PVMFFFErrNotSupported;
6683             break;
6684 
6685         case READ_AVC_SAMPLE_ENTRY_FAILED:
6686             aEventUUID = PVMFFileFormatEventTypesUUID;
6687             aEventCode = PVMFMP4FFParserErrReadAVCSampleEntryFailed;
6688             break;
6689 
6690         case READ_AVC_CONFIG_BOX_FAILED:
6691             aEventUUID = PVMFFileFormatEventTypesUUID;
6692             aEventCode = PVMFMP4FFParserErrReadAVCConfigBoxFailed;
6693             break;
6694 
6695         case READ_MPEG4_BITRATE_BOX_FAILED:
6696             aEventUUID = PVMFFileFormatEventTypesUUID;
6697             aEventCode = PVMFMP4FFParserErrReadMPEG4BitRateBoxFailed;
6698             break;
6699 
6700         case EVERYTHING_FINE:
6701             OSCL_ASSERT(false); // Should not pass this "error" code to this function
6702         default:
6703             return false;
6704     }
6705 
6706     return true;
6707 }
6708 
6709 /* CPM related */
InitCPM()6710 void PVMFMP4FFParserNode::InitCPM()
6711 {
6712     iCPMSequenceInProgress = true;
6713     iCPMInitCmdId = iCPM->Init();
6714 }
6715 
OpenCPMSession()6716 void PVMFMP4FFParserNode::OpenCPMSession()
6717 {
6718     iCPMSequenceInProgress = true;
6719     iCPMOpenSessionCmdId = iCPM->OpenSession(iCPMSessionID);
6720 }
6721 
GetCPMLicenseInterface()6722 void PVMFMP4FFParserNode::GetCPMLicenseInterface()
6723 {
6724     iCPMSequenceInProgress = true;
6725     iCPMLicenseInterfacePVI = NULL;
6726     iCPMGetLicenseInterfaceCmdId =
6727         iCPM->QueryInterface(iCPMSessionID,
6728                              PVMFCPMPluginLicenseInterfaceUuid,
6729                              iCPMLicenseInterfacePVI);
6730 }
6731 
GetCPMContentAccessFactory()6732 bool PVMFMP4FFParserNode::GetCPMContentAccessFactory()
6733 {
6734     iCPMSequenceInProgress = true;
6735     PVMFStatus status = iCPM->GetContentAccessFactory(iCPMSessionID,
6736                         iCPMContentAccessFactory);
6737     if (status != PVMFSuccess)
6738     {
6739         return false;
6740     }
6741     return true;
6742 }
6743 
CPMRegisterContent()6744 void PVMFMP4FFParserNode::CPMRegisterContent()
6745 {
6746     iCPMSequenceInProgress = true;
6747     if (iSourceContextDataValid == true)
6748     {
6749         iCPMRegisterContentCmdId = iCPM->RegisterContent(iCPMSessionID,
6750                                    iFilename,
6751                                    iSourceFormat,
6752                                    (OsclAny*) & iSourceContextData);
6753     }
6754     else
6755     {
6756         iCPMRegisterContentCmdId = iCPM->RegisterContent(iCPMSessionID,
6757                                    iFilename,
6758                                    iSourceFormat,
6759                                    (OsclAny*) & iCPMSourceData);
6760     }
6761 }
6762 
GetCPMContentType()6763 void PVMFMP4FFParserNode::GetCPMContentType()
6764 {
6765     iCPMContentType = iCPM->GetCPMContentType(iCPMSessionID);
6766 }
6767 
GetCPMMetaDataExtensionInterface()6768 bool PVMFMP4FFParserNode::GetCPMMetaDataExtensionInterface()
6769 {
6770     iCPMSequenceInProgress = true;
6771     PVInterface* temp = NULL;
6772     bool retVal =
6773         iCPM->queryInterface(KPVMFMetadataExtensionUuid, temp);
6774     iCPMMetaDataExtensionInterface = OSCL_STATIC_CAST(PVMFMetadataExtensionInterface*, temp);
6775     return retVal;
6776 }
6777 
6778 PVMP4FFNodeTrackOMA2DRMInfo*
LookUpOMA2TrackInfoForTrack(uint32 aTrackID)6779 PVMFMP4FFParserNode::LookUpOMA2TrackInfoForTrack(uint32 aTrackID)
6780 {
6781     Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it;
6782     for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++)
6783     {
6784         if (it->iTrackId == aTrackID)
6785         {
6786             return it;
6787         }
6788     }
6789     return NULL;
6790 }
6791 
CheckForOMA2AuthorizationComplete(PVMP4FFNodeTrackOMA2DRMInfo * & aInfo)6792 PVMFStatus PVMFMP4FFParserNode::CheckForOMA2AuthorizationComplete(PVMP4FFNodeTrackOMA2DRMInfo*& aInfo)
6793 {
6794     aInfo = NULL;
6795     if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
6796     {
6797         /* Look for a track that needs authorization */
6798         Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it;
6799         for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++)
6800         {
6801             if (it->iOMA2TrackAuthorizationComplete == false)
6802             {
6803                 aInfo = it;
6804                 return PVMFPending;
6805             }
6806         }
6807     }
6808     else
6809     {
6810         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForOMA2AuthorizationComplete - Invalid CPM ContentType"));
6811         return PVMFFailure;
6812     }
6813     return PVMFSuccess;
6814 }
6815 
OMA2TrackAuthorizationComplete()6816 void PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete()
6817 {
6818     if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
6819     {
6820         /* Look for a track that needs authorization */
6821         Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it;
6822         for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++)
6823         {
6824             if (it->iOMA2TrackAuthorizationInProgress == true)
6825             {
6826                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete - TrackId=%d", it->iTrackId));
6827                 it->iOMA2TrackAuthorizationComplete = true;
6828                 it->iOMA2TrackAuthorizationInProgress = false;
6829                 if (iApprovedUsage.value.uint32_value ==
6830                         iRequestedUsage.value.uint32_value)
6831                 {
6832                     it->iOMA2TrackAuthorized = true;
6833                 }
6834                 return;
6835             }
6836         }
6837     }
6838     else
6839     {
6840         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete - Invalid CPM ContentType"));
6841         OSCL_ASSERT(false);
6842     }
6843     PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::OMA2TrackAuthorizationComplete - Couldn't Find Track"));
6844 }
6845 
CheckForOMA2UsageApproval()6846 bool PVMFMP4FFParserNode::CheckForOMA2UsageApproval()
6847 {
6848     if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
6849     {
6850         /* Look for a track that needs authorization */
6851         Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it;
6852         for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++)
6853         {
6854             if (it->iOMA2TrackAuthorized == false)
6855             {
6856                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForOMA2UsageApproval - Not Authorized - TrackId=%d", it->iTrackId));
6857                 return false;
6858             }
6859         }
6860     }
6861     else
6862     {
6863         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForOMA2UsageApproval - Invalid CPM ContentType"));
6864         OSCL_ASSERT(false);
6865     }
6866     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForOMA2UsageApproval - All Tracks Authorized"));
6867     return true;
6868 }
6869 
ResetOMA2Flags()6870 void PVMFMP4FFParserNode::ResetOMA2Flags()
6871 {
6872     if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
6873     {
6874         /* Look for a track that needs authorization */
6875         Oscl_Vector<PVMP4FFNodeTrackOMA2DRMInfo, OsclMemAllocator>::iterator it;
6876         for (it = iOMA2DRMInfoVec.begin(); it != iOMA2DRMInfoVec.end(); it++)
6877         {
6878             it->iOMA2TrackAuthorized = false;
6879             it->iOMA2TrackAuthorizationComplete = false;
6880             it->iOMA2TrackAuthorizationInProgress = false;
6881         }
6882     }
6883     else
6884     {
6885         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::ResetOMA2Flags - Invalid CPM ContentType"));
6886         OSCL_ASSERT(false);
6887     }
6888     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ResetOMA2Flags - Complete"));
6889     return;
6890 }
6891 
RequestUsage(PVMP4FFNodeTrackOMA2DRMInfo * aInfo)6892 void PVMFMP4FFParserNode::RequestUsage(PVMP4FFNodeTrackOMA2DRMInfo* aInfo)
6893 {
6894     if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
6895     {
6896         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::RequestUsage - TrackId=%d", aInfo->iTrackId));
6897         aInfo->iOMA2TrackAuthorizationInProgress = true;
6898         PopulateOMA2DRMInfo(aInfo);
6899     }
6900     else if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) ||
6901              (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS))
6902     {
6903         PopulateOMA1DRMInfo();
6904     }
6905     else
6906     {
6907         /* Error */
6908         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::RequestUsage - Invalid CPM Type"));
6909         OSCL_LEAVE(PVMFErrNotSupported);
6910     }
6911 
6912     iCPM->GetContentAccessFactory(iCPMSessionID, iCPMContentAccessFactory);
6913 
6914     if (iDataStreamReadCapacityObserver != NULL)
6915     {
6916         int32 leavecode = 0;
6917         OSCL_TRY(leavecode,
6918                  iCPMContentAccessFactory->SetStreamReadCapacityObserver(iDataStreamReadCapacityObserver););
6919         if (leavecode != 0)
6920         {
6921             PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetCPMContentAccessFactory: SetStreamReadCapacityObserver failed"));
6922         }
6923     }
6924 
6925     iCPMSequenceInProgress = true;
6926     iCPMRequestUsageId = iCPM->ApproveUsage(iCPMSessionID,
6927                                             iRequestedUsage,
6928                                             iApprovedUsage,
6929                                             iAuthorizationDataKvp,
6930                                             iUsageID);
6931     oWaitingOnLicense = true;
6932 }
6933 
PopulateOMA2DRMInfo(PVMP4FFNodeTrackOMA2DRMInfo * aInfo)6934 void PVMFMP4FFParserNode::PopulateOMA2DRMInfo(PVMP4FFNodeTrackOMA2DRMInfo* aInfo)
6935 {
6936     //Cleanup any old key.
6937     if (iRequestedUsage.key)
6938     {
6939         OSCL_ARRAY_DELETE(iRequestedUsage.key);
6940         iRequestedUsage.key = NULL;
6941     }
6942 
6943     if (iApprovedUsage.key)
6944     {
6945         OSCL_ARRAY_DELETE(iApprovedUsage.key);
6946         iApprovedUsage.key = NULL;
6947     }
6948 
6949     if (iAuthorizationDataKvp.key)
6950     {
6951         OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key);
6952         iAuthorizationDataKvp.key = NULL;
6953     }
6954 
6955     int32 UseKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING)) + oscl_strlen(_STRLIT_CHAR(";track_id=0"));
6956     int32 AuthKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING)) + oscl_strlen(_STRLIT_CHAR(";track_id=0"));
6957     int32 leavecode = 0;
6958 
6959     OSCL_TRY(leavecode,
6960              iRequestedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1);
6961              iApprovedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1);
6962              iAuthorizationDataKvp.key = OSCL_ARRAY_NEW(char, AuthKeyLen + 1);
6963             );
6964     if (leavecode || !iRequestedUsage.key || !iApprovedUsage.key || !iAuthorizationDataKvp.key)
6965     {
6966         if (iRequestedUsage.key)
6967         {
6968             OSCL_ARRAY_DELETE(iRequestedUsage.key);
6969             iRequestedUsage.key = NULL;
6970         }
6971         if (iApprovedUsage.key)
6972         {
6973             OSCL_ARRAY_DELETE(iApprovedUsage.key);
6974             iApprovedUsage.key = NULL;
6975         }
6976         if (iAuthorizationDataKvp.key)
6977         {
6978             OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key);
6979             iAuthorizationDataKvp.key = NULL;
6980         }
6981 
6982         return;
6983     }
6984 
6985     char trackID[16];
6986     oscl_snprintf(trackID, 16, ";track_id=%d", aInfo->iTrackId);
6987     trackID[15] = '\0';
6988 
6989     OSCL_StackString<256> requestUsageKey;
6990     requestUsageKey += _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING);
6991     requestUsageKey += trackID;
6992 
6993     oscl_strncpy(iRequestedUsage.key,
6994                  requestUsageKey.get_cstr(),
6995                  UseKeyLen);
6996     iRequestedUsage.key[UseKeyLen] = 0;
6997     iRequestedUsage.length = 0;
6998     iRequestedUsage.capacity = 0;
6999     iRequestedUsage.value.uint32_value =
7000         (BITMASK_PVMF_CPM_DRM_INTENT_PLAY |
7001          BITMASK_PVMF_CPM_DRM_INTENT_PAUSE |
7002          BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD |
7003          BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK);
7004 
7005     oscl_strncpy(iApprovedUsage.key,
7006                  requestUsageKey.get_cstr(),
7007                  UseKeyLen);
7008     iApprovedUsage.key[UseKeyLen] = 0;
7009     iApprovedUsage.length = 0;
7010     iApprovedUsage.capacity = 0;
7011     iApprovedUsage.value.uint32_value = 0;
7012 
7013     OSCL_StackString<512> authorizationKey;
7014     authorizationKey += _STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING);
7015     authorizationKey += trackID;
7016 
7017     oscl_strncpy(iAuthorizationDataKvp.key,
7018                  authorizationKey.get_cstr(),
7019                  AuthKeyLen);
7020     iAuthorizationDataKvp.key[AuthKeyLen] = 0;
7021 
7022     iAuthorizationDataKvp.length = aInfo->iDRMInfoSize;
7023     iAuthorizationDataKvp.capacity = aInfo->iDRMInfoSize;
7024     iAuthorizationDataKvp.value.pUint8_value = aInfo->iDRMInfo;
7025 }
7026 
PopulateOMA1DRMInfo()7027 void PVMFMP4FFParserNode::PopulateOMA1DRMInfo()
7028 {
7029     //Cleanup any old key.
7030     if (iRequestedUsage.key)
7031     {
7032         OSCL_ARRAY_DELETE(iRequestedUsage.key);
7033         iRequestedUsage.key = NULL;
7034     }
7035 
7036     if (iApprovedUsage.key)
7037     {
7038         OSCL_ARRAY_DELETE(iApprovedUsage.key);
7039         iApprovedUsage.key = NULL;
7040     }
7041 
7042     if (iAuthorizationDataKvp.key)
7043     {
7044         OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key);
7045         iAuthorizationDataKvp.key = NULL;
7046     }
7047 
7048     int32 UseKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING));
7049     int32 AuthKeyLen = oscl_strlen(_STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING));
7050     int32 leavecode = 0;
7051 
7052     OSCL_TRY(leavecode,
7053              iRequestedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1);
7054              iApprovedUsage.key = OSCL_ARRAY_NEW(char, UseKeyLen + 1);
7055              iAuthorizationDataKvp.key = OSCL_ARRAY_NEW(char, AuthKeyLen + 1);
7056             );
7057     if (leavecode || !iRequestedUsage.key || !iApprovedUsage.key || !iAuthorizationDataKvp.key)
7058     {
7059         if (iRequestedUsage.key)
7060         {
7061             OSCL_ARRAY_DELETE(iRequestedUsage.key);
7062             iRequestedUsage.key = NULL;
7063         }
7064         if (iApprovedUsage.key)
7065         {
7066             OSCL_ARRAY_DELETE(iApprovedUsage.key);
7067             iApprovedUsage.key = NULL;
7068         }
7069         if (iAuthorizationDataKvp.key)
7070         {
7071             OSCL_ARRAY_DELETE(iAuthorizationDataKvp.key);
7072             iAuthorizationDataKvp.key = NULL;
7073         }
7074 
7075         return;
7076     }
7077 
7078     oscl_strncpy(iRequestedUsage.key,
7079                  _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING),
7080                  UseKeyLen);
7081     iRequestedUsage.key[UseKeyLen] = 0;
7082     iRequestedUsage.length = 0;
7083     iRequestedUsage.capacity = 0;
7084     if (iPreviewMode)
7085     {
7086         iRequestedUsage.value.uint32_value =
7087             (BITMASK_PVMF_CPM_DRM_INTENT_PREVIEW |
7088              BITMASK_PVMF_CPM_DRM_INTENT_PAUSE |
7089              BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD |
7090              BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK);
7091     }
7092     else
7093     {
7094         iRequestedUsage.value.uint32_value =
7095             (BITMASK_PVMF_CPM_DRM_INTENT_PLAY |
7096              BITMASK_PVMF_CPM_DRM_INTENT_PAUSE |
7097              BITMASK_PVMF_CPM_DRM_INTENT_SEEK_FORWARD |
7098              BITMASK_PVMF_CPM_DRM_INTENT_SEEK_BACK);
7099     }
7100     oscl_strncpy(iApprovedUsage.key,
7101                  _STRLIT_CHAR(PVMF_CPM_REQUEST_USE_KEY_STRING),
7102                  UseKeyLen);
7103     iApprovedUsage.key[UseKeyLen] = 0;
7104     iApprovedUsage.length = 0;
7105     iApprovedUsage.capacity = 0;
7106     iApprovedUsage.value.uint32_value = 0;
7107 
7108     oscl_strncpy(iAuthorizationDataKvp.key,
7109                  _STRLIT_CHAR(PVMF_CPM_AUTHORIZATION_DATA_KEY_STRING),
7110                  AuthKeyLen);
7111     iAuthorizationDataKvp.key[AuthKeyLen] = 0;
7112     iAuthorizationDataKvp.length = 0;
7113     iAuthorizationDataKvp.capacity = 0;
7114     iAuthorizationDataKvp.value.pUint8_value = NULL;
7115 }
7116 
SendUsageComplete()7117 void PVMFMP4FFParserNode::SendUsageComplete()
7118 {
7119     iCPMSequenceInProgress = true;
7120     iCPMUsageCompleteCmdId = iCPM->UsageComplete(iCPMSessionID, iUsageID);
7121 }
7122 
CloseCPMSession()7123 void PVMFMP4FFParserNode::CloseCPMSession()
7124 {
7125     iCPMCloseSessionCmdId = iCPM->CloseSession(iCPMSessionID);
7126 }
7127 
ResetCPM()7128 void PVMFMP4FFParserNode::ResetCPM()
7129 {
7130     iCPMResetCmdId = iCPM->Reset();
7131 }
7132 
GetCPMMetaDataKeys()7133 void PVMFMP4FFParserNode::GetCPMMetaDataKeys()
7134 {
7135     if (iCPMMetaDataExtensionInterface != NULL)
7136     {
7137         iCPMMetadataKeys.clear();
7138         iCPMGetMetaDataKeysCmdId =
7139             iCPMMetaDataExtensionInterface->GetNodeMetadataKeys(iCPMSessionID,
7140                     iCPMMetadataKeys,
7141                     0,
7142                     PVMF_MP4FFPARSERNODE_MAX_CPM_METADATA_KEYS);
7143     }
7144 }
7145 
7146 PVMFStatus
CheckCPMCommandCompleteStatus(PVMFCommandId aID,PVMFStatus aStatus)7147 PVMFMP4FFParserNode::CheckCPMCommandCompleteStatus(PVMFCommandId aID,
7148         PVMFStatus aStatus)
7149 {
7150     PVMFStatus status = aStatus;
7151     if (aID == iCPMGetLicenseInterfaceCmdId)
7152     {
7153         if (aStatus == PVMFErrNotSupported)
7154         {
7155             /* License Interface is Optional */
7156             status = PVMFSuccess;
7157         }
7158     }
7159     else if (aID == iCPMRegisterContentCmdId)
7160     {
7161         if (aStatus == PVMFErrNotSupported)
7162         {
7163             /* CPM doesnt care about this content */
7164             status = PVMFErrNotSupported;
7165         }
7166     }
7167     else if (aID == iCPMRequestUsageId)
7168     {
7169         if (iCPMSourceData.iIntent & BITMASK_PVMF_SOURCE_INTENT_GETMETADATA)
7170         {
7171             if (aStatus != PVMFSuccess)
7172             {
7173                 /*
7174                  * If we are doing metadata only then we don't care
7175                  * if license is not available
7176                  */
7177                 status = PVMFSuccess;
7178             }
7179         }
7180     }
7181     return status;
7182 }
7183 
CPMCommandCompleted(const PVMFCmdResp & aResponse)7184 void PVMFMP4FFParserNode::CPMCommandCompleted(const PVMFCmdResp& aResponse)
7185 {
7186     iCPMSequenceInProgress = false;
7187     PVMFCommandId id = aResponse.GetCmdId();
7188     PVMFStatus status =
7189         CheckCPMCommandCompleteStatus(id, aResponse.GetCmdStatus());
7190 
7191     if (id == iCPMCancelGetLicenseCmdId)
7192     {
7193         /*
7194          * if this command is CancelGetLicense, we will return success or fail here.
7195          */
7196         PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted -  CPM CancelGetLicense complete"));
7197         OSCL_ASSERT(!iCancelCommand.empty());
7198         CommandComplete(iCancelCommand,
7199                         iCancelCommand.front(),
7200                         status);
7201         return;
7202     }
7203     //if CPM comes back as PVMFErrNotSupported then by pass rest of the CPM
7204     //sequence. Fake success here so that node doesnt treat this as an error
7205     else if (id == iCPMRegisterContentCmdId && status == PVMFErrNotSupported)
7206     {
7207         /* Unsupported format - Treat it like unprotected content */
7208         PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Unknown CPM Format - Ignoring CPM"));
7209         if (CheckForMP4HeaderAvailability() == PVMFSuccess)
7210         {
7211             CompleteInit(iCurrentCommand, iCurrentCommand.front());
7212         }
7213         return;
7214     }
7215 
7216     if (status != PVMFSuccess)
7217     {
7218         /*
7219          * If any command fails, the sequence fails.
7220          */
7221         if (aResponse.GetEventData() == NULL)
7222         {
7223             // If any command fails, the sequence fails.
7224             CommandComplete(iCurrentCommand,
7225                             iCurrentCommand.front(),
7226                             aResponse.GetCmdStatus());
7227         }
7228         else
7229         {
7230             // Need to pass EventData (=License URL) up to UI.
7231             CommandComplete(iCurrentCommand,
7232                             iCurrentCommand.front(),
7233                             aResponse.GetCmdStatus(),
7234                             aResponse.GetEventData());
7235         }
7236         /*
7237          * if there was any pending cancel, it was waiting on
7238          * this command to complete-- so the cancel is now done.
7239          */
7240         if (!iCancelCommand.empty())
7241         {
7242             if (iCancelCommand.front().iCmd != PVMP4FF_NODE_CMD_CANCEL_GET_LICENSE)
7243             {
7244                 CommandComplete(iCancelCommand,
7245                                 iCancelCommand.front(),
7246                                 PVMFSuccess);
7247             }
7248         }
7249     }
7250     else
7251     {
7252         //process the response, and issue the next command in
7253         //the sequence.
7254 
7255         PVMFCommandId id = aResponse.GetCmdId();
7256 
7257         if (id == iCPMInitCmdId)
7258         {
7259             PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM Init complete"));
7260             OpenCPMSession();
7261         }
7262         else if (id == iCPMOpenSessionCmdId)
7263         {
7264             PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM OpenSession complete"));
7265             CPMRegisterContent();
7266         }
7267         else if (id == iCPMRegisterContentCmdId)
7268         {
7269             GetCPMLicenseInterface();
7270         }
7271         else if (id == iCPMGetLicenseInterfaceCmdId)
7272         {
7273             iCPMLicenseInterface = OSCL_STATIC_CAST(PVMFCPMPluginLicenseInterface*, iCPMLicenseInterfacePVI);
7274             iCPMLicenseInterfacePVI = NULL;
7275             GetCPMContentType();
7276             if ((iCPMContentType == PVMF_CPM_FORMAT_OMA1) ||
7277                     (iCPMContentType == PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS))
7278             {
7279                 iProtectedFile = true;
7280                 GetCPMMetaDataExtensionInterface();
7281                 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - OMA1 - Register content complete"));
7282                 RequestUsage(NULL);
7283             }
7284             else if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
7285             {
7286                 iProtectedFile = true;
7287                 GetCPMMetaDataExtensionInterface();
7288                 if (CheckForMP4HeaderAvailability() == PVMFSuccess)
7289                 {
7290                     PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL;
7291                     if (ParseMP4File(iCurrentCommand,
7292                                      iCurrentCommand.front()))
7293                     {
7294                         if (CheckForOMA2AuthorizationComplete(oma2trackInfo) == PVMFPending)
7295                         {
7296                             RequestUsage(oma2trackInfo);
7297                         }
7298                     }
7299                 }
7300             }
7301             else
7302             {
7303                 /* Unsupported format - Treat it like unprotected content */
7304                 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Unknown CPM Format - Ignoring CPM"));
7305                 if (CheckForMP4HeaderAvailability() == PVMFSuccess)
7306                 {
7307                     CompleteInit(iCurrentCommand, iCurrentCommand.front());
7308                 }
7309             }
7310         }
7311         else if (id == iCPMRequestUsageId)
7312         {
7313             PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Request Usage complete"));
7314             //End of Node Init sequence.
7315             OSCL_ASSERT(!iCurrentCommand.empty());
7316             OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_INIT);
7317             oWaitingOnLicense = false;
7318             if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
7319             {
7320                 //for OMA2 PDCF we need to authorize track by track
7321                 OMA2TrackAuthorizationComplete();
7322                 PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL;
7323                 PVMFStatus status = CheckForOMA2AuthorizationComplete(oma2trackInfo);
7324                 if (status == PVMFPending)
7325                 {
7326                     RequestUsage(oma2trackInfo);
7327                 }
7328                 else if (status == PVMFSuccess)
7329                 {
7330                     //All tracks authorized, complete init
7331                     CompleteInit(iCurrentCommand, iCurrentCommand.front());
7332                 }
7333                 else
7334                 {
7335                     PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CheckForOMA2AuthorizationComplete Failed"));
7336                     OSCL_ASSERT(false);
7337                 }
7338             }
7339             else
7340             {
7341                 if (aResponse.GetCmdStatus() == PVMFSuccess)
7342                 {
7343                     //OMA1 content - Authorization complete
7344                     if (CheckForMP4HeaderAvailability() == PVMFSuccess)
7345                     {
7346                         CompleteInit(iCurrentCommand, iCurrentCommand.front());
7347                     }
7348                 }
7349                 else
7350                 {
7351                     //we are just doing metadata (not necessarily from mp4 file header,
7352                     // say just drm metadata), so complete init from here
7353                     CompleteInit(iCurrentCommand, iCurrentCommand.front());
7354                 }
7355             }
7356         }
7357         else if (id == iCPMUsageCompleteCmdId)
7358         {
7359             if (iProtectedFile == true)
7360             {
7361                 PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - CPM Usage Complete done"));
7362                 CloseCPMSession();
7363             }
7364             else
7365             {
7366                 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Unprotected Content - Can't Send Usage Complete"));
7367                 OSCL_ASSERT(false);
7368             }
7369         }
7370         else if (id == iCPMCloseSessionCmdId)
7371         {
7372             PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted - Close CPM Session complete"));
7373             ResetCPM();
7374         }
7375         else if (id == iCPMResetCmdId)
7376         {
7377             PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted -  CPM Reset complete"));
7378             //End of Node Reset sequence
7379             OSCL_ASSERT(!iCurrentCommand.empty());
7380             OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_RESET);
7381             CompleteReset(iCurrentCommand, iCurrentCommand.front());
7382         }
7383         else if (id == iCPMGetMetaDataKeysCmdId)
7384         {
7385             PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted -  CPM GetMetaDataKeys complete"));
7386             /* End of GetNodeMetaDataKeys */
7387             PVMFStatus status =
7388                 CompleteGetMetadataKeys(iCurrentCommand.front());
7389             CommandComplete(iCurrentCommand,
7390                             iCurrentCommand.front(),
7391                             status);
7392         }
7393         else if (id == iCPMGetMetaDataValuesCmdId)
7394         {
7395             PVMF_MP4FFPARSERNODE_LOGINFO((0, "PVMFMP4FFParserNode::CPMCommandCompleted -  CPM GetMetaDataValues complete"));
7396             /* End of GetNodeMetaDataValues */
7397             OSCL_ASSERT(!iCurrentCommand.empty());
7398             OSCL_ASSERT(iCurrentCommand.front().iCmd == PVMP4FF_NODE_CMD_GETNODEMETADATAVALUES);
7399             CompleteGetMetaDataValues();
7400         }
7401         else if (id == iCPMGetLicenseCmdId)
7402         {
7403             CompleteGetLicense();
7404         }
7405         else
7406         {
7407             /* Unknown cmd - error */
7408             CommandComplete(iCurrentCommand,
7409                             iCurrentCommand.front(),
7410                             PVMFFailure);
7411         }
7412     }
7413 }
7414 
GetFileOffsetForAutoResume(uint32 & aOffset,bool aPortsAvailable)7415 PVMFStatus PVMFMP4FFParserNode::GetFileOffsetForAutoResume(uint32& aOffset, bool aPortsAvailable)
7416 {
7417     uint32 offset = 0;
7418     if (aPortsAvailable == false)
7419     {
7420         int32 iNumTracks = iMP4FileHandle->getNumTracks();
7421         uint32 iIdList[16];
7422         if (iNumTracks != iMP4FileHandle->getTrackIDList(iIdList, iNumTracks))
7423         {
7424             return PVMFFailure;
7425         }
7426         for (int32 i = 0; i < iNumTracks; i++)
7427         {
7428             uint32 trackID = iIdList[i];
7429             /* Convert PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS to media timescale */
7430             MediaClockConverter mcc(1000);
7431             mcc.update_clock(iJitterBufferDurationInMs);
7432             uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(trackID));
7433 
7434             int32 trackOffset = 0;
7435             PVMFTimestamp ts = mediats;
7436             int32 retVal =
7437                 iMP4FileHandle->getOffsetByTime(trackID, ts, &trackOffset, iJitterBufferDurationInMs);
7438 
7439             if (retVal != EVERYTHING_FINE)
7440             {
7441                 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetFileOffsetForAutoResume1 - getOffsetByTime Failed - TrackId=%d, TS=%d, RetVal=%d",  trackID, ts, retVal));
7442                 return PVMFFailure;
7443             }
7444 
7445             if ((uint32)trackOffset > offset)
7446             {
7447                 offset = trackOffset;
7448             }
7449         }
7450     }
7451     else
7452     {
7453         Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
7454 
7455         for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
7456         {
7457             /* Convert PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS to media timescale */
7458             MediaClockConverter mcc(1000);
7459             mcc.update_clock(iJitterBufferDurationInMs);
7460             uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(it->iTrackId));
7461 
7462             int32 trackOffset = 0;
7463             PVMFTimestamp ts = it->iTimestamp + mediats;
7464             int32 retVal =
7465                 iMP4FileHandle->getOffsetByTime(it->iTrackId, ts, &trackOffset, iJitterBufferDurationInMs);
7466 
7467             if (retVal != EVERYTHING_FINE)
7468             {
7469                 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetFileOffsetForAutoResume2 - getOffsetByTime Failed - TrackId=%d, TS=%d, RetVal=%d",  it->iTrackId, ts, retVal));
7470                 return PVMFFailure;
7471             }
7472 
7473             if ((uint32)trackOffset > offset)
7474             {
7475                 offset = trackOffset;
7476             }
7477         }
7478     }
7479     aOffset = offset;
7480     return PVMFSuccess;
7481 }
7482 
GetFileOffsetForAutoResume(uint32 & aOffset,PVMP4FFNodeTrackPortInfo * aInfo)7483 PVMFStatus PVMFMP4FFParserNode::GetFileOffsetForAutoResume(uint32& aOffset, PVMP4FFNodeTrackPortInfo* aInfo)
7484 {
7485     uint32 offset = 0;
7486     /* Convert PVMF_MP4FFPARSER_NODE_PSEUDO_STREAMING_BUFFER_DURATION_IN_MS to media timescale */
7487     MediaClockConverter mcc(1000);
7488     mcc.update_clock(iJitterBufferDurationInMs);
7489     uint32 mediats = mcc.get_converted_ts(iMP4FileHandle->getTrackMediaTimescale(aInfo->iTrackId));
7490 
7491     int32 trackOffset = 0;
7492     PVMFTimestamp ts = aInfo->iTimestamp + mediats;
7493     int32 retVal =
7494         iMP4FileHandle->getOffsetByTime(aInfo->iTrackId, ts, &trackOffset, iJitterBufferDurationInMs);
7495 
7496     if (retVal != EVERYTHING_FINE)
7497     {
7498         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::GetFileOffsetForAutoResume by port - getOffsetByTime Failed - TrackId=%d, TS=%d, RetVal=%d",  aInfo->iTrackId, ts, retVal));
7499         return PVMFFailure;
7500     }
7501 
7502     if ((uint32)trackOffset > offset)
7503     {
7504         offset = trackOffset;
7505     }
7506     aOffset = offset;
7507     return PVMFSuccess;
7508 }
7509 
7510 
DataStreamCommandCompleted(const PVMFCmdResp & aResponse)7511 void PVMFMP4FFParserNode::DataStreamCommandCompleted(const PVMFCmdResp& aResponse)
7512 {
7513     for (uint32 i = 0; i < iNodeTrackPortList.size(); ++i)
7514     {
7515         switch (iNodeTrackPortList[i].iState)
7516         {
7517                 /*
7518                 ** Its possible that track reports inufficient data but does not report Underflow and
7519                 ** justs sets the timer. If we receive DataStreamCommandComplete means we need not report
7520                 ** underflow now, so set track state as GETDATA, cancel the timer and schedule Node to
7521                 ** retrieve data. This case will only happen if CheckForUnderflow returns Pending for
7522                 ** any track.
7523                 */
7524             case PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA:
7525                 iNodeTrackPortList[i].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
7526                 iUnderFlowCheckTimer->Cancel(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID);
7527                 RunIfNotReady();
7528                 break;
7529 
7530             default:
7531                 // nothing to do
7532                 break;
7533         }
7534 
7535     }
7536     if (autopaused)
7537     {
7538         if (aResponse.GetCmdStatus() == PVMFSuccess)
7539         {
7540             autopaused = false;
7541             for (uint32 ii = 0; ii < iNodeTrackPortList.size(); ++ii)
7542             {
7543                 switch (iNodeTrackPortList[ii].iState)
7544                 {
7545                     case PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE:
7546                         iNodeTrackPortList[ii].iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_GETDATA;
7547                         break;
7548 
7549                     default:
7550                         // nothing to do
7551                         break;
7552                 }
7553                 RunIfNotReady();
7554             }
7555 
7556             // report data ready only if underflow was not suppressed earlier
7557             if (iUnderFlowEventReported == true)
7558             {
7559                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::DataStreamReadCapacityNotificationCallBack() Sending PVMFInfoDataReady event"));
7560                 ReportMP4FFParserInfoEvent(PVMFInfoDataReady);
7561                 iUnderFlowEventReported = false;
7562             }
7563             if (iExternalDownload == true)
7564             {
7565                 if ((iCurrentCommand.empty() == false) &&
7566                         (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_PREPARE))
7567                 {
7568                     //we could be waiting on this call back to complete prepare
7569                     CompletePrepare(aResponse.GetCmdStatus());
7570                 }
7571             }
7572             // Schedule AO to run again
7573             RunIfNotReady();
7574             return;
7575         }
7576         else
7577         {
7578             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DataStreamReadCapacityNotificationCallBack() Reporting failure"));
7579             if (iExternalDownload == true)
7580             {
7581                 if ((iCurrentCommand.empty() == false) &&
7582                         (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_PREPARE))
7583                 {
7584                     //we could be waiting on this call back to complete prepare
7585                     CompletePrepare(aResponse.GetCmdStatus());
7586                 }
7587                 else
7588                 {
7589                     ReportMP4FFParserErrorEvent(PVMFErrResource);
7590                 }
7591             }
7592             else
7593             {
7594                 ReportMP4FFParserErrorEvent(PVMFErrResource);
7595             }
7596         }
7597     }
7598     else if ((iCurrentCommand.empty() == false) &&
7599              (iCurrentCommand.front().iCmd == PVMF_GENERIC_NODE_INIT))
7600     {
7601         /* Callbacks intiated  as part of node init */
7602         if (aResponse.GetCmdId() == iRequestReadCapacityNotificationID)
7603         {
7604             iDataStreamRequestPending = false;
7605             /*
7606              * Can come here only if we are doing PDL / PPB.
7607              * Init is still pending and datastream callback has completed.
7608              * A few possible scenarios here:
7609              * - PDL/PPB (DRM/Non-DRM) - We are waiting on movie atom to be downloaded.
7610              * - OMA2 PDCF DRM clip - were waiting on more data to parse the movie atom,
7611              * CPM seq not complete since we need contents of movie atom to authorize
7612              * with CPM
7613              */
7614             if (iCPM)
7615             {
7616                 if (iCPMContentType == PVMF_CPM_FORMAT_OMA2)
7617                 {
7618                     PVMP4FFNodeTrackOMA2DRMInfo* oma2trackInfo = NULL;
7619                     if (ParseMP4File(iCurrentCommand,
7620                                      iCurrentCommand.front()))
7621                     {
7622                         if (CheckForOMA2AuthorizationComplete(oma2trackInfo) == PVMFPending)
7623                         {
7624                             RequestUsage(oma2trackInfo);
7625                             return;
7626                         }
7627                     }
7628                 }
7629             }
7630             if (PVMFSuccess == CheckForMP4HeaderAvailability())
7631             {
7632                 CompleteInit(iCurrentCommand, iCurrentCommand.front());
7633             }
7634         }
7635         else
7636         {
7637             /* unrecognized callback */
7638             OSCL_ASSERT(false);
7639         }
7640     }
7641     else
7642     {
7643         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFMP4FFParserNode::DataStreamReadCapacityNotificationCallBack() in non-autopaused state"));
7644         ReportMP4FFParserErrorEvent(PVMFErrInvalidState);
7645     }
7646     return;
7647 }
7648 
7649 
DataStreamInformationalEvent(const PVMFAsyncEvent & aEvent)7650 void PVMFMP4FFParserNode::DataStreamInformationalEvent(const PVMFAsyncEvent& aEvent)
7651 {
7652     //if Datadownload is complete then send PVMFInfoBufferingComplete event from DS to parser node
7653     if (aEvent.GetEventType() == PVMFInfoBufferingComplete)
7654     {
7655         iDownloadComplete = true;
7656     }
7657 }
7658 
DataStreamErrorEvent(const PVMFAsyncEvent & aEvent)7659 void PVMFMP4FFParserNode::DataStreamErrorEvent(const PVMFAsyncEvent& aEvent)
7660 {
7661     OSCL_UNUSED_ARG(aEvent);
7662     OSCL_ASSERT(false);
7663 }
7664 
getBrand(uint32 aBrandVal,char * BrandVal)7665 void PVMFMP4FFParserNode::getBrand(uint32 aBrandVal, char *BrandVal)
7666 {
7667     BrandVal[0] = (aBrandVal >> 24);
7668     BrandVal[1] = (aBrandVal >> 16);
7669     BrandVal[2] = (aBrandVal >> 8);
7670     BrandVal[3] =  aBrandVal;
7671 }
7672 
GetTrackPortInfoForTrackID(PVMP4FFNodeTrackPortInfo * & aInfo,uint32 aTrackID)7673 bool PVMFMP4FFParserNode::GetTrackPortInfoForTrackID(PVMP4FFNodeTrackPortInfo*& aInfo,
7674         uint32 aTrackID)
7675 {
7676     aInfo = NULL;
7677     Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
7678     for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
7679     {
7680         if (it->iTrackId == (int32)aTrackID)
7681         {
7682             aInfo = it;
7683             return true;
7684         }
7685     }
7686     return false;
7687 }
7688 
GetTrackPortInfoForPort(PVMP4FFNodeTrackPortInfo * & aInfo,PVMFPortInterface * aPort)7689 bool PVMFMP4FFParserNode::GetTrackPortInfoForPort(PVMP4FFNodeTrackPortInfo*& aInfo,
7690         PVMFPortInterface* aPort)
7691 {
7692     aInfo = NULL;
7693     Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
7694     for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
7695     {
7696         if (it->iPortInterface == aPort)
7697         {
7698             aInfo = it;
7699             return true;
7700         }
7701     }
7702     return false;
7703 }
7704 
PassDatastreamFactory(PVMFDataStreamFactory & aFactory,int32 aFactoryTag,const PvmfMimeString * aFactoryConfig)7705 void PVMFMP4FFParserNode::PassDatastreamFactory(PVMFDataStreamFactory& aFactory,
7706         int32 aFactoryTag,
7707         const PvmfMimeString* aFactoryConfig)
7708 {
7709     OSCL_UNUSED_ARG(aFactoryTag);
7710     OSCL_UNUSED_ARG(aFactoryConfig);
7711 
7712     // Fasttrack download does not use data streams
7713     if (iFastTrackSession)
7714         return;
7715 
7716     if (iDataStreamFactory  == NULL)
7717     {
7718         iDataStreamFactory  = &aFactory;
7719         PVUuid uuid = PVMIDataStreamSyncInterfaceUuid;
7720         PVInterface* iFace =
7721             iDataStreamFactory->CreatePVMFCPMPluginAccessInterface(uuid);
7722         if (iFace != NULL)
7723         {
7724             iDataStreamInterface = OSCL_STATIC_CAST(PVMIDataStreamSyncInterface*, iFace);
7725             iDataStreamInterface->OpenSession(iDataStreamSessionID, PVDS_READ_ONLY);
7726         }
7727     }
7728     else
7729     {
7730         OSCL_ASSERT(false);
7731     }
7732 }
7733 
7734 void
PassDatastreamReadCapacityObserver(PVMFDataStreamReadCapacityObserver * aObserver)7735 PVMFMP4FFParserNode::PassDatastreamReadCapacityObserver(PVMFDataStreamReadCapacityObserver* aObserver)
7736 {
7737     iDataStreamReadCapacityObserver = aObserver;
7738 }
7739 
7740 
CheckForMP4HeaderAvailability()7741 PVMFStatus PVMFMP4FFParserNode::CheckForMP4HeaderAvailability()
7742 {
7743     if (iFastTrackSession == true) return PVMFSuccess;
7744 
7745     if (iDataStreamInterface != NULL)
7746     {
7747         /*
7748          * First check if we have minimum number of bytes to recognize
7749          * the file and determine the header size.
7750          */
7751         uint32 currCapacity = 0;
7752         iDataStreamInterface->QueryReadCapacity(iDataStreamSessionID,
7753                                                 currCapacity);
7754 
7755         if (currCapacity <  MP4_MIN_BYTES_FOR_GETTING_MOVIE_HDR_SIZE)
7756         {
7757             iRequestReadCapacityNotificationID =
7758                 iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID,
7759                         *this,
7760                         MP4_MIN_BYTES_FOR_GETTING_MOVIE_HDR_SIZE);
7761             iDataStreamRequestPending = true;
7762             return PVMFPending;
7763         }
7764 
7765 
7766         bool isProgressiveDownloadable = false;
7767         MP4_ERROR_CODE retCode =
7768             IMpeg4File::GetMetaDataSize(iDataStreamFactory,
7769                                         isProgressiveDownloadable,
7770                                         iMP4HeaderSize);
7771 
7772         if (retCode == EVERYTHING_FINE)
7773         {
7774             if (isProgressiveDownloadable == true)
7775             {
7776                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - MetaData ends at file offset %d", iMP4HeaderSize));
7777                 iProgressivelyDownlodable = true;
7778                 // inform data stream that a range of bytes needs to be cached persistently (offset 0, size of moov atom)
7779                 iDataStreamInterface->MakePersistent(0, iMP4HeaderSize);
7780 
7781                 if (currCapacity < iMP4HeaderSize)
7782                 {
7783                     iRequestReadCapacityNotificationID =
7784                         iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID,
7785                                 *this,
7786                                 iMP4HeaderSize);
7787                     iDataStreamRequestPending = true;
7788                     return PVMFPending;
7789                 }
7790                 else
7791                 {
7792                     return PVMFSuccess;
7793                 }
7794             }
7795             else
7796             {
7797                 iProgressivelyDownlodable = false;
7798 
7799                 PVUuid uuid = PVMFFileFormatEventTypesUUID;
7800                 int32 infocode = PVMFMP4FFParserInfoNotPseudostreamableFile;
7801                 ReportMP4FFParserInfoEvent(PVMFInfoRemoteSourceNotification, NULL, &uuid, &infocode);
7802                 /*
7803                  * Wait for download complete
7804                  */
7805                 if (download_progress_interface != NULL)
7806                 {
7807                     uint32 nptTsinMS = 0xFFFFFFFF;
7808 
7809                     if ((NULL != iDataStreamInterface) && (0 != iDataStreamInterface->QueryBufferingCapacity()))
7810                     {
7811                         // if progressive streaming, playResumeNotifcation is guaranteed to be called
7812                         // with the proper download complete state, ignore the current download status
7813                         bool dlcomplete = false;
7814                         download_progress_interface->requestResumeNotification(nptTsinMS, dlcomplete);
7815                     }
7816                     else
7817                     {
7818                         download_progress_interface->requestResumeNotification(nptTsinMS, iDownloadComplete);
7819                     }
7820                     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - Auto Pause Triggered, TS = %d", nptTsinMS));
7821                     return PVMFPending;
7822                 }
7823                 else
7824                 {
7825                     PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - download_progress_interface not available"));
7826                 }
7827             }
7828         }
7829         else if (retCode == INSUFFICIENT_DATA)
7830         {
7831             iRequestReadCapacityNotificationID =
7832                 iDataStreamInterface->RequestReadCapacityNotification(iDataStreamSessionID,
7833                         *this,
7834                         (iMP4HeaderSize + MP4_MIN_BYTES_FOR_GETTING_MOVIE_HDR_SIZE));
7835             iDataStreamRequestPending = true;
7836             return PVMFPending;
7837         }
7838         else if (retCode == NOT_PROGRESSIVE_STREAMABLE)
7839         {
7840             // progressive playback and no movie atom found
7841             PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - Moov atom not found, needed for progressive playback"));
7842             return PVMFErrContentInvalidForProgressivePlayback;
7843         }
7844         else
7845         {
7846             PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForMP4HeaderAvailability() - GetMetaDataSize Failed %d", retCode));
7847         }
7848 
7849         return PVMFFailure;
7850     }
7851     return PVMFSuccess;
7852 }
7853 
CheckForUnderFlow(PVMP4FFNodeTrackPortInfo * aInfo)7854 PVMFStatus PVMFMP4FFParserNode::CheckForUnderFlow(PVMP4FFNodeTrackPortInfo* aInfo)
7855 {
7856     uint32 timebase32 = 0;
7857     uint32 clientClock32 = 0;
7858     bool overload = 0;
7859     if (iClientPlayBackClock != NULL)
7860     {
7861         iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32);
7862     }
7863     else
7864     {
7865         return PVMFFailure;
7866     }
7867 
7868     MediaClockConverter clock_conv(*(aInfo->iClockConverter));
7869     clock_conv.update_clock(aInfo->iTimestamp);
7870     uint32 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE);
7871     if (clientClock32 <= msec)
7872     {
7873         uint32 diff32 = (msec - clientClock32);
7874         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Diff Bet Client Clock(%d) and Track Media TS(%d) = %d", clientClock32, msec, diff32));
7875         if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS || aInfo->iFormatType == PVMF_MIME_AMR_IETF || aInfo->iFormatType == PVMF_MIME_MPEG4_AUDIO)
7876         {
7877             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Time To Auto Pause"));
7878             return PVMFSuccess;
7879         }
7880         else
7881         {
7882             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Setting UnderFlow Timer"));
7883             iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID,
7884                                           0,
7885                                           PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES,
7886                                           this);
7887         }
7888     }
7889     else
7890     {
7891         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Client Clock Greater than Media TS, Clock=%d, MaxMTS=%d",  clientClock32, msec));
7892         OSCL_ASSERT(false);
7893     }
7894 
7895     /* Check if all tracks are autopaused. If so, it is time to autopause the node */
7896     bool oAllTracksAutoPaused = true;
7897     Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
7898     for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
7899     {
7900         if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE)
7901         {
7902             oAllTracksAutoPaused = false;
7903         }
7904     }
7905     if (oAllTracksAutoPaused == true)
7906     {
7907         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - All Tracks AutoPaused - Time To Auto Pause"));
7908         return PVMFSuccess;
7909     }
7910     //not yet time to autopause
7911     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CheckForUnderFlow - Wait on player clock for Auto Pause"));
7912     return PVMFPending;
7913 }
7914 
7915 
ReportUnderFlow()7916 PVMFStatus PVMFMP4FFParserNode::ReportUnderFlow()
7917 {
7918     /* Check if all tracks are autopaused. If so, it is time to autopause the node */
7919     bool oAllTracksAutoPaused = true;
7920     Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
7921     for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
7922     {
7923         if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE)
7924         {
7925             oAllTracksAutoPaused = false;
7926         }
7927     }
7928     if (oAllTracksAutoPaused == true)
7929     {
7930         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Reporting UnderFlow"));
7931         ReportInfoEvent(PVMFInfoUnderflow);
7932         iUnderFlowEventReported = true;
7933         return PVMFSuccess;
7934     }
7935 
7936 
7937     uint32 minTS = 0xFFFFFFFF;
7938     for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
7939     {
7940         if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE)
7941         {
7942             MediaClockConverter clock_conv(*(it->iClockConverter));
7943             clock_conv.update_clock(it->iTimestamp);
7944             uint32 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE);
7945             if (msec < minTS)
7946             {
7947                 minTS = msec;
7948             }
7949         }
7950     }
7951     uint32 timebase32 = 0;
7952     uint32 clientClock32 = 0;
7953     bool overload = 0;
7954 
7955     if (iClientPlayBackClock != NULL)
7956         iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32);
7957 
7958 
7959     uint32 currentFileSize = 0;
7960     MP4_ERROR_CODE code = iMP4FileHandle->GetCurrentFileSize(currentFileSize);
7961     if (code != EVERYTHING_FINE)
7962     {
7963         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::ReportUnderFlow - GetCurrentFileSize Failed - Ret=%d",  code));
7964         return PVMFFailure;
7965     }
7966 
7967     iUnderFlowEventReported = false;
7968     uint32 currNPT = 0;
7969     convertSizeToTime(currentFileSize, currNPT);
7970 
7971     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - ClientClock = %d", clientClock32));
7972     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - NPTInMS = %d, FileSize = %d", currNPT, currentFileSize));
7973     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Min Media TS = %d", minTS));
7974 
7975     if (clientClock32 <= minTS)
7976     {
7977         uint32 diff32 = (minTS - clientClock32);
7978         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Diff Bet Client Clock and Min Media TS = %d", diff32));
7979         if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS)
7980         {
7981             /* If parserNode is reporting Underflow, all tracks should be in auto-paused state */
7982             for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
7983             {
7984                 if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE)
7985                 {
7986                     it->iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE;
7987                 }
7988             }
7989             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Reporting UnderFlow"));
7990             ReportInfoEvent(PVMFInfoUnderflow);
7991             iUnderFlowEventReported = true;
7992         }
7993         else
7994         {
7995             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::ReportUnderFlow - Setting UnderFlow Timer"));
7996             iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID,
7997                                           0,
7998                                           PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES,
7999                                           this);
8000         }
8001     }
8002     else
8003     {
8004         PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::ReportUnderFlow - Client Clock Greater than Min Media TS, Clock=%d, MaxMTS=%d",  clientClock32, minTS));
8005         OSCL_ASSERT(false);
8006     }
8007     return PVMFSuccess;
8008 }
8009 
TimeoutOccurred(int32 timerID,int32 timeoutInfo)8010 void PVMFMP4FFParserNode::TimeoutOccurred(int32 timerID,
8011         int32 timeoutInfo)
8012 {
8013     OSCL_UNUSED_ARG(timeoutInfo);
8014 
8015     if (timerID == PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID)
8016     {
8017         if (autopaused == true && iUnderFlowEventReported == false)
8018         {
8019             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - UnderFlow TimeOut - Still AutoPaused"));
8020             uint32 currentFileSize = 0;
8021             MP4_ERROR_CODE code = iMP4FileHandle->GetCurrentFileSize(currentFileSize);
8022             if (code == EVERYTHING_FINE)
8023             {
8024                 uint32 currNPT = 0;
8025                 convertSizeToTime(currentFileSize, currNPT);
8026 
8027                 uint32 minTS = 0xFFFFFFFF;
8028                 Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
8029                 for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
8030                 {
8031                     if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE)
8032                     {
8033                         MediaClockConverter clock_conv(*(it->iClockConverter));
8034                         clock_conv.update_clock(it->iTimestamp);
8035                         uint32 msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE);
8036                         if (msec < minTS)
8037                         {
8038                             minTS = msec;
8039                         }
8040                     }
8041                 }
8042                 uint32 timebase32 = 0;
8043                 uint32 clientClock32 = 0;
8044                 bool overload = 0;
8045                 if (iClientPlayBackClock != NULL)
8046                     iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32);
8047 
8048 
8049                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - ClientClock = %d", clientClock32));
8050                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - NPTInMS = %d,  FileSize = %d", currNPT, currentFileSize));
8051                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Min Media TS = %d", minTS));
8052 
8053                 if (clientClock32 <= minTS)
8054                 {
8055                     uint32 diff32 = (minTS - clientClock32);
8056                     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Diff Bet Client Clock and Min Media TS = %d", diff32));
8057                     if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS)
8058                     {
8059                         /* If parserNode is reporting Underflow, all tracks should be in auto-paused state */
8060                         for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
8061                         {
8062                             if (it->iState != PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE)
8063                             {
8064                                 it->iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE;
8065                             }
8066                         }
8067 
8068                         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Reporting UnderFlow"));
8069                         ReportInfoEvent(PVMFInfoUnderflow);
8070                         iUnderFlowEventReported = true;
8071                     }
8072                     else
8073                     {
8074                         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Requesting Additional Time Out"));
8075                         iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID,
8076                                                       0,
8077                                                       PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES,
8078                                                       this);
8079                     }
8080                 }
8081                 else
8082                 {
8083                     PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::TimeoutOccurred - Client Clock Greater than Min Media TS, Clock=%d, MaxMTS=%d",  clientClock32, minTS));
8084                     OSCL_ASSERT(false);
8085                 }
8086 
8087             }
8088             else
8089             {
8090                 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::TimeoutOccurred - GetCurrentFileSize Failed - Ret=%d",  code));
8091                 ReportErrorEvent(PVMFErrResource);
8092             }
8093         }
8094         else if (iDownloadComplete == false && iUnderFlowEventReported == false)
8095         {
8096             uint32 timebase32 = 0;
8097             uint32 clientClock32 = 0;
8098             bool overload = 0;
8099             uint32 msec = 0;
8100             if (iClientPlayBackClock != NULL)
8101             {
8102                 iClientPlayBackClock->GetCurrentTime32(clientClock32, overload, PVMF_MEDIA_CLOCK_MSEC, timebase32);
8103             }
8104 
8105             Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
8106             for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
8107             {
8108                 if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA)
8109                 {
8110                     MediaClockConverter clock_conv(*(it->iClockConverter));
8111                     clock_conv.update_clock(it->iTimestamp);
8112                     msec = clock_conv.get_converted_ts(MILLISECOND_TIMESCALE);
8113                 }
8114             }
8115 
8116             if (clientClock32 <= msec)
8117             {
8118                 uint32 diff32 = (msec - clientClock32);
8119                 PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Diff Bet Client Clock(%d) and Track Media TS(%d) = %d", clientClock32, msec, diff32));
8120                 if (diff32 < PVMP4FF_UNDERFLOW_THRESHOLD_IN_MS)
8121                 {
8122                     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Time To Auto Pause"));
8123                     for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
8124                     {
8125                         if (it->iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_INSUFFICIENTDATA)
8126                         {
8127                             it->iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DOWNLOAD_AUTOPAUSE;
8128                         }
8129                     }
8130                     autopaused = true;
8131                     ReportUnderFlow();
8132                 }
8133                 else
8134                 {
8135                     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - Setting UnderFlow Timer"));
8136                     iUnderFlowCheckTimer->Request(PVMF_MP4FFPARSERNODE_UNDERFLOW_STATUS_TIMER_ID,
8137                                                   0,
8138                                                   PVMP4FF_UNDERFLOW_STATUS_EVENT_CYCLES,
8139                                                   this);
8140                 }
8141             }
8142             else
8143             {
8144                 PVMF_MP4FFPARSERNODE_LOGERROR((0, "PVMFMP4FFParserNode::TimeoutOccurred - Client Clock Greater than Media TS, Clock=%d, MaxMTS=%d",  clientClock32, msec));
8145                 //should never happen
8146                 OSCL_ASSERT(false);
8147             }
8148             PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::TimeoutOccurred - UnderFlow TimeOut - After AutoResume"));
8149         }
8150     }
8151     return;
8152 }
8153 
8154 void
LogMediaData(PVMFSharedMediaDataPtr data,PVMFPortInterface * aPort)8155 PVMFMP4FFParserNode::LogMediaData(PVMFSharedMediaDataPtr data,
8156                                   PVMFPortInterface* aPort)
8157 {
8158     PVMP4FFNodeTrackPortInfo* trackInfoPtr = NULL;
8159     if (!GetTrackPortInfoForPort(trackInfoPtr, aPort))
8160     {
8161         return;
8162     }
8163 
8164     bool ologSizeTS = false;
8165 
8166     /* Get Format Specific Info, if any */
8167     if (trackInfoPtr->oFormatSpecificInfoLogged == false)
8168     {
8169         uint32 size = trackInfoPtr->iFormatSpecificConfig.getMemFragSize();
8170         if (size > 0)
8171         {
8172             PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, size, trackInfoPtr->iFormatSpecificConfig.getMemFragPtr()));
8173         }
8174         trackInfoPtr->oFormatSpecificInfoLogged = true;
8175     }
8176 
8177     ologSizeTS = false;
8178 
8179     PVMFMediaData* mediaData = data.GetRep();
8180     if (mediaData != NULL)
8181     {
8182         /* Log Media Fragments */
8183         uint32 numMediaFragments = mediaData->getNumFragments();
8184         for (uint32 i = 0; i < numMediaFragments; i++)
8185         {
8186             OsclRefCounterMemFrag memFrag;
8187             mediaData->getMediaFragment(i, memFrag);
8188             if (ologSizeTS)
8189             {
8190                 PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, sizeof(uint32), memFrag.getMemFragSize()));
8191                 PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, sizeof(uint32), data->getTimestamp()));
8192             }
8193             PVMF_MP4FFPARSERNODE_LOGBIN(trackInfoPtr->iPortLogger, (0, 1, memFrag.getMemFragSize(), memFrag.getMemFragPtr()));
8194         }
8195     }
8196 }
8197 
LogDiagnostics()8198 void PVMFMP4FFParserNode::LogDiagnostics()
8199 {
8200     if (iDiagnosticsLogged == false)
8201     {
8202         iDiagnosticsLogged = true;
8203         Oscl_Vector<PVMP4FFNodeTrackPortInfo, OsclMemAllocator>::iterator it;
8204 
8205         if (&iNodeTrackPortList)
8206         {
8207             it = iNodeTrackPortList.begin();
8208             for (it = iNodeTrackPortList.begin(); it != iNodeTrackPortList.end(); it++)
8209             {
8210                 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"));
8211                 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Time Taken in Read MP4 File  =%d", iTimeTakenInReadMP4File));
8212                 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Minimum Time  =%2d", it->iMinTime));
8213                 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Maximum Time  =%2d", it->iMaxTime));
8214                 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Total Time  =%2d", it->iSumTime));
8215 
8216                 uint64 avg_time = 0;
8217                 if ((it->iNumTimesMediaSampleRead) > 0)
8218                     avg_time = Oscl_Int64_Utils::get_uint64_lower32(it->iSumTime) / (it->iNumTimesMediaSampleRead);
8219 
8220                 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Read Media Sample Avg Time  =%2d", avg_time));
8221                 PVMF_MP4FFPARSERNODE_LOGDIAGNOSTICS((0, "PVMFMP4FFParserNode - Number of Sample Read each time  =%d", it->iNumSamples));
8222 
8223 
8224             }
8225         }
8226     }
8227 }
8228 
GetVideoFrameWidth(uint32 aId,int32 & aWidth,int32 & aDisplayWidth)8229 PVMFStatus PVMFMP4FFParserNode::GetVideoFrameWidth(uint32 aId, int32& aWidth, int32& aDisplayWidth)
8230 {
8231     int32 height = 0;
8232     int32 width = 0;
8233     int32 display_width = 0;
8234     int32 display_height = 0;
8235 
8236     OSCL_HeapString<OsclMemAllocator> trackMIMEType;
8237 
8238     iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType);
8239 
8240     if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H2632000, oscl_strlen(PVMF_MIME_H2632000)) == 0)
8241     {
8242         H263DecoderSpecificInfo *ptr =
8243             (H263DecoderSpecificInfo *)iMP4FileHandle->getTrackDecoderSpecificInfoAtSDI(aId, 0);
8244 
8245         //In case of H263 display dimension and decode dimesnion cannot be different,so pass
8246         //aDisplayHeight as parser level info and Height from decoder utility
8247 
8248         if (ptr != NULL)
8249         {
8250             if (ptr->getMaxWidth() > 0)
8251             {
8252                 aDisplayWidth = display_width = (int32)(ptr->getMaxWidth());
8253             }
8254         }
8255 
8256         if (width == 0)
8257         {
8258             //get width from the first frame
8259             MediaMetaInfo info;
8260             uint32 numSamples = 1;
8261             int32 retval = EVERYTHING_FINE;
8262             retval = iMP4FileHandle->peekNextBundledAccessUnits(aId,
8263                      &numSamples,
8264                      &info);
8265             if ((retval == EVERYTHING_FINE || END_OF_TRACK == retval) && numSamples > 0)
8266             {
8267                 uint32 sampleSize = info.len;
8268                 if (sampleSize > 0)
8269                 {
8270                     uint8* sampleBuf = OSCL_ARRAY_NEW(uint8, sampleSize);
8271 
8272                     oscl_memset(&iGau.buf, 0, sizeof(iGau.buf));
8273                     oscl_memset(&iGau.info, 0, sizeof(iGau.info));
8274                     iGau.free_buffer_states_when_done = 0;
8275                     iGau.numMediaSamples = 1;
8276                     iGau.buf.num_fragments = 1;
8277                     iGau.buf.buf_states[0] = NULL;
8278                     iGau.buf.fragments[0].ptr = (OsclAny*)sampleBuf;
8279                     iGau.buf.fragments[0].len = sampleSize;
8280                     retval =
8281                         iMP4FileHandle->getNextBundledAccessUnits(aId,
8282                                 &numSamples,
8283                                 &iGau);
8284                     if ((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK))
8285                     {
8286                         mp4StreamType streamType;
8287                         streamType.data = sampleBuf;
8288                         streamType.numBytes = sampleSize;
8289                         streamType.bytePos = 0;
8290                         streamType.bitBuf = 0;
8291                         streamType.dataBitPos = 0;
8292                         streamType.bitPos = 32;
8293 
8294                         int16 status =
8295                             iDecodeShortHeader(&streamType,
8296                                                (int32*) & width,
8297                                                (int32*) & height,
8298                                                (int32*) & display_width,
8299                                                (int32*) & display_height);
8300                         if (status != 0)
8301                         {
8302                             return PVMFFailure;
8303                         }
8304 
8305                         aWidth = width;
8306                         if (aDisplayWidth == 0)
8307                         {
8308                             aDisplayWidth = display_width;
8309                         }
8310                     }
8311                     iMP4FileHandle->resetPlayback();
8312                     OSCL_ARRAY_DELETE(sampleBuf);
8313                 }
8314             }
8315         }
8316 
8317     }
8318     else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H264_VIDEO_MP4, oscl_strlen(PVMF_MIME_H264_VIDEO_MP4)) == 0)
8319     {
8320         display_width = iMP4FileHandle->getVideoFrameWidth(aId);
8321         if (display_width > 0)
8322         {
8323             aDisplayWidth = display_width;
8324         }
8325 
8326         uint32 specinfosize =
8327             iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId);
8328         if (specinfosize != 0)
8329         {
8330             // Retrieve the decoder specific info from file parser
8331             uint8* specinfoptr =
8332                 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId);
8333             int32 profile, level = 0;// this info is discarded
8334             int16 status =
8335                 iGetAVCConfigInfo(specinfoptr,
8336                                   (int32)specinfosize,
8337                                   (int32*) & width,
8338                                   (int32*) & height,
8339                                   (int32*) & display_width,
8340                                   (int32*) & display_height,
8341                                   (int32*) & profile,
8342                                   (int32*) & level);
8343             if (status != 0)
8344             {
8345                 return PVMFFailure;
8346             }
8347 
8348             aWidth = width;
8349 
8350             if (aDisplayWidth == 0)
8351                 aDisplayWidth = display_width;
8352         }
8353     }
8354     else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_M4V, oscl_strlen(PVMF_MIME_M4V)) == 0)
8355     {
8356         display_width = iMP4FileHandle->getVideoFrameWidth(aId);
8357         if (display_width > 0)
8358         {
8359             aDisplayWidth = display_width;
8360         }
8361 
8362         uint32 specinfosize =
8363             iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId);
8364         if (specinfosize != 0)
8365         {
8366             // Retrieve the decoder specific info from file parser
8367             uint8* specinfoptr =
8368                 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId);
8369             int16 status =
8370                 iGetM4VConfigInfo(specinfoptr,
8371                                   (int32)specinfosize,
8372                                   (int32*) & width,
8373                                   (int32*) & height,
8374                                   (int32*) & display_width,
8375                                   (int32*) & display_height);
8376             if (status != 0)
8377             {
8378                 return PVMFFailure;
8379             }
8380 
8381             aWidth = width;
8382 
8383             if (aDisplayWidth == 0)
8384                 aDisplayWidth = display_width;
8385         }
8386     }
8387 
8388     return PVMFSuccess;
8389 }
8390 
GetVideoFrameHeight(uint32 aId,int32 & aHeight,int32 & aDisplayHeight)8391 PVMFStatus PVMFMP4FFParserNode::GetVideoFrameHeight(uint32 aId, int32& aHeight, int32& aDisplayHeight)
8392 {
8393     int32 height = 0;
8394     int32 width = 0;
8395     int32 display_width = 0;
8396     int32 display_height = 0;
8397 
8398     OSCL_HeapString<OsclMemAllocator> trackMIMEType;
8399     iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType);
8400 
8401     if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H2632000, oscl_strlen(PVMF_MIME_H2632000)) == 0)
8402     {
8403         H263DecoderSpecificInfo *ptr =
8404             (H263DecoderSpecificInfo *)iMP4FileHandle->getTrackDecoderSpecificInfoAtSDI(aId, 0);
8405 
8406         //In case of H263 display dimension and decode dimesnion cannot be different,so pass
8407         //aDisplayHeight as parser level info and Height from decoder utility
8408         if (ptr != NULL)
8409         {
8410             if (ptr->getMaxHeight() > 0)
8411             {
8412                 aDisplayHeight = display_height = (int32)(ptr->getMaxHeight());
8413             }
8414         }
8415         if (height == 0)
8416         {
8417             //get height from the first frame
8418             MediaMetaInfo info;
8419             uint32 numSamples = 1;
8420             int32 retval = EVERYTHING_FINE;
8421             retval = iMP4FileHandle->peekNextBundledAccessUnits(aId,
8422                      &numSamples,
8423                      &info);
8424             if ((retval == EVERYTHING_FINE || END_OF_TRACK == retval) && numSamples > 0)
8425             {
8426                 uint32 sampleSize = info.len;
8427                 if (sampleSize > 0)
8428                 {
8429                     uint8* sampleBuf = OSCL_ARRAY_NEW(uint8, sampleSize);
8430 
8431                     oscl_memset(&iGau.buf, 0, sizeof(iGau.buf));
8432                     oscl_memset(&iGau.info, 0, sizeof(iGau.info));
8433                     iGau.free_buffer_states_when_done = 0;
8434                     iGau.numMediaSamples = 1;
8435                     iGau.buf.num_fragments = 1;
8436                     iGau.buf.buf_states[0] = NULL;
8437                     iGau.buf.fragments[0].ptr = (OsclAny*)sampleBuf;
8438                     iGau.buf.fragments[0].len = sampleSize;
8439                     retval =
8440                         iMP4FileHandle->getNextBundledAccessUnits(aId,
8441                                 &numSamples,
8442                                 &iGau);
8443                     if ((retval == EVERYTHING_FINE) || (retval == END_OF_TRACK))
8444                     {
8445                         mp4StreamType streamType;
8446                         streamType.data = sampleBuf;
8447                         streamType.numBytes = sampleSize;
8448                         streamType.bytePos = 0;
8449                         streamType.bitBuf = 0;
8450                         streamType.dataBitPos = 0;
8451                         streamType.bitPos = 32;
8452 
8453                         int16 status =
8454                             iDecodeShortHeader(&streamType,
8455                                                (int32*) & width,
8456                                                (int32*) & height,
8457                                                (int32*) & display_width,
8458                                                (int32*) & display_height);
8459                         if (status != 0)
8460                         {
8461                             return PVMFFailure;
8462                         }
8463 
8464                         if (aDisplayHeight == 0)
8465                         {
8466                             aDisplayHeight = display_height;
8467                         }
8468                         aHeight = height;
8469                     }
8470                     iMP4FileHandle->resetPlayback();
8471                     OSCL_ARRAY_DELETE(sampleBuf);
8472                 }
8473             }
8474         }
8475     }
8476     if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_H264_VIDEO_MP4, oscl_strlen(PVMF_MIME_H264_VIDEO_MP4)) == 0)
8477     {
8478         display_height = iMP4FileHandle->getVideoFrameHeight(aId);
8479         if (display_height > 0)
8480         {
8481             aDisplayHeight = display_height;
8482         }
8483 
8484         uint32 specinfosize =
8485             iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId);
8486         if (specinfosize != 0)
8487         {
8488             // Retrieve the decoder specific info from file parser
8489             uint8* specinfoptr =
8490                 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId);
8491             int profile, level = 0; // this info is discarded here
8492             int16 status =
8493                 iGetAVCConfigInfo(specinfoptr,
8494                                   (int32)specinfosize,
8495                                   (int32*) & width,
8496                                   (int32*) & height,
8497                                   (int32*) & display_width,
8498                                   (int32*) & display_height,
8499                                   (int32*) & profile,
8500                                   (int32*) & level);
8501             if (status != 0)
8502             {
8503                 return PVMFFailure;
8504             }
8505 
8506             aHeight = height;
8507 
8508             if (aDisplayHeight == 0)
8509                 aDisplayHeight = display_height;
8510         }
8511     }
8512     else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_M4V, oscl_strlen(PVMF_MIME_M4V)) == 0)
8513     {
8514         display_height = iMP4FileHandle->getVideoFrameHeight(aId);
8515         if (display_height > 0)
8516         {
8517             aDisplayHeight = display_height;
8518         }
8519 
8520         uint32 specinfosize =
8521             iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId);
8522         if (specinfosize != 0)
8523         {
8524             // Retrieve the decoder specific info from file parser
8525             uint8* specinfoptr =
8526                 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId);
8527             int16 status =
8528                 iGetM4VConfigInfo(specinfoptr,
8529                                   (int32)specinfosize,
8530                                   (int32*) & width,
8531                                   (int32*) & height,
8532                                   (int32*) & display_width,
8533                                   (int32*) & display_height);
8534             if (status != 0)
8535             {
8536                 return PVMFFailure;
8537             }
8538 
8539             aHeight = height;
8540 
8541             if (aDisplayHeight == 0)
8542                 aDisplayHeight = display_height;
8543 
8544         }
8545     }
8546 
8547     return PVMFSuccess;
8548 }
8549 
PopulateVideoDimensions(uint32 aId)8550 PVMFStatus PVMFMP4FFParserNode::PopulateVideoDimensions(uint32 aId)
8551 {
8552     VideoTrackDimensionInfo vidDimInfo;
8553     vidDimInfo.iTrackId = aId;
8554     if (PVMFSuccess != GetVideoFrameWidth(aId, vidDimInfo.iWidth, vidDimInfo.iDisplayWidth))
8555     {
8556         return PVMFFailure;
8557     }
8558     if (PVMFSuccess != GetVideoFrameHeight(aId, vidDimInfo.iHeight, vidDimInfo.iDisplayHeight))
8559     {
8560         return PVMFFailure;
8561     }
8562     iVideoDimensionInfoVec.push_back(vidDimInfo);
8563     return PVMFSuccess;
8564 }
8565 
FindVideoWidth(uint32 aId)8566 int32 PVMFMP4FFParserNode::FindVideoWidth(uint32 aId)
8567 {
8568     int32 width = 0;
8569     Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it;
8570     for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++)
8571     {
8572         if (it->iTrackId == aId)
8573         {
8574             width = it->iWidth;
8575         }
8576     }
8577     return width;
8578 }
8579 
FindVideoHeight(uint32 aId)8580 int32 PVMFMP4FFParserNode::FindVideoHeight(uint32 aId)
8581 {
8582     int32 height = 0;
8583     Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it;
8584     for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++)
8585     {
8586         if (it->iTrackId == aId)
8587         {
8588             height = it->iHeight;
8589         }
8590     }
8591     return height;
8592 }
8593 
FindVideoDisplayWidth(uint32 aId)8594 int32 PVMFMP4FFParserNode::FindVideoDisplayWidth(uint32 aId)
8595 {
8596     int32 display_width = 0;
8597     Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it;
8598     for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++)
8599     {
8600         if (it->iTrackId == aId)
8601         {
8602             display_width = it->iDisplayWidth;
8603         }
8604     }
8605     return display_width;
8606 }
8607 
FindVideoDisplayHeight(uint32 aId)8608 int32 PVMFMP4FFParserNode::FindVideoDisplayHeight(uint32 aId)
8609 {
8610     int32 display_height = 0;
8611     Oscl_Vector<VideoTrackDimensionInfo, OsclMemAllocator>::iterator it;
8612     for (it = iVideoDimensionInfoVec.begin(); it != iVideoDimensionInfoVec.end(); it++)
8613     {
8614         if (it->iTrackId == aId)
8615         {
8616             display_height = it->iDisplayHeight;
8617         }
8618     }
8619     return display_height;
8620 }
8621 
GetNumAudioChannels(uint32 aId)8622 uint32 PVMFMP4FFParserNode::GetNumAudioChannels(uint32 aId)
8623 {
8624     uint32 num_channels = 0;
8625     uint8 audioObjectType;
8626     uint8 sampleRateIndex;
8627 
8628     OSCL_HeapString<OsclMemAllocator> trackMIMEType;
8629     iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType);
8630 
8631     if ((oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR, oscl_strlen(PVMF_MIME_AMR)) == 0) ||
8632             (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR_IETF, oscl_strlen(PVMF_MIME_AMR_IETF)) == 0) ||
8633             (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMRWB_IETF, oscl_strlen(PVMF_MIME_AMRWB_IETF)) == 0))
8634     {
8635         //always mono
8636         num_channels = 1;
8637     }
8638     else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_MPEG4_AUDIO, oscl_strlen(PVMF_MIME_MPEG4_AUDIO)) == 0)
8639     {
8640         int32 specinfosize =
8641             (int32)(iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId));
8642         if (specinfosize != 0)
8643         {
8644             // Retrieve the decoder specific info from file parser
8645             uint8* specinfoptr =
8646                 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId);
8647 
8648             GetActualAacConfig(specinfoptr,
8649                                &audioObjectType,
8650                                &specinfosize,
8651                                &sampleRateIndex,
8652                                &num_channels);
8653         }
8654     }
8655 
8656     return num_channels;
8657 }
8658 
GetAudioSampleRate(uint32 aId)8659 uint32 PVMFMP4FFParserNode::GetAudioSampleRate(uint32 aId)
8660 {
8661     uint32 sample_rate = 0;
8662     uint32 num_channels;
8663     uint8 audioObjectType;
8664     uint8 sampleRateIndex;
8665 
8666     const uint32 sample_freq_table[13] =
8667         {96000, 88200, 64000, 48000,
8668          44100, 32000, 24000, 22050,
8669          16000, 12000, 11025, 8000,
8670          7350
8671         };
8672 
8673     OSCL_HeapString<OsclMemAllocator> trackMIMEType;
8674     iMP4FileHandle->getTrackMIMEType(aId, trackMIMEType);
8675 
8676     if ((oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR, oscl_strlen(PVMF_MIME_AMR)) == 0) ||
8677             (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMR_IETF, oscl_strlen(PVMF_MIME_AMR_IETF)) == 0))
8678     {
8679         //always 8KHz
8680         sample_rate = 8000;
8681     }
8682     else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_AMRWB_IETF, oscl_strlen(PVMF_MIME_AMRWB_IETF)) == 0)
8683     {
8684         //always 16KHz
8685         sample_rate = 16000;
8686     }
8687     else if (oscl_strncmp(trackMIMEType.get_str(), PVMF_MIME_MPEG4_AUDIO, oscl_strlen(PVMF_MIME_MPEG4_AUDIO)) == 0)
8688     {
8689         int32 specinfosize =
8690             (int32)(iMP4FileHandle->getTrackDecoderSpecificInfoSize(aId));
8691         if (specinfosize != 0)
8692         {
8693             // Retrieve the decoder specific info from file parser
8694             uint8* specinfoptr =
8695                 iMP4FileHandle->getTrackDecoderSpecificInfoContent(aId);
8696 
8697             GetActualAacConfig(specinfoptr,
8698                                &audioObjectType,
8699                                &specinfosize,
8700                                &sampleRateIndex,
8701                                &num_channels);
8702             if (sampleRateIndex < 13)
8703             {
8704                 sample_rate = sample_freq_table[(uint32)sampleRateIndex];
8705             }
8706         }
8707     }
8708     return sample_rate;
8709 }
8710 
GetAudioBitsPerSample(uint32 aId)8711 uint32 PVMFMP4FFParserNode::GetAudioBitsPerSample(uint32 aId)
8712 {
8713     OSCL_UNUSED_ARG(aId);
8714     //always 16 bits per samples
8715     return 16;
8716 }
8717 
FindBestThumbnailKeyFrame(uint32 aId,uint32 & aKeyFrameNum)8718 PVMFStatus PVMFMP4FFParserNode::FindBestThumbnailKeyFrame(uint32 aId, uint32& aKeyFrameNum)
8719 {
8720     aKeyFrameNum = PVMFFF_DEFAULT_THUMB_NAIL_SAMPLE_NUMBER;
8721 
8722     // Use the MP4 FF API to retrieve the number of sync samples in a track
8723     uint32 numsamples = 0;
8724     int32 retval = iMP4FileHandle->getTimestampForRandomAccessPoints(aId,
8725                    &numsamples,
8726                    NULL,
8727                    NULL);
8728     if (retval == 1 && numsamples > 0)
8729     {
8730         /* It is possible that for some big contents the number of sync samples is a very big
8731         ** value. For these contents retrieval of timesatamps and frame numbers of sync sample
8732         ** will take long time. With NUMSAMPLES_BEST_THUMBNAIL_MODE Parser will try to find
8733         ** best thumbnail frame out of first 10 sync samples.
8734         */
8735         if (numsamples > NUMSAMPLES_BEST_THUMBNAIL_MODE)
8736         {
8737             numsamples = NUMSAMPLES_BEST_THUMBNAIL_MODE;
8738         }
8739         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - NumKeySamples=%d, TrackID=%d", numsamples, aId));
8740 
8741         // Allocate memory for the info
8742         uint32* syncts = OSCL_ARRAY_NEW(uint32, numsamples);
8743         uint32* syncfrnum = OSCL_ARRAY_NEW(uint32, numsamples);
8744         if (syncts == NULL || syncfrnum == NULL)
8745         {
8746             if (syncts)
8747             {
8748                 OSCL_ARRAY_DELETE(syncts);
8749             }
8750             if (syncfrnum)
8751             {
8752                 OSCL_ARRAY_DELETE(syncfrnum);
8753             }
8754             return PVMFErrNoMemory;
8755         }
8756 
8757         // Retrieve the list of timestamp and frame numbers for sync samples.
8758         retval =
8759             iMP4FileHandle->getTimestampForRandomAccessPoints(aId,
8760                     &numsamples,
8761                     syncts,
8762                     syncfrnum);
8763         if (retval != 1)
8764         {
8765             // Error
8766             if (syncts)
8767             {
8768                 OSCL_ARRAY_DELETE(syncts);
8769             }
8770             if (syncfrnum)
8771             {
8772                 OSCL_ARRAY_DELETE(syncfrnum);
8773             }
8774             numsamples = 0;
8775             aKeyFrameNum = 0;
8776             return PVMFSuccess;
8777         }
8778 
8779         uint64 trackduration;
8780         uint32 samplecount;
8781         trackduration = iMP4FileHandle->getTrackMediaDuration(aId);
8782         samplecount = iMP4FileHandle->getSampleCountInTrack(aId);
8783 
8784         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - TrackDuration=%2d", trackduration));
8785         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - TotalNumSamples=%d", samplecount));
8786         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - BitRate=%d", (uint32)iMP4FileHandle->getTrackAverageBitrate(aId)));
8787 
8788         //go thru the key frame list and determine the optimal key frame
8789         uint32 keySampleNum = syncfrnum[0];
8790         int32 keySampleSize =
8791             iMP4FileHandle->getSampleSizeAt(aId, (int32)keySampleNum);
8792         aKeyFrameNum = 0;
8793         for (uint32 i = 1; i < numsamples; i++)
8794         {
8795             uint32 keySampleNumNext = syncfrnum[i];
8796             int32 keySampleSizeNext =
8797                 iMP4FileHandle->getSampleSizeAt(aId, (int32)keySampleNumNext);
8798 
8799             if (keySampleSizeNext > keySampleSize)
8800             {
8801                 keySampleSize = keySampleSizeNext;
8802                 aKeyFrameNum = i;
8803             }
8804         }
8805         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - Picked Best KeyFrame=%d", aKeyFrameNum));
8806         if (syncts)
8807         {
8808             OSCL_ARRAY_DELETE(syncts);
8809         }
8810         if (syncfrnum)
8811         {
8812             OSCL_ARRAY_DELETE(syncfrnum);
8813         }
8814     }
8815     else if (retval == 2)
8816     {
8817         // All samples are sync samples
8818         if (numsamples > NUMSAMPLES_BEST_THUMBNAIL_MODE)
8819         {
8820             numsamples = NUMSAMPLES_BEST_THUMBNAIL_MODE;
8821         }
8822         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - NumKeySamples=%d, TrackID=%d", numsamples, aId));
8823 
8824         //go thru the key frame list and determine the optimal key frame
8825         int32 maxKeySampleSize = 0;
8826         int32 keySampleSize = 0;
8827         aKeyFrameNum = 0;
8828         for (uint32 i = 0; i < numsamples; i++)
8829         {
8830             keySampleSize = iMP4FileHandle->getSampleSizeAt(aId, i);
8831 
8832             if (keySampleSize > maxKeySampleSize)
8833             {
8834                 maxKeySampleSize = keySampleSize;
8835                 aKeyFrameNum = i;
8836             }
8837         }
8838         PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode:FindBestThumbnailKeyFrame - Picked Best KeyFrame=%d", aKeyFrameNum));
8839     }
8840     else
8841     {
8842         numsamples = 0;
8843         aKeyFrameNum = 0;
8844         return PVMFFailure;
8845     }
8846     return PVMFSuccess;
8847 }
8848 
8849 PVMFCommandId
GetLicense(PVMFSessionId aSessionId,OSCL_wString & aContentName,OsclAny * aData,uint32 aDataSize,int32 aTimeoutMsec,OsclAny * aContextData)8850 PVMFMP4FFParserNode::GetLicense(PVMFSessionId aSessionId,
8851                                 OSCL_wString& aContentName,
8852                                 OsclAny* aData,
8853                                 uint32 aDataSize,
8854                                 int32 aTimeoutMsec,
8855                                 OsclAny* aContextData)
8856 {
8857     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::GetLicense - Wide called"));
8858     PVMFMP4FFParserNodeCommand cmd;
8859     cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId,
8860             PVMP4FF_NODE_CMD_GET_LICENSE_W,
8861             aContentName,
8862             aData,
8863             aDataSize,
8864             aTimeoutMsec,
8865             aContextData);
8866     return QueueCommandL(cmd);
8867 }
8868 
8869 PVMFCommandId
GetLicense(PVMFSessionId aSessionId,OSCL_String & aContentName,OsclAny * aData,uint32 aDataSize,int32 aTimeoutMsec,OsclAny * aContextData)8870 PVMFMP4FFParserNode::GetLicense(PVMFSessionId aSessionId,
8871                                 OSCL_String&  aContentName,
8872                                 OsclAny* aData,
8873                                 uint32 aDataSize,
8874                                 int32 aTimeoutMsec,
8875                                 OsclAny* aContextData)
8876 {
8877     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::GetLicense - Wide called"));
8878     PVMFMP4FFParserNodeCommand cmd;
8879     cmd.PVMFMP4FFParserNodeCommand::Construct(aSessionId,
8880             PVMP4FF_NODE_CMD_GET_LICENSE,
8881             aContentName,
8882             aData,
8883             aDataSize,
8884             aTimeoutMsec,
8885             aContextData);
8886     return QueueCommandL(cmd);
8887 }
8888 
8889 PVMFCommandId
CancelGetLicense(PVMFSessionId aSessionId,PVMFCommandId aCmdId,OsclAny * aContextData)8890 PVMFMP4FFParserNode::CancelGetLicense(PVMFSessionId aSessionId, PVMFCommandId aCmdId, OsclAny* aContextData)
8891 {
8892     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::CancelGetLicense - called"));
8893     PVMFMP4FFParserNodeCommand cmd;
8894     cmd.PVMFMP4FFParserNodeCommandBase::Construct(aSessionId, PVMP4FF_NODE_CMD_CANCEL_GET_LICENSE, aCmdId,  aContextData);
8895     return QueueCommandL(cmd);
8896 }
8897 
GetLicenseStatus(PVMFCPMLicenseStatus & aStatus)8898 PVMFStatus PVMFMP4FFParserNode::GetLicenseStatus(
8899     PVMFCPMLicenseStatus& aStatus)
8900 {
8901     if (iCPMLicenseInterface)
8902         return iCPMLicenseInterface->GetLicenseStatus(aStatus);
8903     return PVMFFailure;
8904 }
8905 
DoGetLicense(PVMFMP4FFParserNodeCommand & aCmd,bool aWideCharVersion)8906 PVMFStatus PVMFMP4FFParserNode::DoGetLicense(PVMFMP4FFParserNodeCommand& aCmd,
8907         bool aWideCharVersion)
8908 {
8909     if (iCPMLicenseInterface == NULL)
8910     {
8911         return PVMFErrNotSupported;
8912     }
8913 
8914     if (aWideCharVersion == true)
8915     {
8916         OSCL_wString* contentName = NULL;
8917         OsclAny* data = NULL;
8918         uint32 dataSize = 0;
8919         int32 timeoutMsec = 0;
8920         aCmd.PVMFMP4FFParserNodeCommand::Parse(contentName,
8921                                                data,
8922                                                dataSize,
8923                                                timeoutMsec);
8924         iCPMGetLicenseCmdId =
8925             iCPMLicenseInterface->GetLicense(iCPMSessionID,
8926                                              *contentName,
8927                                              data,
8928                                              dataSize,
8929                                              timeoutMsec);
8930     }
8931     else
8932     {
8933         OSCL_String* contentName = NULL;
8934         OsclAny* data = NULL;
8935         uint32 dataSize = 0;
8936         int32 timeoutMsec = 0;
8937         aCmd.PVMFMP4FFParserNodeCommand::Parse(contentName,
8938                                                data,
8939                                                dataSize,
8940                                                timeoutMsec);
8941         iCPMGetLicenseCmdId =
8942             iCPMLicenseInterface->GetLicense(iCPMSessionID,
8943                                              *contentName,
8944                                              data,
8945                                              dataSize,
8946                                              timeoutMsec);
8947     }
8948     return PVMFPending;
8949 }
8950 
CompleteGetLicense()8951 void PVMFMP4FFParserNode::CompleteGetLicense()
8952 {
8953     CommandComplete(iCurrentCommand,
8954                     iCurrentCommand.front(),
8955                     PVMFSuccess);
8956 }
8957 
DoCancelGetLicense(PVMFMP4FFParserNodeCommand & aCmd)8958 PVMFStatus PVMFMP4FFParserNode::DoCancelGetLicense(PVMFMP4FFParserNodeCommand& aCmd)
8959 {
8960     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::DoCancelGetLicense() Called"));
8961     PVMFStatus status = PVMFErrArgument;
8962 
8963     if (iCPMLicenseInterface == NULL)
8964     {
8965         status = PVMFErrNotSupported;
8966     }
8967     else
8968     {
8969         /* extract the command ID from the parameters.*/
8970         PVMFCommandId id;
8971         aCmd.PVMFMP4FFParserNodeCommandBase::Parse(id);
8972 
8973         /* first check "current" command if any */
8974         PVMFMP4FFParserNodeCommand* cmd = iCurrentCommand.FindById(id);
8975         if (cmd)
8976         {
8977             if (cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE_W || cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE)
8978             {
8979                 iCPMCancelGetLicenseCmdId =
8980                     iCPMLicenseInterface->CancelGetLicense(iCPMSessionID, iCPMGetLicenseCmdId);
8981 
8982                 /*
8983                  * the queued commands are all asynchronous commands to the
8984                  * CPM module. CancelGetLicense can cancel only for GetLicense cmd.
8985                  * We need to wait CPMCommandCompleted.
8986                  */
8987                 return PVMFPending;
8988             }
8989         }
8990 
8991         /*
8992          * next check input queue.
8993          * start at element 1 since this cancel command is element 0.
8994          */
8995         cmd = iInputCommands.FindById(id, 1);
8996         if (cmd)
8997         {
8998             if (cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE_W || cmd->iCmd == PVMP4FF_NODE_CMD_GET_LICENSE)
8999             {
9000                 /* cancel the queued command */
9001                 CommandComplete(iInputCommands, *cmd, PVMFErrCancelled, NULL, NULL);
9002                 /* report cancel success */
9003                 return PVMFSuccess;
9004             }
9005         }
9006     }
9007     /* if we get here the command isn't queued so the cancel fails */
9008     return status;
9009 }
9010 
SendBeginOfMediaStreamCommand(PVMP4FFNodeTrackPortInfo & aTrackPortInfo)9011 bool PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand(PVMP4FFNodeTrackPortInfo& aTrackPortInfo)
9012 {
9013     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
9014     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID);
9015 
9016     aTrackPortInfo.iClockConverter->update_clock(aTrackPortInfo.iTimestamp);
9017     uint32 timestamp = aTrackPortInfo.iClockConverter->get_converted_ts(1000);
9018     sharedMediaCmdPtr->setTimestamp(timestamp);
9019 
9020     PVMFSharedMediaMsgPtr mediaMsgOut;
9021     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
9022     mediaMsgOut->setStreamID(iStreamID);
9023     mediaMsgOut->setSeqNum(aTrackPortInfo.iSeqNum);
9024 
9025     if (aTrackPortInfo.iPortInterface->QueueOutgoingMsg(mediaMsgOut) != PVMFSuccess)
9026     {
9027         // Output queue is busy, so wait for the output queue being ready
9028         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
9029                         (0, "PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand: Outgoing queue busy. "));
9030         if (aTrackPortInfo.iState == PVMP4FFNodeTrackPortInfo::TRACKSTATE_TRANSMITTING_SENDDATA)
9031         {
9032             aTrackPortInfo.iState = PVMP4FFNodeTrackPortInfo::TRACKSTATE_DESTFULL;
9033         }
9034         return false;
9035     }
9036     aTrackPortInfo.iSendBOS = false;
9037     PVMF_MP4FFPARSERNODE_LOGDATATRAFFIC((0, "PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand() BOS sent - Mime=%s, StreamId=%d, TS=%d",
9038                                          aTrackPortInfo.iMimeType.get_cstr(),
9039                                          iStreamID,
9040                                          timestamp));
9041     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFMP4FFParserNode::SendBeginOfMediaStreamCommand() BOS sent StreamId=%d ", iStreamID));
9042     return true;
9043 }
9044 
NotificationsInterfaceDestroyed()9045 void PVMFMP4FFParserNode::NotificationsInterfaceDestroyed()
9046 {
9047     iClockNotificationsInf = NULL;
9048 }
9049 
ClockStateUpdated()9050 void PVMFMP4FFParserNode::ClockStateUpdated()
9051 {
9052     if ((iExternalDownload && iUnderFlowEventReported) ||
9053             (autopaused && download_progress_interface != NULL))
9054     {
9055         // Don't let anyone start the clock while the source node is in underflow
9056         if (iClientPlayBackClock != NULL)
9057         {
9058             if (iClientPlayBackClock->GetState() == PVMFMediaClock::RUNNING)
9059             {
9060                 iClientPlayBackClock->Pause();
9061             }
9062         }
9063     }
9064 }
9065 
9066 
CreateErrorInfoMsg(PVMFBasicErrorInfoMessage ** aErrorMsg,PVUuid aEventUUID,int32 aEventCode)9067 int32 PVMFMP4FFParserNode::CreateErrorInfoMsg(PVMFBasicErrorInfoMessage** aErrorMsg, PVUuid aEventUUID, int32 aEventCode)
9068 {
9069     int32 leavecode = 0;
9070     OSCL_TRY(leavecode, *aErrorMsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (aEventCode, aEventUUID, NULL)));
9071     return leavecode;
9072 }
9073 
9074 
9075 
9076 
9077 
9078 
9079 
9080 
9081 
9082 
9083 
9084 
9085 
9086 
9087