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