1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18
19 /*********************************************************************************/
20 /* ------------------------------------------------------------------- */
21 /* MPEG-4 Mpeg4File Class */
22 /* ------------------------------------------------------------------- */
23 /*********************************************************************************/
24 /*
25 The Mpeg4File Class is the class that will construct and maintain all the
26 mecessary data structures to be able to render a valid MP4 file to disk.
27 Format.
28 */
29
30
31 #define IMPLEMENT_Mpeg4File
32
33 #include "oscl_int64_utils.h"
34
35 #ifndef MPEG4FILE_H_INCLUDED
36 #include "mpeg4file.h"
37 #endif
38
39 #include "atomdefs.h"
40 #include "atomutils.h"
41 #include "filetypeatom.h"
42 #include "oscl_utf8conv.h"
43 #include "oscl_string.h"
44 #include "oscl_snprintf.h"
45 #include "amrdecoderspecificinfo.h"
46 #include "h263decoderspecificinfo.h"
47 #include "media_clock_converter.h"
48
49 typedef Oscl_Vector<TrackAtom*, OsclMemAllocator> trackAtomVecType;
50 typedef Oscl_Vector<MovieFragmentAtom*, OsclMemAllocator> movieFragmentAtomVecType;
51 typedef Oscl_Vector<uint32, OsclMemAllocator> movieFragmentOffsetVecType;
52 typedef Oscl_Vector<TrackDurationInfo*, OsclMemAllocator> trackDurationInfoVecType;
53 typedef Oscl_Vector<MovieFragmentRandomAccessAtom*, OsclMemAllocator> movieFragmentRandomAccessAtomVecType;
54
55 // Stream-in Constructor
Mpeg4File(MP4_FF_FILE * fp,OSCL_wString & filename,uint32 parsingMode)56 Mpeg4File::Mpeg4File(MP4_FF_FILE *fp,
57 OSCL_wString& filename,
58 uint32 parsingMode)
59 {
60
61 _pmovieAtom = NULL;
62 _puserDataAtom = NULL;
63 _pFileTypeAtom = NULL;
64 _pMovieFragmentAtom = NULL;
65 _mp4ErrorCode = EVERYTHING_FINE;
66 _isMovieFragmentsPresent = false;
67 _pointerMovieAtomEnd = 0;
68 _movieFragmentFilePtr = NULL;
69 _pMovieFragmentAtomVec = NULL;
70 _pMfraOffsetAtom = NULL;
71 _pMovieFragmentRandomAccessAtomVec = NULL;
72 _pTrackExtendsAtomVec = NULL;
73 _pMoofOffsetVec = NULL;
74 _ptrMoofEnds = 0;
75 _parsing_mode = parsingMode;
76 _pTrackDurationContainer = NULL;
77 oMfraFound = false;
78 _oVideoTrackPresent = false;
79 parseMoofCompletely = true;
80 isResetPlayBackCalled = false;
81
82 parseMoofCompletely = true;
83 moofParsingCompleted = true;
84 moofSize = 0;
85 moofType = UNKNOWN_ATOM;
86 moofCount = 0;
87 moofPtrPos = 0;
88 currMoofNum = 0;
89 countOfTrunsParsed = 0;
90
91 // Create miscellaneous vector of atoms
92 PV_MP4_FF_NEW(fp->auditCB, trackAtomVecType, (), _pTrackAtomVec);
93 PV_MP4_FF_NEW(fp->auditCB, movieFragmentAtomVecType, (), _pMovieFragmentAtomVec);
94 PV_MP4_FF_NEW(fp->auditCB, movieFragmentOffsetVecType, (), _pMoofOffsetVec);
95 PV_MP4_FF_NEW(fp->auditCB, movieFragmentRandomAccessAtomVecType, (), _pMovieFragmentRandomAccessAtomVec);
96 PV_MP4_FF_NEW(fp->auditCB, PVID3ParCom, (), _pID3Parser);
97
98
99 iLogger = PVLogger::GetLoggerObject("mp4ffparser");
100 iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats");
101 iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata");
102
103 _success = true; // Initial state
104
105 int32 fileSize;
106 int32 filePointer;
107 filePointer = AtomUtils::getCurrentFilePosition(fp);
108 uint32 fsize = 0;
109 AtomUtils::getCurrentFileSize(fp, fsize);
110 fileSize = (int32)fsize;
111
112 _oPVContent = false;
113 _oPVContentDownloadable = false;
114 _commonFilePtr = NULL;
115 _fileSize = fsize;
116
117 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE;
118
119 //top level moov, mdat, udat
120 while (count > 0)
121 {
122 // Read in atoms until reach end of file
123 //there is a case that next atom is valid, but not in top level
124 //so only check top level now
125 uint32 atomType = UNKNOWN_ATOM;
126 uint32 atomSize = 0;
127
128 AtomUtils::getNextAtomType(fp, atomSize, atomType);
129
130 if ((atomType == SKIP_ATOM)
131 || (atomType == FREE_SPACE_ATOM)
132 || (atomType == UUID_ATOM)
133 || (atomType == UNKNOWN_ATOM)
134 || (atomType == MEDIA_DATA_ATOM))
135 {
136 if (atomSize == 1)
137 {
138 uint64 largeSize = 0;
139 AtomUtils::read64(fp, largeSize);
140 uint32 size =
141 Oscl_Int64_Utils::get_uint64_lower32(largeSize);
142 count -= size;
143 size -= 8; //for large size
144 size -= DEFAULT_ATOM_SIZE;
145 AtomUtils::seekFromCurrPos(fp, size);
146 }
147 else
148 {
149 if (atomSize < DEFAULT_ATOM_SIZE)
150 {
151 _success = false;
152 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
153 break;
154 }
155 if (count < (int32)atomSize)
156 {
157 _success = false;
158 _mp4ErrorCode = READ_FAILED;
159 break;
160 }
161 count -= atomSize;
162 atomSize -= DEFAULT_ATOM_SIZE;
163 AtomUtils::seekFromCurrPos(fp, atomSize);
164 }
165 }
166 else if (atomType == USER_DATA_ATOM)
167 {
168 //"udta"
169 // Check for 'pvmm' to see if it is "our" 'udta' atom
170
171 uint32 isPVMMAtom = AtomUtils::peekNextNthBytes(fp, 2);
172
173 if (isPVMMAtom == PVUSER_DATA_ATOM)
174 {
175 if (_puserDataAtom == NULL)
176 {
177 PV_MP4_FF_NEW(fp->auditCB, UserDataAtom, (fp, atomSize, atomType), _puserDataAtom);
178 _oPVContent = true;
179 uint32 contentType = getContentType();
180 if (contentType == DEFAULT_AUTHORING_MODE)
181 {
182 _oPVContentDownloadable = true;
183 }
184 count -= _puserDataAtom->getSize();
185 }
186 else
187 {
188 _success = false;
189 _mp4ErrorCode = READ_USER_DATA_ATOM_FAILED;
190 break;
191 }
192 }
193 else
194 {
195 // Skip third party user data atom
196 if (atomSize < DEFAULT_ATOM_SIZE)
197 {
198 _success = false;
199 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
200 break;
201 }
202 if (count < (int32)atomSize)
203 {
204 _success = false;
205 _mp4ErrorCode = READ_FAILED;
206 break;
207 }
208 count -= atomSize;
209 atomSize -= DEFAULT_ATOM_SIZE;
210 AtomUtils::seekFromCurrPos(fp, atomSize);
211 }
212
213
214 }
215 else if (atomType == FILE_TYPE_ATOM)
216 {
217 if (_pFileTypeAtom == NULL)
218 {
219 //"ftyp"
220 PV_MP4_FF_NEW(fp->auditCB, FileTypeAtom, (fp, atomSize, atomType), _pFileTypeAtom);
221
222 if (!_pFileTypeAtom->MP4Success())
223 {
224 _success = false;
225 _mp4ErrorCode = READ_FILE_TYPE_ATOM_FAILED;
226 break;
227 }
228
229 uint32 majorBrand = _pFileTypeAtom->getMajorBrand();
230 uint32 majorBrandInfo = ENoFileType;
231 uint32 compatibleBrandInfo = ENoFileType;
232
233
234 switch (majorBrand)
235 {
236 case WMF_BRAND:
237 majorBrandInfo |= EWMF;
238 break;
239
240 case BRAND_3GPP4:
241 majorBrandInfo |= E3GP4;
242 break;
243
244 case BRAND_3GPP5:
245 majorBrandInfo |= E3GP5;
246 break;
247
248 case MOBILE_MP4:
249 majorBrandInfo |= EMMP4;
250 break;
251
252 case BRAND_MP41:
253 majorBrandInfo |= EMP41;
254 break;
255
256 case BRAND_MP42:
257 majorBrandInfo |= EMP42;
258 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE;
259 break;
260
261 case BRAND_ISOM:
262 majorBrandInfo |= EISOM;
263 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE;
264 break;
265
266 default:
267 majorBrandInfo |= EUNKNOWN_TYPE;
268 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE;
269 break;
270 }
271
272 Oscl_Vector<uint32, OsclMemAllocator> *compatibleBrandArray =
273 _pFileTypeAtom->getCompatibleBrand();
274
275 if (compatibleBrandArray != NULL)
276 {
277 for (uint32 i = 0; i < compatibleBrandArray->size(); i++)
278 {
279 uint32 compatibleBrand = (*compatibleBrandArray)[i];
280
281 switch (compatibleBrand)
282 {
283 case WMF_BRAND:
284 compatibleBrandInfo |= EWMF;
285 break;
286
287 case BRAND_3GPP4:
288 compatibleBrandInfo |= E3GP4;
289 break;
290
291 case BRAND_3GPP5:
292 compatibleBrandInfo |= E3GP5;
293 break;
294
295 case MOBILE_MP4:
296 compatibleBrandInfo |= EMMP4;
297 break;
298
299 case BRAND_MP41:
300 compatibleBrandInfo |= EMP41;
301 break;
302
303 case BRAND_MP42:
304 compatibleBrandInfo |= EMP42;
305 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE;
306 break;
307
308 case BRAND_ISOM:
309 compatibleBrandInfo |= EISOM;
310 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE;
311 break;
312
313 default:
314 compatibleBrandInfo |= EUNKNOWN_TYPE;
315 _mp4ErrorCode = UNSUPPORTED_FILE_TYPE;
316 break;
317 }
318 }
319 }
320
321 count -= _pFileTypeAtom->getSize();
322 }
323 else
324 {
325 //multiple "ftyp" atom not allowed.skipping
326 count -= atomSize;
327 atomSize -= DEFAULT_ATOM_SIZE;
328 AtomUtils::seekFromCurrPos(fp, atomSize);
329 }
330 }
331 else if (atomType == MOVIE_ATOM)
332 {
333
334
335 //"moov"
336 if (_pmovieAtom == NULL)
337 {
338 // Only 1 movie atom allowed!
339 PV_MP4_FF_NEW(fp->auditCB, MovieAtom,
340 (fp,
341 filename,
342 atomSize,
343 atomType,
344 _oPVContent,
345 _oPVContentDownloadable,
346 parsingMode
347 ),
348 _pmovieAtom);
349
350 if (!_pmovieAtom->MP4Success())
351 {
352 _success = false;
353 _mp4ErrorCode = _pmovieAtom->GetMP4Error();
354 break;
355 }
356 _isMovieFragmentsPresent = _pmovieAtom->IsMovieFragmentPresent();
357 populateTrackDurationVec();
358 _pTrackExtendsAtomVec = _pmovieAtom->getTrackExtendsAtomVec();
359
360 if (_isMovieFragmentsPresent)
361 {
362 atomSize -= DEFAULT_ATOM_SIZE;
363 _pointerMovieAtomEnd = AtomUtils::getCurrentFilePosition(fp);
364 _ptrMoofEnds = _pointerMovieAtomEnd;
365 OsclAny*ptr = oscl_malloc(sizeof(MP4_FF_FILE));
366 if (ptr == NULL)
367 {
368 _success = false;
369 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
370 return;
371 }
372 _movieFragmentFilePtr = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE(*fp));
373 _movieFragmentFilePtr ->_pvfile.Copy(fp->_pvfile);
374 _movieFragmentFilePtr ->_pvfile.SetCPM(fp->_pvfile.GetCPM());
375 }
376 count -= _pmovieAtom->getSize();
377 _scalability = _pmovieAtom->getScalability();
378 _fileType = _pmovieAtom->getFileType();
379
380 if (parsingMode != 0)
381 {
382 if (_isMovieFragmentsPresent)
383 {
384 parseMFRA();
385 }
386 break;
387 }
388 if (!_isMovieFragmentsPresent)
389 {
390 //no moofs, exit the parsing loop since
391 //we are done parsing the moov atom
392 break;
393 }
394
395
396 }
397 else
398 { //after the change above, we will never hit here.
399 _success = false;
400 _mp4ErrorCode = DUPLICATE_MOVIE_ATOMS;
401 break;
402 }
403 }
404 else if (atomType == MOVIE_FRAGMENT_ATOM)
405 {
406 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(fp);
407 moofStartOffset -= DEFAULT_ATOM_SIZE;
408 _pMoofOffsetVec->push_back(moofStartOffset);
409
410 MovieFragmentAtom *pMovieFragmentAtom = NULL;
411 PV_MP4_FF_NEW(fp->auditCB, MovieFragmentAtom, (fp, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), pMovieFragmentAtom);
412
413 if (!pMovieFragmentAtom->MP4Success())
414 {
415 _success = false;
416 _mp4ErrorCode = pMovieFragmentAtom->GetMP4Error();
417 break;
418 }
419 pMovieFragmentAtom->setParent(this);
420 count -= pMovieFragmentAtom->getSize();
421 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(fp);
422 _pMovieFragmentAtomVec->push_back(pMovieFragmentAtom);
423 }
424 else if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_ATOM)
425 {
426 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = NULL;
427 PV_MP4_FF_NEW(fp->auditCB, MovieFragmentRandomAccessAtom, (fp, atomSize, atomType), pMovieFragmentRandomAccessAtom);
428
429 if (!pMovieFragmentRandomAccessAtom->MP4Success())
430 {
431 _success = false;
432 _mp4ErrorCode = pMovieFragmentRandomAccessAtom->GetMP4Error();
433 break;
434 }
435 pMovieFragmentRandomAccessAtom->setParent(this);
436 count -= pMovieFragmentRandomAccessAtom->getSize();
437 _pMovieFragmentRandomAccessAtomVec->push_back(pMovieFragmentRandomAccessAtom);
438 oMfraFound = true;
439 }
440 else
441 {
442 if (count > 0)
443 {
444 _mp4ErrorCode = READ_UNKNOWN_ATOM;
445 _success = false;
446 }
447 break;
448 }
449 }
450
451 if (_success)
452 {
453 // Check that the movie atom was in fact read in
454 if (_pmovieAtom == NULL)
455 {
456 _success = false;
457 _mp4ErrorCode = NO_MOVIE_ATOM_PRESENT;
458 }
459 else
460 {
461 // CHECK IF THERE ARE ANY VALID MEDIA TRACKS IN THE FILE
462 int32 numMediaTracks = getNumTracks();
463 if (numMediaTracks == 0)
464 {
465 _success = false;
466 _mp4ErrorCode = NO_META_DATA_FOR_MEDIA_TRACKS;
467 }
468 if (_success)
469 {
470 uint32 bufferCapacity = AtomUtils::getFileBufferingCapacity(fp);
471 if (0 != bufferCapacity)
472 {
473 // progressive playback
474 int32* offsetList = (int32 *)oscl_malloc(sizeof(int32) * numMediaTracks);
475 if (NULL == offsetList)
476 {
477 _success = false;
478 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
479 }
480 else
481 {
482 // get the list of track ids
483 uint32* idList = (uint32 *)oscl_malloc(sizeof(uint32) * numMediaTracks);
484 _pmovieAtom->getTrackIDList(idList, numMediaTracks);
485
486 // get the first sample file offset of each track
487 for (int32 i = 0; i < numMediaTracks; i++)
488 {
489 int32 retVal = _pmovieAtom->getOffsetByTime(idList[i], 0, &offsetList[i]);
490 if (EVERYTHING_FINE != retVal)
491 {
492 _success = false;
493 _mp4ErrorCode = retVal;
494 break;
495 }
496 }
497 // check if any of the two offsets are too far apart
498 // to coexist in the cache at the same time
499 if (_success)
500 {
501 uint32 largest = 0, temp = 0;
502 for (int i = 0; i < numMediaTracks; i++)
503 {
504 for (int j = 0; j < numMediaTracks; j++)
505 {
506 // same as abs()
507 if (offsetList[i] > offsetList[j])
508 {
509 temp = offsetList[i] - offsetList[j];
510 }
511 else
512 {
513 temp = offsetList[j] - offsetList[i];
514 }
515
516 if (temp > largest)
517 {
518 largest = temp;
519 }
520 }
521 }
522
523 if (largest > bufferCapacity)
524 {
525 // the samples are not interleaved properly
526 // this clip is not authored for progressive playback
527 _success = false;
528 _mp4ErrorCode = INSUFFICIENT_BUFFER_SIZE;
529 }
530 }
531
532 oscl_free(idList);
533 }
534
535 oscl_free(offsetList);
536 }
537 }
538 }
539 }
540
541
542 // Check for any atoms that may have read past the EOF that were not
543 // already caught by any earlier error handling
544
545 if (filePointer > fileSize)
546 {
547 _mp4ErrorCode = READ_FAILED; // Read past EOF
548 _success = false;
549 }
550
551 // skip ID3 tag parsing for progressive playback for now
552 uint32 bufferCapacity = AtomUtils::getFileBufferingCapacity(fp);
553 if (0 == bufferCapacity)
554 {
555 parseID3Header(fp);
556 }
557 //Populate the title vector with all the title metadata values.
558 if (!populateMetadataVectors())
559 {
560 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::populateTitleVector() Failed"));
561 }
562
563 }
564
565
populateMetadataVectors()566 PVMFStatus Mpeg4File::populateMetadataVectors()
567 {
568 if ((!populateTitleVector()) || (!populateAuthorVector() ||
569 (!populateAlbumVector()) ||
570 (!populateArtistVector()) || (!populateGenreVector()) ||
571 (!populateYearVector()) || (!populateCopyrightVector()) ||
572 (!populateCommentVector()) || (!populateDescriptionVector()) ||
573 (!populateRatingVector()))
574 )
575 {
576 return PVMFFailure;
577 }
578
579 return PVMFSuccess;
580 }
581
getNumTitle()582 uint32 Mpeg4File::getNumTitle()
583 {
584 uint32 numTitle = 0;
585 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN;
586 numTitle = getNumAssetInfoTitleAtoms();
587 if (getPVTitle(chartype).get_size() > 0)
588 {
589 numTitle++;
590 }
591 if (getITunesTitle().get_size() > 0)
592 {
593 numTitle++;
594 }
595 PvmiKvpSharedPtrVector framevector;
596 GetID3MetaData(framevector);
597 uint32 num_frames = framevector.size();
598 for (uint32 i = 0; i < num_frames; i++)
599 {
600 if (framevector.size() > 0)
601 {
602 if (oscl_strstr(framevector[i]->key, "title") != 0)
603 {
604 numTitle++;
605 break;
606 }
607 }
608 }
609 return numTitle;
610 }
611
612 //This function populates the Title Vector with values from Asset Info, Itunes, FullMusic and PV Proprietary Atoms.
populateTitleVector()613 PVMFStatus Mpeg4File::populateTitleVector()
614 {
615 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
616 int32 numTitle = getNumTitle();
617 ReserveMemoryForValuesVector(titleValues, numTitle, leavecode);
618 ReserveMemoryForLangCodeVector(iTitleLangCode, numTitle, leavecode1);
619 OSCL_TRY(leavecode2, iTitleCharType.reserve(numTitle));
620 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
621 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
622 {
623 return PVMFFailure;
624 }
625 int32 numAssetInfoTitle = getNumAssetInfoTitleAtoms();
626
627
628 if (numAssetInfoTitle > 0)
629 {
630 for (int32 i = 0; i < numAssetInfoTitle; i++)
631 {
632 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoTitleNotice(charType, i);
633
634 titleValues.push_front(valuestring);
635 iTitleLangCode.push_front(getAssetInfoTitleLangCode(i));
636 iTitleCharType.push_front(charType);
637 }
638 }
639 if (getPVTitle(charType).get_size() > 0)
640 {
641 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVTitle(charType);
642 titleValues.push_front(valuestring);
643 iTitleLangCode.push_front(0);
644 iTitleCharType.push_front(charType);
645 }
646 if (getITunesTitle().get_size() > 0)
647 {
648 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesTitle();
649 titleValues.push_front(valuestring);
650 iTitleLangCode.push_front(0);
651 iTitleCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
652 }
653 PvmiKvpSharedPtrVector framevector;
654 GetID3MetaData(framevector);
655 uint32 num_frames = framevector.size();
656 for (uint32 i = 0; i < num_frames; i++)
657 {
658 if (framevector.size() > 0)
659 {
660 if (oscl_strstr(framevector[i]->key, "title") != 0)
661 {
662 uint32 len = oscl_strlen(framevector[i]->value.pChar_value);
663 oscl_memset(_id3v1Title, 0, ID3V1_STR_MAX_SIZE);
664 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Title, len*2 + 2);
665 titleValues.push_front(_id3v1Title);
666 iTitleLangCode.push_front(0);
667 iTitleCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
668 break;
669 }
670 }
671 }
672 return PVMFSuccess;
673 }
674
675 // This function returns the titles based on index value, to the parser node.
getTitle(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)676 PVMFStatus Mpeg4File::getTitle(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType)
677 {
678 if (index < titleValues.size())
679 {
680 aVal = NULL;
681 aLangCode = 0;
682 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
683 aVal = titleValues[index].get_cstr();
684 aLangCode = iTitleLangCode[index];
685 aCharEncType = iTitleCharType[index];
686 return PVMFSuccess;
687 }
688 return PVMFErrArgument;
689 }
690
getNumAuthor()691 uint32 Mpeg4File::getNumAuthor()
692 {
693 uint32 numAuthor = 0;
694 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN;
695 numAuthor = getNumAssetInfoAuthorAtoms();
696
697 if (getPVAuthor(chartype).get_size() > 0)
698 {
699 numAuthor++;
700 }
701 return numAuthor;
702 }
703
704 //This function populates the Author Vector with values from Asset Info and PV Proprietary Atoms.
populateAuthorVector()705 PVMFStatus Mpeg4File::populateAuthorVector()
706 {
707 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
708 int32 numAuthor = getNumAuthor();
709 ReserveMemoryForValuesVector(authorValues, numAuthor, leavecode);
710 ReserveMemoryForLangCodeVector(iAuthorLangCode, numAuthor, leavecode1);
711 OSCL_TRY(leavecode2, iAuthorCharType.reserve(numAuthor));
712 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
713 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
714 {
715 return PVMFFailure;
716 }
717 int32 numAssetInfoAuthor = getNumAssetInfoAuthorAtoms();
718 if (numAssetInfoAuthor > 0)
719 {
720 for (int32 i = 0; i < numAssetInfoAuthor; i++)
721 {
722 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoAuthorNotice(charType, i);
723 authorValues.push_front(valuestring);
724 iAuthorLangCode.push_front(getAssetInfoAuthorLangCode(i));
725 iAuthorCharType.push_front(charType);
726 }
727 }
728 if (getPVAuthor(charType).get_size() > 0)
729 {
730 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVAuthor(charType);
731 authorValues.push_front(valuestring);
732 iAuthorLangCode.push_front(0);
733 iAuthorCharType.push_front(charType);
734 }
735 return PVMFSuccess;
736 }
737
738 // This function returns the Author based on index value, to the parser node.
getAuthor(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)739 PVMFStatus Mpeg4File::getAuthor(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType)
740 {
741 if (index < authorValues.size())
742 {
743 aVal = NULL;
744 aLangCode = 0;
745 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
746 aVal = authorValues[index].get_cstr();
747 aLangCode = iAuthorLangCode[index];
748 aCharEncType = iAuthorCharType[index];
749 return PVMFSuccess;
750 }
751 return PVMFErrArgument;
752 }
753
getNumAlbum()754 uint32 Mpeg4File::getNumAlbum()
755 {
756 uint32 numAlbum = 0;
757 numAlbum = getNumAssetInfoAlbumAtoms();
758 if (getITunesAlbum().get_size() > 0)
759 {
760 numAlbum++;
761 }
762 PvmiKvpSharedPtrVector framevector;
763 GetID3MetaData(framevector);
764 uint32 num_frames = framevector.size();
765 for (uint32 i = 0; i < num_frames; i++)
766 {
767 if (framevector.size() > 0)
768 {
769 if (oscl_strstr(framevector[i]->key, "album") != 0)
770 {
771 numAlbum++;
772 break;
773 }
774 }
775 }
776 return numAlbum;
777 }
778
779 //This function populates the Album Vector with values from Asset Info, Itunes, FullMusic Atoms.
populateAlbumVector()780 PVMFStatus Mpeg4File::populateAlbumVector()
781 {
782 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
783 int32 numAlbum = getNumAlbum();
784 ReserveMemoryForValuesVector(albumValues, numAlbum, leavecode);
785 ReserveMemoryForLangCodeVector(iAlbumLangCode, numAlbum, leavecode1);
786 OSCL_TRY(leavecode2, iAlbumCharType.reserve(numAlbum));
787 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
788 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
789 {
790 return PVMFFailure;
791 }
792 int32 numAssetInfoAlbum = getNumAssetInfoAlbumAtoms();
793 if (numAssetInfoAlbum > 0)
794 {
795 for (int32 i = 0; i < numAssetInfoAlbum; i++)
796 {
797 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoAlbumNotice(charType, i);
798 albumValues.push_front(valuestring);
799 iAlbumLangCode.push_front(getAssetInfoAlbumLangCode(i));
800 iAlbumCharType.push_front(charType);
801 }
802 }
803 if (getITunesAlbum().get_size() > 0)
804 {
805 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesAlbum();
806 albumValues.push_front(valuestring);
807 iAlbumLangCode.push_front(0);
808 iAlbumCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
809 }
810 PvmiKvpSharedPtrVector framevector;
811 GetID3MetaData(framevector);
812 uint32 num_frames = framevector.size();
813 for (uint32 i = 0; i < num_frames; i++)
814 {
815 if (framevector.size() > 0)
816 {
817 if (oscl_strstr(framevector[i]->key, "album") != 0)
818 {
819 uint32 len = oscl_strlen(framevector[i]->value.pChar_value);
820 oscl_memset(_id3v1Album, 0, ID3V1_STR_MAX_SIZE);
821 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Album, len*2 + 2);
822 albumValues.push_front(_id3v1Album);
823 iAlbumLangCode.push_front(0);
824 iAlbumCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
825 break;
826 }
827 }
828 }
829
830 return PVMFSuccess;
831 }
832
833 // This function returns the Album based on index value, to the parser node.
getAlbum(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)834 PVMFStatus Mpeg4File::getAlbum(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType)
835 {
836 if (index < albumValues.size())
837 {
838 aVal = NULL;
839 aLangCode = 0;
840 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
841 aVal = albumValues[index].get_cstr();
842 aLangCode = iAlbumLangCode[index];
843 aCharEncType = iAlbumCharType[index];
844 return PVMFSuccess;
845 }
846 return PVMFErrArgument;
847 }
848
getNumArtist()849 uint32 Mpeg4File::getNumArtist()
850 {
851 uint32 numArtist = 0;
852 numArtist = getNumAssetInfoPerformerAtoms();
853
854 if (getITunesArtist().get_size() > 0)
855 {
856 numArtist++;
857 }
858 if (getITunesAlbumArtist().get_size() > 0) //AlbumArtist
859 {
860 numArtist++;
861 }
862
863 PvmiKvpSharedPtrVector framevector;
864 GetID3MetaData(framevector);
865 uint32 num_frames = framevector.size();
866 for (uint32 i = 0; i < num_frames; i++)
867 {
868 if (framevector.size() > 0)
869 {
870 if (oscl_strstr(framevector[i]->key, "artist") != 0)
871 {
872 numArtist++;
873 break;
874 }
875 }
876 }
877 return numArtist;
878 }
879
880
881 //This function populates the Artist Vector with values from Asset Info, Itunes, FullMusic Atoms.
populateArtistVector()882 PVMFStatus Mpeg4File::populateArtistVector()
883 {
884 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
885 int32 numArtist = getNumArtist();
886 ReserveMemoryForValuesVector(artistValues, numArtist, leavecode);
887 ReserveMemoryForLangCodeVector(iArtistLangCode, numArtist, leavecode1);
888 OSCL_TRY(leavecode2, iArtistCharType.reserve(numArtist));
889 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
890 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
891 {
892 return PVMFFailure;
893 }
894 int32 numAssetInfoPerformer = getNumAssetInfoPerformerAtoms();
895 if (numAssetInfoPerformer > 0)
896 {
897 for (int32 i = 0; i < numAssetInfoPerformer; i++)
898 {
899 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoPerformerNotice(charType, i);
900 artistValues.push_front(valuestring);
901 iArtistLangCode.push_front(getAssetInfoPerformerLangCode(i));
902 iArtistCharType.push_front(charType);
903 }
904 }
905 if (getITunesArtist().get_size() > 0)
906 {
907 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesArtist();
908 artistValues.push_front(valuestring);
909 iArtistLangCode.push_front(0);
910 iArtistCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
911 }
912 if (getITunesAlbumArtist().get_size() > 0) //AlbumArtist
913 {
914 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesAlbumArtist();
915 artistValues.push_front(valuestring);
916 iArtistLangCode.push_front(0);
917 iArtistCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
918 }
919 PvmiKvpSharedPtrVector framevector;
920 GetID3MetaData(framevector);
921 uint32 num_frames = framevector.size();
922 for (uint32 i = 0; i < num_frames; i++)
923 {
924 if (framevector.size() > 0)
925 {
926 if (oscl_strstr(framevector[i]->key, "artist") != 0)
927 {
928 uint32 len = oscl_strlen(framevector[i]->value.pChar_value);
929 oscl_memset(_id3v1Artist, 0, ID3V1_STR_MAX_SIZE);
930 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Artist, len*2 + 2);
931 artistValues.push_front(_id3v1Artist);
932 iArtistLangCode.push_front(0);
933 iArtistCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
934 break;
935 }
936 }
937 }
938 return PVMFSuccess;
939 }
940
941 // This function returns the Artists based on index value, to the parser node.
getArtist(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)942 PVMFStatus Mpeg4File::getArtist(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType)
943 {
944 if (index < artistValues.size())
945 {
946 aVal = NULL;
947 aLangCode = 0;
948 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
949 aVal = artistValues[index].get_cstr();
950 aLangCode = iArtistLangCode[index];
951 aCharEncType = iArtistCharType[index];
952 return PVMFSuccess;
953 }
954 return PVMFErrArgument;
955 }
956
getNumGenre()957 uint32 Mpeg4File::getNumGenre()
958 {
959 uint32 numGenre = 0;
960 numGenre = getNumAssetInfoGenreAtoms();
961
962 if (getITunesGnreString().get_size() > 0)
963 {
964 numGenre++;
965 }
966 if (getITunesGnreID() > 0)
967 {
968 numGenre++;
969 }
970 return numGenre;
971 }
972
973 //This function populates the Genre Vector with values from Asset Info, Itunes, FullMusic Atoms.
populateGenreVector()974 PVMFStatus Mpeg4File::populateGenreVector()
975 {
976 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
977 int32 numGenre = getNumGenre();
978 ReserveMemoryForValuesVector(genreValues, numGenre, leavecode);
979 ReserveMemoryForLangCodeVector(iGenreLangCode, numGenre, leavecode1);
980 OSCL_TRY(leavecode2, iGenreCharType.reserve(numGenre));
981 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
982 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
983 {
984 return PVMFFailure;
985 }
986 int32 numAssetInfoGenre = getNumAssetInfoGenreAtoms();
987 if (numAssetInfoGenre > 0)
988 {
989 for (int32 i = 0; i < numAssetInfoGenre; i++)
990 {
991 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoGenreNotice(charType, i);
992 genreValues.push_front(valuestring);
993 iGenreLangCode.push_front(getAssetInfoGenreLangCode(i));
994 iGenreCharType.push_front(charType);
995 }
996 }
997 if (getITunesGnreString().get_size() > 0)
998 {
999 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesGnreString();
1000 genreValues.push_front(valuestring);
1001 iGenreLangCode.push_front(0);
1002 iGenreCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
1003 }
1004 return PVMFSuccess;
1005 }
1006
1007 // This function returns the Genres based on index value, to the parser node.
getGenre(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)1008 PVMFStatus Mpeg4File::getGenre(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType)
1009 {
1010 if (index < genreValues.size())
1011 {
1012 aVal = NULL;
1013 aLangCode = 0;
1014 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1015 aVal = genreValues[index].get_cstr();
1016 aLangCode = iGenreLangCode[index];
1017 aCharEncType = iGenreCharType[index];
1018 return PVMFSuccess;
1019 }
1020 return PVMFErrArgument;
1021 }
1022
1023
getNumCopyright()1024 uint32 Mpeg4File::getNumCopyright()
1025 {
1026 uint32 numCopyright = 0;
1027 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN;
1028 numCopyright = getNumCopyRightAtoms();
1029 if (getPVCopyright(chartype).get_size() > 0)
1030 {
1031 numCopyright++;
1032 }
1033 if (getITunesCopyright().get_size() > 0)
1034 {
1035 numCopyright++;
1036 }
1037 return numCopyright;
1038 }
1039
1040
1041 //This function populates the Copyright Vector with values from Asset Info, Itunes and PV Proprietary Atoms.
populateCopyrightVector()1042 PVMFStatus Mpeg4File::populateCopyrightVector()
1043 {
1044 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
1045 int32 numCopyright = getNumCopyright();
1046 ReserveMemoryForValuesVector(copyrightValues, numCopyright, leavecode);
1047 ReserveMemoryForLangCodeVector(iCopyrightLangCode, numCopyright, leavecode1);
1048 OSCL_TRY(leavecode2, iCopyrightCharType.reserve(numCopyright));
1049 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1050 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
1051 {
1052 return PVMFFailure;
1053 }
1054 int32 numAssetInfoCopyright = getNumCopyRightAtoms();
1055 if (numAssetInfoCopyright > 0)
1056 {
1057 for (int32 i = 0; i < numAssetInfoCopyright; i++)
1058 {
1059 OSCL_wHeapString<OsclMemAllocator> valuestring = getCopyRightString(charType, i);
1060 copyrightValues.push_front(valuestring);
1061 iCopyrightLangCode.push_front(getCopyRightLanguageCode(i));
1062 iCopyrightCharType.push_front(charType);
1063 }
1064 }
1065 if (getPVCopyright(charType).get_size() > 0)
1066 {
1067 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVCopyright(charType);
1068 copyrightValues.push_front(valuestring);
1069 iCopyrightLangCode.push_front(0);
1070 iCopyrightCharType.push_front(charType);
1071 }
1072 if (getITunesCopyright().get_size() > 0)
1073 {
1074 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesCopyright();
1075 copyrightValues.push_front(valuestring);
1076 iCopyrightLangCode.push_front(0);
1077 iCopyrightCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
1078 }
1079 return PVMFSuccess;
1080 }
1081
1082 // This function returns the Copyrights based on index value, to the parser node.
getCopyright(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)1083 PVMFStatus Mpeg4File::getCopyright(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType)
1084 {
1085 if (index < copyrightValues.size())
1086 {
1087 aVal = NULL;
1088 aLangCode = 0;
1089 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1090 aVal = copyrightValues[index].get_cstr();
1091 aLangCode = iCopyrightLangCode[index];
1092 aCharEncType = iCopyrightCharType[index];
1093 return PVMFSuccess;
1094 }
1095 return PVMFErrArgument;
1096 }
1097
1098
getNumComment()1099 uint32 Mpeg4File::getNumComment()
1100 {
1101 uint32 numComment = 0;
1102
1103
1104 if (getITunesComment().get_size() > 0)
1105 {
1106 numComment++;
1107 }
1108 PvmiKvpSharedPtrVector framevector;
1109 GetID3MetaData(framevector);
1110 uint32 num_frames = framevector.size();
1111 for (uint32 i = 0; i < num_frames; i++)
1112 {
1113 if (framevector.size() > 0)
1114 {
1115 if (oscl_strstr(framevector[i]->key, "comment") != 0)
1116 {
1117 numComment++;
1118 break;
1119 }
1120 }
1121 }
1122
1123 return numComment;
1124 }
1125
1126
1127 //This function populates the Comment Vector with values from Itunes, FullMusic Atoms.
populateCommentVector()1128 PVMFStatus Mpeg4File::populateCommentVector()
1129 {
1130 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
1131 int32 numComment = getNumComment();
1132 ReserveMemoryForValuesVector(commentValues, numComment, leavecode);
1133 ReserveMemoryForLangCodeVector(iCommentLangCode, numComment, leavecode1);
1134 OSCL_TRY(leavecode2, iCommentCharType.reserve(numComment));
1135 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
1136 {
1137 return PVMFFailure;
1138 }
1139
1140 if (getITunesComment().get_size() > 0)
1141 {
1142 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesComment();
1143 commentValues.push_front(valuestring);
1144 iCommentLangCode.push_front(0);
1145 iCommentCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
1146 }
1147 PvmiKvpSharedPtrVector framevector;
1148 GetID3MetaData(framevector);
1149 uint32 num_frames = framevector.size();
1150 for (uint32 i = 0; i < num_frames; i++)
1151 {
1152 if (framevector.size() > 0)
1153 {
1154 if (oscl_strstr(framevector[i]->key, "comment") != 0)
1155 {
1156 uint32 len = oscl_strlen(framevector[i]->value.pChar_value);
1157 oscl_memset(_id3v1Comment, 0, ID3V1_STR_MAX_SIZE);
1158 oscl_UTF8ToUnicode(framevector[i]->value.pChar_value, len, _id3v1Comment, len*2 + 2);
1159 commentValues.push_front(_id3v1Comment);
1160 iCommentLangCode.push_front(0);
1161 iCommentCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
1162 break;
1163 }
1164 }
1165 }
1166
1167 return PVMFSuccess;
1168 }
1169
1170 // This function returns the Comments based on index value, to the parser node.
getComment(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)1171 PVMFStatus Mpeg4File::getComment(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc& aCharEncType)
1172 {
1173 if (index < commentValues.size())
1174 {
1175 aVal = NULL;
1176 aLangCode = 0;
1177 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1178 aVal = commentValues[index].get_cstr();
1179 aLangCode = iCommentLangCode[index];
1180 aCharEncType = iCommentCharType[index];
1181 return PVMFSuccess;
1182 }
1183 return PVMFErrArgument;
1184 }
1185
1186
getNumDescription()1187 uint32 Mpeg4File::getNumDescription()
1188 {
1189 uint32 numDescription = 0;
1190 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN;
1191 numDescription = getNumAssetInfoDescAtoms();
1192 if (getPVDescription(chartype).get_size() > 0)
1193 {
1194 numDescription++;
1195 }
1196 if (getITunesDescription().get_size() > 0)
1197 {
1198 numDescription++;
1199 }
1200
1201 return numDescription;
1202 }
1203
1204
1205 //This function populates the Description Vector with values from Asset Info, Itunes and PV Proprietary Atoms.
populateDescriptionVector()1206 PVMFStatus Mpeg4File::populateDescriptionVector()
1207 {
1208 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
1209 int32 numDescription = getNumDescription();
1210 ReserveMemoryForValuesVector(descriptionValues, numDescription, leavecode);
1211 ReserveMemoryForLangCodeVector(iDescriptionLangCode, numDescription, leavecode1);
1212 OSCL_TRY(leavecode2, iDescriptionCharType.reserve(numDescription));
1213 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1214 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
1215 {
1216 return PVMFFailure;
1217 }
1218 int32 numAssetInfoDescription = getNumAssetInfoDescAtoms();
1219 if (numAssetInfoDescription > 0)
1220 {
1221 for (int32 i = 0; i < numAssetInfoDescription; i++)
1222 {
1223 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoDescNotice(charType, i);
1224 descriptionValues.push_front(valuestring);
1225 iDescriptionLangCode.push_front(getAssetInfoDescLangCode(i));
1226 iDescriptionCharType.push_front(charType);
1227 }
1228 }
1229 if (getPVDescription(charType).get_size() > 0)
1230 {
1231 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVDescription(charType);
1232 descriptionValues.push_front(valuestring);
1233 iDescriptionLangCode.push_front(0);
1234 iDescriptionCharType.push_front(charType);
1235 }
1236
1237 if (getITunesDescription().get_size() > 0)
1238 {
1239 OSCL_wHeapString<OsclMemAllocator> valuestring = getITunesDescription();
1240 descriptionValues.push_front(valuestring);
1241 iDescriptionLangCode.push_front(0);
1242 iDescriptionCharType.push_front(ORIGINAL_CHAR_TYPE_UNKNOWN);
1243 }
1244
1245 return PVMFSuccess;
1246 }
1247
1248 // This function returns the Descriptions based on index value, to the parser node.
getDescription(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)1249 PVMFStatus Mpeg4File::getDescription(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc&
1250 aCharEncType)
1251 {
1252 if (index < descriptionValues.size())
1253 {
1254 aVal = NULL;
1255 aLangCode = 0;
1256 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1257 aVal = descriptionValues[index].get_cstr();
1258 aLangCode = iDescriptionLangCode[index];
1259 aCharEncType = iDescriptionCharType[index];
1260 return PVMFSuccess;
1261 }
1262 return PVMFErrArgument;
1263 }
1264
1265
getNumRating()1266 uint32 Mpeg4File::getNumRating()
1267 {
1268 uint32 numRating = 0;
1269 MP4FFParserOriginalCharEnc chartype = ORIGINAL_CHAR_TYPE_UNKNOWN;
1270 numRating = getNumAssetInfoRatingAtoms();
1271
1272 if (getPVRating(chartype).get_size() > 0)
1273 {
1274 numRating++;
1275 }
1276 return numRating;
1277 }
1278
1279
1280 //This function populates the Rating Vector with values from Asset Info and PV Proprietary Atoms.
populateRatingVector()1281 PVMFStatus Mpeg4File::populateRatingVector()
1282 {
1283 int32 leavecode = 0, leavecode1 = 0, leavecode2 = 0;
1284 int32 numRating = getNumRating();
1285 ReserveMemoryForValuesVector(ratingValues, numRating, leavecode);
1286 ReserveMemoryForLangCodeVector(iRatingLangCode, numRating, leavecode1);
1287 OSCL_TRY(leavecode2, iRatingCharType.reserve(numRating));
1288 MP4FFParserOriginalCharEnc charType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1289 if (leavecode != 0 || leavecode1 != 0 || leavecode2 != 0)
1290 {
1291 return PVMFFailure;
1292 }
1293 int32 numAssetInfoRating = getNumAssetInfoRatingAtoms();
1294 if (numAssetInfoRating > 0)
1295 {
1296 for (int32 i = 0; i < numAssetInfoRating; i++)
1297 {
1298 OSCL_wHeapString<OsclMemAllocator> valuestring = getAssetInfoRatingNotice(charType, i);
1299 ratingValues.push_front(valuestring);
1300 iRatingLangCode.push_front(getAssetInfoRatingLangCode(i));
1301 iRatingCharType.push_front(charType);
1302 }
1303 }
1304 if (getPVRating(charType).get_size() > 0)
1305 {
1306 OSCL_wHeapString<OsclMemAllocator> valuestring = getPVRating(charType);
1307 ratingValues.push_front(valuestring);
1308 iRatingLangCode.push_front(0);
1309 iRatingCharType.push_front(charType);
1310 }
1311
1312 return PVMFSuccess;
1313 }
1314
1315 // This function returns the Ratings based on index value, to the parser node.
getRating(uint32 index,OSCL_wString & aVal,uint16 & aLangCode,MP4FFParserOriginalCharEnc & aCharEncType)1316 PVMFStatus Mpeg4File::getRating(uint32 index, OSCL_wString& aVal, uint16& aLangCode, MP4FFParserOriginalCharEnc&
1317 aCharEncType)
1318 {
1319 if (index < ratingValues.size())
1320 {
1321 aVal = NULL;
1322 aLangCode = 0;
1323 aCharEncType = ORIGINAL_CHAR_TYPE_UNKNOWN;
1324 aVal = ratingValues[index].get_cstr();
1325 aLangCode = iRatingLangCode[index];
1326 aCharEncType = iRatingCharType[index];
1327 return PVMFSuccess;
1328 }
1329 return PVMFErrArgument;
1330 }
1331
1332
getNumYear()1333 uint32 Mpeg4File::getNumYear()
1334 {
1335 uint32 numYear = 0;
1336 numYear = getNumAssetInfoRecordingYearAtoms();
1337 if (getITunesYear().get_size() > 0)
1338 {
1339 numYear++;
1340 }
1341
1342 PvmiKvpSharedPtrVector framevector;
1343 GetID3MetaData(framevector);
1344 uint32 num_frames = framevector.size();
1345 for (uint32 i = 0; i < num_frames; i++)
1346 {
1347 if (framevector.size() > 0)
1348 {
1349 if (oscl_strstr(framevector[i]->key, "year") != 0)
1350 {
1351 numYear++;
1352 break;
1353 }
1354 }
1355 }
1356 return numYear;
1357 }
1358
1359
1360 //This function populates the Year Vector with values from Asset Info, Itunes, FullMusic and PV Proprietary Atoms.
populateYearVector()1361 PVMFStatus Mpeg4File::populateYearVector()
1362 {
1363 int32 leavecode = 0;
1364 int32 numYear = getNumYear();
1365 OSCL_TRY(leavecode, yearValues.reserve(numYear));
1366
1367 if (leavecode != 0)
1368 {
1369 return PVMFFailure;
1370 }
1371 int32 numAssetInfoRecordingYear = getNumAssetInfoRecordingYearAtoms();
1372 if (numAssetInfoRecordingYear > 0)
1373 {
1374 for (int32 i = 0; i < numAssetInfoRecordingYear; i++)
1375 {
1376 uint16 valuestring = getAssetInfoRecordingYear(i);
1377 yearValues.push_front(valuestring);
1378 }
1379 }
1380 if (getITunesYear().get_size() > 0)
1381 {
1382 uint32 value, i;
1383 OSCL_wHeapString<OsclMemAllocator> values1 = getITunesYear();
1384 char valuestring[256];
1385 oscl_UnicodeToUTF8(values1.get_cstr(), values1.get_size(), valuestring, 256);
1386 i = PV_atoi(valuestring, 'd', value);
1387 yearValues.push_front(value);
1388 }
1389 PvmiKvpSharedPtrVector framevector;
1390 GetID3MetaData(framevector);
1391 uint32 num_frames = framevector.size();
1392 for (uint32 i = 0; i < num_frames; i++)
1393 {
1394 if (framevector.size() > 0)
1395 {
1396 if (oscl_strstr(framevector[i]->key, "year") != 0)
1397 {
1398 PV_atoi(framevector[i]->value.pChar_value, 'd', _id3v1Year);
1399 yearValues.push_front(_id3v1Year);
1400 break;
1401 }
1402 }
1403 }
1404
1405 return PVMFSuccess;
1406 }
1407
1408 // This function returns the Years based on index value, to the parser node.
getYear(uint32 index,uint32 & aVal)1409 PVMFStatus Mpeg4File::getYear(uint32 index, uint32& aVal)
1410 {
1411 if (index < yearValues.size())
1412 {
1413 aVal = 0;
1414 aVal = yearValues[index];
1415
1416 return PVMFSuccess;
1417 }
1418 return PVMFErrArgument;
1419 }
getPVTitle(MP4FFParserOriginalCharEnc & charType)1420 OSCL_wString& Mpeg4File::getPVTitle(MP4FFParserOriginalCharEnc &charType)
1421 {
1422 PVUserDataAtom *patom = NULL;
1423 if (_puserDataAtom != NULL)
1424 {
1425 patom =
1426 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm'));
1427 }
1428 else
1429 {
1430 return _emptyString;
1431 }
1432
1433 if (patom != NULL)
1434 {
1435 return patom->getPVTitle(charType);
1436 }
1437 else
1438 {
1439 return _emptyString;
1440 }
1441 }
1442
getPVAuthor(MP4FFParserOriginalCharEnc & charType)1443 OSCL_wString& Mpeg4File::getPVAuthor(MP4FFParserOriginalCharEnc &charType)
1444 {
1445 PVUserDataAtom *patom = NULL;
1446 if (_puserDataAtom != NULL)
1447 {
1448 patom =
1449 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm'));
1450 }
1451 else
1452 {
1453 return _emptyString;
1454 }
1455
1456 if (patom != NULL)
1457 {
1458 return patom->getPVAuthor(charType);
1459 }
1460 else
1461 {
1462 return _emptyString;
1463 }
1464 }
1465
getPVVersion(MP4FFParserOriginalCharEnc & charType)1466 OSCL_wString& Mpeg4File::getPVVersion(MP4FFParserOriginalCharEnc &charType)
1467 {
1468 OSCL_UNUSED_ARG(charType);
1469
1470 PVUserDataAtom *patom = NULL;
1471 if (_puserDataAtom != NULL)
1472 {
1473 patom =
1474 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm'));
1475 }
1476 else
1477 {
1478 return _emptyString;
1479 }
1480
1481 if (patom != NULL)
1482 {
1483 return patom->getPVVersion();
1484 }
1485 else
1486 {
1487 return _emptyString;
1488 }
1489 }
1490
getPVCopyright(MP4FFParserOriginalCharEnc & charType)1491 OSCL_wString& Mpeg4File::getPVCopyright(MP4FFParserOriginalCharEnc &charType)
1492 {
1493 PVUserDataAtom *patom = NULL;
1494 if (_puserDataAtom != NULL)
1495 {
1496 patom =
1497 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm'));
1498 }
1499 else
1500 {
1501 return _emptyString;
1502 }
1503
1504 if (patom != NULL)
1505 {
1506 return patom->getPVCopyright(charType);
1507 }
1508 else
1509 {
1510 return _emptyString;
1511 }
1512 }
1513
getPVDescription(MP4FFParserOriginalCharEnc & charType)1514 OSCL_wString& Mpeg4File::getPVDescription(MP4FFParserOriginalCharEnc &charType)
1515 {
1516 PVUserDataAtom *patom = NULL;
1517 if (_puserDataAtom != NULL)
1518 {
1519 patom =
1520 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm'));
1521 }
1522 else
1523 {
1524 return _emptyString;
1525 }
1526
1527 if (patom != NULL)
1528 {
1529 return patom->getPVDescription(charType);
1530 }
1531 else
1532 {
1533 return _emptyString;
1534 }
1535 }
1536
getPVRating(MP4FFParserOriginalCharEnc & charType)1537 OSCL_wString& Mpeg4File::getPVRating(MP4FFParserOriginalCharEnc &charType)
1538 {
1539 PVUserDataAtom *patom = NULL;
1540 if (_puserDataAtom != NULL)
1541 {
1542 patom =
1543 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm'));
1544 }
1545 else
1546 {
1547 return _emptyString;
1548 }
1549
1550 if (patom != NULL)
1551 {
1552 return patom->getPVRating(charType);
1553 }
1554 else
1555 {
1556 return _emptyString;
1557 }
1558 }
1559
getCreationDate(MP4FFParserOriginalCharEnc & charType)1560 OSCL_wHeapString<OsclMemAllocator> Mpeg4File::getCreationDate(MP4FFParserOriginalCharEnc &charType)
1561 {
1562 PVUserDataAtom *patom = NULL;
1563 if (_puserDataAtom != NULL)
1564 {
1565 patom =
1566 (PVUserDataAtom*) _puserDataAtom->getAtomOfType(FourCharConstToUint32('p', 'v', 'm', 'm'));
1567 if (patom != NULL)
1568 {
1569 return patom->getPVCreationDate(charType);
1570 }
1571 else
1572 {
1573 return _emptyString;
1574 }
1575 }
1576 else
1577 {
1578 return (_pmovieAtom->getCreationDate());
1579 }
1580 }
1581
1582 // Destructor
~Mpeg4File()1583 Mpeg4File::~Mpeg4File()
1584 {
1585 uint32 i;
1586 // Clean up atoms
1587 if (_pmovieAtom != NULL)
1588 {
1589 PV_MP4_FF_DELETE(NULL, MovieAtom, _pmovieAtom);
1590 }
1591
1592 //Delete all the track atoms in the vec
1593 for (i = 0; i < _pTrackAtomVec->size(); i++)
1594 {
1595 PV_MP4_FF_DELETE(NULL, TrackAtom, (*_pTrackAtomVec)[i]);
1596 }
1597
1598 // Delete the vectors themselves
1599 PV_MP4_FF_TEMPLATED_DELETE(NULL, trackAtomVecType, Oscl_Vector, _pTrackAtomVec);
1600
1601
1602 titleValues.destroy();
1603 iTitleLangCode.destroy();
1604 iTitleCharType.destroy();
1605
1606 authorValues.destroy();
1607 iAuthorLangCode.destroy();
1608 iAuthorCharType.destroy();
1609
1610
1611 albumValues.destroy();
1612 iAlbumLangCode.destroy();
1613 iAlbumCharType.destroy();
1614
1615
1616 artistValues.destroy();
1617 iArtistLangCode.destroy();
1618 iArtistCharType.destroy();
1619
1620
1621 genreValues.destroy();
1622 iGenreLangCode.destroy();
1623 iGenreCharType.destroy();
1624
1625
1626 yearValues.destroy();
1627
1628
1629 copyrightValues.destroy();
1630 iCopyrightLangCode.destroy();
1631 iCopyrightCharType.destroy();
1632
1633
1634 commentValues.destroy();
1635 iCommentLangCode.destroy();
1636 iCommentCharType.destroy();
1637
1638
1639 descriptionValues.destroy();
1640 iDescriptionLangCode.destroy();
1641 iDescriptionCharType.destroy();
1642
1643
1644 ratingValues.destroy();
1645 iRatingLangCode.destroy();
1646 iRatingCharType.destroy() ;
1647
1648
1649 //delete all movie fragments
1650 for (i = 0; i < _pMovieFragmentAtomVec->size(); i++)
1651 {
1652 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom, (*_pMovieFragmentAtomVec)[i]);
1653 }
1654 PV_MP4_FF_TEMPLATED_DELETE(NULL, movieFragmentAtomVecType, Oscl_Vector, _pMovieFragmentAtomVec);
1655 //delete all movie fragments randomm access box
1656 for (i = 0; i < _pMovieFragmentRandomAccessAtomVec->size(); i++)
1657 {
1658 PV_MP4_FF_DELETE(NULL, MovieFragmentRandomAccessAtom, (*_pMovieFragmentRandomAccessAtomVec)[i]);
1659 }
1660 // Delete the vectors themselves
1661 PV_MP4_FF_TEMPLATED_DELETE(NULL, movieFragmentRandomAccessAtomVecType, Oscl_Vector, _pMovieFragmentRandomAccessAtomVec);
1662
1663 if (_pMoofOffsetVec != NULL)
1664 PV_MP4_FF_TEMPLATED_DELETE(NULL, movieFragmentOffsetVecType, Oscl_Vector, _pMoofOffsetVec);
1665
1666
1667 if (_pMfraOffsetAtom != NULL)
1668 {
1669 PV_MP4_FF_DELETE(NULL, MfraOffsetAtom, _pMfraOffsetAtom);
1670 }
1671
1672 if (_pTrackDurationContainer != NULL)
1673 {
1674 for (i = 0; i < _pTrackDurationContainer->_pTrackdurationInfoVec->size(); i++)
1675 {
1676 PV_MP4_FF_DELETE(NULL, TrackDurationInfo, (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i]);
1677 }
1678 PV_MP4_FF_TEMPLATED_DELETE(NULL, trackDurationInfoVecType, Oscl_Vector, _pTrackDurationContainer->_pTrackdurationInfoVec);
1679
1680 PV_MP4_FF_DELETE(NULL, TrackDurationContainer, _pTrackDurationContainer);
1681 }
1682
1683 // Delete user data if present
1684 if (_puserDataAtom != NULL)
1685 {
1686 PV_MP4_FF_DELETE(NULL, UserDataAtom, _puserDataAtom);
1687 }
1688
1689 if (_pFileTypeAtom != NULL)
1690 {
1691 PV_MP4_FF_DELETE(NULL, FileTypeAtom, _pFileTypeAtom);
1692 }
1693
1694 if (_movieFragmentFilePtr != NULL)
1695 {
1696 if (_movieFragmentFilePtr->IsOpen())
1697 {
1698 AtomUtils::CloseMP4File(_movieFragmentFilePtr);
1699 }
1700 oscl_free(_movieFragmentFilePtr);
1701 }
1702 if (_pID3Parser)
1703 {
1704 PV_MP4_FF_DELETE(null, PVID3ParCom, _pID3Parser);
1705 _pID3Parser = NULL;
1706 }
1707 }
1708
1709
getMovieDuration() const1710 uint64 Mpeg4File::getMovieDuration() const
1711 {
1712 uint64 overallMovieDuration = 0;
1713 uint32 id = 0;
1714 if (_isMovieFragmentsPresent)
1715 {
1716 overallMovieDuration = _pmovieAtom->getMovieFragmentDuration();
1717 if (Oscl_Int64_Utils::get_uint64_lower32(overallMovieDuration) != 0)
1718 {
1719 return overallMovieDuration;
1720 }
1721 else if (_parsing_mode == 0)
1722 {
1723 uint numTracks = _pmovieAtom->getNumTracks();
1724 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks);
1725 if (! trackList)
1726 return 0; // malloc failure
1727 _pmovieAtom->getTrackWholeIDList(trackList);
1728 uint32 prevtrackDuration = 0, trackduration = 0;
1729 for (uint32 i = 0; i < numTracks; i++)
1730 {
1731 TrackDurationInfo* pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i];
1732 trackduration = pTrackDurationInfo->trackDuration;
1733 if (prevtrackDuration > trackduration)
1734 {
1735 trackduration = prevtrackDuration;
1736 }
1737 else
1738 {
1739 prevtrackDuration = trackduration;
1740 id = trackList[i];
1741 }
1742 }
1743 Oscl_Int64_Utils::set_uint64(overallMovieDuration, 0, trackduration);
1744
1745 TrackAtom *trackAtom = NULL;
1746 uint32 mediaTimeScale = 0xFFFFFFFE;
1747
1748 if (_pmovieAtom != NULL)
1749 {
1750 trackAtom = _pmovieAtom->getTrackForID(id);
1751 }
1752 if (trackAtom != NULL)
1753 {
1754 mediaTimeScale = trackAtom->getMediaTimescale();
1755 if (mediaTimeScale == 0)
1756 {
1757 // unlikely : getMediaTimescale can return 0
1758 mediaTimeScale = 0xFFFFFFFE;
1759 }
1760 }
1761
1762 overallMovieDuration = (overallMovieDuration / (uint64)mediaTimeScale) * (uint64)getMovieTimescale();
1763 oscl_free(trackList);
1764 return overallMovieDuration;
1765 }
1766 else
1767 {
1768 return overallMovieDuration;
1769 }
1770 }
1771 else if (_pmovieAtom != NULL)
1772 {
1773 // Get the overall duration of the Mpeg-4 presentation
1774 return _pmovieAtom->getDuration();
1775 }
1776 return 0;
1777 }
1778
getMovieFragmentDuration() const1779 uint64 Mpeg4File::getMovieFragmentDuration() const
1780 {
1781 if (_pmovieAtom != NULL)
1782 {
1783 return _pmovieAtom->getMovieFragmentDuration();
1784 }
1785 else
1786 return 0;
1787 }
1788
getTimestampForSampleNumber(uint32 id,uint32 sampleNumber)1789 uint32 Mpeg4File::getTimestampForSampleNumber(uint32 id, uint32 sampleNumber)
1790 {
1791 TrackAtom *trackAtom;
1792
1793 if (_pmovieAtom != NULL)
1794 {
1795 trackAtom = _pmovieAtom->getTrackForID(id);
1796
1797 if (trackAtom != NULL)
1798 {
1799 return trackAtom->getTimestampForSampleNumber(sampleNumber);
1800 }
1801 else
1802 {
1803 return 0;
1804 }
1805 }
1806 else
1807 {
1808 return 0;
1809 }
1810 }
1811
getSampleSizeAt(uint32 id,int32 sampleNum)1812 int32 Mpeg4File::getSampleSizeAt(uint32 id, int32 sampleNum)
1813 {
1814 TrackAtom *trackAtom;
1815
1816 if (_pmovieAtom != NULL)
1817 {
1818 trackAtom = _pmovieAtom->getTrackForID(id);
1819
1820 if (trackAtom != NULL)
1821 {
1822 return (trackAtom->getSampleSizeAt(sampleNum));
1823 }
1824 else
1825 {
1826 return 0;
1827 }
1828 }
1829 else
1830 {
1831 return 0;
1832 }
1833 }
1834
getTrackMediaDurationForMovie(uint32 id)1835 uint64 Mpeg4File::getTrackMediaDurationForMovie(uint32 id)
1836 {
1837 TrackAtom *trackAtom;
1838 if (_pmovieAtom != NULL)
1839 {
1840 trackAtom = _pmovieAtom->getTrackForID(id);
1841 }
1842 else
1843 {
1844 return 0;
1845 }
1846 if (trackAtom != NULL)
1847 {
1848 return trackAtom->getTrackDuration();
1849 }
1850 else
1851 {
1852 return 0;
1853 }
1854
1855 }
1856 // From TrackHeader
getTrackDuration(uint32 id)1857 uint64 Mpeg4File::getTrackDuration(uint32 id)
1858 {
1859 TrackAtom *trackAtom;
1860 if (_pmovieAtom != NULL)
1861 {
1862 trackAtom = _pmovieAtom->getTrackForID(id);
1863 }
1864 else
1865 {
1866 return 0;
1867 }
1868 if (_isMovieFragmentsPresent)
1869 {
1870 if (_parsing_mode)
1871 return _pmovieAtom->getMovieFragmentDuration();
1872 else
1873 {
1874 int32 numTracks = _pmovieAtom->getNumTracks();
1875 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks);
1876 if (!trackList)
1877 return 0; // malloc failed
1878 _pmovieAtom->getTrackWholeIDList(trackList);
1879 uint64 trackduration = 0;
1880 for (int32 i = 0; i < numTracks; i++)
1881 {
1882 if (trackList[i] == id)
1883 {
1884 TrackDurationInfo* pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i];
1885 oscl_free(trackList);
1886 return trackduration = pTrackDurationInfo->trackDuration;
1887 }
1888 }
1889 oscl_free(trackList);
1890 }
1891 }
1892 if (trackAtom != NULL)
1893 {
1894 return trackAtom->getTrackDuration();
1895 }
1896 else
1897 {
1898 return 0;
1899 }
1900 }
1901
1902 // From TrackReference
trackDependsOn(uint32 id)1903 uint32 Mpeg4File::trackDependsOn(uint32 id)
1904 {
1905 TrackAtom *trackAtom;
1906 if (_pmovieAtom != NULL)
1907 {
1908 trackAtom = _pmovieAtom->getTrackForID(id);
1909 }
1910 else
1911 {
1912 return 0;
1913 }
1914
1915 if (trackAtom != NULL)
1916 {
1917 return trackAtom->dependsOn();
1918 }
1919 else
1920 {
1921 return 0;
1922 }
1923
1924 }
1925
1926 // From MediaHeader
getTrackMediaDuration(uint32 id)1927 uint64 Mpeg4File::getTrackMediaDuration(uint32 id)
1928 {
1929 TrackAtom *trackAtom;
1930 if (_pmovieAtom != NULL)
1931 {
1932 trackAtom = _pmovieAtom->getTrackForID(id);
1933 }
1934 else
1935 {
1936 return 0;
1937 }
1938 if (_isMovieFragmentsPresent)
1939 {
1940 if (_parsing_mode)
1941 return _pmovieAtom->getMovieFragmentDuration();
1942 else
1943 {
1944 int numTracks = _pmovieAtom->getNumTracks();
1945 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks);
1946 if (!trackList)
1947 return 0; // malloc failed
1948 _pmovieAtom->getTrackWholeIDList(trackList);
1949 uint32 trackduration = 0;
1950 for (int32 i = 0; i < numTracks; i++)
1951 {
1952 if (trackList[i] == id)
1953 {
1954 TrackDurationInfo* pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i];
1955 oscl_free(trackList);
1956 return trackduration = pTrackDurationInfo->trackDuration;
1957 }
1958 }
1959 oscl_free(trackList);
1960 }
1961 }
1962
1963 if (trackAtom != NULL)
1964 {
1965 return trackAtom->getMediaDuration();
1966 }
1967 else
1968 {
1969 return 0;
1970 }
1971 }
1972
getTrackMediaTimescale(uint32 id)1973 uint32 Mpeg4File::getTrackMediaTimescale(uint32 id)
1974 {
1975 TrackAtom *trackAtom;
1976 if (_pmovieAtom != NULL)
1977 {
1978 trackAtom = _pmovieAtom->getTrackForID(id);
1979 }
1980 else
1981 {
1982 // RETURN UNDEFINED VALUE
1983 return (0xFFFFFFFF);
1984 }
1985
1986 if (trackAtom != NULL)
1987 {
1988 return trackAtom->getMediaTimescale();
1989 }
1990 else
1991 {
1992 // RETURN UNDEFINED VALUE
1993 return (0xFFFFFFFF);
1994 }
1995 }
1996
getTrackLangCode(uint32 id)1997 uint16 Mpeg4File::getTrackLangCode(uint32 id)
1998 {
1999
2000 TrackAtom *trackAtom;
2001 if (_pmovieAtom != NULL)
2002 {
2003 trackAtom = _pmovieAtom->getTrackForID(id);
2004 }
2005 else
2006 {
2007 // RETURN UNDEFINED VALUE
2008 return (0xFFFF);
2009 }
2010
2011 if (trackAtom != NULL)
2012 {
2013 return trackAtom->getLanguageCode();
2014 }
2015 else
2016 {
2017 // RETURN UNDEFINED VALUE
2018 return (0xFFFF);
2019 }
2020 }
2021
2022 // From Handler
getTrackMediaType(uint32 id)2023 uint32 Mpeg4File::getTrackMediaType(uint32 id)
2024 {
2025 TrackAtom *trackAtom;
2026 if (_pmovieAtom != NULL)
2027 {
2028 trackAtom = _pmovieAtom->getTrackForID(id);
2029 }
2030 else
2031 {
2032 // RETURN UNDEFINED VALUE
2033 return (0xFFFFFFFF);
2034 }
2035
2036 if (trackAtom != NULL)
2037 {
2038 return trackAtom->getMediaType();
2039 }
2040 else
2041 {
2042 // RETURN UNDEFINED VALUE
2043 return (0xFFFFFFFF);
2044 }
2045
2046 }
2047
2048 // From SampleDescription
getTrackNumSampleEntries(uint32 id)2049 int32 Mpeg4File::getTrackNumSampleEntries(uint32 id)
2050 {
2051 TrackAtom *trackAtom;
2052
2053 if (_pmovieAtom != NULL)
2054 {
2055 trackAtom = _pmovieAtom->getTrackForID(id);
2056 }
2057 else
2058 {
2059 return 0;
2060 }
2061
2062 if (trackAtom != NULL)
2063 {
2064 return trackAtom->getNumSampleEntries();
2065 }
2066 else
2067 {
2068 return 0;
2069 }
2070 }
2071
2072 // From DecoderConfigDescriptor
getTrackDecoderSpecificInfo(uint32 id)2073 DecoderSpecificInfo *Mpeg4File::getTrackDecoderSpecificInfo(uint32 id)
2074 {
2075 TrackAtom *trackAtom;
2076 if (_pmovieAtom != NULL)
2077 {
2078 trackAtom = _pmovieAtom->getTrackForID(id);
2079 }
2080 else
2081 {
2082 return NULL;
2083 }
2084
2085 if (trackAtom != NULL)
2086 {
2087 return trackAtom->getDecoderSpecificInfo();
2088 }
2089 else
2090 {
2091 return NULL;
2092 }
2093
2094 }
2095
2096 // From DecoderConfigDescriptor
2097 DecoderSpecificInfo *
getTrackDecoderSpecificInfoAtSDI(uint32 trackID,uint32 index)2098 Mpeg4File::getTrackDecoderSpecificInfoAtSDI(uint32 trackID, uint32 index)
2099 {
2100 if (_pmovieAtom != NULL)
2101 {
2102 return (_pmovieAtom->getTrackDecoderSpecificInfoAtSDI(trackID, index));
2103 }
2104 else
2105 {
2106 return NULL;
2107 }
2108 }
2109
getTrackDecoderSpecificInfoContent(uint32 id)2110 uint8 *Mpeg4File::getTrackDecoderSpecificInfoContent(uint32 id)
2111 {
2112 DecoderSpecificInfo *decoderSpecificInfo;
2113 decoderSpecificInfo = getTrackDecoderSpecificInfo(id);
2114
2115 if (decoderSpecificInfo != NULL)
2116 {
2117 return decoderSpecificInfo->getInfo();
2118 }
2119 else
2120 {
2121 return NULL;
2122 }
2123 }
2124
getTrackDecoderSpecificInfoSize(uint32 id)2125 uint32 Mpeg4File::getTrackDecoderSpecificInfoSize(uint32 id)
2126 {
2127 DecoderSpecificInfo *decoderSpecificInfo;
2128 decoderSpecificInfo = getTrackDecoderSpecificInfo(id);
2129
2130 if (decoderSpecificInfo != NULL)
2131 {
2132 return decoderSpecificInfo->getInfoSize();
2133 }
2134 else
2135 {
2136 return 0;
2137 }
2138 }
2139
2140
getTrackMIMEType(uint32 id,OSCL_String & aMimeType)2141 void Mpeg4File::getTrackMIMEType(uint32 id, OSCL_String& aMimeType) // Based on OTI value
2142 {
2143 TrackAtom *trackAtom = NULL;
2144
2145 if (_pmovieAtom != NULL)
2146 {
2147 trackAtom = _pmovieAtom->getTrackForID(id);
2148 }
2149
2150 if (trackAtom != NULL)
2151 {
2152 trackAtom->getMIMEType(aMimeType);
2153 }
2154 }
2155
2156
getTrackMaxBufferSizeDB(uint32 id)2157 int32 Mpeg4File::getTrackMaxBufferSizeDB(uint32 id)
2158 {
2159 TrackAtom *trackAtom;
2160
2161 if (_pmovieAtom != NULL)
2162 {
2163 trackAtom = _pmovieAtom->getTrackForID(id);
2164 }
2165 else
2166 {
2167 return 0;
2168 }
2169
2170 if (trackAtom != NULL)
2171 {
2172 return trackAtom->getMaxBufferSizeDB();
2173 }
2174 else
2175 {
2176 return 0;
2177 }
2178 }
2179
getTrackAverageBitrate(uint32 id)2180 int32 Mpeg4File::getTrackAverageBitrate(uint32 id)
2181 {
2182 TrackAtom *trackAtom;
2183
2184 if (_pmovieAtom != NULL)
2185 {
2186 trackAtom = _pmovieAtom->getTrackForID(id);
2187 }
2188 else
2189 {
2190 return 0;
2191 }
2192
2193 if (trackAtom != NULL)
2194 {
2195 return trackAtom->getAverageBitrate();
2196 }
2197 else
2198 {
2199 return 0;
2200 }
2201 }
2202
2203 // PASP Box
2204 //Hspacing
getHspacing(uint32 id)2205 uint32 Mpeg4File::getHspacing(uint32 id)
2206 {
2207
2208 TrackAtom *trackAtom;
2209
2210 if (_pmovieAtom != NULL)
2211 {
2212 trackAtom = _pmovieAtom->getTrackForID(id);
2213 }
2214 else
2215 {
2216 return 0;
2217 }
2218
2219 if (trackAtom != NULL)
2220 {
2221 return trackAtom->getHspacing();
2222 }
2223 else
2224 {
2225 return 0;
2226 }
2227 }
2228
2229 //Vspacing
getVspacing(uint32 id)2230 uint32 Mpeg4File::getVspacing(uint32 id)
2231 {
2232
2233 TrackAtom *trackAtom;
2234
2235 if (_pmovieAtom != NULL)
2236 {
2237 trackAtom = _pmovieAtom->getTrackForID(id);
2238 }
2239 else
2240 {
2241 return 0;
2242 }
2243
2244 if (trackAtom != NULL)
2245 {
2246 return trackAtom->getVspacing();
2247 }
2248 else
2249 {
2250 return 0;
2251 }
2252 }
2253
2254
2255 uint32
getMovieTimescale() const2256 Mpeg4File::getMovieTimescale() const
2257 {
2258 if (_pmovieAtom != NULL)
2259 {
2260 // Set the overall timescale of the Mpeg-4 presentation
2261 return _pmovieAtom->getTimeScale();
2262 }
2263 else
2264 {
2265 // RETURN UNDEFINED VALUE
2266 return (0xFFFFFFFF);
2267 }
2268 }
2269
2270 /* ======================================================================== */
2271 bool
IsMobileMP4()2272 Mpeg4File::IsMobileMP4()
2273 {
2274 bool oMMP4 = false;
2275
2276 if (_pFileTypeAtom != NULL)
2277 {
2278 uint32 majorBrand = _pFileTypeAtom->getMajorBrand();
2279
2280 if (majorBrand != MOBILE_MP4)
2281 {
2282 Oscl_Vector<uint32, OsclMemAllocator> *_compatibleBrand =
2283 _pFileTypeAtom->getCompatibleBrand();
2284 if (_compatibleBrand != NULL)
2285 {
2286 for (uint32 i = 0; i < _compatibleBrand->size(); i++)
2287 {
2288 uint32 brand = (*_compatibleBrand)[i];
2289
2290 if (brand == MOBILE_MP4)
2291 {
2292 oMMP4 = true;
2293 }
2294 }
2295 }
2296 else
2297 {
2298 return false;
2299 }
2300 }
2301 else
2302 {
2303 oMMP4 = true;
2304 }
2305 }
2306 else
2307 {
2308 return false;
2309 }
2310
2311 if (oMMP4 == true)
2312 {
2313 if (!(_pmovieAtom->checkMMP4()))
2314 {
2315 return false;
2316 }
2317 }
2318
2319 return (oMMP4);
2320 }
2321
2322 uint8
parseBufferAndGetNumAMRFrames(uint8 * buffer,uint32 size)2323 Mpeg4File::parseBufferAndGetNumAMRFrames(uint8* buffer, uint32 size)
2324 {
2325 uint32 inputBufferSize = size;
2326 uint8* inputPtr = buffer;
2327 uint8 numArmFrames = 0;
2328
2329 if (((int32)(size) <= 0) ||
2330 (buffer == NULL))
2331 {
2332 return 0;
2333 }
2334
2335 uint8 aFrameSizes[16] = {12, 13, 15, 17, 19, 20, 26, 31,
2336 5, 0, 0, 0, 0, 0, 0, 0
2337 };
2338
2339 while (inputBufferSize > 0)
2340 {
2341 uint8 toc_byte = *(inputPtr);
2342
2343 uint8 frame_type = (uint8)((toc_byte >> 3) & 0x0F);
2344
2345 inputPtr += 1;
2346 inputBufferSize -= 1;
2347
2348 if ((frame_type > 8) && (frame_type != 15))
2349 {
2350 return 0;
2351 }
2352
2353 numArmFrames++;
2354 inputPtr += aFrameSizes[(uint16)frame_type];
2355 inputBufferSize -= aFrameSizes[(uint16)frame_type];
2356 }
2357 return (numArmFrames);
2358 }
2359
2360
getTrackLevelOMA2DRMInfoSize(uint32 trackID)2361 uint32 Mpeg4File::getTrackLevelOMA2DRMInfoSize(uint32 trackID)
2362 {
2363 TrackAtom *trackAtom;
2364
2365 if (_pmovieAtom != NULL)
2366 {
2367 trackAtom = _pmovieAtom->getTrackForID(trackID);
2368 }
2369 else
2370 {
2371 return 0;
2372 }
2373
2374 if (trackAtom != NULL)
2375 {
2376 return trackAtom->getTrackLevelOMA2DRMInfoSize();
2377 }
2378 else
2379 {
2380 return 0;
2381 }
2382 }
2383
getTrackLevelOMA2DRMInfo(uint32 trackID)2384 uint8* Mpeg4File::getTrackLevelOMA2DRMInfo(uint32 trackID)
2385 {
2386 TrackAtom *trackAtom;
2387
2388 if (_pmovieAtom != NULL)
2389 {
2390 trackAtom = _pmovieAtom->getTrackForID(trackID);
2391 }
2392 else
2393 {
2394 return NULL;
2395 }
2396
2397 if (trackAtom != NULL)
2398 {
2399 return trackAtom->getTrackLevelOMA2DRMInfo();
2400 }
2401 else
2402 {
2403 return NULL;
2404 }
2405 }
2406
2407
2408 MP4_ERROR_CODE
RequestReadCapacityNotification(PvmiDataStreamObserver & aObserver,uint32 aFileOffset,OsclAny * aContextData)2409 Mpeg4File::RequestReadCapacityNotification(PvmiDataStreamObserver& aObserver,
2410 uint32 aFileOffset,
2411 OsclAny* aContextData)
2412 {
2413 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::RequestReadCapacityNotification In Offset %d", aFileOffset));
2414 uint32 capacity = 0;
2415 if (_commonFilePtr != NULL)
2416 {
2417 uint32 currPos = (uint32)(AtomUtils::getCurrentFilePosition(_commonFilePtr));
2418 if (aFileOffset > currPos)
2419 {
2420 capacity = (aFileOffset - currPos);
2421 bool retVal =
2422 _commonFilePtr->_pvfile.RequestReadCapacityNotification(aObserver,
2423 capacity,
2424 aContextData);
2425 if (retVal)
2426 {
2427 return EVERYTHING_FINE;
2428 }
2429 else
2430 {
2431 return DEFAULT_ERROR;
2432 }
2433 }
2434 return SUFFICIENT_DATA_IN_FILE;
2435 }
2436 return DEFAULT_ERROR;
2437 }
2438
2439
2440 MP4_ERROR_CODE
GetCurrentFileSize(uint32 & aFileSize)2441 Mpeg4File::GetCurrentFileSize(uint32& aFileSize)
2442 {
2443 aFileSize = 0;
2444 if (AtomUtils::getCurrentFileSize(_commonFilePtr, aFileSize) == true)
2445 {
2446 return EVERYTHING_FINE;
2447 }
2448 if (_commonFilePtr == NULL && _fileSize != 0)
2449 {
2450 aFileSize = _fileSize;
2451 return EVERYTHING_FINE;
2452 }
2453 return DEFAULT_ERROR;
2454 }
2455
getNextBundledAccessUnits(const uint32 trackID,uint32 * n,GAU * pgau)2456 int32 Mpeg4File::getNextBundledAccessUnits(const uint32 trackID,
2457 uint32 *n,
2458 GAU *pgau)
2459 {
2460 uint32 samplesTobeRead;
2461 samplesTobeRead = *n;
2462 uint32 totalSampleRead = 0;
2463 if (getNumTracks() == 0)
2464 {
2465 return -1;
2466 }
2467
2468 if (_pmovieAtom != NULL)
2469 {
2470 int32 ret = _pmovieAtom->getNextBundledAccessUnits(trackID, n, pgau);
2471 if (ret == END_OF_TRACK)
2472 {
2473 if (!_isMovieFragmentsPresent)
2474 return ret;
2475
2476 totalSampleRead += *n;
2477 bool oAllMoofExhausted = false;
2478 bool oAllMoofParsed = false;
2479
2480 if (_parsing_mode == 0)
2481 {
2482 if (_pMovieFragmentAtomVec != NULL && _isMovieFragmentsPresent)
2483 {
2484 if (samplesTobeRead >= *n)
2485 *n = samplesTobeRead - *n;
2486 }
2487 else
2488 return ret;
2489
2490 int32 return1 = 0;
2491 while (_movieFragmentIdx[trackID] < _pMovieFragmentAtomVec->size())
2492 {
2493 uint32 movieFragmentIdx = _movieFragmentIdx[trackID];
2494 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx];
2495 if (pMovieFragmentAtom != NULL)
2496 {
2497 if ((uint32)pMovieFragmentAtom->getSequenceNumber() == _movieFragmentSeqIdx[trackID])
2498 {
2499 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID);
2500 if (trackfragment != NULL)
2501 {
2502 if (trackfragment->getTrackId() == trackID)
2503 {
2504 return1 = pMovieFragmentAtom->getNextBundledAccessUnits(trackID, n, totalSampleRead, pgau);
2505 totalSampleRead += *n;
2506 if (return1 != END_OF_TRACK)
2507 {
2508 *n = totalSampleRead;
2509 return return1;
2510 }
2511 else
2512 {
2513 _movieFragmentSeqIdx[trackID]++;
2514 if (samplesTobeRead >= *n)
2515 {
2516 samplesTobeRead = samplesTobeRead - *n;
2517 *n = samplesTobeRead;
2518 }
2519 }
2520 }
2521 }
2522 }
2523 }
2524 _movieFragmentIdx[trackID]++;
2525 }
2526 if (return1 == END_OF_TRACK)
2527 {
2528 *n = totalSampleRead;
2529 _movieFragmentIdx[trackID] = 0;
2530 return return1;
2531 }
2532 }
2533 else
2534 {
2535 int32 return1 = 0;
2536 while (!oAllMoofExhausted)
2537 {
2538 if (oAllMoofParsed && (_pMovieFragmentAtomVec->size() < _movieFragmentIdx[trackID]))
2539 {
2540 oAllMoofExhausted = true;
2541 *n = 0;
2542 break;
2543 }
2544
2545 while (!oAllMoofParsed)
2546 {
2547 if (moofParsingCompleted)
2548 {
2549 uint32 moofIndex = 0;
2550 bool moofToBeParsed = false;
2551 if (_pMovieFragmentAtomVec->size() > _movieFragmentIdx[trackID])
2552 {
2553 MovieFragmentAtom *pMovieFragmentAtom = NULL;
2554 uint32 idx = _movieFragmentIdx[trackID];
2555 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[_movieFragmentIdx[trackID]];
2556 if (pMovieFragmentAtom == NULL)
2557 {
2558 isResetPlayBackCalled = true;
2559 moofToBeParsed = true;
2560 moofIndex = _movieFragmentIdx[trackID];
2561 }
2562 else if (isResetPlayBackCalled)
2563 {
2564 isResetPlayBackCalled = false;
2565
2566 // if moofs are already parsed, so go to the end of MOOF Vector.
2567
2568 uint32 currFilePos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2569 if (currFilePos < _ptrMoofEnds)
2570 {
2571 uint32 offset = (_ptrMoofEnds - currFilePos);
2572 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset);
2573 }
2574 else if (currFilePos == _ptrMoofEnds)
2575 {
2576 // no need to seek the File Pointer
2577 }
2578 else
2579 {
2580 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds);
2581 }
2582
2583 idx = currMoofNum - 1;
2584 uint32 i = idx + 1;
2585 while (i < _pMovieFragmentAtomVec->size())
2586 {
2587 idx++;
2588 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
2589 if (pMovieFragmentAtom == NULL)
2590 {
2591 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx-1];
2592 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_start_offset);
2593 uint32 atomType = UNKNOWN_ATOM;
2594 uint32 atomSize = 0;
2595 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
2596 if (atomType == MOVIE_FRAGMENT_ATOM)
2597 {
2598 atomSize -= DEFAULT_ATOM_SIZE;
2599 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
2600 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2601 }
2602 isResetPlayBackCalled = true;
2603 moofToBeParsed = true;
2604 moofIndex = idx;
2605 break;
2606 }
2607 pMovieFragmentAtom->resetPlayback();
2608 i++;
2609 }
2610 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx];
2611 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_start_offset);
2612 uint32 atomType = UNKNOWN_ATOM;
2613 uint32 atomSize = 0;
2614 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
2615 if (atomType == MOVIE_FRAGMENT_ATOM)
2616 {
2617 atomSize -= DEFAULT_ATOM_SIZE;
2618 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
2619 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2620 }
2621 }
2622 }
2623
2624 uint32 fileSize = 0;
2625 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize);
2626 uint32 currFilePos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2627 if (currFilePos < _ptrMoofEnds)
2628 {
2629 uint32 offset = (_ptrMoofEnds - currFilePos);
2630 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset);
2631 }
2632 else
2633 {
2634 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds);
2635 }
2636 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2637 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE;
2638
2639 while (count > 0)
2640 {
2641 uint32 atomType = UNKNOWN_ATOM;
2642 uint32 atomSize = 0;
2643 uint32 currPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2644 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
2645 if ((currPos + atomSize) > fileSize)
2646 {
2647 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos);
2648 if (_movieFragmentIdx[trackID] < _pMovieFragmentAtomVec->size())
2649 {
2650 // dont report insufficient data as we still have a moof/moofs to
2651 // retrieve data. So just go and retrieve the data.
2652 break;
2653 }
2654 else
2655 {
2656 // We have run out of MOOF atoms so report insufficient data.
2657 return INSUFFICIENT_DATA;
2658 }
2659 }
2660
2661 if (atomType == MOVIE_FRAGMENT_ATOM)
2662 {
2663 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2664 moofStartOffset -= DEFAULT_ATOM_SIZE;
2665 parseMoofCompletely = false;
2666 moofSize = atomSize;
2667 moofType = atomType;
2668 moofCount = count;
2669 _ptrMoofEnds = moofStartOffset + atomSize;
2670
2671 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom);
2672 moofSize = atomSize;
2673 moofPtrPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2674
2675 currMoofNum = _pMovieFragmentAtom->getSequenceNumber();
2676 if (moofToBeParsed)
2677 {
2678 (*_pMovieFragmentAtomVec)[moofIndex] = _pMovieFragmentAtom;
2679 (*_pMoofOffsetVec)[moofIndex] = moofStartOffset;
2680 }
2681 else
2682 {
2683 _pMoofOffsetVec->push_back(moofStartOffset);
2684 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom);
2685 }
2686
2687 if (moofParsingCompleted)
2688 {
2689 if (!_pMovieFragmentAtom->MP4Success())
2690 {
2691 _success = false;
2692 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error();
2693 oAllMoofExhausted = true;
2694 break;
2695 }
2696 _pMovieFragmentAtom->setParent(this);
2697 count -= _pMovieFragmentAtom->getSize();
2698
2699 break;
2700 }
2701
2702 break;
2703 }
2704 else if (atomType == MEDIA_DATA_ATOM)
2705 {
2706 if (atomSize == 1)
2707 {
2708 uint64 largeSize = 0;
2709 AtomUtils::read64(_movieFragmentFilePtr, largeSize);
2710 uint32 size =
2711 Oscl_Int64_Utils::get_uint64_lower32(largeSize);
2712 count -= size;
2713 size -= 8; //for large size
2714 size -= DEFAULT_ATOM_SIZE;
2715 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size);
2716 }
2717 else
2718 {
2719 if (atomSize < DEFAULT_ATOM_SIZE)
2720 {
2721 _success = false;
2722 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
2723 oAllMoofExhausted = true;
2724 break;
2725 }
2726 if (count < (int32)atomSize)
2727 {
2728 _success = false;
2729 _mp4ErrorCode = INSUFFICIENT_DATA;
2730 ret = _mp4ErrorCode;
2731 oAllMoofExhausted = true;
2732 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos);
2733 break;
2734 }
2735 count -= atomSize;
2736 atomSize -= DEFAULT_ATOM_SIZE;
2737 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
2738 }
2739 }
2740
2741 else
2742 {
2743 if (count > 0)
2744 {
2745 count -= atomSize;
2746 atomSize -= DEFAULT_ATOM_SIZE;
2747 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
2748 }
2749
2750 }
2751 }
2752 if (count <= 0)
2753 {
2754 oAllMoofParsed = true;
2755 break;
2756 }
2757 break;
2758 }
2759 else if (!moofParsingCompleted)
2760 {
2761 if (currMoofNum != (uint32) _pMovieFragmentAtom->getSequenceNumber())
2762 {
2763 uint32 size = _pMovieFragmentAtomVec->size();
2764 _pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[size - 1];
2765 }
2766 uint32 currPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2767 if (currPos > moofPtrPos)
2768 {
2769 uint32 offset = (currPos - moofPtrPos);
2770 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, -((int32)offset));
2771 }
2772 else
2773 {
2774 uint32 offset = (moofPtrPos - currPos);
2775 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset);
2776 }
2777
2778 _pMovieFragmentAtom->ParseMoofAtom(_movieFragmentFilePtr, moofSize, moofType, _pTrackDurationContainer, _pTrackExtendsAtomVec, moofParsingCompleted, countOfTrunsParsed);
2779 moofPtrPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
2780 if (moofParsingCompleted)
2781 {
2782 if (!_pMovieFragmentAtom->MP4Success())
2783 {
2784 _success = false;
2785 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error();
2786 oAllMoofExhausted = true;
2787 break;
2788 }
2789 _pMovieFragmentAtom->setParent(this);
2790 moofCount -= _pMovieFragmentAtom->getSize();
2791 }
2792
2793 if (currPos > moofPtrPos)
2794 {
2795 uint32 offset = (currPos - moofPtrPos);
2796 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, offset);
2797 }
2798 else
2799 {
2800 uint32 offset = (moofPtrPos - currPos);
2801 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, -((int32)offset));
2802 }
2803
2804 if (moofCount <= 0)
2805 {
2806 oAllMoofParsed = true;
2807 break;
2808 }
2809 break;
2810 }
2811 }
2812
2813 if (return1 != END_OF_TRACK)
2814 {
2815 if (samplesTobeRead >= *n)
2816 *n = samplesTobeRead - *n;
2817 }
2818
2819 uint32 movieFragmentIdx = _movieFragmentIdx[trackID];
2820 MovieFragmentAtom *pMovieFragmentAtom = NULL;
2821
2822 if (movieFragmentIdx < _pMovieFragmentAtomVec->size())
2823 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx];
2824
2825 if (pMovieFragmentAtom != NULL)
2826 {
2827 uint32 seqNum = pMovieFragmentAtom->getSequenceNumber();
2828 if (seqNum == _movieFragmentSeqIdx[trackID])
2829 {
2830 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID);
2831 if (trackfragment != NULL)
2832 {
2833 if (trackfragment->getTrackId() == trackID)
2834 {
2835 return1 = pMovieFragmentAtom->getNextBundledAccessUnits(trackID, n, totalSampleRead, pgau);
2836 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::getNextBundledAccessUnits return %d", return1));
2837 totalSampleRead += *n;
2838 if (return1 != END_OF_TRACK)
2839 {
2840 *n = totalSampleRead;
2841 return return1;
2842 }
2843 else
2844 {
2845 _movieFragmentSeqIdx[trackID]++;
2846 if (samplesTobeRead >= *n)
2847 {
2848 samplesTobeRead = samplesTobeRead - *n;
2849 *n = samplesTobeRead;
2850 if (movieFragmentIdx < _pMovieFragmentAtomVec->size())
2851 {
2852 _movieFragmentIdx[trackID]++;
2853 }
2854 }
2855 }
2856 }
2857 }
2858 else
2859 {
2860 uint32 movieFragmentIdx2 = _movieFragmentIdx[trackID];
2861
2862 if (oAllMoofParsed)
2863 {
2864 // look for all moofs
2865 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size())
2866 {
2867 _movieFragmentIdx[trackID]++;
2868 _movieFragmentSeqIdx[trackID]++;
2869 }
2870 else
2871 {
2872 return END_OF_TRACK;
2873 }
2874
2875 }
2876 else
2877 {
2878 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size())
2879 {
2880 if ((movieFragmentIdx2 == (_pMovieFragmentAtomVec->size() - 1)) && moofParsingCompleted)
2881 {
2882 _movieFragmentIdx[trackID]++;
2883 _movieFragmentSeqIdx[trackID]++;
2884 }
2885 else if (movieFragmentIdx2 < (_pMovieFragmentAtomVec->size() - 1))
2886 {
2887 _movieFragmentIdx[trackID]++;
2888 _movieFragmentSeqIdx[trackID]++;
2889 *n = 0;
2890 return NO_SAMPLE_IN_CURRENT_MOOF;
2891 }
2892 }
2893 }
2894 }
2895 }
2896 else
2897 {
2898 uint32 movieFragmentIdx2 = _movieFragmentIdx[trackID];
2899
2900 if (oAllMoofParsed)
2901 {
2902 // look for all moofs
2903 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size())
2904 {
2905 _movieFragmentIdx[trackID]++;
2906 _movieFragmentSeqIdx[trackID]++;
2907 }
2908 else
2909 {
2910 return END_OF_TRACK;
2911 }
2912
2913 }
2914 else
2915 {
2916 if (movieFragmentIdx2 < _pMovieFragmentAtomVec->size())
2917 {
2918 if ((movieFragmentIdx2 == (_pMovieFragmentAtomVec->size() - 1)) && moofParsingCompleted)
2919 {
2920 _movieFragmentIdx[trackID]++;
2921 _movieFragmentSeqIdx[trackID]++;
2922 }
2923 else if (movieFragmentIdx2 < (_pMovieFragmentAtomVec->size() - 1))
2924 {
2925 _movieFragmentIdx[trackID]++;
2926 _movieFragmentSeqIdx[trackID]++;
2927 *n = 0;
2928 return NO_SAMPLE_IN_CURRENT_MOOF;
2929 }
2930 }
2931 }
2932 }
2933 }
2934 else
2935 {
2936 if (movieFragmentIdx < _pMovieFragmentAtomVec->size())
2937 {
2938 _movieFragmentIdx[trackID]++;
2939 _movieFragmentSeqIdx[trackID]++;
2940 }
2941 else if (oAllMoofParsed)
2942 {
2943 _movieFragmentIdx[trackID]++;
2944 _movieFragmentSeqIdx[trackID]++;
2945 }
2946
2947 }
2948 }
2949 }
2950 }
2951 return ret;
2952 }
2953 return -1;
2954 }
2955
getMovieFragmentForTrackId(uint32 id)2956 MovieFragmentAtom * Mpeg4File::getMovieFragmentForTrackId(uint32 id)
2957 {
2958 MovieFragmentAtom *movieFragmentAtom = NULL;
2959 uint32 i = 0;
2960
2961 if (_pMovieFragmentAtomVec == NULL)
2962 return NULL;
2963
2964 while (i < _pMovieFragmentAtomVec->size())
2965 {
2966 movieFragmentAtom = (*_pMovieFragmentAtomVec)[i];
2967 if (movieFragmentAtom != NULL)
2968 {
2969 TrackFragmentAtom *trackfragment = movieFragmentAtom->getTrackFragmentforID(id);
2970 if (trackfragment != NULL)
2971 {
2972 if (trackfragment->getTrackId() == id)
2973 {
2974 return movieFragmentAtom;
2975 }
2976 }
2977 }
2978 i++;
2979 }
2980 return NULL;
2981 }
2982
populateTrackDurationVec()2983 void Mpeg4File::populateTrackDurationVec()
2984 {
2985 uint32 trackDuration = 0;
2986 if (_pmovieAtom != NULL)
2987 {
2988 uint32 ids[256];
2989 uint32 size = 256;
2990 _pmovieAtom->getTrackIDList(ids, size);
2991 int32 numtracks = _pmovieAtom->getNumTracks();
2992 PV_MP4_FF_NEW(fp->auditCB, TrackDurationContainer, (), _pTrackDurationContainer);
2993 PV_MP4_FF_NEW(fp->auditCB, trackDurationInfoVecType, (), _pTrackDurationContainer->_pTrackdurationInfoVec);
2994 for (int32 i = 0; i < numtracks; i++)
2995 {
2996 uint32 trackID = ids[i];
2997 TrackDurationInfo *trackinfo = NULL;
2998 trackDuration = Oscl_Int64_Utils::get_uint64_lower32(_pmovieAtom->getTrackMediaDuration(trackID));
2999 PV_MP4_FF_NEW(fp->auditCB, TrackDurationInfo, (trackDuration, trackID), trackinfo);
3000 (*_pTrackDurationContainer->_pTrackdurationInfoVec).push_back(trackinfo);
3001 _movieFragmentIdx[trackID] = 0;
3002 _peekMovieFragmentIdx[trackID] = 0;
3003 _movieFragmentSeqIdx[trackID] = 1;
3004 _peekMovieFragmentSeqIdx[trackID] = 1;
3005 }
3006 }
3007 }
3008
GetByteOffsetToStartOfAudioFrames()3009 uint32 Mpeg4File::GetByteOffsetToStartOfAudioFrames()
3010 {
3011 return _pID3Parser->GetByteOffsetToStartOfAudioFrames();
3012
3013 }
3014
GetID3MetaData(PvmiKvpSharedPtrVector & id3Frames)3015 void Mpeg4File::GetID3MetaData(PvmiKvpSharedPtrVector &id3Frames)
3016 {
3017 _pID3Parser->GetID3Frames(id3Frames);
3018
3019 }
3020
IsID3Frame(const OSCL_String & frameType)3021 bool Mpeg4File::IsID3Frame(const OSCL_String& frameType)
3022 {
3023 return _pID3Parser->IsID3FrameAvailable(frameType);
3024 }
3025
GetID3Frame(const OSCL_String & aFrameType,PvmiKvpSharedPtrVector & aFrame)3026 void Mpeg4File::GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrame)
3027 {
3028 _pID3Parser->GetID3Frame(aFrameType, aFrame);
3029 }
3030
GetID3Version() const3031 PVID3Version Mpeg4File::GetID3Version() const
3032 {
3033 return _pID3Parser->GetID3Version();
3034 }
3035
parseID3Header(MP4_FF_FILE * aFile)3036 void Mpeg4File::parseID3Header(MP4_FF_FILE *aFile)
3037 {
3038 int32 curpos = AtomUtils::getCurrentFilePosition(aFile);
3039 AtomUtils::seekFromStart(aFile, 0);
3040 _pID3Parser->ParseID3Tag(&aFile->_pvfile);
3041 AtomUtils::seekFromStart(aFile, curpos);
3042 }
3043
getContentType()3044 uint32 Mpeg4File::getContentType()
3045 {
3046 PVContentTypeAtom *pAtom = NULL;
3047
3048 if (_puserDataAtom != NULL)
3049 {
3050 pAtom =
3051 (PVContentTypeAtom*) _puserDataAtom->getAtomOfType(PV_CONTENT_TYPE_ATOM);
3052
3053 if (pAtom != NULL)
3054 {
3055 return pAtom->getContentType();
3056 }
3057 else
3058 {
3059 if (_oPVContent)
3060 {
3061 //Old PV Content, that doesnt have this atom
3062 //All such content is non-interleaved, with meta data
3063 //towards the very end
3064 return (DEFAULT_AUTHORING_MODE);
3065 }
3066 }
3067 }
3068
3069 //Third party content
3070 return (0xFFFFFFFF);
3071 }
3072
3073
getKeyMediaSampleNumAt(uint32 aTrackId,uint32 aKeySampleNum,GAU * pgau)3074 MP4_ERROR_CODE Mpeg4File::getKeyMediaSampleNumAt(uint32 aTrackId,
3075 uint32 aKeySampleNum,
3076 GAU *pgau)
3077 {
3078 if (_pmovieAtom == NULL)
3079 {
3080 return READ_SAMPLE_TABLE_ATOM_FAILED;
3081 }
3082 MP4_ERROR_CODE ret = _pmovieAtom->getKeyMediaSampleNumAt(aTrackId, aKeySampleNum, pgau);
3083 if (ret == READ_FAILED)
3084 {
3085 uint32 totalSampleRead = 0;
3086 if (_isMovieFragmentsPresent)
3087 {
3088 uint32 n = 1;
3089 uint32 movieFragmentIdx = _movieFragmentIdx[aTrackId];
3090 MovieFragmentAtom *pMovieFragmentAtom = NULL;
3091
3092 if (movieFragmentIdx < _pMovieFragmentAtomVec->size())
3093 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx];
3094
3095 if (pMovieFragmentAtom != NULL)
3096 {
3097 uint32 seqNum = pMovieFragmentAtom->getSequenceNumber();
3098 if (seqNum == _movieFragmentSeqIdx[aTrackId])
3099 {
3100 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(aTrackId);
3101 if (trackfragment != NULL)
3102 {
3103 if (trackfragment->getTrackId() == aTrackId)
3104 {
3105 return (MP4_ERROR_CODE)pMovieFragmentAtom->getNextBundledAccessUnits(aTrackId, &n, totalSampleRead, pgau);
3106 }
3107 }
3108 }
3109 }
3110 }
3111 return READ_FAILED;
3112 }
3113 else
3114 {
3115 return ret;
3116 }
3117 }
3118
3119
3120
getOffsetByTime(uint32 id,uint32 ts,int32 * sampleFileOffset,uint32 jitterbuffertimeinmillisec)3121 int32 Mpeg4File::getOffsetByTime(uint32 id, uint32 ts, int32* sampleFileOffset , uint32 jitterbuffertimeinmillisec)
3122 {
3123 int32 ret = DEFAULT_ERROR;
3124 uint32 sigmaAtomSize = 0;
3125 if (_pmovieAtom != NULL)
3126 {
3127 ret = _pmovieAtom->getOffsetByTime(id, ts, sampleFileOffset);
3128 if (ret == DEFAULT_ERROR || ret == LAST_SAMPLE_IN_MOOV)
3129 {
3130 if (_isMovieFragmentsPresent)
3131 {
3132 uint32 sigmaTrafDuration = 0;
3133
3134 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++)
3135 {
3136 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
3137 if (pMovieFragmentAtom != NULL)
3138 {
3139 uint32 currTrafDuration = pMovieFragmentAtom->getCurrentTrafDuration(id);
3140 if (currTrafDuration >= ts)
3141 {
3142 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
3143 return pMovieFragmentAtom->getOffsetByTime(id, ts, sampleFileOffset);
3144 }
3145 sigmaTrafDuration += currTrafDuration;
3146 }
3147 }
3148
3149 if (_parsing_mode == 1)
3150 {
3151 if (moofParsingCompleted)
3152 {
3153 // do nothing
3154 }
3155 else
3156 {
3157 if ((uint32)_pMovieFragmentAtom->getSequenceNumber() == _movieFragmentSeqIdx[id])
3158 {
3159 AtomUtils::seekFromStart(_movieFragmentFilePtr, moofPtrPos);
3160
3161 while (!moofParsingCompleted)
3162 {
3163 _pMovieFragmentAtom->ParseMoofAtom(_movieFragmentFilePtr, moofSize, moofType, _pTrackDurationContainer, _pTrackExtendsAtomVec, moofParsingCompleted, countOfTrunsParsed);
3164 }
3165
3166 if (moofParsingCompleted)
3167 {
3168 if (!_pMovieFragmentAtom->MP4Success())
3169 {
3170 _success = false;
3171 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error();
3172 }
3173 _pMovieFragmentAtom->setParent(this);
3174 moofSize = _pMovieFragmentAtom->getSize();
3175 moofCount -= _pMovieFragmentAtom->getSize();
3176 }
3177
3178 uint32 currTrafDuration = _pMovieFragmentAtom->getCurrentTrafDuration(id);
3179
3180 if (currTrafDuration >= ts)
3181 {
3182 ret = _pMovieFragmentAtom->getOffsetByTime(id, ts, sampleFileOffset);
3183 if (*sampleFileOffset == 0)
3184 {
3185 // do nothing, continue parsing
3186 }
3187 else
3188 {
3189 return ret;
3190 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: ret Sample Offset=> Sample Offset= %d ret %d********@@@@@@@@@@@@@@@@", *sampleFileOffset, ret));
3191 }
3192 }
3193 sigmaTrafDuration += currTrafDuration;
3194 }
3195 else
3196 {
3197 // This condition will only happen when the MovieFragmentAtomVec size is
3198 // greater than 1.
3199 uint32 i = _pMovieFragmentAtomVec->size();
3200 _ptrMoofEnds = (*_pMoofOffsetVec)[i-2] + (*_pMovieFragmentAtomVec)[i-2]->getSize();
3201 _pMoofOffsetVec->pop_back();
3202 _pMovieFragmentAtomVec->pop_back();
3203 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]);
3204 parseMoofCompletely = true;
3205 moofParsingCompleted = true;
3206 moofSize = 0;
3207 moofType = UNKNOWN_ATOM;
3208 moofCount = 0;
3209 moofPtrPos = 0;
3210 }
3211 }
3212
3213 uint32 fileSize = 0;
3214 uint32 currfptr = 0;
3215
3216 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize);
3217 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime::FileSize %d Track ID %d ********@@@@@@@@@@@@@@@@", fileSize, id));
3218
3219 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds);
3220 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3221 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE;
3222 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: TS= %d ********@@@@@@@@@@@@@@@@, count=%d, filePointer=%d", ts, count, filePointer));
3223
3224 while (count > 0)
3225 {
3226 uint32 atomType = UNKNOWN_ATOM;
3227 uint32 atomSize = 0;
3228 AtomUtils::Flush(_movieFragmentFilePtr);
3229 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
3230 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: count=%d, AtomSize=%d, atomtype=%d", count, atomSize, atomType));
3231 if (atomSize < DEFAULT_ATOM_SIZE)
3232 {
3233
3234 ret = DEFAULT_ERROR;
3235 break;
3236 }
3237 sigmaAtomSize += atomSize;
3238 if (atomType == MOVIE_FRAGMENT_ATOM)
3239 {
3240 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3241 moofStartOffset -= DEFAULT_ATOM_SIZE;
3242 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: MovieFragmentAtom moofStartOffset=%d", moofStartOffset));
3243
3244 moofSize = atomSize;
3245
3246 if ((moofStartOffset + atomSize) > fileSize)
3247 {
3248 uint32 timeScale = _pmovieAtom->getTrackMediaTimescale(id);
3249 if ((timeScale == 0) || (timeScale == 0xFFFFFFFF))
3250 {
3251 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Invalid timeScale %d for Id %d", timeScale, id));
3252 return DEFAULT_ERROR;
3253 }
3254
3255 uint32 trackPlayedSoFarInSec = ts / timeScale - jitterbuffertimeinmillisec / 1000;
3256 uint32 rateOfDataUsageKbPerSec = 0;
3257 if (trackPlayedSoFarInSec != 0)
3258 {
3259 rateOfDataUsageKbPerSec = fileSize / trackPlayedSoFarInSec;
3260 }
3261 // estimate data for PVMF_MP4FFPARSER_PSEUDO_STREAMING_DURATION_IN_SEC
3262 uint32 dataNeededAhead = (rateOfDataUsageKbPerSec * jitterbuffertimeinmillisec) / 1000;
3263
3264 *sampleFileOffset = moofStartOffset + atomSize + DEFAULT_ATOM_SIZE + dataNeededAhead;
3265 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Insufficient data ot get Sample Offset= %d ********@@@@@@@@@@@@@@@@", *sampleFileOffset));
3266 ret = EVERYTHING_FINE;
3267 break;
3268 }
3269
3270 _pMoofOffsetVec->push_back(moofStartOffset);
3271 parseMoofCompletely = true;
3272
3273 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom);
3274
3275 if (!_pMovieFragmentAtom->MP4Success())
3276 {
3277
3278 _success = false;
3279 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error();
3280 break;
3281 }
3282 count -= _pMovieFragmentAtom->getSize();
3283 _pMovieFragmentAtom->setParent(this);
3284
3285 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom);
3286 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3287
3288 uint32 currTrafDuration = _pMovieFragmentAtom->getCurrentTrafDuration(id);
3289
3290 if (currTrafDuration >= ts)
3291 {
3292 ret = _pMovieFragmentAtom->getOffsetByTime(id, ts, sampleFileOffset);
3293 if (*sampleFileOffset == 0)
3294 {
3295 // do nothing, continue parsing
3296 }
3297 else
3298 {
3299 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: ret Sample Offset=> Sample Offset= %d ret %d********@@@@@@@@@@@@@@@@", *sampleFileOffset, ret));
3300 break;
3301 }
3302 }
3303 sigmaTrafDuration += currTrafDuration;
3304 }
3305 else if (atomType == MEDIA_DATA_ATOM)
3306 {
3307
3308 if (atomSize == 1)
3309 {
3310 uint64 largeSize = 0;
3311 AtomUtils::read64(_movieFragmentFilePtr, largeSize);
3312 uint32 size =
3313 Oscl_Int64_Utils::get_uint64_lower32(largeSize);
3314 count -= size;
3315 size -= 8; //for large size
3316 size -= DEFAULT_ATOM_SIZE;
3317 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size);
3318 }
3319 else
3320 {
3321 currfptr = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3322 if ((currfptr + atomSize) > fileSize)
3323 {
3324 uint32 timeScale = _pmovieAtom->getTrackMediaTimescale(id);
3325 if ((timeScale == 0) || (timeScale == 0xFFFFFFFF))
3326 {
3327 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Invalid timeScale %d for Id %d", timeScale, id));
3328 return DEFAULT_ERROR;
3329 }
3330 uint32 trackPlayedSoFarInSec = ts / timeScale - jitterbuffertimeinmillisec / 1000;
3331 uint32 rateOfDataUsageKbPerSec = 0;
3332 if (trackPlayedSoFarInSec != 0)
3333 {
3334 rateOfDataUsageKbPerSec = fileSize / trackPlayedSoFarInSec;
3335 }
3336
3337 // estimate data for PVMF_MP4FFPARSER_PSEUDO_STREAMING_DURATION_IN_SEC
3338 uint32 dataNeededAhead = (rateOfDataUsageKbPerSec * jitterbuffertimeinmillisec) / 1000;
3339 *sampleFileOffset = currfptr + atomSize + moofSize + dataNeededAhead;
3340 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "getOffsetByTime:: Insufficient data ot get Sample Offset= %d ********@@@@@@@@@@@@@@@@", *sampleFileOffset));
3341 ret = EVERYTHING_FINE;
3342 break;
3343
3344 }
3345 count -= atomSize;
3346 atomSize -= DEFAULT_ATOM_SIZE;
3347 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
3348 }
3349 }
3350
3351 else
3352 {
3353 if (count > 0)
3354 {
3355 count -= atomSize;
3356 atomSize -= DEFAULT_ATOM_SIZE;
3357 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
3358 }
3359 }
3360 }
3361 if (sigmaTrafDuration == 0)
3362 {
3363 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize);
3364 *sampleFileOffset = fileSize + 1000;
3365
3366 ret = EVERYTHING_FINE;
3367 }
3368 }
3369 }
3370 else if (ret == LAST_SAMPLE_IN_MOOV)
3371 {
3372 ret = EVERYTHING_FINE;
3373 }
3374
3375 }
3376
3377 return ret;
3378 }
3379 else
3380 {
3381
3382 return ret;
3383 }
3384 }
3385
getTimestampForRandomAccessPoints(uint32 id,uint32 * num,uint32 * tsBuf,uint32 * numBuf,uint32 * offsetBuf)3386 int32 Mpeg4File::getTimestampForRandomAccessPoints(uint32 id, uint32 *num, uint32 *tsBuf, uint32* numBuf, uint32 *offsetBuf)
3387 {
3388 if (_pmovieAtom != NULL)
3389 {
3390 uint32 requestedSamples = *num, delta = 0, returnedSampleFromMoov = 0;
3391 uint32 ret = _pmovieAtom->getTimestampForRandomAccessPoints(id, num, tsBuf, numBuf, offsetBuf);
3392 if (ret == 1)
3393 {
3394 returnedSampleFromMoov = *num;
3395 if (requestedSamples != 0)
3396 {
3397 if (requestedSamples == returnedSampleFromMoov)
3398 return ret;
3399
3400 if (requestedSamples > returnedSampleFromMoov)
3401 {
3402 delta = requestedSamples - returnedSampleFromMoov;
3403 }
3404 }
3405
3406 }
3407 else
3408 delta = *num;
3409
3410 if (_isMovieFragmentsPresent)
3411 {
3412 if (_pMovieFragmentRandomAccessAtomVec != NULL)
3413 { // Only one mfra possible in a clip so this loop will run only once
3414 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++)
3415 {
3416 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx];
3417 ret = pMovieFragmentRandomAccessAtom->getTimestampForRandomAccessPoints(id, &delta, tsBuf, numBuf, offsetBuf, returnedSampleFromMoov);
3418 *num = delta;
3419 return ret;
3420 }
3421
3422 }
3423 }
3424 return ret;
3425 }
3426 return 0;
3427 }
3428
getTimestampForRandomAccessPointsBeforeAfter(uint32 id,uint32 ts,uint32 * tsBuf,uint32 * numBuf,uint32 & numsamplestoget,uint32 howManyKeySamples)3429 int32 Mpeg4File::getTimestampForRandomAccessPointsBeforeAfter(uint32 id, uint32 ts, uint32 *tsBuf, uint32* numBuf,
3430 uint32& numsamplestoget,
3431 uint32 howManyKeySamples)
3432 {
3433 if (_pmovieAtom != NULL)
3434 {
3435 int32 ret = _pmovieAtom->getTimestampForRandomAccessPointsBeforeAfter(id, ts, tsBuf, numBuf, numsamplestoget, howManyKeySamples);
3436 if (ret != 1)
3437 {
3438 if (_isMovieFragmentsPresent)
3439 {
3440 if (_pMovieFragmentRandomAccessAtomVec != NULL)
3441 { // Only one mfra possible in a clip so this loop will run only once
3442 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++)
3443 {
3444 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx];
3445 ret = pMovieFragmentRandomAccessAtom->getTimestampForRandomAccessPointsBeforeAfter(id, ts, tsBuf, numBuf, numsamplestoget, howManyKeySamples);
3446 return ret;
3447 }
3448
3449 }
3450 }
3451 }
3452 return ret;
3453
3454 }
3455 else
3456 {
3457 return 0;
3458 }
3459 }
3460
3461
3462
resetAllMovieFragments()3463 void Mpeg4File::resetAllMovieFragments()
3464 {
3465 uint32 trackDuration = 0;
3466 if (_isMovieFragmentsPresent)
3467 {
3468 if (_pMovieFragmentAtomVec != NULL)
3469 {
3470 int numTracks = _pmovieAtom->getNumTracks();
3471 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks);
3472 if (!trackList)
3473 return; // malloc failed
3474
3475 _pmovieAtom->getTrackWholeIDList(trackList);
3476 for (int32 i = 0; i < numTracks; i++)
3477 {
3478 uint32 trackID = trackList[i];
3479 _movieFragmentIdx[trackID] = 0;
3480 _peekMovieFragmentIdx[trackID] = 0;
3481 _movieFragmentSeqIdx[trackID] = 1;
3482 _peekMovieFragmentSeqIdx[trackID] = 1;
3483 TrackDurationInfo *trackinfo = NULL;
3484 if (_pTrackDurationContainer != NULL)
3485 {
3486 TrackDurationInfo *pTrackDurationInfo = (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i];
3487 if (pTrackDurationInfo != NULL)
3488 {
3489 PV_MP4_FF_DELETE(NULL, TrackDurationInfo, pTrackDurationInfo);
3490 pTrackDurationInfo = NULL;
3491 }
3492 }
3493 trackDuration = Oscl_Int64_Utils::get_uint64_lower32(_pmovieAtom->getTrackMediaDuration(trackID));
3494 PV_MP4_FF_NEW(fp->auditCB, TrackDurationInfo, (trackDuration, trackID), trackinfo);
3495 (*_pTrackDurationContainer->_pTrackdurationInfoVec)[i] = trackinfo;
3496 }
3497 oscl_free(trackList);
3498 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++)
3499 {
3500 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
3501 if (pMovieFragmentAtom != NULL)
3502 pMovieFragmentAtom->resetPlayback();
3503
3504 }
3505 }
3506 }
3507 }
3508
3509
resetPlayback(uint32 time,uint16 numTracks,uint32 * trackList,bool bResetToIFrame)3510 uint32 Mpeg4File::resetPlayback(uint32 time, uint16 numTracks, uint32 *trackList, bool bResetToIFrame)
3511 {
3512 OSCL_UNUSED_ARG(numTracks);
3513
3514 uint32 modifiedTimeStamp = time;
3515 uint32 trackID = 0;
3516
3517 uint32 retVal = 0;
3518 bool oMoofFound = false;
3519
3520 uint32 convertedTS = 0;
3521 uint32 timestamp = 0, returnedTS = 0;
3522
3523 uint32 moof_offset = 0, traf_number = 0, trun_number = 0, sample_num = 0;
3524
3525 trackID = *trackList; // numTracks is the track index in trackList
3526 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL)
3527 {
3528 _oVideoTrackPresent = true;
3529 }
3530
3531 if (_isMovieFragmentsPresent)
3532 {
3533 if (_pMovieFragmentAtomVec->size() > 1)
3534 {
3535 // The boolean is used to reset all MOOFs to start after reposition. This should
3536 // be true only when number of MOOFs in MOOF vector queue is more than one.
3537 isResetPlayBackCalled = true;
3538 }
3539 }
3540
3541 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL)
3542 {
3543 if (repositionFromMoof(time, trackID))
3544 {
3545 //moof
3546 modifiedTimeStamp = time;
3547
3548 // convert modifiedTimeStamp (which is in ms) to the appropriate
3549 // media time scale
3550 MediaClockConverter mcc1(1000);
3551 mcc1.update_clock(modifiedTimeStamp);
3552 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID));
3553 if (oMfraFound)
3554 {
3555 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++)
3556 {
3557 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx];
3558 uint32 ret = pMovieFragmentRandomAccessAtom->getSyncSampleInfoClosestToTime(trackID, convertedTS, moof_offset, traf_number, trun_number, sample_num);
3559 if (ret == 0)
3560 {
3561 if (moofParsingCompleted)
3562 {
3563 // do nothing
3564 }
3565 else
3566 {
3567 uint32 i = _pMovieFragmentAtomVec->size();
3568 _pMoofOffsetVec->pop_back();
3569 _pMovieFragmentAtomVec->pop_back();
3570 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]);
3571 parseMoofCompletely = true;
3572 moofParsingCompleted = true;
3573 moofSize = 0;
3574 moofType = UNKNOWN_ATOM;
3575 moofCount = 0;
3576 moofPtrPos = 0;
3577 }
3578
3579 for (uint32 idx = 0; idx < _pMoofOffsetVec->size(); idx++)
3580 {
3581 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx];
3582 if (moof_start_offset == moof_offset)
3583 {
3584 _movieFragmentIdx[trackID] = idx;
3585 _peekMovieFragmentIdx[trackID] = idx;
3586 _movieFragmentSeqIdx[trackID] = (*_pMovieFragmentAtomVec)[idx]->getSequenceNumber();
3587 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID];
3588 _pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
3589 currMoofNum = _pMovieFragmentAtom->getSequenceNumber();
3590 oMoofFound = true;
3591
3592 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_offset);
3593 uint32 atomType = UNKNOWN_ATOM;
3594 uint32 atomSize = 0;
3595 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
3596 if (atomType == MOVIE_FRAGMENT_ATOM)
3597 {
3598 atomSize -= DEFAULT_ATOM_SIZE;
3599 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
3600 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3601 }
3602 break;
3603 }
3604 }
3605
3606 if (_parsing_mode == 1)
3607 {
3608 if (!oMoofFound)
3609 {
3610 uint32 fileSize = 0;
3611 _ptrMoofEnds = moof_offset;
3612 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize);
3613 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds);
3614 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3615 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE;
3616
3617 while (count > 0)
3618 {
3619 uint32 atomType = UNKNOWN_ATOM;
3620 uint32 atomSize = 0;
3621 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
3622 if (atomType == MOVIE_FRAGMENT_ATOM)
3623 {
3624 parseMoofCompletely = true;
3625
3626 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3627 moofStartOffset -= DEFAULT_ATOM_SIZE;
3628
3629 if (moofParsingCompleted)
3630 {
3631 // do nothing
3632 }
3633 else
3634 {
3635 uint32 i = _pMovieFragmentAtomVec->size();
3636 _pMoofOffsetVec->pop_back();
3637 _pMovieFragmentAtomVec->pop_back();
3638 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]);
3639 parseMoofCompletely = true;
3640 moofParsingCompleted = true;
3641 moofSize = 0;
3642 moofType = UNKNOWN_ATOM;
3643 moofCount = 0;
3644 moofPtrPos = 0;
3645 }
3646
3647 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom);
3648
3649 if (!_pMovieFragmentAtom->MP4Success())
3650 {
3651 _success = false;
3652 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error();
3653 break;
3654 }
3655
3656 _pMovieFragmentAtom->setParent(this);
3657 count -= _pMovieFragmentAtom->getSize();
3658
3659 uint32 i = _pMovieFragmentAtomVec->size();
3660
3661 MovieFragmentAtom *pMovieFragmentAtom = NULL;
3662 uint32 prevMoofSeqNum = 0;
3663
3664 if (i > 0)
3665 {
3666 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[i-1];
3667
3668 if (pMovieFragmentAtom != NULL)
3669 prevMoofSeqNum = (*_pMovieFragmentAtomVec)[i-1]->getSequenceNumber();
3670 }
3671
3672 currMoofNum = _pMovieFragmentAtom->getSequenceNumber();
3673
3674 for (uint32 idx = prevMoofSeqNum; idx < currMoofNum - 1; idx++)
3675 {
3676 _pMovieFragmentAtomVec->push_back(NULL);
3677 _pMoofOffsetVec->push_back(0);
3678 }
3679 if (currMoofNum > i)
3680 {
3681 _pMoofOffsetVec->push_back(moofStartOffset);
3682 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom);
3683 }
3684 else if ((*_pMovieFragmentAtomVec)[currMoofNum-1] == NULL)
3685 {
3686 (*_pMovieFragmentAtomVec)[currMoofNum-1] = _pMovieFragmentAtom;
3687 (*_pMoofOffsetVec)[currMoofNum-1] = moofStartOffset;
3688 }
3689 else
3690 {
3691 PV_MP4_FF_DELETE(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, _pMovieFragmentAtom);
3692 _pMovieFragmentAtom = NULL;
3693 break;
3694
3695 }
3696 _movieFragmentSeqIdx[trackID] = currMoofNum;
3697 _movieFragmentIdx[trackID] = currMoofNum - 1;
3698 _peekMovieFragmentIdx[trackID] = currMoofNum - 1;
3699 _peekMovieFragmentSeqIdx[trackID] = currMoofNum;
3700
3701 oMoofFound = true;
3702
3703 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3704 break;
3705 }
3706 else if (atomType == MEDIA_DATA_ATOM)
3707 {
3708 if (atomSize == 1)
3709 {
3710 uint64 largeSize = 0;
3711 AtomUtils::read64(_movieFragmentFilePtr, largeSize);
3712 uint32 size =
3713 Oscl_Int64_Utils::get_uint64_lower32(largeSize);
3714 count -= size;
3715 size -= 8; //for large size
3716 size -= DEFAULT_ATOM_SIZE;
3717 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size);
3718 }
3719 else
3720 {
3721 if (atomSize < DEFAULT_ATOM_SIZE)
3722 {
3723 _success = false;
3724 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
3725 break;
3726 }
3727 if (count < (int32)atomSize)
3728 {
3729 _success = false;
3730 _mp4ErrorCode = READ_FAILED;
3731 break;
3732 }
3733 count -= atomSize;
3734 atomSize -= DEFAULT_ATOM_SIZE;
3735 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
3736 }
3737 }
3738
3739 else
3740 {
3741 if (count > 0)
3742 {
3743 count -= atomSize;
3744 atomSize -= DEFAULT_ATOM_SIZE;
3745 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
3746 }
3747
3748 }
3749 }
3750 }
3751
3752 }
3753
3754 if (_pmovieAtom != NULL)
3755 _pmovieAtom->resetTrackToEOT();
3756
3757 if (_pMovieFragmentAtom != NULL)
3758 returnedTS = _pMovieFragmentAtom->resetPlayback(trackID, convertedTS, traf_number, trun_number, sample_num);
3759 }
3760 else
3761 {
3762 // Not a valid tfra entries, cannot reposition.
3763 return 0;
3764 }
3765 }
3766
3767 }
3768 else
3769 return 0;
3770
3771 // convert returnedTS (which is in media time scale) to the ms
3772 MediaClockConverter mcc(getTrackMediaTimescale(trackID));
3773 mcc.update_clock(returnedTS);
3774 timestamp = mcc.get_converted_ts(1000);
3775
3776 if (timestamp <= modifiedTimeStamp)
3777 {
3778 modifiedTimeStamp = timestamp;
3779 }
3780
3781 }
3782 else
3783 {
3784 if (_isMovieFragmentsPresent)
3785 {
3786 if (_pMovieFragmentAtomVec->size() > 0)
3787 {
3788 if (moofParsingCompleted)
3789 {
3790 // do nothing
3791 }
3792 else
3793 {
3794 uint32 i = _pMovieFragmentAtomVec->size();
3795 _pMoofOffsetVec->pop_back();
3796 _pMovieFragmentAtomVec->pop_back();
3797 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]);
3798 parseMoofCompletely = true;
3799 moofParsingCompleted = true;
3800 moofSize = 0;
3801 moofType = UNKNOWN_ATOM;
3802 moofCount = 0;
3803 moofPtrPos = 0;
3804 }
3805 }
3806 }
3807
3808 //movie
3809 if (_pmovieAtom != NULL)
3810 {
3811 resetAllMovieFragments();
3812 uint32 trackVideo = trackID;
3813 uint32 numTrackForVideo = 1;
3814 modifiedTimeStamp = _pmovieAtom->resetPlayback(modifiedTimeStamp, numTrackForVideo, &trackVideo, bResetToIFrame);
3815 }
3816 }
3817 }
3818 retVal = modifiedTimeStamp;
3819 if ((getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO) ||
3820 (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT))
3821 {
3822 if (repositionFromMoof(time, trackID))
3823 {
3824 oMoofFound = false;
3825 //moof
3826 // convert modifiedTimeStamp (which is in ms) to the appropriate
3827 // media time scale
3828 MediaClockConverter mcc1(1000);
3829 mcc1.update_clock(modifiedTimeStamp);
3830 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID));
3831 if (oMfraFound)
3832 {
3833 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++)
3834 {
3835 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx];
3836 uint32 ret = pMovieFragmentRandomAccessAtom->getSyncSampleInfoClosestToTime(trackID, convertedTS, moof_offset, traf_number, trun_number, sample_num);
3837 if (ret == 0)
3838 {
3839 if (moofParsingCompleted)
3840 {
3841 // do nothing
3842 }
3843 else
3844 {
3845 uint32 i = _pMovieFragmentAtomVec->size();
3846 _pMoofOffsetVec->pop_back();
3847 _pMovieFragmentAtomVec->pop_back();
3848 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]);
3849 parseMoofCompletely = true;
3850 moofParsingCompleted = true;
3851 moofSize = 0;
3852 moofType = UNKNOWN_ATOM;
3853 moofCount = 0;
3854 moofPtrPos = 0;
3855 }
3856 //
3857 for (idx = 0; idx < _pMoofOffsetVec->size(); idx++)
3858 {
3859 uint32 moof_start_offset = (*_pMoofOffsetVec)[idx];
3860 if (moof_start_offset == moof_offset)
3861 {
3862 _movieFragmentIdx[trackID] = idx;
3863 _peekMovieFragmentIdx[trackID] = idx;
3864 _movieFragmentSeqIdx[trackID] = (*_pMovieFragmentAtomVec)[idx]->getSequenceNumber();
3865 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID];
3866 _pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
3867 currMoofNum = _pMovieFragmentAtom->getSequenceNumber();
3868 oMoofFound = true;
3869
3870 AtomUtils::seekFromStart(_movieFragmentFilePtr, moof_offset);
3871 uint32 atomType = UNKNOWN_ATOM;
3872 uint32 atomSize = 0;
3873 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
3874 if (atomType == MOVIE_FRAGMENT_ATOM)
3875 {
3876 atomSize -= DEFAULT_ATOM_SIZE;
3877 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
3878 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3879 }
3880 break;
3881 }
3882 }
3883 //
3884 }
3885 else
3886 {
3887 // Not a valid tfra entries, cannot reposition.
3888 return 0;
3889 }
3890 }
3891 if (_parsing_mode == 1 && !oMoofFound)
3892 {
3893
3894 if (!oMoofFound)
3895 {
3896 _ptrMoofEnds = moof_offset;
3897 uint32 fileSize = 0;
3898 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize);
3899 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds);
3900 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3901 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE;
3902
3903 while (count > 0)
3904 {
3905 uint32 atomType = UNKNOWN_ATOM;
3906 uint32 atomSize = 0;
3907 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
3908 if (atomType == MOVIE_FRAGMENT_ATOM)
3909 {
3910 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3911 moofStartOffset -= DEFAULT_ATOM_SIZE;
3912 parseMoofCompletely = true;
3913
3914 if (moofParsingCompleted)
3915 {
3916 // do nothing
3917 }
3918 else
3919 {
3920 uint32 i = _pMovieFragmentAtomVec->size();
3921 _pMoofOffsetVec->pop_back();
3922 _pMovieFragmentAtomVec->pop_back();
3923 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]);
3924 parseMoofCompletely = true;
3925 moofParsingCompleted = true;
3926 moofSize = 0;
3927 moofType = UNKNOWN_ATOM;
3928 moofCount = 0;
3929 moofPtrPos = 0;
3930 }
3931
3932 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom);
3933
3934 if (!_pMovieFragmentAtom->MP4Success())
3935 {
3936 _success = false;
3937 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error();
3938 break;
3939 }
3940
3941 _pMovieFragmentAtom->setParent(this);
3942 count -= _pMovieFragmentAtom->getSize();
3943 uint32 i = _pMovieFragmentAtomVec->size();
3944
3945 MovieFragmentAtom *pMovieFragmentAtom = NULL;
3946 uint32 prevMoofSeqNum = 0;
3947
3948 if (i > 0)
3949 {
3950 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[i-1];
3951
3952 if (pMovieFragmentAtom != NULL)
3953 prevMoofSeqNum = (*_pMovieFragmentAtomVec)[i-1]->getSequenceNumber();
3954 }
3955 currMoofNum = _pMovieFragmentAtom->getSequenceNumber();
3956
3957 for (uint32 idx = prevMoofSeqNum; idx < currMoofNum - 1; idx++)
3958 {
3959 _pMovieFragmentAtomVec->push_back(NULL);
3960 _pMoofOffsetVec->push_back(0);
3961 }
3962
3963 if (currMoofNum > i)
3964 {
3965 _pMoofOffsetVec->push_back(moofStartOffset);
3966 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom);
3967 }
3968 else if ((*_pMovieFragmentAtomVec)[currMoofNum-1] == NULL)
3969 {
3970 (*_pMovieFragmentAtomVec)[currMoofNum-1] = _pMovieFragmentAtom;
3971 (*_pMoofOffsetVec)[currMoofNum-1] = moofStartOffset;
3972 }
3973 else
3974 {
3975 PV_MP4_FF_DELETE(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, _pMovieFragmentAtom);
3976 _pMovieFragmentAtom = NULL;
3977 break;
3978
3979 }
3980 if (oMfraFound)
3981 {
3982 currMoofNum = _pMovieFragmentAtom->getSequenceNumber();
3983 _movieFragmentIdx[trackID] = currMoofNum - 1 ;
3984 _peekMovieFragmentIdx[trackID] = currMoofNum - 1;
3985 _movieFragmentSeqIdx[trackID] = currMoofNum;
3986 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID];
3987 oMoofFound = true;
3988 if (!_oVideoTrackPresent)
3989 {
3990 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
3991 }
3992 break;
3993 }
3994 uint32 currTrafDuration = _pMovieFragmentAtom->getCurrentTrafDuration(trackID);
3995 if (currTrafDuration >= modifiedTimeStamp)
3996 {
3997 currMoofNum = _pMovieFragmentAtom->getSequenceNumber();
3998 _movieFragmentIdx[trackID] = currMoofNum - 1;
3999 _peekMovieFragmentIdx[trackID] = currMoofNum - 1;
4000 _movieFragmentSeqIdx[trackID] = currMoofNum;
4001 _peekMovieFragmentSeqIdx[trackID] = _movieFragmentSeqIdx[trackID];
4002 oMoofFound = true;
4003 if (!_oVideoTrackPresent)
4004 {
4005 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
4006 }
4007 break;
4008 }
4009
4010 }
4011 else if (atomType == MEDIA_DATA_ATOM)
4012 {
4013 if (atomSize == 1)
4014 {
4015 uint64 largeSize = 0;
4016 AtomUtils::read64(_movieFragmentFilePtr, largeSize);
4017 uint32 size =
4018 Oscl_Int64_Utils::get_uint64_lower32(largeSize);
4019 count -= size;
4020 size -= 8; //for large size
4021 size -= DEFAULT_ATOM_SIZE;
4022 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size);
4023 }
4024 else
4025 {
4026 if (atomSize < DEFAULT_ATOM_SIZE)
4027 {
4028 _success = false;
4029 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
4030 break;
4031 }
4032 if (count < (int32)atomSize)
4033 {
4034 _success = false;
4035 _mp4ErrorCode = READ_FAILED;
4036 break;
4037 }
4038 count -= atomSize;
4039 atomSize -= DEFAULT_ATOM_SIZE;
4040 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
4041 }
4042 }
4043
4044 else
4045 {
4046 if (count > 0)
4047 {
4048 count -= atomSize;
4049 atomSize -= DEFAULT_ATOM_SIZE;
4050 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
4051 }
4052
4053 }
4054 }
4055 }
4056
4057 }
4058
4059 if (_pmovieAtom != NULL)
4060 _pmovieAtom->resetTrackToEOT();
4061
4062 if (_pMovieFragmentAtom != NULL)
4063 returnedTS = _pMovieFragmentAtom->resetPlayback(trackID, convertedTS, traf_number, trun_number, sample_num);
4064 }
4065 else
4066 return 0;
4067
4068 // convert returnedTS (which is in media time scale) to the ms
4069 MediaClockConverter mcc(getTrackMediaTimescale(trackID));
4070 mcc.update_clock(returnedTS);
4071 timestamp = mcc.get_converted_ts(1000);
4072
4073
4074 if (timestamp <= modifiedTimeStamp)
4075 {
4076 modifiedTimeStamp = timestamp;
4077 }
4078 retVal = modifiedTimeStamp;
4079
4080 }
4081 else
4082 {
4083 if (_isMovieFragmentsPresent)
4084 {
4085 if (_pMovieFragmentAtomVec->size() > 0)
4086 {
4087 if (moofParsingCompleted)
4088 {
4089 // do nothing
4090 }
4091 else
4092 {
4093 uint32 i = _pMovieFragmentAtomVec->size();
4094 _pMoofOffsetVec->pop_back();
4095 _pMovieFragmentAtomVec->pop_back();
4096 PV_MP4_FF_DELETE(NULL, MovieFragmentAtom , (*_pMovieFragmentAtomVec)[i-1]);
4097 parseMoofCompletely = true;
4098 moofParsingCompleted = true;
4099 moofSize = 0;
4100 moofType = UNKNOWN_ATOM;
4101 moofCount = 0;
4102 moofPtrPos = 0;
4103 }
4104 }
4105 }
4106
4107 //movie
4108 if (_pmovieAtom != NULL)
4109 {
4110 resetAllMovieFragments();
4111 uint32 trackAudio = trackID;
4112 uint32 numTrackforAudio = 1;
4113 retVal = _pmovieAtom->resetPlayback(modifiedTimeStamp, numTrackforAudio, &trackAudio
4114 , bResetToIFrame);
4115 }
4116 }
4117
4118 }
4119 return retVal;
4120
4121 }
4122
4123
4124
queryRepositionTime(uint32 time,uint16 numTracks,uint32 * trackList,bool bResetToIFrame,bool bBeforeRequestedTime)4125 int32 Mpeg4File::queryRepositionTime(uint32 time,
4126 uint16 numTracks,
4127 uint32 *trackList,
4128 bool bResetToIFrame,
4129 bool bBeforeRequestedTime)
4130 {
4131
4132 uint32 i = 0;
4133 uint32 ret = 0;
4134 uint32 modifiedTimeStamp = time;
4135 uint32 trackID = 0;
4136 uint32 trackIds[256];
4137
4138 bool oVideoTrackFound = false;
4139 int j = 1;
4140 for (i = 0; i < numTracks; i++)
4141 {
4142 trackID = trackList[i];
4143 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL)
4144 {
4145 trackIds[0] = trackList[i];
4146 oVideoTrackFound = true;
4147 }
4148 else
4149 {
4150 trackIds[j++] = trackList[i];
4151 }
4152 }
4153
4154 uint32 convertedTS = 0;
4155 uint32 timestamp = 0, returnedTS = 0;
4156
4157 for (i = 0; i < numTracks; i++)
4158 {
4159 trackID = trackIds[i];
4160
4161 if (!oVideoTrackFound)
4162 trackID = trackList[i];
4163
4164 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL)
4165 {
4166 if (repositionFromMoof(time, trackID))
4167 {
4168 //moof
4169 modifiedTimeStamp = time;
4170
4171 // convert modifiedTimeStamp (which is in ms) to the appropriate
4172 // media time scale
4173 MediaClockConverter mcc1(1000);
4174 mcc1.update_clock(modifiedTimeStamp);
4175 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID));
4176 if (oMfraFound)
4177 {
4178 oMfraFound = true;
4179 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++)
4180 {
4181
4182 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx];
4183 returnedTS = pMovieFragmentRandomAccessAtom->queryRepositionTime(trackID, convertedTS, bResetToIFrame,
4184 bBeforeRequestedTime);
4185 if (returnedTS != 0)
4186 {
4187 break;
4188 }
4189 }
4190 }
4191 else
4192 {
4193 oMfraFound = false;
4194 if (_parsing_mode == 1)
4195 return -1;
4196 }
4197
4198 // convert returnedTS (which is in media time scale) to the ms
4199 MediaClockConverter mcc(getTrackMediaTimescale(trackID));
4200 mcc.update_clock(returnedTS);
4201 timestamp = mcc.get_converted_ts(1000);
4202
4203 modifiedTimeStamp = timestamp;
4204
4205 ret = modifiedTimeStamp;
4206
4207 }
4208 else
4209 {
4210 //movie
4211 if (_pmovieAtom != NULL)
4212 {
4213 modifiedTimeStamp = _pmovieAtom->queryRepositionTime(time,
4214 numTracks,
4215 trackList,
4216 bResetToIFrame,
4217 bBeforeRequestedTime);
4218 ret = modifiedTimeStamp;
4219 }
4220 }
4221 }
4222
4223 if ((getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO) ||
4224 (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT))
4225 {
4226 if (repositionFromMoof(time, trackID))
4227 {
4228 //moof
4229 MediaClockConverter mcc1(1000);
4230 mcc1.update_clock(modifiedTimeStamp);
4231 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID));
4232
4233 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++)
4234 {
4235
4236 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx];
4237 returnedTS = pMovieFragmentRandomAccessAtom->queryRepositionTime(trackID, convertedTS, bResetToIFrame,
4238 bBeforeRequestedTime);
4239 if (returnedTS != 0)
4240 {
4241 break;
4242 }
4243 }
4244 // convert returnedTS (which is in media time scale) to the ms
4245 MediaClockConverter mcc(getTrackMediaTimescale(trackID));
4246 mcc.update_clock(returnedTS);
4247 timestamp = mcc.get_converted_ts(1000);
4248
4249 if (!oVideoTrackFound)
4250 {
4251 if (getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO)
4252 {
4253 modifiedTimeStamp = timestamp;
4254 }
4255 else if (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT && numTracks == 1)
4256 {
4257 modifiedTimeStamp = timestamp;
4258 }
4259 }
4260
4261 return modifiedTimeStamp;
4262
4263 }
4264 else
4265 {
4266 //movie
4267 if (_pmovieAtom != NULL)
4268 {
4269 modifiedTimeStamp = _pmovieAtom->queryRepositionTime(modifiedTimeStamp,
4270 numTracks,
4271 trackList,
4272 bResetToIFrame,
4273 bBeforeRequestedTime);
4274
4275 if (!oVideoTrackFound)
4276 {
4277 if (getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO)
4278 {
4279 ret = modifiedTimeStamp;
4280 }
4281 else if (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT && numTracks == 1)
4282 {
4283 ret = modifiedTimeStamp;
4284 }
4285 }
4286 }
4287
4288 }
4289
4290 }
4291 }
4292 return ret;
4293 }
4294
4295
4296
parseMFRA()4297 int32 Mpeg4File::parseMFRA()
4298 {
4299 uint32 ret = 0;
4300 uint32 fileSize = 0;
4301 uint32 MfraStartOffset = 0;
4302 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize);
4303 AtomUtils::seekFromStart(_movieFragmentFilePtr, fileSize);
4304 AtomUtils::rewindFilePointerByN(_movieFragmentFilePtr, 16);
4305
4306 uint32 atomType = UNKNOWN_ATOM;
4307 uint32 atomSize = 0;
4308 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
4309
4310 if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_ATOM)
4311 {
4312 if (_pMfraOffsetAtom == NULL)
4313 {
4314 PV_MP4_FF_NEW(fp->auditCB, MfraOffsetAtom, (_movieFragmentFilePtr, atomSize, atomType), _pMfraOffsetAtom);
4315 if (!_pMfraOffsetAtom->MP4Success())
4316 {
4317 _success = false;
4318 _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_FAILED;
4319 return _mp4ErrorCode;
4320 }
4321 MfraStartOffset = _pMfraOffsetAtom->getSizeStoredInmfro();
4322
4323 }
4324 }
4325 AtomUtils::rewindFilePointerByN(_movieFragmentFilePtr, MfraStartOffset);
4326 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
4327 if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_ATOM)
4328 {
4329 if (_pMovieFragmentRandomAccessAtomVec->size() == 0)
4330 {
4331 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = NULL;
4332 PV_MP4_FF_NEW(fp->auditCB, MovieFragmentRandomAccessAtom, (_movieFragmentFilePtr, atomSize, atomType), pMovieFragmentRandomAccessAtom);
4333
4334 if (!pMovieFragmentRandomAccessAtom->MP4Success())
4335 {
4336 PV_MP4_FF_DELETE(NULL, MovieFragmentRandomAccessAtom, pMovieFragmentRandomAccessAtom);
4337 _success = false;
4338 _mp4ErrorCode = pMovieFragmentRandomAccessAtom->GetMP4Error();
4339 return _mp4ErrorCode ;
4340 }
4341 pMovieFragmentRandomAccessAtom->setParent(this);
4342 _pMovieFragmentRandomAccessAtomVec->push_back(pMovieFragmentRandomAccessAtom);
4343 oMfraFound = true;
4344 }
4345 }
4346
4347 return ret;
4348
4349 }
4350
4351
peekNextBundledAccessUnits(const uint32 trackID,uint32 * n,MediaMetaInfo * mInfo)4352 int32 Mpeg4File::peekNextBundledAccessUnits(const uint32 trackID,
4353 uint32 *n,
4354 MediaMetaInfo *mInfo)
4355 {
4356 // IF THERE ARE NO MEDIA TRACKS, RETURN READ ERROR
4357 uint32 samplesTobeRead;
4358 samplesTobeRead = *n;
4359 uint32 totalSampleRead = 0;
4360 if (getNumTracks() == 0)
4361 {
4362 return -1;
4363 }
4364 if (_pmovieAtom != NULL)
4365 {
4366 uint32 ret = (_pmovieAtom->peekNextBundledAccessUnits(trackID, n, mInfo));
4367 if (ret == END_OF_TRACK)
4368 {
4369 if (!_isMovieFragmentsPresent)
4370 return ret;
4371
4372 bool oAllMoofExhausted = false;
4373
4374 totalSampleRead += *n;
4375
4376 if (totalSampleRead == samplesTobeRead)
4377 {
4378 *n = totalSampleRead;
4379 return EVERYTHING_FINE;
4380 }
4381
4382 if (_pMovieFragmentAtomVec != NULL)
4383 {
4384 if (samplesTobeRead >= *n)
4385 *n = samplesTobeRead - *n;
4386 if (*n == 0)
4387 *n = samplesTobeRead;
4388 }
4389 else
4390 return ret;
4391
4392 if (_parsing_mode == 0)
4393 {
4394 int32 return1 = 0;
4395 while (_peekMovieFragmentIdx[trackID] < _pMovieFragmentAtomVec->size())
4396 {
4397 uint32 peekMovieFragmentIdx = _peekMovieFragmentIdx[trackID];
4398 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[peekMovieFragmentIdx];
4399 if (pMovieFragmentAtom != NULL)
4400 {
4401 if ((uint32)pMovieFragmentAtom->getSequenceNumber() == _peekMovieFragmentSeqIdx[trackID])
4402 {
4403 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID);
4404 if (trackfragment != NULL)
4405 {
4406 if (trackfragment->getTrackId() == trackID)
4407 {
4408 return1 = pMovieFragmentAtom->peekNextBundledAccessUnits(trackID, n, totalSampleRead, mInfo);
4409 totalSampleRead += *n;
4410 if (return1 != END_OF_TRACK)
4411 {
4412 *n = totalSampleRead;
4413 return return1;
4414 }
4415 else
4416 {
4417 _peekMovieFragmentSeqIdx[trackID]++;
4418 if (samplesTobeRead >= *n)
4419 {
4420 samplesTobeRead = samplesTobeRead - *n;
4421 *n = samplesTobeRead;
4422 }
4423 }
4424 }
4425 }
4426 }
4427 }
4428 _peekMovieFragmentIdx[trackID]++;
4429 }
4430 if (return1 == END_OF_TRACK)
4431 {
4432 *n = totalSampleRead;
4433 _peekMovieFragmentIdx[trackID] = 0;
4434 _peekMovieFragmentSeqIdx[trackID] = 1;
4435 return return1;
4436 }
4437 }
4438 else
4439 {
4440
4441 while (!oAllMoofExhausted)
4442 {
4443 uint32 moofIndex = 0;
4444 bool moofToBeParsed = false;
4445
4446 if (_pMovieFragmentAtomVec->size() > _peekMovieFragmentIdx[trackID])
4447 {
4448 MovieFragmentAtom *pMovieFragmentAtom = NULL;
4449 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[_peekMovieFragmentIdx[trackID]];
4450 if (pMovieFragmentAtom == NULL)
4451 {
4452 moofToBeParsed = true;
4453 moofIndex = _peekMovieFragmentIdx[trackID];
4454 }
4455 }
4456 if ((_pMovieFragmentAtomVec->size() <= _peekMovieFragmentIdx[trackID]) || moofToBeParsed)
4457 {
4458 uint32 fileSize = 0;
4459 AtomUtils::getCurrentFileSize(_movieFragmentFilePtr, fileSize);
4460 AtomUtils::seekFromStart(_movieFragmentFilePtr, _ptrMoofEnds);
4461 uint32 filePointer = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
4462 int32 count = fileSize - filePointer;// -DEFAULT_ATOM_SIZE;
4463
4464 while (count > 0)
4465 {
4466 uint32 atomType = UNKNOWN_ATOM;
4467 uint32 atomSize = 0;
4468 uint32 currPos = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
4469 AtomUtils::getNextAtomType(_movieFragmentFilePtr, atomSize, atomType);
4470 if ((currPos + atomSize) > fileSize)
4471 {
4472 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos);
4473 return INSUFFICIENT_DATA;
4474 }
4475 if (atomType == MOVIE_FRAGMENT_ATOM)
4476 {
4477 uint32 moofStartOffset = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
4478 moofStartOffset -= DEFAULT_ATOM_SIZE;
4479
4480 parseMoofCompletely = true;
4481
4482 PV_MP4_FF_NEW(_movieFragmentFilePtr->auditCB, MovieFragmentAtom, (_movieFragmentFilePtr, atomSize, atomType, _pTrackDurationContainer, _pTrackExtendsAtomVec, parseMoofCompletely, moofParsingCompleted, countOfTrunsParsed), _pMovieFragmentAtom);
4483
4484 if (!_pMovieFragmentAtom->MP4Success())
4485 {
4486 _success = false;
4487 _mp4ErrorCode = _pMovieFragmentAtom->GetMP4Error();
4488 oAllMoofExhausted = true;
4489 break;
4490 }
4491 _pMovieFragmentAtom->setParent(this);
4492 count -= _pMovieFragmentAtom->getSize();
4493 if (moofToBeParsed)
4494 {
4495 (*_pMovieFragmentAtomVec)[moofIndex] = _pMovieFragmentAtom;
4496 (*_pMoofOffsetVec)[moofIndex] = moofStartOffset;
4497 }
4498 else
4499 {
4500 _pMoofOffsetVec->push_back(moofStartOffset);
4501 _pMovieFragmentAtomVec->push_back(_pMovieFragmentAtom);
4502 }
4503 _ptrMoofEnds = AtomUtils::getCurrentFilePosition(_movieFragmentFilePtr);
4504
4505 break;
4506 }
4507 else if (atomType == MEDIA_DATA_ATOM)
4508 {
4509 if (atomSize == 1)
4510 {
4511 uint64 largeSize = 0;
4512 AtomUtils::read64(_movieFragmentFilePtr, largeSize);
4513 uint32 size =
4514 Oscl_Int64_Utils::get_uint64_lower32(largeSize);
4515 count -= size;
4516 size -= 8; //for large size
4517 size -= DEFAULT_ATOM_SIZE;
4518 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, size);
4519 }
4520 else
4521 {
4522 if (atomSize < DEFAULT_ATOM_SIZE)
4523 {
4524 _success = false;
4525 oAllMoofExhausted = true;
4526 _mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
4527 break;
4528 }
4529 if (count < (int32)atomSize)
4530 {
4531 _success = false;
4532 oAllMoofExhausted = true;
4533 _mp4ErrorCode = INSUFFICIENT_DATA;
4534 AtomUtils::seekFromStart(_movieFragmentFilePtr, currPos);
4535 ret = _mp4ErrorCode;
4536 break;
4537 }
4538 count -= atomSize;
4539 atomSize -= DEFAULT_ATOM_SIZE;
4540 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
4541 }
4542 }
4543
4544 else
4545 {
4546 if (count > 0)
4547 {
4548 count -= atomSize;
4549 atomSize -= DEFAULT_ATOM_SIZE;
4550 AtomUtils::seekFromCurrPos(_movieFragmentFilePtr, atomSize);
4551 }
4552 break;
4553 }
4554 }
4555 if (count <= 0)
4556 {
4557 oAllMoofExhausted = true;
4558 if (_pMovieFragmentAtomVec->size() < _peekMovieFragmentIdx[trackID])
4559 break;
4560 }
4561 }
4562
4563 int32 return1 = 0;
4564 MovieFragmentAtom *pMovieFragmentAtom = NULL;
4565 uint32 movieFragmentIdx = _peekMovieFragmentIdx[trackID];
4566
4567 if (movieFragmentIdx < _pMovieFragmentAtomVec->size())
4568 pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[movieFragmentIdx];
4569
4570 if (pMovieFragmentAtom != NULL)
4571 {
4572 uint32 seqNum = pMovieFragmentAtom->getSequenceNumber();
4573 if (seqNum == _peekMovieFragmentSeqIdx[trackID])
4574 {
4575 TrackFragmentAtom *trackfragment = pMovieFragmentAtom->getTrackFragmentforID(trackID);
4576 if (trackfragment != NULL)
4577 {
4578 if (trackfragment->getTrackId() == trackID)
4579 {
4580 return1 = pMovieFragmentAtom->peekNextBundledAccessUnits(trackID, n, totalSampleRead, mInfo);
4581 totalSampleRead += *n;
4582 if (return1 != END_OF_TRACK)
4583 {
4584 *n = totalSampleRead;
4585 return return1;
4586 }
4587 else
4588 {
4589 _peekMovieFragmentSeqIdx[trackID]++;
4590 if (samplesTobeRead >= *n)
4591 {
4592 samplesTobeRead = samplesTobeRead - *n;
4593 *n = samplesTobeRead;
4594 }
4595 }
4596 }
4597 }
4598 else
4599 {
4600 _peekMovieFragmentIdx[trackID]++;
4601 _peekMovieFragmentSeqIdx[trackID]++;
4602 *n = 0;
4603 return NO_SAMPLE_IN_CURRENT_MOOF;
4604 }
4605 }
4606 }
4607 _peekMovieFragmentIdx[trackID]++;
4608
4609 }
4610 }
4611 }
4612 return ret;
4613 }
4614 else
4615 {
4616 return -1;
4617 }
4618 }
4619
4620
getSampleCountInTrack(uint32 id)4621 uint32 Mpeg4File::getSampleCountInTrack(uint32 id)
4622 {
4623 uint32 nTotalSamples = 0;
4624 if (_pmovieAtom != NULL)
4625 {
4626 nTotalSamples = (_pmovieAtom->getSampleCountInTrack(id));
4627 if (!_isMovieFragmentsPresent)
4628 return nTotalSamples;
4629
4630 if (_parsing_mode == 0)
4631 {
4632 if (_pMovieFragmentAtomVec->size() > 0)
4633 {
4634 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++)
4635 {
4636 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
4637 if (pMovieFragmentAtom != NULL)
4638 {
4639 nTotalSamples += pMovieFragmentAtom->getTotalSampleInTraf(id);
4640 }
4641 }
4642 return nTotalSamples;
4643 }
4644 }
4645 return nTotalSamples;
4646 }
4647 return 0;
4648 }
4649
4650
IsTFRAPresentForTrack(uint32 TrackId,bool oVideoAudioTextTrack)4651 bool Mpeg4File::IsTFRAPresentForTrack(uint32 TrackId, bool oVideoAudioTextTrack)
4652 {
4653 if (_pMovieFragmentRandomAccessAtomVec != NULL)
4654 {
4655 for (uint32 idx = 0; idx < _pMovieFragmentRandomAccessAtomVec->size(); idx++)
4656 {
4657
4658 MovieFragmentRandomAccessAtom *pMovieFragmentRandomAccessAtom = (*_pMovieFragmentRandomAccessAtomVec)[idx];
4659 return pMovieFragmentRandomAccessAtom->IsTFRAPresentForTrack(TrackId, oVideoAudioTextTrack);
4660 }
4661 }
4662 return false;
4663 }
4664
4665
4666 /*
4667 This function has been modified to check the entry count in TFRA for all tracks are equal.
4668 The code change is under macro DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT
4669 */
IsTFRAPresentForAllTrack(uint32 numTracks,uint32 * trackList)4670 bool Mpeg4File::IsTFRAPresentForAllTrack(uint32 numTracks, uint32 *trackList)
4671 {
4672
4673 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT)
4674 bool oVideoAudioTextTrack = false;
4675 // This flag will be true for Video in AVT,VT & AV and for Audio in AT.
4676 // Based on this flag IsTFRAPresentForTrack() functions behaviour is changing
4677 // We are comparing the entry count for all the tracks to entry count of V in case of Vonly,AVT,VT & AV clips
4678 // and in case of Aonly & AT clips, entry count for all the tracks is compared with entry count of audio. For Tonly
4679 // clips, entry count for text track is compared with its own entry count.
4680
4681 // Support for clips having Video track.
4682 for (int32 i = 0; i < numTracks; i++)
4683 {
4684 uint32 trackID = trackList[i];
4685 if (getTrackMediaType(trackID) == MEDIA_TYPE_VISUAL)
4686 {
4687 oVideoAudioTextTrack = true;
4688 if (IsTFRAPresentForTrack(trackID, oVideoAudioTextTrack) == false)
4689 {
4690 return false;
4691 }
4692 break;
4693 }
4694 }
4695 // Support for clips having Audio track and no Video track.
4696 if (!oVideoAudioTextTrack)
4697 {
4698 for (int32 i = 0; i < numTracks; i++)
4699 {
4700 uint32 trackID = trackList[i];
4701 if (getTrackMediaType(trackID) == MEDIA_TYPE_AUDIO)
4702 {
4703 oVideoAudioTextTrack = true;
4704 if (IsTFRAPresentForTrack(trackID, oVideoAudioTextTrack) == false)
4705 {
4706 return false;
4707 }
4708 break;
4709 }
4710 }
4711 }
4712 // Support for clips having only Text track.
4713 if (!oVideoAudioTextTrack && numTracks == 1)
4714 {
4715 for (uint32 i = 0; i < numTracks; i++)
4716 {
4717 uint32 trackID = trackList[i];
4718 if (getTrackMediaType(trackID) == MEDIA_TYPE_TEXT)
4719 {
4720 oVideoAudioTextTrack = true;
4721 if (IsTFRAPresentForTrack(trackID, oVideoAudioTextTrack) == false)
4722 {
4723 return false;
4724 }
4725 break;
4726 }
4727 }
4728 }
4729 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT
4730 for (uint32 idx = 0; idx < numTracks; idx++)
4731 {
4732 uint32 trackID = trackList[idx];
4733 // second argument is false always
4734 if (IsTFRAPresentForTrack(trackID, false) == false)
4735 {
4736 return false;
4737 }
4738 }
4739 return true;
4740 }
4741
resetPlayback()4742 void Mpeg4File::resetPlayback()
4743 {
4744 if (_pmovieAtom == NULL)
4745 return;
4746
4747 _pmovieAtom->resetPlayback();
4748
4749 if (_isMovieFragmentsPresent)
4750 {
4751 if (_pMovieFragmentAtomVec != NULL)
4752 {
4753 int numTracks = _pmovieAtom->getNumTracks();
4754 uint32 *trackList = (uint32 *) oscl_malloc(sizeof(uint32) * numTracks);
4755 if (!trackList)
4756 return; // malloc failed
4757
4758 _pmovieAtom->getTrackWholeIDList(trackList);
4759 for (int i = 0; i < numTracks; i++)
4760 {
4761 uint32 trackID = trackList[i];
4762 _peekMovieFragmentIdx[trackID] = 0;
4763 _movieFragmentIdx[trackID] = 0;
4764 _movieFragmentSeqIdx[trackID] = 1;
4765 _peekMovieFragmentSeqIdx[trackID] = 1;
4766 }
4767 oscl_free(trackList);
4768 for (uint32 idx = 0; idx < _pMovieFragmentAtomVec->size(); idx++)
4769 {
4770 MovieFragmentAtom *pMovieFragmentAtom = (*_pMovieFragmentAtomVec)[idx];
4771 if (pMovieFragmentAtom != NULL)
4772 pMovieFragmentAtom->resetPlayback();
4773
4774 }
4775 }
4776 }
4777 }
4778
repositionFromMoof(uint32 time,uint32 trackID)4779 uint32 Mpeg4File::repositionFromMoof(uint32 time, uint32 trackID)
4780 {
4781 uint32 modifiedTimeStamp = time;
4782 uint32 convertedTS = 0;
4783 uint32 trackDuration = Oscl_Int64_Utils::get_uint64_lower32(getTrackMediaDurationForMovie(trackID));//getMovieDuration() - getMovieFragmentDuration();
4784
4785 MediaClockConverter mcc1(1000);
4786 mcc1.update_clock(modifiedTimeStamp);
4787 convertedTS = mcc1.get_converted_ts(getTrackMediaTimescale(trackID));
4788
4789 if (_isMovieFragmentsPresent)
4790 {
4791 if (IsTFRAPresentForTrack(trackID, false) == false)
4792 {
4793 return 0;
4794 }
4795 if (modifiedTimeStamp >= trackDuration)
4796 {
4797 return 1; //repos in moof
4798 }
4799 }
4800 return 0; //repos in moov
4801 }
4802
CancelNotificationSync()4803 MP4_ERROR_CODE Mpeg4File::CancelNotificationSync()
4804 {
4805 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "Mpeg4File::CancelNotificationSync"));
4806
4807 bool retVal = _commonFilePtr->_pvfile.CancelNotificationSync();
4808
4809 if (retVal)
4810 {
4811 return EVERYTHING_FINE;
4812 }
4813 else
4814 {
4815 return DEFAULT_ERROR;
4816 }
4817 }
4818
CreateDataStreamSessionForExternalDownload(OSCL_wString & aFilename,PVMFCPMPluginAccessInterfaceFactory * aCPMAccessFactory,OsclFileHandle * aHandle,Oscl_FileServer * aFileServSession)4819 bool Mpeg4File::CreateDataStreamSessionForExternalDownload(OSCL_wString& aFilename,
4820 PVMFCPMPluginAccessInterfaceFactory* aCPMAccessFactory,
4821 OsclFileHandle* aHandle,
4822 Oscl_FileServer* aFileServSession)
4823 {
4824 OsclAny*ptr = oscl_malloc(sizeof(MP4_FF_FILE));
4825 if (ptr == NULL)
4826 {
4827 _success = false;
4828 _mp4ErrorCode = MEMORY_ALLOCATION_FAILED;
4829 return false;
4830 }
4831 _commonFilePtr = OSCL_PLACEMENT_NEW(ptr, MP4_FF_FILE());
4832
4833 if (_commonFilePtr != NULL)
4834 {
4835 _commonFilePtr->_fileServSession = aFileServSession;
4836 _commonFilePtr->_pvfile.SetCPM(aCPMAccessFactory);
4837 _commonFilePtr->_pvfile.SetFileHandle(aHandle);
4838
4839 if (AtomUtils::OpenMP4File(aFilename,
4840 Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
4841 _commonFilePtr) != 0)
4842 {
4843 return false;
4844 }
4845
4846 uint32 fileSize;
4847 AtomUtils::getCurrentFileSize(_commonFilePtr, fileSize);
4848 _commonFilePtr->_fileSize = (int32)fileSize;
4849 }
4850 return true;
4851 }
4852
DestroyDataStreamForExternalDownload()4853 void Mpeg4File::DestroyDataStreamForExternalDownload()
4854 {
4855 if (_commonFilePtr != NULL)
4856 {
4857 if (_commonFilePtr->IsOpen())
4858 {
4859 AtomUtils::CloseMP4File(_commonFilePtr);
4860 }
4861 oscl_free(_commonFilePtr);
4862 _commonFilePtr = NULL;
4863 }
4864 }
4865
4866 //Below APIs are used to supress Warning
ReserveMemoryForLangCodeVector(Oscl_Vector<uint16,OsclMemAllocator> & iLangCode,int32 capacity,int32 & leavecode)4867 void Mpeg4File::ReserveMemoryForLangCodeVector(Oscl_Vector<uint16, OsclMemAllocator> &iLangCode, int32 capacity, int32 &leavecode)
4868 {
4869 leavecode = 0;
4870 OSCL_TRY(leavecode, iLangCode.reserve(capacity));
4871
4872 }
4873
ReserveMemoryForValuesVector(Oscl_Vector<OSCL_wHeapString<OsclMemAllocator>,OsclMemAllocator> & iValues,int32 capacity,int32 & leavecode)4874 void Mpeg4File::ReserveMemoryForValuesVector(Oscl_Vector<OSCL_wHeapString<OsclMemAllocator>, OsclMemAllocator> &iValues, int32 capacity, int32 &leavecode)
4875 {
4876 leavecode = 0;
4877 OSCL_TRY(leavecode, iValues.reserve(capacity));
4878
4879 }
4880
4881
4882