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 /*     -------------------------------------------------------------------       */
     20 /*                            MPEG-4 Track Fragment Atom Class                             */
     21 /*     -------------------------------------------------------------------       */
     22 /*********************************************************************************/
     23 /*
     24 */
     25 
     26 #define IMPLEMENT_MovieFragmentRandomAccessAtom
     27 
     28 #include "atomdefs.h"
     29 #include "atomutils.h"
     30 #include "moviefragmentrandomaccess.h"
     31 
     32 typedef Oscl_Vector<TrackFragmentRandomAccessAtom*, OsclMemAllocator> trackFragmentRandomAccessAtomVecType;
     33 
     34 // Constructor
     35 MovieFragmentRandomAccessAtom::MovieFragmentRandomAccessAtom(MP4_FF_FILE *fp,
     36         uint32 size,
     37         uint32 type)
     38         : Atom(fp, size, type)
     39 {
     40     _pTrackFragmentRandomAccessAtomVec      = NULL;
     41     _pMfraOffsetAtom = NULL;
     42 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT)
     43     // This will store the entry count of TFRA for Video for Vonly,AVT,AV,VT clips and Audio TFRA entry count for Aonly,AT clips
     44     // and Text TFRA entry count for Tonly clips.
     45     oVideoAudioTextTrackTfraCount = 0;
     46 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT
     47 
     48     iLogger = PVLogger::GetLoggerObject("mp4ffparser");
     49     iStateVarLogger = PVLogger::GetLoggerObject("mp4ffparser_mediasamplestats");
     50     iParsedDataLogger = PVLogger::GetLoggerObject("mp4ffparser_parseddata");
     51 
     52     uint32 count = size - DEFAULT_ATOM_SIZE;
     53     if (_success)
     54     {
     55         PV_MP4_FF_NEW(fp->auditCB, trackFragmentRandomAccessAtomVecType, (), _pTrackFragmentRandomAccessAtomVec);
     56         while (count > 0)
     57         {
     58             uint32 atomType = UNKNOWN_ATOM;
     59             uint32 atomSize = 0;
     60             AtomUtils::getNextAtomType(fp, atomSize, atomType);
     61 
     62             if (atomType == MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_ATOM)
     63             {
     64                 if (_pMfraOffsetAtom == NULL)
     65                 {
     66                     PV_MP4_FF_NEW(fp->auditCB, MfraOffsetAtom, (fp, atomSize, atomType), _pMfraOffsetAtom);
     67                     if (!_pMfraOffsetAtom->MP4Success())
     68                     {
     69                         _success = false;
     70                         _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_OFFSET_FAILED;
     71                         return;
     72                     }
     73                     count -= _pMfraOffsetAtom->getSize();
     74                 }
     75                 else
     76                 {
     77                     //duplicate atom
     78                     count -= atomSize;
     79                     atomSize -= DEFAULT_ATOM_SIZE;
     80                     AtomUtils::seekFromCurrPos(fp, atomSize);
     81                 }
     82             }
     83             else if (atomType == TRACK_FRAGMENT_RANDOM_ACCESS_ATOM)
     84             {
     85                 TrackFragmentRandomAccessAtom *pTrackFragmentRandomAccessAtom = NULL;
     86                 PV_MP4_FF_NEW(fp->auditCB, TrackFragmentRandomAccessAtom, (fp, atomSize, atomType),
     87                               pTrackFragmentRandomAccessAtom);
     88                 if (!pTrackFragmentRandomAccessAtom->MP4Success())
     89                 {
     90                     PV_MP4_FF_DELETE(NULL, TrackFragmentRandomAccessAtom, pTrackFragmentRandomAccessAtom);
     91                     _success = false;
     92                     _mp4ErrorCode = READ_TRACK_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
     93                     return;
     94                 }
     95                 count -= pTrackFragmentRandomAccessAtom->getSize();
     96                 _pTrackFragmentRandomAccessAtomVec->push_back(pTrackFragmentRandomAccessAtom);
     97             }
     98 
     99         }
    100     }
    101     else
    102     {
    103         _mp4ErrorCode = READ_MOVIE_FRAGMENT_RANDOM_ACCESS_ATOM_FAILED;
    104     }
    105 }
    106 
    107 MovieFragmentRandomAccessAtom::~MovieFragmentRandomAccessAtom()
    108 {
    109     if (_pMfraOffsetAtom != NULL)
    110     {
    111         PV_MP4_FF_DELETE(NULL, MfraOffsetAtom, _pMfraOffsetAtom);
    112     }
    113 
    114     for (uint32 i = 0; i < _pTrackFragmentRandomAccessAtomVec->size(); i++)
    115     {
    116         PV_MP4_FF_DELETE(NULL, TrackFragmentRandomAccessAtom, (*_pTrackFragmentRandomAccessAtomVec)[i]);
    117     }
    118     PV_MP4_FF_TEMPLATED_DELETE(NULL, trackFragmentRandomAccessAtomVecType, Oscl_Vector, _pTrackFragmentRandomAccessAtomVec);
    119 
    120 }
    121 
    122 bool MovieFragmentRandomAccessAtom::IsTFRAPresentForTrack(uint32 trackID, bool oVideoAudioTextTrack)
    123 {
    124 
    125     uint32 num_tfra = 0;
    126     if (_pTrackFragmentRandomAccessAtomVec != NULL)
    127     {
    128         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
    129         for (uint32 idx = 0; idx < num_tfra; idx++)
    130         {
    131             TrackFragmentRandomAccessAtom *tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
    132             if (tfraAtom->getTrackID() == trackID)
    133             {
    134                 if (tfraAtom->_entry_count > 0)
    135                 {
    136 #if (DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT)
    137                     if (oVideoAudioTextTrack)
    138                     {
    139                         oVideoAudioTextTrackTfraCount = tfraAtom->_entry_count;
    140                         // If oVideoAudioTextTrack flag is set we just store the entry count to be checked
    141                         // for other tracks.
    142                         return true;
    143                     }
    144                     else if (oVideoAudioTextTrackTfraCount == tfraAtom->_entry_count)
    145 #else
    146                     OSCL_UNUSED_ARG(oVideoAudioTextTrack);
    147 #endif // DISABLE_REPOS_ON_CLIPS_HAVING_UNEQUAL_TFRA_ENTRY_COUNT
    148                     {
    149                         return true;
    150                     }
    151                 }
    152             }
    153         }
    154     }
    155     return false;
    156 
    157 }
    158 int32 MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime(uint32 trackID, uint32 &time, uint32 &moof_offset,
    159         uint32 &traf_number, uint32 &trun_number,
    160         uint32 &sample_num)
    161 {
    162     uint32 num_tfra = 0;
    163     PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Input Time =%d", time));
    164     if (_pTrackFragmentRandomAccessAtomVec == NULL)
    165     {
    166         return -1;
    167     };
    168     num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
    169     for (uint32 idx = 0; idx < num_tfra; idx++)
    170     {
    171         TrackFragmentRandomAccessAtom *tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
    172         if (! tfraAtom)     // (unlikely)
    173             return -1;
    174         if (tfraAtom->getTrackID() == trackID)
    175         {
    176             uint32 entries = tfraAtom->_entry_count;
    177             if (entries == 0)
    178                 return -1;
    179 
    180             Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
    181             if (!tfraEntries)       // unlikely/error
    182                 return -1;
    183             int32 prevTime = 0;
    184             for (uint32 idy = 0; idy < entries; idy++)
    185             {
    186                 if (time < (*tfraEntries)[idy]->getTimeStamp())
    187                 {
    188                     uint32 tmp = (*tfraEntries)[idy]->getTimeStamp();
    189                     uint32 diffwithbeforeTS = time - prevTime;
    190                     uint32 diffwithafterTS = tmp - time;
    191                     if (diffwithbeforeTS > diffwithafterTS)
    192                     {
    193                         time = tmp;
    194                         moof_offset = (*tfraEntries)[idy]->getTimeMoofOffset();
    195                         traf_number = (*tfraEntries)[idy]->_traf_number;
    196                         trun_number = (*tfraEntries)[idy]->_trun_number;
    197                         sample_num = (*tfraEntries)[idy]->_sample_number;
    198                         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
    199                         return 0;
    200                     }
    201                     else
    202                     {
    203                         time = prevTime;
    204                         PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
    205                         return 0;
    206                     }
    207                 }
    208                 moof_offset = (*tfraEntries)[idy]->getTimeMoofOffset();
    209                 traf_number = (*tfraEntries)[idy]->_traf_number;
    210                 trun_number = (*tfraEntries)[idy]->_trun_number;
    211                 sample_num = (*tfraEntries)[idy]->_sample_number;
    212 
    213                 prevTime = (*tfraEntries)[idy]->getTimeStamp();
    214             }
    215             time = prevTime;
    216             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
    217             return 0;
    218         }
    219     }
    220 
    221     // error return if we get here.
    222     return -1;
    223 }
    224 
    225 int32 MovieFragmentRandomAccessAtom::queryRepositionTime(uint32 trackID, int32 time, bool oDependsOn, bool bBeforeRequestedTime)
    226 {
    227     OSCL_UNUSED_ARG(oDependsOn);
    228 
    229     uint32 num_tfra = 0;
    230     int32 closestTime = 0;
    231     PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Input Time =%d", time));
    232     if (_pTrackFragmentRandomAccessAtomVec != NULL)
    233     {
    234         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
    235         for (uint32 idx = 0; idx < num_tfra; idx++)
    236         {
    237             TrackFragmentRandomAccessAtom* tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
    238             if (tfraAtom->getTrackID() == trackID)
    239             {
    240                 uint32 entries = tfraAtom->_entry_count;
    241                 Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
    242                 if (!tfraEntries)   // unlikely/error
    243                     return closestTime;
    244                 int32 prevTime = 0;
    245                 for (uint32 idy = 0; idy < entries; idy++)
    246                 {
    247                     if (bBeforeRequestedTime)
    248                     {
    249                         if (time < (int32)(*tfraEntries)[idy]->getTimeStamp())
    250                         {
    251                             time = prevTime;
    252                             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
    253                             break;
    254                         }
    255                         else if ((time == (int32)(*tfraEntries)[idy]->getTimeStamp()) ||
    256                                  ((idy == (entries - 1)) && (time > (int32)(*tfraEntries)[idy]->getTimeStamp())))
    257                         {
    258                             time = (*tfraEntries)[idy]->getTimeStamp();
    259                             break;
    260 
    261                         }
    262                         prevTime = (*tfraEntries)[idy]->getTimeStamp();
    263                     }
    264                     else
    265                     {
    266                         if (time <= (int32)(*tfraEntries)[idy]->getTimeStamp())
    267                         {
    268                             time = (*tfraEntries)[idy]->getTimeStamp();
    269                             PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
    270                             break;
    271                         }
    272                         else if ((idy == (entries - 1)) && (time > (int32)(*tfraEntries)[idy]->getTimeStamp()))
    273                         {
    274                             time = (*tfraEntries)[idy]->getTimeStamp();
    275                             break;
    276 
    277                         }
    278 
    279                         prevTime = (*tfraEntries)[idy]->getTimeStamp();
    280 
    281                     }
    282                 }
    283                 closestTime = time;
    284                 PVMF_MP4FFPARSER_LOGMEDIASAMPELSTATEVARIABLES((0, "MovieFragmentRandomAccessAtom::getSyncSampleInfoClosestToTime Return Time =%d", time));
    285                 return closestTime;
    286             }
    287         }
    288     }
    289     return closestTime;
    290 }
    291 
    292 int32 MovieFragmentRandomAccessAtom::getTimestampForRandomAccessPoints(uint32 id, uint32 *num, uint32 *tsBuf, uint32* numBuf, uint32* offsetBuff, uint32 samplesFromMovie)
    293 {
    294     uint32 num_tfra = 0;
    295     uint32 samplesfromMoov = samplesFromMovie;
    296     TrackFragmentRandomAccessAtom *tfraAtom = NULL;
    297 
    298     if (_pTrackFragmentRandomAccessAtomVec != NULL)
    299     {
    300         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
    301 
    302         for (uint32 idx = 0; idx < num_tfra; idx++)
    303         {
    304             tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
    305             if (tfraAtom->getTrackID() == id)
    306             {
    307                 break;
    308             }
    309         }
    310     }
    311     if (tfraAtom != NULL)
    312     {
    313         uint32 entries = tfraAtom->_entry_count;
    314         Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
    315         if (!tfraEntries)       // unlikely/error
    316             return 0;
    317 
    318 
    319         uint32 tmp = entries;
    320 
    321         if (*num == 0)
    322         {
    323             *num = tmp;
    324             return 1;   //success. This is only the query mode.
    325         }
    326 
    327         uint32 sampleToBeRead = *num;
    328         if (tmp < sampleToBeRead)
    329             sampleToBeRead = tmp;
    330 
    331         for (uint32 idx = samplesfromMoov; idx < sampleToBeRead + samplesfromMoov; idx++)
    332         {
    333             //it may crash if this buffer is not big enough
    334             if (tsBuf != NULL)
    335                 tsBuf[idx] = (*tfraEntries)[idx]->getTimeStamp();
    336             if (numBuf)
    337                 numBuf[idx] = (*tfraEntries)[idx]->_sample_number;
    338             if (offsetBuff)
    339                 offsetBuff[idx] = (*tfraEntries)[idx]->getTimeMoofOffset();
    340         }
    341         *num = sampleToBeRead + samplesfromMoov;
    342 
    343         return  1;  //success
    344     }
    345     return 0;
    346 }
    347 
    348 
    349 int32 MovieFragmentRandomAccessAtom::getTimestampForRandomAccessPointsBeforeAfter(uint32 id, uint32 ts, uint32 *tsBuf, uint32* numBuf,
    350         uint32& numsamplestoget,
    351         uint32 howManyKeySamples)
    352 {
    353     uint32 num_tfra = 0, prevSampleNum = 0, sample_num = 0;
    354     uint32 time = ts;
    355     uint32 startIdx = 0, endIdx = 0;
    356 
    357     TrackFragmentRandomAccessAtom *tfraAtom = NULL;
    358     if (_pTrackFragmentRandomAccessAtomVec != NULL)
    359     {
    360         num_tfra = _pTrackFragmentRandomAccessAtomVec->size();
    361 
    362         for (uint32 idx = 0; idx < num_tfra; idx++)
    363         {
    364             tfraAtom = (*_pTrackFragmentRandomAccessAtomVec)[idx];
    365             if (tfraAtom != NULL)
    366             {
    367                 if (tfraAtom->getTrackID() == id)
    368                 {
    369                     break;
    370                 }
    371             }
    372         }
    373     }
    374     if (tfraAtom != NULL)
    375     {
    376         uint32 entries = tfraAtom->_entry_count;
    377         startIdx = entries;
    378         endIdx = entries;
    379         Oscl_Vector<TFRAEntries*, OsclMemAllocator>* tfraEntries = tfraAtom->getTrackFragmentRandomAccessEntries();
    380         if (!tfraEntries)       // unlikely/error
    381             return 0;
    382         int32 prevTime = 0;
    383         for (uint32 idy = 0; idy < entries; idy++)
    384         {
    385             if (time <= (*tfraEntries)[idy]->getTimeStamp())
    386             {
    387                 uint32 tmp = (*tfraEntries)[idy]->getTimeStamp();
    388                 uint32 diffwithbeforeTS = time - prevTime;
    389                 uint32 diffwithafterTS = tmp - time;
    390                 if (diffwithbeforeTS > diffwithafterTS)
    391                 {
    392                     sample_num = (*tfraEntries)[idy]->_sample_number;
    393                 }
    394                 else
    395                 {
    396                     sample_num = prevSampleNum;
    397                 }
    398                 startIdx = idy;
    399                 endIdx = entries;
    400                 break;
    401             }
    402             prevSampleNum = (*tfraEntries)[idy]->_sample_number;
    403             prevTime = (*tfraEntries)[idy]->getTimeStamp();
    404         }
    405         if ((startIdx + howManyKeySamples) <= entries)
    406             endIdx = startIdx + howManyKeySamples;
    407 
    408         if (startIdx > howManyKeySamples)
    409             startIdx -= howManyKeySamples;
    410         else
    411         {
    412             startIdx = 0;
    413         }
    414 
    415         uint32 idx = 0;
    416         uint32 k = 0;
    417         for (idx = startIdx; idx < endIdx; idx++)
    418         {
    419             int32 keySampleNum = (*tfraEntries)[idx]->_sample_number;
    420             int32 keySampleTS = (*tfraEntries)[idx]->getTimeStamp();
    421             numBuf[k] = keySampleNum;
    422             tsBuf[k] = keySampleTS;
    423             k++;
    424         }
    425         numsamplestoget = k;
    426     }
    427     else
    428         return 0;
    429 
    430     return  1;  //success
    431 
    432 }
    433