• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /*
19     The PVA_FF_Mpeg4File Class fp the class that will construct and maintain all the
20     mecessary data structures to be able to render a valid MP4 file to disk.
21     Format.
22 */
23 
24 
25 #define IMPLEMENT_Mpeg4File
26 
27 #ifndef OSCL_STRING_UTILS_H_INCLUDED
28 #include "oscl_string_utils.h"
29 #endif
30 
31 #include "mpeg4file.h"
32 #include "a_atomdefs.h"
33 #include "atomutils.h"
34 
35 #include "pv_gau.h"
36 #include "oscl_byte_order.h"
37 #include "oscl_bin_stream.h"
38 
39 #include "pv_mp4ffcomposer_config.h"
40 
41 const uint8 aAMRNBZeroSetMask[9] =
42 {
43     0xfe, 0xfe, 0xfc, 0xfc,
44     0xf0, 0xfe, 0xf0, 0xf0,
45     0xfe
46 };
47 //IETF AMR WB Speech Frame Sizes (including zero byte padding but not including TOC)
48 //FT 0 (6.6 Kbps) - 17 bytes = 136 bits
49 //FT 1 (8.85 Kbps) - 23 bytes = 184 bits
50 //FT 2 (12.65 Kbps) - 32 bytes = 256 bits
51 //FT 3 (14.25 Kbps) - 36 bytes = 288 bits
52 //FT 4 (15.85 Kbps) - 40 bytes = 320 bits
53 //FT 5 (18.25 Kbps) - 46 bytes = 368 bits
54 //FT 6 (19.85 Kbps) - 50 bytes = 400 bits
55 //FT 7 (23.05 Kbps) - 58 bytes = 464 bits
56 //FT 8 (23.85 Kbps) - 60 bytes = 480 bits
57 //FT 9 (SID) - 5 bytes = 40 bits
58 //FT 10-13 - Reserved
59 //FT 14 (Lost frame) and FT 15 (NO DATA) - 0 bytes = 0 bits
60 
61 //IETF AMR WB IF1 Speech Frame Sizes (just Class A, B & C speech bits, does not include FT or any other headers)
62 //FT 0 (6.6 Kbps) -  132 bits; num-bits-padded = 4
63 //FT 1 (8.85 Kbps) - 177 bits; num-bits-padded = 7
64 //FT 2 (12.65 Kbps) - 253 bits; num-bits-padded = 3
65 //FT 3 (14.25 Kbps) - 285 bits; num-bits-padded = 3
66 //FT 4 (15.85 Kbps) - 317 bits; num-bits-padded = 3
67 //FT 5 (18.25 Kbps) - 365 bits; num-bits-padded = 3
68 //FT 6 (19.85 Kbps) - 397 bits; num-bits-padded = 3
69 //FT 7 (23.05 Kbps) - 461 bits; num-bits-padded = 3
70 //FT 8 (23.85 Kbps) - 477 bits; num-bits-padded = 3
71 //FT 9 (SID) - 5 bytes = 40 bits; num-bits-padded = 0
72 //FT 10-13 - Reserved
73 //FT 14 (Lost frame) and FT 15 (NO DATA) - 0 bytes = 0 bits; num-bits-padded = 0
74 
75 // Difference between IF1 bits and IETF storage bits is padded with zeros to byte align the frame
76 const uint8 aAMRWBZeroSetMask[9] =
77 {
78     0xf0, 0x80, 0xf8, 0xf8,
79     0xf8, 0xf8, 0xf8, 0xf8,
80     0xf8
81 };
82 
83 typedef Oscl_Vector<PVA_FF_MediaDataAtom*, OsclMemAllocator> PVA_FF_MediaDataAtomVecType;
84 typedef Oscl_Vector<PVA_FF_MovieFragmentAtom*, OsclMemAllocator> PVA_FF_MovieFragmentAtomVecType;
85 typedef Oscl_Vector<PVA_FF_InterLeaveBuffer*, OsclMemAllocator> PVA_FF_InterLeaveBufferVecType;
86 
87 //common to both AMR and AMR-WB
88 const uint32 AMRModeSetMask[16] =
89 {
90     0x0001, 0x0002, 0x0004, 0x0008,
91     0x0010, 0x0020, 0x0040, 0x0080,
92     0x0100, 0x0200, 0x0400, 0x0800,
93     0x1000, 0x2000, 0x4000, 0x8000
94 };
95 
96 // Constructor
PVA_FF_Mpeg4File(int32 mediaType)97 PVA_FF_Mpeg4File::PVA_FF_Mpeg4File(int32 mediaType)
98 {
99     OSCL_UNUSED_ARG(mediaType);
100     _success = true;
101 
102     _tempFilePostfix = _STRLIT("");
103 
104     _tempOutputPath = _STRLIT("");
105 
106     _oUserDataPopulated = true;
107     _pmovieAtom = NULL;
108     _pmediaDataAtomVec = NULL;
109     _puserDataAtom = NULL;
110     _pFileTypeAtom = NULL;
111     _pCurrentMoofAtom = NULL;
112     _pCurrentMediaDataAtom = NULL;
113     iCacheSize = 0;
114     _oIsFileOpen = false;
115     _pInterLeaveBufferVec = NULL;
116     _oInterLeaveEnabled = false;
117     _aFs = NULL;
118 }
119 
120 // Destructor
~PVA_FF_Mpeg4File()121 PVA_FF_Mpeg4File::~PVA_FF_Mpeg4File()
122 {
123 
124     {
125         if (_oUserDataPopulated == false)
126         {
127             populateUserDataAtom();
128         }
129     }
130 
131     // Clean up atoms
132     if (_pmovieAtom != NULL)
133     {
134         PV_MP4_FF_DELETE(NULL, PVA_FF_MovieAtom, _pmovieAtom);
135     }
136 
137     int32 i;
138 
139     // Delete all the atoms in the media data vec
140     if (_pmediaDataAtomVec != NULL)
141     {
142         int32 size = _pmediaDataAtomVec->size();
143         for (i = 0; i < size; i++)
144         {
145             PV_MP4_FF_DELETE(NULL, PVA_FF_MediaDataAtom, (*_pmediaDataAtomVec)[i]);
146         }
147 
148         // Delete the vectors themselves
149         PV_MP4_FF_TEMPLATED_DELETE(NULL, PVA_FF_MediaDataAtomVecType, Oscl_Vector, _pmediaDataAtomVec);
150     }
151 
152 
153     if ((_oInterLeaveEnabled) && (NULL != _pInterLeaveBufferVec))
154     {
155         // delete all interleave buffers
156         int32 size = _pInterLeaveBufferVec->size();
157         for (i = 0; i < size; i++)
158         {
159             PV_MP4_FF_DELETE(NULL, PVA_FF_MediaDataAtom, (*_pInterLeaveBufferVec)[i]);
160         }
161 
162         // Delete the vectors themselves
163         PV_MP4_FF_TEMPLATED_DELETE(NULL, PVA_FF_InterLeaveBufferVecType, Oscl_Vector, _pInterLeaveBufferVec);
164     }
165 
166     // in movie fragment mode delete MOOF and MFRA atoms
167     if (_oMovieFragmentEnabled == true)
168     {
169         PV_MP4_FF_DELETE(NULL, PVA_FF_MovieFragmentAtom, _pCurrentMoofAtom);
170         PV_MP4_FF_DELETE(NULL, PVA_FF_MediaDataAtom, _pCurrentMediaDataAtom);
171 
172         PV_MP4_FF_DELETE(NULL, PVA_FF_MovieFragmentRandomAccessAtom, _pMfraAtom);
173     }
174 
175     // Delete user data if present
176     if (_puserDataAtom != NULL)
177     {
178         PV_MP4_FF_DELETE(NULL, PVA_FF_UserDataAtom, _puserDataAtom);
179     }
180 
181     if (_pFileTypeAtom != NULL)
182     {
183         PV_MP4_FF_DELETE(NULL, PVA_FF_FileTypeAtom, _pFileTypeAtom);
184     }
185     if (_aFs)
186     {
187         PVA_FF_AtomUtils::closeFileSession(OSCL_STATIC_CAST(Oscl_FileServer*, _aFs));
188     }
189 }
190 
SetCacheSize(uint32 aCacheSize)191 void PVA_FF_Mpeg4File::SetCacheSize(uint32 aCacheSize)
192 {
193     iCacheSize = aCacheSize;
194 }
195 bool
init(int32 mediaType,void * osclFileServerSession,uint32 fileAuthoringFlags)196 PVA_FF_Mpeg4File::init(int32 mediaType,
197                        void *osclFileServerSession,
198                        uint32 fileAuthoringFlags)
199 {
200     OSCL_UNUSED_ARG(mediaType);
201     _modifiable = true; // Allow addition of media samples
202     _firstFrameInLayer0 = true;
203     _firstFrameInLayer1 = true;
204     _fileWriteFailed = false;
205 
206     _o3GPPTrack = true;
207     _oWMFTrack  = false;
208     _oPVMMTrack = false;
209     _oMPEGTrack = false;
210 
211     _oFileRenderCalled = false;
212     _oUserDataPopulated = false;
213     _oFtypPopulated = false;
214 
215     _baseOffset = 0;
216     _oInterLeaveEnabled = false;
217     _oMovieAtomUpfront = false;
218 
219     _oAuthorASSETINFOAtoms = false;
220     _oChunkStart = false;
221 
222     // Movie Fragments flags initialised
223     _oMovieFragmentEnabled      = false;
224     _oComposeMoofAtom           = false;
225     _movieFragmentDuration      = DEFAULT_MOVIE_FRAGMENT_DURATION_IN_MS;
226     _pCurrentMoofAtom           = NULL;
227     _pCurrentMediaDataAtom      = NULL;
228     _currentMoofOffset          = 0;
229     _sequenceNumber             = 0;
230 
231 
232     _aFs = osclFileServerSession;
233 
234     _nextAvailableODID = 1;
235     _tempFileIndex = 'a';
236 
237     _pmediaDataAtomVec  = NULL;
238     _pmovieAtom         = NULL;
239 
240     _puserDataAtom      = NULL;
241     _pFileTypeAtom      = NULL;
242 
243     _initialUserDataSize     = 0;
244     _oDirectRenderEnabled    = false;
245 
246     _oSetTitleDone          = false;
247     _oSetAuthorDone         = false;
248     _oSetCopyrightDone      = false;
249     _oSetDescriptionDone    = false;
250     _oSetRatingDone         = false;
251     _oSetCreationDateDone   = false;
252     _oSetPerformerDone      = false;
253     _oSetRatingDone         = false;
254     _oSetGenreDone          = false;
255     _oSetClassificationDone = false;
256     _oSetLocationInfoDone   = false;
257     _oSetAlbumDone          = false;
258     _oSetRecordingYearDone  = false;
259 
260 
261     _totalTempFileRemoval = false;
262     _oUserDataUpFront     = true;
263     _oIsFileOpen          = false;
264     _oFirstSampleEditMode = false;
265 
266     _fileAuthoringFlags = fileAuthoringFlags;
267 
268     if (fileAuthoringFlags & PVMP4FF_SET_MEDIA_INTERLEAVE_MODE)
269     {
270         _oInterLeaveEnabled = true;
271     }
272 
273     if (fileAuthoringFlags & PVMP4FF_SET_META_DATA_UPFRONT_MODE)
274     {
275         _oMovieAtomUpfront = true;
276     }
277 
278     if ((fileAuthoringFlags & PVMP4FF_3GPP_DOWNLOAD_MODE) ==
279             (PVMP4FF_3GPP_DOWNLOAD_MODE))
280     {
281         //Not possible to remove temp files, without output file name being set
282         if (_outputFileNameSet == false)
283         {
284             return false;
285         }
286         _oInterLeaveEnabled   = true;
287         _totalTempFileRemoval = true;
288         _oUserDataUpFront     = false;
289     }
290 
291     if (fileAuthoringFlags & PVMP4FF_SET_FIRST_SAMPLE_EDIT_MODE)
292     {
293         /* Supported only if interleaving is enabled */
294         if (!_oInterLeaveEnabled)
295         {
296             return false;
297         }
298         _oFirstSampleEditMode = true;
299     }
300 
301     // Movie fragment mode
302     if ((fileAuthoringFlags & PVMP4FF_MOVIE_FRAGMENT_MODE) == PVMP4FF_MOVIE_FRAGMENT_MODE)
303     {
304         if (!_oInterLeaveEnabled)
305         {
306             return false;
307         }
308         _oMovieFragmentEnabled = true;
309         _totalTempFileRemoval = true;
310         _oUserDataUpFront     = false;
311     }
312 
313     // Create user data atom
314     PV_MP4_FF_NEW(fp->auditCB, PVA_FF_UserDataAtom, (), _puserDataAtom);
315 
316     PV_MP4_FF_NEW(fp->auditCB, PVA_FF_FileTypeAtom, (), _pFileTypeAtom);
317 
318     // Create the moov atom
319     PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MovieAtom, (fileAuthoringFlags), _pmovieAtom);
320 
321     // Movie fragment atom vectors initialised
322     if (_oMovieFragmentEnabled)
323     {
324         PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MovieFragmentRandomAccessAtom, (), _pMfraAtom);
325     }
326 
327     // IODS uses the first ODID, hence the increment here.
328     _nextAvailableODID++;
329 
330     // Create miscellaneous vector of atoms
331     PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtomVecType, (), _pmediaDataAtomVec);
332 
333     _pparent = NULL;
334 
335     /*
336      * In interleave mode, create only ONE media atom, to store
337      * all the media samples.
338      */
339     if (_oInterLeaveEnabled)
340     {
341         PV_MP4_FF_NEW(fp->auditCB, PVA_FF_InterLeaveBufferVecType, (), _pInterLeaveBufferVec);
342         PVA_FF_MediaDataAtom *mda = NULL;
343         if (!_totalTempFileRemoval)
344         {
345             // Create PVA_FF_MediaDataAtom
346             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_tempOutputPath,
347                           _tempFilePostfix,
348                           _tempFileIndex,
349                           MEDIA_DATA_ON_DISK,
350                           _aFs, iCacheSize),
351                           mda);
352 
353             _tempFileIndex++;
354         }
355         else
356         {
357             if (_oFileOpenedOutsideAFFLib)
358             {
359                 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_outputFileHandle, _aFs, iCacheSize), mda);
360             }
361             else
362             {
363                 PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_outputFileName, _aFs, iCacheSize), mda);
364             }
365         }
366 
367         if (mda->_targetFileWriteError)
368         {
369             PV_MP4_FF_DELETE(NULL, PVA_FF_MediaDataAtom, mda);
370             mda = NULL;
371             return false;
372         }
373         addMediaDataAtom(mda);
374 
375         _interLeaveDuration = DEFAULT_INTERLEAVE_INTERVAL;
376     }
377     {
378         _pmovieAtom->createAssetInfoAtoms();
379     }
380     recomputeSize();
381 
382     return true;
383 }
384 
385 bool
setOutputFileName(PVA_FF_UNICODE_STRING_PARAM outputFileName)386 PVA_FF_Mpeg4File::setOutputFileName(PVA_FF_UNICODE_STRING_PARAM outputFileName)
387 {
388     _targetFileName           = (_STRLIT(""));
389     _oPartialTempFileRemoval  = false;
390     _outputFileName           = _STRLIT("");
391     _outputFileNameSet        = false;
392     _outputFileHandle         = NULL;
393     _targetFileHandle         = NULL;
394     _oFileOpenedOutsideAFFLib = false;
395 
396     if (outputFileName.get_size() > 0)
397     {
398         _outputFileName   += outputFileName;
399         _outputFileNameSet = true;
400 
401         if (!_oPartialTempFileRemoval)
402         {
403             _targetFileName += outputFileName;
404             _oPartialTempFileRemoval = true;
405         }
406         return true;
407     }
408     return false;
409 }
410 
411 bool
setOutputFileHandle(MP4_AUTHOR_FF_FILE_HANDLE outputFileHandle)412 PVA_FF_Mpeg4File::setOutputFileHandle(MP4_AUTHOR_FF_FILE_HANDLE outputFileHandle)
413 {
414     _targetFileName           = (_STRLIT(""));
415     _oPartialTempFileRemoval  = false;
416     _outputFileName           = _STRLIT("");
417     _outputFileNameSet        = false;
418     _outputFileHandle         = NULL;
419     _targetFileHandle         = NULL;
420     _oFileOpenedOutsideAFFLib = false;
421 
422     if (outputFileHandle != NULL)
423     {
424         _outputFileHandle  = outputFileHandle;
425         _outputFileNameSet = true;
426 
427         if (!_oPartialTempFileRemoval)
428         {
429             _targetFileHandle = outputFileHandle;
430             _oPartialTempFileRemoval = true;
431         }
432         _oFileOpenedOutsideAFFLib = true;
433         return true;
434     }
435     return false;
436 }
437 
438 uint32
addTrack(int32 mediaType,int32 codecType,bool oDirectRender,uint8 profile,uint8 profileComp,uint8 level)439 PVA_FF_Mpeg4File::addTrack(int32 mediaType,
440                            int32 codecType,
441                            bool oDirectRender,
442                            uint8 profile,
443                            uint8 profileComp,
444                            uint8 level)
445 {
446     uint32 TrackID = 0;
447     PVA_FF_TrackAtom *pmediatrack = NULL;
448     _codecType = codecType;
449     PVA_FF_MediaDataAtom *mda = NULL;
450     PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = NULL;
451 
452     if (!_oInterLeaveEnabled)
453     {
454         if (oDirectRender)
455         {
456             if (!_oDirectRenderEnabled)
457             {
458                 if ((_oPartialTempFileRemoval) &&
459                         (_totalTempFileRemoval == false))
460                 {
461                     _oDirectRenderEnabled = true;
462 
463                     if (_oFileOpenedOutsideAFFLib)
464                     {
465                         PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_targetFileHandle, _aFs, iCacheSize), mda);
466                     }
467                     else
468                     {
469                         PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_targetFileName, _aFs, iCacheSize), mda);
470                     }
471                 }
472                 else
473                 {
474                     //Target File name not set
475                     return (INVALID_TRACK_ID);
476                 }
477             }
478             else
479             {
480                 //Multiple Tracks cannot be directly rendered
481                 return (INVALID_TRACK_ID);
482             }
483         }
484         else
485         {
486             //create new track - media will be stored in temp file
487             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_tempOutputPath,
488                           _tempFilePostfix,
489                           _tempFileIndex,
490                           MEDIA_DATA_ON_DISK,
491                           _aFs, iCacheSize), mda);
492 
493             _tempFileIndex++;
494         }
495         addMediaDataAtom(mda);
496     }
497     else
498     {
499         mda = getMediaDataAtomForTrack(0);
500     }
501 
502     if ((uint32) mediaType == MEDIA_TYPE_AUDIO)
503     {
504         // Create default audio track and add it to moov atom
505         PV_MP4_FF_NEW(fp->auditCB, PVA_FF_TrackAtom, (MEDIA_TYPE_AUDIO,
506                       _pmovieAtom->getMutableMovieHeaderAtom().findNextTrackID(),
507                       _fileAuthoringFlags,
508                       codecType,
509                       1, profile, profileComp, level),
510                       pmediatrack);
511 
512         if (mda)
513             mda->setTrackReferencePtr(pmediatrack);
514         _pmovieAtom->addTrackAtom(pmediatrack);
515 
516         // add audio interleave buffer for track
517         if (_oInterLeaveEnabled)
518         {
519             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_InterLeaveBuffer, (MEDIA_TYPE_AUDIO,
520                           codecType,
521                           pmediatrack->getTrackID()),
522                           pInterLeaveBuffer);
523 
524             addInterLeaveBuffer(pInterLeaveBuffer);
525         }
526 
527         // Returns the index of the reference in the table to which this was
528         // just added (with a 1-based index NOT a zero-based index)
529 
530         TrackID = pmediatrack->getTrackID();
531 
532         if ((codecType == CODEC_TYPE_AMR_AUDIO) ||
533                 (codecType == CODEC_TYPE_AMR_WB_AUDIO))
534         {
535             _o3GPPTrack = true;
536         }
537         if (codecType == CODEC_TYPE_AAC_AUDIO)
538         {
539             _o3GPPTrack = true;
540             _oMPEGTrack = true;
541         }
542     }
543 
544     if ((uint32) mediaType == MEDIA_TYPE_VISUAL)
545     {
546         if ((codecType == CODEC_TYPE_BASELINE_H263_VIDEO) ||
547                 (codecType == CODEC_TYPE_AVC_VIDEO))
548         {
549             _o3GPPTrack = true;
550         }
551         else if (codecType == CODEC_TYPE_MPEG4_VIDEO)
552         {
553             _o3GPPTrack = true;
554             _oMPEGTrack = true;
555         }
556 
557         // Create default video track and add it to moov atom
558         PV_MP4_FF_NEW(fp->auditCB, PVA_FF_TrackAtom, (MEDIA_TYPE_VISUAL,
559                       _pmovieAtom->getMutableMovieHeaderAtom().findNextTrackID(),
560                       _fileAuthoringFlags,
561                       codecType,
562                       1, profile, profileComp, level),
563                       pmediatrack);
564 
565         // add video interleave buffer for track
566 
567         if (_oInterLeaveEnabled)
568         {
569             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_InterLeaveBuffer, (MEDIA_TYPE_VISUAL,
570                           codecType,
571                           pmediatrack->getTrackID()),
572                           pInterLeaveBuffer);
573 
574             addInterLeaveBuffer(pInterLeaveBuffer);
575         }
576 
577         if (mda)
578             mda->setTrackReferencePtr(pmediatrack);
579         _pmovieAtom->addTrackAtom(pmediatrack);
580 
581         // Returns the index of the reference in the table to which this was
582         // just added (with a 1-based index NOT a zero-based index)
583         TrackID = pmediatrack->getTrackID();
584     }
585 
586     if ((uint32) mediaType == MEDIA_TYPE_TEXT)//added for the support of timed text track
587     {
588         if (codecType == CODEC_TYPE_TIMED_TEXT)
589         {
590             _o3GPPTrack = true;
591         }
592         // Create default video track and add it to moov atom
593         PV_MP4_FF_NEW(fp->auditCB, PVA_FF_TrackAtom, (MEDIA_TYPE_TEXT,
594                       _pmovieAtom->getMutableMovieHeaderAtom().findNextTrackID(),
595                       _fileAuthoringFlags,
596                       codecType,
597                       1,
598                       profile, profileComp, level),
599                       pmediatrack);
600 
601         // add text interleave buffer for track
602         if (_oInterLeaveEnabled)
603         {
604             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_InterLeaveBuffer, (MEDIA_TYPE_TEXT,
605                           codecType,
606                           pmediatrack->getTrackID()),
607                           pInterLeaveBuffer);
608 
609             addInterLeaveBuffer(pInterLeaveBuffer);
610         }
611 
612         mda->setTrackReferencePtr(pmediatrack);
613         _pmovieAtom->addTrackAtom(pmediatrack);
614 
615         // Returns the index of the reference in the table to which this was
616         // just added (with a 1-based index NOT a zero-based index)
617         TrackID = pmediatrack->getTrackID();
618     }
619     recomputeSize();
620     return (TrackID);
621 }
622 
623 void
addTrackReference(uint32 currtrackID,int32 reftrackID)624 PVA_FF_Mpeg4File::addTrackReference(uint32 currtrackID, int32 reftrackID)
625 {
626     PVA_FF_TrackAtom *pCurrTrack = _pmovieAtom->getMediaTrack(currtrackID);
627     pCurrTrack->addTrackReference(reftrackID);
628     return;
629 }
630 
631 void
setTargetBitrate(uint32 trackID,uint32 avgBitRate,uint32 maxBitRate,uint32 bufferSizeDB)632 PVA_FF_Mpeg4File::setTargetBitrate(uint32 trackID, uint32 avgBitRate, uint32 maxBitRate, uint32 bufferSizeDB)
633 {
634     _pmovieAtom->setTargetBitrate(trackID, avgBitRate, maxBitRate, bufferSizeDB);
635     return;
636 }
637 
638 void
setTimeScale(uint32 trackID,uint32 rate)639 PVA_FF_Mpeg4File::setTimeScale(uint32 trackID, uint32 rate)
640 {
641     // Set the sample rate for the specific video track
642     _pmovieAtom->setTimeScale(trackID, rate);
643     return;
644 }
645 
646 //this will work same as the addsampletotrack but this
647 //will be called only for timed text file format
addTextSampleToTrack(uint32 trackID,Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> & fragmentList,uint32 ts,uint8 flags,int32 index,uint8 * textsamplemodifier)648 bool PVA_FF_Mpeg4File::addTextSampleToTrack(uint32 trackID,
649         Oscl_Vector <OsclMemoryFragment, OsclMemAllocator>& fragmentList,
650         uint32 ts, uint8 flags, int32 index, uint8* textsamplemodifier)
651 {
652     OSCL_UNUSED_ARG(textsamplemodifier);
653     PVA_FF_TrackAtom *mediaTrack;
654     uint32 mediaType;
655     int32 codecType;
656     bool retVal = true;
657 
658     mediaTrack = _pmovieAtom->getMediaTrack(trackID);
659     mediaType  = mediaTrack->getMediaType();
660     codecType = _pmovieAtom->getCodecType(trackID);
661 
662     // Create media sample buffer and size field
663     uint32 size = 0;
664     // temporary variables
665     uint32 ii = 0;
666     OsclBinIStreamBigEndian stream;
667 
668     if (!fragmentList.empty())
669     {
670         if (mediaType == MEDIA_TYPE_TEXT)//CALCULATES SIZE OF TIMED TEXT SAMPLE
671         {
672             for (ii = 0; ii < fragmentList.size(); ii++)
673             {
674                 size += fragmentList[ii].len;
675             }
676         }
677     }
678 
679     PVA_FF_MediaDataAtom *mdatAtom = getMediaDataAtomForTrack(trackID);
680     if (mediaType == MEDIA_TYPE_TEXT)
681     {
682         if (_modifiable)
683         {
684             // The layer in the flags byte indicates which video track to add to
685             // int32 trackNum = (int32)(flags & 0x70) >> 4;
686 
687             if (mediaTrack)
688             {
689                 // Add to mdat PVA_FF_Atom for the specified track
690                 if (codecType == CODEC_TYPE_TIMED_TEXT)
691                 {
692                     if (_oInterLeaveEnabled)
693                     {
694                         if (!addTextMediaSampleInterleave(trackID, fragmentList, size, ts, flags, index))
695                         {
696                             return false;
697                         }
698                     }
699                     else
700                     {
701                         if (!mdatAtom->addRawSample((fragmentList), (size), mediaType, codecType))
702                         {
703                             retVal = false;
704                         }
705                         _pmovieAtom->addTextSampleToTrack(trackID, fragmentList, size, ts, flags, index);
706                     }
707                 }
708             }
709             else
710             {
711                 return false;
712             }
713         }
714         else
715         {
716             return false;
717         }
718     }
719 
720     return (retVal);
721 }
722 
723 // Movie fragment Mode : APIs to set and get duration of each MOOF atom
724 void
setMovieFragmentDuration(uint32 duration)725 PVA_FF_Mpeg4File::setMovieFragmentDuration(uint32 duration)
726 {
727     _movieFragmentDuration = duration;
728     return;
729 }
730 
731 
732 
733 uint32
getMovieFragmentDuration()734 PVA_FF_Mpeg4File::getMovieFragmentDuration()
735 {
736     return  _movieFragmentDuration;
737 }
738 
739 
740 bool
addSampleToTrack(uint32 trackID,Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> & fragmentList,uint32 ts,uint8 flags)741 PVA_FF_Mpeg4File::addSampleToTrack(uint32 trackID,
742                                    Oscl_Vector <OsclMemoryFragment, OsclMemAllocator>& fragmentList,    // vector which contains either NALs or a sample
743                                    uint32 ts, uint8 flags)
744 {
745     PVA_FF_TrackAtom *mediaTrack;
746     uint32 mediaType;
747     int32 codecType;
748     bool retVal = true;
749     //int32 flags;
750 
751     mediaTrack = _pmovieAtom->getMediaTrack(trackID);
752     mediaType  = mediaTrack->getMediaType();
753     codecType = _pmovieAtom->getCodecType(trackID);
754 
755     // Create media sample buffer and size field
756     uint32 size = 0;
757     // temporary variables
758     uint32 ii = 0;
759     OsclBinIStreamBigEndian stream;
760     OsclMemoryFragment fragment;
761     if (!fragmentList.empty())
762     {
763         // calculate size of AVC sample
764         if (mediaType == MEDIA_TYPE_VISUAL && codecType == CODEC_TYPE_AVC_VIDEO)
765         {
766             // compose AVC sample
767             for (uint32 ii = 0; ii < fragmentList.size(); ii++)
768             {
769                 size += (fragmentList[ii].len + 4); // length + '2' size of NAL unit length field
770             }
771         }
772         // all memory fragments in the vector combines into one sample
773         else
774         {
775             for (ii = 0; ii < fragmentList.size(); ii++)
776             {
777                 size += fragmentList[ii].len;
778             }
779         }
780     }
781 
782     PVA_FF_MediaDataAtom *mdatAtom = getMediaDataAtomForTrack(trackID);
783     if (mediaType == MEDIA_TYPE_AUDIO)
784     {
785         if (_modifiable)
786         {
787             if (mediaTrack != NULL)
788             {
789                 if ((mediaTrack->getCodecType() == CODEC_TYPE_AMR_AUDIO) ||
790                         (mediaTrack->getCodecType() == CODEC_TYPE_AMR_WB_AUDIO))
791                 {
792                     if (size >= 1)
793                     {
794                         PVA_FF_TrackAtom *track = _pmovieAtom->getMediaTrack(trackID);
795                         if (track != NULL)
796                         {
797                             // FT is in the first byte that comes off the encoder
798                             flags = *((uint8*)(fragmentList.front().ptr));
799                             uint32 mode_set = 0;
800                             if (flags < 16)
801                             {
802                                 mode_set = AMRModeSetMask[(flags&0x0f)];
803                             }
804                             if (flags < 9)
805                             {
806                                 // JUST TO ENSURE THAT THE PADDED BITS ARE ZERO
807                                 fragment = fragmentList.back();
808                                 if (mediaTrack->getCodecType() == CODEC_TYPE_AMR_AUDIO)
809                                 {
810                                     ((uint8*)fragment.ptr)[ fragment.len - 1] &= aAMRNBZeroSetMask[(flags&0x0f)];
811                                 }
812                                 else if (mediaTrack->getCodecType() == CODEC_TYPE_AMR_WB_AUDIO)
813                                 {
814                                     ((uint8*)fragment.ptr)[ fragment.len - 1] &= aAMRWBZeroSetMask[(flags&0x0f)];
815                                 }
816 
817                             }
818                             if (_oInterLeaveEnabled)
819                             {
820                                 if (!addMediaSampleInterleave(trackID, fragmentList, size, ts, flags))
821                                 {
822                                     return false;
823                                 }
824                             }
825                             else
826                             {
827                                 // Add to mdat PVA_FF_Atom for the specified track
828                                 if (!mdatAtom->addRawSample(fragmentList, size, mediaType, codecType))
829                                 {
830                                     retVal = false;
831                                 }
832                                 // Add to moov atom (in turn adds to tracks)
833                                 _pmovieAtom->addSampleToTrack(trackID, fragmentList, size,
834                                                               ts, flags);
835                             }
836                         }
837                     }
838                     else
839                     {
840                         return false;
841                     }
842                 }
843                 else if (mediaTrack->getCodecType() == CODEC_TYPE_AAC_AUDIO)
844                 {
845                     if (size > 0)
846                     {
847                         if (_oInterLeaveEnabled)
848                         {
849                             if (!addMediaSampleInterleave(trackID, fragmentList, size, ts, flags))
850                             {
851                                 return false;
852                             }
853                         }
854                         else
855                         {
856 
857                             // Add to mdat PVA_FF_Atom for the specified track
858 
859                             if (!mdatAtom->addRawSample((fragmentList), (size), mediaType, codecType))
860                             {
861                                 retVal = false;
862                             }
863 
864                             flags = 0;
865 
866                             // Add to moov atom (in turn adds to tracks)
867                             _pmovieAtom->addSampleToTrack(trackID, fragmentList, size,
868                                                           ts, flags);
869                         }
870                     }
871                 }
872             }
873             else
874             {
875                 return false;
876             }
877         }
878         else
879         {
880             return false;
881         }
882     }
883 
884     if (mediaType == MEDIA_TYPE_VISUAL)
885     {
886         // For the first frame in each layer, pull off the VOL header.  For the base layer
887         // (layer=0), this fp the first 28 bytes.  For the enhancememnt(temporal) layer
888         // (layer=1), this fp the first 17 bytes (compact version with no repeate headers).
889         //
890         // Note that this fp making the assumption that the first frame of each layer will
891         // contain this VOL header information.  In the current encoder (version 1.0), this
892         // fp true.
893         //
894         // Eventually strip the VOL headers from the first samples of each layer so that
895         // there fp no redundancy w.r.t. the VOL headers in the MP4 file.  Currently the
896         // VOL headers are remaining in the first frame data
897 
898         // uint8 layer = (uint8)((flags & 0x70) >> 4);
899 
900 
901         if (codecType == CODEC_TYPE_BASELINE_H263_VIDEO)
902         {
903             if (_firstFrameInLayer0)
904             {
905                 _firstFrameInLayer0 = false;
906             }
907         }
908 
909         if (_modifiable)
910         {
911             // The layer in the flags byte indicates which video track to add to
912             // int32 trackNum = (int32)(flags & 0x70) >> 4;
913 
914             if (mediaTrack)
915             {
916                 // Add to mdat PVA_FF_Atom for the specified track
917                 if ((codecType == CODEC_TYPE_MPEG4_VIDEO) ||
918                         (codecType == CODEC_TYPE_BASELINE_H263_VIDEO) ||
919                         (codecType == CODEC_TYPE_AVC_VIDEO))
920                 {
921                     if (_oInterLeaveEnabled)
922                     {
923                         if (!addMediaSampleInterleave(trackID, fragmentList, size, ts, flags))
924                         {
925                             return false;
926                         }
927                     }
928                     else
929                     {
930 
931                         if (!mdatAtom->addRawSample((fragmentList), (size), mediaType, codecType))
932                         {
933                             retVal = false;
934                         }
935                         _pmovieAtom->addSampleToTrack(trackID, fragmentList, size, ts, flags);
936                     }
937                 }
938             }
939             else
940             {
941                 return false;
942             }
943         }
944         else
945         {
946             return false;
947         }
948     }
949 
950     return (retVal);
951 }
952 
953 // The following methods are used to set the user data
954 void
setVersion(PVA_FF_UNICODE_STRING_PARAM version,uint16 langCode)955 PVA_FF_Mpeg4File::setVersion(PVA_FF_UNICODE_STRING_PARAM version, uint16 langCode)
956 {
957     OSCL_UNUSED_ARG(version);
958     OSCL_UNUSED_ARG(langCode);
959 }
960 
961 void
setTitle(PVA_FF_UNICODE_STRING_PARAM title,uint16 langCode)962 PVA_FF_Mpeg4File::setTitle(PVA_FF_UNICODE_STRING_PARAM title, uint16 langCode)
963 {
964     if (!_oSetTitleDone)
965     {
966         _oSetTitleDone = true;
967         _title = title;
968         if (_pmovieAtom != NULL)
969         {
970             _pmovieAtom->setTitleInfo(title, langCode);
971         }
972     }
973 }
974 
975 void
setAuthor(PVA_FF_UNICODE_STRING_PARAM author,uint16 langCode)976 PVA_FF_Mpeg4File::setAuthor(PVA_FF_UNICODE_STRING_PARAM author, uint16 langCode)
977 {
978     if (!_oSetAuthorDone)
979     {
980         _oSetAuthorDone = true;
981         _author = author;
982         if (_pmovieAtom != NULL)
983         {
984             _pmovieAtom->setAuthorInfo(author, langCode);
985         }
986     }
987 }
988 
989 void
setCopyright(PVA_FF_UNICODE_STRING_PARAM copyright,uint16 langCode)990 PVA_FF_Mpeg4File::setCopyright(PVA_FF_UNICODE_STRING_PARAM copyright, uint16 langCode)
991 {
992     if (!_oSetCopyrightDone)
993     {
994         _oSetCopyrightDone = true;
995         _copyright = copyright;
996         if (_pmovieAtom != NULL)
997         {
998             _pmovieAtom->setCopyRightInfo(copyright, langCode);
999         }
1000     }
1001 }
1002 
1003 void
setDescription(PVA_FF_UNICODE_STRING_PARAM description,uint16 langCode)1004 PVA_FF_Mpeg4File::setDescription(PVA_FF_UNICODE_STRING_PARAM description, uint16 langCode)
1005 {
1006     if (!_oSetDescriptionDone)
1007     {
1008         _oSetDescriptionDone = true;
1009         _description = description;
1010         if (_pmovieAtom != NULL)
1011         {
1012             _pmovieAtom->setDescription(description, langCode);
1013         }
1014     }
1015 }
1016 
1017 void
setRating(PVA_FF_UNICODE_STRING_PARAM ratingInfo,uint16 langCode,uint32 ratingEntity,uint32 ratingCriteria)1018 PVA_FF_Mpeg4File::setRating(PVA_FF_UNICODE_STRING_PARAM ratingInfo,
1019                             uint16 langCode,
1020                             uint32 ratingEntity,
1021                             uint32 ratingCriteria)
1022 {
1023     OSCL_UNUSED_ARG(langCode);
1024 
1025     if (!_oSetRatingDone)
1026     {
1027         _oSetRatingDone = true;
1028         _ratingInfo     = ratingInfo;
1029         _ratingEntity   = ratingEntity;
1030         _ratingCriteria = ratingCriteria;
1031         if (_pmovieAtom != NULL)
1032         {
1033             _pmovieAtom->setRatingInfo(ratingInfo, ratingEntity, ratingCriteria, langCode);
1034         }
1035 
1036     }
1037 }
1038 
1039 void
setPerformer(PVA_FF_UNICODE_STRING_PARAM performer,uint16 langCode)1040 PVA_FF_Mpeg4File::setPerformer(PVA_FF_UNICODE_STRING_PARAM performer, uint16 langCode)
1041 {
1042     OSCL_UNUSED_ARG(langCode);
1043 
1044     if (!_oSetPerformerDone)
1045     {
1046         _oSetPerformerDone = true;
1047         _performer = performer;
1048 
1049         if (_pmovieAtom != NULL)
1050         {
1051             _pmovieAtom->setPerformerInfo(performer, langCode);
1052         }
1053 
1054     }
1055 }
1056 
1057 void
setGenre(PVA_FF_UNICODE_STRING_PARAM genre,uint16 langCode)1058 PVA_FF_Mpeg4File::setGenre(PVA_FF_UNICODE_STRING_PARAM genre, uint16 langCode)
1059 {
1060     OSCL_UNUSED_ARG(langCode);
1061 
1062     if (!_oSetGenreDone)
1063     {
1064         _oSetGenreDone = true;
1065         _genre = genre;
1066 
1067         if (_pmovieAtom != NULL)
1068         {
1069             _pmovieAtom->setGenreInfo(genre, langCode);
1070         }
1071 
1072     }
1073 }
1074 
1075 void
setClassification(PVA_FF_UNICODE_STRING_PARAM classificationInfo,uint32 classificationEntity,uint16 classificationTable,uint16 langCode)1076 PVA_FF_Mpeg4File::setClassification(PVA_FF_UNICODE_STRING_PARAM classificationInfo,
1077                                     uint32 classificationEntity, uint16 classificationTable,
1078                                     uint16 langCode)
1079 {
1080     OSCL_UNUSED_ARG(langCode);
1081 
1082     if (!_oSetClassificationDone)
1083     {
1084         _oSetClassificationDone = true;
1085         _classificationInfo     = classificationInfo;
1086         _classificationEntity   = classificationEntity;
1087         _classificationTable    = classificationTable;
1088 
1089         if (_pmovieAtom != NULL)
1090         {
1091             _pmovieAtom->setClassificationInfo(classificationInfo, classificationEntity, classificationTable, langCode);
1092         }
1093     }
1094 }
1095 
1096 void
setKeyWord(uint8 keyWordSize,PVA_FF_UNICODE_HEAP_STRING keyWordInfo,uint16 langCode)1097 PVA_FF_Mpeg4File::setKeyWord(uint8 keyWordSize, PVA_FF_UNICODE_HEAP_STRING keyWordInfo, uint16 langCode)
1098 {
1099     OSCL_UNUSED_ARG(langCode);
1100 
1101     _keyWordSize     = keyWordSize;
1102     _keyWordInfo     = keyWordInfo;
1103 
1104     if (_pmovieAtom != NULL)
1105     {
1106         _pmovieAtom->setKeyWordsInfo(keyWordSize, keyWordInfo, langCode);
1107     }
1108 }
1109 
1110 void
setLocationInfo(PvmfAssetInfo3GPPLocationStruct * ptr_loc_struct)1111 PVA_FF_Mpeg4File::setLocationInfo(PvmfAssetInfo3GPPLocationStruct *ptr_loc_struct)
1112 {
1113     if (!_oSetLocationInfoDone)
1114     {
1115         _oSetLocationInfoDone       = true;
1116         _locationName           = ptr_loc_struct->_location_name;
1117         _locationInfoAstrBody   = ptr_loc_struct->_astronomical_body;
1118         _locationInfoAddNotes   = ptr_loc_struct->_additional_notes;
1119         _locationInfoRole       = ptr_loc_struct->_role;
1120         _locationInfoLongitude  = ptr_loc_struct->_longitude;
1121         _locationInfoAltitude   = ptr_loc_struct->_altitude;
1122         _locationInfoLatitude   = ptr_loc_struct->_latitude;
1123 
1124         if (_pmovieAtom != NULL)
1125         {
1126             _pmovieAtom->setLocationInfo(ptr_loc_struct);
1127         }
1128     }
1129 }
1130 
1131 void
setAlbumInfo(PVA_FF_UNICODE_STRING_PARAM albumInfo,uint16 langCode)1132 PVA_FF_Mpeg4File::setAlbumInfo(PVA_FF_UNICODE_STRING_PARAM albumInfo, uint16 langCode)
1133 {
1134     if (!_oSetAlbumDone)
1135     {
1136         _oSetAlbumDone = true;
1137         _albumInfo = albumInfo;
1138 
1139         if (_pmovieAtom != NULL)
1140         {
1141             _pmovieAtom->setAlbumInfo(albumInfo, langCode);
1142         }
1143 
1144     }
1145 }
1146 
1147 void
setAlbumTrackNumber(uint8 trackNumber)1148 PVA_FF_Mpeg4File::setAlbumTrackNumber(uint8 trackNumber)
1149 {
1150     if (_pmovieAtom != NULL)
1151     {
1152         _pmovieAtom->setAlbumTrackNumber(trackNumber);
1153     }
1154 }
1155 
1156 void
setRecordingYear(uint16 recordingYear)1157 PVA_FF_Mpeg4File::setRecordingYear(uint16 recordingYear)
1158 {
1159     if (!_oSetRecordingYearDone)
1160     {
1161         _oSetRecordingYearDone = true;
1162         _recordingYear = recordingYear;
1163 
1164         if (_pmovieAtom != NULL)
1165         {
1166             _pmovieAtom->setRecordingYearInfo(recordingYear);
1167         }
1168 
1169     }
1170 }
1171 
1172 void
setCreationDate(PVA_FF_UNICODE_STRING_PARAM creationDate)1173 PVA_FF_Mpeg4File::setCreationDate(PVA_FF_UNICODE_STRING_PARAM creationDate)
1174 {
1175     if (!_oSetCreationDateDone)
1176     {
1177         _oSetCreationDateDone = true;
1178         _creationDate = creationDate;
1179     }
1180 }
1181 
1182 void
setVideoParams(uint32 trackID,float frate,uint16 interval,uint32 frame_width,uint32 frame_height)1183 PVA_FF_Mpeg4File::setVideoParams(uint32 trackID,
1184                                  float frate,
1185                                  uint16 interval,
1186                                  uint32 frame_width,
1187                                  uint32 frame_height)
1188 {
1189     OSCL_UNUSED_ARG(frate);
1190     OSCL_UNUSED_ARG(interval);
1191     PVA_FF_TrackAtom *trackAtom;
1192     trackAtom = _pmovieAtom->getMediaTrack(trackID);
1193 
1194     if (trackAtom != NULL)
1195         trackAtom->setVideoParams(frame_width, frame_height);
1196 
1197     return;
1198 }
1199 
1200 void
setH263ProfileLevel(uint32 trackID,uint8 profile,uint8 level)1201 PVA_FF_Mpeg4File::setH263ProfileLevel(uint32 trackID,
1202                                       uint8  profile,
1203                                       uint8  level)
1204 {
1205     PVA_FF_TrackAtom *trackAtom;
1206     trackAtom = _pmovieAtom->getMediaTrack(trackID);
1207     trackAtom->setH263ProfileLevel(profile, level);
1208     return;
1209 }
1210 
1211 // Methods to get and set the sample rate (i.e. timescales) for the streams and
1212 // the overall Mpeg-4 presentation
1213 void
setPresentationTimescale(uint32 timescale)1214 PVA_FF_Mpeg4File::setPresentationTimescale(uint32 timescale)
1215 {   // Set the overall timescale of the Mpeg-4 presentation
1216     _pmovieAtom->setTimeScale(timescale);
1217 }
1218 
1219 void
addMediaDataAtom(PVA_FF_MediaDataAtom * atom)1220 PVA_FF_Mpeg4File::addMediaDataAtom(PVA_FF_MediaDataAtom* atom)
1221 {
1222     if (_modifiable)
1223     {
1224         _pmediaDataAtomVec->push_back(atom);
1225     }
1226 }
1227 
1228 //for timed text only
1229 void
setTextDecoderSpecificInfo(PVA_FF_TextSampleDescInfo * header,int32 trackID)1230 PVA_FF_Mpeg4File::setTextDecoderSpecificInfo(PVA_FF_TextSampleDescInfo *header, int32 trackID)
1231 {
1232     PVA_FF_TextSampleDescInfo *pinfo = NULL;
1233     pinfo = header;
1234     _pmovieAtom->addTextDecoderSpecificInfo(pinfo, trackID);
1235     return;
1236 }
1237 
1238 
1239 void
setDecoderSpecificInfo(uint8 * header,int32 size,int32 trackID)1240 PVA_FF_Mpeg4File::setDecoderSpecificInfo(uint8 * header, int32 size, int32 trackID)
1241 {
1242     PVA_FF_DecoderSpecificInfo *pinfo = NULL;
1243     PV_MP4_FF_NEW(fp->auditCB, PVA_FF_DecoderSpecificInfo, (header, (uint32)size), pinfo);
1244     _pmovieAtom->addDecoderSpecificInfo(pinfo, trackID);
1245     PVA_FF_TrackAtom *track = _pmovieAtom->getMediaTrack(trackID);
1246     if (track->getMediaType() == MEDIA_TYPE_VISUAL)
1247     {
1248         if (track->getCodecType() == CODEC_TYPE_AVC_VIDEO)
1249         {
1250             PV_MP4_FF_DELETE(NULL, PVA_FF_DecoderSpecificInfo, pinfo);
1251         }
1252     }
1253 }
1254 
1255 void
recomputeSize()1256 PVA_FF_Mpeg4File::recomputeSize()
1257 {
1258     uint32 i;
1259     uint32 size = getMovieAtom().getSize();
1260 
1261     for (i = 0; i < getMediaDataAtomVec().size(); i++)
1262     {
1263         size += getMediaDataAtomVec()[i]->getSize();
1264     }
1265     _size = size;
1266 }
1267 
1268 // Rendering the PVA_FF_Mpeg4File in proper format (bitlengths, etc.) to an ostream
1269 bool
renderToFileStream(MP4_AUTHOR_FF_FILE_IO_WRAP * fp)1270 PVA_FF_Mpeg4File::renderToFileStream(MP4_AUTHOR_FF_FILE_IO_WRAP *fp)
1271 {
1272     uint32 metaDataSize = 0;
1273     /*
1274      * Setting the major brand in ftyp atom
1275      */
1276     if (!_oFtypPopulated)
1277     {
1278         if (_o3GPPTrack)
1279         {
1280             setMajorBrand(BRAND_3GPP4);
1281             setMajorBrandVersion(VERSION_3GPP4);
1282         }
1283         else if (_oMPEGTrack)
1284         {
1285             setMajorBrand(BRAND_MPEG4);
1286             setMajorBrandVersion(VERSION_MPEG4);
1287         }
1288         else if (_oPVMMTrack)
1289         {
1290             setMajorBrand(PVMM_BRAND);
1291             setMajorBrandVersion(PVMM_VERSION);
1292         }
1293 
1294         /*
1295          * Add compatible brands
1296          */
1297         if (_o3GPPTrack)
1298         {
1299             addCompatibleBrand(BRAND_3GPP4);
1300         }
1301         if (_oPVMMTrack)
1302         {
1303             addCompatibleBrand(PVMM_BRAND);
1304         }
1305         if (_oMPEGTrack)
1306         {
1307             addCompatibleBrand(BRAND_MPEG4);
1308         }
1309         addCompatibleBrand(BRAND_3GPP5);
1310     }
1311 
1312     if( _oSetCreationDateDone )
1313     {
1314         uint32 time = convertCreationTime(_creationDate);
1315 
1316         _pmovieAtom->getMutableMovieHeaderAtom().setCreationTime(time);
1317         _pmovieAtom->getMutableMovieHeaderAtom().setModificationTime(time);
1318     }
1319 
1320     if ((_o3GPPTrack == true) || (_oPVMMTrack == true) || (_oMPEGTrack == true))
1321     {
1322         _pFileTypeAtom->renderToFileStream(fp);
1323 
1324         metaDataSize += _pFileTypeAtom->getSize();
1325     }
1326     {
1327         if (!_oDirectRenderEnabled)
1328         {
1329             populateUserDataAtom();
1330         }
1331     }
1332     if (!_fileAuthoringFlags)
1333     {
1334         if (_oUserDataUpFront)
1335         {
1336             {
1337                 if (!_puserDataAtom->renderToFileStream(fp))
1338                 {
1339                     return false;
1340                 }
1341                 metaDataSize += _puserDataAtom->getSize();
1342             }
1343         }
1344     }
1345     if ((_oDirectRenderEnabled) || (_totalTempFileRemoval))
1346     {
1347         PVA_FF_AtomUtils::seekFromStart(fp, _directRenderFileOffset);
1348     }
1349 
1350     _oFileRenderCalled = true;
1351 
1352     uint32 chunkFileOffset  = 0;
1353 
1354     int32 i;
1355     uint32 size = _pmediaDataAtomVec->size();
1356 
1357     _pmovieAtom->prepareToRender();
1358 
1359     if (_oMovieAtomUpfront)
1360     {
1361         metaDataSize += _pmovieAtom->getSize();
1362 
1363         chunkFileOffset = DEFAULT_ATOM_SIZE + metaDataSize;
1364 
1365         // Update all chunk offsets
1366         for (i = size - 1; i >= 0; i--)
1367         {
1368             PVA_FF_MediaDataAtom *mdat = (*_pmediaDataAtomVec)[i];
1369 
1370             if (!(mdat->IsTargetRender()))
1371             {
1372                 Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
1373                     (*_pmediaDataAtomVec)[i]->getTrackReferencePtrVec();
1374 
1375                 if (trefVec != NULL)
1376                 {
1377                     for (uint32 trefVecIndex = 0;
1378                             trefVecIndex < trefVec->size();
1379                             trefVecIndex++)
1380                     {
1381                         (*trefVec)[trefVecIndex]->updateAtomFileOffsets(chunkFileOffset);
1382                     }
1383                 }
1384                 chunkFileOffset += mdat->getMediaDataSize();
1385             }
1386             else
1387             {
1388                 // not supported - no direct render with media interleaving
1389                 return false;
1390             }
1391         }
1392 
1393         // Render the movie atom to the file stream
1394         if (!_pmovieAtom->renderToFileStream(fp))
1395         {
1396             return false;
1397         }
1398     }
1399 
1400 
1401     // Render all mediaData atoms to the file stream
1402     for (i = size - 1; i >= 0; i--)
1403     {
1404         bool oRenderMdat = true;
1405         if (oRenderMdat)
1406         {
1407             if (!((*_pmediaDataAtomVec)[i]->IsTargetRender()))
1408             {
1409                 if (!((*_pmediaDataAtomVec)[i]->renderToFileStream(fp)))
1410                 {
1411                     _fileWriteFailed = true;
1412                     return false;
1413                 }
1414                 if ((*_pmediaDataAtomVec)[i]->_targetFileWriteError == true)
1415                 {
1416                     _fileWriteFailed = true;
1417                     return false;
1418                 }
1419 
1420                 if (!_oMovieAtomUpfront)
1421                 {
1422                     chunkFileOffset =
1423                         (*_pmediaDataAtomVec)[i]->getFileOffsetForChunkStart();
1424                     if (chunkFileOffset != 0)
1425                     {
1426                         // Only true when fp a PVA_FF_MediaDataAtom
1427 
1428                         Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
1429                             (*_pmediaDataAtomVec)[i]->getTrackReferencePtrVec();
1430 
1431 
1432                         if (trefVec != NULL)
1433                         {
1434                             for (uint32 trefVecIndex = 0;
1435                                     trefVecIndex < trefVec->size();
1436                                     trefVecIndex++)
1437                             {
1438                                 (*trefVec)[trefVecIndex]->updateAtomFileOffsets(chunkFileOffset);
1439                             }
1440                         }
1441                     }
1442                 }
1443             }
1444             else
1445             {
1446                 if (!_oMovieAtomUpfront)
1447                 {
1448                     chunkFileOffset =
1449                         (*_pmediaDataAtomVec)[i]->getFileOffsetForChunkStart();
1450 
1451                     if (chunkFileOffset != 0)
1452                     {
1453                         // Only true when fp a PVA_FF_MediaDataAtom
1454 
1455                         Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec = (*_pmediaDataAtomVec)[i]->getTrackReferencePtrVec();
1456                         if (trefVec != NULL)
1457                         {
1458                             for (uint32 trefVecIndex = 0;
1459                                     trefVecIndex < trefVec->size();
1460                                     trefVecIndex++)
1461                             {
1462                                 (*trefVec)[trefVecIndex]->updateAtomFileOffsets(chunkFileOffset);
1463                             }
1464                         }
1465                     }
1466                 }
1467             }
1468         }
1469     }
1470     if (!_fileAuthoringFlags)
1471     {
1472         if (!_oUserDataUpFront)
1473         {
1474             {
1475                 if (!_puserDataAtom->renderToFileStream(fp))
1476                 {
1477                     return false;
1478                 }
1479             }
1480         }
1481     }
1482     //Important: This needs to be done AFTER the user data has been rendered to file
1483     if (!_oMovieAtomUpfront)
1484     {
1485         // Render the movie atom to the file stream
1486         if (!_pmovieAtom->renderToFileStream(fp))
1487         {
1488             return false;
1489         }
1490     }
1491 
1492     _tempFileIndex = 'a';
1493 
1494     return true;
1495 }
1496 
1497 // Rendering the MP4 file to disk
1498 bool
renderToFile(PVA_FF_UNICODE_STRING_PARAM filename)1499 PVA_FF_Mpeg4File::renderToFile(PVA_FF_UNICODE_STRING_PARAM filename)
1500 {
1501     MP4_AUTHOR_FF_FILE_IO_WRAP fp;
1502     fp._filePtr = NULL;
1503     fp._osclFileServerSession = NULL;
1504     bool status = true;
1505 
1506     if (!(_oMovieFragmentEnabled && _oComposeMoofAtom))
1507     {
1508 
1509         _modifiable = false; // Only allow addition of samples BEFORE rendering to disk
1510         // After render to disk - cannot add more data
1511 
1512 
1513         //make sure to flush the interleave buffers, be it to temp files
1514         //or to target files
1515         uint32 k = 0;
1516 
1517         for (k = 0; status && k < _pmediaDataAtomVec->size(); k++)
1518         {
1519             Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
1520                 (*_pmediaDataAtomVec)[k]->getTrackReferencePtrVec();
1521 
1522             if (trefVec != NULL)
1523             {
1524                 for (uint32 trefVecIndex = 0;
1525                         status && trefVecIndex < trefVec->size();
1526                         trefVecIndex++)
1527                 {
1528                     PVA_FF_TrackAtom* pTrack = (*trefVec)[trefVecIndex];
1529                     uint32 trackID = pTrack->getTrackID();
1530 
1531                     if (_oInterLeaveEnabled)
1532                     {
1533                         if (!flushInterLeaveBuffer(trackID))
1534                         {
1535                             status = false;
1536                         }
1537                     }
1538 
1539                 }
1540             }
1541         }
1542 
1543         bool targetRender = false;
1544         _directRenderFileOffset = 0;
1545 
1546         if ((_oDirectRenderEnabled) || (_totalTempFileRemoval))
1547         {
1548             for (uint32 k = 0; k < _pmediaDataAtomVec->size(); k++)
1549             {
1550                 bool tempVal = ((*_pmediaDataAtomVec)[k]->IsTargetRender());
1551 
1552                 if (tempVal)
1553                 {
1554                     if (targetRender)
1555                     {
1556                         //Only one track is allowed to be rendered directly onto the target
1557                         //file
1558                         status = false;
1559                     }
1560                     else
1561                     {
1562                         targetRender = true;
1563 
1564                         if (!((*_pmediaDataAtomVec)[k]->closeTargetFile()))
1565                         {
1566                             status = false;
1567                         }
1568 
1569                         fp._filePtr = ((*_pmediaDataAtomVec)[k]->getTargetFilePtr());
1570                         fp._osclFileServerSession = OSCL_STATIC_CAST(Oscl_FileServer*, _aFs);
1571                         _directRenderFileOffset =
1572                             ((*_pmediaDataAtomVec)[k]->getTotalDataRenderedToTargetFileInDirectRenderMode());
1573                     }
1574                 }
1575             }
1576         }
1577         else
1578         {
1579             fp._osclFileServerSession = OSCL_STATIC_CAST(Oscl_FileServer*, _aFs);
1580             PVA_FF_AtomUtils::openFile(&fp, filename, Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY);
1581             _oIsFileOpen = true;
1582         }
1583 
1584         if (fp._filePtr == NULL)
1585         {
1586             status = false;
1587         }
1588 
1589         if (!renderToFileStream(&fp))
1590         {
1591             status = false;
1592         }
1593 
1594         if (_oIsFileOpen)
1595         {
1596             PVA_FF_AtomUtils::closeFile(&fp);
1597             _oIsFileOpen = false;
1598         }
1599 
1600         if (_fileWriteFailed)
1601         {
1602             status = false;
1603         }
1604     }
1605     else
1606     {
1607         // flush interleave buffers into last TRUN
1608         for (uint32 k = 0; k < _pmediaDataAtomVec->size(); k++)
1609         {
1610             if ((*_pmediaDataAtomVec)[k]->IsTargetRender())
1611             {
1612                 Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
1613                     (*_pmediaDataAtomVec)[k]->getTrackReferencePtrVec();
1614 
1615                 if (trefVec != NULL)
1616                 {
1617                     for (uint32 trefVecIndex = 0; status && trefVecIndex < trefVec->size(); trefVecIndex++)
1618                     {
1619                         PVA_FF_TrackAtom* pTrack = (*trefVec)[trefVecIndex];
1620                         uint32 trackID = pTrack->getTrackID();
1621 
1622                         if (_oInterLeaveEnabled)
1623                         {
1624                             if (!flushInterLeaveBuffer(trackID))
1625                             {
1626                                 status = false;
1627                             }
1628                         }
1629                     }
1630                 }
1631             }
1632         }
1633 
1634         fp._filePtr = _targetFileHandle;
1635         fp._osclFileServerSession = OSCL_STATIC_CAST(Oscl_FileServer*, _aFs);
1636 
1637         // write movie fragment duration in movie extends atom
1638         _pmovieAtom->writeMovieFragmentDuration(&fp);
1639 
1640         if (!renderMovieFragments())
1641         {
1642             status = false;
1643         }
1644 
1645         fp._filePtr = _targetFileHandle;
1646         fp._osclFileServerSession = OSCL_STATIC_CAST(Oscl_FileServer*, _aFs);
1647         _pMfraAtom->renderToFileStream(&fp);
1648         _pmovieAtom->writeMaxSampleSize(&fp);
1649         if (_oIsFileOpen)
1650         {
1651             PVA_FF_AtomUtils::closeFile(&fp);
1652             _oIsFileOpen = false;
1653         }
1654     }
1655 
1656     return status;
1657 }
1658 
1659 
1660 // Access function to set the postfix string for PVA_FF_MediaDataAtom objects
1661 // Set the post fix string for the temporary file in order to support multiple instances,
1662 // the goal fp to create temporary files with different names
1663 void
SetTempFilePostFix(PVA_FF_UNICODE_STRING_PARAM postFix)1664 PVA_FF_Mpeg4File::SetTempFilePostFix(PVA_FF_UNICODE_STRING_PARAM postFix)
1665 {
1666     _tempFilePostfix = (_STRLIT(""));
1667     _tempFilePostfix += postFix;
1668 }
1669 
1670 // Access function to set the output path string for PVA_FF_MediaDataAtom objects
1671 // Set the output path string for the temporary files in order to generate them at the same location
1672 // as the final mp4 file.
1673 void
SetTempOutputPath(PVA_FF_UNICODE_STRING_PARAM outputPath)1674 PVA_FF_Mpeg4File::SetTempOutputPath(PVA_FF_UNICODE_STRING_PARAM outputPath)
1675 {
1676     _tempOutputPath = (_STRLIT(""));
1677     _tempOutputPath += outputPath;
1678 }
1679 
1680 PVA_FF_MediaDataAtom*
getMediaDataAtomForTrack(uint32 trackID)1681 PVA_FF_Mpeg4File::getMediaDataAtomForTrack(uint32 trackID)
1682 {
1683     if (_oInterLeaveEnabled)
1684     {
1685         if (_pmediaDataAtomVec != NULL)
1686         {
1687             if (_pmediaDataAtomVec->size() > MIN_NUM_MEDIA_TRACKS)
1688             {
1689                 int32 index = MIN_NUM_MEDIA_TRACKS;
1690                 return (*_pmediaDataAtomVec)[index];
1691             }
1692         }
1693     }
1694     else
1695     {
1696         for (uint32 k = 0; k < _pmediaDataAtomVec->size(); k++)
1697         {
1698             PVA_FF_TrackAtom *pTrack  = (PVA_FF_TrackAtom *)((*_pmediaDataAtomVec)[k]->getTrackReferencePtr());
1699             uint32 tID = pTrack->getTrackID();
1700 
1701             if (tID == trackID)
1702             {
1703                 return (*_pmediaDataAtomVec)[k];
1704             }
1705         }
1706     }
1707     return (NULL);
1708 }
1709 
1710 bool
addMultipleAccessUnitsToTrack(uint32 trackID,GAU * pgau)1711 PVA_FF_Mpeg4File::addMultipleAccessUnitsToTrack(uint32 trackID, GAU *pgau)
1712 {
1713     PVA_FF_TrackAtom *mediaTrack;
1714     uint32 mediaType;
1715     bool retVal = true;
1716 
1717     mediaTrack = _pmovieAtom->getMediaTrack(trackID);
1718 
1719     if (mediaTrack == NULL)
1720     {
1721         return false;
1722     }
1723 
1724     mediaType  = mediaTrack->getMediaType();
1725 
1726     PVA_FF_MediaDataAtom *mdatAtom = getMediaDataAtomForTrack(trackID);
1727 
1728     if (mdatAtom == NULL)
1729     {
1730         return false;
1731     }
1732 
1733     if (mediaType == MEDIA_TYPE_AUDIO)
1734     {
1735         if (_modifiable)
1736         {
1737             if ((mediaTrack->getCodecType() == CODEC_TYPE_AMR_AUDIO) ||
1738                     (mediaTrack->getCodecType() == CODEC_TYPE_AMR_WB_AUDIO))
1739             {
1740                 int32 index = 0;
1741 
1742                 uint8  *frag_ptr = (uint8 *)pgau->buf.fragments[index].ptr;
1743                 int32 frag_len  = pgau->buf.fragments[index].len;
1744 
1745                 for (uint32 k = 0; k < pgau->numMediaSamples; k++)
1746                 {
1747                     uint8 frame_type = (uint8)pgau->info[k].sample_info;
1748 
1749                     frame_type = (uint8)(frame_type << 3);
1750                     frame_type |= 0x04;
1751 
1752                     // Add to mdat PVA_FF_Atom for the specified track
1753                     if (!mdatAtom->addRawSample(&frame_type, 1))
1754                     {
1755                         retVal = false;
1756                     }
1757 
1758                     int32 frame_size = pgau->info[k].len;
1759 
1760                     while (frame_size)
1761                     {
1762                         if (frag_len >= frame_size)
1763                         {
1764                             // Add to mdat PVA_FF_Atom for the specified track
1765                             if (!mdatAtom->addRawSample(frag_ptr,
1766                                                         frame_size))
1767                             {
1768                                 retVal = false;
1769                             }
1770 
1771                             frag_ptr += frame_size;
1772                             frag_len -= frame_size;
1773                             frame_size = 0;
1774                         }
1775                         else
1776                         {
1777                             // Add to mdat PVA_FF_Atom for the specified track
1778                             if (!mdatAtom->addRawSample(frag_ptr,
1779                                                         frag_len))
1780                             {
1781                                 retVal = false;
1782                             }
1783 
1784                             frame_size -= frag_len;
1785 
1786                             index++;
1787 
1788                             if (index == pgau->buf.num_fragments)
1789                             {
1790                                 return false;
1791                             }
1792 
1793                             frag_ptr = (uint8 *)pgau->buf.fragments[index].ptr;
1794                             frag_len = pgau->buf.fragments[index].len;
1795                         }
1796                     }
1797                     // Add to moov atom (in turn adds to tracks)
1798                     _pmovieAtom->addSampleToTrack(trackID, NULL,
1799                                                   (pgau->info[k].len + 1),
1800                                                   pgau->info[k].ts,
1801                                                   (uint8)pgau->info[k].sample_info);
1802                 }
1803             }
1804             else
1805             {
1806                 for (int32 k = 0; k < pgau->buf.num_fragments; k++)
1807                 {
1808                     // Add to mdat PVA_FF_Atom for the specified track
1809                     if (!mdatAtom->addRawSample(pgau->buf.fragments[k].ptr,
1810                                                 pgau->buf.fragments[k].len))
1811                     {
1812                         retVal = false;
1813                     }
1814                 }
1815 
1816                 for (uint32 j = 0; j < pgau->numMediaSamples; j++)
1817                 {
1818                     // Add to moov atom (in turn adds to tracks)
1819                     _pmovieAtom->addSampleToTrack(trackID, NULL,
1820                                                   pgau->info[j].len,
1821                                                   pgau->info[j].ts,
1822                                                   (uint8)pgau->info[j].sample_info);
1823                 }
1824             }
1825         }
1826     }
1827     else if (mediaType == MEDIA_TYPE_VISUAL)
1828     {
1829         if (_modifiable)
1830         {
1831             for (int32 k = 0; k < pgau->buf.num_fragments; k++)
1832             {
1833                 // Add to mdat PVA_FF_Atom for the specified track
1834                 if (!mdatAtom->addRawSample(pgau->buf.fragments[k].ptr,
1835                                             pgau->buf.fragments[k].len))
1836                 {
1837                     retVal = false;
1838                 }
1839             }
1840 
1841             for (uint32 j = 0; j < pgau->numMediaSamples; j++)
1842             {
1843                 // Add to moov atom (in turn adds to tracks)
1844                 _pmovieAtom->addSampleToTrack(trackID, NULL,
1845                                               pgau->info[j].len,
1846                                               pgau->info[j].ts,
1847                                               (uint8)pgau->info[j].sample_info);
1848             }
1849         }
1850     }
1851     else
1852     {
1853         return false;
1854     }
1855 
1856     return (retVal);
1857 }
1858 
1859 bool
renderTruncatedFile(PVA_FF_UNICODE_STRING_PARAM filename)1860 PVA_FF_Mpeg4File::renderTruncatedFile(PVA_FF_UNICODE_STRING_PARAM filename)
1861 {
1862     MP4_AUTHOR_FF_FILE_IO_WRAP fp;
1863 
1864     fp._osclFileServerSession = OSCL_STATIC_CAST(Oscl_FileServer*, _aFs);
1865 
1866     PVA_FF_AtomUtils::openFile(&fp, filename, Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY);
1867 
1868     if (fp._filePtr == NULL)
1869     {
1870         return false;
1871     }
1872     /*
1873      * Setting the major brand in ftyp atom
1874      */
1875 
1876     if (_o3GPPTrack)
1877     {
1878         setMajorBrand(BRAND_3GPP4);
1879         setMajorBrandVersion(VERSION_3GPP4);
1880     }
1881     else if (_oMPEGTrack)
1882     {
1883         setMajorBrand(BRAND_MPEG4);
1884         setMajorBrandVersion(VERSION_MPEG4);
1885     }
1886     else if (_oPVMMTrack)
1887     {
1888         setMajorBrand(PVMM_BRAND);
1889         setMajorBrandVersion(PVMM_VERSION);
1890     }
1891 
1892     /*
1893      * Add compatible brands
1894      */
1895     if (_o3GPPTrack)
1896     {
1897         addCompatibleBrand(BRAND_3GPP4);
1898     }
1899     if (_oPVMMTrack)
1900     {
1901         addCompatibleBrand(PVMM_BRAND);
1902     }
1903     if (_oMPEGTrack)
1904     {
1905         addCompatibleBrand(BRAND_MPEG4);
1906     }
1907     addCompatibleBrand(BRAND_3GPP5);
1908 
1909     if ((_o3GPPTrack == true) || (_oPVMMTrack == true) || (_oMPEGTrack == true))
1910     {
1911         _pFileTypeAtom->renderToFileStream(&fp);
1912     }
1913     {
1914         populateUserDataAtom();
1915         _puserDataAtom->renderToFileStream(&fp);
1916     }
1917     _oFileRenderCalled = true;
1918 
1919     PVA_FF_AtomUtils::closeFile(&fp);
1920 
1921     return true;
1922 }
1923 
1924 uint32
convertCreationTime(PVA_FF_UNICODE_STRING_PARAM creationDate)1925 PVA_FF_Mpeg4File::convertCreationTime(PVA_FF_UNICODE_STRING_PARAM creationDate)
1926 {
1927     uint32 numSecs = 0;
1928 
1929     uint32 numDaysInMonth[12] =
1930         {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1931 
1932     uint32 numDaysInLeapFeb = 29;
1933     uint32 refYear = 1904;
1934 
1935     // (365*4 + 1) * 24 * 3600
1936     uint32 numSecsInABlkofFourYears = 126230400;
1937 
1938     OSCL_TCHAR *date_ptr = (OSCL_TCHAR *)(creationDate.get_cstr());
1939 
1940     uint32 index = 0;
1941     uint32 currYear  = 0;
1942     uint32 month = 0;
1943     uint32 day   = 0;
1944     uint32 hour  = 0;
1945     uint32 minutes = 0;
1946     uint32 seconds = 0;
1947 
1948     bool nextChar = (date_ptr[index] == 0) ? false : true;
1949 
1950     char *c = (char *)(oscl_malloc(5 * sizeof(char)));
1951 
1952     uint8 s = 0;
1953     oscl_memset(c, 0, 5);
1954 
1955     while (nextChar && (index < 4))
1956     {
1957         c[s++] = (char)(date_ptr[index]);
1958 
1959         index++;
1960 
1961         nextChar = (date_ptr[index] == 0) ? false : true;
1962     }
1963 
1964     PV_atoi(c, 'd', currYear);
1965 
1966     if (currYear < refYear)
1967     {
1968         oscl_free(c);
1969         return 0;
1970     }
1971 
1972     if (index != 4)
1973     {
1974         oscl_free(c);
1975         return 0;
1976     }
1977 
1978     s = 0;
1979     oscl_memset(c, 0, 5);
1980 
1981     while (nextChar && (index < 6))
1982     {
1983         c[s++] = (char)(date_ptr[index]);
1984 
1985         index++;
1986 
1987         nextChar = (date_ptr[index] == 0) ? false : true;
1988     }
1989 
1990     PV_atoi(c, 'd', month);
1991 
1992     if (index  != 6)
1993     {
1994         oscl_free(c);
1995         return 0;
1996     }
1997 
1998     s = 0;
1999     oscl_memset(c, 0, 5);
2000 
2001     while (nextChar && (index < 8))
2002     {
2003         c[s++] = (char)(date_ptr[index]);
2004 
2005         index++;
2006 
2007         nextChar = (date_ptr[index] == 0) ? false : true;
2008     }
2009 
2010     PV_atoi(c, 'd', day);
2011 
2012     if (index  != 8)
2013     {
2014         oscl_free(c);
2015         return 0;
2016     }
2017 
2018     char val = (char)(date_ptr[index]);
2019 
2020     if (val != 'T')
2021     {
2022         oscl_free(c);
2023         return 0;
2024     }
2025     else
2026     {
2027         index++;
2028     }
2029 
2030     s = 0;
2031     oscl_memset(c, 0, 5);
2032 
2033     while (nextChar && (index < 11))
2034     {
2035         c[s++] = (char)(date_ptr[index]);
2036 
2037         index++;
2038 
2039         nextChar = (date_ptr[index] == 0) ? false : true;
2040     }
2041 
2042     PV_atoi(c, 'd', hour);
2043 
2044     if (index  != 11)
2045     {
2046         oscl_free(c);
2047         return 0;
2048     }
2049 
2050     s = 0;
2051     oscl_memset(c, 0, 5);
2052 
2053     while (nextChar && (index < 13))
2054     {
2055         c[s++] = (char)(date_ptr[index]);
2056 
2057         index++;
2058 
2059         nextChar = (date_ptr[index] == 0) ? false : true;
2060     }
2061 
2062     PV_atoi(c, 'd', minutes);
2063 
2064     if (index  != 13)
2065     {
2066         oscl_free(c);
2067         return 0;
2068     }
2069 
2070     s = 0;
2071     oscl_memset(c, 0, 5);
2072 
2073     while (nextChar && (index < 15))
2074     {
2075         c[s++] = (char)(date_ptr[index]);
2076 
2077         index++;
2078 
2079         nextChar = (date_ptr[index] == 0) ? false : true;
2080     }
2081 
2082     PV_atoi(c, 'd', seconds);
2083 
2084     uint32 deltaYears = currYear - refYear;
2085 
2086     uint32 numBlks = (deltaYears / 4);
2087 
2088     uint32 numLeftOverYears = (deltaYears - (numBlks * 4));
2089 
2090     numSecs = (numBlks * numSecsInABlkofFourYears);
2091 
2092     uint32 numDays = 0;
2093 
2094     if (numLeftOverYears > 1)
2095     {
2096         // Acct for leap year
2097         numDays = ((numLeftOverYears * 365) + 1);
2098 
2099         for (uint32 i = 0; i < month; i++)
2100         {
2101             numDays += numDaysInMonth[i];
2102         }
2103 
2104         numDays += day;
2105 
2106         uint32 numHours = (numDays * 24);
2107 
2108         numHours += hour;
2109 
2110         uint32 numMins = (numHours * 60);
2111 
2112         numMins += minutes;
2113 
2114         numSecs += ((numMins * 60) + seconds);
2115     }
2116     else
2117     {
2118         for (uint32 i = 0; i < month; i++)
2119         {
2120             if (i != 1)
2121                 numDays += numDaysInMonth[i];
2122             else
2123                 numDays += numDaysInLeapFeb;
2124         }
2125 
2126         numDays += day;
2127 
2128         uint32 numHours = (numDays * 24);
2129 
2130         numHours += hour;
2131 
2132         uint32 numMins = (numHours * 60);
2133 
2134         numMins += minutes;
2135 
2136         numSecs += ((numMins * 60) + seconds);
2137     }
2138 
2139     oscl_free(c);
2140 
2141     return (numSecs);
2142 }
2143 
2144 bool
checkInterLeaveDuration(uint32 trackID,uint32 ts)2145 PVA_FF_Mpeg4File::checkInterLeaveDuration(uint32 trackID, uint32 ts)
2146 {
2147     // get the interleave buffer for the track
2148     PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = getInterLeaveBuffer(trackID);
2149 
2150     PVA_FF_TrackAtom* mediaTrack = _pmovieAtom->getMediaTrack(trackID);
2151 
2152     uint32 lastChunkEndTime = pInterLeaveBuffer->getLastChunkEndTime();
2153 
2154     uint32 timescale = mediaTrack->getMediaTimeScale();
2155 
2156     uint32 interLeaveDurationInTrackTimeScale =
2157         (uint32)((_interLeaveDuration) * (timescale / 1000.0f));
2158 
2159     if ((ts - lastChunkEndTime) >= interLeaveDurationInTrackTimeScale)
2160     {
2161         pInterLeaveBuffer->setLastChunkEndTime(ts);
2162         return true;
2163     }
2164 
2165     return false;
2166 }
2167 
2168 bool
flushInterLeaveBuffer(uint32 trackID)2169 PVA_FF_Mpeg4File::flushInterLeaveBuffer(uint32 trackID)
2170 {
2171     uint32 mediaType;
2172     int32 codecType;
2173 
2174 
2175     PVA_FF_TrackAtom* mediaTrack = _pmovieAtom->getMediaTrack(trackID);
2176     PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = getInterLeaveBuffer(trackID);
2177     if ((NULL == mediaTrack) || (NULL == pInterLeaveBuffer))
2178     {
2179         // Returning true here might sound strange, however this is a valid case
2180         // where by tracks like odsm or sdsm might not have a valid mediaTrack
2181         // However if false is returned here, the function renderToFile will
2182         // break the for loops and return back.
2183         return true;
2184     }
2185     if (!(_oMovieFragmentEnabled && _oComposeMoofAtom))
2186     {
2187         PVA_FF_MediaDataAtom *mdatAtom = getMediaDataAtomForTrack(trackID);
2188 
2189         mediaType  = mediaTrack->getMediaType();
2190         codecType = _pmovieAtom->getCodecType(trackID);
2191 
2192         _oChunkStart = true;
2193 
2194         Oscl_Vector<uint32, OsclMemAllocator> *tsVec = pInterLeaveBuffer->getTimeStampVec();
2195 
2196         Oscl_Vector<uint32, OsclMemAllocator> *sizeVec = pInterLeaveBuffer->getSampleSizeVec();
2197 
2198         Oscl_Vector<uint8, OsclMemAllocator> *flagsVec = pInterLeaveBuffer->getFlagsVec();
2199 
2200         Oscl_Vector<int32, OsclMemAllocator> *indexVec = NULL;
2201 
2202         if (mediaType == MEDIA_TYPE_TEXT && codecType == CODEC_TYPE_TIMED_TEXT)
2203         {
2204             indexVec = pInterLeaveBuffer->getTextIndexVec();
2205         }
2206 
2207         int32 numBufferedSamples = tsVec->size();
2208 
2209         if (numBufferedSamples > 0)
2210         {
2211             for (int32 i = 0; i < numBufferedSamples; i++)
2212             {
2213                 if (mediaType == MEDIA_TYPE_TEXT && codecType == CODEC_TYPE_TIMED_TEXT)
2214                 {
2215                     uint32 sampleTS   = (*tsVec)[i];
2216                     uint32 sampleSize = (*sizeVec)[i];
2217                     uint8  sampleFlag = (*flagsVec)[i];
2218                     int32  sampleIndex = (*indexVec)[i];
2219 
2220                     // Add to moov atom (in turn adds to tracks)
2221                     _pmovieAtom->addTextSampleToTrack(trackID,
2222                                                       NULL,
2223                                                       sampleSize,
2224                                                       sampleTS,
2225                                                       sampleFlag,
2226                                                       sampleIndex,
2227                                                       _baseOffset,
2228                                                       _oChunkStart);
2229 
2230                 }
2231                 else
2232                 {
2233                     uint32 sampleTS   = (*tsVec)[i];
2234                     uint32 sampleSize = (*sizeVec)[i];
2235                     uint8  sampleFlag = (*flagsVec)[i];
2236 
2237                     // Add to moov atom (in turn adds to tracks)
2238                     _pmovieAtom->addSampleToTrack(trackID,
2239                                                   NULL,
2240                                                   sampleSize,
2241                                                   sampleTS,
2242                                                   sampleFlag,
2243                                                   _baseOffset,
2244                                                   _oChunkStart);
2245                 }
2246 
2247 
2248                 _oChunkStart = false;
2249             }
2250 
2251             //Render chunk
2252             uint32 chunkSize = 0;
2253             uint8* ptr = pInterLeaveBuffer->resetInterLeaveBuffer(chunkSize);
2254 
2255             if (!mdatAtom->addRawSample(ptr, chunkSize))
2256             {
2257                 return false;
2258             }
2259             _baseOffset += chunkSize;
2260         }
2261     }
2262     else
2263     {
2264         // add remaining samples as last TRUN in current track fragment
2265         PVA_FF_TrackFragmentAtom    *pCurrentTrackFragment;
2266         pCurrentTrackFragment = _pCurrentMoofAtom->getTrackFragment(trackID);
2267 
2268         // Set trun end time to the last sample TS
2269         // in the interleave buffer
2270 
2271         _oTrunStart = true;
2272 
2273         Oscl_Vector<uint32, OsclMemAllocator> *tsVec = pInterLeaveBuffer->getTimeStampVec();
2274 
2275         Oscl_Vector<uint32, OsclMemAllocator> *sizeVec = pInterLeaveBuffer->getSampleSizeVec();
2276 
2277         Oscl_Vector<uint8, OsclMemAllocator> *flagsVec = pInterLeaveBuffer->getFlagsVec();
2278 
2279         int32 numBufferedSamples = tsVec->size();
2280 
2281         int32 ii = 0;
2282 
2283         for (ii = 0; ii < numBufferedSamples; ii++)
2284         {
2285             uint32  sampleTS   = (*tsVec)[ii];
2286             uint32  sampleSize = (*sizeVec)[ii];
2287             uint8   sampleFlag = (*flagsVec)[ii];
2288             uint32  mediaType  = mediaTrack->getMediaType();
2289 
2290             // Add to moof atom (in turn adds to tracks)
2291             _pCurrentMoofAtom->addSampleToFragment(trackID, sampleSize, sampleTS,
2292                                                    sampleFlag,
2293                                                    _baseOffset,     // update data offset for each new trun
2294                                                    _oTrunStart);        // determine to add new trun or not
2295 
2296             // update movie duration in MVEX atom
2297             _pmovieAtom->updateMovieFragmentDuration(trackID, sampleTS);
2298 
2299             if (mediaType == MEDIA_TYPE_VISUAL)
2300             {
2301                 // make entry for every sync sample
2302                 uint8 codingType = (uint8)((sampleFlag >> 2) & 0x03);
2303                 if (codingType == CODING_TYPE_I)
2304                 {
2305                     // add video key frame as random sample entry
2306                     _pMfraAtom->addSampleEntry(trackID, sampleTS, _currentMoofOffset,
2307                                                _pCurrentMoofAtom->getTrackFragmentNumber(trackID),
2308                                                pCurrentTrackFragment->getTrunNumber(),
2309                                                (ii + 1));
2310                 }
2311             }
2312             else if (mediaType == MEDIA_TYPE_AUDIO && _oTrunStart == true)
2313             {
2314                 // add first audio sample in each TRUN as random sample entry
2315                 _pMfraAtom->addSampleEntry(trackID, sampleTS, _currentMoofOffset,
2316                                            _pCurrentMoofAtom->getTrackFragmentNumber(trackID),
2317                                            pCurrentTrackFragment->getTrunNumber(),
2318                                            (ii + 1));
2319 
2320             }
2321 
2322             _oTrunStart = false;
2323         }
2324 
2325         // update the last TS entry only if there is 1 sample in buffer
2326 
2327         if (numBufferedSamples == 1)
2328         {
2329             uint32 lastSampleTS = pInterLeaveBuffer->getLastSampleTS();
2330             uint32 ts = pInterLeaveBuffer->getLastChunkEndTime();
2331             pCurrentTrackFragment->updateLastTSEntry(ts + (ts - lastSampleTS));
2332             _pmovieAtom->updateMovieFragmentDuration(trackID, ts + (ts - lastSampleTS));
2333         }
2334         // make entry for last sample same as duration of second to last sample
2335         else
2336         {
2337             if (tsVec->size() > 1)
2338             {
2339                 uint32 delta = (*tsVec)[ii -1] - (*tsVec)[ii -2];
2340                 uint32 ts = (*tsVec)[ii -1];
2341                 pCurrentTrackFragment->updateLastTSEntry(ts + delta);
2342                 _pmovieAtom->updateMovieFragmentDuration(trackID, ts + delta);
2343             }
2344         }
2345 
2346 
2347         if (numBufferedSamples > 0)
2348         {
2349             //Render chunk
2350             uint32 trunSize = 0;
2351             uint8* ptr = pInterLeaveBuffer->resetInterLeaveBuffer(trunSize);
2352 
2353             if (!_pCurrentMediaDataAtom->addRawSample(ptr, trunSize))
2354             {
2355                 return false;
2356             }
2357             _baseOffset += trunSize;
2358         }
2359     }
2360 
2361     return true;
2362 }
2363 
2364 bool
getTargetFileSize(uint32 & metaDataSize,uint32 & mediaDataSize)2365 PVA_FF_Mpeg4File::getTargetFileSize(uint32 &metaDataSize, uint32 &mediaDataSize)
2366 {
2367     metaDataSize  = 0;
2368     mediaDataSize = 0;
2369 
2370     for (uint32 k = 0; k < _pmediaDataAtomVec->size(); k++)
2371     {
2372         mediaDataSize += (*_pmediaDataAtomVec)[k]->getMediaDataSize();
2373 
2374         Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
2375             (*_pmediaDataAtomVec)[k]->getTrackReferencePtrVec();
2376 
2377         if (trefVec != NULL)
2378         {
2379             for (uint32 trefVecIndex = 0;
2380                     trefVecIndex < trefVec->size();
2381                     trefVecIndex++)
2382             {
2383                 PVA_FF_TrackAtom* pTrack = (*trefVec)[trefVecIndex];
2384 
2385                 /*
2386                  * Account for media data that is remaining in the interleave
2387                  * buffers
2388                  */
2389                 if (_oInterLeaveEnabled)
2390                 {
2391                     uint32 trackID = pTrack->getTrackID();
2392                     PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = getInterLeaveBuffer(trackID);
2393                     if (pInterLeaveBuffer)
2394                     {
2395                         uint32 currInterLeaveBufferSize = pInterLeaveBuffer->getCurrentInterLeaveBufferSize();
2396 
2397                         mediaDataSize += currInterLeaveBufferSize;
2398                     }
2399                 }
2400             }
2401         }
2402     }
2403 
2404 
2405     if (_pFileTypeAtom != NULL)
2406     {
2407         metaDataSize += _pFileTypeAtom->getSize();
2408     }
2409 
2410     if (_pmovieAtom != NULL)
2411     {
2412         metaDataSize += _pmovieAtom->getSize();
2413     }
2414 
2415     metaDataSize += 1024; //Gaurd Band
2416 
2417     return true;
2418 }
2419 
2420 bool
prepareToEncode()2421 PVA_FF_Mpeg4File::prepareToEncode()
2422 {
2423     if (_oInterLeaveEnabled)
2424     {
2425         if (!_totalTempFileRemoval)
2426         {
2427             return true;
2428         }
2429     }
2430 
2431     /*
2432      * Setting the major brand in ftyp atom
2433      */
2434     if (_o3GPPTrack)
2435     {
2436         if (_oMovieFragmentEnabled)
2437         {
2438             setMajorBrand(BRAND_3GPP6);
2439             setMajorBrandVersion(VERSION_3GPP6);
2440         }
2441         else
2442         {
2443             setMajorBrand(BRAND_3GPP4);
2444             setMajorBrandVersion(VERSION_3GPP4);
2445         }
2446     }
2447     else if (_oMPEGTrack)
2448     {
2449         setMajorBrand(BRAND_MPEG4);
2450         setMajorBrandVersion(VERSION_MPEG4);
2451     }
2452     else if (_oPVMMTrack)
2453     {
2454         setMajorBrand(PVMM_BRAND);
2455         setMajorBrandVersion(PVMM_VERSION);
2456     }
2457 
2458     /*
2459      * Add compatible brands
2460      */
2461     if (_o3GPPTrack)
2462     {
2463         if (_oMovieFragmentEnabled)
2464             addCompatibleBrand(BRAND_3GPP6);
2465         else
2466             addCompatibleBrand(BRAND_3GPP4);
2467     }
2468     if (_oPVMMTrack)
2469     {
2470         addCompatibleBrand(PVMM_BRAND);
2471     }
2472     if (_oMPEGTrack)
2473     {
2474         addCompatibleBrand(BRAND_MPEG4);
2475     }
2476 
2477     if (!_oMovieFragmentEnabled)
2478     {
2479         addCompatibleBrand(BRAND_3GPP6);
2480     }
2481 
2482     _initialUserDataSize += _pFileTypeAtom->getSize();
2483 
2484     _oFtypPopulated = true;
2485 
2486     if (_oDirectRenderEnabled)
2487     {
2488         if ((_oSetTitleDone        == false) ||
2489                 (_oSetAuthorDone       == false) ||
2490                 (_oSetCopyrightDone    == false) ||
2491                 (_oSetDescriptionDone  == false) ||
2492                 (_oSetRatingDone       == false) ||
2493                 (_pmediaDataAtomVec->size() == 0))
2494         {
2495             // Requirements for this API not met
2496             return false;
2497         }
2498 
2499         /*
2500          * If VOL Header had not been set, use the pre defined
2501          * value.
2502          */
2503         for (uint32 j = 0; j < _pmediaDataAtomVec->size(); j++)
2504         {
2505             PVA_FF_TrackAtom *pTrack  =
2506                 (PVA_FF_TrackAtom *)((*_pmediaDataAtomVec)[j]->getTrackReferencePtr());
2507 
2508             uint32 codecType = pTrack->getCodecType();
2509             // uint32 trackID = pTrack->getTrackID();
2510             uint32 mediaType = pTrack->getMediaType();
2511 
2512             if (mediaType == MEDIA_TYPE_VISUAL)
2513             {
2514                 if (codecType == CODEC_TYPE_MPEG4_VIDEO)
2515                 {
2516                     if (!pTrack->IsDecoderSpecificInfoSet())
2517                     {
2518                         _initialUserDataSize +=
2519                             MAX_PV_BASE_SIMPLE_PROFILE_VOL_HEADER_SIZE;
2520                     }
2521                 }
2522             }
2523         }
2524         {
2525             populateUserDataAtom();
2526             _initialUserDataSize += _puserDataAtom->getSize();
2527         }
2528     }
2529 
2530     bool targetRender = false;
2531 
2532     for (uint32 j = 0; j < _pmediaDataAtomVec->size(); j++)
2533     {
2534         bool tempVal = ((*_pmediaDataAtomVec)[j]->IsTargetRender());
2535 
2536         if (tempVal)
2537         {
2538             if (targetRender)
2539             {
2540                 //Only one track is allowed to be rendered directly onto the target
2541                 //file
2542                 return false;
2543             }
2544             else
2545             {
2546                 targetRender = true;
2547                 ((*_pmediaDataAtomVec)[j]->prepareTargetFile(_initialUserDataSize));
2548             }
2549         }
2550     }
2551 
2552     return true;
2553 }
2554 
2555 void
populateUserDataAtom()2556 PVA_FF_Mpeg4File::populateUserDataAtom()
2557 {
2558     _oUserDataPopulated = true;
2559 }
2560 
2561 bool
addMediaSampleInterleave(uint32 trackID,Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> & fragmentList,uint32 size,uint32 ts,uint8 flags)2562 PVA_FF_Mpeg4File::addMediaSampleInterleave(uint32 trackID,
2563         Oscl_Vector < OsclMemoryFragment,
2564         OsclMemAllocator > & fragmentList,
2565         uint32 size, uint32 ts, uint8 flags)
2566 {
2567     PVA_FF_TrackAtom *mediaTrack = _pmovieAtom->getMediaTrack(trackID);
2568     PVA_FF_MediaDataAtom *mdatAtom = getMediaDataAtomForTrack(trackID);
2569     PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = getInterLeaveBuffer(trackID);
2570     int32 codecType = _pmovieAtom->getCodecType(trackID);
2571     uint32 mediaType = mediaTrack->getMediaType();
2572     int32 index = 0;
2573     if (true == _oComposeMoofAtom)
2574         _pmovieAtom->SetMaxSampleSize(trackID, size);
2575     if (_oFirstSampleEditMode)
2576     {
2577         _oChunkStart = true;
2578         /*
2579          * In this mode very first sample in each track is authored
2580          * in a separate chunk. It is easier to go back and edit the
2581          * sample meta data if we authored it in a seperate chunk by
2582          * itself.
2583          */
2584         if (mediaTrack->IsFirstSample())
2585         {
2586             // Add to moov atom (in turn adds to tracks)
2587             _pmovieAtom->addSampleToTrack(trackID,
2588                                           fragmentList,
2589                                           size,
2590                                           ts,
2591                                           flags,
2592                                           _baseOffset,
2593                                           _oChunkStart);
2594             _oChunkStart = false;
2595 
2596             if (!mdatAtom->addRawSample(fragmentList, size, mediaType, codecType))
2597             {
2598                 return false;
2599             }
2600             _baseOffset += size;
2601             return true;
2602         }
2603     }
2604 
2605     /* Movie Fragment : check if fragment duration reached for MOOV atom. If yes, allocate new
2606     movie fragment (MOOF) and write data in new media data atom.
2607     */
2608     if (_oMovieFragmentEnabled == true && _oComposeMoofAtom == false)
2609     {
2610         uint32 duration = _pmovieAtom->getDuration();
2611         uint32 duration_msec = (uint)((((float)duration / _pmovieAtom->getTimeScale()) * 1000.0f));
2612 
2613         if (duration_msec >= _movieFragmentDuration)
2614         {
2615             // render MOOV and MDAT atoms
2616             renderMoovAtom();
2617 
2618             _oComposeMoofAtom = true;
2619 
2620             // allocate Moof movie fragments
2621             PVA_FF_MovieFragmentAtom    *pMoofAtom;
2622             _sequenceNumber++;
2623             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MovieFragmentAtom, (_sequenceNumber,
2624                           _movieFragmentDuration,
2625                           _interLeaveDuration),
2626                           pMoofAtom);
2627 
2628             _pCurrentMoofAtom = pMoofAtom;
2629 
2630             // set Movie fragment duration
2631             _pmovieAtom->setMovieFragmentDuration();
2632 
2633             // add track fragments
2634             for (uint32 kk = 0; kk < _pmediaDataAtomVec->size(); kk++)
2635             {
2636                 // add track fragments from MDAT with interleaved data
2637                 if ((*_pmediaDataAtomVec)[kk]->IsTargetRender())
2638                 {
2639                     Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
2640                         (*_pmediaDataAtomVec)[kk]->getTrackReferencePtrVec();
2641 
2642                     if (trefVec != NULL)
2643                     {
2644                         for (uint32 trefVecIndex = 0; trefVecIndex < trefVec->size(); trefVecIndex++)
2645                         {
2646                             PVA_FF_TrackAtom* pTrack = (*trefVec)[trefVecIndex];
2647 
2648                             _pCurrentMoofAtom->addTrackFragment(pTrack->getMediaType(),
2649                                                                 pTrack->getCodecType(),
2650                                                                 pTrack->getTrackID(),
2651                                                                 pTrack->getMediaTimeScale());
2652 
2653                             // add random access atom for each track
2654                             _pMfraAtom->addTrackFragmentRandomAccessAtom(pTrack->getTrackID());
2655                         }
2656                     }
2657                 }
2658             }
2659 
2660             // form new MDAT atom
2661             PVA_FF_MediaDataAtom *pMdatAtom = NULL;
2662             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_targetFileHandle, _aFs, iCacheSize), pMdatAtom);
2663 
2664             _pCurrentMediaDataAtom = pMdatAtom;
2665 
2666             // current moof offset set at start of mdat, (later updated by size of mdat atom)
2667             _currentMoofOffset = _baseOffset;
2668 
2669             // base offset set to start of mdat (after fourcc code) as base data offset
2670             _baseOffset += _pCurrentMediaDataAtom->prepareTargetFileForFragments(_directRenderFileOffset);
2671 
2672         }
2673 
2674     }
2675 
2676     if (_oMovieFragmentEnabled == false || _oComposeMoofAtom == false)
2677     {
2678 
2679         if (!pInterLeaveBuffer->checkInterLeaveBufferSpace(size))
2680         {
2681             // Set Chunk end time to the last sample TS
2682             // in the interleave buffer
2683             pInterLeaveBuffer->setLastChunkEndTime(ts);
2684 
2685             _oChunkStart = true;
2686 
2687             Oscl_Vector<uint32, OsclMemAllocator> *tsVec =
2688                 pInterLeaveBuffer->getTimeStampVec();
2689 
2690             Oscl_Vector<uint32, OsclMemAllocator> *sizeVec =
2691                 pInterLeaveBuffer->getSampleSizeVec();
2692 
2693             Oscl_Vector<uint8, OsclMemAllocator> *flagsVec =
2694                 pInterLeaveBuffer->getFlagsVec();
2695 
2696             int32 numBufferedSamples = tsVec->size();
2697 
2698             for (int32 ii = 0; ii < numBufferedSamples; ii++)
2699             {
2700                 uint32 sampleTS   = (*tsVec)[ii];
2701                 uint32 sampleSize = (*sizeVec)[ii];
2702                 uint8  sampleFlag = (*flagsVec)[ii];
2703 
2704                 // Add to moov atom (in turn adds to tracks)
2705                 _pmovieAtom->addSampleToTrack(trackID,
2706                                               fragmentList,
2707                                               sampleSize,
2708                                               sampleTS,
2709                                               sampleFlag,
2710                                               _baseOffset,
2711                                               _oChunkStart);
2712 
2713                 _oChunkStart = false;
2714             }
2715 
2716             if (numBufferedSamples > 0)
2717             {
2718                 //Render chunk
2719                 uint32 chunkSize = 0;
2720                 uint8* ptr = pInterLeaveBuffer->resetInterLeaveBuffer(chunkSize);
2721 
2722                 if (!mdatAtom->addRawSample(ptr, chunkSize))
2723                 {
2724                     return false;
2725                 }
2726                 _baseOffset += chunkSize;
2727             }
2728 
2729             if (!(pInterLeaveBuffer->addSampleToInterLeaveBuffer(fragmentList,
2730                     size, ts, flags, index)))
2731             {
2732                 return false;
2733             }
2734         }
2735         else
2736         {
2737             if (checkInterLeaveDuration(trackID, ts))
2738             {
2739                 _oChunkStart = true;
2740 
2741                 Oscl_Vector<uint32, OsclMemAllocator> *tsVec =
2742                     pInterLeaveBuffer->getTimeStampVec();
2743 
2744                 Oscl_Vector<uint32, OsclMemAllocator> *sizeVec =
2745                     pInterLeaveBuffer->getSampleSizeVec();
2746 
2747                 Oscl_Vector<uint8, OsclMemAllocator> *flagsVec =
2748                     pInterLeaveBuffer->getFlagsVec();
2749 
2750                 int32 numBufferedSamples = tsVec->size();
2751 
2752                 for (int32 ii = 0; ii < numBufferedSamples; ii++)
2753                 {
2754                     uint32 sampleTS   = (*tsVec)[ii];
2755                     uint32 sampleSize = (*sizeVec)[ii];
2756                     uint8  sampleFlag = (*flagsVec)[ii];
2757 
2758                     // Add to moov atom (in turn adds to tracks)
2759                     _pmovieAtom->addSampleToTrack(trackID,
2760                                                   fragmentList,
2761                                                   sampleSize,
2762                                                   sampleTS,
2763                                                   sampleFlag,
2764                                                   _baseOffset,
2765                                                   _oChunkStart);
2766 
2767                     _oChunkStart = false;
2768                 }
2769 
2770                 if (numBufferedSamples > 0)
2771                 {
2772                     //Render chunk
2773                     uint32 chunkSize = 0;
2774                     uint8* ptr = pInterLeaveBuffer->resetInterLeaveBuffer(chunkSize);
2775 
2776                     if (!mdatAtom->addRawSample(ptr, chunkSize))
2777                     {
2778                         return false;
2779                     }
2780                     _baseOffset += chunkSize;
2781                 }
2782             }
2783             else
2784             {
2785                 _oChunkStart = false;
2786             }
2787 
2788             if (!(pInterLeaveBuffer->addSampleToInterLeaveBuffer(fragmentList,
2789                     size, ts, flags, index)))
2790             {
2791                 return false;
2792             }
2793         }
2794     }
2795     else
2796     {
2797         // add data in movie fragment
2798         uint32  trackFragmentDuration = _pCurrentMoofAtom->getTrackFragmentDuration(trackID);
2799 
2800         // check if Movie Fragment duration is reached for current fragment
2801         if (trackFragmentDuration < _movieFragmentDuration)
2802         {
2803             // add fragment to the current track fragment
2804 
2805             //check for interleaving in current track fragment
2806             PVA_FF_TrackFragmentAtom    *pCurrentTrackFragment;
2807             pCurrentTrackFragment = _pCurrentMoofAtom->getTrackFragment(trackID);
2808 
2809             if (!pInterLeaveBuffer->checkInterLeaveBufferSpace(size))
2810             {
2811                 // Set trun end time to the last sample TS
2812                 // in the interleave buffer
2813                 pInterLeaveBuffer->setLastChunkEndTime(ts);
2814 
2815                 _oTrunStart = true;
2816 
2817                 Oscl_Vector<uint32, OsclMemAllocator> *tsVec =
2818                     pInterLeaveBuffer->getTimeStampVec();
2819 
2820                 Oscl_Vector<uint32, OsclMemAllocator> *sizeVec =
2821                     pInterLeaveBuffer->getSampleSizeVec();
2822 
2823                 Oscl_Vector<uint8, OsclMemAllocator> *flagsVec =
2824                     pInterLeaveBuffer->getFlagsVec();
2825 
2826                 int32 numBufferedSamples = tsVec->size();
2827 
2828 
2829                 for (int32 ii = 0; ii < numBufferedSamples; ii++)
2830                 {
2831                     uint32 sampleTS   = (*tsVec)[ii];
2832                     uint32 sampleSize = (*sizeVec)[ii];
2833                     uint8  sampleFlag = (*flagsVec)[ii];
2834 
2835                     // Add to moof atom (in turn adds to tracks)
2836                     _pCurrentMoofAtom->addSampleToFragment(trackID, sampleSize, sampleTS,
2837                                                            sampleFlag,
2838                                                            _baseOffset,     // update data offset for each new trun
2839                                                            _oTrunStart);        // determine to add new trun or not
2840 
2841                     // update movie duration in MVEX atom
2842                     _pmovieAtom->updateMovieFragmentDuration(trackID, sampleTS);
2843 
2844                     if (mediaType == MEDIA_TYPE_VISUAL)
2845                     {
2846                         // make entry for every sync sample
2847                         uint8 codingType = (uint8)((sampleFlag >> 2) & 0x03);
2848                         if (codingType == CODING_TYPE_I)
2849                         {
2850                             // add video key frame as random sample entry
2851                             _pMfraAtom->addSampleEntry(trackID, sampleTS, _currentMoofOffset,
2852                                                        _pCurrentMoofAtom->getTrackFragmentNumber(trackID),
2853                                                        pCurrentTrackFragment->getTrunNumber(),
2854                                                        (ii + 1));
2855                         }
2856                     }
2857                     else if (mediaType == MEDIA_TYPE_AUDIO && _oTrunStart == true)
2858                     {
2859                         // add first audio sample in each TRUN as random sample entry
2860                         _pMfraAtom->addSampleEntry(trackID, sampleTS, _currentMoofOffset,
2861                                                    _pCurrentMoofAtom->getTrackFragmentNumber(trackID),
2862                                                    pCurrentTrackFragment->getTrunNumber(),
2863                                                    (ii + 1));
2864 
2865                     }
2866 
2867                     _oTrunStart = false;
2868                 }
2869 
2870                 pCurrentTrackFragment->updateLastTSEntry(ts);
2871 
2872                 if (numBufferedSamples > 0)
2873                 {
2874                     //Render chunk
2875                     uint32 trunSize = 0;
2876                     uint8* ptr = pInterLeaveBuffer->resetInterLeaveBuffer(trunSize);
2877 
2878                     if (!_pCurrentMediaDataAtom->addRawSample(ptr, trunSize))
2879                     {
2880                         return false;
2881                     }
2882                     _baseOffset += trunSize;
2883                 }
2884 
2885                 if (!(pInterLeaveBuffer->addSampleToInterLeaveBuffer(fragmentList, size, ts, flags, index)))
2886                 {
2887                     return false;
2888                 }
2889             }
2890             else
2891             {
2892                 if (checkInterLeaveDuration(trackID, ts))
2893                 {
2894                     _oTrunStart = true;
2895 
2896 
2897                     Oscl_Vector<uint32, OsclMemAllocator> *tsVec =
2898                         pInterLeaveBuffer->getTimeStampVec();
2899 
2900                     Oscl_Vector<uint32, OsclMemAllocator> *sizeVec =
2901                         pInterLeaveBuffer->getSampleSizeVec();
2902 
2903                     Oscl_Vector<uint8, OsclMemAllocator> *flagsVec =
2904                         pInterLeaveBuffer->getFlagsVec();
2905 
2906                     int32 numBufferedSamples = tsVec->size();
2907 
2908                     for (int32 ii = 0; ii < numBufferedSamples; ii++)
2909                     {
2910                         uint32 sampleTS   = (*tsVec)[ii];
2911                         uint32 sampleSize = (*sizeVec)[ii];
2912                         uint8  sampleFlag = (*flagsVec)[ii];
2913 
2914                         // update movie duration in MVEX atom
2915                         _pmovieAtom->updateMovieFragmentDuration(trackID, sampleTS);
2916 
2917                         // Add to moov atom (in turn adds to tracks)
2918                         _pCurrentMoofAtom->addSampleToFragment(trackID, sampleSize, sampleTS,
2919                                                                sampleFlag,
2920                                                                _baseOffset,
2921                                                                _oTrunStart);
2922 
2923                         if (mediaType == MEDIA_TYPE_VISUAL)
2924                         {
2925                             // make entry for every sync sample
2926                             uint8 codingType = (uint8)((sampleFlag >> 2) & 0x03);
2927                             if (codingType == CODING_TYPE_I)
2928                             {
2929                                 // add video key frame as random sample entry
2930                                 _pMfraAtom->addSampleEntry(trackID, sampleTS, _currentMoofOffset,
2931                                                            _pCurrentMoofAtom->getTrackFragmentNumber(trackID),
2932                                                            pCurrentTrackFragment->getTrunNumber(),
2933                                                            (ii + 1));
2934                             }
2935                         }
2936                         else if (mediaType == MEDIA_TYPE_AUDIO && _oTrunStart == true)
2937                         {
2938                             // add first audio sample in each TRUN as random sample entry
2939                             _pMfraAtom->addSampleEntry(trackID, sampleTS, _currentMoofOffset,
2940                                                        _pCurrentMoofAtom->getTrackFragmentNumber(trackID),
2941                                                        pCurrentTrackFragment->getTrunNumber(),
2942                                                        (ii + 1));
2943 
2944                         }
2945 
2946 
2947                         _oTrunStart = false;
2948                     }
2949 
2950                     pCurrentTrackFragment->updateLastTSEntry(ts);
2951 
2952                     if (numBufferedSamples > 0)
2953                     {
2954                         //Render chunk
2955                         uint32 trunSize = 0;
2956                         uint8* ptr = pInterLeaveBuffer->resetInterLeaveBuffer(trunSize);
2957 
2958                         if (!_pCurrentMediaDataAtom->addRawSample(ptr, trunSize))
2959                         {
2960                             return false;
2961                         }
2962                         _baseOffset += trunSize;
2963                     }
2964                 }
2965                 else
2966                 {
2967                     _oTrunStart = false;
2968                 }
2969 
2970                 if (!(pInterLeaveBuffer->addSampleToInterLeaveBuffer(fragmentList, size,
2971                         ts, flags, index)))
2972                 {
2973                     return false;
2974                 }
2975             }
2976         }
2977         else
2978         {
2979 
2980             // add sample
2981             if (!(pInterLeaveBuffer->addSampleToInterLeaveBuffer(fragmentList, size,
2982                     ts, flags, index)))
2983             {
2984                 return false;
2985             }
2986 
2987             uint32 kk = 0;
2988 
2989             // update last sample TS entry
2990             for (kk = 0; kk < _pmediaDataAtomVec->size(); kk++)
2991             {
2992                 if ((*_pmediaDataAtomVec)[kk]->IsTargetRender())
2993                 {
2994 
2995                     Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
2996                         (*_pmediaDataAtomVec)[kk]->getTrackReferencePtrVec();
2997 
2998                     if (trefVec != NULL)
2999                     {
3000                         for (uint32 trefVecIndex = 0; trefVecIndex < trefVec->size(); trefVecIndex++)
3001                         {
3002                             PVA_FF_TrackAtom* pTrack = (*trefVec)[trefVecIndex];
3003                             uint32 trackID = pTrack->getTrackID();
3004 
3005                             PVA_FF_TrackFragmentAtom    *pCurrentTrackFragment;
3006                             pCurrentTrackFragment = _pCurrentMoofAtom->getTrackFragment(trackID);
3007 
3008                             PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = getInterLeaveBuffer(trackID);
3009                             uint32 ts = pInterLeaveBuffer->getFirstTSEntry();
3010                             pCurrentTrackFragment->updateLastTSEntry(ts);
3011                         }
3012                     }
3013                 }
3014             }
3015 
3016             // close MDAT atom and render current fragment
3017             if (!renderMovieFragments())
3018             {
3019                 _fileWriteFailed = true;
3020                 return false;
3021             }
3022 
3023             // delete current moof atom
3024             PV_MP4_FF_DELETE(NULL, PVA_FF_MovieFragmentAtom, _pCurrentMoofAtom);
3025 
3026             // allocate new fragment
3027             PVA_FF_MovieFragmentAtom    *pMoofAtom;
3028             _sequenceNumber++;
3029             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MovieFragmentAtom, (_sequenceNumber,
3030                           _movieFragmentDuration,
3031                           _interLeaveDuration),
3032                           pMoofAtom);
3033             _pCurrentMoofAtom = pMoofAtom;
3034 
3035             // add track fragments
3036             for (kk = 0; kk < _pmediaDataAtomVec->size(); kk++)
3037             {
3038                 if ((*_pmediaDataAtomVec)[kk]->IsTargetRender())
3039                 {
3040                     Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
3041                         (*_pmediaDataAtomVec)[kk]->getTrackReferencePtrVec();
3042 
3043                     if (trefVec != NULL)
3044                     {
3045                         for (uint32 trefVecIndex = 0; trefVecIndex < trefVec->size(); trefVecIndex++)
3046                         {
3047                             PVA_FF_TrackAtom* pTrack = (*trefVec)[trefVecIndex];
3048 
3049                             _pCurrentMoofAtom->addTrackFragment(pTrack->getMediaType(),
3050                                                                 pTrack->getCodecType(),
3051                                                                 pTrack->getTrackID(),
3052                                                                 pTrack->getMediaTimeScale());
3053 
3054                         }
3055                     }
3056                 }
3057             }
3058 
3059             // delete current MDAT atom for movie fragment
3060             PV_MP4_FF_DELETE(NULL, PVA_FF_MediaDataAtom, _pCurrentMediaDataAtom);
3061 
3062             // form new MDAT atom
3063             PVA_FF_MediaDataAtom *pMdatAtom = NULL;
3064             PV_MP4_FF_NEW(fp->auditCB, PVA_FF_MediaDataAtom, (_targetFileHandle, _aFs, iCacheSize), pMdatAtom);
3065 
3066             _pCurrentMediaDataAtom = pMdatAtom;
3067 
3068             // current moof offset set at start of mdat, (later updated by size of mdat atom)
3069             _currentMoofOffset = _baseOffset;
3070 
3071             // base offset set to start of mdat (after fourcc code) as base data offset
3072             _baseOffset += _pCurrentMediaDataAtom->prepareTargetFileForFragments(_directRenderFileOffset);
3073 
3074         }
3075 
3076     }
3077     return true;
3078 
3079 }
3080 
3081 bool
addTextMediaSampleInterleave(uint32 trackID,Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> & fragmentList,uint32 size,uint32 ts,uint8 flags,int32 index)3082 PVA_FF_Mpeg4File::addTextMediaSampleInterleave(uint32 trackID,
3083         Oscl_Vector <OsclMemoryFragment, OsclMemAllocator>& fragmentList,
3084         uint32 size, uint32 ts, uint8 flags, int32 index)
3085 {
3086     PVA_FF_TrackAtom *mediaTrack = _pmovieAtom->getMediaTrack(trackID);
3087     PVA_FF_MediaDataAtom *mdatAtom = getMediaDataAtomForTrack(trackID);
3088     PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = getInterLeaveBuffer(trackID);
3089     int32 codecType = _pmovieAtom->getCodecType(trackID);
3090     uint32 mediaType  = mediaTrack->getMediaType();
3091 
3092     if (_oFirstSampleEditMode)
3093     {
3094         _oChunkStart = true;
3095         /*
3096          * In this mode very first sample in each track is authored
3097          * in a separate chunk. It is easier to go back and edit the
3098          * sample meta data if we authored it in a seperate chunk by
3099          * itself.
3100          */
3101         if (mediaTrack->IsFirstSample())
3102         {
3103             // Add to moov atom (in turn adds to tracks)
3104             _pmovieAtom->addTextSampleToTrack(trackID,
3105                                               fragmentList,
3106                                               size,
3107                                               ts,
3108                                               flags,
3109                                               index,
3110                                               _baseOffset,
3111                                               _oChunkStart);
3112             _oChunkStart = false;
3113 
3114             if (!mdatAtom->addRawSample(fragmentList, size, mediaType, codecType))
3115             {
3116                 return false;
3117             }
3118             _baseOffset += size;
3119             return true;
3120         }
3121     }
3122 
3123     if (!pInterLeaveBuffer->checkInterLeaveBufferSpace(size))
3124     {
3125         // Set Chunk end time to the last sample TS
3126         // in the interleave buffer
3127         pInterLeaveBuffer->setLastChunkEndTime();
3128 
3129         _oChunkStart = true;
3130 
3131         Oscl_Vector<uint32, OsclMemAllocator> *tsVec =
3132             pInterLeaveBuffer->getTimeStampVec();
3133 
3134         Oscl_Vector<uint32, OsclMemAllocator> *sizeVec =
3135             pInterLeaveBuffer->getSampleSizeVec();
3136 
3137         Oscl_Vector<uint8, OsclMemAllocator> *flagsVec =
3138             pInterLeaveBuffer->getFlagsVec();
3139 
3140         Oscl_Vector<int32, OsclMemAllocator> *indexVec =
3141             pInterLeaveBuffer->getTextIndexVec();
3142 
3143         int32 numBufferedSamples = tsVec->size();
3144 
3145         for (int32 i = 0; i < numBufferedSamples; i++)
3146         {
3147             uint32 sampleTS   = (*tsVec)[i];
3148             uint32 sampleSize = (*sizeVec)[i];
3149             uint8  sampleFlag = (*flagsVec)[i];
3150             int32 sampleIndex = (*indexVec)[i];
3151 
3152             // Add to moov atom (in turn adds to tracks)
3153             _pmovieAtom->addTextSampleToTrack(trackID,
3154                                               fragmentList,
3155                                               sampleSize,
3156                                               sampleTS,
3157                                               sampleFlag,
3158                                               sampleIndex,
3159                                               _baseOffset,
3160                                               _oChunkStart);
3161 
3162             _oChunkStart = false;
3163         }
3164 
3165         if (numBufferedSamples > 0)
3166         {
3167             //Render chunk
3168             uint32 chunkSize = 0;
3169             uint8* ptr =
3170                 pInterLeaveBuffer->resetInterLeaveBuffer(chunkSize);
3171 
3172             if (!mdatAtom->addRawSample(ptr, chunkSize))
3173             {
3174                 return false;
3175             }
3176             _baseOffset += chunkSize;
3177         }
3178 
3179         if (!(pInterLeaveBuffer->addSampleToInterLeaveBuffer(fragmentList,
3180                 size, ts, flags, index)))
3181         {
3182             return false;
3183         }
3184     }
3185     else
3186     {
3187         if (checkInterLeaveDuration(trackID, ts))
3188         {
3189             _oChunkStart = true;
3190 
3191             Oscl_Vector<uint32, OsclMemAllocator> *tsVec =
3192                 pInterLeaveBuffer->getTimeStampVec();
3193 
3194             Oscl_Vector<uint32, OsclMemAllocator> *sizeVec =
3195                 pInterLeaveBuffer->getSampleSizeVec();
3196 
3197             Oscl_Vector<uint8, OsclMemAllocator> *flagsVec =
3198                 pInterLeaveBuffer->getFlagsVec();
3199 
3200             Oscl_Vector<int32, OsclMemAllocator> *indexVec =
3201                 pInterLeaveBuffer->getTextIndexVec();
3202 
3203             int32 numBufferedSamples = tsVec->size();
3204 
3205             for (int32 i = 0; i < numBufferedSamples; i++)
3206             {
3207                 uint32 sampleTS   = (*tsVec)[i];
3208                 uint32 sampleSize = (*sizeVec)[i];
3209                 uint8  sampleFlag = (*flagsVec)[i];
3210                 int32 sampleIndex = (*indexVec)[i];
3211 
3212                 // Add to moov atom (in turn adds to tracks)
3213                 _pmovieAtom->addTextSampleToTrack(trackID,
3214                                                   fragmentList,
3215                                                   sampleSize,
3216                                                   sampleTS,
3217                                                   sampleFlag,
3218                                                   sampleIndex,
3219                                                   _baseOffset,
3220                                                   _oChunkStart);
3221 
3222 
3223 
3224                 _oChunkStart = false;
3225             }
3226 
3227             if (numBufferedSamples > 0)
3228             {
3229                 //Render chunk
3230                 uint32 chunkSize = 0;
3231                 uint8* ptr =
3232                     pInterLeaveBuffer->resetInterLeaveBuffer(chunkSize);
3233 
3234                 if (!mdatAtom->addRawSample(ptr, chunkSize))
3235                 {
3236                     return false;
3237                 }
3238                 _baseOffset += chunkSize;
3239             }
3240         }
3241         else
3242         {
3243             _oChunkStart = false;
3244         }
3245 
3246         if (!(pInterLeaveBuffer->addSampleToInterLeaveBuffer(fragmentList, size, ts, flags , index)))
3247         {
3248             return false;
3249         }
3250     }
3251 
3252     return true;
3253 }
3254 
3255 bool
reAuthorFirstSampleInTrack(uint32 trackID,uint8 * psample,uint32 size)3256 PVA_FF_Mpeg4File::reAuthorFirstSampleInTrack(uint32 trackID,
3257         uint8 *psample,
3258         uint32 size)
3259 {
3260     bool retVal = false;
3261     if (_oInterLeaveEnabled)
3262     {
3263         PVA_FF_TrackAtom *mediaTrack = _pmovieAtom->getMediaTrack(trackID);
3264         PVA_FF_MediaDataAtom *mdatAtom = getMediaDataAtomForTrack(trackID);
3265 
3266         mediaTrack = _pmovieAtom->getMediaTrack(trackID);
3267 
3268         // Add to moov atom (in turn adds to tracks)
3269         retVal =
3270             _pmovieAtom->reAuthorFirstSampleInTrack(trackID,
3271                                                     size,
3272                                                     _baseOffset);
3273 
3274         if (!mdatAtom->addRawSample(psample, size))
3275         {
3276             retVal = false;
3277         }
3278         else
3279         {
3280             _baseOffset += size;
3281         }
3282     }
3283     return retVal;
3284 }
3285 
3286 
3287 bool
renderMoovAtom()3288 PVA_FF_Mpeg4File::renderMoovAtom()
3289 {
3290     MP4_AUTHOR_FF_FILE_IO_WRAP fp;
3291     fp._filePtr = NULL;
3292     fp._osclFileServerSession = NULL;
3293 
3294     //make sure to flush the interleave buffers, be it to temp files
3295     //or to target files
3296     uint32 kk = 0;
3297 
3298     for (kk = 0; kk < _pmediaDataAtomVec->size(); kk++)
3299     {
3300         Oscl_Vector<PVA_FF_TrackAtom*, OsclMemAllocator> *trefVec =
3301             (*_pmediaDataAtomVec)[kk]->getTrackReferencePtrVec();
3302 
3303         if (trefVec != NULL)
3304         {
3305             for (uint32 trefVecIndex = 0; trefVecIndex < trefVec->size(); trefVecIndex++)
3306             {
3307                 PVA_FF_TrackAtom* pTrack = (*trefVec)[trefVecIndex];
3308                 uint32 trackID = pTrack->getTrackID();
3309                 PVA_FF_InterLeaveBuffer *pInterLeaveBuffer = getInterLeaveBuffer(trackID);
3310                 if (pInterLeaveBuffer != NULL)
3311                 {
3312                     uint32 ts = pInterLeaveBuffer->getFirstTSEntry();
3313                     pTrack->updateLastTSEntry(ts);
3314                 }
3315             }
3316         }
3317     }
3318 
3319     bool targetRender = false;
3320     _directRenderFileOffset = 0;
3321 
3322     if ((_oDirectRenderEnabled) || (_totalTempFileRemoval))
3323     {
3324         for (uint32 kk = 0; kk < _pmediaDataAtomVec->size(); kk++)
3325         {
3326             bool tempVal = ((*_pmediaDataAtomVec)[kk]->IsTargetRender());
3327 
3328             if (tempVal)
3329             {
3330                 if (targetRender)
3331                 {
3332                     //Only one track is allowed to be rendered directly onto the target
3333                     //file
3334                     return false;
3335                 }
3336                 else
3337                 {
3338                     targetRender = true;
3339 
3340                     if (!((*_pmediaDataAtomVec)[kk]->closeTargetFile()))
3341                     {
3342                         return false;
3343                     }
3344 
3345                     fp._filePtr = ((*_pmediaDataAtomVec)[kk]->getTargetFilePtr());
3346                     fp._osclFileServerSession = OSCL_STATIC_CAST(Oscl_FileServer*, _aFs);
3347 
3348                     _directRenderFileOffset =
3349                         ((*_pmediaDataAtomVec)[kk]->getTotalDataRenderedToTargetFileInDirectRenderMode());
3350                 }
3351             }
3352         }
3353     }
3354 
3355     if (fp._filePtr == NULL)
3356     {
3357         return false;
3358     }
3359 
3360     if (!renderToFileStream(&fp))
3361     {
3362         return false;
3363     }
3364     _directRenderFileOffset = PVA_FF_AtomUtils::getCurrentFilePosition(&fp);    // hereafter movie fragments are written
3365     _baseOffset = _directRenderFileOffset;  // base offset is used to set base data offset of Moof
3366 
3367 
3368     // store target file handle used to write further movie fragments
3369     _targetFileHandle = fp._filePtr;
3370 
3371     return true;
3372 }
3373 
3374 bool
renderMovieFragments()3375 PVA_FF_Mpeg4File::renderMovieFragments()
3376 {
3377     uint32 size;
3378 
3379     uint32 fileWriteOffset;
3380 
3381     MP4_AUTHOR_FF_FILE_IO_WRAP fp;
3382 
3383     fp._filePtr = _pCurrentMediaDataAtom->getTargetFilePtr();
3384     fp._osclFileServerSession = OSCL_STATIC_CAST(Oscl_FileServer*, _aFs);
3385 
3386     fileWriteOffset = PVA_FF_AtomUtils::getCurrentFilePosition(&fp);
3387 
3388     _pCurrentMediaDataAtom->closeTargetFile();
3389 
3390     size = _pCurrentMediaDataAtom->getMediaDataSize();
3391 
3392     _pMfraAtom->updateMoofOffset(size);
3393 
3394     PVA_FF_AtomUtils::seekFromStart(&fp, fileWriteOffset);
3395 
3396 
3397     if (!(_pCurrentMoofAtom->renderToFileStream(&fp)))
3398     {
3399         return false;
3400     }
3401 
3402     _directRenderFileOffset = PVA_FF_AtomUtils::getCurrentFilePosition(&fp);    // hereafter further movie fragments are written
3403     _baseOffset = _directRenderFileOffset;  // base offset is used to set base data offset of Moof
3404 
3405     return true;
3406 }
3407 
3408 
3409 void
addInterLeaveBuffer(PVA_FF_InterLeaveBuffer * pInterLeaveBuffer)3410 PVA_FF_Mpeg4File::addInterLeaveBuffer(PVA_FF_InterLeaveBuffer   *pInterLeaveBuffer)
3411 {
3412     if (_oInterLeaveEnabled)
3413     {
3414         if (_modifiable)
3415         {
3416             _pInterLeaveBufferVec->push_back(pInterLeaveBuffer);
3417         }
3418     }
3419 }
3420 
3421 
3422 
3423 PVA_FF_InterLeaveBuffer*
getInterLeaveBuffer(uint32 trackID)3424 PVA_FF_Mpeg4File::getInterLeaveBuffer(uint32    trackID)
3425 {
3426     if (_pInterLeaveBufferVec->size() > 0)
3427     {
3428         for (uint32 ii = 0; ii < _pInterLeaveBufferVec->size(); ii++)
3429         {
3430             if ((*_pInterLeaveBufferVec)[ii]->getTrackID() == trackID)
3431                 return (*_pInterLeaveBufferVec)[ii];
3432         }
3433     }
3434     return NULL;
3435 }
3436 
3437 void
setAudioEncodeParams(uint32 trackId,PVMP4FFComposerAudioEncodeParams & audioParams)3438 PVA_FF_Mpeg4File::setAudioEncodeParams(uint32 trackId,
3439                                        PVMP4FFComposerAudioEncodeParams &audioParams)
3440 {
3441     PVA_FF_TrackAtom *trackAtom;
3442     trackAtom = _pmovieAtom->getMediaTrack(trackId);
3443 
3444     if (trackAtom != NULL)
3445         trackAtom->setAudioEncodeParams(audioParams);
3446 
3447     return;
3448 }
3449 
3450 
3451 
3452 
3453