Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 /*
     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
     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
    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 
    191 void PVA_FF_Mpeg4File::SetCacheSize(uint32 aCacheSize)
    192 {
    193     iCacheSize = aCacheSize;
    194 }
    195 bool
    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
    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
    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
    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
    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
    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
    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
    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
    725 PVA_FF_Mpeg4File::setMovieFragmentDuration(uint32 duration)
    726 {
    727     _movieFragmentDuration = duration;
    728     return;
    729 }
    730 
    731 
    732 
    733 uint32
    734 PVA_FF_Mpeg4File::getMovieFragmentDuration()
    735 {
    736     return  _movieFragmentDuration;
    737 }
    738 
    739 
    740 bool
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   1148 PVA_FF_Mpeg4File::setAlbumTrackNumber(uint8 trackNumber)
   1149 {
   1150     if (_pmovieAtom != NULL)
   1151     {
   1152         _pmovieAtom->setAlbumTrackNumber(trackNumber);
   1153     }
   1154 }
   1155 
   1156 void
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   1674 PVA_FF_Mpeg4File::SetTempOutputPath(PVA_FF_UNICODE_STRING_PARAM outputPath)
   1675 {
   1676     _tempOutputPath = (_STRLIT(""));
   1677     _tempOutputPath += outputPath;
   1678 }
   1679 
   1680 PVA_FF_MediaDataAtom*
   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
   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
   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
   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
   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
   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
   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
   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
   2556 PVA_FF_Mpeg4File::populateUserDataAtom()
   2557 {
   2558     _oUserDataPopulated = true;
   2559 }
   2560 
   2561 bool
   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
   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
   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
   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
   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
   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*
   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
   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