mmplugins/lib3gp/impl/src/atom.cpp
changeset 0 40261b775718
child 23 545d349d14da
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <3gplibrary/mp4config.h>
       
    17 #include <3gplibrary/mp4lib.h>
       
    18 #include "mp4atom.h"
       
    19 #include "mp4memwrap.h"
       
    20 #include "mp4buffer.h"
       
    21 #include "mp4endian.h"
       
    22 #include "mp4file.h"
       
    23 #include "mp4utils.h"
       
    24 
       
    25 // MACROS
       
    26 // Debug print macro
       
    27 #ifdef _DEBUG
       
    28 #include <e32svr.h>
       
    29 //#define PRINT(x) RDebug::Print x
       
    30 #define PRINT(x)
       
    31 #else
       
    32 #define PRINT(x)
       
    33 #endif
       
    34 
       
    35 mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type);
       
    36  
       
    37 /*
       
    38  * Function:
       
    39  *
       
    40  *   mp4_i32 metaDataAvailable(MP4HandleImp handle)
       
    41  *
       
    42  * Description:
       
    43  *
       
    44  *   This function determines whether meta data is available for reading
       
    45  *   or not.
       
    46  *
       
    47  *   Meta data is available if the input is in a file.
       
    48  *
       
    49  *   When reading from a stream, meta data is considered available if
       
    50  *   it is in the beginning of the stream and the entire Moov atom has
       
    51  *   been received. FTYP atom is allowed before MOOV atom.
       
    52  *
       
    53  * Parameters:
       
    54  *
       
    55  *   handle   MP4 library handle
       
    56  *
       
    57  * Return value:
       
    58  *
       
    59  *   0                Meta data is not available because enough data has not
       
    60  *                    been inserted into the library
       
    61  *   1                Meta data is available
       
    62  *   Negative value   Meta data is not available because of fatal error
       
    63  *
       
    64  */
       
    65 mp4_i32 metaDataAvailable(MP4HandleImp handle)
       
    66 {
       
    67   mp4_u32 size;
       
    68   mp4_u32 type;
       
    69 
       
    70 
       
    71   /* Meta data is available if the input is in a file or if a complete file has been inputted as a stream*/
       
    72 
       
    73   if (handle->file)
       
    74     return 1;
       
    75 
       
    76   /* When reading from a stream, meta data is considered available if
       
    77      it is in the beginning of the stream and the entire MOOV atom has
       
    78      been received. FTYP atom is allowed before MOOV atom. */
       
    79 
       
    80   if (!handle->ftypRead)
       
    81   {
       
    82     if (peekData(handle, handle->buf, 8) < 0) /* 8 bytes are not available */
       
    83         return 0;
       
    84 
       
    85     size = u32endian(*((mp4_u32 *)handle->buf));
       
    86     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
    87 
       
    88     if (type == ATOMTYPE_FTYP)
       
    89     {
       
    90       if (getBufferedBytes(handle) - handle->position < size) /* FTYP is not available */
       
    91         return 0;
       
    92       if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL)
       
    93         return -100;
       
    94       if (readFTYP(handle, handle->ftyp) < 0)
       
    95         return -2;
       
    96     }
       
    97   }
       
    98 
       
    99   // Now the ftyp is read. No need to chedk MOOV presence for full files in the memory.
       
   100   if (handle->LastWriteDataCalled == MP4TRUE)
       
   101       return 1;
       
   102 
       
   103   if (handle->LastWriteDataCalled == MP4FALSE)
       
   104   {//Whole stream is not fed to the internal memory yet. 
       
   105    for (;;)
       
   106     {
       
   107       if (peekData(handle, handle->buf, 8) < 0)
       
   108         return 0;
       
   109 
       
   110       size = u32endian(*((mp4_u32 *)handle->buf));
       
   111       type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
   112 
       
   113       if (type == ATOMTYPE_MOOV)
       
   114         {
       
   115         if (getBufferedBytes(handle) - handle->absPosition >= size) /* Entire Moov is available */
       
   116             {
       
   117             return 1;        
       
   118             }
       
   119         else
       
   120             {
       
   121             return 0;
       
   122             }
       
   123         }
       
   124 
       
   125       if ((mp4_i32)size <= 0)
       
   126         return -1;
       
   127 
       
   128       handle->absPosition+=size;
       
   129     }
       
   130   }
       
   131   return 0;
       
   132 }
       
   133 
       
   134 
       
   135 /*
       
   136  * Function:
       
   137  *
       
   138  *   mp4_i32 readFTYP(MP4HandleImp handle,
       
   139  *                    fileTypeAtom *ftyp)
       
   140  *
       
   141  * Description:
       
   142  *
       
   143  *   This function parses one FTYP atom.
       
   144  *
       
   145  * Parameters:
       
   146  *
       
   147  *   handle             MP4 library handle
       
   148  *   ftyp               FTYP pointer
       
   149  *
       
   150  * Return value:
       
   151  *
       
   152  *   Negative integer   Error
       
   153  *   >= 0               Success. Value tells how many bytes were read.
       
   154  *
       
   155  */
       
   156 mp4_i32 readFTYP(MP4HandleImp handle, fileTypeAtom *ftyp)
       
   157 {
       
   158   mp4_i32 bytesread;
       
   159   mp4_i32 totalbytesread = 0;
       
   160   mp4_u32 n = 0;
       
   161   mp4_i32 compatiblebrandsize = 0;
       
   162 
       
   163 
       
   164   if ((ftyp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
   165     return -100;
       
   166 
       
   167   bytesread = readAtomHeader(handle, ftyp->atomhdr);
       
   168   if (bytesread < 0)
       
   169     return -1;
       
   170   totalbytesread += bytesread;
       
   171 
       
   172   if (ftyp->atomhdr->type != ATOMTYPE_FTYP)
       
   173     return -1;
       
   174 
       
   175   if (ftyp->atomhdr->size < 16) // 8(header)+8bytes needed for major and minor brand
       
   176     return -1;
       
   177 
       
   178   bytesread = readData(handle, handle->buf, 4);
       
   179   if (bytesread < 0)
       
   180     return -1;
       
   181   ftyp->majorBrand = u32endian(*((mp4_u32 *)handle->buf));
       
   182   totalbytesread += bytesread;
       
   183 
       
   184   bytesread = readData(handle, handle->buf, 4);
       
   185   if (bytesread < 0)
       
   186     return -1;
       
   187   ftyp->minorVersion = u32endian(*((mp4_u32 *)handle->buf));
       
   188   totalbytesread += bytesread;
       
   189 
       
   190   if (ftyp->atomhdr->size == (mp4_u32)totalbytesread)
       
   191     return totalbytesread;
       
   192 
       
   193   compatiblebrandsize = (mp4_i32)ftyp->atomhdr->size - totalbytesread;
       
   194   if ( compatiblebrandsize < 4 )   // at this point we must have at least 1 compatible brand
       
   195     return -1;
       
   196   if ( compatiblebrandsize > 20*4) // maximum of 20 compatible brands 4byte entries
       
   197     return -1;
       
   198   if ( compatiblebrandsize % 4 ) // must be able to divide by 4
       
   199     return -1;
       
   200 
       
   201   ftyp->compatibleBrands = (mp4_u32 *)mp4malloc( compatiblebrandsize );
       
   202   if (ftyp->compatibleBrands == NULL)
       
   203     return -1;
       
   204 
       
   205   while ((mp4_u32)totalbytesread < ftyp->atomhdr->size)
       
   206   {
       
   207     bytesread = readData(handle, handle->buf, 4);
       
   208     if (bytesread < 0)
       
   209       return -1;
       
   210 
       
   211     ftyp->compatibleBrands[n] = u32endian(*((mp4_u32 *)handle->buf));
       
   212 
       
   213     n++;
       
   214     totalbytesread += bytesread;
       
   215   }
       
   216 
       
   217   return totalbytesread;
       
   218 }
       
   219 
       
   220 
       
   221 /*
       
   222  * Function:
       
   223  *
       
   224  *   mp4_i32 readMetaData(MP4HandleImp handle)
       
   225  *
       
   226  * Description:
       
   227  *
       
   228  *   This function reads the meta data from the file/stream and stores
       
   229  *   the information in the atom structures available via handle.
       
   230  *
       
   231  * Parameters:
       
   232  *
       
   233  *   handle  MP4 library handle
       
   234  *
       
   235  * Return value:
       
   236  *
       
   237  *   Negative value   Error
       
   238  *   >= 0             Success. Value tells the number of bytes read.
       
   239  *
       
   240  */
       
   241 mp4_i32 readMetaData(MP4HandleImp handle)
       
   242 {
       
   243   mp4_i32 bytesread;
       
   244   mp4_i32 totalbytesread = 0;
       
   245 
       
   246 
       
   247   if (handle->file)
       
   248   {
       
   249     mp4_u64 size;
       
   250     mp4_u32 type;
       
   251 
       
   252 
       
   253     if (seekFileAbs(handle, 0) < 0)
       
   254       return -1;
       
   255 
       
   256     /* Seek to the start of FTYP atom */
       
   257 
       
   258     for (;;)
       
   259     {
       
   260       if (readBoxHeader(handle, &size, &type) <0)
       
   261         return -1;
       
   262 
       
   263       if (type == ATOMTYPE_FTYP)
       
   264       {
       
   265         /* Read FTYP */
       
   266 
       
   267         if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL)
       
   268           return -100;
       
   269         bytesread = readFTYP(handle, handle->ftyp);
       
   270         if (bytesread < 0)
       
   271           return -3;
       
   272         totalbytesread += bytesread;
       
   273 
       
   274         break;
       
   275       }
       
   276 
       
   277       if (size <= 0)
       
   278         return -1;
       
   279 
       
   280       if (seekFile(handle, size) != 0)
       
   281         return -1;
       
   282     }
       
   283 
       
   284     if (seekFileAbs(handle, 0) < 0)
       
   285       return -1;
       
   286 
       
   287     /* Seek to the start of MOOV atom */
       
   288     for (;;)
       
   289     {
       
   290       if (readBoxHeader(handle, &size, &type) <0)
       
   291         return -1;
       
   292 
       
   293       if (type == ATOMTYPE_MOOV)
       
   294         break;
       
   295 
       
   296       if (size <= 0)
       
   297         return -1;
       
   298 
       
   299       if (seekFile(handle, size) != 0)
       
   300         return -1;
       
   301     }
       
   302   }
       
   303 
       
   304   // If all data of a file is in the memory and the file does not have MOOV box right after FTYP, 
       
   305   // then we need to seek for the location of the MOOV first
       
   306 
       
   307   if (handle->LastWriteDataCalled == MP4TRUE)
       
   308   { 
       
   309     mp4_u32 size;
       
   310     mp4_u32 type;
       
   311     // Seek until the beginning of MOOV box.
       
   312     for(;;)
       
   313     {
       
   314         if (peekData(handle, handle->buf, 8) < 0)
       
   315             return -1;
       
   316 
       
   317         size = u32endian(*((mp4_u32 *)handle->buf));
       
   318         type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
   319     
       
   320         if (type == ATOMTYPE_MOOV)
       
   321           break;
       
   322 
       
   323         if ((mp4_i32)size <= 0)
       
   324           return -1;
       
   325 
       
   326         if (discardData(handle, size) < 0)
       
   327           return -1;
       
   328     }
       
   329   }
       
   330 
       
   331   if ((handle->moov = (movieAtom *)mp4malloc(sizeof(movieAtom))) == NULL)
       
   332     return -100;
       
   333 
       
   334   bytesread = readMoov(handle, handle->moov);
       
   335   if (bytesread < 0)
       
   336     return -3;
       
   337   totalbytesread += bytesread;
       
   338 
       
   339   if (handle->moov->trakAudio)
       
   340   {
       
   341     mp4_u32 audiotype;
       
   342 	mp4_i32 errorAudio = 0;
       
   343 
       
   344 	errorAudio = determineAudioType(handle, &audiotype);
       
   345     if ( errorAudio == 0 )
       
   346     {
       
   347 	   	handle->type |= audiotype;    	
       
   348     
       
   349 	    /* Move to the beginning of the 1st audio frame */
       
   350 	    switch (advanceAudioSample(handle, handle->moov->trakAudio))
       
   351 	    {
       
   352 	    case -1:
       
   353 	      return -1;
       
   354 	    case -2:
       
   355 	      handle->audioLast = MP4TRUE;
       
   356 	      break;
       
   357 	    default:
       
   358 	      break;
       
   359 	    }
       
   360 	}
       
   361 	else if (errorAudio == -2)
       
   362 	{
       
   363 		handle->type |= audiotype;	
       
   364 	}
       
   365 	else
       
   366 	{
       
   367 		return -1;
       
   368 	}
       
   369   }
       
   370 
       
   371   if (handle->moov->trakVideo)
       
   372   {
       
   373     mp4_u32 videotype;
       
   374     mp4_i32 errorVideo = 0;
       
   375 
       
   376 	errorVideo = determineVideoType(handle, &videotype);
       
   377     if ( errorVideo == 0 )
       
   378     {
       
   379 	   	handle->type |= videotype;    	
       
   380     
       
   381     	/* Move to the beginning of the 1st video frame */
       
   382 	    switch (advanceVideoFrame(handle, handle->moov->trakVideo))
       
   383 	    {
       
   384 	    case -1:
       
   385 	      return -1;
       
   386 	    case -2:
       
   387 	       handle->videoLast = MP4TRUE;
       
   388 	      break;
       
   389 	    default:
       
   390 	      break;
       
   391 	    }
       
   392 	}
       
   393 	else if (errorVideo == -2)
       
   394 	{
       
   395 	   	handle->type |= videotype;	
       
   396 	}
       
   397 	else
       
   398 	{
       
   399 		return -1;
       
   400 	}
       
   401   }
       
   402 
       
   403   return totalbytesread;
       
   404 }
       
   405 
       
   406 
       
   407 /*
       
   408  * Function:
       
   409  *
       
   410  *   mp4_i32 readMoov(MP4HandleImp handle,
       
   411  *                    movieAtom *moov)
       
   412  *
       
   413  * Description:
       
   414  *
       
   415  *   This function parses one MOOV atom.
       
   416  *
       
   417  * Parameters:
       
   418  *
       
   419  *   handle             MP4 library handle
       
   420  *   moov               MOOV pointer
       
   421  *
       
   422  * Return value:
       
   423  *
       
   424  *   Negative integer   Error
       
   425  *   >= 0               Success. Value tells how many bytes were read.
       
   426  *
       
   427  */
       
   428 mp4_i32 readMoov(MP4HandleImp handle, movieAtom *moov)
       
   429 {
       
   430   mp4_i32 bytesread;
       
   431   mp4_i32 totalbytesread = 0;
       
   432 
       
   433 
       
   434   if ((moov->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
   435     return -100;
       
   436 
       
   437   bytesread = readAtomHeader(handle, moov->atomhdr);
       
   438   if (bytesread < 0)
       
   439     return -1;
       
   440   totalbytesread += bytesread;
       
   441 
       
   442   if (moov->atomhdr->type != ATOMTYPE_MOOV)
       
   443     return -1;
       
   444 
       
   445   while ((mp4_u32)totalbytesread < handle->moov->atomhdr->size)
       
   446   {
       
   447     mp4_u32 type;
       
   448 
       
   449 
       
   450     if (peekData(handle, handle->buf, 8) < 0)
       
   451       return -1;
       
   452 
       
   453     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
   454 
       
   455     switch (type)
       
   456     {
       
   457     case ATOMTYPE_MVHD:
       
   458 
       
   459       if (moov->mvhd) /* MVHD has already been read, more than one is not allowed */
       
   460         return -1;
       
   461 
       
   462       if ((moov->mvhd = (movieHeaderAtom *)mp4malloc(sizeof(movieHeaderAtom))) == NULL)
       
   463         return -100;
       
   464 
       
   465       bytesread = readMVHD(handle, moov->mvhd);
       
   466       if (bytesread < 0)
       
   467         return -1;
       
   468       totalbytesread += bytesread;
       
   469 
       
   470       break;
       
   471 
       
   472     case ATOMTYPE_IODS:
       
   473 
       
   474       if (moov->iods) /* IODS has already been read, more than one is not allowed */
       
   475         return -1;
       
   476 
       
   477       if ((moov->iods = (objectDescriptorAtom *)mp4malloc(sizeof(objectDescriptorAtom))) == NULL)
       
   478         return -100;
       
   479 
       
   480       bytesread = readIODS(handle, moov->iods);
       
   481       if (bytesread < 0)
       
   482         return -1;
       
   483       totalbytesread += bytesread;
       
   484 
       
   485       break;
       
   486 
       
   487     case ATOMTYPE_TRAK:
       
   488 
       
   489       {
       
   490         trackAtom *ta;
       
   491 
       
   492         if ((ta = (trackAtom *)mp4malloc(sizeof(trackAtom))) == NULL)
       
   493           return -100;
       
   494 
       
   495         bytesread = readTRAK(handle, ta);
       
   496         if (bytesread < 0)
       
   497         {
       
   498           if (freeTRAK(ta) < 0)
       
   499             return -1;
       
   500           return -1;
       
   501         }
       
   502         totalbytesread += bytesread;
       
   503 
       
   504         if (!ta->mdia)
       
   505         {
       
   506           if (freeTRAK(ta) < 0)
       
   507             return -1;
       
   508           return -1;
       
   509         }
       
   510         if (!ta->mdia->hdlr)
       
   511         {
       
   512           if (freeTRAK(ta) < 0)
       
   513             return -1;
       
   514           return -1;
       
   515         }
       
   516 
       
   517         if (ta->mdia->hdlr->handlerType != HANDLERTYPE_VIDE &&
       
   518             ta->mdia->hdlr->handlerType != HANDLERTYPE_SOUN) /* Track is neither video nor audio */
       
   519         {
       
   520           /* Do nothing with the unknown track */
       
   521           if (freeTRAK(ta) < 0)
       
   522             return -1;
       
   523           break;
       
   524         }
       
   525 
       
   526         if (ta->mdia->hdlr->handlerType == HANDLERTYPE_VIDE)
       
   527         {
       
   528 	        if (moov->trakVideo) /* Video Track already read */
       
   529 	        {
       
   530 	          if (freeTRAK(ta) < 0)
       
   531 	            return -1;
       
   532 	        }
       
   533 	        else
       
   534 	        {
       
   535 	          moov->trakVideo = ta;
       
   536 	        }
       
   537         }
       
   538 		else if (ta->mdia->hdlr->handlerType == HANDLERTYPE_SOUN)
       
   539         {
       
   540 	        if (moov->trakAudio) /* Audio Track already read */
       
   541 	        {
       
   542 	          if (freeTRAK(ta) < 0)
       
   543 	            return -1;
       
   544 	        }
       
   545 	        else
       
   546 	        {
       
   547 	          moov->trakAudio = ta;
       
   548 	        }
       
   549         }
       
   550         else
       
   551         {
       
   552         }
       
   553         break;
       
   554       }
       
   555 
       
   556     case ATOMTYPE_UDTA:
       
   557 
       
   558       {
       
   559       if (moov->udta) /* UDTA has already been read */
       
   560           {
       
   561           bytesread = readUnknown(handle);
       
   562           if (bytesread < 0)
       
   563             return -1;
       
   564           totalbytesread += bytesread;
       
   565           break;
       
   566           }
       
   567 
       
   568 
       
   569       if ((moov->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL)
       
   570         return -100;
       
   571 
       
   572       bytesread = readUDTA(handle, moov->udta);
       
   573       if (bytesread < 0)
       
   574         return -1;
       
   575       totalbytesread += bytesread;
       
   576 
       
   577       break;
       
   578       }
       
   579 
       
   580     default:
       
   581 
       
   582       bytesread = readUnknown(handle);
       
   583       if (bytesread < 0)
       
   584         return -1;
       
   585       totalbytesread += bytesread;
       
   586 
       
   587       break;
       
   588     }
       
   589   }
       
   590 
       
   591   return totalbytesread;
       
   592 }
       
   593 
       
   594 
       
   595 /*
       
   596  * Function:
       
   597  *
       
   598  *   mp4_i32 readAtomheader(MP4HandleImp handle,
       
   599  *                          atomHeader *ah)
       
   600  *
       
   601  * Description:
       
   602  *
       
   603  *   This function reads an atom header and stores the information
       
   604  *   in ah.
       
   605  *
       
   606  * Parameters:
       
   607  *
       
   608  *   handle           MP4 library handle
       
   609  *   ah               atomHeader structure that is used to store the
       
   610  *                    information
       
   611  *
       
   612  * Return value:
       
   613  *
       
   614  *   Negative value   Error
       
   615  *   >= 0             Success. Value tells how many bytes were read.
       
   616  *
       
   617  */
       
   618 mp4_i32 readAtomHeader(MP4HandleImp handle, atomHeader *ah)
       
   619 {
       
   620   mp4_i32 bytesread;
       
   621   mp4_i32 totalbytesread = 0;
       
   622 
       
   623   //PRINT((_L("readAtomHeader")));
       
   624   bytesread = readData(handle, handle->buf, 4);
       
   625   if (bytesread < 0)
       
   626     return -1;
       
   627   ah->size = u32endian(*((mp4_u32 *)handle->buf));
       
   628   totalbytesread += bytesread;
       
   629 
       
   630   bytesread = readData(handle, handle->buf, 4);
       
   631   if (bytesread < 0)
       
   632     return -1;
       
   633   ah->type = u32endian(*((mp4_u32 *)handle->buf));
       
   634   totalbytesread += bytesread;
       
   635 
       
   636   if (ah->size == 1)
       
   637   {
       
   638     bytesread = readData(handle, handle->buf, 8);
       
   639     if (bytesread < 0)
       
   640       return -1;
       
   641     ah->largeSize = u64endian(*((mp4_u64 *)handle->buf));
       
   642     totalbytesread += bytesread;
       
   643   }
       
   644 
       
   645   if (ah->type == ATOMTYPE_UUID)
       
   646   {
       
   647     bytesread = readData(handle, handle->buf, 16);
       
   648     if (bytesread < 0)
       
   649       return -1;
       
   650     mp4memcpy(ah->extendedType, handle->buf, 16);
       
   651     totalbytesread += bytesread;
       
   652   }
       
   653 
       
   654   //PRINT((_L("   size %u, size %Lu, type %c%c%c%c"), ah->size, ah->largeSize,((unsigned char *)(&ah->type))[3], ((unsigned char *)(&ah->type))[2], ((unsigned char *)(&ah->type))[1], ((unsigned char *)(&ah->type))[0]));
       
   655   return totalbytesread;
       
   656 }
       
   657 
       
   658 
       
   659 /*
       
   660  * Function:
       
   661  *
       
   662  *   mp4_i32 readFullAtomHeader(MP4HandleImp handle,
       
   663  *                              atomHeader *ah)
       
   664  *
       
   665  * Description:
       
   666  *
       
   667  *   This function reads a full atom header and stores the information
       
   668  *   in ah.
       
   669  *
       
   670  * Parameters:
       
   671  *
       
   672  *   handle           MP4 library handle
       
   673  *   ah               atomHeader structure that is used to store the
       
   674  *                    information
       
   675  *
       
   676  * Return value:
       
   677  *
       
   678  *   Negative value   Error
       
   679  *   >= 0             Success. Value tells how many bytes were read.
       
   680  *
       
   681  */
       
   682 mp4_i32 readFullAtomHeader(MP4HandleImp handle, atomHeader *ah)
       
   683 {
       
   684   mp4_i32 bytesread;
       
   685   mp4_i32 totalbytesread = 0;
       
   686 
       
   687   //PRINT((_L("readFullAtomHeader")));
       
   688 
       
   689   bytesread = readData(handle, handle->buf, 4);
       
   690   if (bytesread < 0)
       
   691     return -1;
       
   692   ah->size = u32endian(*((mp4_u32 *)handle->buf));
       
   693   totalbytesread += bytesread;
       
   694 
       
   695   bytesread = readData(handle, handle->buf, 4);
       
   696   if (bytesread < 0)
       
   697     return -1;
       
   698   ah->type = u32endian(*((mp4_u32 *)handle->buf));
       
   699   totalbytesread += bytesread;
       
   700 
       
   701   bytesread = readData(handle, handle->buf, 1);
       
   702   if (bytesread < 0)
       
   703     return -1;
       
   704   ah->version = *(handle->buf);
       
   705   totalbytesread += bytesread;
       
   706 
       
   707   bytesread = readData(handle, handle->buf, 3);
       
   708   if (bytesread < 0)
       
   709     return -1;
       
   710   mp4memcpy(ah->flags, handle->buf, 3);
       
   711   totalbytesread += bytesread;
       
   712 
       
   713   //PRINT((_L("   size %u, size %Lu, type %c%c%c%c"), ah->size, ah->largeSize,((unsigned char *)(&ah->type))[3], ((unsigned char *)(&ah->type))[2], ((unsigned char *)(&ah->type))[1], ((unsigned char *)(&ah->type))[0]));
       
   714   return totalbytesread;
       
   715 }
       
   716 
       
   717 
       
   718 /*
       
   719  * Function:
       
   720  *
       
   721  *   mp4_i32 readMVHD(MP4HandleImp handle,
       
   722  *                    movieHeaderAtom *mvhd)
       
   723  *
       
   724  * Description:
       
   725  *
       
   726  *   This function parses one MVHD atom.
       
   727  *
       
   728  * Parameters:
       
   729  *
       
   730  *   handle             MP4 library handle
       
   731  *   mvhd               MVHD pointer
       
   732  *
       
   733  * Return value:
       
   734  *
       
   735  *   Negative integer   Error
       
   736  *   >= 0               Success. Value tells how many bytes were read.
       
   737  *
       
   738  */
       
   739 mp4_i32 readMVHD(MP4HandleImp handle, movieHeaderAtom *mvhd)
       
   740 {
       
   741   mp4_i32 bytesread;
       
   742   mp4_i32 totalbytesread = 0;
       
   743 
       
   744 
       
   745   if ((mvhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
   746     return -100;
       
   747 
       
   748   bytesread = readFullAtomHeader(handle, mvhd->atomhdr);
       
   749   if (bytesread < 0)
       
   750     return -1;
       
   751   totalbytesread += bytesread;
       
   752 
       
   753   if (mvhd->atomhdr->type != ATOMTYPE_MVHD)
       
   754     return -1;
       
   755 
       
   756   if (mvhd->atomhdr->version == 1) /* 64 bit */
       
   757   {
       
   758     bytesread = readData(handle, handle->buf, 8);
       
   759     if (bytesread < 0)
       
   760       return -1;
       
   761     mvhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
       
   762     totalbytesread += bytesread;
       
   763 
       
   764     bytesread = readData(handle, handle->buf, 8);
       
   765     if (bytesread < 0)
       
   766       return -1;
       
   767     mvhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
       
   768     totalbytesread += bytesread;
       
   769 
       
   770     bytesread = readData(handle, handle->buf, 4);
       
   771     if (bytesread < 0)
       
   772       return -1;
       
   773     mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
       
   774     totalbytesread += bytesread;
       
   775 
       
   776     bytesread = readData(handle, handle->buf, 8);
       
   777     if (bytesread < 0)
       
   778       return -1;
       
   779     mvhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
       
   780     totalbytesread += bytesread;
       
   781   }
       
   782   else /* 32 bit */
       
   783   {
       
   784     bytesread = readData(handle, handle->buf, 4);
       
   785     if (bytesread < 0)
       
   786       return -1;
       
   787     mvhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
       
   788     totalbytesread += bytesread;
       
   789 
       
   790     bytesread = readData(handle, handle->buf, 4);
       
   791     if (bytesread < 0)
       
   792       return -1;
       
   793     mvhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
       
   794     totalbytesread += bytesread;
       
   795 
       
   796     bytesread = readData(handle, handle->buf, 4);
       
   797     if (bytesread < 0)
       
   798       return -1;
       
   799     mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
       
   800     totalbytesread += bytesread;
       
   801 
       
   802     bytesread = readData(handle, handle->buf, 4);
       
   803     if (bytesread < 0)
       
   804       return -1;
       
   805     mvhd->duration = u32endian(*((mp4_u32 *)handle->buf));
       
   806     totalbytesread += bytesread;
       
   807   }
       
   808 
       
   809   bytesread = discardData(handle, 76);
       
   810   if (bytesread < 0)
       
   811     return -1;
       
   812   totalbytesread += bytesread;
       
   813 
       
   814   bytesread = readData(handle, handle->buf, 4);
       
   815   if (bytesread < 0)
       
   816     return -1;
       
   817   mvhd->nextTrackID = u32endian(*((mp4_u32 *)handle->buf));
       
   818   totalbytesread += bytesread;
       
   819 
       
   820   return totalbytesread;
       
   821 }
       
   822 
       
   823 
       
   824 /*
       
   825  * Function:
       
   826  *
       
   827  *   mp4_i32 readIODS(MP4HandleImp handle,
       
   828  *                    objectDescriptorAtom *iods)
       
   829  *
       
   830  * Description:
       
   831  *
       
   832  *   This function parses one IODS atom.
       
   833  *
       
   834  * Parameters:
       
   835  *
       
   836  *   handle             MP4 library handle
       
   837  *   iods               IODS pointer
       
   838  *
       
   839  * Return value:
       
   840  *
       
   841  *   Negative integer   Error
       
   842  *   >= 0               Success. Value tells how many bytes were read.
       
   843  *
       
   844  */
       
   845 mp4_i32 readIODS(MP4HandleImp handle, objectDescriptorAtom *iods)
       
   846 {
       
   847   mp4_i32 bytesread;
       
   848   mp4_i32 totalbytesread = 0;
       
   849 
       
   850 
       
   851   if ((iods->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
   852     return -100;
       
   853 
       
   854   bytesread = readFullAtomHeader(handle, iods->atomhdr);
       
   855   if (bytesread < 0)
       
   856     return -1;
       
   857   totalbytesread += bytesread;
       
   858 
       
   859   if (iods->atomhdr->type != ATOMTYPE_IODS)
       
   860     return -1;
       
   861 
       
   862   bytesread = discardData(handle, iods->atomhdr->size - totalbytesread);
       
   863   if (bytesread < 0)
       
   864     return -1;
       
   865   totalbytesread += bytesread;
       
   866 
       
   867   return totalbytesread;
       
   868 }
       
   869 
       
   870 
       
   871 /*
       
   872  * Function:
       
   873  *
       
   874  *   mp4_i32 readTRAK(MP4HandleImp handle,
       
   875  *                    trackAtom *trak)
       
   876  *
       
   877  * Description:
       
   878  *
       
   879  *   This function parses one TRAK atom.
       
   880  *
       
   881  * Parameters:
       
   882  *
       
   883  *   handle             MP4 library handle
       
   884  *   trak               TRAK pointer
       
   885  *
       
   886  * Return value:
       
   887  *
       
   888  *   Negative integer   Error
       
   889  *   >= 0               Success. Value tells how many bytes were read.
       
   890  *
       
   891  */
       
   892 mp4_i32 readTRAK(MP4HandleImp handle, trackAtom *trak)
       
   893 {
       
   894   mp4_i32 bytesread;
       
   895   mp4_i32 totalbytesread = 0;
       
   896 
       
   897 
       
   898   if ((trak->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
   899     return -100;
       
   900 
       
   901   bytesread = readAtomHeader(handle, trak->atomhdr);
       
   902   if (bytesread < 0)
       
   903     return -1;
       
   904   totalbytesread += bytesread;
       
   905 
       
   906   if (trak->atomhdr->type != ATOMTYPE_TRAK)
       
   907     return -1;
       
   908 
       
   909 
       
   910   while ((mp4_u32)totalbytesread < trak->atomhdr->size)
       
   911   {
       
   912     mp4_u32 type;
       
   913 
       
   914 
       
   915     if (peekData(handle, handle->buf, 8) < 0)
       
   916       return -1;
       
   917 
       
   918     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
   919 
       
   920     switch (type)
       
   921     {
       
   922     case ATOMTYPE_TKHD:
       
   923 
       
   924       if (trak->tkhd) /* MVHD has already been read, more than one is not allowed */
       
   925         return -1;
       
   926 
       
   927       if ((trak->tkhd = (trackHeaderAtom *)mp4malloc(sizeof(trackHeaderAtom))) == NULL)
       
   928         return -100;
       
   929 
       
   930       bytesread = readTKHD(handle, trak->tkhd);
       
   931       if (bytesread < 0)
       
   932         return -1;
       
   933       totalbytesread += bytesread;
       
   934 
       
   935       break;
       
   936 
       
   937     case ATOMTYPE_TREF:
       
   938 
       
   939       if (trak->tref) /* TREF has already been read, more than one is not allowed */
       
   940         return -1;
       
   941 
       
   942       if ((trak->tref = (trackReferenceAtom *)mp4malloc(sizeof(trackReferenceAtom))) == NULL)
       
   943         return -100;
       
   944 
       
   945       bytesread = readTREF(handle, trak->tref);
       
   946       if (bytesread < 0)
       
   947         return -1;
       
   948       totalbytesread += bytesread;
       
   949 
       
   950       break;
       
   951 
       
   952     case ATOMTYPE_EDTS:
       
   953 
       
   954       if (trak->edts) /* EDTS has already been read, more than one is not allowed */
       
   955         return -1;
       
   956 
       
   957       if ((trak->edts = (editListContainerAtom *)mp4malloc(sizeof(editListContainerAtom))) == NULL)
       
   958         return -100;
       
   959 
       
   960       bytesread = readEDTS(handle, trak->edts);
       
   961       if (bytesread < 0)
       
   962         return -1;
       
   963       totalbytesread += bytesread;
       
   964 
       
   965       break;
       
   966 
       
   967     case ATOMTYPE_MDIA:
       
   968 
       
   969       if (trak->mdia) /* MDIA has already been read, more than one is not allowed */
       
   970         return -1;
       
   971 
       
   972       if ((trak->mdia = (mediaAtom *)mp4malloc(sizeof(mediaAtom))) == NULL)
       
   973         return -100;
       
   974 
       
   975       bytesread = readMDIA(handle, trak->mdia);
       
   976       if (bytesread < 0)
       
   977         return -1;
       
   978       totalbytesread += bytesread;
       
   979 
       
   980       break;
       
   981 
       
   982     case ATOMTYPE_UDTA:
       
   983       {
       
   984       if (trak->udta) /* UDTA has already been read */
       
   985           {
       
   986           bytesread = readUnknown(handle);
       
   987           if (bytesread < 0)
       
   988             return -1;
       
   989           totalbytesread += bytesread;
       
   990           break;
       
   991           }
       
   992 
       
   993       if ((trak->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL)
       
   994         return -100;
       
   995 
       
   996       bytesread = readUDTA(handle, trak->udta);
       
   997       if (bytesread < 0)
       
   998         return -1;
       
   999       totalbytesread += bytesread;
       
  1000 
       
  1001       break;
       
  1002       }
       
  1003 
       
  1004     default:
       
  1005 
       
  1006       bytesread = readUnknown(handle);
       
  1007       if (bytesread < 0)
       
  1008         return -1;
       
  1009       totalbytesread += bytesread;
       
  1010 
       
  1011       break;
       
  1012     }
       
  1013   }
       
  1014 
       
  1015   return totalbytesread;
       
  1016 }
       
  1017 
       
  1018 
       
  1019 /*
       
  1020  * Function:
       
  1021  *
       
  1022  *   mp4_i32 readUnknown(MP4HandleImp handle)
       
  1023  *
       
  1024  * Description:
       
  1025  *
       
  1026  *   This function reads one atom of unknown type. Atom contents are
       
  1027  *   discarded.
       
  1028  *
       
  1029  * Parameters:
       
  1030  *
       
  1031  *   handle             MP4 library handle
       
  1032  *
       
  1033  * Return value:
       
  1034  *
       
  1035  *   Negative integer   Error
       
  1036  *   >= 0               Success. Value tells how many bytes were read.
       
  1037  *
       
  1038  */
       
  1039 mp4_i32 readUnknown(MP4HandleImp handle)
       
  1040 {
       
  1041   mp4_i32 bytesread;
       
  1042   mp4_i32 totalbytesread = 0;
       
  1043   mp4_u32 size;
       
  1044 
       
  1045 
       
  1046   bytesread = readData(handle, handle->buf, 4);
       
  1047   if (bytesread < 0)
       
  1048     return -1;
       
  1049   totalbytesread += bytesread;
       
  1050 
       
  1051   size = u32endian(*((mp4_u32 *)handle->buf));
       
  1052   if ( size < 4 )
       
  1053   {
       
  1054   	return -1;
       
  1055   }
       
  1056 
       
  1057   if ( handle->file )
       
  1058   {
       
  1059   	if ( seekFile(handle, size - totalbytesread) < 0 )
       
  1060   	{
       
  1061   	   return -1;	
       
  1062   	}
       
  1063   	else
       
  1064   	{
       
  1065   	   return size;	
       
  1066   	}
       
  1067   }
       
  1068   else
       
  1069   {
       
  1070   	bytesread = discardData(handle, size - totalbytesread);
       
  1071 	  if (bytesread < 0)
       
  1072     	return -1;
       
  1073   	totalbytesread += bytesread;
       
  1074   }
       
  1075   return totalbytesread;
       
  1076 }
       
  1077 
       
  1078 
       
  1079 /*
       
  1080  * Function:
       
  1081  *
       
  1082  *   mp4_i32 readTKHD(MP4HandleImp handle,
       
  1083  *                    trackHeaderAtom *tkhd)
       
  1084  *
       
  1085  * Description:
       
  1086  *
       
  1087  *   This function parses one TKHD atom.
       
  1088  *
       
  1089  * Parameters:
       
  1090  *
       
  1091  *   handle             MP4 library handle
       
  1092  *   tkhd               TKHD pointer
       
  1093  *
       
  1094  * Return value:
       
  1095  *
       
  1096  *   Negative integer   Error
       
  1097  *   >= 0               Success. Value tells how many bytes were read.
       
  1098  *
       
  1099  */
       
  1100 mp4_i32 readTKHD(MP4HandleImp handle, trackHeaderAtom *tkhd)
       
  1101 {
       
  1102   mp4_i32 bytesread;
       
  1103   mp4_i32 totalbytesread = 0;
       
  1104 
       
  1105 
       
  1106   if ((tkhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1107     return -100;
       
  1108 
       
  1109   bytesread = readFullAtomHeader(handle, tkhd->atomhdr);
       
  1110   if (bytesread < 0)
       
  1111     return -1;
       
  1112   totalbytesread += bytesread;
       
  1113 
       
  1114   if (tkhd->atomhdr->type != ATOMTYPE_TKHD)
       
  1115     return -1;
       
  1116 
       
  1117   if (tkhd->atomhdr->version == 1) /* 64 bit */
       
  1118   {
       
  1119     bytesread = readData(handle, handle->buf, 8);
       
  1120     if (bytesread < 0)
       
  1121       return -1;
       
  1122     tkhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
       
  1123     totalbytesread += bytesread;
       
  1124 
       
  1125     bytesread = readData(handle, handle->buf, 8);
       
  1126     if (bytesread < 0)
       
  1127       return -1;
       
  1128     tkhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
       
  1129     totalbytesread += bytesread;
       
  1130 
       
  1131     bytesread = readData(handle, handle->buf, 4);
       
  1132     if (bytesread < 0)
       
  1133       return -1;
       
  1134     tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf));
       
  1135     totalbytesread += bytesread;
       
  1136 
       
  1137     bytesread = readData(handle, handle->buf, 4);
       
  1138     if (bytesread < 0)
       
  1139       return -1;
       
  1140     tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf));
       
  1141     totalbytesread += bytesread;
       
  1142 
       
  1143     bytesread = readData(handle, handle->buf, 8);
       
  1144     if (bytesread < 0)
       
  1145       return -1;
       
  1146     tkhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
       
  1147     totalbytesread += bytesread;
       
  1148   }
       
  1149   else /* 32 bit */
       
  1150   {
       
  1151     bytesread = readData(handle, handle->buf, 4);
       
  1152     if (bytesread < 0)
       
  1153       return -1;
       
  1154     tkhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
       
  1155     totalbytesread += bytesread;
       
  1156 
       
  1157     bytesread = readData(handle, handle->buf, 4);
       
  1158     if (bytesread < 0)
       
  1159       return -1;
       
  1160     tkhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
       
  1161     totalbytesread += bytesread;
       
  1162 
       
  1163     bytesread = readData(handle, handle->buf, 4);
       
  1164     if (bytesread < 0)
       
  1165       return -1;
       
  1166     tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf));
       
  1167     totalbytesread += bytesread;
       
  1168 
       
  1169     bytesread = readData(handle, handle->buf, 4);
       
  1170     if (bytesread < 0)
       
  1171       return -1;
       
  1172     tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf));
       
  1173     totalbytesread += bytesread;
       
  1174 
       
  1175     bytesread = readData(handle, handle->buf, 4);
       
  1176     if (bytesread < 0)
       
  1177       return -1;
       
  1178     tkhd->duration = u32endian(*((mp4_u32 *)handle->buf));
       
  1179     totalbytesread += bytesread;
       
  1180   }
       
  1181 
       
  1182   bytesread = discardData(handle, 52);
       
  1183   if (bytesread < 0)
       
  1184     return -1;
       
  1185   totalbytesread += bytesread;
       
  1186 
       
  1187   bytesread = readData(handle, handle->buf, 4);
       
  1188   if (bytesread < 0)
       
  1189     return -1;
       
  1190   tkhd->width = u16endian(*((mp4_u16 *)handle->buf));
       
  1191   totalbytesread += bytesread;
       
  1192 
       
  1193   bytesread = readData(handle, handle->buf, 4);
       
  1194   if (bytesread < 0)
       
  1195     return -1;
       
  1196   tkhd->height = u16endian(*((mp4_u16 *)handle->buf));
       
  1197   totalbytesread += bytesread;
       
  1198 
       
  1199   return totalbytesread;
       
  1200 }
       
  1201 
       
  1202 
       
  1203 /*
       
  1204  * Function:
       
  1205  *
       
  1206  *   mp4_i32 readTREF(MP4HandleImp handle,
       
  1207  *                    trackReferenceAtom *tref)
       
  1208  *
       
  1209  * Description:
       
  1210  *
       
  1211  *   This function parses one TREF atom and discards the contents.
       
  1212  *
       
  1213  * Parameters:
       
  1214  *
       
  1215  *   handle             MP4 library handle
       
  1216  *   tref               TREF pointer
       
  1217  *
       
  1218  * Return value:
       
  1219  *
       
  1220  *   Negative integer   Error
       
  1221  *   >= 0               Success. Value tells how many bytes were read.
       
  1222  *
       
  1223  */
       
  1224 mp4_i32 readTREF(MP4HandleImp handle, trackReferenceAtom *tref)
       
  1225 {
       
  1226   mp4_i32 bytesread;
       
  1227   mp4_i32 totalbytesread = 0;
       
  1228 
       
  1229 
       
  1230   if ((tref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1231     return -100;
       
  1232 
       
  1233   bytesread = readAtomHeader(handle, tref->atomhdr);
       
  1234   if (bytesread < 0)
       
  1235     return -1;
       
  1236   totalbytesread += bytesread;
       
  1237 
       
  1238   if (tref->atomhdr->type != ATOMTYPE_TREF)
       
  1239     return -1;
       
  1240 
       
  1241   bytesread = discardData(handle, tref->atomhdr->size - totalbytesread);
       
  1242   if (bytesread < 0)
       
  1243     return -1;
       
  1244   totalbytesread += bytesread;
       
  1245 
       
  1246   return totalbytesread;
       
  1247 }
       
  1248 
       
  1249 
       
  1250 /*
       
  1251  * Function:
       
  1252  *
       
  1253  *   mp4_i32 readEDTS(MP4HandleImp handle,
       
  1254  *                    editListContainerAtom *edts)
       
  1255  *
       
  1256  * Description:
       
  1257  *
       
  1258  *   This function parses one EDTS atom and discards the contents.
       
  1259  *
       
  1260  * Parameters:
       
  1261  *
       
  1262  *   handle             MP4 library handle
       
  1263  *   edts               EDTS pointer
       
  1264  *
       
  1265  * Return value:
       
  1266  *
       
  1267  *   Negative integer   Error
       
  1268  *   >= 0               Success. Value tells how many bytes were read.
       
  1269  *
       
  1270  */
       
  1271 mp4_i32 readEDTS(MP4HandleImp handle, editListContainerAtom *edts)
       
  1272 {
       
  1273   mp4_i32 bytesread;
       
  1274   mp4_i32 totalbytesread = 0;
       
  1275 
       
  1276 
       
  1277   if ((edts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1278     return -100;
       
  1279 
       
  1280   bytesread = readAtomHeader(handle, edts->atomhdr);
       
  1281   if (bytesread < 0)
       
  1282     return -1;
       
  1283   totalbytesread += bytesread;
       
  1284 
       
  1285   if (edts->atomhdr->type != ATOMTYPE_EDTS)
       
  1286     return -1;
       
  1287 
       
  1288   bytesread = discardData(handle, edts->atomhdr->size - totalbytesread);
       
  1289   if (bytesread < 0)
       
  1290     return -1;
       
  1291   totalbytesread += bytesread;
       
  1292 
       
  1293   return totalbytesread;
       
  1294 }
       
  1295 
       
  1296 
       
  1297 /*
       
  1298  * Function:
       
  1299  *
       
  1300  *   mp4_i32 readMDIA(MP4HandleImp handle,
       
  1301  *                    mediaAtom *mdia)
       
  1302  *
       
  1303  * Description:
       
  1304  *
       
  1305  *   This function parses one MDIA atom.
       
  1306  *
       
  1307  * Parameters:
       
  1308  *
       
  1309  *   handle             MP4 library handle
       
  1310  *   mdia               MDIA pointer
       
  1311  *
       
  1312  * Return value:
       
  1313  *
       
  1314  *   Negative integer   Error
       
  1315  *   >= 0               Success. Value tells how many bytes were read.
       
  1316  *
       
  1317  */
       
  1318 mp4_i32 readMDIA(MP4HandleImp handle, mediaAtom *mdia)
       
  1319 {
       
  1320   mp4_i32 bytesread;
       
  1321   mp4_i32 totalbytesread = 0;
       
  1322 
       
  1323 
       
  1324   if ((mdia->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1325     return -100;
       
  1326 
       
  1327   bytesread = readAtomHeader(handle, mdia->atomhdr);
       
  1328   if (bytesread < 0)
       
  1329     return -1;
       
  1330   totalbytesread += bytesread;
       
  1331 
       
  1332   if (mdia->atomhdr->type != ATOMTYPE_MDIA)
       
  1333     return -1;
       
  1334 
       
  1335 
       
  1336   while ((mp4_u32)totalbytesread < mdia->atomhdr->size)
       
  1337   {
       
  1338     mp4_u32 type;
       
  1339 
       
  1340 
       
  1341     if (peekData(handle, handle->buf, 8) < 0)
       
  1342       return -1;
       
  1343 
       
  1344     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  1345 
       
  1346     switch (type)
       
  1347     {
       
  1348     case ATOMTYPE_MDHD:
       
  1349 
       
  1350       if (mdia->mdhd) /* MDHD has already been read, more than one is not allowed */
       
  1351         return -1;
       
  1352 
       
  1353       if ((mdia->mdhd = (mediaHeaderAtom *)mp4malloc(sizeof(mediaHeaderAtom))) == NULL)
       
  1354         return -100;
       
  1355 
       
  1356       bytesread = readMDHD(handle, mdia->mdhd);
       
  1357       if (bytesread < 0)
       
  1358         return -1;
       
  1359       totalbytesread += bytesread;
       
  1360 
       
  1361       break;
       
  1362 
       
  1363     case ATOMTYPE_HDLR:
       
  1364 
       
  1365       if (mdia->hdlr) /* HDLR has already been read, more than one is not allowed */
       
  1366         return -1;
       
  1367 
       
  1368       if ((mdia->hdlr = (handlerAtom *)mp4malloc(sizeof(handlerAtom))) == NULL)
       
  1369         return -100;
       
  1370 
       
  1371       bytesread = readHDLR(handle, mdia->hdlr);
       
  1372       if (bytesread < 0)
       
  1373         return -1;
       
  1374       totalbytesread += bytesread;
       
  1375 
       
  1376       break;
       
  1377 
       
  1378     case ATOMTYPE_MINF:
       
  1379 
       
  1380       if (mdia->minf) /* MINF has already been read, more than one is not allowed */
       
  1381         return -1;
       
  1382 
       
  1383       if ((mdia->minf = (mediaInformationAtom *)mp4malloc(sizeof(mediaInformationAtom))) == NULL)
       
  1384         return -100;
       
  1385 
       
  1386       bytesread = readMINF(handle, mdia->minf);
       
  1387       if (bytesread < 0)
       
  1388         return -1;
       
  1389       totalbytesread += bytesread;
       
  1390 
       
  1391       break;
       
  1392 
       
  1393     default:
       
  1394 
       
  1395       bytesread = readUnknown(handle);
       
  1396       if (bytesread < 0)
       
  1397         return -1;
       
  1398       totalbytesread += bytesread;
       
  1399 
       
  1400       break;
       
  1401     }
       
  1402   }
       
  1403 
       
  1404   return totalbytesread;
       
  1405 }
       
  1406 
       
  1407 
       
  1408 /*
       
  1409  * Function:
       
  1410  *
       
  1411  *   mp4_i32 readMDHD(MP4HandleImp handle,
       
  1412  *                    mediaHeaderAtom *mdhd)
       
  1413  *
       
  1414  * Description:
       
  1415  *
       
  1416  *   This function parses one MDHD atom.
       
  1417  *
       
  1418  * Parameters:
       
  1419  *
       
  1420  *   handle             MP4 library handle
       
  1421  *   mdhd               MDHD pointer
       
  1422  *
       
  1423  * Return value:
       
  1424  *
       
  1425  *   Negative integer   Error
       
  1426  *   >= 0               Success. Value tells how many bytes were read.
       
  1427  *
       
  1428  */
       
  1429 mp4_i32 readMDHD(MP4HandleImp handle, mediaHeaderAtom *mdhd)
       
  1430 {
       
  1431   mp4_i32 bytesread;
       
  1432   mp4_i32 totalbytesread = 0;
       
  1433 
       
  1434 
       
  1435   if ((mdhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1436     return -100;
       
  1437 
       
  1438   bytesread = readFullAtomHeader(handle, mdhd->atomhdr);
       
  1439   if (bytesread < 0)
       
  1440     return -1;
       
  1441   totalbytesread += bytesread;
       
  1442 
       
  1443   if (mdhd->atomhdr->type != ATOMTYPE_MDHD)
       
  1444     return -1;
       
  1445 
       
  1446 
       
  1447   if (mdhd->atomhdr->version == 1) /* 64 bit */
       
  1448   {
       
  1449     bytesread = readData(handle, handle->buf, 8);
       
  1450     if (bytesread < 0)
       
  1451       return -1;
       
  1452     mdhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
       
  1453     totalbytesread += bytesread;
       
  1454 
       
  1455     bytesread = readData(handle, handle->buf, 8);
       
  1456     if (bytesread < 0)
       
  1457       return -1;
       
  1458     mdhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
       
  1459     totalbytesread += bytesread;
       
  1460 
       
  1461     bytesread = readData(handle, handle->buf, 4);
       
  1462     if (bytesread < 0)
       
  1463       return -1;
       
  1464     mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
       
  1465     totalbytesread += bytesread;
       
  1466 
       
  1467     bytesread = readData(handle, handle->buf, 8);
       
  1468     if (bytesread < 0)
       
  1469       return -1;
       
  1470     mdhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
       
  1471     totalbytesread += bytesread;
       
  1472   }
       
  1473   else /* 32 bit */
       
  1474   {
       
  1475     bytesread = readData(handle, handle->buf, 4);
       
  1476     if (bytesread < 0)
       
  1477       return -1;
       
  1478     mdhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
       
  1479     totalbytesread += bytesread;
       
  1480 
       
  1481     bytesread = readData(handle, handle->buf, 4);
       
  1482     if (bytesread < 0)
       
  1483       return -1;
       
  1484     mdhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
       
  1485     totalbytesread += bytesread;
       
  1486 
       
  1487     bytesread = readData(handle, handle->buf, 4);
       
  1488     if (bytesread < 0)
       
  1489       return -1;
       
  1490     mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
       
  1491     totalbytesread += bytesread;
       
  1492 
       
  1493     bytesread = readData(handle, handle->buf, 4);
       
  1494     if (bytesread < 0)
       
  1495       return -1;
       
  1496     mdhd->duration = u32endian(*((mp4_u32 *)handle->buf));
       
  1497     totalbytesread += bytesread;
       
  1498   }
       
  1499 
       
  1500   bytesread = discardData(handle, 4);
       
  1501   if (bytesread < 0)
       
  1502     return -1;
       
  1503   totalbytesread += bytesread;
       
  1504 
       
  1505   return totalbytesread;
       
  1506 }
       
  1507 
       
  1508 
       
  1509 /*
       
  1510  * Function:
       
  1511  *
       
  1512  *   mp4_i32 readHDLR(MP4HandleImp handle,
       
  1513  *                    handlerAtom *hdlr)
       
  1514  *
       
  1515  * Description:
       
  1516  *
       
  1517  *   This function parses one HDLR atom.
       
  1518  *
       
  1519  * Parameters:
       
  1520  *
       
  1521  *   handle             MP4 library handle
       
  1522  *   hdlr               HDLR pointer
       
  1523  *
       
  1524  * Return value:
       
  1525  *
       
  1526  *   Negative integer   Error
       
  1527  *   >= 0               Success. Value tells how many bytes were read.
       
  1528  *
       
  1529  */
       
  1530 mp4_i32 readHDLR(MP4HandleImp handle, handlerAtom *hdlr)
       
  1531 {
       
  1532   mp4_i32 bytesread;
       
  1533   mp4_i32 totalbytesread = 0;
       
  1534 
       
  1535 
       
  1536   if ((hdlr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1537     return -100;
       
  1538 
       
  1539   bytesread = readFullAtomHeader(handle, hdlr->atomhdr);
       
  1540   if (bytesread < 0)
       
  1541     return -1;
       
  1542   totalbytesread += bytesread;
       
  1543 
       
  1544   if (hdlr->atomhdr->type != ATOMTYPE_HDLR)
       
  1545     return -1;
       
  1546 
       
  1547 
       
  1548   bytesread = discardData(handle, 4);
       
  1549   if (bytesread < 0)
       
  1550     return -1;
       
  1551   totalbytesread += bytesread;
       
  1552 
       
  1553   bytesread = readData(handle, handle->buf, 4);
       
  1554   if (bytesread < 0)
       
  1555     return -1;
       
  1556   hdlr->handlerType = u32endian(*((mp4_u32 *)handle->buf));
       
  1557   totalbytesread += bytesread;
       
  1558 
       
  1559   bytesread = discardData(handle, hdlr->atomhdr->size - totalbytesread);
       
  1560   if (bytesread < 0)
       
  1561     return -1;
       
  1562   totalbytesread += bytesread;
       
  1563 
       
  1564   return totalbytesread;
       
  1565 }
       
  1566 
       
  1567 
       
  1568 /*
       
  1569  * Function:
       
  1570  *
       
  1571  *   mp4_i32 readMINF(MP4HandleImp handle,
       
  1572  *                    mediaInformationAtom *minf)
       
  1573  *
       
  1574  * Description:
       
  1575  *
       
  1576  *   This function parses one MINF atom.
       
  1577  *
       
  1578  * Parameters:
       
  1579  *
       
  1580  *   handle             MP4 library handle
       
  1581  *   minf               MINF pointer
       
  1582  *
       
  1583  * Return value:
       
  1584  *
       
  1585  *   Negative integer   Error
       
  1586  *   >= 0               Success. Value tells how many bytes were read.
       
  1587  *
       
  1588  */
       
  1589 mp4_i32 readMINF(MP4HandleImp handle, mediaInformationAtom *minf)
       
  1590 {
       
  1591   mp4_i32 bytesread;
       
  1592   mp4_i32 totalbytesread = 0;
       
  1593 
       
  1594 
       
  1595   if ((minf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1596     return -100;
       
  1597 
       
  1598   bytesread = readAtomHeader(handle, minf->atomhdr);
       
  1599   if (bytesread < 0)
       
  1600     return -1;
       
  1601   totalbytesread += bytesread;
       
  1602 
       
  1603   if (minf->atomhdr->type != ATOMTYPE_MINF)
       
  1604     return -1;
       
  1605 
       
  1606 
       
  1607   while ((mp4_u32)totalbytesread < minf->atomhdr->size)
       
  1608   {
       
  1609     mp4_u32 type;
       
  1610 
       
  1611 
       
  1612     if (peekData(handle, handle->buf, 8) < 0)
       
  1613       return -1;
       
  1614 
       
  1615     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  1616 
       
  1617     switch (type)
       
  1618     {
       
  1619     case ATOMTYPE_VMHD:
       
  1620 
       
  1621       if (minf->vmhd || minf->smhd) /* VMHD or SMHD has already been read, more than one is not allowed */
       
  1622         return -1;
       
  1623 
       
  1624       if ((minf->vmhd = (videoMediaHeaderAtom *)mp4malloc(sizeof(videoMediaHeaderAtom))) == NULL)
       
  1625         return -100;
       
  1626 
       
  1627       bytesread = readVMHD(handle, minf->vmhd);
       
  1628       if (bytesread < 0)
       
  1629         return -1;
       
  1630       totalbytesread += bytesread;
       
  1631 
       
  1632       break;
       
  1633 
       
  1634     case ATOMTYPE_SMHD:
       
  1635 
       
  1636       if (minf->smhd || minf->vmhd) /* SMHD or VMHD has already been read, more than one is not allowed */
       
  1637         return -1;
       
  1638 
       
  1639       if ((minf->smhd = (soundMediaHeaderAtom *)mp4malloc(sizeof(soundMediaHeaderAtom))) == NULL)
       
  1640         return -100;
       
  1641 
       
  1642       bytesread = readSMHD(handle, minf->smhd);
       
  1643       if (bytesread < 0)
       
  1644         return -1;
       
  1645       totalbytesread += bytesread;
       
  1646 
       
  1647       break;
       
  1648 
       
  1649     case ATOMTYPE_DINF:
       
  1650 
       
  1651       if (minf->dinf) /* DINF has already been read, more than one is not allowed */
       
  1652         return -1;
       
  1653 
       
  1654       if ((minf->dinf = (dataInformationAtom *)mp4malloc(sizeof(dataInformationAtom))) == NULL)
       
  1655         return -100;
       
  1656 
       
  1657       bytesread = readDINF(handle, minf->dinf);
       
  1658       if (bytesread < 0)
       
  1659         return -1;
       
  1660       totalbytesread += bytesread;
       
  1661 
       
  1662       break;
       
  1663 
       
  1664     case ATOMTYPE_STBL:
       
  1665 
       
  1666       if (minf->stbl) /* STBL has already been read, more than one is not allowed */
       
  1667         return -1;
       
  1668 
       
  1669       if ((minf->stbl = (sampleTableAtom *)mp4malloc(sizeof(sampleTableAtom))) == NULL)
       
  1670         return -100;
       
  1671 
       
  1672       bytesread = readSTBL(handle, minf->stbl);
       
  1673       if (bytesread < 0)
       
  1674         return -1;
       
  1675       totalbytesread += bytesread;
       
  1676 
       
  1677       break;
       
  1678 
       
  1679     default:
       
  1680 
       
  1681       bytesread = readUnknown(handle);
       
  1682       if (bytesread < 0)
       
  1683         return -1;
       
  1684       totalbytesread += bytesread;
       
  1685 
       
  1686       break;
       
  1687     }
       
  1688   }
       
  1689 
       
  1690   return totalbytesread;
       
  1691 }
       
  1692 
       
  1693 
       
  1694 /*
       
  1695  * Function:
       
  1696  *
       
  1697  *   mp4_i32 readVMHD(MP4HandleImp handle,
       
  1698  *                    videoMediaHeaderAtom *vmhd)
       
  1699  *
       
  1700  * Description:
       
  1701  *
       
  1702  *   This function parses one VMHD atom.
       
  1703  *
       
  1704  * Parameters:
       
  1705  *
       
  1706  *   handle             MP4 library handle
       
  1707  *   vmhd               VMHD pointer
       
  1708  *
       
  1709  * Return value:
       
  1710  *
       
  1711  *   Negative integer   Error
       
  1712  *   >= 0               Success. Value tells how many bytes were read.
       
  1713  *
       
  1714  */
       
  1715 mp4_i32 readVMHD(MP4HandleImp handle, videoMediaHeaderAtom *vmhd)
       
  1716 {
       
  1717   mp4_i32 bytesread;
       
  1718   mp4_i32 totalbytesread = 0;
       
  1719 
       
  1720 
       
  1721   if ((vmhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1722     return -100;
       
  1723 
       
  1724   bytesread = readFullAtomHeader(handle, vmhd->atomhdr);
       
  1725   if (bytesread < 0)
       
  1726     return -1;
       
  1727   totalbytesread += bytesread;
       
  1728 
       
  1729   if (vmhd->atomhdr->type != ATOMTYPE_VMHD)
       
  1730     return -1;
       
  1731 
       
  1732 
       
  1733   bytesread = discardData(handle, vmhd->atomhdr->size - totalbytesread);
       
  1734   if (bytesread < 0)
       
  1735     return -1;
       
  1736   totalbytesread += bytesread;
       
  1737 
       
  1738   return totalbytesread;
       
  1739 }
       
  1740 
       
  1741 
       
  1742 /*
       
  1743  * Function:
       
  1744  *
       
  1745  *   mp4_i32 readSMHD(MP4HandleImp handle,
       
  1746  *                    soundMediaHeaderAtom *smhd)
       
  1747  *
       
  1748  * Description:
       
  1749  *
       
  1750  *   This function parses one SMHD atom.
       
  1751  *
       
  1752  * Parameters:
       
  1753  *
       
  1754  *   handle             MP4 library handle
       
  1755  *   smhd               SMHD pointer
       
  1756  *
       
  1757  * Return value:
       
  1758  *
       
  1759  *   Negative integer   Error
       
  1760  *   >= 0               Success. Value tells how many bytes were read.
       
  1761  *
       
  1762  */
       
  1763 mp4_i32 readSMHD(MP4HandleImp handle, soundMediaHeaderAtom *smhd)
       
  1764 {
       
  1765   mp4_i32 bytesread;
       
  1766   mp4_i32 totalbytesread = 0;
       
  1767 
       
  1768 
       
  1769   if ((smhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1770     return -100;
       
  1771 
       
  1772   bytesread = readFullAtomHeader(handle, smhd->atomhdr);
       
  1773   if (bytesread < 0)
       
  1774     return -1;
       
  1775   totalbytesread += bytesread;
       
  1776 
       
  1777   if (smhd->atomhdr->type != ATOMTYPE_SMHD)
       
  1778     return -1;
       
  1779 
       
  1780 
       
  1781   bytesread = discardData(handle, smhd->atomhdr->size - totalbytesread);
       
  1782   if (bytesread < 0)
       
  1783     return -1;
       
  1784   totalbytesread += bytesread;
       
  1785 
       
  1786   return totalbytesread;
       
  1787 }
       
  1788 
       
  1789 
       
  1790 /*
       
  1791  * Function:
       
  1792  *
       
  1793  *   mp4_i32 readDINF(MP4HandleImp handle,
       
  1794  *                    dataInformationAtom *dinf)
       
  1795  *
       
  1796  * Description:
       
  1797  *
       
  1798  *   This function parses one DINF atom.
       
  1799  *
       
  1800  * Parameters:
       
  1801  *
       
  1802  *   handle             MP4 library handle
       
  1803  *   dinf               DINF pointer
       
  1804  *
       
  1805  * Return value:
       
  1806  *
       
  1807  *   Negative integer   Error
       
  1808  *   >= 0               Success. Value tells how many bytes were read.
       
  1809  *
       
  1810  */
       
  1811 mp4_i32 readDINF(MP4HandleImp handle, dataInformationAtom *dinf)
       
  1812 {
       
  1813   mp4_i32 bytesread;
       
  1814   mp4_i32 totalbytesread = 0;
       
  1815 
       
  1816 
       
  1817   if ((dinf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1818     return -100;
       
  1819 
       
  1820   bytesread = readAtomHeader(handle, dinf->atomhdr);
       
  1821   if (bytesread < 0)
       
  1822     return -1;
       
  1823   totalbytesread += bytesread;
       
  1824 
       
  1825   if (dinf->atomhdr->type != ATOMTYPE_DINF)
       
  1826     return -1;
       
  1827 
       
  1828 
       
  1829   while ((mp4_u32)totalbytesread < dinf->atomhdr->size)
       
  1830   {
       
  1831     mp4_u32 type;
       
  1832 
       
  1833 
       
  1834     if (peekData(handle, handle->buf, 8) < 0)
       
  1835       return -1;
       
  1836 
       
  1837     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  1838 
       
  1839     switch (type)
       
  1840     {
       
  1841     case ATOMTYPE_DREF:
       
  1842 
       
  1843       if (dinf->dref) /* DINF has already been read, more than one is not allowed */
       
  1844         return -1;
       
  1845 
       
  1846       if ((dinf->dref = (dataReferenceAtom *)mp4malloc(sizeof(dataReferenceAtom))) == NULL)
       
  1847         return -100;
       
  1848 
       
  1849       bytesread = readDREF(handle, dinf->dref);
       
  1850       if (bytesread < 0)
       
  1851         return -1;
       
  1852       totalbytesread += bytesread;
       
  1853 
       
  1854       break;
       
  1855 
       
  1856     default:
       
  1857 
       
  1858       return -1;
       
  1859     }
       
  1860   }
       
  1861 
       
  1862   return totalbytesread;
       
  1863 }
       
  1864 
       
  1865 
       
  1866 /*
       
  1867  * Function:
       
  1868  *
       
  1869  *   mp4_i32 readDREF(MP4HandleImp handle,
       
  1870  *                    dataReferenceAtom *dref)
       
  1871  *
       
  1872  * Description:
       
  1873  *
       
  1874  *   This function parses one DREF atom.
       
  1875  *
       
  1876  * Parameters:
       
  1877  *
       
  1878  *   handle             MP4 library handle
       
  1879  *   dref               DREF pointer
       
  1880  *
       
  1881  * Return value:
       
  1882  *
       
  1883  *   Negative integer   Error
       
  1884  *   >= 0               Success. Value tells how many bytes were read.
       
  1885  *
       
  1886  */
       
  1887 mp4_i32 readDREF(MP4HandleImp handle, dataReferenceAtom *dref)
       
  1888 {
       
  1889   mp4_i32 bytesread;
       
  1890   mp4_i32 totalbytesread = 0;
       
  1891 
       
  1892 
       
  1893   if ((dref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1894     return -100;
       
  1895 
       
  1896   bytesread = readFullAtomHeader(handle, dref->atomhdr);
       
  1897   if (bytesread < 0)
       
  1898     return -1;
       
  1899   totalbytesread += bytesread;
       
  1900 
       
  1901   if (dref->atomhdr->type != ATOMTYPE_DREF)
       
  1902     return -1;
       
  1903 
       
  1904 
       
  1905   bytesread = readData(handle, handle->buf, 4);
       
  1906   if (bytesread < 0)
       
  1907     return -1;
       
  1908   dref->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  1909   totalbytesread += bytesread;
       
  1910 
       
  1911   if (dref->entryCount != 1)
       
  1912     return -1;
       
  1913 
       
  1914   while ((mp4_u32)totalbytesread < dref->atomhdr->size)
       
  1915   {
       
  1916     bytesread = readUnknown(handle);
       
  1917     if (bytesread < 0)
       
  1918       return -1;
       
  1919     totalbytesread += bytesread;
       
  1920   }
       
  1921   return totalbytesread;
       
  1922 }
       
  1923 
       
  1924 
       
  1925 /*
       
  1926  * Function:
       
  1927  *
       
  1928  *   mp4_i32 readURL(MP4HandleImp handle,
       
  1929  *                   dataEntryURLAtom *url)
       
  1930  *
       
  1931  * Description:
       
  1932  *
       
  1933  *   This function parses one URL atom.
       
  1934  *
       
  1935  * Parameters:
       
  1936  *
       
  1937  *   handle             MP4 library handle
       
  1938  *   url                URL pointer
       
  1939  *
       
  1940  * Return value:
       
  1941  *
       
  1942  *   Negative integer   Error
       
  1943  *   >= 0               Success. Value tells how many bytes were read.
       
  1944  *
       
  1945  */
       
  1946 mp4_i32 readURL(MP4HandleImp handle, dataEntryURLAtom *url)
       
  1947 {
       
  1948   mp4_i32 bytesread;
       
  1949   mp4_i32 totalbytesread = 0;
       
  1950 
       
  1951 
       
  1952   if ((url->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  1953     return -100;
       
  1954 
       
  1955   bytesread = readFullAtomHeader(handle, url->atomhdr);
       
  1956   if (bytesread < 0)
       
  1957     return -1;
       
  1958   totalbytesread += bytesread;
       
  1959 
       
  1960   if (url->atomhdr->type != ATOMTYPE_URL)
       
  1961     return -1;
       
  1962 
       
  1963 
       
  1964   if (!(url->atomhdr->flags[0] == 0x00 &&
       
  1965         url->atomhdr->flags[1] == 0x00 &&
       
  1966         url->atomhdr->flags[2] == 0x01))
       
  1967     return -1;
       
  1968 
       
  1969   return totalbytesread;
       
  1970 }
       
  1971 
       
  1972 
       
  1973 /*
       
  1974  * Function:
       
  1975  *
       
  1976  *   mp4_i32 readURN(MP4HandleImp handle,
       
  1977  *                   dataEntryURNAtom *urn)
       
  1978  *
       
  1979  * Description:
       
  1980  *
       
  1981  *   This function parses one URN atom.
       
  1982  *
       
  1983  * Parameters:
       
  1984  *
       
  1985  *   handle             MP4 library handle
       
  1986  *   urn                URN pointer
       
  1987  *
       
  1988  * Return value:
       
  1989  *
       
  1990  *   Negative integer   Error
       
  1991  *   >= 0               Success. Value tells how many bytes were read.
       
  1992  *
       
  1993  */
       
  1994 mp4_i32 readURN(MP4HandleImp handle, dataEntryURNAtom *urn)
       
  1995 {
       
  1996   mp4_i32 bytesread;
       
  1997   mp4_i32 totalbytesread = 0;
       
  1998 
       
  1999 
       
  2000   if ((urn->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2001     return -100;
       
  2002 
       
  2003   bytesread = readFullAtomHeader(handle, urn->atomhdr);
       
  2004   if (bytesread < 0)
       
  2005     return -1;
       
  2006   totalbytesread += bytesread;
       
  2007 
       
  2008   if (urn->atomhdr->type != ATOMTYPE_URN)
       
  2009     return -1;
       
  2010 
       
  2011 
       
  2012   if (!(urn->atomhdr->flags[0] == 0x00 &&
       
  2013         urn->atomhdr->flags[1] == 0x00 &&
       
  2014         urn->atomhdr->flags[2] == 0x01))
       
  2015     return -1;
       
  2016 
       
  2017   return totalbytesread;
       
  2018 }
       
  2019 
       
  2020 
       
  2021 /*
       
  2022  * Function:
       
  2023  *
       
  2024  *   mp4_i32 readSTBL(MP4HandleImp handle,
       
  2025  *                    sampleTableAtom *stbl)
       
  2026  *
       
  2027  * Description:
       
  2028  *
       
  2029  *   This function parses one STBL atom.
       
  2030  *
       
  2031  * Parameters:
       
  2032  *
       
  2033  *   handle             MP4 library handle
       
  2034  *   stbl               STBL pointer
       
  2035  *
       
  2036  * Return value:
       
  2037  *
       
  2038  *   Negative integer   Error
       
  2039  *   >= 0               Success. Value tells how many bytes were read.
       
  2040  *
       
  2041  */
       
  2042 mp4_i32 readSTBL(MP4HandleImp handle, sampleTableAtom *stbl)
       
  2043 {
       
  2044   mp4_i32 bytesread;
       
  2045   mp4_i32 totalbytesread = 0;
       
  2046 
       
  2047 
       
  2048   if ((stbl->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2049     return -100;
       
  2050 
       
  2051   bytesread = readAtomHeader(handle, stbl->atomhdr);
       
  2052   if (bytesread < 0)
       
  2053     return -1;
       
  2054   totalbytesread += bytesread;
       
  2055 
       
  2056   if (stbl->atomhdr->type != ATOMTYPE_STBL)
       
  2057     return -1;
       
  2058 
       
  2059 
       
  2060   while ((mp4_u32)totalbytesread < stbl->atomhdr->size)
       
  2061   {
       
  2062     mp4_u32 type;
       
  2063 
       
  2064 
       
  2065     if (peekData(handle, handle->buf, 8) < 0)
       
  2066       return -1;
       
  2067 
       
  2068     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  2069 
       
  2070     switch (type)
       
  2071     {
       
  2072     case ATOMTYPE_STTS:
       
  2073 
       
  2074       if (stbl->stts) /* STTS has already been read, more than one is not allowed */
       
  2075         return -1;
       
  2076 
       
  2077       if ((stbl->stts = (timeToSampleAtom *)mp4malloc(sizeof(timeToSampleAtom))) == NULL)
       
  2078         return -100;
       
  2079 
       
  2080       bytesread = readSTTS(handle, stbl->stts);
       
  2081       if (bytesread < 0)
       
  2082         return -1;
       
  2083       totalbytesread += bytesread;
       
  2084 
       
  2085       break;
       
  2086 
       
  2087     case ATOMTYPE_CTTS:
       
  2088 
       
  2089       if (stbl->ctts) /* CTTS has already been read, more than one is not allowed */
       
  2090         return -1;
       
  2091 
       
  2092       if ((stbl->ctts = (compositionTimeToSampleAtom *)mp4malloc(sizeof(compositionTimeToSampleAtom))) == NULL)
       
  2093         return -100;
       
  2094 
       
  2095       bytesread = readCTTS(handle, stbl->ctts);
       
  2096       if (bytesread < 0)
       
  2097         return -1;
       
  2098       totalbytesread += bytesread;
       
  2099 
       
  2100       break;
       
  2101 
       
  2102     case ATOMTYPE_STSS:
       
  2103 
       
  2104       if (stbl->stss) /* STSS has already been read, more than one is not allowed */
       
  2105         return -1;
       
  2106 
       
  2107       if ((stbl->stss = (syncSampleAtom *)mp4malloc(sizeof(syncSampleAtom))) == NULL)
       
  2108         return -100;
       
  2109 
       
  2110       bytesread = readSTSS(handle, stbl->stss);
       
  2111       if (bytesread < 0)
       
  2112         return -1;
       
  2113       totalbytesread += bytesread;
       
  2114 
       
  2115       break;
       
  2116 
       
  2117     case ATOMTYPE_STSD:
       
  2118 
       
  2119       if (stbl->stsd) /* STSD has already been read, more than one is not allowed */
       
  2120         return -1;
       
  2121 
       
  2122       if ((stbl->stsd = (sampleDescriptionAtom *)mp4malloc(sizeof(sampleDescriptionAtom))) == NULL)
       
  2123         return -100;
       
  2124 
       
  2125       bytesread = readSTSD(handle, stbl->stsd);
       
  2126       if (bytesread < 0)
       
  2127         return -1;
       
  2128       totalbytesread += bytesread;
       
  2129 
       
  2130       break;
       
  2131 
       
  2132     case ATOMTYPE_STSZ:
       
  2133 
       
  2134       if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */
       
  2135         return -1;
       
  2136 
       
  2137       if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL)
       
  2138         return -100;
       
  2139 
       
  2140       bytesread = readSTSZ(handle, stbl->stsz);
       
  2141       if (bytesread < 0)
       
  2142         return -1;
       
  2143       totalbytesread += bytesread;
       
  2144 
       
  2145       break;
       
  2146 
       
  2147     case ATOMTYPE_STZ2:
       
  2148 
       
  2149       if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */
       
  2150         return -1;
       
  2151 
       
  2152       if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL)
       
  2153         return -100;
       
  2154 
       
  2155       bytesread = readSTZ2(handle, stbl->stsz);
       
  2156       if (bytesread < 0)
       
  2157         return -1;
       
  2158       totalbytesread += bytesread;
       
  2159 
       
  2160       break;
       
  2161 
       
  2162     case ATOMTYPE_STSC:
       
  2163 
       
  2164       if (stbl->stsc) /* STSC has already been read, more than one is not allowed */
       
  2165         return -1;
       
  2166 
       
  2167       if ((stbl->stsc = (sampleToChunkAtom *)mp4malloc(sizeof(sampleToChunkAtom))) == NULL)
       
  2168         return -100;
       
  2169 
       
  2170       bytesread = readSTSC(handle, stbl->stsc);
       
  2171       if (bytesread < 0)
       
  2172         return -1;
       
  2173       totalbytesread += bytesread;
       
  2174 
       
  2175       break;
       
  2176 
       
  2177     case ATOMTYPE_STCO:
       
  2178 
       
  2179       if (stbl->stco) /* STCO or CO64 has already been read, more than one is not allowed */
       
  2180         return -1;
       
  2181 
       
  2182       if ((stbl->stco = (chunkOffsetAtom *)mp4malloc(sizeof(chunkOffsetAtom))) == NULL)
       
  2183         return -100;
       
  2184       
       
  2185       stbl->is32BitOffsets = ETrue;
       
  2186       bytesread = readSTCO(handle, stbl->stco);
       
  2187       if (bytesread < 0)
       
  2188         return -1;
       
  2189       totalbytesread += bytesread;
       
  2190 
       
  2191       break;
       
  2192 
       
  2193     case ATOMTYPE_CO64:
       
  2194 
       
  2195       if (stbl->stco64) /* STCO or CO64 has already been read, more than one is not allowed */
       
  2196         return -1;
       
  2197 
       
  2198       if ((stbl->stco64 = (chunkOffset64Atom *)mp4malloc(sizeof(chunkOffset64Atom))) == NULL)
       
  2199         return -100;
       
  2200       
       
  2201       stbl->is32BitOffsets = EFalse;
       
  2202       bytesread = readCO64(handle, stbl->stco64);
       
  2203       if (bytesread < 0)
       
  2204         return -1;
       
  2205       totalbytesread += bytesread;
       
  2206 
       
  2207       break;
       
  2208 
       
  2209     case ATOMTYPE_SDTP:
       
  2210       if (stbl->sdtp) /* SDTP has already been read, more than one is not allowed */
       
  2211         return -1;
       
  2212       
       
  2213       if ((stbl->sdtp = (sampleDependencyAtom *)mp4malloc(sizeof(sampleDependencyAtom))) == NULL)
       
  2214         return -100;
       
  2215 
       
  2216       if (!stbl->stsz)
       
  2217     	  {
       
  2218     	  return -1;
       
  2219     	  }
       
  2220 
       
  2221 	  // sample_count of SDTP is taken from the sample_count in the Sample Size Box ('stsz') or
       
  2222 	  // Compact Sample Size Box (‘stz2’). 
       
  2223 	  bytesread = readSDTP(handle, stbl->sdtp, stbl->stsz->sampleCount);
       
  2224     	  
       
  2225       if (bytesread < 0)
       
  2226         return -1;
       
  2227       totalbytesread += bytesread;
       
  2228       break;
       
  2229 
       
  2230     default: /* Other atoms are not needed */
       
  2231 
       
  2232       bytesread = readUnknown(handle);
       
  2233       if (bytesread < 0)
       
  2234         return -1;
       
  2235       totalbytesread += bytesread;
       
  2236 
       
  2237       break;
       
  2238     }
       
  2239   }
       
  2240 
       
  2241   return totalbytesread;
       
  2242 }
       
  2243 
       
  2244 
       
  2245 /*
       
  2246  * Function:
       
  2247  *
       
  2248  *   mp4_i32 readSTTS(MP4HandleImp handle,
       
  2249  *                    timeToSampleAtom *stts)
       
  2250  *
       
  2251  * Description:
       
  2252  *
       
  2253  *   This function parses one STTS atom.
       
  2254  *
       
  2255  * Parameters:
       
  2256  *
       
  2257  *   handle             MP4 library handle
       
  2258  *   stts               STTS pointer
       
  2259  *
       
  2260  * Return value:
       
  2261  *
       
  2262  *   Negative integer   Error
       
  2263  *   >= 0               Success. Value tells how many bytes were read.
       
  2264  *
       
  2265  */
       
  2266 mp4_i32 readSTTS(MP4HandleImp handle, timeToSampleAtom *stts)
       
  2267 {
       
  2268   mp4_i32 bytesread;
       
  2269   mp4_i32 totalbytesread = 0;
       
  2270   mp4_u32 i;
       
  2271 
       
  2272 
       
  2273   if ((stts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2274     return -100;
       
  2275 
       
  2276   bytesread = readFullAtomHeader(handle, stts->atomhdr);
       
  2277   if (bytesread < 0)
       
  2278     return -1;
       
  2279   totalbytesread += bytesread;
       
  2280 
       
  2281   if (stts->atomhdr->type != ATOMTYPE_STTS)
       
  2282     return -1;
       
  2283 
       
  2284 
       
  2285   bytesread = readData(handle, handle->buf, 4);
       
  2286   if (bytesread < 0)
       
  2287     return -1;
       
  2288   stts->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  2289   totalbytesread += bytesread;
       
  2290   
       
  2291   if ( stts->entryCount )
       
  2292   {
       
  2293 	  stts->sampleCount = (mp4_u32 *)mp4malloc(stts->entryCount * sizeof(mp4_u32));
       
  2294 	  if (stts->sampleCount == NULL)
       
  2295 	    return -1;
       
  2296 	  stts->sampleDelta = (mp4_i32 *)mp4malloc(stts->entryCount * sizeof(mp4_i32));
       
  2297 	  if (stts->sampleDelta == NULL)
       
  2298 	    return -1;
       
  2299 
       
  2300 	  for (i = 0; i < stts->entryCount; i++)
       
  2301 	  {
       
  2302 	    bytesread = readData(handle, handle->buf, 8);
       
  2303 	    if (bytesread < 0)
       
  2304 	      return -1;
       
  2305 
       
  2306 	    stts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf));
       
  2307 	    stts->sampleDelta[i] = i32endian(*((mp4_i32 *)(handle->buf+4)));
       
  2308 
       
  2309 	    totalbytesread += bytesread;
       
  2310 	  }
       
  2311   }
       
  2312 
       
  2313   return totalbytesread;
       
  2314 }
       
  2315 
       
  2316 
       
  2317 /*
       
  2318  * Function:
       
  2319  *
       
  2320  *   mp4_i32 readCTTS(MP4HandleImp handle,
       
  2321  *                    compositionTimeToSampleAtom *ctts)
       
  2322  *
       
  2323  * Description:
       
  2324  *
       
  2325  *   This function parses one CTTS atom.
       
  2326  *
       
  2327  * Parameters:
       
  2328  *
       
  2329  *   handle             MP4 library handle
       
  2330  *   ctts               CTTS pointer
       
  2331  *
       
  2332  * Return value:
       
  2333  *
       
  2334  *   Negative integer   Error
       
  2335  *   >= 0               Success. Value tells how many bytes were read.
       
  2336  *
       
  2337  */
       
  2338 mp4_i32 readCTTS(MP4HandleImp handle, compositionTimeToSampleAtom *ctts)
       
  2339 {
       
  2340   mp4_i32 bytesread;
       
  2341   mp4_i32 totalbytesread = 0;
       
  2342   mp4_u32 i;
       
  2343 
       
  2344 
       
  2345   if ((ctts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2346     return -100;
       
  2347 
       
  2348   bytesread = readFullAtomHeader(handle, ctts->atomhdr);
       
  2349   if (bytesread < 0)
       
  2350     return -1;
       
  2351   totalbytesread += bytesread;
       
  2352 
       
  2353   if (ctts->atomhdr->type != ATOMTYPE_CTTS)
       
  2354     return -1;
       
  2355 
       
  2356   bytesread = readData(handle, handle->buf, 4);
       
  2357   if (bytesread < 0)
       
  2358     return -1;
       
  2359   ctts->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  2360   totalbytesread += bytesread;
       
  2361 
       
  2362   if ( ctts->entryCount )
       
  2363   {
       
  2364 	  ctts->sampleCount = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32));
       
  2365 	  if (ctts->sampleCount == NULL)
       
  2366 	    return -1;
       
  2367 	  ctts->sampleOffset = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32));
       
  2368 	  if (ctts->sampleOffset == NULL)
       
  2369 	    return -1;
       
  2370 
       
  2371 	  for (i = 0; i < ctts->entryCount; i++)
       
  2372 	  {
       
  2373 	    bytesread = readData(handle, handle->buf, 8);
       
  2374 	    if (bytesread < 0)
       
  2375 	      return -1;
       
  2376 
       
  2377 	    ctts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf));
       
  2378 	    ctts->sampleOffset[i] = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  2379 
       
  2380 	    totalbytesread += bytesread;
       
  2381 	  }
       
  2382   }
       
  2383   return totalbytesread;
       
  2384 }
       
  2385 
       
  2386 
       
  2387 /*
       
  2388  * Function:
       
  2389  *
       
  2390  *   mp4_i32 readSTSS(MP4HandleImp handle,
       
  2391  *                    syncSampleAtom *stss)
       
  2392  *
       
  2393  * Description:
       
  2394  *
       
  2395  *   This function parses one STSS atom.
       
  2396  *
       
  2397  * Parameters:
       
  2398  *
       
  2399  *   handle             MP4 library handle
       
  2400  *   stss               STSS pointer
       
  2401  *
       
  2402  * Return value:
       
  2403  *
       
  2404  *   Negative integer   Error
       
  2405  *   >= 0               Success. Value tells how many bytes were read.
       
  2406  *
       
  2407  */
       
  2408 mp4_i32 readSTSS(MP4HandleImp handle, syncSampleAtom *stss)
       
  2409 {
       
  2410   mp4_i32 bytesread;
       
  2411   mp4_i32 totalbytesread = 0;
       
  2412   mp4_u32 i;
       
  2413 
       
  2414 
       
  2415   if ((stss->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2416     return -100;
       
  2417 
       
  2418   bytesread = readFullAtomHeader(handle, stss->atomhdr);
       
  2419   if (bytesread < 0)
       
  2420     return -1;
       
  2421   totalbytesread += bytesread;
       
  2422 
       
  2423   if (stss->atomhdr->type != ATOMTYPE_STSS)
       
  2424     return -1;
       
  2425 
       
  2426 
       
  2427   bytesread = readData(handle, handle->buf, 4);
       
  2428   if (bytesread < 0)
       
  2429     return -1;
       
  2430   stss->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  2431   totalbytesread += bytesread;
       
  2432 
       
  2433   if ( stss->entryCount )
       
  2434   {
       
  2435 	  stss->sampleNumber = (mp4_u32 *)mp4malloc(stss->entryCount * sizeof(mp4_u32));
       
  2436 	  if (stss->sampleNumber == NULL)
       
  2437 	    return -1;
       
  2438 
       
  2439 	  for (i = 0; i < stss->entryCount; i++)
       
  2440 	  {
       
  2441 	    bytesread = readData(handle, handle->buf, 4);
       
  2442 	    if (bytesread < 0)
       
  2443 	      return -1;
       
  2444 
       
  2445 	    stss->sampleNumber[i] = u32endian(*((mp4_u32 *)handle->buf));
       
  2446 
       
  2447 	    totalbytesread += bytesread;
       
  2448 	  }
       
  2449   }
       
  2450 
       
  2451   return totalbytesread;
       
  2452 }
       
  2453 
       
  2454 
       
  2455 /*
       
  2456  * Function:
       
  2457  *
       
  2458  *   mp4_i32 readSTSD(MP4HandleImp handle,
       
  2459  *                    sampleDescriptionAtom *stsd)
       
  2460  *
       
  2461  * Description:
       
  2462  *
       
  2463  *   This function parses one STSD atom.
       
  2464  *
       
  2465  * Parameters:
       
  2466  *
       
  2467  *   handle             MP4 library handle
       
  2468  *   stsd               STSD pointer
       
  2469  *
       
  2470  * Return value:
       
  2471  *
       
  2472  *   Negative integer   Error
       
  2473  *   >= 0               Success. Value tells how many bytes were read.
       
  2474  *
       
  2475  */
       
  2476 mp4_i32 readSTSD(MP4HandleImp handle, sampleDescriptionAtom *stsd)
       
  2477 	{
       
  2478 	mp4_i32 bytesread;
       
  2479 	mp4_i32 totalbytesread = 0;
       
  2480 	mp4_u32 totalsampleentriesread = 0;
       
  2481 	mp4_u32 unknownsampleentriesread = 0;
       
  2482 	mp4_bool skipentries = 0;
       
  2483 
       
  2484 	if ((stsd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2485         {
       
  2486         // for memory cleanup set entrycount to allocated num of entries.
       
  2487         stsd->entryCount = totalsampleentriesread;
       
  2488 	    return -100;
       
  2489         }
       
  2490 
       
  2491 	bytesread = readFullAtomHeader(handle, stsd->atomhdr);
       
  2492 	if (bytesread < 0)
       
  2493 	    {
       
  2494 	    // for memory cleanup set entrycount to allocated num of entries.
       
  2495 	    stsd->entryCount = totalsampleentriesread;
       
  2496 	    return -1;
       
  2497 	    }
       
  2498 	totalbytesread += bytesread;
       
  2499 
       
  2500 	if (stsd->atomhdr->type != ATOMTYPE_STSD)
       
  2501 	    {
       
  2502 	    // for memory cleanup set entrycount to allocated num of entries.
       
  2503 	    stsd->entryCount = totalsampleentriesread;
       
  2504 	    return -1;
       
  2505 	    }
       
  2506 
       
  2507 	bytesread = readData(handle, handle->buf, 4);
       
  2508 	if (bytesread < 0)
       
  2509 	    {
       
  2510 	    // for memory cleanup set entrycount to allocated num of entries.
       
  2511 	    stsd->entryCount = totalsampleentriesread;
       
  2512 	    return -1;
       
  2513 	    }
       
  2514 	stsd->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  2515 	totalbytesread += bytesread;
       
  2516 
       
  2517 	mp4_u32 type;
       
  2518 	while ((mp4_u32)totalbytesread < stsd->atomhdr->size)
       
  2519 		{	
       
  2520 		// if the number of entries read already surpasses the number of entries specified 
       
  2521 		// within the STSD atom, the file is corrupted.
       
  2522 		if ((totalsampleentriesread + unknownsampleentriesread) >= stsd->entryCount)
       
  2523 			{
       
  2524 			// for memory cleanup set entrycount to allocated num of entries.
       
  2525 			stsd->entryCount = totalsampleentriesread;
       
  2526   	  		return -1;    	    	
       
  2527 			}
       
  2528 
       
  2529 		// read the next sample type
       
  2530 		if (peekData(handle, handle->buf, 8) < 0)
       
  2531 	        {
       
  2532 	        // for memory cleanup set entrycount to allocated num of entries.
       
  2533 	        stsd->entryCount = totalsampleentriesread;
       
  2534 		    return -1;
       
  2535 	        }
       
  2536 		type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  2537     
       
  2538 		// if the max sample entiries supported by the library has been reached 
       
  2539 		if ((stsd->entryCount > STSDMAXSAMPLEENTRYCOUNT) && (totalsampleentriesread == STSDMAXSAMPLEENTRYCOUNT))
       
  2540 			{
       
  2541 			// skip reading the rest of the entries to make sure no more than max count of sample entries 
       
  2542 			// will be processed, so that cleanup will always work. 
       
  2543 			type = 0;
       
  2544 			skipentries = 1;
       
  2545 			}
       
  2546 
       
  2547 		switch (type)
       
  2548 			{
       
  2549 			case ATOMTYPE_MP4V:
       
  2550 				{
       
  2551 				if (stsd->mp4v[totalsampleentriesread]) /* MP4V[totalsampleentriesread] has already been read, more than one is not allowed */ 
       
  2552 			        {
       
  2553 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2554 			        stsd->entryCount = totalsampleentriesread;
       
  2555 				    return -1;
       
  2556 			        }
       
  2557 		
       
  2558 				if ((stsd->mp4v[totalsampleentriesread] = (visualSampleEntry *)mp4malloc(sizeof(visualSampleEntry))) == NULL)
       
  2559 			        {
       
  2560 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2561 			        stsd->entryCount = totalsampleentriesread;
       
  2562 				    return -100;
       
  2563 			        }
       
  2564 		
       
  2565 				bytesread = readMP4V(handle, stsd->mp4v[totalsampleentriesread]);
       
  2566 				totalsampleentriesread++;
       
  2567 				if (bytesread < 0)
       
  2568 			        {
       
  2569 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2570 			        stsd->entryCount = totalsampleentriesread;
       
  2571 				    return -1;
       
  2572 			        }
       
  2573 				totalbytesread += bytesread;
       
  2574 				break;
       
  2575 				}
       
  2576 
       
  2577 			case ATOMTYPE_MP4A:
       
  2578 				{	
       
  2579 				if (stsd->mp4a[totalsampleentriesread]) /* MP4A[totalsampleentriesread] has already been read, more than one is not allowed */
       
  2580 			        {
       
  2581 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2582 			        stsd->entryCount = totalsampleentriesread;
       
  2583 				    return -1;
       
  2584 			        }
       
  2585 
       
  2586 				if ((stsd->mp4a[totalsampleentriesread] = (audioSampleEntry *)mp4malloc(sizeof(audioSampleEntry))) == NULL)
       
  2587 			        {
       
  2588 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2589 			        stsd->entryCount = totalsampleentriesread;
       
  2590 				    return -100;
       
  2591 			        }
       
  2592 
       
  2593 				bytesread = readMP4A(handle, stsd->mp4a[totalsampleentriesread]);
       
  2594 				totalsampleentriesread++;
       
  2595 				if (bytesread < 0)
       
  2596 			        {
       
  2597 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2598 			        stsd->entryCount = totalsampleentriesread;
       
  2599 				    return -1;
       
  2600 			        }
       
  2601 				totalbytesread += bytesread;
       
  2602 				break;
       
  2603 				}
       
  2604 
       
  2605 			case ATOMTYPE_MP4S:
       
  2606 				{
       
  2607 				if (stsd->mp4s[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */
       
  2608 			        {
       
  2609 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2610 			        stsd->entryCount = totalsampleentriesread;
       
  2611 				    return -1;
       
  2612 			        }
       
  2613 
       
  2614 				if ((stsd->mp4s[totalsampleentriesread] = (mpegSampleEntry *)mp4malloc(sizeof(mpegSampleEntry))) == NULL)
       
  2615 			        {
       
  2616 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2617 			        stsd->entryCount = totalsampleentriesread;
       
  2618 				    return -100;
       
  2619 			        }
       
  2620 
       
  2621 				bytesread = readMP4S(handle, stsd->mp4s[totalsampleentriesread]);
       
  2622 				totalsampleentriesread++;
       
  2623 				if (bytesread < 0)
       
  2624 			        {
       
  2625 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2626 			        stsd->entryCount = totalsampleentriesread;
       
  2627 				    return -1;
       
  2628 			        }
       
  2629 				totalbytesread += bytesread;
       
  2630 				}
       
  2631 				break;
       
  2632 
       
  2633 			case ATOMTYPE_S263:
       
  2634 				{
       
  2635 				if (stsd->s263[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */
       
  2636 			        {
       
  2637 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2638 			        stsd->entryCount = totalsampleentriesread;
       
  2639 				    return -1;
       
  2640 			        }
       
  2641 
       
  2642 				if ((stsd->s263[totalsampleentriesread] = (h263SampleEntry *)mp4malloc(sizeof(h263SampleEntry))) == NULL)
       
  2643 			        {
       
  2644 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2645 			        stsd->entryCount = totalsampleentriesread;
       
  2646 				    return -100;
       
  2647 			        }
       
  2648 
       
  2649 				bytesread = readS263(handle, stsd->s263[totalsampleentriesread]);
       
  2650 				totalsampleentriesread++;
       
  2651 				if (bytesread < 0)
       
  2652 			        {
       
  2653 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2654 			        stsd->entryCount = totalsampleentriesread;
       
  2655 				    return -1;
       
  2656 			        }
       
  2657 				totalbytesread += bytesread;
       
  2658 				}
       
  2659 				break;
       
  2660 
       
  2661 			case ATOMTYPE_SAMR:
       
  2662 				{
       
  2663 				if (stsd->samr[totalsampleentriesread]) /* SAMR has already been read, more than one is not allowed */
       
  2664 			        {
       
  2665 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2666 			        stsd->entryCount = totalsampleentriesread;
       
  2667 				    return -1;
       
  2668 			        }
       
  2669 
       
  2670 				if ((stsd->samr[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL)
       
  2671 			        {
       
  2672 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2673 			        stsd->entryCount = totalsampleentriesread;
       
  2674 				    return -100;
       
  2675 			        }
       
  2676 
       
  2677 				bytesread = readSAMR(handle, stsd->samr[totalsampleentriesread]);
       
  2678 				totalsampleentriesread++;
       
  2679 				if (bytesread < 0)
       
  2680 			        {
       
  2681 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2682 			        stsd->entryCount = totalsampleentriesread;
       
  2683 				    return -1;
       
  2684 			        }
       
  2685 				totalbytesread += bytesread;
       
  2686 				}
       
  2687 				break;
       
  2688 
       
  2689 			case ATOMTYPE_SAWB:
       
  2690 				{
       
  2691 				if (stsd->sawb[totalsampleentriesread]) /* SAWB has already been read, more than one is not allowed */
       
  2692 			        {
       
  2693 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2694 			        stsd->entryCount = totalsampleentriesread;
       
  2695 				    return -1;
       
  2696 			        }
       
  2697 
       
  2698 				if ((stsd->sawb[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL)
       
  2699 			        {
       
  2700 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2701 			        stsd->entryCount = totalsampleentriesread;
       
  2702 				    return -100;
       
  2703 			        }
       
  2704 
       
  2705 				bytesread = readSAWB(handle, stsd->sawb[totalsampleentriesread]);
       
  2706 				totalsampleentriesread++;
       
  2707 				if (bytesread < 0)
       
  2708 			        {
       
  2709 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2710 			        stsd->entryCount = totalsampleentriesread;
       
  2711 				    return -1;
       
  2712 			        }
       
  2713 				totalbytesread += bytesread;
       
  2714 				}
       
  2715 				break;
       
  2716 
       
  2717 			case ATOMTYPE_AVC1:
       
  2718 				{
       
  2719 				if (stsd->avc1[totalsampleentriesread]) /* AVC1 has already been read, more than one is not allowed */
       
  2720 					{
       
  2721 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2722 			        stsd->entryCount = totalsampleentriesread;
       
  2723 				    return -1;
       
  2724 					}
       
  2725 				if ((stsd->avc1[totalsampleentriesread] = (avcSampleEntry *)mp4malloc(sizeof(avcSampleEntry))) == NULL)
       
  2726 			        {
       
  2727 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2728 			        stsd->entryCount = totalsampleentriesread;
       
  2729 				    return -100;
       
  2730 			        }
       
  2731 
       
  2732 				bytesread = readAVC1(handle, stsd->avc1[totalsampleentriesread]);
       
  2733 				totalsampleentriesread++;
       
  2734 				if (bytesread < 0)
       
  2735 					{
       
  2736 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2737 			        stsd->entryCount = totalsampleentriesread;
       
  2738 				    return -1;
       
  2739 			        }
       
  2740 				totalbytesread += bytesread;
       
  2741 				}
       
  2742 				break;
       
  2743 
       
  2744 			case ATOMTYPE_SQCP:
       
  2745 				{
       
  2746 				if (stsd->sqcp[totalsampleentriesread]) /* SQCP has already been read, more than one is not allowed */
       
  2747 			        {
       
  2748 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2749 			        stsd->entryCount = totalsampleentriesread;
       
  2750 				    return -1;
       
  2751 			        }
       
  2752 				if ((stsd->sqcp[totalsampleentriesread] = (qcelpSampleEntry *)mp4malloc(sizeof(qcelpSampleEntry))) == NULL)
       
  2753 			        {
       
  2754 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2755 			        stsd->entryCount = totalsampleentriesread;
       
  2756 				    return -100;
       
  2757 			        }
       
  2758 
       
  2759 				bytesread = readSQCP(handle, stsd->sqcp[totalsampleentriesread]);
       
  2760 				totalsampleentriesread++;
       
  2761 				if (bytesread < 0)
       
  2762 					{
       
  2763 			        // for memory cleanup set entrycount to allocated num of entries.
       
  2764 			        stsd->entryCount = totalsampleentriesread;
       
  2765 				    return -1;
       
  2766 			        }
       
  2767 				totalbytesread += bytesread;
       
  2768 				}
       
  2769 				break;
       
  2770 
       
  2771 			default: /* Other atoms are not needed */
       
  2772 				// no need to increment totalsampleentriesread as no memory is allocated for unsupported 
       
  2773 				// or unrecognized sample types.  Alternatively, increment the count of unknown samples.   
       
  2774 				// This is for ensure if a non-audio/video track can properly be parsed without being 
       
  2775 				// recongized as an invalid format file.
       
  2776 				unknownsampleentriesread++;
       
  2777 				bytesread = readUnknown(handle);
       
  2778 				if (bytesread < 0)
       
  2779 		    		{
       
  2780 		    		// for memory cleanup set entrycount to allocated num of entries.
       
  2781 		    		stsd->entryCount = totalsampleentriesread;
       
  2782 		    		return -1;
       
  2783 		    		}
       
  2784 				totalbytesread += bytesread;
       
  2785 				break;
       
  2786 			}
       
  2787 		}
       
  2788 
       
  2789 	// if the STSD atom's entry count is NOT the same as the number (supported & unsupported) entries parsed,
       
  2790 	// the atom is likely a corrupted one. 
       
  2791 	if ((totalsampleentriesread + unknownsampleentriesread) != stsd->entryCount)
       
  2792 		{
       
  2793 		// for memory cleanup set entrycount to allocated num of entries.
       
  2794 		stsd->entryCount = totalsampleentriesread;
       
  2795 		return -1;
       
  2796 		}
       
  2797 	else 
       
  2798 		{
       
  2799 		// if the STSD atom's entry count is the same as the number of (supported & unsupported) entries 
       
  2800 		// parsed, check if some entries are skipped because the max sample entry count has been reached  
       
  2801 		if (skipentries) 
       
  2802 			{
       
  2803 			// if STSDMAXSAMPLEENTRYCOUNT was reached edit entrycount to make sure cleanup works.
       
  2804 			stsd->entryCount = STSDMAXSAMPLEENTRYCOUNT;
       
  2805 			}
       
  2806 		else if (unknownsampleentriesread > 0)
       
  2807 			{
       
  2808 			// unknown (unsupported) sample entries present, set the STSD entry count to the actual 
       
  2809 			// number of supported sample entries detected
       
  2810 			stsd->entryCount = totalsampleentriesread;
       
  2811 			}
       
  2812 		}
       
  2813   
       
  2814 	return totalbytesread;
       
  2815 	}
       
  2816 
       
  2817 
       
  2818 /*
       
  2819  * Function:
       
  2820  *
       
  2821  *   mp4_i32 readSTSZ(MP4HandleImp handle,
       
  2822  *                    sampleSizeAtom *stsz)
       
  2823  *
       
  2824  * Description:
       
  2825  *
       
  2826  *   This function parses one STSZ atom.
       
  2827  *
       
  2828  * Parameters:
       
  2829  *
       
  2830  *   handle             MP4 library handle
       
  2831  *   stsz               STSZ pointer
       
  2832  *
       
  2833  * Return value:
       
  2834  *
       
  2835  *   Negative integer   Error
       
  2836  *   >= 0               Success. Value tells how many bytes were read.
       
  2837  *
       
  2838  */
       
  2839 mp4_i32 readSTSZ(MP4HandleImp handle, sampleSizeAtom *stsz)
       
  2840 {
       
  2841   mp4_i32 bytesread;
       
  2842   mp4_i32 totalbytesread = 0;
       
  2843 
       
  2844 
       
  2845   if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2846     return -100;
       
  2847 
       
  2848   bytesread = readFullAtomHeader(handle, stsz->atomhdr);
       
  2849   if (bytesread < 0)
       
  2850     return -1;
       
  2851   totalbytesread += bytesread;
       
  2852 
       
  2853   if (stsz->atomhdr->type != ATOMTYPE_STSZ)
       
  2854     return -1;
       
  2855 
       
  2856 
       
  2857   bytesread = readData(handle, handle->buf, 4);
       
  2858   if (bytesread < 0)
       
  2859     return -1;
       
  2860   stsz->sampleSize = u32endian(*((mp4_u32 *)handle->buf));
       
  2861   totalbytesread += bytesread;
       
  2862 
       
  2863   bytesread = readData(handle, handle->buf, 4);
       
  2864   if (bytesread < 0)
       
  2865     return -1;
       
  2866   stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf));
       
  2867   totalbytesread += bytesread;
       
  2868 
       
  2869   // zero size samplesize means samples have different sizes, and those sizes are stored in sampleSizeEntries.
       
  2870   if ((stsz->sampleCount) && (stsz->sampleSize == 0))
       
  2871   {
       
  2872     mp4_u32 i;
       
  2873 
       
  2874     // check validity of stsz->sampleCount before allocating entrysize table.
       
  2875     if ( handle->moov->mvhd )
       
  2876         {
       
  2877         if ( handle->moov->mvhd->timeScale > 0 )
       
  2878             {
       
  2879             TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND;
       
  2880             TUint maxSampleCount;
       
  2881 
       
  2882             if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration
       
  2883                 {
       
  2884                 maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec;
       
  2885                 }
       
  2886             else    // 32bit duration
       
  2887                 {
       
  2888                 maxSampleCount = TUint((TUint( handle->moov->mvhd->duration  ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec;
       
  2889                 }
       
  2890 
       
  2891             if ( maxSampleCount < stsz->sampleCount )
       
  2892                 {
       
  2893                 // corrupted 
       
  2894                 return -1;
       
  2895                 }
       
  2896             }
       
  2897         }
       
  2898 
       
  2899     // allocate stsz->entrySize table
       
  2900     stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
       
  2901     if (stsz->entrySize == NULL)
       
  2902       return -1;
       
  2903 
       
  2904     for (i = 0; i < stsz->sampleCount; i++)
       
  2905     {
       
  2906       bytesread = readData(handle, handle->buf, 4);
       
  2907       if (bytesread < 0)
       
  2908         return -1;
       
  2909 
       
  2910       stsz->entrySize[i] = u32endian(*((mp4_u32 *)handle->buf));
       
  2911 
       
  2912       totalbytesread += bytesread;
       
  2913     }
       
  2914   }
       
  2915 
       
  2916   return totalbytesread;
       
  2917 }
       
  2918 
       
  2919 
       
  2920 /*
       
  2921  * Function:
       
  2922  *
       
  2923  *   mp4_i32 readSTZ2(MP4HandleImp handle,
       
  2924  *                    sampleSizeAtom *stsz)
       
  2925  *
       
  2926  * Description:
       
  2927  *
       
  2928  *   This function parses one STZ2 atom.
       
  2929  *
       
  2930  *   The result is placed in STSZ structure.
       
  2931  *
       
  2932  * Parameters:
       
  2933  *
       
  2934  *   handle             MP4 library handle
       
  2935  *   stsz               STSZ pointer
       
  2936  *
       
  2937  * Return value:
       
  2938  *
       
  2939  *   Negative integer   Error
       
  2940  *   >= 0               Success. Value tells how many bytes were read.
       
  2941  *
       
  2942  */
       
  2943 mp4_i32 readSTZ2(MP4HandleImp handle, sampleSizeAtom *stsz)
       
  2944 {
       
  2945   mp4_i32 bytesread;
       
  2946   mp4_i32 totalbytesread = 0;
       
  2947   mp4_u8  fieldsize;
       
  2948 
       
  2949 
       
  2950   if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  2951     return -100;
       
  2952 
       
  2953   bytesread = readFullAtomHeader(handle, stsz->atomhdr);
       
  2954   if (bytesread < 0)
       
  2955     return -1;
       
  2956   totalbytesread += bytesread;
       
  2957 
       
  2958   if (stsz->atomhdr->type != ATOMTYPE_STZ2)
       
  2959     return -1;
       
  2960 
       
  2961 
       
  2962   bytesread = discardData(handle, 3);
       
  2963   if (bytesread < 0)
       
  2964     return -1;
       
  2965   totalbytesread += bytesread;
       
  2966 
       
  2967   bytesread = readData(handle, handle->buf, 1);
       
  2968   if (bytesread < 0)
       
  2969     return -1;
       
  2970   fieldsize = handle->buf[0];
       
  2971   totalbytesread += bytesread;
       
  2972 
       
  2973   bytesread = readData(handle, handle->buf, 4);
       
  2974   if (bytesread < 0)
       
  2975     return -1;
       
  2976   stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf));
       
  2977   totalbytesread += bytesread;
       
  2978 
       
  2979   switch (fieldsize)
       
  2980   {
       
  2981   case 4: /* Two entries in each byte */
       
  2982 
       
  2983     {
       
  2984       mp4_u32 i;
       
  2985 
       
  2986       stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
       
  2987       if (stsz->entrySize == NULL)
       
  2988         return -1;
       
  2989 
       
  2990       for (i = 0; i < (stsz->sampleCount + 1) / 2; i++)
       
  2991       {
       
  2992         bytesread = readData(handle, handle->buf, 1);
       
  2993         if (bytesread < 0)
       
  2994           return -1;
       
  2995 
       
  2996         totalbytesread += bytesread;
       
  2997 
       
  2998         stsz->entrySize[i * 2] = (mp4_u32)(handle->buf[0] >> 4);
       
  2999 
       
  3000         if (stsz->sampleCount % 2 == 0) /* Even number of samples */
       
  3001         {
       
  3002           stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f);
       
  3003           continue;
       
  3004         }
       
  3005 
       
  3006         /* This condition is needed to avoid writing after the table */
       
  3007 
       
  3008         if (i == (stsz->sampleCount + 1) / 2 - 1) /* Last sample */
       
  3009         {
       
  3010         }
       
  3011         else
       
  3012           stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f);
       
  3013       }
       
  3014     }
       
  3015 
       
  3016     break;
       
  3017 
       
  3018   case 8: /* One entry for each byte */
       
  3019 
       
  3020     {
       
  3021       mp4_u32 i;
       
  3022 
       
  3023       stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
       
  3024       if (stsz->entrySize == NULL)
       
  3025         return -1;
       
  3026 
       
  3027       for (i = 0; i < stsz->sampleCount; i++)
       
  3028       {
       
  3029         bytesread = readData(handle, handle->buf, 1);
       
  3030         if (bytesread < 0)
       
  3031           return -1;
       
  3032 
       
  3033         stsz->entrySize[i] = (mp4_u32)handle->buf[0];
       
  3034 
       
  3035         totalbytesread += bytesread;
       
  3036       }
       
  3037     }
       
  3038 
       
  3039     break;
       
  3040 
       
  3041   case 16: /* Each entry in 2 bytes */
       
  3042 
       
  3043     {
       
  3044       mp4_u32 i;
       
  3045 
       
  3046       stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
       
  3047       if (stsz->entrySize == NULL)
       
  3048         return -1;
       
  3049 
       
  3050       for (i = 0; i < stsz->sampleCount; i++)
       
  3051       {
       
  3052         bytesread = readData(handle, handle->buf, 2);
       
  3053         if (bytesread < 0)
       
  3054           return -1;
       
  3055 
       
  3056         stsz->entrySize[i] = (mp4_u32)u16endian(*((mp4_u16 *)handle->buf));
       
  3057 
       
  3058         totalbytesread += bytesread;
       
  3059       }
       
  3060     }
       
  3061 
       
  3062     break;
       
  3063 
       
  3064   default: /* Illegal fieldsize */
       
  3065 
       
  3066     return -1;
       
  3067   }
       
  3068 
       
  3069 
       
  3070   return totalbytesread;
       
  3071 }
       
  3072 
       
  3073 
       
  3074 /*
       
  3075  * Function:
       
  3076  *
       
  3077  *   mp4_i32 readSTSC(MP4HandleImp handle,
       
  3078  *                    sampleToChunkAtom *stsc)
       
  3079  *
       
  3080  * Description:
       
  3081  *
       
  3082  *   This function parses one STSC atom.
       
  3083  *
       
  3084  * Parameters:
       
  3085  *
       
  3086  *   handle             MP4 library handle
       
  3087  *   stsc               STSC pointer
       
  3088  *
       
  3089  * Return value:
       
  3090  *
       
  3091  *   Negative integer   Error
       
  3092  *   >= 0               Success. Value tells how many bytes were read.
       
  3093  *
       
  3094  */
       
  3095 mp4_i32 readSTSC(MP4HandleImp handle, sampleToChunkAtom *stsc)
       
  3096 {
       
  3097   mp4_i32 bytesread;
       
  3098   mp4_i32 totalbytesread = 0;
       
  3099   mp4_u32 i;
       
  3100 
       
  3101 
       
  3102   if ((stsc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3103     return -100;
       
  3104 
       
  3105   bytesread = readFullAtomHeader(handle, stsc->atomhdr);
       
  3106   if (bytesread < 0)
       
  3107     return -1;
       
  3108   totalbytesread += bytesread;
       
  3109 
       
  3110   if (stsc->atomhdr->type != ATOMTYPE_STSC)
       
  3111     return -1;
       
  3112 
       
  3113 
       
  3114   bytesread = readData(handle, handle->buf, 4);
       
  3115   if (bytesread < 0)
       
  3116     return -1;
       
  3117   stsc->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  3118   totalbytesread += bytesread;
       
  3119 
       
  3120   if (stsc->entryCount)
       
  3121   {
       
  3122 	  stsc->firstChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
       
  3123 	  if (stsc->firstChunk == NULL)
       
  3124 	    return -1;
       
  3125 	  stsc->samplesPerChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
       
  3126 	  if (stsc->samplesPerChunk == NULL)
       
  3127 	    return -1;
       
  3128 	  stsc->sampleDescriptionIndex = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
       
  3129 	  if (stsc->sampleDescriptionIndex == NULL)
       
  3130 	  {
       
  3131 		return -1;	  	
       
  3132 	  }
       
  3133 
       
  3134 	  for (i = 0; i < stsc->entryCount; i++)
       
  3135 	  {
       
  3136 	    bytesread = readData(handle, handle->buf, 12);
       
  3137 	    if (bytesread < 0)
       
  3138 	      return -1;
       
  3139 
       
  3140 	    stsc->firstChunk[i] = u32endian(*((mp4_u32 *)handle->buf));
       
  3141 	    stsc->samplesPerChunk[i] = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  3142 	    stsc->sampleDescriptionIndex[i] = u32endian(*((mp4_u32 *)(handle->buf+8)));
       
  3143 	    if ( stsc->sampleDescriptionIndex[i] > stsc->entryCount)
       
  3144 	    {
       
  3145 	    	return -1;
       
  3146 	    }
       
  3147 
       
  3148 	    totalbytesread += bytesread;
       
  3149 	  }
       
  3150   }
       
  3151   return totalbytesread;
       
  3152 }
       
  3153 
       
  3154 
       
  3155 /*
       
  3156  * Function:
       
  3157  *
       
  3158  *   mp4_i32 readSTCO(MP4HandleImp handle,
       
  3159  *                    chunkOffsetAtom *stco)
       
  3160  *
       
  3161  * Description:
       
  3162  *
       
  3163  *   This function parses one STCO atom.
       
  3164  *
       
  3165  * Parameters:
       
  3166  *
       
  3167  *   handle             MP4 library handle
       
  3168  *   stco               STCO pointer
       
  3169  *
       
  3170  * Return value:
       
  3171  *
       
  3172  *   Negative integer   Error
       
  3173  *   >= 0               Success. Value tells how many bytes were read.
       
  3174  *
       
  3175  */
       
  3176 mp4_i32 readSTCO(MP4HandleImp handle, chunkOffsetAtom *stco)
       
  3177 {
       
  3178   mp4_i32 bytesread;
       
  3179   mp4_i32 totalbytesread = 0;
       
  3180   mp4_u32  i;
       
  3181 
       
  3182 
       
  3183   if ((stco->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3184     return -100;
       
  3185 
       
  3186   bytesread = readFullAtomHeader(handle, stco->atomhdr);
       
  3187   if (bytesread < 0)
       
  3188     return -1;
       
  3189   totalbytesread += bytesread;
       
  3190 
       
  3191   if (stco->atomhdr->type != ATOMTYPE_STCO)
       
  3192     return -1;
       
  3193 
       
  3194 
       
  3195   bytesread = readData(handle, handle->buf, 4);
       
  3196   if (bytesread < 0)
       
  3197     return -1;
       
  3198   stco->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  3199   totalbytesread += bytesread;
       
  3200 
       
  3201   if (stco->entryCount)
       
  3202   {
       
  3203 	  // validate stco->entryCount before allocating chunkOffsetTable
       
  3204 	  if ( handle->moov->mvhd )
       
  3205 	    {
       
  3206 	    if ( handle->moov->mvhd->timeScale > 0 )
       
  3207 	        {
       
  3208 	        TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND;
       
  3209 	        TUint maxSampleCount;
       
  3210 
       
  3211 	        if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration
       
  3212 	            {
       
  3213 	            maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec;
       
  3214 	            }
       
  3215 	        else    // 32bit duration
       
  3216 	            {
       
  3217 	            maxSampleCount = TUint((TUint( handle->moov->mvhd->duration  ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec;
       
  3218 	            }
       
  3219 
       
  3220 	        if ( maxSampleCount < stco->entryCount )
       
  3221 	            {
       
  3222 	            // corrupted 
       
  3223 	            return -1;
       
  3224 	            }
       
  3225 	        }
       
  3226 	    }
       
  3227 
       
  3228 	  stco->chunkOffset = (mp4_u32 *)mp4malloc(stco->entryCount * sizeof(mp4_u32));
       
  3229 	  if (stco->chunkOffset == NULL)
       
  3230 	    return -1;
       
  3231 
       
  3232 	  for (i = 0; i < stco->entryCount; i++)
       
  3233 	  {
       
  3234 	    bytesread = readData(handle, handle->buf, 4);
       
  3235 	    if (bytesread < 0)
       
  3236 	      return -1;
       
  3237 
       
  3238 	    stco->chunkOffset[i] = u32endian(*((mp4_u32 *)handle->buf));
       
  3239 
       
  3240 	    totalbytesread += bytesread;
       
  3241 	  }
       
  3242   }
       
  3243   return totalbytesread;
       
  3244 }
       
  3245 
       
  3246 
       
  3247 /*
       
  3248  * Function:
       
  3249  *
       
  3250  *   mp4_i32 readCO64(MP4HandleImp handle,
       
  3251  *                    chunkOffset64Atom *stco64)
       
  3252  *
       
  3253  * Description:
       
  3254  *
       
  3255  *   This function parses one CO64 atom.
       
  3256  *
       
  3257  * Parameters:
       
  3258  *
       
  3259  *   handle             MP4 library handle
       
  3260  *   stco64               CO64 pointer
       
  3261  *
       
  3262  * Return value:
       
  3263  *
       
  3264  *   Negative integer   Error
       
  3265  *   >= 0               Success. Value tells how many bytes were read.
       
  3266  *
       
  3267  */
       
  3268 mp4_i32 readCO64(MP4HandleImp handle, chunkOffset64Atom *stco64)
       
  3269 {
       
  3270   mp4_i32 bytesread;
       
  3271   mp4_i32 totalbytesread = 0;
       
  3272   mp4_u32 i;
       
  3273 
       
  3274 
       
  3275   if ((stco64->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3276     return -100;
       
  3277 
       
  3278   bytesread = readFullAtomHeader(handle, stco64->atomhdr);
       
  3279   if (bytesread < 0)
       
  3280     return -1;
       
  3281   totalbytesread += bytesread;
       
  3282 
       
  3283   if (stco64->atomhdr->type != ATOMTYPE_CO64)
       
  3284     return -1;
       
  3285 
       
  3286 
       
  3287   bytesread = readData(handle, handle->buf, 4);
       
  3288   if (bytesread < 0)
       
  3289     return -1;
       
  3290   stco64->entryCount = u32endian(*((mp4_u32 *)handle->buf));
       
  3291   totalbytesread += bytesread;
       
  3292 
       
  3293   if ( stco64->entryCount )
       
  3294   {
       
  3295 	  stco64->chunkOffset = (mp4_u64 *)mp4malloc(stco64->entryCount * sizeof(mp4_u64));
       
  3296 	  if (stco64->chunkOffset == NULL)
       
  3297 	    return -1;
       
  3298 
       
  3299 	  for (i = 0; i < stco64->entryCount; i++)
       
  3300 	  {
       
  3301 	    bytesread = readData(handle, handle->buf, 8);
       
  3302 	    if (bytesread < 0)
       
  3303 	      return -1;
       
  3304 	    
       
  3305 	    stco64->chunkOffset[i] = u64endian(*((mp4_u64 *)(handle->buf)));
       
  3306 
       
  3307 	    totalbytesread += bytesread;
       
  3308 	  }
       
  3309   }
       
  3310   return totalbytesread;
       
  3311 }
       
  3312 
       
  3313 
       
  3314 /*
       
  3315  * Function:
       
  3316  *
       
  3317  *   mp4_i32 readMP4V(MP4HandleImp handle,
       
  3318  *                    visualSampleEntry *mp4v)
       
  3319  *
       
  3320  * Description:
       
  3321  *
       
  3322  *   This function parses one MP4V atom.
       
  3323  *
       
  3324  * Parameters:
       
  3325  *
       
  3326  *   handle             MP4 library handle
       
  3327  *   mp4v               MP4V pointer
       
  3328  *
       
  3329  * Return value:
       
  3330  *
       
  3331  *   Negative integer   Error
       
  3332  *   >= 0               Success. Value tells how many bytes were read.
       
  3333  *
       
  3334  */
       
  3335 mp4_i32 readMP4V(MP4HandleImp handle, visualSampleEntry *mp4v)
       
  3336 {
       
  3337   mp4_i32 bytesread;
       
  3338   mp4_i32 totalbytesread = 0;
       
  3339 
       
  3340 
       
  3341   if ((mp4v->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3342     return -100;
       
  3343 
       
  3344   bytesread = readAtomHeader(handle, mp4v->atomhdr);
       
  3345   if (bytesread < 0)
       
  3346     return -1;
       
  3347   totalbytesread += bytesread;
       
  3348 
       
  3349   if (mp4v->atomhdr->type != ATOMTYPE_MP4V)
       
  3350     return -1;
       
  3351 
       
  3352 
       
  3353   bytesread = discardData(handle, 6);
       
  3354   if (bytesread < 0)
       
  3355     return -1;
       
  3356   totalbytesread += bytesread;
       
  3357 
       
  3358   bytesread = readData(handle, handle->buf, 2);
       
  3359   if (bytesread < 0)
       
  3360     return -1;
       
  3361   mp4v->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  3362   totalbytesread += bytesread;
       
  3363 
       
  3364   bytesread = discardData(handle, 16);
       
  3365   if (bytesread < 0)
       
  3366     return -1;
       
  3367   totalbytesread += bytesread;
       
  3368 
       
  3369   bytesread = readData(handle, handle->buf, 2);
       
  3370   if (bytesread < 0)
       
  3371     return -1;
       
  3372   mp4v->width = u16endian(*((mp4_u16 *)handle->buf));
       
  3373   totalbytesread += bytesread;
       
  3374 
       
  3375   bytesread = readData(handle, handle->buf, 2);
       
  3376   if (bytesread < 0)
       
  3377     return -1;
       
  3378   mp4v->height = u16endian(*((mp4_u16 *)handle->buf));
       
  3379   totalbytesread += bytesread;
       
  3380 
       
  3381   bytesread = discardData(handle, 50);
       
  3382   if (bytesread < 0)
       
  3383     return -1;
       
  3384   totalbytesread += bytesread;
       
  3385 
       
  3386   if ((mp4v->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
       
  3387     return -100;
       
  3388 
       
  3389   bytesread = readESD(handle, mp4v->esd);
       
  3390   if (bytesread < 0)
       
  3391     return -1;
       
  3392   totalbytesread += bytesread;
       
  3393   
       
  3394   if ( totalbytesread < mp4v->atomhdr->size )
       
  3395   	{
       
  3396     bytesread = discardData(handle, mp4v->atomhdr->size - totalbytesread );
       
  3397   	if (bytesread < 0)
       
  3398   		{
       
  3399     	return -1;	  		
       
  3400   		}
       
  3401   	totalbytesread += bytesread;
       
  3402   	}  
       
  3403 
       
  3404   return totalbytesread;
       
  3405 }
       
  3406 
       
  3407 
       
  3408 /*
       
  3409  * Function:
       
  3410  *
       
  3411  *   mp4_i32 readMP4A(MP4HandleImp handle,
       
  3412  *                    audioSampleEntry *mp4a)
       
  3413  *
       
  3414  * Description:
       
  3415  *
       
  3416  *   This function parses one MP4A atom.
       
  3417  *
       
  3418  * Parameters:
       
  3419  *
       
  3420  *   handle             MP4 library handle
       
  3421  *   mp4a               MP4A pointer
       
  3422  *
       
  3423  * Return value:
       
  3424  *
       
  3425  *   Negative integer   Error
       
  3426  *   >= 0               Success. Value tells how many bytes were read.
       
  3427  *
       
  3428  */
       
  3429 mp4_i32 readMP4A(MP4HandleImp handle, audioSampleEntry *mp4a)
       
  3430 {
       
  3431   mp4_i32 bytesread;
       
  3432   mp4_i32 totalbytesread = 0;
       
  3433 
       
  3434 
       
  3435   if ((mp4a->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3436     return -100;
       
  3437 
       
  3438   bytesread = readAtomHeader(handle, mp4a->atomhdr);
       
  3439   if (bytesread < 0)
       
  3440     return -1;
       
  3441   totalbytesread += bytesread;
       
  3442 
       
  3443   if (mp4a->atomhdr->type != ATOMTYPE_MP4A)
       
  3444     return -1;
       
  3445 
       
  3446 
       
  3447   bytesread = discardData(handle, 6);
       
  3448   if (bytesread < 0)
       
  3449     return -1;
       
  3450   totalbytesread += bytesread;
       
  3451 
       
  3452   bytesread = readData(handle, handle->buf, 2);
       
  3453   if (bytesread < 0)
       
  3454     return -1;
       
  3455   mp4a->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  3456   totalbytesread += bytesread;
       
  3457 
       
  3458   bytesread = discardData(handle, 16);
       
  3459   if (bytesread < 0)
       
  3460     return -1;
       
  3461   totalbytesread += bytesread;
       
  3462 
       
  3463   bytesread = readData(handle, handle->buf, 2);
       
  3464   if (bytesread < 0)
       
  3465     return -1;
       
  3466   mp4a->timeScale = u16endian(*((mp4_u16 *)handle->buf));
       
  3467   totalbytesread += bytesread;
       
  3468 
       
  3469   bytesread = discardData(handle, 2);
       
  3470   if (bytesread < 0)
       
  3471     return -1;
       
  3472   totalbytesread += bytesread;
       
  3473 
       
  3474   if ((mp4a->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
       
  3475     return -100;
       
  3476 
       
  3477   bytesread = readESD(handle, mp4a->esd);
       
  3478   if (bytesread < 0)
       
  3479     return -1;
       
  3480   totalbytesread += bytesread;
       
  3481   
       
  3482   if ( totalbytesread < mp4a->atomhdr->size )
       
  3483   	{
       
  3484     bytesread = discardData(handle, mp4a->atomhdr->size - totalbytesread );
       
  3485   	if (bytesread < 0)
       
  3486   		{
       
  3487     	return -1;	  		
       
  3488   		}
       
  3489   	totalbytesread += bytesread;
       
  3490   	}
       
  3491 
       
  3492   return totalbytesread;
       
  3493 }
       
  3494 
       
  3495 
       
  3496 /*
       
  3497  * Function:
       
  3498  *
       
  3499  *   mp4_i32 readMP4S(MP4HandleImp handle,
       
  3500  *                    mpegSampleEntry *mp4s)
       
  3501  *
       
  3502  * Description:
       
  3503  *
       
  3504  *   This function parses one MP4S atom.
       
  3505  *
       
  3506  * Parameters:
       
  3507  *
       
  3508  *   handle             MP4 library handle
       
  3509  *   mp4s               MP4S pointer
       
  3510  *
       
  3511  * Return value:
       
  3512  *
       
  3513  *   Negative integer   Error
       
  3514  *   >= 0               Success. Value tells how many bytes were read.
       
  3515  *
       
  3516  */
       
  3517 mp4_i32 readMP4S(MP4HandleImp handle, mpegSampleEntry *mp4s)
       
  3518 {
       
  3519   mp4_i32 bytesread;
       
  3520   mp4_i32 totalbytesread = 0;
       
  3521 
       
  3522 
       
  3523   if ((mp4s->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3524     return -100;
       
  3525 
       
  3526   bytesread = readAtomHeader(handle, mp4s->atomhdr);
       
  3527   if (bytesread < 0)
       
  3528     return -1;
       
  3529   totalbytesread += bytesread;
       
  3530 
       
  3531   if (mp4s->atomhdr->type != ATOMTYPE_MP4S)
       
  3532     return -1;
       
  3533 
       
  3534 
       
  3535   bytesread = discardData(handle, 6);
       
  3536   if (bytesread < 0)
       
  3537     return -1;
       
  3538   totalbytesread += bytesread;
       
  3539 
       
  3540   bytesread = readData(handle, handle->buf, 2);
       
  3541   if (bytesread < 0)
       
  3542     return -1;
       
  3543   mp4s->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  3544   totalbytesread += bytesread;
       
  3545 
       
  3546   if ((mp4s->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
       
  3547     return -100;
       
  3548 
       
  3549   bytesread = readESD(handle, mp4s->esd);
       
  3550   if (bytesread < 0)
       
  3551     return -1;
       
  3552   totalbytesread += bytesread;
       
  3553   
       
  3554   if ( totalbytesread < mp4s->atomhdr->size )
       
  3555   	{
       
  3556     bytesread = discardData(handle, mp4s->atomhdr->size - totalbytesread );
       
  3557   	if (bytesread < 0)
       
  3558   		{
       
  3559     	return -1;	  		
       
  3560   		}
       
  3561   	totalbytesread += bytesread;
       
  3562   	}    
       
  3563 
       
  3564   return totalbytesread;
       
  3565 }
       
  3566 
       
  3567 
       
  3568 /*
       
  3569  * Function:
       
  3570  *
       
  3571  *   mp4_i32 readS263(MP4HandleImp handle,
       
  3572  *                    h263SampleEntry *s263)
       
  3573  *
       
  3574  * Description:
       
  3575  *
       
  3576  *   This function parses one S263 atom.
       
  3577  *
       
  3578  * Parameters:
       
  3579  *
       
  3580  *   handle             MP4 library handle
       
  3581  *   s263               S263 pointer
       
  3582  *
       
  3583  * Return value:
       
  3584  *
       
  3585  *   Negative integer   Error
       
  3586  *   >= 0               Success. Value tells how many bytes were read.
       
  3587  *
       
  3588  */
       
  3589 mp4_i32 readS263(MP4HandleImp handle, h263SampleEntry *s263)
       
  3590 {
       
  3591   mp4_i32 bytesread;
       
  3592   mp4_i32 totalbytesread = 0;
       
  3593 
       
  3594 
       
  3595   if ((s263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3596     return -100;
       
  3597 
       
  3598   bytesread = readAtomHeader(handle, s263->atomhdr);
       
  3599   if (bytesread < 0)
       
  3600     return -1;
       
  3601   totalbytesread += bytesread;
       
  3602 
       
  3603   if (s263->atomhdr->type != ATOMTYPE_S263)
       
  3604     return -1;
       
  3605 
       
  3606 
       
  3607   bytesread = discardData(handle, 6);
       
  3608   if (bytesread < 0)
       
  3609     return -1;
       
  3610   totalbytesread += bytesread;
       
  3611 
       
  3612   bytesread = readData(handle, handle->buf, 2);
       
  3613   if (bytesread < 0)
       
  3614     return -1;
       
  3615   s263->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  3616   totalbytesread += bytesread;
       
  3617 
       
  3618   bytesread = discardData(handle, 16);
       
  3619   if (bytesread < 0)
       
  3620     return -1;
       
  3621   totalbytesread += bytesread;
       
  3622 
       
  3623   bytesread = readData(handle, handle->buf, 2);
       
  3624   if (bytesread < 0)
       
  3625     return -1;
       
  3626   s263->width = u16endian(*((mp4_u16 *)handle->buf));
       
  3627   totalbytesread += bytesread;
       
  3628 
       
  3629   bytesread = readData(handle, handle->buf, 2);
       
  3630   if (bytesread < 0)
       
  3631     return -1;
       
  3632   s263->height = u16endian(*((mp4_u16 *)handle->buf));
       
  3633   totalbytesread += bytesread;
       
  3634 
       
  3635   bytesread = discardData(handle, 50);
       
  3636   if (bytesread < 0)
       
  3637     return -1;
       
  3638   totalbytesread += bytesread;
       
  3639 
       
  3640   if ((s263->d263 = (h263SpecificAtom *)mp4malloc(sizeof(h263SpecificAtom))) == NULL)
       
  3641     return -100;
       
  3642 
       
  3643   bytesread = readD263(handle, s263->d263);
       
  3644   if (bytesread < 0)
       
  3645     return -1;
       
  3646   totalbytesread += bytesread;
       
  3647   
       
  3648   if ( totalbytesread < s263->atomhdr->size )
       
  3649   	{
       
  3650     bytesread = discardData(handle, s263->atomhdr->size - totalbytesread );
       
  3651   	if (bytesread < 0)
       
  3652   		{
       
  3653     	return -1;	  		
       
  3654   		}
       
  3655   	totalbytesread += bytesread;
       
  3656   	}      
       
  3657 
       
  3658   return totalbytesread;
       
  3659 }
       
  3660 
       
  3661 
       
  3662 /*
       
  3663  * Function:
       
  3664  *
       
  3665  *   mp4_i32 readSAMR(MP4HandleImp handle,
       
  3666  *                    amrSampleEntry *samr)
       
  3667  *
       
  3668  * Description:
       
  3669  *
       
  3670  *   This function parses one SAMR atom.
       
  3671  *
       
  3672  * Parameters:
       
  3673  *
       
  3674  *   handle             MP4 library handle
       
  3675  *   samr               SAMR pointer
       
  3676  *
       
  3677  * Return value:
       
  3678  *
       
  3679  *   Negative integer   Error
       
  3680  *   >= 0               Success. Value tells how many bytes were read.
       
  3681  *
       
  3682  */
       
  3683 mp4_i32 readSAMR(MP4HandleImp handle, amrSampleEntry *samr)
       
  3684 {
       
  3685   mp4_i32 bytesread;
       
  3686   mp4_i32 totalbytesread = 0;
       
  3687 
       
  3688 
       
  3689   if ((samr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3690     return -100;
       
  3691 
       
  3692   bytesread = readAtomHeader(handle, samr->atomhdr);
       
  3693   if (bytesread < 0)
       
  3694     return -1;
       
  3695   totalbytesread += bytesread;
       
  3696 
       
  3697   if (samr->atomhdr->type != ATOMTYPE_SAMR)
       
  3698     return -1;
       
  3699 
       
  3700 
       
  3701   bytesread = discardData(handle, 6);
       
  3702   if (bytesread < 0)
       
  3703     return -1;
       
  3704   totalbytesread += bytesread;
       
  3705 
       
  3706   bytesread = readData(handle, handle->buf, 2);
       
  3707   if (bytesread < 0)
       
  3708     return -1;
       
  3709   samr->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  3710   totalbytesread += bytesread;
       
  3711 
       
  3712   bytesread = discardData(handle, 16);
       
  3713   if (bytesread < 0)
       
  3714     return -1;
       
  3715   totalbytesread += bytesread;
       
  3716 
       
  3717   bytesread = readData(handle, handle->buf, 2);
       
  3718   if (bytesread < 0)
       
  3719     return -1;
       
  3720   samr->timeScale = u16endian(*((mp4_u16 *)handle->buf));
       
  3721   totalbytesread += bytesread;
       
  3722 
       
  3723   bytesread = discardData(handle, 2);
       
  3724   if (bytesread < 0)
       
  3725     return -1;
       
  3726   totalbytesread += bytesread;
       
  3727 
       
  3728   if ((samr->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL)
       
  3729     return -100;
       
  3730 
       
  3731   bytesread = readDAMR(handle, samr->damr);
       
  3732   if (bytesread < 0)
       
  3733     return -1;
       
  3734   totalbytesread += bytesread;
       
  3735   
       
  3736   if ( totalbytesread < samr->atomhdr->size )
       
  3737   	{
       
  3738     bytesread = discardData(handle, samr->atomhdr->size - totalbytesread );
       
  3739   	if (bytesread < 0)
       
  3740   		{
       
  3741     	return -1;	  		
       
  3742   		}
       
  3743   	totalbytesread += bytesread;
       
  3744   	}      
       
  3745 
       
  3746   return totalbytesread;
       
  3747 }
       
  3748 
       
  3749 
       
  3750 /*
       
  3751  * Function:
       
  3752  *
       
  3753  *   mp4_i32 readSAWB(MP4HandleImp handle,
       
  3754  *                    amrSampleEntry *sawb)
       
  3755  *
       
  3756  * Description:
       
  3757  *
       
  3758  *   This function parses one SAWB atom.
       
  3759  *
       
  3760  * Parameters:
       
  3761  *
       
  3762  *   handle             MP4 library handle
       
  3763  *   sawb               SAWB pointer
       
  3764  *
       
  3765  * Return value:
       
  3766  *
       
  3767  *   Negative integer   Error
       
  3768  *   >= 0               Success. Value tells how many bytes were read.
       
  3769  *
       
  3770  */
       
  3771 mp4_i32 readSAWB(MP4HandleImp handle, amrSampleEntry *sawb)
       
  3772 {
       
  3773   mp4_i32 bytesread;
       
  3774   mp4_i32 totalbytesread = 0;
       
  3775 
       
  3776 
       
  3777   if ((sawb->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3778     return -100;
       
  3779 
       
  3780   bytesread = readAtomHeader(handle, sawb->atomhdr);
       
  3781   if (bytesread < 0)
       
  3782     return -1;
       
  3783   totalbytesread += bytesread;
       
  3784 
       
  3785   if (sawb->atomhdr->type != ATOMTYPE_SAWB)
       
  3786     return -1;
       
  3787 
       
  3788 
       
  3789   bytesread = discardData(handle, 6);
       
  3790   if (bytesread < 0)
       
  3791     return -1;
       
  3792   totalbytesread += bytesread;
       
  3793 
       
  3794   bytesread = readData(handle, handle->buf, 2);
       
  3795   if (bytesread < 0)
       
  3796     return -1;
       
  3797   sawb->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  3798   totalbytesread += bytesread;
       
  3799 
       
  3800   bytesread = discardData(handle, 16);
       
  3801   if (bytesread < 0)
       
  3802     return -1;
       
  3803   totalbytesread += bytesread;
       
  3804 
       
  3805   bytesread = readData(handle, handle->buf, 2);
       
  3806   if (bytesread < 0)
       
  3807     return -1;
       
  3808   sawb->timeScale = u16endian(*((mp4_u16 *)handle->buf));
       
  3809   totalbytesread += bytesread;
       
  3810 
       
  3811   bytesread = discardData(handle, 2);
       
  3812   if (bytesread < 0)
       
  3813     return -1;
       
  3814   totalbytesread += bytesread;
       
  3815 
       
  3816   if ((sawb->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL)
       
  3817     return -100;
       
  3818 
       
  3819   bytesread = readDAMR(handle, sawb->damr);
       
  3820   if (bytesread < 0)
       
  3821     return -1;
       
  3822   totalbytesread += bytesread;
       
  3823   
       
  3824   if ( totalbytesread < sawb->atomhdr->size )
       
  3825   	{
       
  3826     bytesread = discardData(handle, sawb->atomhdr->size - totalbytesread );
       
  3827   	if (bytesread < 0)
       
  3828   		{
       
  3829     	return -1;	  		
       
  3830   		}
       
  3831   	totalbytesread += bytesread;
       
  3832   	}      
       
  3833 
       
  3834   return totalbytesread;
       
  3835 }
       
  3836 
       
  3837 
       
  3838 /*
       
  3839  * Function:
       
  3840  *
       
  3841  *   mp4_i32 readESD(MP4HandleImp handle,
       
  3842  *                   ESDAtom *esd)
       
  3843  *
       
  3844  * Description:
       
  3845  *
       
  3846  *   This function parses one ESD atom.
       
  3847  *
       
  3848  * Parameters:
       
  3849  *
       
  3850  *   handle             MP4 library handle
       
  3851  *   esd                ESD pointer
       
  3852  *
       
  3853  * Return value:
       
  3854  *
       
  3855  *   Negative integer   Error
       
  3856  *   >= 0               Success. Value tells how many bytes were read.
       
  3857  *
       
  3858  */
       
  3859 mp4_i32 readESD(MP4HandleImp handle, ESDAtom *esd)
       
  3860 {
       
  3861   mp4_i32 bytesread;
       
  3862   mp4_i32 totalbytesread = 0;
       
  3863   mp4_i32 decConfDescrBytesRead = 0;
       
  3864 
       
  3865 
       
  3866   if ((esd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  3867     return -100;
       
  3868 
       
  3869   bytesread = readFullAtomHeader(handle, esd->atomhdr);
       
  3870   if (bytesread < 0)
       
  3871     return -1;
       
  3872   totalbytesread += bytesread;
       
  3873 
       
  3874   if (esd->atomhdr->type != ATOMTYPE_ESD)
       
  3875     return -1;
       
  3876 
       
  3877 
       
  3878   bytesread = readData(handle, handle->buf, 1);
       
  3879   if (bytesread < 0)
       
  3880     return -1;
       
  3881   esd->esDescrTag = handle->buf[0];
       
  3882   totalbytesread += bytesread;
       
  3883   if (esd->esDescrTag != 3) /* ES_DescrTag == 3 */
       
  3884     return -1;
       
  3885 
       
  3886   esd->size = 0;
       
  3887   do
       
  3888   {
       
  3889     mp4_u8 c;
       
  3890 
       
  3891     bytesread = readData(handle, handle->buf, 1);
       
  3892     if (bytesread < 0)
       
  3893       return -1;
       
  3894     c = (mp4_u8)(handle->buf[0] & 0x7f);
       
  3895     esd->size = (esd->size << 7) | c;
       
  3896     totalbytesread += bytesread;
       
  3897   }
       
  3898   while (handle->buf[0] & 0x80);
       
  3899 
       
  3900   bytesread = readData(handle, handle->buf, 2);
       
  3901   if (bytesread < 0)
       
  3902     return -1;
       
  3903   esd->ESID = u16endian(*((mp4_u16 *)handle->buf));
       
  3904   totalbytesread += bytesread;
       
  3905 
       
  3906   bytesread = readData(handle, handle->buf, 1);
       
  3907   if (bytesread < 0)
       
  3908     return -1;
       
  3909   esd->flags = handle->buf[0];
       
  3910   totalbytesread += bytesread;
       
  3911 
       
  3912   if (esd->flags & 0x80) /* Stream Dependence flag has been set */
       
  3913   {
       
  3914     bytesread = readData(handle, handle->buf, 2);
       
  3915     if (bytesread < 0)
       
  3916       return -1;
       
  3917     esd->dependsOnESID = u16endian(*((mp4_u16 *)handle->buf));
       
  3918     totalbytesread += bytesread;
       
  3919   }
       
  3920 
       
  3921   if (esd->flags & 0x40) /* URL flag has been set */
       
  3922   {
       
  3923     bytesread = readData(handle, handle->buf, 1);
       
  3924     if (bytesread < 0)
       
  3925       return -1;
       
  3926     esd->URLLength = handle->buf[0];
       
  3927     totalbytesread += bytesread;
       
  3928 
       
  3929     bytesread = discardData(handle, esd->URLLength);
       
  3930     if (bytesread < 0)
       
  3931       return -1;
       
  3932     totalbytesread += bytesread;
       
  3933   }
       
  3934 
       
  3935   if (esd->flags & 0x20) /* OCR stream flag has been set */
       
  3936   {
       
  3937     bytesread = readData(handle, handle->buf, 2);
       
  3938     if (bytesread < 0)
       
  3939       return -1;
       
  3940     esd->OCRESID = u16endian(*((mp4_u16 *)handle->buf));
       
  3941     totalbytesread += bytesread;
       
  3942   }
       
  3943 
       
  3944   bytesread = readData(handle, handle->buf, 1);
       
  3945   if (bytesread < 0)
       
  3946     return -1;
       
  3947   esd->decConfDescrTag = handle->buf[0];
       
  3948   totalbytesread += bytesread;
       
  3949   if (esd->decConfDescrTag != 4) /* DecoderConfigDescrTag == 4 */
       
  3950     return -1;
       
  3951 
       
  3952   esd->decConfDescrSize = 0;
       
  3953   do
       
  3954   {
       
  3955     mp4_u8 c;
       
  3956 
       
  3957     bytesread = readData(handle, handle->buf, 1);
       
  3958     if (bytesread < 0)
       
  3959       return -1;
       
  3960     c = (mp4_u8)(handle->buf[0] & 0x7f);
       
  3961     esd->decConfDescrSize = (esd->decConfDescrSize << 7) | c;
       
  3962     totalbytesread += bytesread;
       
  3963   }
       
  3964   while (handle->buf[0] & 0x80);
       
  3965 
       
  3966   bytesread = readData(handle, handle->buf, 1);
       
  3967   if (bytesread < 0)
       
  3968     return -1;
       
  3969   esd->objectTypeIndication = handle->buf[0];
       
  3970   totalbytesread += bytesread;
       
  3971   decConfDescrBytesRead += bytesread;
       
  3972 
       
  3973   bytesread = readData(handle, handle->buf, 1);
       
  3974   if (bytesread < 0)
       
  3975     return -1;
       
  3976   esd->stream = handle->buf[0];
       
  3977   totalbytesread += bytesread;
       
  3978   decConfDescrBytesRead += bytesread;
       
  3979 
       
  3980   bytesread = readData(handle, handle->buf, 3);
       
  3981   if (bytesread < 0)
       
  3982     return -1;
       
  3983   esd->bufferSizeDB = ((mp4_u32)handle->buf[0]) << 16 |
       
  3984                       ((mp4_u32)handle->buf[1]) << 8 |
       
  3985                       ((mp4_u32)handle->buf[2]);
       
  3986   totalbytesread += bytesread;
       
  3987   decConfDescrBytesRead += bytesread;
       
  3988 
       
  3989   bytesread = readData(handle, handle->buf, 4);
       
  3990   if (bytesread < 0)
       
  3991     return -1;
       
  3992   esd->maxBitrate = u32endian(*((mp4_u32 *)handle->buf));
       
  3993   totalbytesread += bytesread;
       
  3994   decConfDescrBytesRead += bytesread;
       
  3995 
       
  3996   bytesread = readData(handle, handle->buf, 4);
       
  3997   if (bytesread < 0)
       
  3998     return -1;
       
  3999   esd->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
       
  4000   totalbytesread += bytesread;
       
  4001   decConfDescrBytesRead += bytesread;
       
  4002 
       
  4003   if ((mp4_u32)decConfDescrBytesRead < esd->decConfDescrSize)
       
  4004   {
       
  4005     bytesread = readData(handle, handle->buf, 1);
       
  4006     if (bytesread < 0)
       
  4007       return -1;
       
  4008     esd->decSpecificInfoTag = handle->buf[0];
       
  4009     totalbytesread += bytesread;
       
  4010     decConfDescrBytesRead += bytesread;
       
  4011     if (esd->decSpecificInfoTag != 5) /* DecSpecificInfoTag == 5 */
       
  4012     {
       
  4013       bytesread = discardData(handle, esd->decConfDescrSize - decConfDescrBytesRead);
       
  4014       if (bytesread < 0)
       
  4015         return -1;
       
  4016       totalbytesread += bytesread;
       
  4017     }
       
  4018     else
       
  4019     {
       
  4020       esd->decSpecificInfoSize = 0;
       
  4021       do
       
  4022       {
       
  4023         mp4_u8 c;
       
  4024 
       
  4025         bytesread = readData(handle, handle->buf, 1);
       
  4026         if (bytesread < 0)
       
  4027           return -1;
       
  4028         c = (mp4_u8)(handle->buf[0] & 0x7f);
       
  4029         esd->decSpecificInfoSize = (esd->decSpecificInfoSize << 7) | c;
       
  4030         totalbytesread += bytesread;
       
  4031       }
       
  4032       while (handle->buf[0] & 0x80);
       
  4033 
       
  4034       if(esd->decSpecificInfoSize)
       
  4035       {
       
  4036         if ((esd->decSpecificInfo = (mp4_u8 *)mp4malloc(esd->decSpecificInfoSize)) == NULL)
       
  4037           return -100;
       
  4038 
       
  4039         bytesread = readData(handle, esd->decSpecificInfo, esd->decSpecificInfoSize);
       
  4040         if (bytesread < 0)
       
  4041           return -1;
       
  4042         totalbytesread += bytesread;
       
  4043       }
       
  4044     }
       
  4045   }
       
  4046 
       
  4047   bytesread = discardData(handle, esd->atomhdr->size - totalbytesread);
       
  4048   if (bytesread < 0)
       
  4049     return -1;
       
  4050   totalbytesread += bytesread;
       
  4051 
       
  4052   return totalbytesread;
       
  4053 }
       
  4054 
       
  4055 
       
  4056 /*
       
  4057  * Function:
       
  4058  *
       
  4059  *   mp4_i32 readD263(MP4HandleImp handle,
       
  4060  *                    h263SpecificAtom *d263)
       
  4061  *
       
  4062  * Description:
       
  4063  *
       
  4064  *   This function parses one D263 atom.
       
  4065  *
       
  4066  * Parameters:
       
  4067  *
       
  4068  *   handle             MP4 library handle
       
  4069  *   d263               D263 pointer
       
  4070  *
       
  4071  * Return value:
       
  4072  *
       
  4073  *   Negative integer   Error
       
  4074  *   >= 0               Success. Value tells how many bytes were read.
       
  4075  *
       
  4076  */
       
  4077 mp4_i32 readD263(MP4HandleImp handle, h263SpecificAtom *d263)
       
  4078 {
       
  4079   mp4_i32 bytesread;
       
  4080   mp4_i32 totalbytesread = 0;
       
  4081 
       
  4082 
       
  4083   if ((d263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  4084     return -100;
       
  4085 
       
  4086   bytesread = readAtomHeader(handle, d263->atomhdr);
       
  4087   if (bytesread < 0)
       
  4088     return -1;
       
  4089   totalbytesread += bytesread;
       
  4090 
       
  4091   if (d263->atomhdr->type != ATOMTYPE_D263)
       
  4092     return -1;
       
  4093 
       
  4094 
       
  4095   bytesread = readData(handle, handle->buf, 4);
       
  4096   if (bytesread < 0)
       
  4097     return -1;
       
  4098   d263->vendor = u32endian(*((mp4_u32 *)handle->buf));
       
  4099   totalbytesread += bytesread;
       
  4100 
       
  4101   bytesread = readData(handle, handle->buf, 1);
       
  4102   if (bytesread < 0)
       
  4103     return -1;
       
  4104   d263->decoderVersion = handle->buf[0];
       
  4105   totalbytesread += bytesread;
       
  4106 
       
  4107   bytesread = readData(handle, handle->buf, 1);
       
  4108   if (bytesread < 0)
       
  4109     return -1;
       
  4110   d263->h263Level = handle->buf[0];
       
  4111   totalbytesread += bytesread;
       
  4112 
       
  4113   bytesread = readData(handle, handle->buf, 1);
       
  4114   if (bytesread < 0)
       
  4115     return -1;
       
  4116   d263->h263Profile = handle->buf[0];
       
  4117   totalbytesread += bytesread;
       
  4118 
       
  4119   /* Check for the bitrate atom */
       
  4120 
       
  4121   while ((mp4_u32)totalbytesread < d263->atomhdr->size)
       
  4122   {
       
  4123     mp4_u32 type;
       
  4124 
       
  4125 
       
  4126     if (peekData(handle, handle->buf, 8) < 0)
       
  4127       return -1;
       
  4128 
       
  4129     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  4130 
       
  4131     switch (type)
       
  4132     {
       
  4133     case ATOMTYPE_BITR:
       
  4134 
       
  4135       if (d263->bitr) /* BITR has already been read, more than one is not allowed */
       
  4136         return -1;
       
  4137 
       
  4138       if ((d263->bitr = (bitrateAtom *)mp4malloc(sizeof(bitrateAtom))) == NULL)
       
  4139         return -100;
       
  4140 
       
  4141       bytesread = readBITR(handle, d263->bitr);
       
  4142       if (bytesread < 0)
       
  4143         return -1;
       
  4144       totalbytesread += bytesread;
       
  4145 
       
  4146       break;
       
  4147 
       
  4148     default: /* Other atoms are not needed */
       
  4149 
       
  4150       bytesread = readUnknown(handle);
       
  4151       if (bytesread < 0)
       
  4152         return -1;
       
  4153       totalbytesread += bytesread;
       
  4154 
       
  4155       break;
       
  4156     }
       
  4157   }
       
  4158 
       
  4159   return totalbytesread;
       
  4160 }
       
  4161 
       
  4162 
       
  4163 /*
       
  4164  * Function:
       
  4165  *
       
  4166  *   mp4_i32 readBITR(MP4HandleImp handle,
       
  4167  *                    bitrateAtom *d263)
       
  4168  *
       
  4169  * Description:
       
  4170  *
       
  4171  *   This function parses one BITR atom.
       
  4172  *
       
  4173  * Parameters:
       
  4174  *
       
  4175  *   handle             MP4 library handle
       
  4176  *   bitr               BITR pointer
       
  4177  *
       
  4178  * Return value:
       
  4179  *
       
  4180  *   Negative integer   Error
       
  4181  *   >= 0               Success. Value tells how many bytes were read.
       
  4182  *
       
  4183  */
       
  4184 mp4_i32 readBITR(MP4HandleImp handle, bitrateAtom *bitr)
       
  4185 {
       
  4186   mp4_i32 bytesread;
       
  4187   mp4_i32 totalbytesread = 0;
       
  4188 
       
  4189 
       
  4190   if ((bitr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  4191     return -100;
       
  4192 
       
  4193   bytesread = readAtomHeader(handle, bitr->atomhdr);
       
  4194   if (bytesread < 0)
       
  4195     return -1;
       
  4196   totalbytesread += bytesread;
       
  4197 
       
  4198   if (bitr->atomhdr->type != ATOMTYPE_BITR)
       
  4199     return -1;
       
  4200 
       
  4201 
       
  4202   bytesread = readData(handle, handle->buf, 4);
       
  4203   if (bytesread < 0)
       
  4204     return -1;
       
  4205   bitr->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
       
  4206   totalbytesread += bytesread;
       
  4207 
       
  4208   bytesread = readData(handle, handle->buf, 4);
       
  4209   if (bytesread < 0)
       
  4210     return -1;
       
  4211   bitr->maxBitrate = u32endian(*((mp4_u32 *)handle->buf));
       
  4212   totalbytesread += bytesread;
       
  4213 
       
  4214   return totalbytesread;
       
  4215 }
       
  4216 
       
  4217 
       
  4218 /*
       
  4219  * Function:
       
  4220  *
       
  4221  *   mp4_i32 readDAMR(MP4HandleImp handle,
       
  4222  *                    amrDecSpecStruc *damr)
       
  4223  *
       
  4224  * Description:
       
  4225  *
       
  4226  *   This function parses one DAMR atom.
       
  4227  *
       
  4228  * Parameters:
       
  4229  *
       
  4230  *   handle             MP4 library handle
       
  4231  *   damr               DAMR pointer
       
  4232  *
       
  4233  * Return value:
       
  4234  *
       
  4235  *   Negative integer   Error
       
  4236  *   >= 0               Success. Value tells how many bytes were read.
       
  4237  *
       
  4238  */
       
  4239 mp4_i32 readDAMR(MP4HandleImp handle, amrDecSpecStruc *damr)
       
  4240 {
       
  4241   mp4_i32 bytesread;
       
  4242   mp4_i32 totalbytesread = 0;
       
  4243 
       
  4244 
       
  4245   if ((damr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  4246     return -100;
       
  4247 
       
  4248   bytesread = readAtomHeader(handle, damr->atomhdr);
       
  4249   if (bytesread < 0)
       
  4250     return -1;
       
  4251   totalbytesread += bytesread;
       
  4252 
       
  4253   if (damr->atomhdr->type != ATOMTYPE_DAMR)
       
  4254     return -1;
       
  4255 
       
  4256 
       
  4257   bytesread = readData(handle, handle->buf, 4);
       
  4258   if (bytesread < 0)
       
  4259     return -1;
       
  4260   damr->vendor = u32endian(*((mp4_u32 *)handle->buf));
       
  4261   totalbytesread += bytesread;
       
  4262 
       
  4263   bytesread = readData(handle, handle->buf, 1);
       
  4264   if (bytesread < 0)
       
  4265     return -1;
       
  4266   damr->decoderVersion = handle->buf[0];
       
  4267   totalbytesread += bytesread;
       
  4268 
       
  4269   bytesread = readData(handle, handle->buf, 2);
       
  4270   if (bytesread < 0)
       
  4271     return -1;
       
  4272   damr->modeSet = u16endian(*((mp4_u16 *)handle->buf));
       
  4273   totalbytesread += bytesread;
       
  4274 
       
  4275   bytesread = readData(handle, handle->buf, 1);
       
  4276   if (bytesread < 0)
       
  4277     return -1;
       
  4278   damr->modeChangePeriod = handle->buf[0];
       
  4279   totalbytesread += bytesread;
       
  4280 
       
  4281   bytesread = readData(handle, handle->buf, 1);
       
  4282   if (bytesread < 0)
       
  4283     return -1;
       
  4284   damr->framesPerSample = handle->buf[0];
       
  4285   totalbytesread += bytesread;
       
  4286 
       
  4287   return totalbytesread;
       
  4288 }
       
  4289 
       
  4290 
       
  4291 /*
       
  4292  * Function:
       
  4293  *
       
  4294  *   mp4_i32 freeFTYP(MP4HandleImp handle)
       
  4295  *
       
  4296  * Description:
       
  4297  *
       
  4298  *   This function frees memory for FTYP atom.
       
  4299  *
       
  4300  * Parameters:
       
  4301  *
       
  4302  *   ftyp       FTYP atom pointer
       
  4303  *
       
  4304  * Return value:
       
  4305  *
       
  4306  *   0          Success
       
  4307  *   Negative   Error
       
  4308  *
       
  4309  */
       
  4310 mp4_i32 freeFTYP(fileTypeAtom *ftyp)
       
  4311 {
       
  4312   if (ftyp)
       
  4313   {
       
  4314     if (freeAtomHeader(ftyp->atomhdr) < 0)
       
  4315       return -1;
       
  4316     if (ftyp->compatibleBrands)
       
  4317       mp4free(ftyp->compatibleBrands);
       
  4318 
       
  4319     mp4free(ftyp);
       
  4320   }
       
  4321 
       
  4322   return 0;
       
  4323 }
       
  4324 
       
  4325 
       
  4326 /*
       
  4327  * Function:
       
  4328  *
       
  4329  *   mp4_i32 freeMOOV(movieAtom *moov)
       
  4330  *
       
  4331  * Description:
       
  4332  *
       
  4333  *   This function frees memory for MOOV atom.
       
  4334  *
       
  4335  * Parameters:
       
  4336  *
       
  4337  *   moov       MOOV atom pointer
       
  4338  *
       
  4339  * Return value:
       
  4340  *
       
  4341  *   0          Success
       
  4342  *   Negative   Error
       
  4343  *
       
  4344  */
       
  4345 mp4_i32 freeMOOV(movieAtom *moov)
       
  4346 {
       
  4347   if (moov)
       
  4348   {
       
  4349     if (freeAtomHeader(moov->atomhdr) < 0)
       
  4350       return -1;
       
  4351     if (freeMVHD(moov->mvhd) < 0)
       
  4352       return -1;
       
  4353     if (freeTRAK(moov->trakAudio) < 0)
       
  4354       return -1;
       
  4355     if (freeTRAK(moov->trakVideo) < 0)
       
  4356       return -1;
       
  4357     if (freeIODS(moov->iods) < 0)
       
  4358       return -1;
       
  4359     if (freeUDTA(moov->udta) < 0)
       
  4360       return -1;
       
  4361 
       
  4362     mp4free(moov);
       
  4363   }
       
  4364 
       
  4365   return 0;
       
  4366 }
       
  4367 
       
  4368 
       
  4369 /*
       
  4370  * Function:
       
  4371  *
       
  4372  *   mp4_i32 freeAtomHeader(atomHeader *atomhdr)
       
  4373  *
       
  4374  * Description:
       
  4375  *
       
  4376  *   This function frees memory for atom header.
       
  4377  *
       
  4378  * Parameters:
       
  4379  *
       
  4380  *   atomhdr    atom header pointer
       
  4381  *
       
  4382  * Return value:
       
  4383  *
       
  4384  *   0          Success
       
  4385  *   Negative   Error
       
  4386  *
       
  4387  */
       
  4388 mp4_i32 freeAtomHeader(atomHeader *atomhdr)
       
  4389 {
       
  4390   if (atomhdr)
       
  4391     mp4free(atomhdr);
       
  4392 
       
  4393   return 0;
       
  4394 }
       
  4395 
       
  4396 
       
  4397 /*
       
  4398  * Function:
       
  4399  *
       
  4400  *   mp4_i32 freeMVHD(movieHeaderAtom *mvhd)
       
  4401  *
       
  4402  * Description:
       
  4403  *
       
  4404  *   This function frees memory for MVHD atom.
       
  4405  *
       
  4406  * Parameters:
       
  4407  *
       
  4408  *   mvhd       MVHD atom pointer
       
  4409  *
       
  4410  * Return value:
       
  4411  *
       
  4412  *   0          Success
       
  4413  *   Negative   Error
       
  4414  *
       
  4415  */
       
  4416 mp4_i32 freeMVHD(movieHeaderAtom *mvhd)
       
  4417 {
       
  4418   if (mvhd)
       
  4419   {
       
  4420     if (freeAtomHeader(mvhd->atomhdr) < 0)
       
  4421       return -1;
       
  4422 
       
  4423     mp4free(mvhd);
       
  4424   }
       
  4425 
       
  4426   return 0;
       
  4427 }
       
  4428 
       
  4429 
       
  4430 /*
       
  4431  * Function:
       
  4432  *
       
  4433  *   mp4_i32 freeTRAK(trackAtom *trak)
       
  4434  *
       
  4435  * Description:
       
  4436  *
       
  4437  *   This function frees memory for TRAK atom.
       
  4438  *
       
  4439  * Parameters:
       
  4440  *
       
  4441  *   trak       TRAK atom pointer
       
  4442  *
       
  4443  * Return value:
       
  4444  *
       
  4445  *   0          Success
       
  4446  *   Negative   Error
       
  4447  *
       
  4448  */
       
  4449 mp4_i32 freeTRAK(trackAtom *trak)
       
  4450 {
       
  4451   if (trak)
       
  4452   {
       
  4453     if (freeAtomHeader(trak->atomhdr) < 0)
       
  4454       return -1;
       
  4455     if (freeTKHD(trak->tkhd) < 0)
       
  4456       return -1;
       
  4457     if (freeTREF(trak->tref) < 0)
       
  4458       return -1;
       
  4459     if (freeEDTS(trak->edts) < 0)
       
  4460       return -1;
       
  4461     if (freeMDIA(trak->mdia) < 0)
       
  4462       return -1;
       
  4463     if (freeUDTA(trak->udta) < 0)
       
  4464       return -1;
       
  4465 
       
  4466     mp4free(trak);
       
  4467   }
       
  4468 
       
  4469   return 0;
       
  4470 }
       
  4471 
       
  4472 
       
  4473 /*
       
  4474  * Function:
       
  4475  *
       
  4476  *   mp4_i32 freeTKHD(trackHeaderAtom *tkhd)
       
  4477  *
       
  4478  * Description:
       
  4479  *
       
  4480  *   This function frees memory for TKHD atom.
       
  4481  *
       
  4482  * Parameters:
       
  4483  *
       
  4484  *   tkhd       TKHD atom pointer
       
  4485  *
       
  4486  * Return value:
       
  4487  *
       
  4488  *   0          Success
       
  4489  *   Negative   Error
       
  4490  *
       
  4491  */
       
  4492 mp4_i32 freeTKHD(trackHeaderAtom *tkhd)
       
  4493 {
       
  4494   if (tkhd)
       
  4495   {
       
  4496     if (freeAtomHeader(tkhd->atomhdr) < 0)
       
  4497       return -1;
       
  4498 
       
  4499     mp4free(tkhd);
       
  4500   }
       
  4501 
       
  4502   return 0;
       
  4503 }
       
  4504 
       
  4505 
       
  4506 /*
       
  4507  * Function:
       
  4508  *
       
  4509  *   mp4_i32 freeTREF(trackReferenceAtom *tref)
       
  4510  *
       
  4511  * Description:
       
  4512  *
       
  4513  *   This function frees memory for TREF atom.
       
  4514  *
       
  4515  * Parameters:
       
  4516  *
       
  4517  *   tref       TREF atom pointer
       
  4518  *
       
  4519  * Return value:
       
  4520  *
       
  4521  *   0          Success
       
  4522  *   Negative   Error
       
  4523  *
       
  4524  */
       
  4525 mp4_i32 freeTREF(trackReferenceAtom *tref)
       
  4526 {
       
  4527   if (tref)
       
  4528   {
       
  4529     if (freeAtomHeader(tref->atomhdr) < 0)
       
  4530       return -1;
       
  4531 
       
  4532     mp4free(tref);
       
  4533   }
       
  4534 
       
  4535   return 0;
       
  4536 }
       
  4537 
       
  4538 
       
  4539 /*
       
  4540  * Function:
       
  4541  *
       
  4542  *   mp4_i32 freeEDTS(editListContainerAtom *edts)
       
  4543  *
       
  4544  * Description:
       
  4545  *
       
  4546  *   This function frees memory for EDTS atom.
       
  4547  *
       
  4548  * Parameters:
       
  4549  *
       
  4550  *   edts       EDTS atom pointer
       
  4551  *
       
  4552  * Return value:
       
  4553  *
       
  4554  *   0          Success
       
  4555  *   Negative   Error
       
  4556  *
       
  4557  */
       
  4558 mp4_i32 freeEDTS(editListContainerAtom *edts)
       
  4559 {
       
  4560   if (edts)
       
  4561   {
       
  4562     if (freeAtomHeader(edts->atomhdr) < 0)
       
  4563       return -1;
       
  4564 
       
  4565     mp4free(edts);
       
  4566   }
       
  4567 
       
  4568   return 0;
       
  4569 }
       
  4570 
       
  4571 
       
  4572 /*
       
  4573  * Function:
       
  4574  *
       
  4575  *   mp4_i32 freeMDIA(mediaAtom *mdia)
       
  4576  *
       
  4577  * Description:
       
  4578  *
       
  4579  *   This function frees memory for MDIA atom.
       
  4580  *
       
  4581  * Parameters:
       
  4582  *
       
  4583  *   mdia       MDIA atom pointer
       
  4584  *
       
  4585  * Return value:
       
  4586  *
       
  4587  *   0          Success
       
  4588  *   Negative   Error
       
  4589  *
       
  4590  */
       
  4591 mp4_i32 freeMDIA(mediaAtom *mdia)
       
  4592 {
       
  4593   if (mdia)
       
  4594   {
       
  4595     if (freeAtomHeader(mdia->atomhdr) < 0)
       
  4596       return -1;
       
  4597     if (freeMDHD(mdia->mdhd) < 0)
       
  4598       return -1;
       
  4599     if (freeHDLR(mdia->hdlr) < 0)
       
  4600       return -1;
       
  4601     if (freeMINF(mdia->minf) < 0)
       
  4602       return -1;
       
  4603 
       
  4604     mp4free(mdia);
       
  4605   }
       
  4606 
       
  4607   return 0;
       
  4608 }
       
  4609 
       
  4610 
       
  4611 /*
       
  4612  * Function:
       
  4613  *
       
  4614  *   mp4_i32 freeMDHD(mediaHeaderAtom *mdhd)
       
  4615  *
       
  4616  * Description:
       
  4617  *
       
  4618  *   This function frees memory for MDHD atom.
       
  4619  *
       
  4620  * Parameters:
       
  4621  *
       
  4622  *   mdhd       MDHD atom pointer
       
  4623  *
       
  4624  * Return value:
       
  4625  *
       
  4626  *   0          Success
       
  4627  *   Negative   Error
       
  4628  *
       
  4629  */
       
  4630 mp4_i32 freeMDHD(mediaHeaderAtom *mdhd)
       
  4631 {
       
  4632   if (mdhd)
       
  4633   {
       
  4634     if (freeAtomHeader(mdhd->atomhdr) < 0)
       
  4635       return -1;
       
  4636 
       
  4637     mp4free(mdhd);
       
  4638   }
       
  4639 
       
  4640   return 0;
       
  4641 }
       
  4642 
       
  4643 
       
  4644 /*
       
  4645  * Function:
       
  4646  *
       
  4647  *   mp4_i32 freeHDLR(handlerAtom *hdlr)
       
  4648  *
       
  4649  * Description:
       
  4650  *
       
  4651  *   This function frees memory for HDLR atom.
       
  4652  *
       
  4653  * Parameters:
       
  4654  *
       
  4655  *   hdlr       HDLR atom pointer
       
  4656  *
       
  4657  * Return value:
       
  4658  *
       
  4659  *   0          Success
       
  4660  *   Negative   Error
       
  4661  *
       
  4662  */
       
  4663 mp4_i32 freeHDLR(handlerAtom *hdlr)
       
  4664 {
       
  4665   if (hdlr)
       
  4666   {
       
  4667     if (freeAtomHeader(hdlr->atomhdr) < 0)
       
  4668       return -1;
       
  4669     if (hdlr->name)
       
  4670       mp4free(hdlr->name);
       
  4671 
       
  4672     mp4free(hdlr);
       
  4673   }
       
  4674 
       
  4675   return 0;
       
  4676 }
       
  4677 
       
  4678 
       
  4679 /*
       
  4680  * Function:
       
  4681  *
       
  4682  *   mp4_i32 freeMINF(mediaInformationAtom *minf)
       
  4683  *
       
  4684  * Description:
       
  4685  *
       
  4686  *   This function frees memory for MINF atom.
       
  4687  *
       
  4688  * Parameters:
       
  4689  *
       
  4690  *   minf       MINF atom pointer
       
  4691  *
       
  4692  * Return value:
       
  4693  *
       
  4694  *   0          Success
       
  4695  *   Negative   Error
       
  4696  *
       
  4697  */
       
  4698 mp4_i32 freeMINF(mediaInformationAtom *minf)
       
  4699 {
       
  4700   if (minf)
       
  4701   {
       
  4702     if (freeAtomHeader(minf->atomhdr) < 0)
       
  4703       return -1;
       
  4704     if (freeVMHD(minf->vmhd) < 0)
       
  4705       return -1;
       
  4706     if (freeSMHD(minf->smhd) < 0)
       
  4707       return -1;
       
  4708     if (freeDINF(minf->dinf) < 0)
       
  4709       return -1;
       
  4710     if (freeSTBL(minf->stbl) < 0)
       
  4711       return -1;
       
  4712 
       
  4713     mp4free(minf);
       
  4714   }
       
  4715 
       
  4716   return 0;
       
  4717 }
       
  4718 
       
  4719 
       
  4720 /*
       
  4721  * Function:
       
  4722  *
       
  4723  *   mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd)
       
  4724  *
       
  4725  * Description:
       
  4726  *
       
  4727  *   This function frees memory for VMHD atom.
       
  4728  *
       
  4729  * Parameters:
       
  4730  *
       
  4731  *   vmhd       VMHD atom pointer
       
  4732  *
       
  4733  * Return value:
       
  4734  *
       
  4735  *   0          Success
       
  4736  *   Negative   Error
       
  4737  *
       
  4738  */
       
  4739 mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd)
       
  4740 {
       
  4741   if (vmhd)
       
  4742   {
       
  4743     if (freeAtomHeader(vmhd->atomhdr) < 0)
       
  4744       return -1;
       
  4745 
       
  4746     mp4free(vmhd);
       
  4747   }
       
  4748 
       
  4749   return 0;
       
  4750 }
       
  4751 
       
  4752 
       
  4753 /*
       
  4754  * Function:
       
  4755  *
       
  4756  *   mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd)
       
  4757  *
       
  4758  * Description:
       
  4759  *
       
  4760  *   This function frees memory for SMHD atom.
       
  4761  *
       
  4762  * Parameters:
       
  4763  *
       
  4764  *   smhd       SMHD atom pointer
       
  4765  *
       
  4766  * Return value:
       
  4767  *
       
  4768  *   0          Success
       
  4769  *   Negative   Error
       
  4770  *
       
  4771  */
       
  4772 mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd)
       
  4773 {
       
  4774   if (smhd)
       
  4775   {
       
  4776     if (freeAtomHeader(smhd->atomhdr) < 0)
       
  4777       return -1;
       
  4778 
       
  4779     mp4free(smhd);
       
  4780   }
       
  4781 
       
  4782   return 0;
       
  4783 }
       
  4784 
       
  4785 
       
  4786 /*
       
  4787  * Function:
       
  4788  *
       
  4789  *   mp4_i32 freeDINF(dataInformationAtom *dinf)
       
  4790  *
       
  4791  * Description:
       
  4792  *
       
  4793  *   This function frees memory for DINF atom.
       
  4794  *
       
  4795  * Parameters:
       
  4796  *
       
  4797  *   dinf       DINF atom pointer
       
  4798  *
       
  4799  * Return value:
       
  4800  *
       
  4801  *   0          Success
       
  4802  *   Negative   Error
       
  4803  *
       
  4804  */
       
  4805 mp4_i32 freeDINF(dataInformationAtom *dinf)
       
  4806 {
       
  4807   if (dinf)
       
  4808   {
       
  4809     if (freeAtomHeader(dinf->atomhdr) < 0)
       
  4810       return -1;
       
  4811     if (freeDREF(dinf->dref) < 0)
       
  4812       return -1;
       
  4813 
       
  4814     mp4free(dinf);
       
  4815   }
       
  4816 
       
  4817   return 0;
       
  4818 }
       
  4819 
       
  4820 
       
  4821 /*
       
  4822  * Function:
       
  4823  *
       
  4824  *   mp4_i32 freeDREF(dataReferenceAtom *dref)
       
  4825  *
       
  4826  * Description:
       
  4827  *
       
  4828  *   This function frees memory for DREF atom.
       
  4829  *
       
  4830  * Parameters:
       
  4831  *
       
  4832  *   dref       DREF atom pointer
       
  4833  *
       
  4834  * Return value:
       
  4835  *
       
  4836  *   0          Success
       
  4837  *   Negative   Error
       
  4838  *
       
  4839  */
       
  4840 mp4_i32 freeDREF(dataReferenceAtom *dref)
       
  4841 {
       
  4842   if (dref)
       
  4843   {
       
  4844     if (freeAtomHeader(dref->atomhdr) < 0)
       
  4845       return -1;
       
  4846     if (freeURL(dref->url) < 0)
       
  4847       return -1;
       
  4848     if (freeURN(dref->urn) < 0)
       
  4849       return -1;
       
  4850 
       
  4851     mp4free(dref);
       
  4852   }
       
  4853 
       
  4854   return 0;
       
  4855 }
       
  4856 
       
  4857 
       
  4858 /*
       
  4859  * Function:
       
  4860  *
       
  4861  *   mp4_i32 freeURL(dataEntryURLAtom *url)
       
  4862  *
       
  4863  * Description:
       
  4864  *
       
  4865  *   This function frees memory for URL atom.
       
  4866  *
       
  4867  * Parameters:
       
  4868  *
       
  4869  *   url        URL atom pointer
       
  4870  *
       
  4871  * Return value:
       
  4872  *
       
  4873  *   0          Success
       
  4874  *   Negative   Error
       
  4875  *
       
  4876  */
       
  4877 mp4_i32 freeURL(dataEntryURLAtom *url)
       
  4878 {
       
  4879   if (url)
       
  4880   {
       
  4881     if (freeAtomHeader(url->atomhdr) < 0)
       
  4882       return -1;
       
  4883 
       
  4884     mp4free(url);
       
  4885   }
       
  4886 
       
  4887   return 0;
       
  4888 }
       
  4889 
       
  4890 
       
  4891 /*
       
  4892  * Function:
       
  4893  *
       
  4894  *   mp4_i32 freeURN(dataEntryURNAtom *urn)
       
  4895  *
       
  4896  * Description:
       
  4897  *
       
  4898  *   This function frees memory for URN atom.
       
  4899  *
       
  4900  * Parameters:
       
  4901  *
       
  4902  *   urn        URN atom pointer
       
  4903  *
       
  4904  * Return value:
       
  4905  *
       
  4906  *   0          Success
       
  4907  *   Negative   Error
       
  4908  *
       
  4909  */
       
  4910 mp4_i32 freeURN(dataEntryURNAtom *urn)
       
  4911 {
       
  4912   if (urn)
       
  4913   {
       
  4914     if (freeAtomHeader(urn->atomhdr) < 0)
       
  4915       return -1;
       
  4916 
       
  4917     mp4free(urn);
       
  4918   }
       
  4919 
       
  4920   return 0;
       
  4921 }
       
  4922 
       
  4923 
       
  4924 /*
       
  4925  * Function:
       
  4926  *
       
  4927  *   mp4_i32 freeSTBL(sampleTableAtom *stbl)
       
  4928  *
       
  4929  * Description:
       
  4930  *
       
  4931  *   This function frees memory for STBL atom.
       
  4932  *
       
  4933  * Parameters:
       
  4934  *
       
  4935  *   stbl       STBL atom pointer
       
  4936  *
       
  4937  * Return value:
       
  4938  *
       
  4939  *   0          Success
       
  4940  *   Negative   Error
       
  4941  *
       
  4942  */
       
  4943 mp4_i32 freeSTBL(sampleTableAtom *stbl)
       
  4944 {
       
  4945   if (stbl)
       
  4946   {
       
  4947     if (freeAtomHeader(stbl->atomhdr) < 0)
       
  4948       return -1;
       
  4949     if (freeSTTS(stbl->stts) < 0)
       
  4950       return -1;
       
  4951     if (freeCTTS(stbl->ctts) < 0)
       
  4952       return -1;
       
  4953     if (freeSTSD(stbl->stsd) < 0)
       
  4954       return -1;
       
  4955     if (freeSTSZ(stbl->stsz) < 0)
       
  4956       return -1;
       
  4957     if (freeSTSC(stbl->stsc) < 0)
       
  4958       return -1;
       
  4959     if (stbl->is32BitOffsets)
       
  4960     {
       
  4961     
       
  4962       if (freeSTCO(stbl->stco) < 0)
       
  4963         return -1;
       
  4964     }
       
  4965     else
       
  4966     {
       
  4967     
       
  4968       if (freeSTCO64(stbl->stco64) < 0)
       
  4969         return -1;
       
  4970     }
       
  4971     if (freeSTSS(stbl->stss) < 0)
       
  4972       return -1;
       
  4973     if (freeSTSH(stbl->stsh) < 0)
       
  4974       return -1;
       
  4975     if (freeSDTP(stbl->sdtp) < 0)
       
  4976       return -1;
       
  4977 
       
  4978     mp4free(stbl);
       
  4979   }
       
  4980 
       
  4981   return 0;
       
  4982 }
       
  4983 
       
  4984 
       
  4985 /*
       
  4986  * Function:
       
  4987  *
       
  4988  *   mp4_i32 freeSTTS(timeToSampleAtom *stts)
       
  4989  *
       
  4990  * Description:
       
  4991  *
       
  4992  *   This function frees memory for STTS atom.
       
  4993  *
       
  4994  * Parameters:
       
  4995  *
       
  4996  *   stts       STTS atom pointer
       
  4997  *
       
  4998  * Return value:
       
  4999  *
       
  5000  *   0          Success
       
  5001  *   Negative   Error
       
  5002  *
       
  5003  */
       
  5004 mp4_i32 freeSTTS(timeToSampleAtom *stts)
       
  5005 {
       
  5006   if (stts)
       
  5007   {
       
  5008     if (freeAtomHeader(stts->atomhdr) < 0)
       
  5009       return -1;
       
  5010     if (stts->sampleCount)
       
  5011       mp4free(stts->sampleCount);
       
  5012     if (stts->sampleDelta)
       
  5013       mp4free(stts->sampleDelta);
       
  5014 
       
  5015     mp4free(stts);
       
  5016   }
       
  5017 
       
  5018   return 0;
       
  5019 }
       
  5020 
       
  5021 
       
  5022 /*
       
  5023  * Function:
       
  5024  *
       
  5025  *   mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts)
       
  5026  *
       
  5027  * Description:
       
  5028  *
       
  5029  *   This function frees memory for CTTS atom.
       
  5030  *
       
  5031  * Parameters:
       
  5032  *
       
  5033  *   ctts       CTTS atom pointer
       
  5034  *
       
  5035  * Return value:
       
  5036  *
       
  5037  *   0          Success
       
  5038  *   Negative   Error
       
  5039  *
       
  5040  */
       
  5041 mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts)
       
  5042 {
       
  5043   if (ctts)
       
  5044   {
       
  5045     if (freeAtomHeader(ctts->atomhdr) < 0)
       
  5046       return -1;
       
  5047     if (ctts->sampleCount)
       
  5048       mp4free(ctts->sampleCount);
       
  5049     if (ctts->sampleOffset)
       
  5050       mp4free(ctts->sampleOffset);
       
  5051 
       
  5052     mp4free(ctts);
       
  5053   }
       
  5054 
       
  5055   return 0;
       
  5056 }
       
  5057 
       
  5058 
       
  5059 /*
       
  5060  * Function:
       
  5061  *
       
  5062  *   mp4_i32 freeSTSD(sampleDescriptionAtom *stsd)
       
  5063  *
       
  5064  * Description:
       
  5065  *
       
  5066  *   This function frees memory for STSD atom.
       
  5067  *
       
  5068  * Parameters:
       
  5069  *
       
  5070  *   stsd       STSD atom pointer
       
  5071  *
       
  5072  * Return value:
       
  5073  *
       
  5074  *   0          Success
       
  5075  *   Negative   Error
       
  5076  *
       
  5077  */
       
  5078 mp4_i32 freeSTSD(sampleDescriptionAtom *stsd)
       
  5079 {
       
  5080   mp4_u32 sampleentrycount = 0;
       
  5081   mp4_u32 entryindex;
       
  5082   
       
  5083   if (stsd)
       
  5084   {
       
  5085 	sampleentrycount = stsd->entryCount;
       
  5086 
       
  5087     if (freeAtomHeader(stsd->atomhdr) < 0)
       
  5088       return -1;
       
  5089 	for (entryindex = 0; entryindex < sampleentrycount; entryindex++)
       
  5090 	{
       
  5091 		if (freeMP4V(stsd->mp4v[entryindex]) < 0)
       
  5092 		  return -1;
       
  5093 		if (freeMP4A(stsd->mp4a[entryindex]) < 0)
       
  5094 		  return -1;
       
  5095 		if (freeMP4S(stsd->mp4s[entryindex]) < 0)
       
  5096 		  return -1;
       
  5097 		if (freeS263(stsd->s263[entryindex]) < 0)
       
  5098 		  return -1;
       
  5099 		if (freeSAMR(stsd->samr[entryindex]) < 0)
       
  5100 		  return -1;
       
  5101 		if (freeSAWB(stsd->sawb[entryindex]) < 0)
       
  5102 		  return -1;
       
  5103 		if (freeAVC1(stsd->avc1[entryindex]) < 0)
       
  5104 			return -1;
       
  5105         if (freeSQCP(stsd->sqcp[entryindex]) < 0)
       
  5106           return -1;
       
  5107 	}
       
  5108     mp4free(stsd);
       
  5109   }
       
  5110 
       
  5111   return 0;
       
  5112 }
       
  5113 
       
  5114 
       
  5115 /*
       
  5116  * Function:
       
  5117  *
       
  5118  *   mp4_i32 freeMP4V(visualSampleEntry *mp4v)
       
  5119  *
       
  5120  * Description:
       
  5121  *
       
  5122  *   This function frees memory for MP4V atom.
       
  5123  *
       
  5124  * Parameters:
       
  5125  *
       
  5126  *   mp4v       MP4V atom pointer
       
  5127  *
       
  5128  * Return value:
       
  5129  *
       
  5130  *   0          Success
       
  5131  *   Negative   Error
       
  5132  *
       
  5133  */
       
  5134 mp4_i32 freeMP4V(visualSampleEntry *mp4v)
       
  5135 {
       
  5136   if (mp4v)
       
  5137   {
       
  5138     if (freeAtomHeader(mp4v->atomhdr) < 0)
       
  5139       return -1;
       
  5140     if (freeESD(mp4v->esd) < 0)
       
  5141       return -1;
       
  5142 
       
  5143     mp4free(mp4v);
       
  5144   }
       
  5145 
       
  5146   return 0;
       
  5147 }
       
  5148 
       
  5149 
       
  5150 /*
       
  5151  * Function:
       
  5152  *
       
  5153  *   mp4_i32 freeESD(ESDAtom *esd)
       
  5154  *
       
  5155  * Description:
       
  5156  *
       
  5157  *   This function frees memory for ESD atom.
       
  5158  *
       
  5159  * Parameters:
       
  5160  *
       
  5161  *   esd        ESD atom pointer
       
  5162  *
       
  5163  * Return value:
       
  5164  *
       
  5165  *   0          Success
       
  5166  *   Negative   Error
       
  5167  *
       
  5168  */
       
  5169 mp4_i32 freeESD(ESDAtom *esd)
       
  5170 {
       
  5171   if (esd)
       
  5172   {
       
  5173     if (freeAtomHeader(esd->atomhdr) < 0)
       
  5174       return -1;
       
  5175     if (esd->URLString)
       
  5176       mp4free(esd->URLString);
       
  5177     if (esd->decSpecificInfo)
       
  5178       mp4free(esd->decSpecificInfo);
       
  5179 
       
  5180     mp4free(esd);
       
  5181   }
       
  5182 
       
  5183   return 0;
       
  5184 }
       
  5185 
       
  5186 
       
  5187 /*
       
  5188  * Function:
       
  5189  *
       
  5190  *   mp4_i32 freeMP4A(audioSampleEntry *mp4a)
       
  5191  *
       
  5192  * Description:
       
  5193  *
       
  5194  *   This function frees memory for MP4A atom.
       
  5195  *
       
  5196  * Parameters:
       
  5197  *
       
  5198  *   mp4a       MP4A atom pointer
       
  5199  *
       
  5200  * Return value:
       
  5201  *
       
  5202  *   0          Success
       
  5203  *   Negative   Error
       
  5204  *
       
  5205  */
       
  5206 mp4_i32 freeMP4A(audioSampleEntry *mp4a)
       
  5207 {
       
  5208   if (mp4a)
       
  5209   {
       
  5210     if (freeAtomHeader(mp4a->atomhdr) < 0)
       
  5211       return -1;
       
  5212     if (freeESD(mp4a->esd) < 0)
       
  5213       return -1;
       
  5214 
       
  5215     mp4free(mp4a);
       
  5216   }
       
  5217 
       
  5218   return 0;
       
  5219 }
       
  5220 
       
  5221 
       
  5222 /*
       
  5223  * Function:
       
  5224  *
       
  5225  *   mp4_i32 freeMP4S(mpegSampleEntry *mp4s)
       
  5226  *
       
  5227  * Description:
       
  5228  *
       
  5229  *   This function frees memory for MP4S atom.
       
  5230  *
       
  5231  * Parameters:
       
  5232  *
       
  5233  *   mp4s       MP4S atom pointer
       
  5234  *
       
  5235  * Return value:
       
  5236  *
       
  5237  *   0          Success
       
  5238  *   Negative   Error
       
  5239  *
       
  5240  */
       
  5241 mp4_i32 freeMP4S(mpegSampleEntry *mp4s)
       
  5242 {
       
  5243   if (mp4s)
       
  5244   {
       
  5245     if (freeAtomHeader(mp4s->atomhdr) < 0)
       
  5246       return -1;
       
  5247     if (freeESD(mp4s->esd) < 0)
       
  5248       return -1;
       
  5249 
       
  5250     mp4free(mp4s);
       
  5251   }
       
  5252 
       
  5253   return 0;
       
  5254 }
       
  5255 
       
  5256 
       
  5257 /*
       
  5258  * Function:
       
  5259  *
       
  5260  *   mp4_i32 freeS263(h263SampleEntry *s263)
       
  5261  *
       
  5262  * Description:
       
  5263  *
       
  5264  *   This function frees memory for S263 atom.
       
  5265  *
       
  5266  * Parameters:
       
  5267  *
       
  5268  *   s263       S263 atom pointer
       
  5269  *
       
  5270  * Return value:
       
  5271  *
       
  5272  *   0          Success
       
  5273  *   Negative   Error
       
  5274  *
       
  5275  */
       
  5276 mp4_i32 freeS263(h263SampleEntry *s263)
       
  5277 {
       
  5278   if (s263)
       
  5279   {
       
  5280     if (freeAtomHeader(s263->atomhdr) < 0)
       
  5281       return -1;
       
  5282     if (freeD263(s263->d263) < 0)
       
  5283       return -1;
       
  5284 
       
  5285     mp4free(s263);
       
  5286   }
       
  5287 
       
  5288   return 0;
       
  5289 }
       
  5290 
       
  5291 
       
  5292 /*
       
  5293  * Function:
       
  5294  *
       
  5295  *   mp4_i32 freeD263(h263SpecificAtom *d263)
       
  5296  *
       
  5297  * Description:
       
  5298  *
       
  5299  *   This function frees memory for D263 atom.
       
  5300  *
       
  5301  * Parameters:
       
  5302  *
       
  5303  *   d263       D263 atom pointer
       
  5304  *
       
  5305  * Return value:
       
  5306  *
       
  5307  *   0          Success
       
  5308  *   Negative   Error
       
  5309  *
       
  5310  */
       
  5311 mp4_i32 freeD263(h263SpecificAtom *d263)
       
  5312 {
       
  5313   if (d263)
       
  5314   {
       
  5315     if (freeAtomHeader(d263->atomhdr) < 0)
       
  5316       return -1;
       
  5317     if (freeBITR(d263->bitr) < 0)
       
  5318       return -1;
       
  5319 
       
  5320     mp4free(d263);
       
  5321   }
       
  5322 
       
  5323   return 0;
       
  5324 }
       
  5325 
       
  5326 
       
  5327 /*
       
  5328  * Function:
       
  5329  *
       
  5330  *   mp4_i32 freeBITR(BitrateAtom *bitr)
       
  5331  *
       
  5332  * Description:
       
  5333  *
       
  5334  *   This function frees memory for BITR atom.
       
  5335  *
       
  5336  * Parameters:
       
  5337  *
       
  5338  *   bitr       BITR atom pointer
       
  5339  *
       
  5340  * Return value:
       
  5341  *
       
  5342  *   0          Success
       
  5343  *   Negative   Error
       
  5344  *
       
  5345  */
       
  5346 mp4_i32 freeBITR(bitrateAtom *bitr)
       
  5347 {
       
  5348   if (bitr)
       
  5349   {
       
  5350     if (freeAtomHeader(bitr->atomhdr) < 0)
       
  5351       return -1;
       
  5352 
       
  5353     mp4free(bitr);
       
  5354   }
       
  5355 
       
  5356   return 0;
       
  5357 }
       
  5358 
       
  5359 
       
  5360 /*
       
  5361  * Function:
       
  5362  *
       
  5363  *   mp4_i32 freeSAMR(amrSampleEntry *samr)
       
  5364  *
       
  5365  * Description:
       
  5366  *
       
  5367  *   This function frees memory for SAMR atom.
       
  5368  *
       
  5369  * Parameters:
       
  5370  *
       
  5371  *   samr       SAMR atom pointer
       
  5372  *
       
  5373  * Return value:
       
  5374  *
       
  5375  *   0          Success
       
  5376  *   Negative   Error
       
  5377  *
       
  5378  */
       
  5379 mp4_i32 freeSAMR(amrSampleEntry *samr)
       
  5380 {
       
  5381   if (samr)
       
  5382   {
       
  5383     if (freeAtomHeader(samr->atomhdr) < 0)
       
  5384       return -1;
       
  5385     if (freeDAMR(samr->damr) < 0)
       
  5386       return -1;
       
  5387 
       
  5388     mp4free(samr);
       
  5389   }
       
  5390 
       
  5391   return 0;
       
  5392 }
       
  5393 
       
  5394 
       
  5395 /*
       
  5396  * Function:
       
  5397  *
       
  5398  *   mp4_i32 freeSAWB(amrSampleEntry *sawb)
       
  5399  *
       
  5400  * Description:
       
  5401  *
       
  5402  *   This function frees memory for SAWB atom.
       
  5403  *
       
  5404  * Parameters:
       
  5405  *
       
  5406  *   sawb       SAWB atom pointer
       
  5407  *
       
  5408  * Return value:
       
  5409  *
       
  5410  *   0          Success
       
  5411  *   Negative   Error
       
  5412  *
       
  5413  */
       
  5414 mp4_i32 freeSAWB(amrSampleEntry *sawb)
       
  5415 {
       
  5416   if (sawb)
       
  5417   {
       
  5418     if (freeAtomHeader(sawb->atomhdr) < 0)
       
  5419       return -1;
       
  5420     if (freeDAMR(sawb->damr) < 0)
       
  5421       return -1;
       
  5422 
       
  5423     mp4free(sawb);
       
  5424   }
       
  5425 
       
  5426   return 0;
       
  5427 }
       
  5428 
       
  5429 
       
  5430 /*
       
  5431  * Function:
       
  5432  *
       
  5433  *   mp4_i32 freeDAMR(amrDecSpecStruc *damr)
       
  5434  *
       
  5435  * Description:
       
  5436  *
       
  5437  *   This function frees memory for DAMR atom.
       
  5438  *
       
  5439  * Parameters:
       
  5440  *
       
  5441  *   damr       DAMR atom pointer
       
  5442  *
       
  5443  * Return value:
       
  5444  *
       
  5445  *   0          Success
       
  5446  *   Negative   Error
       
  5447  *
       
  5448  */
       
  5449 mp4_i32 freeDAMR(amrDecSpecStruc *damr)
       
  5450 {
       
  5451   if (damr)
       
  5452   {
       
  5453     if (freeAtomHeader(damr->atomhdr) < 0)
       
  5454       return -1;
       
  5455 
       
  5456     mp4free(damr);
       
  5457   }
       
  5458 
       
  5459   return 0;
       
  5460 }
       
  5461 
       
  5462 
       
  5463 /*
       
  5464  * Function:
       
  5465  *
       
  5466  *   mp4_i32 freeSTSZ(sampleSizeAtom *stsz)
       
  5467  *
       
  5468  * Description:
       
  5469  *
       
  5470  *   This function frees memory for STSZ atom.
       
  5471  *
       
  5472  * Parameters:
       
  5473  *
       
  5474  *   stsz       STSZ atom pointer
       
  5475  *
       
  5476  * Return value:
       
  5477  *
       
  5478  *   0          Success
       
  5479  *   Negative   Error
       
  5480  *
       
  5481  */
       
  5482 mp4_i32 freeSTSZ(sampleSizeAtom *stsz)
       
  5483 {
       
  5484   if (stsz)
       
  5485   {
       
  5486     if (freeAtomHeader(stsz->atomhdr) < 0)
       
  5487       return -1;
       
  5488     if (stsz->entrySize)
       
  5489       mp4free(stsz->entrySize);
       
  5490 
       
  5491     mp4free(stsz);
       
  5492   }
       
  5493 
       
  5494   return 0;
       
  5495 }
       
  5496 
       
  5497 
       
  5498 /*
       
  5499  * Function:
       
  5500  *
       
  5501  *   mp4_i32 freeSTSC(sampleToChunkAtom *stsc)
       
  5502  *
       
  5503  * Description:
       
  5504  *
       
  5505  *   This function frees memory for STSC atom.
       
  5506  *
       
  5507  * Parameters:
       
  5508  *
       
  5509  *   stsc       STSC atom pointer
       
  5510  *
       
  5511  * Return value:
       
  5512  *
       
  5513  *   0          Success
       
  5514  *   Negative   Error
       
  5515  *
       
  5516  */
       
  5517 mp4_i32 freeSTSC(sampleToChunkAtom *stsc)
       
  5518 {
       
  5519   if (stsc)
       
  5520   {
       
  5521     if (freeAtomHeader(stsc->atomhdr) < 0)
       
  5522       return -1;
       
  5523     if (stsc->firstChunk)
       
  5524       mp4free(stsc->firstChunk);
       
  5525     if (stsc->samplesPerChunk)
       
  5526       mp4free(stsc->samplesPerChunk);
       
  5527     if (stsc->sampleDescriptionIndex)
       
  5528       mp4free(stsc->sampleDescriptionIndex);
       
  5529 
       
  5530     mp4free(stsc);
       
  5531   }
       
  5532 
       
  5533   return 0;
       
  5534 }
       
  5535 
       
  5536 
       
  5537 /*
       
  5538  * Function:
       
  5539  *
       
  5540  *   mp4_i32 freeSTCO(chunkOffsetAtom *stco)
       
  5541  *
       
  5542  * Description:
       
  5543  *
       
  5544  *   This function frees memory for STCO atom.
       
  5545  *
       
  5546  * Parameters:
       
  5547  *
       
  5548  *   stco       STCO atom pointer
       
  5549  *
       
  5550  * Return value:
       
  5551  *
       
  5552  *   0          Success
       
  5553  *   Negative   Error
       
  5554  *
       
  5555  */
       
  5556 mp4_i32 freeSTCO(chunkOffsetAtom *stco)
       
  5557 {
       
  5558   if (stco)
       
  5559   {
       
  5560     if (freeAtomHeader(stco->atomhdr) < 0)
       
  5561       return -1;
       
  5562     if (stco->chunkOffset)
       
  5563       mp4free(stco->chunkOffset);
       
  5564 
       
  5565     mp4free(stco);
       
  5566   }
       
  5567 
       
  5568   return 0;
       
  5569 }
       
  5570 
       
  5571 /*
       
  5572  * Function:
       
  5573  *
       
  5574  *   mp4_i32 freeSTCO64(chunkOffset64Atom *stco64)
       
  5575  *
       
  5576  * Description:
       
  5577  *
       
  5578  *   This function frees memory for STCO64 atom.
       
  5579  *
       
  5580  * Parameters:
       
  5581  *
       
  5582  *   stco64       STCO64 atom pointer
       
  5583  *
       
  5584  * Return value:
       
  5585  *
       
  5586  *   0          Success
       
  5587  *   Negative   Error
       
  5588  *
       
  5589  */
       
  5590 mp4_i32 freeSTCO64(chunkOffset64Atom *stco64)
       
  5591 {
       
  5592   if (stco64)
       
  5593   {
       
  5594     if (freeAtomHeader(stco64->atomhdr) < 0)
       
  5595       return -1;
       
  5596     if (stco64->chunkOffset)
       
  5597       mp4free(stco64->chunkOffset);
       
  5598 
       
  5599     mp4free(stco64);
       
  5600   }
       
  5601 
       
  5602   return 0;
       
  5603 }
       
  5604 
       
  5605 
       
  5606 /*
       
  5607  * Function:
       
  5608  *
       
  5609  *   mp4_i32 freeSTSS(syncSampleAtom *stss)
       
  5610  *
       
  5611  * Description:
       
  5612  *
       
  5613  *   This function frees memory for STSS atom.
       
  5614  *
       
  5615  * Parameters:
       
  5616  *
       
  5617  *   stss       STSS atom pointer
       
  5618  *
       
  5619  * Return value:
       
  5620  *
       
  5621  *   0          Success
       
  5622  *   Negative   Error
       
  5623  *
       
  5624  */
       
  5625 mp4_i32 freeSTSS(syncSampleAtom *stss)
       
  5626 {
       
  5627   if (stss)
       
  5628   {
       
  5629     if (freeAtomHeader(stss->atomhdr) < 0)
       
  5630       return -1;
       
  5631     if (stss->sampleNumber)
       
  5632       mp4free(stss->sampleNumber);
       
  5633 
       
  5634     mp4free(stss);
       
  5635   }
       
  5636 
       
  5637   return 0;
       
  5638 }
       
  5639 
       
  5640 
       
  5641 /*
       
  5642  * Function:
       
  5643  *
       
  5644  *   mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh)
       
  5645  *
       
  5646  * Description:
       
  5647  *
       
  5648  *   This function frees memory for STSH atom.
       
  5649  *
       
  5650  * Parameters:
       
  5651  *
       
  5652  *   stsh       STSH atom pointer
       
  5653  *
       
  5654  * Return value:
       
  5655  *
       
  5656  *   0          Success
       
  5657  *   Negative   Error
       
  5658  *
       
  5659  */
       
  5660 mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh)
       
  5661 {
       
  5662   if (stsh)
       
  5663   {
       
  5664     if (freeAtomHeader(stsh->atomhdr) < 0)
       
  5665       return -1;
       
  5666 
       
  5667     mp4free(stsh);
       
  5668   }
       
  5669 
       
  5670   return 0;
       
  5671 }
       
  5672 
       
  5673 
       
  5674 /*
       
  5675  * Function:
       
  5676  *
       
  5677  *   mp4_i32 freeSDTP(sampleDependencyAtom *sdtp)
       
  5678  *
       
  5679  * Description:
       
  5680  *
       
  5681  *   This function frees memory for SDTP atom.
       
  5682  *
       
  5683  * Parameters:
       
  5684  *
       
  5685  *   sdtp       SDTP atom pointer
       
  5686  *
       
  5687  * Return value:
       
  5688  *
       
  5689  *   0          Success
       
  5690  *   Negative   Error
       
  5691  *
       
  5692  */
       
  5693 mp4_i32 freeSDTP(sampleDependencyAtom *sdtp)
       
  5694 	{
       
  5695 	if (sdtp)
       
  5696 		{
       
  5697 		if (freeAtomHeader(sdtp->atomhdr) < 0)
       
  5698 			{
       
  5699 			return -1;
       
  5700 			}
       
  5701 
       
  5702 		if (sdtp->dep)
       
  5703 			{
       
  5704 			mp4free(sdtp->dep);
       
  5705 			}		
       
  5706     
       
  5707 		mp4free(sdtp);
       
  5708 		}
       
  5709 
       
  5710   	return 0;
       
  5711 	}
       
  5712 
       
  5713 /*
       
  5714  * Function:
       
  5715  *
       
  5716  *   mp4_i32 freeIODS(objectDescriptorAtom *iods)
       
  5717  *
       
  5718  * Description:
       
  5719  *
       
  5720  *   This function frees memory for IODS atom.
       
  5721  *
       
  5722  * Parameters:
       
  5723  *
       
  5724  *   iods       IODS atom pointer
       
  5725  *
       
  5726  * Return value:
       
  5727  *
       
  5728  *   0          Success
       
  5729  *   Negative   Error
       
  5730  *
       
  5731  */
       
  5732 mp4_i32 freeIODS(objectDescriptorAtom *iods)
       
  5733 {
       
  5734   if (iods)
       
  5735   {
       
  5736     if (freeAtomHeader(iods->atomhdr) < 0)
       
  5737       return -1;
       
  5738 
       
  5739     mp4free(iods);
       
  5740   }
       
  5741 
       
  5742   return 0;
       
  5743 }
       
  5744 
       
  5745 
       
  5746 /*
       
  5747  * Function:
       
  5748  *
       
  5749  *   mp4_i32 readUDTA(MP4HandleImp handle,
       
  5750  *                    userDataAtom *udta)
       
  5751  *
       
  5752  * Description:
       
  5753  *
       
  5754  *   This function parses one UDTA atom.
       
  5755  *
       
  5756  * Parameters:
       
  5757  *
       
  5758  *   handle             MP4 library handle
       
  5759  *   udta               UDTA pointer
       
  5760  *
       
  5761  * Return value:
       
  5762  *
       
  5763  *   Negative integer   Error
       
  5764  *   >= 0               Success. Value tells how many bytes were read.
       
  5765  *
       
  5766  */
       
  5767 mp4_i32 readUDTA(MP4HandleImp handle, userDataAtom *udta)
       
  5768 {
       
  5769   mp4_i32 bytesread;
       
  5770   mp4_i32 totalbytesread = 0;
       
  5771 
       
  5772   if ((udta->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  5773     return -100;
       
  5774 
       
  5775   bytesread = readAtomHeader(handle, udta->atomhdr);
       
  5776   if (bytesread < 0)
       
  5777     return -1;
       
  5778   totalbytesread += bytesread;
       
  5779 
       
  5780   if (udta->atomhdr->type != ATOMTYPE_UDTA)
       
  5781     return -1;
       
  5782 
       
  5783   if ( handle->file )
       
  5784       {
       
  5785       udta->atomcontentloc = handle->diskReadBufStart + handle->diskReadBufPos;
       
  5786       }
       
  5787   else
       
  5788       {
       
  5789       udta->atomcontentloc = handle->absPosition;
       
  5790       }
       
  5791 
       
  5792   if ( udta->atomhdr->size == 1 )
       
  5793       {
       
  5794       udta->atomcontentsize = I64INT(udta->atomhdr->largeSize) - (TInt)totalbytesread;
       
  5795       }
       
  5796   else
       
  5797       {
       
  5798       udta->atomcontentsize = (TInt)(udta->atomhdr->size - totalbytesread);
       
  5799       }
       
  5800 
       
  5801   if ( handle->file )
       
  5802   {
       
  5803   	if ( seekFile(handle, udta->atomhdr->size - totalbytesread) < 0 )
       
  5804   	{
       
  5805   	   return -1;	
       
  5806   	}
       
  5807   	else
       
  5808   	{
       
  5809   	   return udta->atomhdr->size;	
       
  5810   	}
       
  5811   }
       
  5812   else
       
  5813   {
       
  5814 	  bytesread = discardData(handle, udta->atomhdr->size - totalbytesread);
       
  5815 	  if (bytesread < 0)
       
  5816 	    return -1;
       
  5817 	  totalbytesread += bytesread;
       
  5818   }
       
  5819   return totalbytesread;
       
  5820 }
       
  5821 
       
  5822 /*
       
  5823  * Function:
       
  5824  *
       
  5825  *   mp4_i32 freeUDTA(userDataAtom *udta)
       
  5826  *
       
  5827  * Description:
       
  5828  *
       
  5829  *   This function frees memory for UDTA atom.
       
  5830  *
       
  5831  * Parameters:
       
  5832  *
       
  5833  *   udta       UDTA atom pointer
       
  5834  *
       
  5835  * Return value:
       
  5836  *
       
  5837  *   0          Success
       
  5838  *   Negative   Error
       
  5839  *
       
  5840  */
       
  5841 mp4_i32 freeUDTA(userDataAtom *udta)
       
  5842 {
       
  5843   if (udta)
       
  5844   {
       
  5845     if (freeAtomHeader(udta->atomhdr) < 0)
       
  5846       return -1;
       
  5847     mp4free(udta);
       
  5848   }
       
  5849 
       
  5850   return 0;
       
  5851 }
       
  5852 
       
  5853 
       
  5854 /*
       
  5855  * Function:
       
  5856  *
       
  5857  *   mp4_i32 determineVideoLength(MP4HandleImp handle,
       
  5858  *                                mp4_u32 *videolength)
       
  5859  *
       
  5860  * Description:
       
  5861  *
       
  5862  *   This function determines the length of video in milliseconds.
       
  5863  *
       
  5864  * Parameters:
       
  5865  *
       
  5866  *   handle       MP4 library handle
       
  5867  *   videolength  Video length is returned here
       
  5868  *
       
  5869  * Return value:
       
  5870  *
       
  5871  *   0            Success
       
  5872  *   Negative     Error
       
  5873  *
       
  5874  */
       
  5875 mp4_i32 determineVideoLength(MP4HandleImp handle, mp4_u32 *videolength)
       
  5876 {
       
  5877   if (!handle->moov)
       
  5878     return -1;
       
  5879 
       
  5880   if (!handle->moov->mvhd)
       
  5881     return -1;
       
  5882 
       
  5883   if (!handle->moov->trakVideo)
       
  5884     return -1;
       
  5885 
       
  5886   if (!handle->moov->trakVideo->tkhd)
       
  5887     return -1;
       
  5888 
       
  5889   /* Is timescale set? */
       
  5890   if (handle->moov->mvhd->timeScale == 0)
       
  5891     return -1;
       
  5892 
       
  5893   *videolength = (mp4_u32)(((mp4_double)handle->moov->trakVideo->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000);
       
  5894 
       
  5895   return 0;
       
  5896 }
       
  5897 
       
  5898 
       
  5899 /*
       
  5900  * Function:
       
  5901  *
       
  5902  *   mp4_i32 determineFrameRate(MP4HandleImp handle,
       
  5903  *                              mp4_double *framerate)
       
  5904  *
       
  5905  * Description:
       
  5906  *
       
  5907  *   This function determines the frame rate of video.
       
  5908  *
       
  5909  *   Frame rate is calculated as the average frame rate of the entire video.
       
  5910  *
       
  5911  * Parameters:
       
  5912  *
       
  5913  *   handle     MP4 library handle
       
  5914  *   framerate  Frame rate is returned here
       
  5915  *
       
  5916  * Return value:
       
  5917  *
       
  5918  *   0          Success
       
  5919  *   Negative   Error
       
  5920  *
       
  5921  */
       
  5922 mp4_i32 determineFrameRate(MP4HandleImp handle, mp4_double *framerate)
       
  5923 {
       
  5924   mp4_double numberofframes;
       
  5925   mp4_double length;
       
  5926 
       
  5927 
       
  5928   if (!handle)
       
  5929     return -1;
       
  5930   if (!handle->moov)
       
  5931     return -1;
       
  5932   if (!handle->moov->trakVideo)
       
  5933     return -1;
       
  5934   if (!handle->moov->trakVideo->mdia)
       
  5935     return -1;
       
  5936   if (!handle->moov->trakVideo->mdia->minf)
       
  5937     return -1;
       
  5938   if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  5939     return -1;
       
  5940   if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
       
  5941     return -1;
       
  5942   if (!handle->moov->trakVideo->mdia->mdhd)
       
  5943     return -1;
       
  5944 
       
  5945 
       
  5946   	if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
       
  5947     	return -1;
       
  5948   	
       
  5949   	if (handle->moov->trakVideo->mdia->mdhd->duration == 0)
       
  5950   		{
       
  5951   		*framerate = 0;
       
  5952   		}
       
  5953 	else
       
  5954 		{
       
  5955   		numberofframes = (mp4_double)handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount;
       
  5956   		length = (mp4_double)handle->moov->trakVideo->mdia->mdhd->duration /
       
  5957            		 (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale;
       
  5958 
       
  5959   		*framerate = numberofframes / length;			
       
  5960 		}    
       
  5961 
       
  5962   	return 0;
       
  5963 	}
       
  5964 
       
  5965 
       
  5966 /*
       
  5967  * Function:
       
  5968  *
       
  5969  *   mp4_i32 determineVideoType(MP4HandleImp handle,
       
  5970  *                              mp4_u32 *videotype)
       
  5971  *
       
  5972  * Description:
       
  5973  *
       
  5974  *   This function determines the video type of the MP4.
       
  5975  *
       
  5976  * Parameters:
       
  5977  *
       
  5978  *   handle     MP4 library handle
       
  5979  *   videotype  Video type is returned here
       
  5980  *
       
  5981  * Return value:
       
  5982  *
       
  5983  *   0          Success
       
  5984  *   -1			Error
       
  5985  *	 -2			Unknown video type
       
  5986  *
       
  5987  */
       
  5988 mp4_i32 determineVideoType(MP4HandleImp handle, mp4_u32 *videotype)
       
  5989 {
       
  5990   *videotype = MP4_TYPE_NONE;
       
  5991 
       
  5992   if (!handle->moov)
       
  5993     return -1;
       
  5994 
       
  5995   if (!handle->moov->trakVideo)
       
  5996     return -1;
       
  5997 
       
  5998   if (!handle->moov->trakVideo->mdia)
       
  5999     return -1;
       
  6000 
       
  6001   if (!handle->moov->trakVideo->mdia->minf)
       
  6002     return -1;
       
  6003 
       
  6004   if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  6005     return -1;
       
  6006 
       
  6007   if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
       
  6008     return -1;
       
  6009   
       
  6010   if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0)
       
  6011     return -1;  
       
  6012 
       
  6013 /* Assume that the video type is the same for all sample entries. Just get the video type from the first one */
       
  6014 
       
  6015   if (handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0])
       
  6016   {
       
  6017     if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd)
       
  6018       return -1;
       
  6019 
       
  6020     if ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->objectTypeIndication == 0x20) &&
       
  6021         ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->stream >> 2) == 0x04))
       
  6022       *videotype = MP4_TYPE_MPEG4_VIDEO;
       
  6023   }
       
  6024   else
       
  6025   if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
       
  6026   {
       
  6027     if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263)
       
  6028       return -1;
       
  6029 
       
  6030     switch (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Profile)
       
  6031     {
       
  6032     case 0:
       
  6033       *videotype = MP4_TYPE_H263_PROFILE_0;
       
  6034       break;
       
  6035     case 3:
       
  6036       *videotype = MP4_TYPE_H263_PROFILE_3;
       
  6037       break;
       
  6038     default:
       
  6039       break;
       
  6040     }
       
  6041   }
       
  6042   else
       
  6043    if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0])
       
  6044    {
       
  6045 	   if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc)
       
  6046 		   return -1;
       
  6047 
       
  6048 	   if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize == 0)
       
  6049 		   return -1;
       
  6050 
       
  6051 	   /* AVC profile is in the second byte of the avcconfigrecord */
       
  6052 	   switch((mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[1]) 
       
  6053 	   {
       
  6054 	   case 66:
       
  6055 		   *videotype = MP4_TYPE_AVC_PROFILE_BASELINE;
       
  6056 		   break;
       
  6057 	   case 77:
       
  6058 		   *videotype = MP4_TYPE_AVC_PROFILE_MAIN;
       
  6059 		   break;
       
  6060 	   case 88:
       
  6061 		   *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED;
       
  6062 		   break;
       
  6063        case 100:
       
  6064           *videotype = MP4_TYPE_AVC_PROFILE_HIGH;
       
  6065            break;
       
  6066 	   default:
       
  6067 		   {
       
  6068 		   mp4_u8 constraintByte = (mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[2];
       
  6069 		   if ( (constraintByte & 0x80) || (constraintByte & 0x10) )
       
  6070 			   {
       
  6071 			   *videotype = MP4_TYPE_AVC_PROFILE_BASELINE;	
       
  6072 			   }
       
  6073 		   else if (constraintByte & 0x40)
       
  6074 			   {
       
  6075 			   *videotype = MP4_TYPE_AVC_PROFILE_MAIN;	
       
  6076 			   }
       
  6077 		   else if (constraintByte & 0x20)
       
  6078 			   {
       
  6079 			   *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED;
       
  6080 			   }
       
  6081 		   // NOTE: Cannot reliably determine higher profiles from
       
  6082 		   // the constraint flags.
       
  6083 		   break;	   	
       
  6084 		   }
       
  6085 	   }
       
  6086 	}
       
  6087    else
       
  6088        {}
       
  6089    /* Note: Read the AVC level and recreate the actual AVC profile and level in the future! */
       
  6090   if (*videotype == MP4_TYPE_NONE)
       
  6091     return -2;
       
  6092 
       
  6093   return 0;
       
  6094 }
       
  6095 
       
  6096 
       
  6097 /*
       
  6098  * Function:
       
  6099  *
       
  6100  *   mp4_i32 determineVideoResolution(MP4HandleImp handle,
       
  6101  *                                    mp4_u32 *videowidth,
       
  6102  *                                    mp4_u32 *videoheight)
       
  6103  *
       
  6104  * Description:
       
  6105  *
       
  6106  *   This function finds out the video width and height from the atom
       
  6107  *   structure.
       
  6108  *
       
  6109  * Parameters:
       
  6110  *
       
  6111  *   handle       MP4 library handle
       
  6112  *   videowidth   Video width is returned here
       
  6113  *   videoheight  Video height is returned here
       
  6114  *
       
  6115  * Return value:
       
  6116  *
       
  6117  *   0            Success
       
  6118  *   Negative     Error
       
  6119  *
       
  6120  */
       
  6121 mp4_i32 determineVideoResolution(MP4HandleImp handle, mp4_u32 *videowidth, mp4_u32 *videoheight)
       
  6122 {
       
  6123   mp4_u32 videotype = MP4_TYPE_NONE;
       
  6124 
       
  6125 
       
  6126   if (determineVideoType(handle, &videotype) < 0)
       
  6127     return -1;
       
  6128 
       
  6129   if (videotype == MP4_TYPE_NONE)
       
  6130     return -1;
       
  6131 
       
  6132   if (!handle->moov)
       
  6133     return -1;
       
  6134 
       
  6135   if (!handle->moov->trakVideo)
       
  6136     return -1;
       
  6137 
       
  6138   if (!handle->moov->trakVideo->mdia)
       
  6139     return -1;
       
  6140 
       
  6141   if (!handle->moov->trakVideo->mdia->minf)
       
  6142     return -1;
       
  6143 
       
  6144   if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  6145     return -1;
       
  6146 
       
  6147   if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
       
  6148     return -1;
       
  6149 
       
  6150   if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0)
       
  6151     return -1;  
       
  6152   
       
  6153 /* Assume that the video characteristics for all the video sample entries are the same. Just get them from the first one */
       
  6154 
       
  6155   if (videotype == MP4_TYPE_H263_PROFILE_0 ||
       
  6156       videotype == MP4_TYPE_H263_PROFILE_3)
       
  6157   {
       
  6158     if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
       
  6159       return -1;
       
  6160 
       
  6161     *videowidth  = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->width;
       
  6162     *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->height;
       
  6163   }
       
  6164   else if (videotype == MP4_TYPE_MPEG4_VIDEO)
       
  6165   {
       
  6166     if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0])
       
  6167       return -1;
       
  6168 
       
  6169     *videowidth  = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->width;
       
  6170     *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->height;
       
  6171   }
       
  6172   else if ( isAvcVideo(videotype) )
       
  6173   {
       
  6174     if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0])
       
  6175       return -1;
       
  6176 
       
  6177     *videowidth  = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->width;
       
  6178     *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->height;
       
  6179   }
       
  6180   else
       
  6181   {
       
  6182   }
       
  6183 
       
  6184   return 0;
       
  6185 }
       
  6186 
       
  6187 
       
  6188 /*
       
  6189  * Function:
       
  6190  *
       
  6191  *   mp4_i32 determineVideoTimeScale(MP4HandleImp handle,
       
  6192  *                                   mp4_u32 *timescale)
       
  6193  *
       
  6194  * Description:
       
  6195  *
       
  6196  *   This function determines the timescale of video track.
       
  6197  *
       
  6198  * Parameters:
       
  6199  *
       
  6200  *   handle     MP4 library handle
       
  6201  *   timescale  Timescale of video track is returned here
       
  6202  *
       
  6203  * Return value:
       
  6204  *
       
  6205  *   0          Success
       
  6206  *   Negative   Error
       
  6207  *
       
  6208  */
       
  6209 mp4_i32 determineVideoTimeScale(MP4HandleImp handle, mp4_u32 *timescale)
       
  6210 {
       
  6211   if (timescale == NULL)
       
  6212     return 0;
       
  6213 
       
  6214   if (!handle)
       
  6215     return -1;
       
  6216   if (!handle->moov)
       
  6217     return -1;
       
  6218   if (!handle->moov->trakVideo)
       
  6219     return -1;
       
  6220   if (!handle->moov->trakVideo->mdia)
       
  6221     return -1;
       
  6222   if (!handle->moov->trakVideo->mdia->mdhd)
       
  6223     return -1;
       
  6224   if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
       
  6225     return -1;
       
  6226 
       
  6227   *timescale = handle->moov->trakVideo->mdia->mdhd->timeScale;
       
  6228 
       
  6229   return 0;
       
  6230 }
       
  6231 
       
  6232 
       
  6233 /*
       
  6234  * Function:
       
  6235  *
       
  6236  *   mp4_i32 determineAudioLength(MP4HandleImp handle,
       
  6237  *                                mp4_u32 *audiolength)
       
  6238  *
       
  6239  * Description:
       
  6240  *
       
  6241  *   This function determines the length of audio in milliseconds.
       
  6242  *
       
  6243  * Parameters:
       
  6244  *
       
  6245  *   handle       MP4 library handle
       
  6246  *   audiolength  Audio length is returned here
       
  6247  *
       
  6248  * Return value:
       
  6249  *
       
  6250  *   0            Success
       
  6251  *   Negative     Error
       
  6252  *
       
  6253  */
       
  6254 mp4_i32 determineAudioLength(MP4HandleImp handle, mp4_u32 *audiolength)
       
  6255 {
       
  6256   if (!handle->moov)
       
  6257     return -1;
       
  6258 
       
  6259   if (!handle->moov->mvhd)
       
  6260     return -1;
       
  6261 
       
  6262   if (!handle->moov->trakAudio)
       
  6263     return -1;
       
  6264 
       
  6265   if (!handle->moov->trakAudio->tkhd)
       
  6266     return -1;
       
  6267 
       
  6268   /* Is timescale set? */
       
  6269   if (handle->moov->mvhd->timeScale == 0)
       
  6270     return -1;
       
  6271 
       
  6272   *audiolength = (mp4_u32)(((mp4_double)handle->moov->trakAudio->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000);
       
  6273 
       
  6274   return 0;
       
  6275 }
       
  6276 
       
  6277 
       
  6278 /*
       
  6279  * Function:
       
  6280  *
       
  6281  *   mp4_i32 determineAudioType(MP4HandleImp handle,
       
  6282  *                              mp4_u32 *audiotype)
       
  6283  *
       
  6284  * Description:
       
  6285  *
       
  6286  *   This function determines the audio type of the MP4.
       
  6287  *
       
  6288  * Parameters:
       
  6289  *
       
  6290  *   handle     MP4 library handle
       
  6291  *   audiotype  Audio type is returned here
       
  6292  *
       
  6293  * Return value:
       
  6294  *
       
  6295  *   0          Success
       
  6296  *   -1   		Error
       
  6297  *   -2			Unknown audiotrack
       
  6298  *
       
  6299  */
       
  6300 mp4_i32 determineAudioType(MP4HandleImp handle, mp4_u32 *audiotype)
       
  6301 {
       
  6302   *audiotype = MP4_TYPE_NONE;
       
  6303 
       
  6304 
       
  6305   if (!handle->moov)
       
  6306     return -1;
       
  6307 
       
  6308   if (!handle->moov->trakAudio)
       
  6309     return -1;
       
  6310 
       
  6311   if (!handle->moov->trakAudio->mdia)
       
  6312     return -1;
       
  6313 
       
  6314   if (!handle->moov->trakAudio->mdia->minf)
       
  6315     return -1;
       
  6316 
       
  6317   if (!handle->moov->trakAudio->mdia->minf->stbl)
       
  6318     return -1;
       
  6319 
       
  6320   if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
       
  6321     return -1;
       
  6322   
       
  6323   if (handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount == 0)
       
  6324     return -1;  
       
  6325 
       
  6326 /* Assume that the audio type is the same for all sample entries. Just get the audio type from the first one */
       
  6327   if (handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0])
       
  6328   {
       
  6329     if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd)
       
  6330       return -1;
       
  6331 
       
  6332     if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0x40) &&
       
  6333         ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05))
       
  6334       *audiotype = MP4_TYPE_MPEG4_AUDIO;
       
  6335 
       
  6336    if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0xE1) &&
       
  6337      ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05))  
       
  6338    {
       
  6339       *audiotype = MP4_TYPE_QCELP_13K;
       
  6340       handle->qcelpStoredAsMPEGAudio = MP4TRUE;
       
  6341    }
       
  6342   }
       
  6343   else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[0])
       
  6344     *audiotype = MP4_TYPE_AMR_NB;
       
  6345   else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[0])
       
  6346     *audiotype = MP4_TYPE_AMR_WB;
       
  6347   else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[0])
       
  6348   {
       
  6349     *audiotype = MP4_TYPE_QCELP_13K;
       
  6350     handle->qcelpStoredAsMPEGAudio = MP4FALSE;
       
  6351   }
       
  6352   else
       
  6353   {
       
  6354   }
       
  6355 
       
  6356   if (*audiotype == MP4_TYPE_NONE)
       
  6357     return -2;
       
  6358 
       
  6359   return 0;
       
  6360 }
       
  6361 
       
  6362 
       
  6363 /*
       
  6364  * Function:
       
  6365  *
       
  6366  *   mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle,
       
  6367  *                                         mp4_u8 *framespersample)
       
  6368  *
       
  6369  * Description:
       
  6370  *
       
  6371  *   This function determines the number of audio frames in each sample.
       
  6372  *   The function works with AMR audio type only.
       
  6373  *
       
  6374  * Parameters:
       
  6375  *
       
  6376  *   handle           MP4 library handle
       
  6377  *   framespersample  Number of frames in each sample
       
  6378  *
       
  6379  * Return value:
       
  6380  *
       
  6381  *   0                Success
       
  6382  *   Negative         Error
       
  6383  *
       
  6384  */
       
  6385 mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle, mp4_u8 *framespersample)
       
  6386 {
       
  6387   mp4_i8 sampleentryindex;
       
  6388   
       
  6389   *framespersample = 0;
       
  6390 
       
  6391 
       
  6392   if (!((handle->type & MP4_TYPE_AMR_NB) ||
       
  6393         (handle->type & MP4_TYPE_AMR_WB) ||
       
  6394         ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))))
       
  6395   {
       
  6396     *framespersample = 1;
       
  6397 
       
  6398     return 0;
       
  6399   }
       
  6400 
       
  6401 
       
  6402   if (!handle->moov)
       
  6403     return -1;
       
  6404 
       
  6405   if (!handle->moov->trakAudio)
       
  6406     return -1;
       
  6407 
       
  6408   if (!handle->moov->trakAudio->mdia)
       
  6409     return -1;
       
  6410 
       
  6411   if (!handle->moov->trakAudio->mdia->minf)
       
  6412     return -1;
       
  6413 
       
  6414   if (!handle->moov->trakAudio->mdia->minf->stbl)
       
  6415     return -1;
       
  6416 
       
  6417   if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
       
  6418     return -1;
       
  6419 
       
  6420   if (handle->type & MP4_TYPE_AMR_NB)
       
  6421   {
       
  6422 /* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/
       
  6423 	for (sampleentryindex = 0; (mp4_u8) sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
       
  6424 	{
       
  6425 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex])
       
  6426 		  return -1;
       
  6427 
       
  6428 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr)
       
  6429 		  return -1;
       
  6430 
       
  6431 		if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample)
       
  6432 			*framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample;
       
  6433 	}
       
  6434   }
       
  6435   else if (handle->type & MP4_TYPE_AMR_WB)
       
  6436   {
       
  6437 /* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/
       
  6438 	for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
       
  6439 	{
       
  6440 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex])
       
  6441 		  return -1;
       
  6442 
       
  6443 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr)
       
  6444 		  return -1;
       
  6445 
       
  6446 		if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample)
       
  6447  		  *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample;
       
  6448 	}
       
  6449   }
       
  6450   else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))
       
  6451   {
       
  6452 /* Now, framespersample returns the maximum frames_per_sample listed in the QCELP-13K sample entries*/
       
  6453 	for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
       
  6454 	{
       
  6455 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex])
       
  6456 		  return -1;
       
  6457 
       
  6458 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp)
       
  6459 		  return -1;
       
  6460 
       
  6461 		if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample)
       
  6462 		  *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample;
       
  6463 	}
       
  6464   }
       
  6465   else
       
  6466   {
       
  6467   }
       
  6468 
       
  6469   return 0;
       
  6470 }
       
  6471 
       
  6472 
       
  6473 /*
       
  6474  * Function:
       
  6475  *
       
  6476  *   mp4_i32 determineAudioTimeScale(MP4HandleImp handle,
       
  6477  *                                   mp4_u32 *timescale)
       
  6478  *
       
  6479  * Description:
       
  6480  *
       
  6481  *   This function determines the timescale of audio track.
       
  6482  *
       
  6483  * Parameters:
       
  6484  *
       
  6485  *   handle     MP4 library handle
       
  6486  *   timescale  Timescale of audio track is returned here
       
  6487  *
       
  6488  * Return value:
       
  6489  *
       
  6490  *   0          Success
       
  6491  *   Negative   Error
       
  6492  *
       
  6493  */
       
  6494 mp4_i32 determineAudioTimeScale(MP4HandleImp handle, mp4_u32 *timescale)
       
  6495 {
       
  6496   if (timescale == NULL)
       
  6497     return 0;
       
  6498 
       
  6499   if (!handle)
       
  6500     return -1;
       
  6501   if (!handle->moov)
       
  6502     return -1;
       
  6503   if (!handle->moov->trakAudio)
       
  6504     return -1;
       
  6505   if (!handle->moov->trakAudio->mdia)
       
  6506     return -1;
       
  6507   if (!handle->moov->trakAudio->mdia->mdhd)
       
  6508     return -1;
       
  6509 
       
  6510 
       
  6511   if (handle->moov->trakAudio->mdia->mdhd->timeScale == 0)
       
  6512     return -1;
       
  6513 
       
  6514   *timescale = handle->moov->trakAudio->mdia->mdhd->timeScale;
       
  6515 
       
  6516   return 0;
       
  6517 }
       
  6518 
       
  6519 
       
  6520 /*
       
  6521  * Function:
       
  6522  *
       
  6523  *   mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle,
       
  6524  *                                        mp4_u32 *averagebitrate)
       
  6525  *
       
  6526  * Description:
       
  6527  *
       
  6528  *   This function determines the average bitrate of the audio in bits per
       
  6529  *   second.
       
  6530  *
       
  6531  *   The average is calculated so that the audio data length is divided by
       
  6532  *   the length of the  audio track.
       
  6533  *
       
  6534  * Parameters:
       
  6535  *
       
  6536  *   handle                MP4 library handle
       
  6537  *   averagebitrate        Result is returned here
       
  6538  *
       
  6539  * Return value:
       
  6540  *
       
  6541  *   0           Success
       
  6542  *   Negative    Error
       
  6543  *
       
  6544  */
       
  6545 mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle, mp4_u32 *averagebitrate)
       
  6546 	{
       
  6547 	mp4_u32 audiosize = 0;
       
  6548 
       
  6549   	if (!handle->moov)
       
  6550   		{
       
  6551   		return -1;	
       
  6552   		}
       
  6553     	
       
  6554   	if (handle->moov->trakAudio)
       
  6555   		{
       
  6556 		if (!handle->moov->trakAudio->mdia)
       
  6557 			{
       
  6558 			return -1;		
       
  6559 			}
       
  6560 					
       
  6561 		if (!handle->moov->trakAudio->mdia->minf)
       
  6562 			{
       
  6563 			return -1;	
       
  6564 			}
       
  6565 		
       
  6566 		if (!handle->moov->trakAudio->mdia->minf->stbl)
       
  6567 			{
       
  6568 			return -1;				
       
  6569 			}
       
  6570 
       
  6571 		if (!handle->moov->trakAudio->mdia->minf->stbl->stsz)
       
  6572 			{
       
  6573 			return -1;				
       
  6574 			}
       
  6575 
       
  6576 		if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0)
       
  6577 			{
       
  6578 			audiosize += (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount *
       
  6579 	                   	 handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize);			
       
  6580 			}
       
  6581 	    else
       
  6582 	    	{
       
  6583 	      	mp4_u32 i;
       
  6584 	      	for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++)
       
  6585 	      		{
       
  6586 	        	audiosize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i];      			
       
  6587 	      		}
       
  6588 	    	}
       
  6589 	  	}
       
  6590 	else
       
  6591 		{
       
  6592 		return -1;  		
       
  6593 		}
       
  6594 
       
  6595   	if (!handle->moov->trakAudio->mdia->mdhd)
       
  6596   		{
       
  6597     	return -1;  			
       
  6598   		}
       
  6599   	
       
  6600   	if (!handle->moov->trakAudio->mdia->mdhd->timeScale)
       
  6601   		{
       
  6602 		return -1;  			
       
  6603   		}
       
  6604 
       
  6605   	if (handle->moov->trakAudio->mdia->mdhd->duration == 0)
       
  6606   		{
       
  6607   		*averagebitrate = 0;
       
  6608   		}
       
  6609 	else
       
  6610 		{
       
  6611 		*averagebitrate = (mp4_u32)((mp4_double)8 *
       
  6612 		                  (mp4_double)audiosize /
       
  6613 		                  ((mp4_double)handle->moov->trakAudio->mdia->mdhd->duration /
       
  6614 		                  (mp4_double)handle->moov->trakAudio->mdia->mdhd->timeScale));
       
  6615 		}  	
       
  6616 
       
  6617   	return 0;
       
  6618 	}
       
  6619 
       
  6620 
       
  6621 /*
       
  6622  * Function:
       
  6623  *
       
  6624  *   mp4_i32 determineStreamSize(MP4HandleImp handle,
       
  6625  *                              mp4_u32 *streamsize)
       
  6626  *
       
  6627  * Description:
       
  6628  *
       
  6629  *   This function determines the size of media data in MP4 file/stream.
       
  6630  *
       
  6631  * Parameters:
       
  6632  *
       
  6633  *   handle      MP4 library handle
       
  6634  *   streamsize  Size of data
       
  6635  *
       
  6636  * Return value:
       
  6637  *
       
  6638  *   0           Success
       
  6639  *   Negative    Error
       
  6640  *
       
  6641  */
       
  6642 mp4_i32 determineStreamSize(MP4HandleImp handle, mp4_u32 *streamsize)
       
  6643 {
       
  6644   *streamsize = 0;
       
  6645 
       
  6646   if (!handle->moov)
       
  6647     return -1;
       
  6648 
       
  6649   if ((!handle->moov->trakAudio) && (!handle->moov->trakVideo))
       
  6650     return -1;
       
  6651 
       
  6652   if (handle->moov->trakAudio)
       
  6653   {
       
  6654     if (!handle->moov->trakAudio->mdia)
       
  6655       return -1;
       
  6656 
       
  6657     if (!handle->moov->trakAudio->mdia->minf)
       
  6658       return -1;
       
  6659 
       
  6660     if (!handle->moov->trakAudio->mdia->minf->stbl)
       
  6661       return -1;
       
  6662 
       
  6663     if (!handle->moov->trakAudio->mdia->minf->stbl->stsz)
       
  6664       return -1;
       
  6665 
       
  6666     if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0)
       
  6667       *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount *
       
  6668                      handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize;
       
  6669     else
       
  6670     {
       
  6671       mp4_u32 i;
       
  6672 
       
  6673       for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++)
       
  6674         *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i];
       
  6675     }
       
  6676   }
       
  6677 
       
  6678   if (handle->moov->trakVideo)
       
  6679   {
       
  6680     if (!handle->moov->trakVideo->mdia)
       
  6681       return -1;
       
  6682 
       
  6683     if (!handle->moov->trakVideo->mdia->minf)
       
  6684       return -1;
       
  6685 
       
  6686     if (!handle->moov->trakVideo->mdia->minf->stbl)
       
  6687       return -1;
       
  6688 
       
  6689     if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
       
  6690       return -1;
       
  6691 
       
  6692     if (handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize != 0)
       
  6693       *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount *
       
  6694                      handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize;
       
  6695     else
       
  6696     {
       
  6697       mp4_u32 i;
       
  6698 
       
  6699       for (i = 0; i < handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount; i++)
       
  6700         *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[i];
       
  6701     }
       
  6702   }
       
  6703 
       
  6704   return 0;
       
  6705 }
       
  6706 
       
  6707 
       
  6708 /*
       
  6709  * Function:
       
  6710  *
       
  6711  *   mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle,
       
  6712  *                                         mp4_u32 *streamaveragebitrate,
       
  6713  *                                         mp4_u32 streamsize)
       
  6714  *
       
  6715  * Description:
       
  6716  *
       
  6717  *   This function determines the average bitrate of the stream in bits per
       
  6718  *   second.
       
  6719  *
       
  6720  *   The average is calculated so that the media data length is divided by
       
  6721  *   the length of the presentation.
       
  6722  *
       
  6723  * Parameters:
       
  6724  *
       
  6725  *   handle                MP4 library handle
       
  6726  *   streamaveragebitrate  Result is returned here
       
  6727  *   streamsize            Size of media data in bytes
       
  6728  *
       
  6729  * Return value:
       
  6730  *
       
  6731  *   0           Success
       
  6732  *   Negative    Error
       
  6733  *
       
  6734  */
       
  6735 mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle, mp4_u32 *streamaveragebitrate, mp4_u32 streamsize)
       
  6736 {
       
  6737   if (!handle->moov)
       
  6738     return -1;
       
  6739 
       
  6740   if (!handle->moov->mvhd)
       
  6741     return -1;
       
  6742 
       
  6743   if (!handle->moov->mvhd->timeScale)
       
  6744     return -1;
       
  6745 
       
  6746   if (handle->moov->mvhd->atomhdr->version == 1) /* 64 bit */
       
  6747       {
       
  6748       if (!handle->moov->mvhd->duration64)
       
  6749         return -1;
       
  6750      
       
  6751       *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize /
       
  6752                                         ((mp4_double)handle->moov->mvhd->duration64 / handle->moov->mvhd->timeScale));      
       
  6753       }
       
  6754   else /* 32 bit */
       
  6755       {
       
  6756       if (!handle->moov->mvhd->duration)
       
  6757         return -1;
       
  6758 
       
  6759       *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize /
       
  6760                                         ((mp4_double)handle->moov->mvhd->duration / handle->moov->mvhd->timeScale));      
       
  6761       }
       
  6762 
       
  6763   return 0;
       
  6764 }
       
  6765 
       
  6766 
       
  6767 /*
       
  6768  * Function:
       
  6769  *
       
  6770  *   mp4_i32 advanceVideoFrame(MP4HandleImp handle,
       
  6771  *                             trackAtom *trak)
       
  6772  *
       
  6773  * Description:
       
  6774  *
       
  6775  *   This function Advances one video frame and finds the frame offset
       
  6776  *   and size.
       
  6777  *
       
  6778  * Parameters:
       
  6779  *
       
  6780  *   handle    MP4 library handle
       
  6781  *   trak      TRAK atom pointer
       
  6782  *
       
  6783  * Return value:
       
  6784  *
       
  6785  *   0         Success
       
  6786  *   Negative  Error
       
  6787  *
       
  6788  */
       
  6789 mp4_i32 advanceVideoFrame(MP4HandleImp handle, trackAtom *trak)
       
  6790 {
       
  6791   if (!trak->mdia)
       
  6792     return -1;
       
  6793   if (!trak->mdia->minf)
       
  6794     return -1;
       
  6795   if (!trak->mdia->minf->stbl)
       
  6796     return -1;
       
  6797   if (!trak->mdia->minf->stbl->stsz)
       
  6798     return -1;
       
  6799 
       
  6800   /* Are there frames (samples) left? */
       
  6801 
       
  6802   if (trak->mdia->minf->stbl->stsz->sampleCount > handle->videoSampleNum)
       
  6803     handle->videoSampleNum++;
       
  6804   else
       
  6805     return -2;
       
  6806 
       
  6807   /* Find the size of the frame (sample) */
       
  6808 
       
  6809   if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
       
  6810     return -1;
       
  6811 
       
  6812   /* Find the offset of the frame (sample) */
       
  6813 
       
  6814   if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0)
       
  6815     return -1;
       
  6816 
       
  6817 
       
  6818   return 0;
       
  6819 }
       
  6820 
       
  6821 
       
  6822 /*
       
  6823  * Function:
       
  6824  *
       
  6825  *   mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle,
       
  6826  *                                    sampleTableAtom *stbl)
       
  6827  *
       
  6828  * Description:
       
  6829  *
       
  6830  *   This function finds the offset of the current video sample.
       
  6831  *   The result is stored in handle->videoFrameOffset.
       
  6832  *
       
  6833  * Parameters:
       
  6834  *
       
  6835  *   handle    MP4 library handle
       
  6836  *   stbl      STBL atom pointer
       
  6837  *
       
  6838  * Return value:
       
  6839  *
       
  6840  *   0         Success
       
  6841  *   Negative  Error
       
  6842  *
       
  6843  */
       
  6844 mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl)
       
  6845 	{
       
  6846 	mp4_u32  chunk;            /* Current chunk number */
       
  6847 	mp4_u32  sample;           /* Number of samples before this run of chunks */
       
  6848 	mp4_u32  entry;            /* Current entry in sample to chunk */
       
  6849 	mp4_u32  chunksInThisRun;  /* Number of chunks in this run */
       
  6850 	mp4_u32  sampleNrInChunk = 0;	/* Sample number in the chunk */
       
  6851 
       
  6852 	if (!stbl->stsc || stbl->stsc->entryCount == 0)
       
  6853 		{
       
  6854 		return -1;
       
  6855 		}
       
  6856 	
       
  6857 	if (!stbl->stco || stbl->stco->entryCount == 0)
       
  6858 		{
       
  6859 		return -1;
       
  6860 		}
       
  6861 
       
  6862 	chunk = 0;
       
  6863 	sample = 0;
       
  6864 	entry = 0;
       
  6865 
       
  6866   for (;;)
       
  6867 		{
       
  6868 		/* Find how many chunks there are in this run */
       
  6869 		
       
  6870 		if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */
       
  6871 			{
       
  6872 			chunksInThisRun = stbl->stsc->firstChunk[entry + 1] - stbl->stsc->firstChunk[entry];
       
  6873 			}
       
  6874 		else
       
  6875 			{
       
  6876 			chunksInThisRun = stbl->stco->entryCount - chunk + 1;
       
  6877 			}
       
  6878 
       
  6879 		if (handle->videoSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample)
       
  6880 			{
       
  6881 			chunk += (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry];
       
  6882 			sampleNrInChunk = (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry];
       
  6883 	  
       
  6884 			/* The following functions are needed for multiple sample entry support */
       
  6885 			handle->videoSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry];
       
  6886 
       
  6887 			break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/
       
  6888 			}
       
  6889 		else
       
  6890 			{
       
  6891 			chunk += chunksInThisRun;
       
  6892 			sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry];
       
  6893 			}
       
  6894 
       
  6895 	    entry++;
       
  6896 		}
       
  6897 
       
  6898 	if (chunk > stbl->stco->entryCount)
       
  6899 		{
       
  6900 		return -1;
       
  6901 		}
       
  6902 
       
  6903 	handle->videoFrameOffset = getChunkOffset(stbl, chunk - 1);
       
  6904 
       
  6905 	if (sampleNrInChunk)
       
  6906 		{
       
  6907 		if (stbl->stsz->sampleSize)
       
  6908 			{
       
  6909 			handle->videoFrameOffset += stbl->stsz->sampleSize * sampleNrInChunk;
       
  6910 			}
       
  6911 		else
       
  6912 			{
       
  6913 			if (stbl->stsz->sampleCount == 0)
       
  6914 				{
       
  6915 				return -1;
       
  6916 				}
       
  6917 			while (sampleNrInChunk)
       
  6918 				{
       
  6919 				handle->videoFrameOffset += stbl->stsz->entrySize[handle->videoSampleNum - sampleNrInChunk - 1];
       
  6920 				sampleNrInChunk--;
       
  6921 				}
       
  6922 			}
       
  6923 		}
       
  6924 		
       
  6925 		
       
  6926 	//PRINT((_L("videoFrameOffset %Lu"), handle->videoFrameOffset));
       
  6927 	return 0;
       
  6928 	}
       
  6929 
       
  6930 
       
  6931 /*
       
  6932  * Function:
       
  6933  *
       
  6934  *   mp4_i32 resolveVideoSampleSize(MP4HandleImp handle,
       
  6935  *                                  sampleSizeAtom *stsz)
       
  6936  *
       
  6937  * Description:
       
  6938  *
       
  6939  *   This function finds the size of the current video sample.
       
  6940  *   The result is stored in handle->videoFrameSize.
       
  6941  *
       
  6942  * Parameters:
       
  6943  *
       
  6944  *   handle    MP4 library handle
       
  6945  *   stsz      STSZ atom pointer
       
  6946  *
       
  6947  * Return value:
       
  6948  *
       
  6949  *   0         Success
       
  6950  *   Negative  Error
       
  6951  *
       
  6952  */
       
  6953 mp4_i32 resolveVideoSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz)
       
  6954 	{
       
  6955 	if (stsz->sampleSize)
       
  6956 		{
       
  6957 		handle->videoFrameSize = stsz->sampleSize;
       
  6958 		return 0;
       
  6959 		}
       
  6960 
       
  6961 	if (stsz->sampleCount == 0)
       
  6962 		{
       
  6963 		return -1;
       
  6964 		}
       
  6965 	handle->videoFrameSize = stsz->entrySize[handle->videoSampleNum - 1];
       
  6966 
       
  6967 	return 0;
       
  6968 	}
       
  6969 
       
  6970 
       
  6971 /*
       
  6972  * Function:
       
  6973  *
       
  6974  *   mp4_i32 fetchVideoFrame(MP4HandleImp handle,
       
  6975  *                           trackAtom *trak,
       
  6976  *                           mp4_u8 *buffer,
       
  6977  *                           mp4_u32 buffersize,
       
  6978  *                           mp4_u32 *framesize,
       
  6979  *                           mp4_u32 *timestamp,
       
  6980  *                           mp4_bool *keyframe,
       
  6981  *                           mp4_u32 *timestamp2)
       
  6982  *
       
  6983  * Description:
       
  6984  *
       
  6985  *   This function fetches one video frame from a file.
       
  6986  *
       
  6987  * Parameters:
       
  6988  *
       
  6989  *   handle       MP4 library handle
       
  6990  *   trak         TRAK atom pointer
       
  6991  *   buffer       Video frame is retuned here
       
  6992  *   buffersize   Size of buffer
       
  6993  *   framesize    Size of returned frame in bytes
       
  6994  *   timestamp    Frame time in milliseconds (from the beginning of the
       
  6995  *                presentation)
       
  6996  *   keyframe     True if intra frame, false otherwise
       
  6997  *   timestamp2   Frame time in timescale (from the beginning of the
       
  6998  *                presentation)
       
  6999  *
       
  7000  * Return value:
       
  7001  *
       
  7002  *   0            Success
       
  7003  *   Negative     Error
       
  7004  *
       
  7005  */
       
  7006 mp4_i32 fetchVideoFrame(MP4HandleImp handle,
       
  7007                         trackAtom *trak,
       
  7008                         mp4_u8 *buffer,
       
  7009                         mp4_u32 buffersize,
       
  7010                         mp4_u32 *framesize,
       
  7011                         mp4_u32 *timestamp,
       
  7012                         mp4_bool *keyframe,
       
  7013                         mp4_u32 *timestamp2)
       
  7014 {
       
  7015   mp4_i32 bytesread;
       
  7016 
       
  7017 
       
  7018   if (!trak->mdia)
       
  7019     return -1;
       
  7020 
       
  7021   if (handle->file) /* Input is in a file */
       
  7022   {
       
  7023     if (seekFileAbs(handle, handle->videoFrameOffset) != 0)
       
  7024       return -4;
       
  7025   }
       
  7026   else /* Input is a stream */
       
  7027   {
       
  7028       if (handle->videoFrameOffset + handle->videoFrameSize <= getCumulativeBufferedBytes(handle))
       
  7029       {
       
  7030           handle->absPosition = handle->videoFrameOffset;
       
  7031       }
       
  7032       else
       
  7033         return -3;
       
  7034   }
       
  7035 
       
  7036   if (handle->videoFrameSize > buffersize)
       
  7037   {
       
  7038     *framesize = handle->videoFrameSize;
       
  7039     return -2;
       
  7040   }
       
  7041 
       
  7042   bytesread = readData(handle, buffer, handle->videoFrameSize);
       
  7043   switch (bytesread)
       
  7044   {
       
  7045     case -1:
       
  7046       return -1;
       
  7047     case -2:
       
  7048       return -4;
       
  7049     case -10:
       
  7050       return -3;
       
  7051     default:
       
  7052       break;
       
  7053   }
       
  7054 
       
  7055   if (handle->file)
       
  7056     if (handle->videoFrameOffset + handle->videoFrameSize - 1 > handle->lastAccessedPosInFile)
       
  7057       handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1;
       
  7058 
       
  7059   *framesize = handle->videoFrameSize;
       
  7060 
       
  7061   if (convertVideoSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0)
       
  7062     return -1;
       
  7063 
       
  7064   if (isVideoFrameKeyFrame(handle, trak, keyframe) < 0)
       
  7065     return -1;
       
  7066 
       
  7067   return 0;
       
  7068 }
       
  7069 
       
  7070 /*
       
  7071  * Function:
       
  7072  *
       
  7073  *   mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle,
       
  7074  *                           	  trackAtom *trak,
       
  7075  *                           	  mp4_u8 *buffer,
       
  7076  *                           	  mp4_u32 buffersize,
       
  7077  *
       
  7078  * Description:
       
  7079  *
       
  7080  *   This function fetches one video frame from a file asyncronously.
       
  7081  *
       
  7082  * Parameters:
       
  7083  *
       
  7084  *   handle       MP4 library handle
       
  7085  *   trak         TRAK atom pointer
       
  7086  *   buffer       Video frame is retuned here
       
  7087  *   buffersize   Size of buffer
       
  7088  *
       
  7089  * Return value:
       
  7090  *
       
  7091  *   0            Success
       
  7092  *   Negative     Error
       
  7093  *
       
  7094  */
       
  7095 mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle,
       
  7096                         trackAtom *trak,
       
  7097                         mp4_u8 *buffer,
       
  7098                         mp4_u32 *buffersize)
       
  7099 {
       
  7100   if (trak)
       
  7101 	{
       
  7102 	if (!trak->mdia)
       
  7103 		return -1;
       
  7104 	}
       
  7105   else
       
  7106     {
       
  7107 	return -1;
       
  7108     }
       
  7109   
       
  7110   if (handle->videoFrameSize > *buffersize)
       
  7111   {
       
  7112     *buffersize = handle->videoFrameSize;
       
  7113     return -2;
       
  7114   }
       
  7115   
       
  7116   if ( handle->asyncReader == NULL )
       
  7117   	{
       
  7118 	TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile ));
       
  7119 	if ( error != KErrNone )
       
  7120 		{
       
  7121 		if (error == KErrNoMemory )
       
  7122 			{
       
  7123 			return MP4_OUT_OF_MEMORY;    		
       
  7124 			}
       
  7125 		else
       
  7126 			{
       
  7127 			return -1;
       
  7128 			}
       
  7129 		}  	
       
  7130   	}
       
  7131   
       
  7132   return handle->asyncReader->ReadVideoFrame( buffer, handle->videoFrameOffset, handle->videoFrameSize);
       
  7133 }
       
  7134 
       
  7135 /*
       
  7136  * Function:
       
  7137  *
       
  7138  *   mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle,
       
  7139  *                                trackAtom *trak,
       
  7140  *                                mp4_bool *keyframe)
       
  7141  *
       
  7142  * Description:
       
  7143  *
       
  7144  *   This function determines if the current frame is a keyframe (intra)
       
  7145  *   or not.
       
  7146  *
       
  7147  * Parameters:
       
  7148  *
       
  7149  *   handle       MP4 library handle
       
  7150  *   trak         TRAK atom pointer
       
  7151  *   keyframe     Has a value of MP4TRUE if current frame is a keyframe
       
  7152  *                (intra) or MP4FALSE otherwise
       
  7153  *
       
  7154  * Return value:
       
  7155  *
       
  7156  *   0            Success
       
  7157  *   Negative     Error
       
  7158  *
       
  7159  */
       
  7160 mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle, trackAtom *trak, mp4_bool *keyframe)
       
  7161 {
       
  7162   mp4_u32  i;
       
  7163 
       
  7164 
       
  7165   *keyframe = MP4FALSE;
       
  7166 
       
  7167   if (!trak->mdia)
       
  7168     return -1;
       
  7169 
       
  7170   if (!trak->mdia->minf)
       
  7171     return -1;
       
  7172 
       
  7173   if (!trak->mdia->minf->stbl)
       
  7174     return -1;
       
  7175 
       
  7176   if (!trak->mdia->minf->stbl->stss)
       
  7177   {
       
  7178     *keyframe = MP4TRUE;
       
  7179 
       
  7180     return 0;
       
  7181   }
       
  7182 
       
  7183   for (i = 0; i < trak->mdia->minf->stbl->stss->entryCount; i++)
       
  7184   {
       
  7185     if (trak->mdia->minf->stbl->stss->sampleNumber[i] == handle->videoSampleNum)
       
  7186     {
       
  7187       *keyframe = MP4TRUE;
       
  7188       break;
       
  7189     }
       
  7190   }
       
  7191 
       
  7192   return 0;
       
  7193 }
       
  7194 
       
  7195 
       
  7196 /*
       
  7197  * Function:
       
  7198  *
       
  7199  *   mp4_i32 convertVideoSampleToTime(MP4HandleImp handle,
       
  7200  *                                    mediaAtom *mdia,
       
  7201  *                                    mp4_u32 *timestamp,
       
  7202  *                                    mp4_u32 *timestamp2)
       
  7203  *
       
  7204  * Description:
       
  7205  *
       
  7206  *   This function converts a video sample to corresponding time.
       
  7207  *
       
  7208  * Parameters:
       
  7209  *
       
  7210  *   handle       MP4 library handle
       
  7211  *   mdia         MDIA atom pointer
       
  7212  *   timestamp    Time in milliseconds is returned here
       
  7213  *   timestamp2   Time in timescale is returned here
       
  7214  *
       
  7215  * Return value:
       
  7216  *
       
  7217  *   0            Success
       
  7218  *   Negative     Error
       
  7219  *
       
  7220  */
       
  7221 mp4_i32 convertVideoSampleToTime(MP4HandleImp handle,
       
  7222                                  mediaAtom *mdia,
       
  7223                                  mp4_u32 *timestamp,
       
  7224                                  mp4_u32 *timestamp2)
       
  7225 	{
       
  7226 	mp4_u32      tmptime;
       
  7227 	mp4_double   tmptime2;
       
  7228 	mp4_u32      sample;
       
  7229 	mp4_u32      entry;
       
  7230 
       
  7231 	if (!mdia->mdhd)
       
  7232 		{
       
  7233 		return -1;
       
  7234 		}
       
  7235 	if (!mdia->minf)
       
  7236 		{
       
  7237 		return -1;
       
  7238 		}
       
  7239 	if (!mdia->minf->stbl)
       
  7240 		{
       
  7241 		return -1;
       
  7242 		}
       
  7243 	if (!mdia->minf->stbl->stts)
       
  7244 		{
       
  7245 		return -1;
       
  7246 		}
       
  7247 	if (mdia->minf->stbl->stts->entryCount == 0)
       
  7248 		{
       
  7249 		return -1;
       
  7250 		}
       
  7251 
       
  7252 	tmptime = 0;
       
  7253 	sample = 0;
       
  7254 	entry = 0;
       
  7255 
       
  7256 	for (;;)
       
  7257 		{
       
  7258 		if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->videoSampleNum)
       
  7259 			{
       
  7260 			sample += mdia->minf->stbl->stts->sampleCount[entry];
       
  7261 			tmptime += (mdia->minf->stbl->stts->sampleCount[entry] * mdia->minf->stbl->stts->sampleDelta[entry]);
       
  7262 			entry++;
       
  7263 			if (entry == mdia->minf->stbl->stts->entryCount)
       
  7264 				{
       
  7265 				return -1;
       
  7266 				}
       
  7267 			}
       
  7268 		else
       
  7269 			{
       
  7270 			tmptime += ((handle->videoSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry]);
       
  7271 			break;
       
  7272 			}
       
  7273 		}
       
  7274 	
       
  7275   	if (mdia->mdhd->timeScale == 0)
       
  7276   		{
       
  7277   		return -1;
       
  7278   		}
       
  7279 
       
  7280   	if (timestamp2)
       
  7281   		{
       
  7282   		*timestamp2 = tmptime;
       
  7283   		}
       
  7284 
       
  7285   	tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5;
       
  7286 
       
  7287   	*timestamp = (mp4_u32)tmptime2;
       
  7288 
       
  7289   	return 0;
       
  7290 	}
       
  7291 
       
  7292 
       
  7293 /*
       
  7294  * Function:
       
  7295  *
       
  7296  *   mp4_i32 advanceAudioSample(MP4HandleImp handle,
       
  7297  *                              trackAtom *trak)
       
  7298  *
       
  7299  * Description:
       
  7300  *
       
  7301  *   This function advances one audio sample and finds the sample
       
  7302  *   offset and sample size.
       
  7303  *
       
  7304  * Parameters:
       
  7305  *
       
  7306  *   handle    MP4 library handle
       
  7307  *   trak      TRAK atom pointer
       
  7308  *
       
  7309  * Return value:
       
  7310  *
       
  7311  *   0         Success
       
  7312  *   Negative  Error
       
  7313  *
       
  7314  */
       
  7315 mp4_i32 advanceAudioSample(MP4HandleImp handle,
       
  7316                            trackAtom *trak)
       
  7317 {
       
  7318   if (!trak->mdia)
       
  7319     return -1;
       
  7320   if (!trak->mdia->minf)
       
  7321     return -1;
       
  7322   if (!trak->mdia->minf->stbl)
       
  7323     return -1;
       
  7324   if (!trak->mdia->minf->stbl->stsz)
       
  7325     return -1;
       
  7326 
       
  7327 
       
  7328   /* Are there samples left? */
       
  7329 
       
  7330   if (trak->mdia->minf->stbl->stsz->sampleCount > handle->audioSampleNum)
       
  7331     handle->audioSampleNum++;
       
  7332   else
       
  7333     return -2;
       
  7334 
       
  7335   /* Find the size of the sample */
       
  7336 
       
  7337   if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
       
  7338     return -1;
       
  7339 
       
  7340   /* Find the offset of the sample */
       
  7341 
       
  7342   if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0)
       
  7343     return -1;
       
  7344 
       
  7345 
       
  7346   return 0;
       
  7347 }
       
  7348 
       
  7349 
       
  7350 /*
       
  7351  * Function:
       
  7352  *
       
  7353  *   mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle,
       
  7354  *                                    sampleTableAtom *stbl)
       
  7355  *
       
  7356  * Description:
       
  7357  *
       
  7358  *   This function finds the offset of the current audio sample.
       
  7359  *   The result is stored in handle->audioSampleOffset.
       
  7360  *
       
  7361  * Parameters:
       
  7362  *
       
  7363  *   handle    MP4 library handle
       
  7364  *   stbl      STBL atom pointer
       
  7365  *
       
  7366  * Return value:
       
  7367  *
       
  7368  *   0         Success
       
  7369  *   Negative  Error
       
  7370  *
       
  7371  */
       
  7372 mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl)
       
  7373 {
       
  7374   mp4_u32  chunk;            /* Current chunk number */
       
  7375   mp4_u32  sample;            /* Number of samples before this run of chunks */
       
  7376   mp4_u32  entry;            /* Current entry in sample to chunk */
       
  7377   mp4_u32 chunksInThisRun;  /* Number of chunks in this run */
       
  7378   mp4_u32  sampleNrInChunk;  /* Sample number in the chunk */
       
  7379 
       
  7380 
       
  7381   if (!stbl->stsc || stbl->stsc->entryCount == 0)
       
  7382     return -1;
       
  7383   if (!stbl->stco || stbl->stco->entryCount == 0)
       
  7384     return -1;
       
  7385 
       
  7386   chunk = 0;
       
  7387   sample = 0;
       
  7388   entry = 0;
       
  7389 
       
  7390   for (;;)
       
  7391   {
       
  7392     /* Find how many chunks there are in this run */
       
  7393 
       
  7394     if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */
       
  7395     {
       
  7396       chunksInThisRun = stbl->stsc->firstChunk[entry + 1] -
       
  7397                         stbl->stsc->firstChunk[entry];
       
  7398     }
       
  7399     else
       
  7400       chunksInThisRun = stbl->stco->entryCount - chunk + 1;
       
  7401 
       
  7402 
       
  7403     if (handle->audioSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample)
       
  7404     {
       
  7405       chunk += (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry];
       
  7406       sampleNrInChunk = (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry];
       
  7407 
       
  7408 	  /* The following functions are needed for multiple sample entry support */
       
  7409 	  handle->audioSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry];
       
  7410 
       
  7411       break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/
       
  7412     }
       
  7413     else
       
  7414     {
       
  7415       chunk += chunksInThisRun;
       
  7416       sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry];
       
  7417     }
       
  7418 
       
  7419     entry++;
       
  7420   }
       
  7421 
       
  7422   if (chunk > stbl->stco->entryCount)
       
  7423     return -1;
       
  7424 
       
  7425   handle->audioSampleOffset = getChunkOffset(stbl, chunk - 1);
       
  7426 
       
  7427   	if (sampleNrInChunk)
       
  7428   		{
       
  7429   		if (stbl->stsz->sampleSize)
       
  7430   			{
       
  7431   			handle->audioSampleOffset += stbl->stsz->sampleSize * sampleNrInChunk;
       
  7432   			}
       
  7433   		else
       
  7434   			{
       
  7435   			if (stbl->stsz->sampleCount == 0)
       
  7436   				{
       
  7437   				// ensure there are entries in the entrySize array
       
  7438   				return -1;
       
  7439   				}
       
  7440     
       
  7441   			while (sampleNrInChunk)
       
  7442   				{
       
  7443   				handle->audioSampleOffset += stbl->stsz->entrySize[handle->audioSampleNum - sampleNrInChunk - 1];
       
  7444   				sampleNrInChunk--;
       
  7445   				}
       
  7446   			}
       
  7447   		}
       
  7448   		
       
  7449   //PRINT((_L("audioSampleOffset %Lu"), handle->audioSampleOffset));
       
  7450   return 0;
       
  7451 }
       
  7452 
       
  7453 
       
  7454 /*
       
  7455  * Function:
       
  7456  *
       
  7457  *   mp4_i32 resolveAudioSampleSize(MP4HandleImp handle,
       
  7458  *                                  sampleSizeAtom *stsz)
       
  7459  *
       
  7460  * Description:
       
  7461  *
       
  7462  *   This function finds the size of the current audio sample.
       
  7463  *   The result is stored in handle->audioSampleSize.
       
  7464  *
       
  7465  * Parameters:
       
  7466  *
       
  7467  *   handle    MP4 library handle
       
  7468  *   stsz      STSZ atom pointer
       
  7469  *
       
  7470  * Return value:
       
  7471  *
       
  7472  *   0         Success
       
  7473  *   Negative  Error
       
  7474  *
       
  7475  */
       
  7476 mp4_i32 resolveAudioSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz)
       
  7477 	{
       
  7478 	if (stsz->sampleSize)
       
  7479 		{
       
  7480 		handle->audioSampleSize = stsz->sampleSize;
       
  7481 		return 0;
       
  7482 		}
       
  7483 
       
  7484 	if (stsz->sampleCount == 0)
       
  7485 		{
       
  7486 		return -1;
       
  7487 		}
       
  7488 	handle->audioSampleSize = stsz->entrySize[handle->audioSampleNum - 1];
       
  7489 
       
  7490 	return 0;
       
  7491 	}
       
  7492 
       
  7493 
       
  7494 /*
       
  7495  * Function:
       
  7496  *
       
  7497  *   mp4_i32 fetchAudioSample(MP4HandleImp handle,
       
  7498  *                            trackAtom *trak,
       
  7499  *                            mp4_u8 *buffer,
       
  7500  *                            mp4_u32 buffersize,
       
  7501  *                            mp4_u32 *framesize,
       
  7502  *                            mp4_u32 *timestamp,
       
  7503  *                            mp4_u32 *returnedframes,
       
  7504  *                            mp4_u32 *timestamp2)
       
  7505  *
       
  7506  * Description:
       
  7507  *
       
  7508  *   This function fetches one audio sample from a file.
       
  7509  *
       
  7510  *   Note: returnedframes may differ from the correct value when accessing
       
  7511  *         the last audio sample.
       
  7512  *
       
  7513  * Parameters:
       
  7514  *
       
  7515  *   handle           MP4 library handle
       
  7516  *   trak             TRAK atom pointer
       
  7517  *   buffer           Audio frame is retuned here
       
  7518  *   buffersize       Size of buffer
       
  7519  *   framesize        Size of returned frame in bytes
       
  7520  *   timestamp        Frame time in milliseconds (from the beginning of the
       
  7521  *                    presentation)
       
  7522  *   returnedframes   Number of frames returned, of 0 if not known
       
  7523  *   timestamp2       Frame time in timescale (from the beginning of the
       
  7524  *                    presentation)
       
  7525  *
       
  7526  * Return value:
       
  7527  *
       
  7528  *   0                Success
       
  7529  *   Negative         Error
       
  7530  *
       
  7531  */
       
  7532 mp4_i32 fetchAudioSample(MP4HandleImp handle,
       
  7533                          trackAtom *trak,
       
  7534                          mp4_u8 *buffer,
       
  7535                          mp4_u32 buffersize,
       
  7536                          mp4_u32 *framesize,
       
  7537                          mp4_u32 *timestamp,
       
  7538                          mp4_u32 *returnedframes,
       
  7539                          mp4_u32 *timestamp2)
       
  7540 {
       
  7541   mp4_i32 bytesread;
       
  7542   mp4_i32 frameLength;
       
  7543   mp4_u32 numOfFrames;
       
  7544   mp4_u8 *framepointer;
       
  7545   mp4_u32 rawAmrFrameLength[16] = {13,14,16,18,20,21,27,32,6,0,0,0,0,0,0,1};
       
  7546 
       
  7547   if (!trak->mdia)
       
  7548     return -1;
       
  7549 
       
  7550   if (handle->file) /* Input is in a file */
       
  7551   {
       
  7552     if (seekFileAbs(handle, handle->audioSampleOffset) != 0)
       
  7553       return -4;
       
  7554   }
       
  7555   else /* Input is a stream */
       
  7556   {
       
  7557       if (handle->audioSampleOffset + handle->audioSampleSize <= getCumulativeBufferedBytes(handle))
       
  7558       {
       
  7559           handle->absPosition = handle->audioSampleOffset;
       
  7560       }
       
  7561       else
       
  7562         return -3;
       
  7563   }
       
  7564 
       
  7565   if (handle->audioSampleSize > buffersize)
       
  7566   {
       
  7567     *framesize = handle->audioSampleSize;
       
  7568     return -2;
       
  7569   }
       
  7570 
       
  7571   bytesread = readData(handle, buffer, handle->audioSampleSize);
       
  7572   switch (bytesread)
       
  7573   {
       
  7574     case -1:
       
  7575       return -1;
       
  7576     case -2:
       
  7577       return -4;
       
  7578     case -10:
       
  7579       return -3;
       
  7580     default:
       
  7581       break;
       
  7582   }
       
  7583 
       
  7584   if (handle->file)
       
  7585     if (handle->audioSampleOffset + handle->audioSampleSize - 1 > handle->lastAccessedPosInFile)
       
  7586       handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1;
       
  7587 
       
  7588   *framesize = handle->audioSampleSize;
       
  7589   if (convertAudioSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0)
       
  7590     return -1;
       
  7591 
       
  7592   *returnedframes = 0;
       
  7593 
       
  7594   /* AMR */
       
  7595   if (trak->mdia->minf)
       
  7596     if (trak->mdia->minf->stbl)
       
  7597       if (trak->mdia->minf->stbl->stsd)
       
  7598         if (handle->type & MP4_TYPE_AMR_NB)
       
  7599         {
       
  7600             framepointer = buffer;
       
  7601             numOfFrames = 0;
       
  7602             while ( bytesread > 0 )
       
  7603             {
       
  7604                 frameLength = rawAmrFrameLength[(TInt)(((*framepointer) & 0x78) >> 3)];
       
  7605                 if ( frameLength == 0)
       
  7606                 {
       
  7607                     return -4;
       
  7608                 }
       
  7609                 bytesread -= frameLength;
       
  7610                 framepointer += frameLength;
       
  7611                 numOfFrames++;
       
  7612             }
       
  7613             *returnedframes = numOfFrames;
       
  7614 
       
  7615 		  /* Return the number of sample entries listed for this particular sample entry index 
       
  7616           if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1])
       
  7617             if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr)
       
  7618               *returnedframes = trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr->framesPerSample;*/
       
  7619         }
       
  7620         else if (handle->type & MP4_TYPE_AMR_WB)
       
  7621         {
       
  7622 		  /* Return the number of sample entries listed for this particular sample entry index */
       
  7623           if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1])
       
  7624             if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr)
       
  7625               *returnedframes = trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr->framesPerSample;
       
  7626         }
       
  7627         else
       
  7628         {
       
  7629         }
       
  7630 
       
  7631   /* MPEG-4 audio */
       
  7632   if (trak->mdia->minf)
       
  7633     if (trak->mdia->minf->stbl)
       
  7634       if (trak->mdia->minf->stbl->stsd)
       
  7635         if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1])
       
  7636           *returnedframes = 1;
       
  7637 
       
  7638   /* QCELP 13K as QCELPSampleEntry*/
       
  7639   if (trak->mdia->minf)
       
  7640     if (trak->mdia->minf->stbl)
       
  7641       if (trak->mdia->minf->stbl->stsd)
       
  7642         if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))
       
  7643         {
       
  7644 		  /* Return the number of sample entries listed for this particular sample entry index */
       
  7645           if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1])
       
  7646             if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp)
       
  7647               *returnedframes = trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp->framesPerSample;
       
  7648         }
       
  7649 
       
  7650   /* QCELP 13K as MPEG-4 audio */
       
  7651   if (trak->mdia->minf)
       
  7652     if (trak->mdia->minf->stbl)
       
  7653       if (trak->mdia->minf->stbl->stsd)
       
  7654         if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1])
       
  7655           *returnedframes = 1;
       
  7656 
       
  7657   return 0;
       
  7658 }
       
  7659 
       
  7660 /*
       
  7661  * Function:
       
  7662  *
       
  7663  *   mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle,
       
  7664  *                            trackAtom *trak,
       
  7665  *                            mp4_u8 *buffer,
       
  7666  *                            mp4_u32 buffersize,
       
  7667  *
       
  7668  * Description:
       
  7669  *
       
  7670  *   This function fetches one audio sample from a file asyncronously.
       
  7671  *
       
  7672  * Parameters:
       
  7673  *
       
  7674  *   handle           MP4 library handle
       
  7675  *   trak             TRAK atom pointer
       
  7676  *   buffer           Audio frame is retuned here
       
  7677  *   buffersize       Size of buffer
       
  7678  *
       
  7679  * Return value:
       
  7680  *
       
  7681  *   0                Success
       
  7682  *   Negative         Error
       
  7683  *
       
  7684  */
       
  7685 mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle,
       
  7686                          	  trackAtom *trak,
       
  7687                          	  mp4_u8 *buffer,
       
  7688                          	  mp4_u32 *buffersize)
       
  7689 {
       
  7690   if (trak)
       
  7691 	{
       
  7692 	if (!trak->mdia)
       
  7693 		return -1;
       
  7694 	}
       
  7695   else
       
  7696     {
       
  7697 	return -1;
       
  7698     }
       
  7699   
       
  7700   if (handle->audioSampleSize > *buffersize)
       
  7701 		{
       
  7702 		*buffersize = handle->audioSampleSize;
       
  7703 		return -2;
       
  7704 		}
       
  7705   
       
  7706   if (!handle->file) // Other input than file is not supported
       
  7707 	  {
       
  7708 	  return -1;
       
  7709 	  }
       
  7710   
       
  7711   if ( handle->asyncReader == NULL )
       
  7712   	{
       
  7713 	TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile ));
       
  7714 	if ( error != KErrNone )
       
  7715 		{
       
  7716 		if (error == KErrNoMemory )
       
  7717 			{
       
  7718 			return MP4_OUT_OF_MEMORY;    		
       
  7719 			}
       
  7720 		else
       
  7721 			{
       
  7722 			return -1;
       
  7723 			}
       
  7724 		}  	
       
  7725   	}
       
  7726     
       
  7727   return handle->asyncReader->ReadAudioFrames( buffer, handle->audioSampleOffset, handle->audioSampleSize);
       
  7728 }
       
  7729 
       
  7730 /*
       
  7731  * Function:
       
  7732  *
       
  7733  *   mp4_i32 convertAudioSampleToTime(MP4HandleImp handle,
       
  7734  *                                    mediaAtom *mdia,
       
  7735  *                                    mp4_u32 *timestamp,
       
  7736  *                                    mp4_u32 *timestamp2)
       
  7737  *
       
  7738  * Description:
       
  7739  *
       
  7740  *   This function converts an audio sample to corresponding time.
       
  7741  *
       
  7742  * Parameters:
       
  7743  *
       
  7744  *   handle       MP4 library handle
       
  7745  *   mdia         MDIA atom pointer
       
  7746  *   timestamp    Time in milliseconds is returned here
       
  7747  *   timestamp2   Time in timescale is returned here
       
  7748  *
       
  7749  * Return value:
       
  7750  *
       
  7751  *   0            Success
       
  7752  *   Negative     Error
       
  7753  *
       
  7754  */
       
  7755 mp4_i32 convertAudioSampleToTime(MP4HandleImp handle,
       
  7756                                  mediaAtom *mdia,
       
  7757                                  mp4_u32 *timestamp,
       
  7758                                  mp4_u32 *timestamp2)
       
  7759 	{
       
  7760 	mp4_u32      tmptime;
       
  7761 	mp4_double  tmptime2;
       
  7762 	mp4_u32      sample;
       
  7763 	mp4_u32      entry;
       
  7764 
       
  7765   	if (!mdia->mdhd)
       
  7766   		{
       
  7767   		return -1;
       
  7768   		}
       
  7769   	if (!mdia->minf)
       
  7770   		{
       
  7771   		return -1;
       
  7772   		}
       
  7773   	if (!mdia->minf->stbl)
       
  7774   		{
       
  7775   		return -1;
       
  7776   		}
       
  7777   	if (!mdia->minf->stbl->stts)
       
  7778   		{
       
  7779   		return -1;
       
  7780   		}
       
  7781   	if (mdia->minf->stbl->stts->entryCount == 0)
       
  7782   		{
       
  7783   		return -1;
       
  7784   		}
       
  7785 
       
  7786   	tmptime = 0;
       
  7787   	sample = 0;
       
  7788   	entry = 0;
       
  7789 
       
  7790   	for (;;)
       
  7791   		{
       
  7792   		if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->audioSampleNum)
       
  7793   			{
       
  7794   			sample += mdia->minf->stbl->stts->sampleCount[entry];
       
  7795   			tmptime += mdia->minf->stbl->stts->sampleCount[entry] *
       
  7796                  	mdia->minf->stbl->stts->sampleDelta[entry];
       
  7797   			entry++;
       
  7798   			
       
  7799   			if (entry == mdia->minf->stbl->stts->entryCount)
       
  7800   				return -1;
       
  7801   			}
       
  7802   		else
       
  7803   			{
       
  7804   			tmptime += (handle->audioSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry];
       
  7805   			break;
       
  7806   			}
       
  7807   		}
       
  7808 
       
  7809   	if (mdia->mdhd->timeScale == 0)
       
  7810   		{
       
  7811   		return -1;
       
  7812   		}
       
  7813 
       
  7814   	if (timestamp2)
       
  7815   		{
       
  7816   		*timestamp2 = tmptime;
       
  7817   		}
       
  7818 
       
  7819   	tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5;
       
  7820 
       
  7821   	*timestamp = (mp4_u32)tmptime2;
       
  7822 
       
  7823   	return 0;
       
  7824 	}
       
  7825 
       
  7826 
       
  7827 /*
       
  7828  * Function:
       
  7829  *
       
  7830  *   mp4_i32 convertTimeToSample(MP4HandleImp handle,
       
  7831  *                               trackAtom *trak,
       
  7832  *                               mp4_u32 position,
       
  7833  *                               mp4_u32 *sample)
       
  7834  *
       
  7835  * Description:
       
  7836  *
       
  7837  *   This function converts time to corresponding sample number.
       
  7838  *
       
  7839  * Parameters:
       
  7840  *
       
  7841  *   handle       MP4 library handle
       
  7842  *   trak         trackAtom pointer
       
  7843  *   position     Time in milliseconds
       
  7844  *   sample       Sample number is returned here
       
  7845  *
       
  7846  * Return value:
       
  7847  *
       
  7848  *   0            Success
       
  7849  *   Negative     Error
       
  7850  *
       
  7851  */
       
  7852 mp4_i32 convertTimeToSample(MP4HandleImp handle,
       
  7853                             trackAtom *trak,
       
  7854                             mp4_u32 position,
       
  7855                             mp4_u32 *sample)
       
  7856 {
       
  7857   mp4_u32 pos;      /* Target position in media timescale */
       
  7858   mp4_u32 tmppos;   /* Temporary position counter */
       
  7859   mp4_u32 i;
       
  7860 
       
  7861 
       
  7862   if (!handle)
       
  7863     return -1;
       
  7864   if (!trak)
       
  7865     return -1;
       
  7866   if (!trak->mdia)
       
  7867     return -1;
       
  7868   if (!trak->mdia->mdhd)
       
  7869     return -1;
       
  7870   if (!trak->mdia->minf)
       
  7871     return -1;
       
  7872   if (!trak->mdia->minf->stbl)
       
  7873     return -1;
       
  7874   if (!trak->mdia->minf->stbl->stts)
       
  7875     return -1;
       
  7876   if (trak->mdia->minf->stbl->stts->entryCount == 0)
       
  7877     return -1;
       
  7878 
       
  7879   *sample = 1;
       
  7880   tmppos = 0;
       
  7881 
       
  7882   pos = (mp4_u32)((mp4_double)position / (mp4_double)1000 * (mp4_double)trak->mdia->mdhd->timeScale + (mp4_double)0.5);
       
  7883 
       
  7884   for (i = 0; i < trak->mdia->minf->stbl->stts->entryCount; i++)
       
  7885   {
       
  7886     if (pos >= (tmppos + trak->mdia->minf->stbl->stts->sampleCount[i] *
       
  7887                          trak->mdia->minf->stbl->stts->sampleDelta[i]))
       
  7888     {
       
  7889       *sample += trak->mdia->minf->stbl->stts->sampleCount[i];
       
  7890       tmppos += (trak->mdia->minf->stbl->stts->sampleCount[i] *
       
  7891                  trak->mdia->minf->stbl->stts->sampleDelta[i]);
       
  7892 
       
  7893       if (i == trak->mdia->minf->stbl->stts->entryCount - 1) /* Last entry */
       
  7894         *sample = *sample - 1;
       
  7895     }
       
  7896     else
       
  7897     {
       
  7898       if (trak->mdia->minf->stbl->stts->sampleDelta[i] == 0)
       
  7899         return -1;
       
  7900 
       
  7901       *sample += ((pos - tmppos) / trak->mdia->minf->stbl->stts->sampleDelta[i]);
       
  7902 
       
  7903       break;
       
  7904     }
       
  7905   }
       
  7906 
       
  7907   return 0;
       
  7908 }
       
  7909 
       
  7910 
       
  7911 /*
       
  7912  * Function:
       
  7913  *
       
  7914  *   mp4_i32 goToVideoSample(MP4HandleImp handle,
       
  7915  *                           trackAtom *trak,
       
  7916  *                           mp4_u32 sample)
       
  7917  *
       
  7918  * Description:
       
  7919  *
       
  7920  *   This function moves to video sample indicated by sample and finds the
       
  7921  *   sample offset and sample size.
       
  7922  *
       
  7923  * Parameters:
       
  7924  *
       
  7925  *   handle    MP4 library handle
       
  7926  *   trak      TRAK atom pointer
       
  7927  *   sample    Sample to go to
       
  7928  *
       
  7929  * Return value:
       
  7930  *
       
  7931  *   0         Success
       
  7932  *   Negative  Error
       
  7933  *
       
  7934  */
       
  7935 mp4_i32 goToVideoSample(MP4HandleImp handle,
       
  7936                         trackAtom *trak,
       
  7937                         mp4_u32 sample)
       
  7938 {
       
  7939   if (!trak->mdia)
       
  7940     return -1;
       
  7941   if (!trak->mdia->minf)
       
  7942     return -1;
       
  7943   if (!trak->mdia->minf->stbl)
       
  7944     return -1;
       
  7945   if (!trak->mdia->minf->stbl->stsz)
       
  7946     return -1;
       
  7947 
       
  7948 
       
  7949   /* Is the sample valid? */
       
  7950 
       
  7951   if (sample <= trak->mdia->minf->stbl->stsz->sampleCount)
       
  7952     handle->videoSampleNum = sample;
       
  7953   else
       
  7954     return -1;
       
  7955 
       
  7956   /* Find the size of the sample */
       
  7957 
       
  7958   if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
       
  7959     return -1;
       
  7960 
       
  7961   /* Find the offset of the sample */
       
  7962 
       
  7963   if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0)
       
  7964     return -1;
       
  7965 
       
  7966 
       
  7967   return 0;
       
  7968 }
       
  7969 
       
  7970 
       
  7971 /*
       
  7972  * Function:
       
  7973  *
       
  7974  *   mp4_i32 goToAudioSample(MP4HandleImp handle,
       
  7975  *                           trackAtom *trak,
       
  7976  *                           mp4_u32 sample)
       
  7977  *
       
  7978  * Description:
       
  7979  *
       
  7980  *   This function moves to audio sample indicated by sample and finds the
       
  7981  *   sample offset and sample size.
       
  7982  *
       
  7983  * Parameters:
       
  7984  *
       
  7985  *   handle    MP4 library handle
       
  7986  *   trak      TRAK atom pointer
       
  7987  *   sample    Sample to go to
       
  7988  *
       
  7989  * Return value:
       
  7990  *
       
  7991  *   0         Success
       
  7992  *   Negative  Error
       
  7993  *
       
  7994  */
       
  7995 mp4_i32 goToAudioSample(MP4HandleImp handle,
       
  7996                         trackAtom *trak,
       
  7997                         mp4_u32 sample)
       
  7998 {
       
  7999   if (!trak->mdia)
       
  8000     return -1;
       
  8001   if (!trak->mdia->minf)
       
  8002     return -1;
       
  8003   if (!trak->mdia->minf->stbl)
       
  8004     return -1;
       
  8005   if (!trak->mdia->minf->stbl->stsz)
       
  8006     return -1;
       
  8007 
       
  8008 
       
  8009   /* Is the sample valid? */
       
  8010 
       
  8011   if (sample <= trak->mdia->minf->stbl->stsz->sampleCount)
       
  8012     handle->audioSampleNum = sample;
       
  8013   else
       
  8014     return -1;
       
  8015 
       
  8016   /* Find the size of the sample */
       
  8017 
       
  8018   if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
       
  8019     return -1;
       
  8020 
       
  8021   /* Find the offset of the sample */
       
  8022 
       
  8023   if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0)
       
  8024     return -1;
       
  8025 
       
  8026 
       
  8027   return 0;
       
  8028 }
       
  8029 
       
  8030 
       
  8031 /*
       
  8032  * Function:
       
  8033  *
       
  8034  *   mp4_i32 findVideoKeyFrame(MP4HandleImp handle,
       
  8035  *                             trackAtom *trak,
       
  8036  *                             mp4_u32 sample,
       
  8037  *                             mp4_u32 *newsample)
       
  8038  *
       
  8039  * Description:
       
  8040  *
       
  8041  *   This function finds the video keyframe that is identical to or precedes
       
  8042  *   the sample indicated by sample.
       
  8043  *
       
  8044  * Parameters:
       
  8045  *
       
  8046  *   handle       MP4 library handle
       
  8047  *   trak         TRAK atom pointer
       
  8048  *   sample       Sample number
       
  8049  *   newsample    Sample number of found keyframe
       
  8050  *
       
  8051  * Return value:
       
  8052  *
       
  8053  *   0            Success
       
  8054  *   Negative     Error
       
  8055  *
       
  8056  */
       
  8057 mp4_i32 findVideoKeyFrame(MP4HandleImp handle,
       
  8058                           trackAtom *trak,
       
  8059                           mp4_u32 sample,
       
  8060                           mp4_u32 *newsample)
       
  8061 {
       
  8062   mp4_i32  i;
       
  8063 
       
  8064 
       
  8065   if (!handle)
       
  8066     return -1;
       
  8067   if (!trak->mdia)
       
  8068     return -1;
       
  8069   if (!trak->mdia->minf)
       
  8070     return -1;
       
  8071   if (!trak->mdia->minf->stbl)
       
  8072     return -1;
       
  8073 
       
  8074   if (!trak->mdia->minf->stbl->stss) /* No sync sample atom => all samples are
       
  8075                                         random access points */
       
  8076   {
       
  8077     *newsample = sample;
       
  8078 
       
  8079     return 0;
       
  8080   }
       
  8081   *newsample = 0;
       
  8082 
       
  8083   for (i = trak->mdia->minf->stbl->stss->entryCount - 1; i >= 0; i--)
       
  8084   {
       
  8085     if (sample >= trak->mdia->minf->stbl->stss->sampleNumber[i])
       
  8086     {
       
  8087       *newsample = trak->mdia->minf->stbl->stss->sampleNumber[i];
       
  8088       break;
       
  8089     }
       
  8090   }
       
  8091 
       
  8092   if (*newsample == 0)
       
  8093     return -1;
       
  8094 
       
  8095   return 0;
       
  8096 }
       
  8097 
       
  8098 
       
  8099 /*
       
  8100  * Function:
       
  8101  *
       
  8102  *   mp4_i32 readAVCC(MP4HandleImp handle,
       
  8103  *                    avcConfigurationAtom *avcc)
       
  8104  *
       
  8105  * Description:
       
  8106  *
       
  8107  *   This function parses one avcc atom.
       
  8108  *
       
  8109  * Parameters:
       
  8110  *
       
  8111  *   handle             MP4 library handle
       
  8112  *   avcc               avcC pointer
       
  8113  *
       
  8114  * Return value:
       
  8115  *
       
  8116  *   Negative integer   Error
       
  8117  *   >= 0               Success. Value tells how many bytes were read.
       
  8118  *
       
  8119  */
       
  8120 mp4_i32 readAVCC(MP4HandleImp handle, avcConfigurationAtom *avcc)
       
  8121 {
       
  8122 	mp4_i32 bytesread;
       
  8123 	mp4_i32 totalbytesread = 0;
       
  8124 
       
  8125 	avcc->avcConfigSize = 0;
       
  8126 
       
  8127 	if ((avcc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  8128 		return -100;
       
  8129 
       
  8130 	bytesread = readAtomHeader(handle, avcc->atomhdr);
       
  8131 	if (bytesread < 0)
       
  8132 		return -1;
       
  8133 	totalbytesread +=bytesread;
       
  8134 
       
  8135 	if (avcc->atomhdr->type != ATOMTYPE_AVCC)
       
  8136 		return -1;
       
  8137 
       
  8138     /* read the avcDecoderConfigurationRecord */
       
  8139     if  (avcc->atomhdr->size != 1)
       
  8140     	avcc->avcConfigSize = avcc->atomhdr->size - 8;
       
  8141     else
       
  8142     	avcc->avcConfigSize = (mp4_u32)(I64INT(avcc->atomhdr->largeSize) - 16);
       
  8143 
       
  8144    	avcc->avcConfig = (mp4_u8 *)mp4malloc(avcc->avcConfigSize);
       
  8145 	if (avcc->avcConfig == 0)
       
  8146 		return -100;
       
  8147 	
       
  8148 	bytesread = readData(handle, avcc->avcConfig, avcc->avcConfigSize );
       
  8149     
       
  8150 	if (bytesread < 0)
       
  8151 		return -1;
       
  8152 	totalbytesread +=bytesread;
       
  8153 	return totalbytesread;
       
  8154 }
       
  8155 
       
  8156 
       
  8157 /*
       
  8158  * Function:
       
  8159  *
       
  8160  *   mp4_i32 readBTRT(MP4HandleImp handle,
       
  8161  *                    mpeg4BitrateAtom *btrt)
       
  8162  *
       
  8163  * Description:
       
  8164  *
       
  8165  *   This function parses one btrt atom.
       
  8166  *
       
  8167  * Parameters:
       
  8168  *
       
  8169  *   handle             MP4 library handle
       
  8170  *   btrt					btrt pointer
       
  8171  *
       
  8172  * Return value:
       
  8173  *
       
  8174  *   Negative integer   Error
       
  8175  *   >= 0               Success. Value tells how many bytes were read.
       
  8176  *
       
  8177  */
       
  8178 mp4_i32 readBTRT(MP4HandleImp handle, mpeg4BitrateAtom *btrt)
       
  8179 {
       
  8180 	mp4_i32 bytesread;
       
  8181 	mp4_i32 totalbytesread = 0;
       
  8182 
       
  8183 
       
  8184 	if ((btrt->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  8185 		return -100;
       
  8186 
       
  8187 	bytesread = readAtomHeader(handle, btrt->atomhdr);
       
  8188 	if (bytesread < 0)
       
  8189 		return -1;
       
  8190 	totalbytesread +=bytesread;
       
  8191 
       
  8192 	if (btrt->atomhdr->type != ATOMTYPE_BTRT)
       
  8193 		return -1;
       
  8194 
       
  8195     /* read the mpeg4BitrateAtom */
       
  8196    bytesread = readData(handle, handle->buf, 4);
       
  8197    if (bytesread < 0)
       
  8198 	   return -1;
       
  8199    btrt->bufferSizeDB = u32endian(*((mp4_u32 *)handle->buf));
       
  8200    totalbytesread +=bytesread;
       
  8201 
       
  8202    bytesread = readData(handle, handle->buf, 4);
       
  8203    if (bytesread < 0)
       
  8204 	   return -1;
       
  8205    btrt->maxBitRate = u32endian(*((mp4_u32 *)handle->buf));
       
  8206    totalbytesread +=bytesread;
       
  8207 
       
  8208    bytesread = readData(handle, handle->buf, 4);
       
  8209    if (bytesread < 0)
       
  8210 	   return -1;
       
  8211    btrt->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
       
  8212    totalbytesread +=bytesread;
       
  8213 
       
  8214 	return totalbytesread;
       
  8215 }
       
  8216 
       
  8217 /*
       
  8218  * Function:
       
  8219  *
       
  8220  *   mp4_i32 readM4DS(MP4HandleImp handle,
       
  8221  *                    mpeg4ExtensionDescriptorsAtom *m4ds)
       
  8222  *
       
  8223  * Description:
       
  8224  *
       
  8225  *   This function parses one m4ds atom.
       
  8226  *
       
  8227  * Parameters:
       
  8228  *
       
  8229  *   handle             MP4 library handle
       
  8230  *   m4ds               m4ds pointer
       
  8231  *
       
  8232  * Return value:
       
  8233  *
       
  8234  *   Negative integer   Error
       
  8235  *   >= 0               Success. Value tells how many bytes were read.
       
  8236  *
       
  8237  */
       
  8238 mp4_i32 readM4DS(MP4HandleImp handle, mpeg4ExtensionDescriptorsAtom *m4ds)
       
  8239 {
       
  8240 	mp4_i32 bytesread;
       
  8241 	mp4_i32 totalbytesread = 0;
       
  8242 	mp4_u32 i;
       
  8243 
       
  8244 	m4ds->descrSize = 0;
       
  8245 
       
  8246 	if ((m4ds->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  8247 		return -100;
       
  8248 
       
  8249 	bytesread = readAtomHeader(handle, m4ds->atomhdr);
       
  8250 	if (bytesread < 0)
       
  8251 		return -1;
       
  8252 	totalbytesread +=bytesread;
       
  8253 
       
  8254 	if (m4ds->atomhdr->type != ATOMTYPE_M4DS)
       
  8255 		return -1;
       
  8256 
       
  8257     /* read the avcDecoderConfigurationRecord */
       
  8258 	if  (m4ds->atomhdr->size != 1)
       
  8259 		bytesread = readData(handle, handle->buf, m4ds->atomhdr->size - 8);
       
  8260 	else
       
  8261         bytesread = readData(handle, handle->buf, (mp4_u32)(I64INT(m4ds->atomhdr->largeSize) - 16) );
       
  8262 
       
  8263 	if (bytesread < 0)
       
  8264 		return -1;
       
  8265 	m4ds->descrSize = bytesread;
       
  8266 	m4ds->descr = (mp4_u8 *)mp4malloc(m4ds->descrSize * sizeof(mp4_u8));
       
  8267 	
       
  8268 	/* copy the mpeg4ExtensionDescriptors from the temp. buffer */
       
  8269 	for(i = 0; i <  m4ds->descrSize; i++)
       
  8270 		m4ds->descr[i] = handle->buf[i];
       
  8271 	
       
  8272 	totalbytesread +=bytesread;
       
  8273 
       
  8274 	return totalbytesread;
       
  8275 }
       
  8276 
       
  8277 /*
       
  8278  * Function:
       
  8279  *
       
  8280  *   mp4_i32 readAVC1(MP4HandleImp handle,
       
  8281  *                    avcSampleEntry *avc1)
       
  8282  *
       
  8283  * Description:
       
  8284  *
       
  8285  *   This function parses one avc1 atom.
       
  8286  *
       
  8287  * Parameters:
       
  8288  *
       
  8289  *   handle             MP4 library handle
       
  8290  *   avc1               avc1 pointer
       
  8291  *
       
  8292  * Return value:
       
  8293  *
       
  8294  *   Negative integer   Error
       
  8295  *   >= 0               Success. Value tells how many bytes were read.
       
  8296  *
       
  8297  */
       
  8298 mp4_i32 readAVC1(MP4HandleImp handle, avcSampleEntry *avc1)
       
  8299 {
       
  8300   mp4_i32 bytesread;
       
  8301   mp4_i32 totalbytesread = 0;
       
  8302 
       
  8303   if ((avc1->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  8304     return -100;
       
  8305 
       
  8306   bytesread = readAtomHeader(handle, avc1->atomhdr);
       
  8307 
       
  8308   if (bytesread < 0)
       
  8309     return -1;
       
  8310   totalbytesread += bytesread;
       
  8311 
       
  8312   if (avc1->atomhdr->type != ATOMTYPE_AVC1)
       
  8313     return -1;
       
  8314 
       
  8315   bytesread = discardData(handle, 6);
       
  8316   if (bytesread < 0)
       
  8317     return -1;
       
  8318   totalbytesread += bytesread;
       
  8319 
       
  8320   bytesread = readData(handle, handle->buf, 2);
       
  8321   if (bytesread < 0)
       
  8322     return -1;
       
  8323   avc1->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  8324   totalbytesread += bytesread;
       
  8325 
       
  8326   bytesread = discardData(handle, 16);
       
  8327   if (bytesread < 0)
       
  8328     return -1;
       
  8329   totalbytesread += bytesread;
       
  8330 
       
  8331   bytesread = readData(handle, handle->buf, 2);
       
  8332   if (bytesread < 0)
       
  8333     return -1;
       
  8334   avc1->width = u16endian(*((mp4_u16 *)handle->buf));
       
  8335   totalbytesread += bytesread;
       
  8336 
       
  8337   bytesread = readData(handle, handle->buf, 2);
       
  8338   if (bytesread < 0)
       
  8339     return -1;
       
  8340   avc1->height = u16endian(*((mp4_u16 *)handle->buf));
       
  8341   totalbytesread += bytesread;
       
  8342 
       
  8343   bytesread = discardData(handle, 50);
       
  8344   if (bytesread < 0)
       
  8345     return -1;
       
  8346   totalbytesread += bytesread;
       
  8347 
       
  8348   /* Check for the present atoms */
       
  8349   while ((mp4_u32)totalbytesread < avc1->atomhdr->size)
       
  8350   {
       
  8351     mp4_u32 type;
       
  8352 
       
  8353     if (peekData(handle, handle->buf, 8) < 0)
       
  8354       return -1;
       
  8355 
       
  8356     type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  8357 
       
  8358     switch (type)
       
  8359     {
       
  8360     case ATOMTYPE_AVCC:
       
  8361 
       
  8362 		if (avc1->avcc) /* avcC has already been read, more than one is not allowed. */
       
  8363 			return -1;
       
  8364 
       
  8365 		if ((avc1->avcc = (avcConfigurationAtom *)mp4malloc(sizeof(avcConfigurationAtom))) == NULL)
       
  8366 			return -100;
       
  8367 
       
  8368 		bytesread = readAVCC(handle, avc1->avcc);  
       
  8369 		if(bytesread < 0)
       
  8370 			return -1;
       
  8371 		totalbytesread +=bytesread;
       
  8372   	    break;
       
  8373 
       
  8374     case ATOMTYPE_BTRT:
       
  8375 
       
  8376 		if (avc1->btrt) /* btrt has already been read, more than one is not allowed. */
       
  8377 			return -1;
       
  8378 
       
  8379 		if ((avc1->btrt = (mpeg4BitrateAtom *)mp4malloc(sizeof(mpeg4BitrateAtom))) == NULL)
       
  8380 			return -100;
       
  8381 
       
  8382 		bytesread = readBTRT(handle, avc1->btrt);  
       
  8383 		if(bytesread < 0)
       
  8384 			return -1;
       
  8385 		totalbytesread +=bytesread;
       
  8386 	    break;
       
  8387 
       
  8388     case ATOMTYPE_M4DS:
       
  8389 
       
  8390 		if (avc1->m4ds) /* m4ds has already been read, more than one is not allowed. */
       
  8391 			return -1;
       
  8392 
       
  8393 		if ((avc1->m4ds = (mpeg4ExtensionDescriptorsAtom *)mp4malloc(sizeof(mpeg4ExtensionDescriptorsAtom))) == NULL)
       
  8394 			return -100;
       
  8395 
       
  8396 		bytesread = readM4DS(handle, avc1->m4ds);  
       
  8397 		if(bytesread < 0)
       
  8398 			return -1;
       
  8399 		totalbytesread +=bytesread;
       
  8400 	    break;
       
  8401 	 
       
  8402 	 default:
       
  8403 
       
  8404         bytesread = readUnknown(handle);
       
  8405         if (bytesread < 0)
       
  8406             return -1;
       
  8407         totalbytesread += bytesread;
       
  8408 
       
  8409         break;
       
  8410 
       
  8411 	}
       
  8412   }
       
  8413 
       
  8414   return totalbytesread;
       
  8415 }
       
  8416 
       
  8417 /*
       
  8418  * Function:
       
  8419  *
       
  8420  *   mp4_i32 freeAVCC(avcConfigurationAtom *avcc)
       
  8421  *
       
  8422  * Description:
       
  8423  *
       
  8424  *   This function frees memory for avcc atom.
       
  8425  *
       
  8426  * Parameters:
       
  8427  *
       
  8428  *   avcc       avcc atom pointer
       
  8429  *
       
  8430  * Return value:
       
  8431  *
       
  8432  *   0          Success
       
  8433  *   Negative   Error
       
  8434  *
       
  8435  */
       
  8436 mp4_i32 freeAVCC(avcConfigurationAtom *avcc)
       
  8437 {
       
  8438   if (avcc)
       
  8439   {
       
  8440     if (freeAtomHeader(avcc->atomhdr) < 0)
       
  8441       return -1;
       
  8442 	if(avcc->avcConfig)
       
  8443 		mp4free(avcc->avcConfig);
       
  8444 
       
  8445     mp4free(avcc);
       
  8446   }
       
  8447 
       
  8448   return 0;
       
  8449 }
       
  8450 
       
  8451 /*
       
  8452  * Function:
       
  8453  *
       
  8454  *   mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt)
       
  8455  *
       
  8456  * Description:
       
  8457  *
       
  8458  *   This function frees memory for btrt atom.
       
  8459  *
       
  8460  * Parameters:
       
  8461  *
       
  8462  *   btrt       btrt atom pointer
       
  8463  *
       
  8464  * Return value:
       
  8465  *
       
  8466  *   0          Success
       
  8467  *   Negative   Error
       
  8468  *
       
  8469  */
       
  8470 mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt)
       
  8471 {
       
  8472   if (btrt)
       
  8473   {
       
  8474     if (freeAtomHeader(btrt->atomhdr) < 0)
       
  8475       return -1;
       
  8476 
       
  8477     mp4free(btrt);
       
  8478   }
       
  8479 
       
  8480   return 0;
       
  8481 }
       
  8482 
       
  8483 /*
       
  8484  * Function:
       
  8485  *
       
  8486  *   mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds)
       
  8487  *
       
  8488  * Description:
       
  8489  *
       
  8490  *   This function frees memory for m4ds atom.
       
  8491  *
       
  8492  * Parameters:
       
  8493  *
       
  8494  *   m4ds       m4ds atom pointer
       
  8495  *
       
  8496  * Return value:
       
  8497  *
       
  8498  *   0          Success
       
  8499  *   Negative   Error
       
  8500  *
       
  8501  */
       
  8502 mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds)
       
  8503 {
       
  8504   if (m4ds)
       
  8505   {
       
  8506     if (freeAtomHeader(m4ds->atomhdr) < 0)
       
  8507       return -1;
       
  8508 	if(m4ds->descr)
       
  8509 		mp4free(m4ds->descr);
       
  8510 
       
  8511     mp4free(m4ds);
       
  8512   }
       
  8513 
       
  8514   return 0;
       
  8515 }
       
  8516 
       
  8517 /*
       
  8518  * Function:
       
  8519  *
       
  8520  *   mp4_i32 freeAVC1(avcSampleEntry *avc1)
       
  8521  *
       
  8522  * Description:
       
  8523  *
       
  8524  *   This function frees memory for avc1 atom.
       
  8525  *
       
  8526  * Parameters:
       
  8527  *
       
  8528  *   avc1       avc1 atom pointer
       
  8529  *
       
  8530  * Return value:
       
  8531  *
       
  8532  *   0          Success
       
  8533  *   Negative   Error
       
  8534  *
       
  8535  */
       
  8536 mp4_i32 freeAVC1(avcSampleEntry *avc1)
       
  8537 {
       
  8538   if (avc1)
       
  8539   {
       
  8540     if (freeAtomHeader(avc1->atomhdr) < 0)
       
  8541       return -1;
       
  8542     if (freeAVCC(avc1->avcc) < 0)
       
  8543       return -1;
       
  8544 	if (freeBTRT(avc1->btrt) < 0)
       
  8545 		return -1;
       
  8546 	if (freeM4DS(avc1->m4ds) < 0)
       
  8547 		return -1;
       
  8548 
       
  8549     mp4free(avc1);
       
  8550   }
       
  8551 
       
  8552   return 0;
       
  8553 }
       
  8554 
       
  8555 /*
       
  8556  * Function:
       
  8557  *
       
  8558  *   mp4_i32 readSQCP(MP4HandleImp handle,
       
  8559  *                    qcelpSampleEntry *sqcp)
       
  8560  *
       
  8561  * Description:
       
  8562  *
       
  8563  *   This function parses one SQCP atom.
       
  8564  *
       
  8565  * Parameters:
       
  8566  *
       
  8567  *   handle             MP4 library handle
       
  8568  *   sqcp               SQCP pointer
       
  8569  *
       
  8570  * Return value:
       
  8571  *
       
  8572  *   Negative integer   Error
       
  8573  *   >= 0               Success. Value tells how many bytes were read.
       
  8574  *
       
  8575  */
       
  8576 mp4_i32 readSQCP(MP4HandleImp handle, qcelpSampleEntry *sqcp)
       
  8577 {
       
  8578   mp4_i32 bytesread;
       
  8579   mp4_i32 totalbytesread = 0;
       
  8580 
       
  8581 
       
  8582   if ((sqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  8583     return -100;
       
  8584 
       
  8585   bytesread = readAtomHeader(handle, sqcp->atomhdr);
       
  8586   if (bytesread < 0)
       
  8587     return -1;
       
  8588   totalbytesread += bytesread;
       
  8589 
       
  8590   if (sqcp->atomhdr->type != ATOMTYPE_SQCP)
       
  8591     return -1;
       
  8592 
       
  8593 
       
  8594   bytesread = discardData(handle, 6);
       
  8595   if (bytesread < 0)
       
  8596     return -1;
       
  8597   totalbytesread += bytesread;
       
  8598 
       
  8599   bytesread = readData(handle, handle->buf, 2);
       
  8600   if (bytesread < 0)
       
  8601     return -1;
       
  8602   sqcp->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
       
  8603   totalbytesread += bytesread;
       
  8604 
       
  8605   bytesread = discardData(handle, 16);
       
  8606   if (bytesread < 0)
       
  8607     return -1;
       
  8608   totalbytesread += bytesread;
       
  8609 
       
  8610   bytesread = readData(handle, handle->buf, 2);
       
  8611   if (bytesread < 0)
       
  8612     return -1;
       
  8613   sqcp->timeScale = u16endian(*((mp4_u16 *)handle->buf));
       
  8614   totalbytesread += bytesread;
       
  8615 
       
  8616   bytesread = discardData(handle, 2);
       
  8617   if (bytesread < 0)
       
  8618     return -1;
       
  8619   totalbytesread += bytesread;
       
  8620 
       
  8621   if ((sqcp->dqcp = (qcelpDecSpecStruc *)mp4malloc(sizeof(qcelpDecSpecStruc))) == NULL)
       
  8622     return -100;
       
  8623 
       
  8624   bytesread = readDQCP(handle, sqcp->dqcp);
       
  8625   if (bytesread < 0)
       
  8626     return -1;
       
  8627   totalbytesread += bytesread;
       
  8628   
       
  8629   if ( totalbytesread < sqcp->atomhdr->size )
       
  8630   	{
       
  8631     bytesread = discardData(handle, sqcp->atomhdr->size - totalbytesread );
       
  8632   	if (bytesread < 0)
       
  8633   		{
       
  8634     	return -1;	  		
       
  8635   		}
       
  8636   	totalbytesread += bytesread;
       
  8637   	}  
       
  8638 
       
  8639   return totalbytesread;
       
  8640 }
       
  8641 
       
  8642 /*
       
  8643  * Function:
       
  8644  *
       
  8645  *   mp4_i32 freeSQCP(qcelpSampleEntry *sqcp)
       
  8646  *
       
  8647  * Description:
       
  8648  *
       
  8649  *   This function frees memory for SQCP atom.
       
  8650  *
       
  8651  * Parameters:
       
  8652  *
       
  8653  *   sqcp       SQCP atom pointer
       
  8654  *
       
  8655  * Return value:
       
  8656  *
       
  8657  *   0          Success
       
  8658  *   Negative   Error
       
  8659  *
       
  8660  */
       
  8661 mp4_i32 freeSQCP(qcelpSampleEntry *sqcp)
       
  8662 {
       
  8663   if (sqcp)
       
  8664   {
       
  8665     if (freeAtomHeader(sqcp->atomhdr) < 0)
       
  8666       return -1;
       
  8667     if (freeDQCP(sqcp->dqcp) < 0)
       
  8668       return -1;
       
  8669 
       
  8670     mp4free(sqcp);
       
  8671   }
       
  8672 
       
  8673   return 0;
       
  8674 }
       
  8675 
       
  8676 /*
       
  8677  * Function:
       
  8678  *
       
  8679  *   mp4_i32 readDQCP(MP4HandleImp handle,
       
  8680  *                    qcelpDecSpecStruc *dqcp)
       
  8681  *
       
  8682  * Description:
       
  8683  *
       
  8684  *   This function parses one DQCP atom.
       
  8685  *
       
  8686  * Parameters:
       
  8687  *
       
  8688  *   handle             MP4 library handle
       
  8689  *   dqcp               DQCP pointer
       
  8690  *
       
  8691  * Return value:
       
  8692  *
       
  8693  *   Negative integer   Error
       
  8694  *   >= 0               Success. Value tells how many bytes were read.
       
  8695  *
       
  8696  */
       
  8697 mp4_i32 readDQCP(MP4HandleImp handle, qcelpDecSpecStruc *dqcp)
       
  8698 {
       
  8699   mp4_i32 bytesread;
       
  8700   mp4_i32 totalbytesread = 0;
       
  8701 
       
  8702 
       
  8703   if ((dqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  8704     return -100;
       
  8705 
       
  8706   bytesread = readAtomHeader(handle, dqcp->atomhdr);
       
  8707   if (bytesread < 0)
       
  8708     return -1;
       
  8709   totalbytesread += bytesread;
       
  8710 
       
  8711   if (dqcp->atomhdr->type != ATOMTYPE_DQCP)
       
  8712     return -1;
       
  8713 
       
  8714 
       
  8715   bytesread = readData(handle, handle->buf, 4);
       
  8716   if (bytesread < 0)
       
  8717     return -1;
       
  8718   dqcp->vendor = u32endian(*((mp4_u32 *)handle->buf));
       
  8719   totalbytesread += bytesread;
       
  8720 
       
  8721   bytesread = readData(handle, handle->buf, 1);
       
  8722   if (bytesread < 0)
       
  8723     return -1;
       
  8724   dqcp->decoderVersion = handle->buf[0];
       
  8725   totalbytesread += bytesread;
       
  8726 
       
  8727   bytesread = readData(handle, handle->buf, 1);
       
  8728   if (bytesread < 0)
       
  8729     return -1;
       
  8730   dqcp->framesPerSample = handle->buf[0];
       
  8731   totalbytesread += bytesread;
       
  8732 
       
  8733   return totalbytesread;
       
  8734 }
       
  8735 
       
  8736 /*
       
  8737  * Function:
       
  8738  *
       
  8739  *   mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp)
       
  8740  *
       
  8741  * Description:
       
  8742  *
       
  8743  *   This function frees memory for DQCP atom.
       
  8744  *
       
  8745  * Parameters:
       
  8746  *
       
  8747  *   damr       DQCP atom pointer
       
  8748  *
       
  8749  * Return value:
       
  8750  *
       
  8751  *   0          Success
       
  8752  *   Negative   Error
       
  8753  *
       
  8754  */
       
  8755 mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp)
       
  8756 {
       
  8757   if (dqcp)
       
  8758   {
       
  8759     if (freeAtomHeader(dqcp->atomhdr) < 0)
       
  8760       return -1;
       
  8761 
       
  8762     mp4free(dqcp);
       
  8763   }
       
  8764 
       
  8765   return 0;
       
  8766 }
       
  8767 
       
  8768 /*
       
  8769  * Function:
       
  8770  *
       
  8771  *   mp4_i32 readSDTP(MP4HandleImp handle, sampleDependencyAtom *sdtp, 
       
  8772  * 				      mp4_i32 sample_count)
       
  8773  *
       
  8774  * Description:
       
  8775  *
       
  8776  *   This function parses one SDTP atom.
       
  8777  *
       
  8778  * Parameters:
       
  8779  *
       
  8780  *   handle             MP4 library handle
       
  8781  *   sdtp               SDTP atom pointer
       
  8782  *
       
  8783  * Return value:
       
  8784  *
       
  8785  *   Negative integer   Error
       
  8786  *   >= 0               Success. Value tells how many bytes were read.
       
  8787  *
       
  8788  */
       
  8789 
       
  8790 mp4_i32 readSDTP(MP4HandleImp handle, 
       
  8791 				 sampleDependencyAtom *sdtp, 
       
  8792 				 mp4_i32 sample_count)
       
  8793 {
       
  8794   mp4_i32 bytesread = 0;
       
  8795   mp4_i32 totalbytesread = 0;
       
  8796   mp4_u32 i = 0;
       
  8797 
       
  8798   if ((sdtp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
       
  8799     return -100;
       
  8800 
       
  8801   bytesread = readAtomHeader(handle, sdtp->atomhdr);
       
  8802   if (bytesread < 0)
       
  8803     return -1;
       
  8804   totalbytesread += bytesread;
       
  8805 
       
  8806   if (sdtp->atomhdr->type != ATOMTYPE_SDTP)
       
  8807     return -1;
       
  8808   
       
  8809   bytesread = readData(handle, handle->buf, 1); //Version must be 0
       
  8810   if (bytesread < 0 || handle->buf[0] != 0)
       
  8811     return -1;
       
  8812   totalbytesread += bytesread;
       
  8813   bytesread = readData(handle, handle->buf, 3); // Flags must be 0
       
  8814   if (bytesread < 0 || handle->buf[0] != 0 || handle->buf[1] != 0 || handle->buf[2] != 0)
       
  8815     return -1;
       
  8816   totalbytesread += bytesread;
       
  8817 
       
  8818   // sample_count == (size_of_atom - 12) ???  12 = size + 'sdtp' + ver + flags = 4 + 4 + 1 + 3 ???
       
  8819   //
       
  8820   // sample_count is taken from the sample_count in the Sample Size Box ('stsz') or
       
  8821   // Compact Sample Size Box (‘stz2’).
       
  8822   if (sample_count != sdtp->atomhdr->size-12 || sample_count < 0)
       
  8823 	  {
       
  8824 	  // as each byte consititue one entry in the table, the number of remaining bytes in this
       
  8825 	  // atom should match the sample count.  If not, the file is corrupted.
       
  8826 	  return -1;
       
  8827 	  }
       
  8828   
       
  8829   if ((sdtp->dep = (sampleDependency *)mp4malloc(sample_count * sizeof(sampleDependency))) == NULL)
       
  8830     return -100;
       
  8831   
       
  8832   for(i=0;i<sample_count;i++)
       
  8833   {
       
  8834     bytesread = readData(handle, handle->buf, 1);
       
  8835     if (bytesread < 0)
       
  8836       return -1;
       
  8837     
       
  8838     sdtp->dep[i].sDependsOn = (handle->buf[0] >> 4) & 0x03; // value from 0 to 3
       
  8839     sdtp->dep[i].sIsDependentOn = (handle->buf[0] >> 2) & 0x03; // value from 0 to 3
       
  8840     sdtp->dep[i].sHasRedundancy = handle->buf[0] & 0x03; // value from 0 to 3
       
  8841     totalbytesread += bytesread;
       
  8842   }
       
  8843 
       
  8844   sdtp->sampleCount = sample_count;
       
  8845   return totalbytesread;	
       
  8846 }
       
  8847 
       
  8848 /*
       
  8849  * Function:
       
  8850  *
       
  8851  *   mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type)
       
  8852  * 				      
       
  8853  *
       
  8854  * Description:
       
  8855  *
       
  8856  *   This function parses the size and type information for a box. 
       
  8857  *   Taking into account largesize if needed.
       
  8858  *
       
  8859  * Parameters:
       
  8860  *
       
  8861  *   handle             MP4 library handle
       
  8862  *   size               Size of box is returned here
       
  8863  *   type               Type of the box is returned here
       
  8864  * Return value:
       
  8865  *
       
  8866  *   Negative integer   Error
       
  8867  *   0               Success.
       
  8868  *
       
  8869  */
       
  8870 mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type)
       
  8871 {
       
  8872   if (peekData(handle, handle->buf, 8) < 0)
       
  8873     return -1;
       
  8874 
       
  8875   *size = u32endian(*((mp4_u32 *)handle->buf));
       
  8876   *type = u32endian(*((mp4_u32 *)(handle->buf+4)));
       
  8877 
       
  8878   if (*size == 1)
       
  8879   {
       
  8880     if (peekData(handle, handle->buf, 16) < 0)
       
  8881       return -1;
       
  8882     
       
  8883     *size = u64endian(*((mp4_u64 *)(handle->buf+8)));
       
  8884   }
       
  8885 
       
  8886   return 0;
       
  8887 }
       
  8888 
       
  8889 /*
       
  8890  */
       
  8891 
       
  8892 mp4_i64 getChunkOffset(sampleTableAtom *stbl, mp4_u32 index)
       
  8893 {
       
  8894   if (stbl->is32BitOffsets)
       
  8895   	return (mp4_i64)stbl->stco->chunkOffset[index];
       
  8896   else
       
  8897     return stbl->stco64->chunkOffset[index];
       
  8898 }
       
  8899 
       
  8900 // End of File