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 IMpeg4File Class                            */
     21 /*     -------------------------------------------------------------------       */
     22 /*********************************************************************************/
     23 /*
     24     The IMpeg4File Class is INTERFACE that exsposes only those necessary
     25     methods of the underlying Mpeg4File class.
     26 */
     27 
     28 #define IMPLEMENT_IMpeg4File_H__
     29 
     30 #define GENERIC_ATOM_SIZE 8
     31 
     32 #ifndef OSCL_FILE_IO_H_INCLUDED
     33 #include "oscl_file_io.h"
     34 #endif
     35 
     36 #include "atom.h"
     37 #include "atomutils.h"
     38 #include "atomdefs.h"
     39 
     40 #include "pvuserdataatom.h"
     41 #include "oscl_utf8conv.h"
     42 #include "isucceedfail.h"
     43 
     44 #include "impeg4file.h"
     45 #include "mpeg4file.h"
     46 
     47 #include "oscl_string.h"
     48 
     49 
     50 // Use default DLL entry point for Symbian
     51 #include "oscl_dll.h"
     52 OSCL_DLL_ENTRY_POINT_DEFAULT()
     53 
     54 
     55 /* ======================================================================== */
     56 OSCL_EXPORT_REF  IMpeg4File *IMpeg4File::readMP4File(OSCL_wString& aFilename,
     57         PVMFCPMPluginAccessInterfaceFactory* aCPMAccessFactory,
     58         OsclFileHandle* aHandle,
     59         uint32 aParsingMode,
     60         Oscl_FileServer* aFileServSession)
     61 {
     62     //optimized mode is not supported if multiple file ptrs are not allowed
     63     if (aParsingMode == 1)
     64     {
     65 #ifndef OPEN_FILE_ONCE_PER_TRACK
     66         aParsingMode = 0;
     67 #endif
     68     }
     69 
     70     MP4_FF_FILE fileStruct;
     71     MP4_FF_FILE *fp = &fileStruct;
     72 
     73     fp->_fileServSession = aFileServSession;
     74     fp->_pvfile.SetCPM(aCPMAccessFactory);
     75     fp->_pvfile.SetFileHandle(aHandle);
     76 
     77     if (AtomUtils::OpenMP4File(aFilename,
     78                                Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
     79                                fp) != 0)
     80     {
     81         return NULL;
     82     }
     83 
     84     uint32 fileSize;
     85     AtomUtils::getCurrentFileSize(fp, fileSize);
     86     fp->_fileSize = (int32)fileSize;
     87 
     88     Mpeg4File *mp4 = NULL;
     89     PV_MP4_FF_NEW(fp->auditCB, Mpeg4File, (fp, aFilename, aParsingMode), mp4);
     90 
     91 #ifdef OPEN_FILE_ONCE_PER_TRACK
     92     if (mp4 != NULL)
     93     {
     94         if (!mp4->IsMovieFragmentsPresent())
     95         {
     96             if (fp->IsOpen())
     97                 AtomUtils::CloseMP4File(fp);
     98         }
     99     }
    100 #endif
    101 
    102     return mp4;
    103 }
    104 
    105 //IsXXXable *******************************************
    106 /*
    107 oMoovBeforeMdat: as input,
    108                 1: IsMobileMP4 check
    109                 2: IsPseudoStreamable() check
    110                 3: IsPlayable() check
    111                  as output,
    112                  1: moov atom is in front of the mdat atom
    113                  0: there is mdat atom in front of moov atom
    114 
    115 metaDataSize   : as input. It is the available data size
    116                  as output. It is the offset of the file where the full "moov" atom is available.
    117 */
    118 
    119 OSCL_EXPORT_REF
    120 int32
    121 IMpeg4File::IsXXXable(OSCL_wString& filename,
    122                       int32 &metaDataSize,
    123                       int32  &oMoovBeforeMdat,
    124                       uint32 *pMajorBrand,
    125                       uint32 *pCompatibleBrands,
    126                       Oscl_FileServer* fileServSession)
    127 {
    128     const int ISMOBILEMP4 = 1, ISPSEUDOSTREMABLE = 2, ISPLAYABLE = 3;
    129 
    130     if (metaDataSize <= DEFAULT_ATOM_SIZE)
    131         return READ_FAILED;
    132 
    133     if ((oMoovBeforeMdat < ISMOBILEMP4) || (oMoovBeforeMdat > ISPLAYABLE))
    134         return DEFAULT_ERROR;
    135 
    136     int32 checkType = oMoovBeforeMdat;
    137     int32 fileSize = metaDataSize;
    138 
    139     MP4_FF_FILE fileStruct;
    140     MP4_FF_FILE *fp = &fileStruct;
    141 
    142     fp->_fileServSession = fileServSession;
    143 
    144     if (AtomUtils::OpenMP4File(filename,
    145                                Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
    146                                fp) != 0)
    147     {
    148         return (FILE_OPEN_FAILED);
    149     }
    150 
    151     fp->_fileSize = fileSize;
    152 
    153     int32   mp4ErrorCode = DEFAULT_ERROR;
    154 
    155     uint32 atomType = UNKNOWN_ATOM;
    156     uint32 atomSize = 0;
    157 
    158     AtomUtils::getNextAtomType(fp, atomSize, atomType);
    159 
    160     if (atomType == FILE_TYPE_ATOM)
    161     {
    162         //"ftyp"
    163         if (fileSize < (int32)atomSize)
    164         {
    165             AtomUtils::CloseMP4File(fp);
    166             return READ_FAILED;
    167         }
    168         FileTypeAtom *_pFileTypeAtom = NULL;
    169         PV_MP4_FF_NEW(fp->auditCB, FileTypeAtom, (fp, atomSize, atomType), _pFileTypeAtom);
    170 
    171         if (!_pFileTypeAtom->MP4Success())
    172         {
    173             PV_MP4_FF_DELETE(NULL, FileTypeAtom, _pFileTypeAtom);
    174             AtomUtils::CloseMP4File(fp);
    175             return READ_FILE_TYPE_ATOM_FAILED;
    176         }
    177         //get file type
    178         {
    179             *pMajorBrand = ENoFileType;
    180 
    181             uint32 majorBrand = _pFileTypeAtom->getMajorBrand();
    182 
    183             //conversion
    184             if (majorBrand == MOBILE_MP4)   *pMajorBrand = EMMP4;
    185             else if (majorBrand == BRAND_3GPP4) *pMajorBrand = E3GP4;
    186             else if (majorBrand == BRAND_3GPP5) *pMajorBrand = E3GP5;
    187             else if (majorBrand == BRAND_ISOM)  *pMajorBrand = EISOM;
    188             else if (majorBrand == BRAND_MP41)  *pMajorBrand = EMP41;
    189             else if (majorBrand == BRAND_MP42)  *pMajorBrand = EMP42;
    190             else if (majorBrand == WMF_BRAND)   *pMajorBrand = EWMF;
    191             // else .. set to ENoFileType above
    192 
    193             Oscl_Vector<uint32, OsclMemAllocator> *compatibleBrandArray =
    194                 _pFileTypeAtom->getCompatibleBrand();
    195 
    196             *pCompatibleBrands = ENoFileType;
    197 
    198             if (compatibleBrandArray != NULL)
    199             {
    200                 for (uint32 i = 0; i < compatibleBrandArray->size(); i++)
    201                 {
    202                     uint32 compatibleBrand = (*compatibleBrandArray)[i];
    203 
    204                     if (compatibleBrand == MOBILE_MP4)          *pCompatibleBrands |= EMMP4;
    205                     else if (compatibleBrand == BRAND_3GPP4)    *pCompatibleBrands |= E3GP4;
    206                     else if (compatibleBrand == BRAND_3GPP5)    *pCompatibleBrands |= E3GP5;
    207                     else if (compatibleBrand == BRAND_ISOM)     *pCompatibleBrands |= EISOM;
    208                     else if (compatibleBrand == BRAND_MP41)     *pCompatibleBrands |= EMP41;
    209                     else if (compatibleBrand == BRAND_MP42)     *pCompatibleBrands |= EMP42;
    210                     else if (compatibleBrand == WMF_BRAND)      *pCompatibleBrands |= EWMF;
    211                 }
    212             }
    213         }//end of get file type
    214 
    215         int32 fpos = _pFileTypeAtom->getSize();
    216         PV_MP4_FF_DELETE(NULL, FileTypeAtom, _pFileTypeAtom);
    217 
    218         if (checkType == ISMOBILEMP4)
    219         {
    220             AtomUtils::CloseMP4File(fp);
    221             return EVERYTHING_FINE;
    222         }
    223 
    224         oMoovBeforeMdat = true;
    225         metaDataSize = 0;
    226 
    227         if ((fpos + DEFAULT_ATOM_SIZE) > fileSize)
    228         {
    229             AtomUtils::CloseMP4File(fp);
    230             return READ_FAILED;
    231         }
    232 
    233         while (fpos < fileSize)
    234         {
    235             uint32 atomType = UNKNOWN_ATOM;
    236             uint32 atomSize = 0;
    237 
    238             AtomUtils::getNextAtomType(fp, atomSize, atomType);
    239 
    240             fpos += DEFAULT_ATOM_SIZE;
    241 
    242             if ((atomType == FREE_SPACE_ATOM)
    243                     || (atomType == SKIP_ATOM)
    244                     || (atomType == USER_DATA_ATOM)
    245                     || (atomType == UUID_ATOM)
    246                     || (atomType == MOVIE_ATOM)
    247                     || (atomType == MEDIA_DATA_ATOM)
    248                     || (atomType == UNKNOWN_ATOM))
    249             {
    250                 if (atomSize < DEFAULT_ATOM_SIZE)
    251                 {
    252                     mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
    253                     break;
    254                 }
    255                 atomSize -= DEFAULT_ATOM_SIZE;
    256                 if (atomType == MOVIE_ATOM)
    257                 {
    258                     //this is an exit
    259                     //no check of the "size" validity
    260                     metaDataSize = fpos + atomSize;
    261                     mp4ErrorCode = EVERYTHING_FINE;
    262                     break;
    263                 }
    264                 else if (atomType == MEDIA_DATA_ATOM)
    265                 {
    266                     oMoovBeforeMdat = false;
    267                     if (checkType == ISPSEUDOSTREMABLE)
    268                     {
    269                         mp4ErrorCode = EVERYTHING_FINE;
    270                         break;
    271                     }
    272                 }
    273 
    274                 if ((int32)(fpos + atomSize) > fileSize)
    275                 {
    276                     mp4ErrorCode = READ_FAILED;
    277                     break;
    278                 }
    279                 AtomUtils::seekFromCurrPos(fp, atomSize);
    280                 fpos += atomSize;
    281 
    282             }
    283             else if (atomType == 0)
    284             {
    285                 //return READ_FAILED;
    286                 //since extra check is put above, it should NEVER fall in this bracket
    287                 mp4ErrorCode = READ_FAILED;
    288                 break;
    289             }
    290             else
    291             {   //error: other atoms should not be in file level
    292                 mp4ErrorCode = DEFAULT_ERROR;
    293                 break;
    294             }
    295         }
    296     }
    297     AtomUtils::CloseMP4File(fp);
    298     return (mp4ErrorCode);
    299 }
    300 
    301 OSCL_EXPORT_REF
    302 int32
    303 IMpeg4File::IsXXXable(MP4_FF_FILE_REFERENCE fileRef,
    304                       int32 &metaDataSize,
    305                       int32  &oMoovBeforeMdat,
    306                       uint32 *pMajorBrand,
    307                       uint32 *pCompatibleBrands)
    308 {
    309     const int ISMOBILEMP4 = 1, ISPSEUDOSTREMABLE = 2, ISPLAYABLE = 3;
    310 
    311     if (metaDataSize <= DEFAULT_ATOM_SIZE)
    312         return READ_FAILED;
    313 
    314     if ((oMoovBeforeMdat < ISMOBILEMP4) || (oMoovBeforeMdat > ISPLAYABLE))
    315         return DEFAULT_ERROR;
    316 
    317     int32 checkType = oMoovBeforeMdat;
    318     int32 fileSize = metaDataSize;
    319 
    320     MP4_FF_FILE fileStruct;
    321     MP4_FF_FILE *fp = &fileStruct;
    322 
    323     fp->_pvfile.SetFilePtr(fileRef);
    324 
    325     AtomUtils::seekFromStart(fp, 0);
    326     fp->_fileSize = fileSize;
    327 
    328     int32   mp4ErrorCode = DEFAULT_ERROR;
    329 
    330     uint32 atomType = UNKNOWN_ATOM;
    331     uint32 atomSize = 0;
    332 
    333     AtomUtils::getNextAtomType(fp, atomSize, atomType);
    334 
    335     if (atomType == FILE_TYPE_ATOM)
    336     {
    337         //"ftyp"
    338         if (fileSize < (int32)atomSize)
    339         {
    340             AtomUtils::CloseMP4File(fp);
    341             return READ_FAILED;
    342         }
    343         FileTypeAtom *_pFileTypeAtom = NULL;
    344         PV_MP4_FF_NEW(fp->auditCB, FileTypeAtom, (fp, atomSize, atomType), _pFileTypeAtom);
    345 
    346         if (!_pFileTypeAtom->MP4Success())
    347         {
    348             PV_MP4_FF_DELETE(NULL, FileTypeAtom, _pFileTypeAtom);
    349             AtomUtils::CloseMP4File(fp);
    350             return READ_FILE_TYPE_ATOM_FAILED;
    351         }
    352         //get file type
    353         {
    354             *pMajorBrand = ENoFileType;
    355 
    356             uint32 majorBrand = _pFileTypeAtom->getMajorBrand();
    357 
    358             //conversion
    359             if (majorBrand == MOBILE_MP4)   *pMajorBrand = EMMP4;
    360             else if (majorBrand == BRAND_3GPP4) *pMajorBrand = E3GP4;
    361             else if (majorBrand == BRAND_3GPP5) *pMajorBrand = E3GP5;
    362             else if (majorBrand == BRAND_ISOM)  *pMajorBrand = EISOM;
    363             else if (majorBrand == BRAND_MP41)  *pMajorBrand = EMP41;
    364             else if (majorBrand == BRAND_MP42)  *pMajorBrand = EMP42;
    365             else if (majorBrand == WMF_BRAND)   *pMajorBrand = EWMF;
    366 
    367 
    368             Oscl_Vector<uint32, OsclMemAllocator> *compatibleBrandArray =
    369                 _pFileTypeAtom->getCompatibleBrand();
    370 
    371 
    372             *pCompatibleBrands = ENoFileType;
    373 
    374             if (compatibleBrandArray != NULL)
    375             {
    376                 for (uint32 i = 0; i < compatibleBrandArray->size(); i++)
    377                 {
    378                     uint32 compatibleBrand = (*compatibleBrandArray)[i];
    379 
    380                     if (compatibleBrand == MOBILE_MP4)          *pCompatibleBrands |= EMMP4;
    381                     else if (compatibleBrand == BRAND_3GPP4)    *pCompatibleBrands |= E3GP4;
    382                     else if (compatibleBrand == BRAND_3GPP5)    *pCompatibleBrands |= E3GP5;
    383                     else if (compatibleBrand == BRAND_ISOM)     *pCompatibleBrands |= EISOM;
    384                     else if (compatibleBrand == BRAND_MP41)     *pCompatibleBrands |= EMP41;
    385                     else if (compatibleBrand == BRAND_MP42)     *pCompatibleBrands |= EMP42;
    386                     else if (compatibleBrand == WMF_BRAND)      *pCompatibleBrands |= EWMF;
    387                 }
    388             }
    389         }//end of get file type
    390 
    391         int32 fpos = _pFileTypeAtom->getSize();
    392         PV_MP4_FF_DELETE(NULL, FileTypeAtom, _pFileTypeAtom);
    393 
    394         if (checkType == ISMOBILEMP4)
    395         {
    396             AtomUtils::CloseMP4File(fp);
    397             return EVERYTHING_FINE;
    398         }
    399 
    400         oMoovBeforeMdat = true;
    401         metaDataSize = 0;
    402 
    403         if ((fpos + DEFAULT_ATOM_SIZE) > fileSize)
    404         {
    405             AtomUtils::CloseMP4File(fp);
    406             return READ_FAILED;
    407         }
    408 
    409         while (fpos < fileSize)
    410         {
    411             uint32 atomType = UNKNOWN_ATOM;
    412             uint32 atomSize = 0;
    413 
    414             AtomUtils::getNextAtomType(fp, atomSize, atomType);
    415 
    416             fpos += DEFAULT_ATOM_SIZE;
    417 
    418             if ((atomType == FREE_SPACE_ATOM)
    419                     || (atomType == SKIP_ATOM)
    420                     || (atomType == USER_DATA_ATOM)
    421                     || (atomType == UUID_ATOM)
    422                     || (atomType == MOVIE_ATOM)
    423                     || (atomType == MEDIA_DATA_ATOM)
    424                     || (atomType == UNKNOWN_ATOM))
    425             {
    426                 if (atomSize < DEFAULT_ATOM_SIZE)
    427                 {
    428                     mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
    429                     break;
    430                 }
    431                 atomSize -= DEFAULT_ATOM_SIZE;
    432                 if (atomType == MOVIE_ATOM)
    433                 {
    434                     //this is an exit
    435                     //no check of the "size" validity
    436                     metaDataSize = fpos + atomSize;
    437                     mp4ErrorCode = EVERYTHING_FINE;
    438                     break;
    439                 }
    440                 else if (atomType == MEDIA_DATA_ATOM)
    441                 {
    442                     oMoovBeforeMdat = false;
    443                     if (checkType == ISPSEUDOSTREMABLE)
    444                     {
    445                         mp4ErrorCode = EVERYTHING_FINE;
    446                         break;
    447                     }
    448                 }
    449 
    450                 if ((int32)(fpos + atomSize) > fileSize)
    451                 {
    452                     mp4ErrorCode = READ_FAILED;
    453                     break;
    454                 }
    455                 AtomUtils::seekFromCurrPos(fp, atomSize);
    456                 fpos += atomSize;
    457 
    458             }
    459             else if (atomType == 0)
    460             {
    461                 //return READ_FAILED;
    462                 //since extra check is put above, it should NEVER fall in this bracket
    463                 mp4ErrorCode = READ_FAILED;
    464                 break;
    465             }
    466             else
    467             {   //error: other atoms should not be in file level
    468                 mp4ErrorCode = DEFAULT_ERROR;
    469                 break;
    470             }
    471         }
    472     }
    473     AtomUtils::CloseMP4File(fp);
    474     return (mp4ErrorCode);
    475 }
    476 
    477 
    478 OSCL_EXPORT_REF MP4_ERROR_CODE
    479 IMpeg4File::IsProgressiveDownloadable(MP4_FF_FILE_REFERENCE filePtr,
    480                                       uint32 fileSize,
    481                                       bool& oIsProgressiveDownloadable,
    482                                       uint32& metaDataSize)
    483 {
    484     oIsProgressiveDownloadable = false;
    485     metaDataSize  = 0;
    486 
    487     MP4_FF_FILE fileStruct;
    488     MP4_FF_FILE *fp = &fileStruct;
    489 
    490     fp->_pvfile.SetFilePtr(filePtr);
    491 
    492     if (fileSize <= DEFAULT_ATOM_SIZE)
    493     {
    494         return INSUFFICIENT_DATA;
    495     }
    496 
    497     int32 filePointer = AtomUtils::getCurrentFilePosition(fp);
    498     AtomUtils::seekFromStart(fp, 0);
    499 
    500     fp->_fileSize = fileSize;
    501 
    502     uint32 atomType          = UNKNOWN_ATOM;
    503     uint32 atomSize          = 0;
    504     bool oMovieAtomFound     = false;
    505     bool oMediaDataAtomFound = false;
    506 
    507     int32 fpos = 0;
    508 
    509     MP4_ERROR_CODE mp4ErrorCode = INSUFFICIENT_DATA;
    510 
    511     while ((uint32)(fpos + DEFAULT_ATOM_SIZE) < fileSize)
    512     {
    513         AtomUtils::getNextAtomType(fp, atomSize, atomType);
    514         if (atomSize < DEFAULT_ATOM_SIZE)
    515         {
    516             mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
    517             break;
    518         }
    519 
    520         if ((atomType == FILE_TYPE_ATOM) ||
    521                 (atomType == FREE_SPACE_ATOM) ||
    522                 (atomType == SKIP_ATOM) ||
    523                 (atomType == USER_DATA_ATOM) ||
    524                 (atomType == UUID_ATOM) ||
    525                 (atomType == UNKNOWN_ATOM))
    526         {
    527             fpos += atomSize;
    528             if ((uint32)fpos > fileSize)
    529             {
    530                 break;
    531             }
    532             AtomUtils::seekFromStart(fp, fpos);
    533             continue;
    534         }
    535         else if (atomType == MOVIE_ATOM)
    536         {
    537             fpos += atomSize;
    538             oMovieAtomFound = true;
    539             metaDataSize = fpos;
    540         }
    541         else if (atomType == MEDIA_DATA_ATOM)
    542         {
    543             fpos += atomSize;
    544             oMediaDataAtomFound  = true;
    545         }
    546         else
    547         {
    548             //error: should never get here
    549             mp4ErrorCode = DEFAULT_ERROR;
    550         }
    551         break;
    552     }
    553 
    554     if (oMovieAtomFound || oMediaDataAtomFound)
    555     {
    556         //at most one of two can be true
    557         oIsProgressiveDownloadable = oMovieAtomFound;
    558         mp4ErrorCode = EVERYTHING_FINE;
    559     }
    560 
    561     AtomUtils::seekFromStart(fp, filePointer);
    562 
    563     return (mp4ErrorCode);
    564 }
    565 
    566 OSCL_EXPORT_REF MP4_ERROR_CODE
    567 IMpeg4File::GetMetaDataSize(PVMFCPMPluginAccessInterfaceFactory* aCPMAccessFactory,
    568                             bool& oIsProgressiveDownloadable,
    569                             uint32& metaDataSize)
    570 {
    571     oIsProgressiveDownloadable = false;
    572     metaDataSize  = 0;
    573 
    574     /* use a dummy string for file name */
    575     OSCL_wHeapString<OsclMemAllocator> filename;
    576 
    577     MP4_FF_FILE fileStruct;
    578     MP4_FF_FILE *fp = &fileStruct;
    579     fp->_pvfile.SetCPM(aCPMAccessFactory);
    580 
    581     if (AtomUtils::OpenMP4File(filename,
    582                                Oscl_File::MODE_READ | Oscl_File::MODE_BINARY,
    583                                fp) != 0)
    584     {
    585         return FILE_OPEN_FAILED;
    586     }
    587 
    588     uint32 fileSize;
    589     AtomUtils::getCurrentFileSize(fp, fileSize);
    590     fp->_fileSize = (int32)fileSize;
    591 
    592     AtomUtils::seekFromStart(fp, 0);
    593 
    594     if (fileSize <= DEFAULT_ATOM_SIZE)
    595     {
    596         return INSUFFICIENT_DATA;
    597     }
    598 
    599     uint32 atomType          = UNKNOWN_ATOM;
    600     uint32 atomSize          = 0;
    601     bool oMovieAtomFound     = false;
    602     bool oMediaDataAtomFound = false;
    603 
    604     int32 fpos = 0;
    605 
    606     MP4_ERROR_CODE mp4ErrorCode = INSUFFICIENT_DATA;
    607 
    608     while ((uint32)(fpos + DEFAULT_ATOM_SIZE) < fileSize)
    609     {
    610         AtomUtils::getNextAtomType(fp, atomSize, atomType);
    611         if (atomSize < DEFAULT_ATOM_SIZE)
    612         {
    613             mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
    614             break;
    615         }
    616 
    617         if ((atomType == FILE_TYPE_ATOM) ||
    618                 (atomType == FREE_SPACE_ATOM) ||
    619                 (atomType == SKIP_ATOM) ||
    620                 (atomType == USER_DATA_ATOM) ||
    621                 (atomType == UUID_ATOM) ||
    622                 (atomType == UNKNOWN_ATOM))
    623         {
    624             fpos += atomSize;
    625             metaDataSize = fpos;
    626             if ((uint32)fpos > fileSize)
    627             {
    628                 break;
    629             }
    630             AtomUtils::seekFromStart(fp, fpos);
    631             continue;
    632         }
    633         else if (atomType == MOVIE_ATOM)
    634         {
    635             fpos += atomSize;
    636             oMovieAtomFound = true;
    637             metaDataSize = fpos;
    638         }
    639         else if (atomType == MEDIA_DATA_ATOM)
    640         {
    641             fpos += atomSize;
    642             oMediaDataAtomFound  = true;
    643             metaDataSize = fpos;
    644         }
    645         else
    646         {
    647             //error: should never get here
    648             mp4ErrorCode = DEFAULT_ERROR;
    649         }
    650         break;
    651     }
    652 
    653     if (oMovieAtomFound || oMediaDataAtomFound)
    654     {
    655         //at most one of two can be true
    656         oIsProgressiveDownloadable = oMovieAtomFound;
    657         mp4ErrorCode = EVERYTHING_FINE;
    658     }
    659 
    660     if (!oMovieAtomFound && (0 != AtomUtils::getFileBufferingCapacity(fp)))
    661     {
    662         // can't support progressive playback if no movie atom found
    663         mp4ErrorCode = NOT_PROGRESSIVE_STREAMABLE;
    664     }
    665 
    666     AtomUtils::CloseMP4File(fp);
    667 
    668     return (mp4ErrorCode);
    669 }
    670 
    671 OSCL_EXPORT_REF void IMpeg4File::DestroyMP4FileObject(IMpeg4File* aMP4FileObject)
    672 {
    673     Mpeg4File* ptr = OSCL_STATIC_CAST(Mpeg4File*, aMP4FileObject);
    674     PV_MP4_FF_DELETE(NULL, Mpeg4File, ptr);
    675 }
    676