os/mm/mmplugins/lib3gp/impl/src/atom.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/mmplugins/lib3gp/impl/src/atom.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,9143 @@
     1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <3gplibrary/mp4config.h>
    1.20 +#include <3gplibrary/mp4lib.h>
    1.21 +#include "mp4atom.h"
    1.22 +#include "mp4memwrap.h"
    1.23 +#include "mp4buffer.h"
    1.24 +#include "mp4endian.h"
    1.25 +#include "mp4file.h"
    1.26 +#include "mp4utils.h"
    1.27 +
    1.28 +// MACROS
    1.29 +// Debug print macro
    1.30 +#ifdef _DEBUG
    1.31 +#include <e32svr.h>
    1.32 +//#define PRINT(x) RDebug::Print x
    1.33 +#define PRINT(x)
    1.34 +#else
    1.35 +#define PRINT(x)
    1.36 +#endif
    1.37 +
    1.38 +mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type);
    1.39 + 
    1.40 +/*
    1.41 + * Function:
    1.42 + *
    1.43 + *   mp4_i32 metaDataAvailable(MP4HandleImp handle)
    1.44 + *
    1.45 + * Description:
    1.46 + *
    1.47 + *   This function determines whether meta data is available for reading
    1.48 + *   or not.
    1.49 + *
    1.50 + *   Meta data is available if the input is in a file.
    1.51 + *
    1.52 + *   When reading from a stream, meta data is considered available if
    1.53 + *   it is in the beginning of the stream and the entire Moov atom has
    1.54 + *   been received. FTYP atom is allowed before MOOV atom.
    1.55 + *
    1.56 + * Parameters:
    1.57 + *
    1.58 + *   handle   MP4 library handle
    1.59 + *
    1.60 + * Return value:
    1.61 + *
    1.62 + *   0                Meta data is not available because enough data has not
    1.63 + *                    been inserted into the library
    1.64 + *   1                Meta data is available
    1.65 + *   Negative value   Meta data is not available because of fatal error
    1.66 + *
    1.67 + */
    1.68 +mp4_i32 metaDataAvailable(MP4HandleImp handle)
    1.69 +{
    1.70 +  mp4_u32 size;
    1.71 +  mp4_u32 type;
    1.72 +
    1.73 +
    1.74 +  /* Meta data is available if the input is in a file or if a complete file has been inputted as a stream*/
    1.75 +
    1.76 +  if (handle->file)
    1.77 +    return 1;
    1.78 +
    1.79 +  /* When reading from a stream, meta data is considered available if
    1.80 +     it is in the beginning of the stream and the entire MOOV atom has
    1.81 +     been received. FTYP atom is allowed before MOOV atom. */
    1.82 +
    1.83 +  if (!handle->ftypRead)
    1.84 +  {
    1.85 +    if (peekData(handle, handle->buf, 8) < 0) /* 8 bytes are not available */
    1.86 +        return 0;
    1.87 +
    1.88 +    size = u32endian(*((mp4_u32 *)handle->buf));
    1.89 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
    1.90 +
    1.91 +    if (type == ATOMTYPE_FTYP)
    1.92 +    {
    1.93 +      if (getBufferedBytes(handle) - handle->position < size) /* FTYP is not available */
    1.94 +        return 0;
    1.95 +      if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL)
    1.96 +        return -100;
    1.97 +      if (readFTYP(handle, handle->ftyp) < 0)
    1.98 +        return -2;
    1.99 +    }
   1.100 +  }
   1.101 +
   1.102 +  // Now the ftyp is read. No need to chedk MOOV presence for full files in the memory.
   1.103 +  if (handle->LastWriteDataCalled == MP4TRUE)
   1.104 +      return 1;
   1.105 +
   1.106 +  if (handle->LastWriteDataCalled == MP4FALSE)
   1.107 +  {//Whole stream is not fed to the internal memory yet. 
   1.108 +   for (;;)
   1.109 +    {
   1.110 +      if (peekData(handle, handle->buf, 8) < 0)
   1.111 +        return 0;
   1.112 +
   1.113 +      size = u32endian(*((mp4_u32 *)handle->buf));
   1.114 +      type = u32endian(*((mp4_u32 *)(handle->buf+4)));
   1.115 +
   1.116 +      if (type == ATOMTYPE_MOOV)
   1.117 +        {
   1.118 +        if (getBufferedBytes(handle) - handle->absPosition >= size) /* Entire Moov is available */
   1.119 +            {
   1.120 +            return 1;        
   1.121 +            }
   1.122 +        else
   1.123 +            {
   1.124 +            return 0;
   1.125 +            }
   1.126 +        }
   1.127 +
   1.128 +      if ((mp4_i32)size <= 0)
   1.129 +        return -1;
   1.130 +
   1.131 +      handle->absPosition+=size;
   1.132 +    }
   1.133 +  }
   1.134 +  return 0;
   1.135 +}
   1.136 +
   1.137 +
   1.138 +/*
   1.139 + * Function:
   1.140 + *
   1.141 + *   mp4_i32 readFTYP(MP4HandleImp handle,
   1.142 + *                    fileTypeAtom *ftyp)
   1.143 + *
   1.144 + * Description:
   1.145 + *
   1.146 + *   This function parses one FTYP atom.
   1.147 + *
   1.148 + * Parameters:
   1.149 + *
   1.150 + *   handle             MP4 library handle
   1.151 + *   ftyp               FTYP pointer
   1.152 + *
   1.153 + * Return value:
   1.154 + *
   1.155 + *   Negative integer   Error
   1.156 + *   >= 0               Success. Value tells how many bytes were read.
   1.157 + *
   1.158 + */
   1.159 +mp4_i32 readFTYP(MP4HandleImp handle, fileTypeAtom *ftyp)
   1.160 +{
   1.161 +  mp4_i32 bytesread;
   1.162 +  mp4_i32 totalbytesread = 0;
   1.163 +  mp4_u32 n = 0;
   1.164 +  mp4_i32 compatiblebrandsize = 0;
   1.165 +
   1.166 +
   1.167 +  if ((ftyp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
   1.168 +    return -100;
   1.169 +
   1.170 +  bytesread = readAtomHeader(handle, ftyp->atomhdr);
   1.171 +  if (bytesread < 0)
   1.172 +    return -1;
   1.173 +  totalbytesread += bytesread;
   1.174 +
   1.175 +  if (ftyp->atomhdr->type != ATOMTYPE_FTYP)
   1.176 +    return -1;
   1.177 +
   1.178 +  if (ftyp->atomhdr->size < 16) // 8(header)+8bytes needed for major and minor brand
   1.179 +    return -1;
   1.180 +
   1.181 +  bytesread = readData(handle, handle->buf, 4);
   1.182 +  if (bytesread < 0)
   1.183 +    return -1;
   1.184 +  ftyp->majorBrand = u32endian(*((mp4_u32 *)handle->buf));
   1.185 +  totalbytesread += bytesread;
   1.186 +
   1.187 +  bytesread = readData(handle, handle->buf, 4);
   1.188 +  if (bytesread < 0)
   1.189 +    return -1;
   1.190 +  ftyp->minorVersion = u32endian(*((mp4_u32 *)handle->buf));
   1.191 +  totalbytesread += bytesread;
   1.192 +
   1.193 +  if (ftyp->atomhdr->size == (mp4_u32)totalbytesread)
   1.194 +    return totalbytesread;
   1.195 +
   1.196 +  compatiblebrandsize = (mp4_i32)ftyp->atomhdr->size - totalbytesread;
   1.197 +  if ( compatiblebrandsize < 4 )   // at this point we must have at least 1 compatible brand
   1.198 +    return -1;
   1.199 +  if ( compatiblebrandsize > 20*4) // maximum of 20 compatible brands 4byte entries
   1.200 +    return -1;
   1.201 +  if ( compatiblebrandsize % 4 ) // must be able to divide by 4
   1.202 +    return -1;
   1.203 +
   1.204 +  ftyp->compatibleBrands = (mp4_u32 *)mp4malloc( compatiblebrandsize );
   1.205 +  if (ftyp->compatibleBrands == NULL)
   1.206 +    return -1;
   1.207 +
   1.208 +  while ((mp4_u32)totalbytesread < ftyp->atomhdr->size)
   1.209 +  {
   1.210 +    bytesread = readData(handle, handle->buf, 4);
   1.211 +    if (bytesread < 0)
   1.212 +      return -1;
   1.213 +
   1.214 +    ftyp->compatibleBrands[n] = u32endian(*((mp4_u32 *)handle->buf));
   1.215 +
   1.216 +    n++;
   1.217 +    totalbytesread += bytesread;
   1.218 +  }
   1.219 +
   1.220 +  return totalbytesread;
   1.221 +}
   1.222 +
   1.223 +
   1.224 +/*
   1.225 + * Function:
   1.226 + *
   1.227 + *   mp4_i32 readMetaData(MP4HandleImp handle)
   1.228 + *
   1.229 + * Description:
   1.230 + *
   1.231 + *   This function reads the meta data from the file/stream and stores
   1.232 + *   the information in the atom structures available via handle.
   1.233 + *
   1.234 + * Parameters:
   1.235 + *
   1.236 + *   handle  MP4 library handle
   1.237 + *
   1.238 + * Return value:
   1.239 + *
   1.240 + *   Negative value   Error
   1.241 + *   >= 0             Success. Value tells the number of bytes read.
   1.242 + *
   1.243 + */
   1.244 +mp4_i32 readMetaData(MP4HandleImp handle)
   1.245 +{
   1.246 +  mp4_i32 bytesread;
   1.247 +  mp4_i32 totalbytesread = 0;
   1.248 +
   1.249 +
   1.250 +  if (handle->file)
   1.251 +  {
   1.252 +    mp4_u64 size;
   1.253 +    mp4_u32 type;
   1.254 +
   1.255 +
   1.256 +    if (seekFileAbs(handle, 0) < 0)
   1.257 +      return -1;
   1.258 +
   1.259 +    /* Seek to the start of FTYP atom */
   1.260 +
   1.261 +    for (;;)
   1.262 +    {
   1.263 +      if (readBoxHeader(handle, &size, &type) <0)
   1.264 +        return -1;
   1.265 +
   1.266 +      if (type == ATOMTYPE_FTYP)
   1.267 +      {
   1.268 +        /* Read FTYP */
   1.269 +
   1.270 +        if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL)
   1.271 +          return -100;
   1.272 +        bytesread = readFTYP(handle, handle->ftyp);
   1.273 +        if (bytesread < 0)
   1.274 +          return -3;
   1.275 +        totalbytesread += bytesread;
   1.276 +
   1.277 +        break;
   1.278 +      }
   1.279 +
   1.280 +      if (size <= 0)
   1.281 +        return -1;
   1.282 +
   1.283 +      if (seekFile(handle, size) != 0)
   1.284 +        return -1;
   1.285 +    }
   1.286 +
   1.287 +    if (seekFileAbs(handle, 0) < 0)
   1.288 +      return -1;
   1.289 +
   1.290 +    /* Seek to the start of MOOV atom */
   1.291 +    for (;;)
   1.292 +    {
   1.293 +      if (readBoxHeader(handle, &size, &type) <0)
   1.294 +        return -1;
   1.295 +
   1.296 +      if (type == ATOMTYPE_MOOV)
   1.297 +        break;
   1.298 +
   1.299 +      if (size <= 0)
   1.300 +        return -1;
   1.301 +
   1.302 +      if (seekFile(handle, size) != 0)
   1.303 +        return -1;
   1.304 +    }
   1.305 +  }
   1.306 +
   1.307 +  // If all data of a file is in the memory and the file does not have MOOV box right after FTYP, 
   1.308 +  // then we need to seek for the location of the MOOV first
   1.309 +
   1.310 +  if (handle->LastWriteDataCalled == MP4TRUE)
   1.311 +  { 
   1.312 +    mp4_u32 size;
   1.313 +    mp4_u32 type;
   1.314 +    // Seek until the beginning of MOOV box.
   1.315 +    for(;;)
   1.316 +    {
   1.317 +        if (peekData(handle, handle->buf, 8) < 0)
   1.318 +            return -1;
   1.319 +
   1.320 +        size = u32endian(*((mp4_u32 *)handle->buf));
   1.321 +        type = u32endian(*((mp4_u32 *)(handle->buf+4)));
   1.322 +    
   1.323 +        if (type == ATOMTYPE_MOOV)
   1.324 +          break;
   1.325 +
   1.326 +        if ((mp4_i32)size <= 0)
   1.327 +          return -1;
   1.328 +
   1.329 +        if (discardData(handle, size) < 0)
   1.330 +          return -1;
   1.331 +    }
   1.332 +  }
   1.333 +
   1.334 +  if ((handle->moov = (movieAtom *)mp4malloc(sizeof(movieAtom))) == NULL)
   1.335 +    return -100;
   1.336 +
   1.337 +  bytesread = readMoov(handle, handle->moov);
   1.338 +  if (bytesread < 0)
   1.339 +    return -3;
   1.340 +  totalbytesread += bytesread;
   1.341 +
   1.342 +  if (handle->moov->trakAudio)
   1.343 +  {
   1.344 +    mp4_u32 audiotype;
   1.345 +	mp4_i32 errorAudio = 0;
   1.346 +
   1.347 +	errorAudio = determineAudioType(handle, &audiotype);
   1.348 +    if ( errorAudio == 0 )
   1.349 +    {
   1.350 +	   	handle->type |= audiotype;    	
   1.351 +    
   1.352 +	    /* Move to the beginning of the 1st audio frame */
   1.353 +	    switch (advanceAudioSample(handle, handle->moov->trakAudio))
   1.354 +	    {
   1.355 +	    case -1:
   1.356 +	      return -1;
   1.357 +	    case -2:
   1.358 +	      handle->audioLast = MP4TRUE;
   1.359 +	      break;
   1.360 +	    default:
   1.361 +	      break;
   1.362 +	    }
   1.363 +	}
   1.364 +	else if (errorAudio == -2)
   1.365 +	{
   1.366 +		handle->type |= audiotype;	
   1.367 +	}
   1.368 +	else
   1.369 +	{
   1.370 +		return -1;
   1.371 +	}
   1.372 +  }
   1.373 +
   1.374 +  if (handle->moov->trakVideo)
   1.375 +  {
   1.376 +    mp4_u32 videotype;
   1.377 +    mp4_i32 errorVideo = 0;
   1.378 +
   1.379 +	errorVideo = determineVideoType(handle, &videotype);
   1.380 +    if ( errorVideo == 0 )
   1.381 +    {
   1.382 +	   	handle->type |= videotype;    	
   1.383 +    
   1.384 +    	/* Move to the beginning of the 1st video frame */
   1.385 +	    switch (advanceVideoFrame(handle, handle->moov->trakVideo))
   1.386 +	    {
   1.387 +	    case -1:
   1.388 +	      return -1;
   1.389 +	    case -2:
   1.390 +	       handle->videoLast = MP4TRUE;
   1.391 +	      break;
   1.392 +	    default:
   1.393 +	      break;
   1.394 +	    }
   1.395 +	}
   1.396 +	else if (errorVideo == -2)
   1.397 +	{
   1.398 +	   	handle->type |= videotype;	
   1.399 +	}
   1.400 +	else
   1.401 +	{
   1.402 +		return -1;
   1.403 +	}
   1.404 +  }
   1.405 +
   1.406 +  return totalbytesread;
   1.407 +}
   1.408 +
   1.409 +
   1.410 +/*
   1.411 + * Function:
   1.412 + *
   1.413 + *   mp4_i32 readMoov(MP4HandleImp handle,
   1.414 + *                    movieAtom *moov)
   1.415 + *
   1.416 + * Description:
   1.417 + *
   1.418 + *   This function parses one MOOV atom.
   1.419 + *
   1.420 + * Parameters:
   1.421 + *
   1.422 + *   handle             MP4 library handle
   1.423 + *   moov               MOOV pointer
   1.424 + *
   1.425 + * Return value:
   1.426 + *
   1.427 + *   Negative integer   Error
   1.428 + *   >= 0               Success. Value tells how many bytes were read.
   1.429 + *
   1.430 + */
   1.431 +mp4_i32 readMoov(MP4HandleImp handle, movieAtom *moov)
   1.432 +{
   1.433 +  mp4_i32 bytesread;
   1.434 +  mp4_i32 totalbytesread = 0;
   1.435 +
   1.436 +
   1.437 +  if ((moov->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
   1.438 +    return -100;
   1.439 +
   1.440 +  bytesread = readAtomHeader(handle, moov->atomhdr);
   1.441 +  if (bytesread < 0)
   1.442 +    return -1;
   1.443 +  totalbytesread += bytesread;
   1.444 +
   1.445 +  if (moov->atomhdr->type != ATOMTYPE_MOOV)
   1.446 +    return -1;
   1.447 +
   1.448 +  while ((mp4_u32)totalbytesread < handle->moov->atomhdr->size)
   1.449 +  {
   1.450 +    mp4_u32 type;
   1.451 +
   1.452 +
   1.453 +    if (peekData(handle, handle->buf, 8) < 0)
   1.454 +      return -1;
   1.455 +
   1.456 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
   1.457 +
   1.458 +    switch (type)
   1.459 +    {
   1.460 +    case ATOMTYPE_MVHD:
   1.461 +
   1.462 +      if (moov->mvhd) /* MVHD has already been read, more than one is not allowed */
   1.463 +        return -1;
   1.464 +
   1.465 +      if ((moov->mvhd = (movieHeaderAtom *)mp4malloc(sizeof(movieHeaderAtom))) == NULL)
   1.466 +        return -100;
   1.467 +
   1.468 +      bytesread = readMVHD(handle, moov->mvhd);
   1.469 +      if (bytesread < 0)
   1.470 +        return -1;
   1.471 +      totalbytesread += bytesread;
   1.472 +
   1.473 +      break;
   1.474 +
   1.475 +    case ATOMTYPE_IODS:
   1.476 +
   1.477 +      if (moov->iods) /* IODS has already been read, more than one is not allowed */
   1.478 +        return -1;
   1.479 +
   1.480 +      if ((moov->iods = (objectDescriptorAtom *)mp4malloc(sizeof(objectDescriptorAtom))) == NULL)
   1.481 +        return -100;
   1.482 +
   1.483 +      bytesread = readIODS(handle, moov->iods);
   1.484 +      if (bytesread < 0)
   1.485 +        return -1;
   1.486 +      totalbytesread += bytesread;
   1.487 +
   1.488 +      break;
   1.489 +
   1.490 +    case ATOMTYPE_TRAK:
   1.491 +
   1.492 +      {
   1.493 +        trackAtom *ta;
   1.494 +
   1.495 +        if ((ta = (trackAtom *)mp4malloc(sizeof(trackAtom))) == NULL)
   1.496 +          return -100;
   1.497 +
   1.498 +        bytesread = readTRAK(handle, ta);
   1.499 +        if (bytesread < 0)
   1.500 +        {
   1.501 +          if (freeTRAK(ta) < 0)
   1.502 +            return -1;
   1.503 +          return -1;
   1.504 +        }
   1.505 +        totalbytesread += bytesread;
   1.506 +
   1.507 +        if (!ta->mdia)
   1.508 +        {
   1.509 +          if (freeTRAK(ta) < 0)
   1.510 +            return -1;
   1.511 +          return -1;
   1.512 +        }
   1.513 +        if (!ta->mdia->hdlr)
   1.514 +        {
   1.515 +          if (freeTRAK(ta) < 0)
   1.516 +            return -1;
   1.517 +          return -1;
   1.518 +        }
   1.519 +
   1.520 +        if (ta->mdia->hdlr->handlerType != HANDLERTYPE_VIDE &&
   1.521 +            ta->mdia->hdlr->handlerType != HANDLERTYPE_SOUN) /* Track is neither video nor audio */
   1.522 +        {
   1.523 +          /* Do nothing with the unknown track */
   1.524 +          if (freeTRAK(ta) < 0)
   1.525 +            return -1;
   1.526 +          break;
   1.527 +        }
   1.528 +
   1.529 +        if (ta->mdia->hdlr->handlerType == HANDLERTYPE_VIDE)
   1.530 +        {
   1.531 +	        if (moov->trakVideo) /* Video Track already read */
   1.532 +	        {
   1.533 +	          if (freeTRAK(ta) < 0)
   1.534 +	            return -1;
   1.535 +	        }
   1.536 +	        else
   1.537 +	        {
   1.538 +	          moov->trakVideo = ta;
   1.539 +	        }
   1.540 +        }
   1.541 +		else if (ta->mdia->hdlr->handlerType == HANDLERTYPE_SOUN)
   1.542 +        {
   1.543 +	        if (moov->trakAudio) /* Audio Track already read */
   1.544 +	        {
   1.545 +	          if (freeTRAK(ta) < 0)
   1.546 +	            return -1;
   1.547 +	        }
   1.548 +	        else
   1.549 +	        {
   1.550 +	          moov->trakAudio = ta;
   1.551 +	        }
   1.552 +        }
   1.553 +        else
   1.554 +        {
   1.555 +        }
   1.556 +        break;
   1.557 +      }
   1.558 +
   1.559 +    case ATOMTYPE_UDTA:
   1.560 +
   1.561 +      {
   1.562 +      if (moov->udta) /* UDTA has already been read */
   1.563 +          {
   1.564 +          bytesread = readUnknown(handle);
   1.565 +          if (bytesread < 0)
   1.566 +            return -1;
   1.567 +          totalbytesread += bytesread;
   1.568 +          break;
   1.569 +          }
   1.570 +
   1.571 +
   1.572 +      if ((moov->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL)
   1.573 +        return -100;
   1.574 +
   1.575 +      bytesread = readUDTA(handle, moov->udta);
   1.576 +      if (bytesread < 0)
   1.577 +        return -1;
   1.578 +      totalbytesread += bytesread;
   1.579 +
   1.580 +      break;
   1.581 +      }
   1.582 +      
   1.583 +    case ATOMTYPE_META:
   1.584 +        
   1.585 +        {
   1.586 +        if (moov->meta) /* META has already been read, more than one is not allowed */
   1.587 +          return -1;
   1.588 +           
   1.589 +        if ((moov->meta = (metaAtom *)mp4malloc(sizeof(metaAtom))) == NULL)
   1.590 +            return -100;
   1.591 +
   1.592 +        bytesread = readMeta(handle, moov->meta);
   1.593 +        if (bytesread < 0)
   1.594 +          return -1;
   1.595 +        totalbytesread += bytesread;
   1.596 +        
   1.597 +        break;
   1.598 +        }
   1.599 +        
   1.600 +    default:
   1.601 +
   1.602 +      bytesread = readUnknown(handle);
   1.603 +      if (bytesread < 0)
   1.604 +        return -1;
   1.605 +      totalbytesread += bytesread;
   1.606 +
   1.607 +      break;
   1.608 +    }
   1.609 +  }
   1.610 +
   1.611 +  return totalbytesread;
   1.612 +}
   1.613 +
   1.614 +
   1.615 +/*
   1.616 + * Function:
   1.617 + *
   1.618 + *   mp4_i32 readAtomheader(MP4HandleImp handle,
   1.619 + *                          atomHeader *ah)
   1.620 + *
   1.621 + * Description:
   1.622 + *
   1.623 + *   This function reads an atom header and stores the information
   1.624 + *   in ah.
   1.625 + *
   1.626 + * Parameters:
   1.627 + *
   1.628 + *   handle           MP4 library handle
   1.629 + *   ah               atomHeader structure that is used to store the
   1.630 + *                    information
   1.631 + *
   1.632 + * Return value:
   1.633 + *
   1.634 + *   Negative value   Error
   1.635 + *   >= 0             Success. Value tells how many bytes were read.
   1.636 + *
   1.637 + */
   1.638 +mp4_i32 readAtomHeader(MP4HandleImp handle, atomHeader *ah)
   1.639 +{
   1.640 +  mp4_i32 bytesread;
   1.641 +  mp4_i32 totalbytesread = 0;
   1.642 +
   1.643 +  //PRINT((_L("readAtomHeader")));
   1.644 +  bytesread = readData(handle, handle->buf, 4);
   1.645 +  if (bytesread < 0)
   1.646 +    return -1;
   1.647 +  ah->size = u32endian(*((mp4_u32 *)handle->buf));
   1.648 +  totalbytesread += bytesread;
   1.649 +
   1.650 +  bytesread = readData(handle, handle->buf, 4);
   1.651 +  if (bytesread < 0)
   1.652 +    return -1;
   1.653 +  ah->type = u32endian(*((mp4_u32 *)handle->buf));
   1.654 +  totalbytesread += bytesread;
   1.655 +
   1.656 +  if (ah->size == 1)
   1.657 +  {
   1.658 +    bytesread = readData(handle, handle->buf, 8);
   1.659 +    if (bytesread < 0)
   1.660 +      return -1;
   1.661 +    ah->largeSize = u64endian(*((mp4_u64 *)handle->buf));
   1.662 +    totalbytesread += bytesread;
   1.663 +  }
   1.664 +
   1.665 +  if (ah->type == ATOMTYPE_UUID)
   1.666 +  {
   1.667 +    bytesread = readData(handle, handle->buf, 16);
   1.668 +    if (bytesread < 0)
   1.669 +      return -1;
   1.670 +    mp4memcpy(ah->extendedType, handle->buf, 16);
   1.671 +    totalbytesread += bytesread;
   1.672 +  }
   1.673 +
   1.674 +  //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]));
   1.675 +  return totalbytesread;
   1.676 +}
   1.677 +
   1.678 +
   1.679 +/*
   1.680 + * Function:
   1.681 + *
   1.682 + *   mp4_i32 readFullAtomHeader(MP4HandleImp handle,
   1.683 + *                              atomHeader *ah)
   1.684 + *
   1.685 + * Description:
   1.686 + *
   1.687 + *   This function reads a full atom header and stores the information
   1.688 + *   in ah.
   1.689 + *
   1.690 + * Parameters:
   1.691 + *
   1.692 + *   handle           MP4 library handle
   1.693 + *   ah               atomHeader structure that is used to store the
   1.694 + *                    information
   1.695 + *
   1.696 + * Return value:
   1.697 + *
   1.698 + *   Negative value   Error
   1.699 + *   >= 0             Success. Value tells how many bytes were read.
   1.700 + *
   1.701 + */
   1.702 +mp4_i32 readFullAtomHeader(MP4HandleImp handle, atomHeader *ah)
   1.703 +{
   1.704 +  mp4_i32 bytesread;
   1.705 +  mp4_i32 totalbytesread = 0;
   1.706 +
   1.707 +  //PRINT((_L("readFullAtomHeader")));
   1.708 +
   1.709 +  bytesread = readData(handle, handle->buf, 4);
   1.710 +  if (bytesread < 0)
   1.711 +    return -1;
   1.712 +  ah->size = u32endian(*((mp4_u32 *)handle->buf));
   1.713 +  totalbytesread += bytesread;
   1.714 +
   1.715 +  bytesread = readData(handle, handle->buf, 4);
   1.716 +  if (bytesread < 0)
   1.717 +    return -1;
   1.718 +  ah->type = u32endian(*((mp4_u32 *)handle->buf));
   1.719 +  totalbytesread += bytesread;
   1.720 +
   1.721 +  bytesread = readData(handle, handle->buf, 1);
   1.722 +  if (bytesread < 0)
   1.723 +    return -1;
   1.724 +  ah->version = *(handle->buf);
   1.725 +  totalbytesread += bytesread;
   1.726 +
   1.727 +  bytesread = readData(handle, handle->buf, 3);
   1.728 +  if (bytesread < 0)
   1.729 +    return -1;
   1.730 +  mp4memcpy(ah->flags, handle->buf, 3);
   1.731 +  totalbytesread += bytesread;
   1.732 +
   1.733 +  //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]));
   1.734 +  return totalbytesread;
   1.735 +}
   1.736 +
   1.737 +
   1.738 +/*
   1.739 + * Function:
   1.740 + *
   1.741 + *   mp4_i32 readMVHD(MP4HandleImp handle,
   1.742 + *                    movieHeaderAtom *mvhd)
   1.743 + *
   1.744 + * Description:
   1.745 + *
   1.746 + *   This function parses one MVHD atom.
   1.747 + *
   1.748 + * Parameters:
   1.749 + *
   1.750 + *   handle             MP4 library handle
   1.751 + *   mvhd               MVHD pointer
   1.752 + *
   1.753 + * Return value:
   1.754 + *
   1.755 + *   Negative integer   Error
   1.756 + *   >= 0               Success. Value tells how many bytes were read.
   1.757 + *
   1.758 + */
   1.759 +mp4_i32 readMVHD(MP4HandleImp handle, movieHeaderAtom *mvhd)
   1.760 +{
   1.761 +  mp4_i32 bytesread;
   1.762 +  mp4_i32 totalbytesread = 0;
   1.763 +
   1.764 +
   1.765 +  if ((mvhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
   1.766 +    return -100;
   1.767 +
   1.768 +  bytesread = readFullAtomHeader(handle, mvhd->atomhdr);
   1.769 +  if (bytesread < 0)
   1.770 +    return -1;
   1.771 +  totalbytesread += bytesread;
   1.772 +
   1.773 +  if (mvhd->atomhdr->type != ATOMTYPE_MVHD)
   1.774 +    return -1;
   1.775 +
   1.776 +  if (mvhd->atomhdr->version == 1) /* 64 bit */
   1.777 +  {
   1.778 +    bytesread = readData(handle, handle->buf, 8);
   1.779 +    if (bytesread < 0)
   1.780 +      return -1;
   1.781 +    mvhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
   1.782 +    totalbytesread += bytesread;
   1.783 +
   1.784 +    bytesread = readData(handle, handle->buf, 8);
   1.785 +    if (bytesread < 0)
   1.786 +      return -1;
   1.787 +    mvhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
   1.788 +    totalbytesread += bytesread;
   1.789 +
   1.790 +    bytesread = readData(handle, handle->buf, 4);
   1.791 +    if (bytesread < 0)
   1.792 +      return -1;
   1.793 +    mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
   1.794 +    totalbytesread += bytesread;
   1.795 +
   1.796 +    bytesread = readData(handle, handle->buf, 8);
   1.797 +    if (bytesread < 0)
   1.798 +      return -1;
   1.799 +    mvhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
   1.800 +    totalbytesread += bytesread;
   1.801 +  }
   1.802 +  else /* 32 bit */
   1.803 +  {
   1.804 +    bytesread = readData(handle, handle->buf, 4);
   1.805 +    if (bytesread < 0)
   1.806 +      return -1;
   1.807 +    mvhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
   1.808 +    totalbytesread += bytesread;
   1.809 +
   1.810 +    bytesread = readData(handle, handle->buf, 4);
   1.811 +    if (bytesread < 0)
   1.812 +      return -1;
   1.813 +    mvhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
   1.814 +    totalbytesread += bytesread;
   1.815 +
   1.816 +    bytesread = readData(handle, handle->buf, 4);
   1.817 +    if (bytesread < 0)
   1.818 +      return -1;
   1.819 +    mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
   1.820 +    totalbytesread += bytesread;
   1.821 +
   1.822 +    bytesread = readData(handle, handle->buf, 4);
   1.823 +    if (bytesread < 0)
   1.824 +      return -1;
   1.825 +    mvhd->duration = u32endian(*((mp4_u32 *)handle->buf));
   1.826 +    totalbytesread += bytesread;
   1.827 +  }
   1.828 +
   1.829 +  bytesread = discardData(handle, 76);
   1.830 +  if (bytesread < 0)
   1.831 +    return -1;
   1.832 +  totalbytesread += bytesread;
   1.833 +
   1.834 +  bytesread = readData(handle, handle->buf, 4);
   1.835 +  if (bytesread < 0)
   1.836 +    return -1;
   1.837 +  mvhd->nextTrackID = u32endian(*((mp4_u32 *)handle->buf));
   1.838 +  totalbytesread += bytesread;
   1.839 +
   1.840 +  return totalbytesread;
   1.841 +}
   1.842 +
   1.843 +
   1.844 +/*
   1.845 + * Function:
   1.846 + *
   1.847 + *   mp4_i32 readIODS(MP4HandleImp handle,
   1.848 + *                    objectDescriptorAtom *iods)
   1.849 + *
   1.850 + * Description:
   1.851 + *
   1.852 + *   This function parses one IODS atom.
   1.853 + *
   1.854 + * Parameters:
   1.855 + *
   1.856 + *   handle             MP4 library handle
   1.857 + *   iods               IODS pointer
   1.858 + *
   1.859 + * Return value:
   1.860 + *
   1.861 + *   Negative integer   Error
   1.862 + *   >= 0               Success. Value tells how many bytes were read.
   1.863 + *
   1.864 + */
   1.865 +mp4_i32 readIODS(MP4HandleImp handle, objectDescriptorAtom *iods)
   1.866 +{
   1.867 +  mp4_i32 bytesread;
   1.868 +  mp4_i32 totalbytesread = 0;
   1.869 +
   1.870 +
   1.871 +  if ((iods->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
   1.872 +    return -100;
   1.873 +
   1.874 +  bytesread = readFullAtomHeader(handle, iods->atomhdr);
   1.875 +  if (bytesread < 0)
   1.876 +    return -1;
   1.877 +  totalbytesread += bytesread;
   1.878 +
   1.879 +  if (iods->atomhdr->type != ATOMTYPE_IODS)
   1.880 +    return -1;
   1.881 +
   1.882 +  bytesread = discardData(handle, iods->atomhdr->size - totalbytesread);
   1.883 +  if (bytesread < 0)
   1.884 +    return -1;
   1.885 +  totalbytesread += bytesread;
   1.886 +
   1.887 +  return totalbytesread;
   1.888 +}
   1.889 +
   1.890 +
   1.891 +/*
   1.892 + * Function:
   1.893 + *
   1.894 + *   mp4_i32 readTRAK(MP4HandleImp handle,
   1.895 + *                    trackAtom *trak)
   1.896 + *
   1.897 + * Description:
   1.898 + *
   1.899 + *   This function parses one TRAK atom.
   1.900 + *
   1.901 + * Parameters:
   1.902 + *
   1.903 + *   handle             MP4 library handle
   1.904 + *   trak               TRAK pointer
   1.905 + *
   1.906 + * Return value:
   1.907 + *
   1.908 + *   Negative integer   Error
   1.909 + *   >= 0               Success. Value tells how many bytes were read.
   1.910 + *
   1.911 + */
   1.912 +mp4_i32 readTRAK(MP4HandleImp handle, trackAtom *trak)
   1.913 +{
   1.914 +  mp4_i32 bytesread;
   1.915 +  mp4_i32 totalbytesread = 0;
   1.916 +
   1.917 +
   1.918 +  if ((trak->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
   1.919 +    return -100;
   1.920 +
   1.921 +  bytesread = readAtomHeader(handle, trak->atomhdr);
   1.922 +  if (bytesread < 0)
   1.923 +    return -1;
   1.924 +  totalbytesread += bytesread;
   1.925 +
   1.926 +  if (trak->atomhdr->type != ATOMTYPE_TRAK)
   1.927 +    return -1;
   1.928 +
   1.929 +
   1.930 +  while ((mp4_u32)totalbytesread < trak->atomhdr->size)
   1.931 +  {
   1.932 +    mp4_u32 type;
   1.933 +
   1.934 +
   1.935 +    if (peekData(handle, handle->buf, 8) < 0)
   1.936 +      return -1;
   1.937 +
   1.938 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
   1.939 +
   1.940 +    switch (type)
   1.941 +    {
   1.942 +    case ATOMTYPE_TKHD:
   1.943 +
   1.944 +      if (trak->tkhd) /* MVHD has already been read, more than one is not allowed */
   1.945 +        return -1;
   1.946 +
   1.947 +      if ((trak->tkhd = (trackHeaderAtom *)mp4malloc(sizeof(trackHeaderAtom))) == NULL)
   1.948 +        return -100;
   1.949 +
   1.950 +      bytesread = readTKHD(handle, trak->tkhd);
   1.951 +      if (bytesread < 0)
   1.952 +        return -1;
   1.953 +      totalbytesread += bytesread;
   1.954 +
   1.955 +      break;
   1.956 +
   1.957 +    case ATOMTYPE_TREF:
   1.958 +
   1.959 +      if (trak->tref) /* TREF has already been read, more than one is not allowed */
   1.960 +        return -1;
   1.961 +
   1.962 +      if ((trak->tref = (trackReferenceAtom *)mp4malloc(sizeof(trackReferenceAtom))) == NULL)
   1.963 +        return -100;
   1.964 +
   1.965 +      bytesread = readTREF(handle, trak->tref);
   1.966 +      if (bytesread < 0)
   1.967 +        return -1;
   1.968 +      totalbytesread += bytesread;
   1.969 +
   1.970 +      break;
   1.971 +
   1.972 +    case ATOMTYPE_EDTS:
   1.973 +
   1.974 +      if (trak->edts) /* EDTS has already been read, more than one is not allowed */
   1.975 +        return -1;
   1.976 +
   1.977 +      if ((trak->edts = (editListContainerAtom *)mp4malloc(sizeof(editListContainerAtom))) == NULL)
   1.978 +        return -100;
   1.979 +
   1.980 +      bytesread = readEDTS(handle, trak->edts);
   1.981 +      if (bytesread < 0)
   1.982 +        return -1;
   1.983 +      totalbytesread += bytesread;
   1.984 +
   1.985 +      break;
   1.986 +
   1.987 +    case ATOMTYPE_MDIA:
   1.988 +
   1.989 +      if (trak->mdia) /* MDIA has already been read, more than one is not allowed */
   1.990 +        return -1;
   1.991 +
   1.992 +      if ((trak->mdia = (mediaAtom *)mp4malloc(sizeof(mediaAtom))) == NULL)
   1.993 +        return -100;
   1.994 +
   1.995 +      bytesread = readMDIA(handle, trak->mdia);
   1.996 +      if (bytesread < 0)
   1.997 +        return -1;
   1.998 +      totalbytesread += bytesread;
   1.999 +
  1.1000 +      break;
  1.1001 +
  1.1002 +    case ATOMTYPE_UDTA:
  1.1003 +      {
  1.1004 +      if (trak->udta) /* UDTA has already been read */
  1.1005 +          {
  1.1006 +          bytesread = readUnknown(handle);
  1.1007 +          if (bytesread < 0)
  1.1008 +            return -1;
  1.1009 +          totalbytesread += bytesread;
  1.1010 +          break;
  1.1011 +          }
  1.1012 +
  1.1013 +      if ((trak->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL)
  1.1014 +        return -100;
  1.1015 +
  1.1016 +      bytesread = readUDTA(handle, trak->udta);
  1.1017 +      if (bytesread < 0)
  1.1018 +        return -1;
  1.1019 +      totalbytesread += bytesread;
  1.1020 +
  1.1021 +      break;
  1.1022 +      }
  1.1023 +
  1.1024 +    default:
  1.1025 +
  1.1026 +      bytesread = readUnknown(handle);
  1.1027 +      if (bytesread < 0)
  1.1028 +        return -1;
  1.1029 +      totalbytesread += bytesread;
  1.1030 +
  1.1031 +      break;
  1.1032 +    }
  1.1033 +  }
  1.1034 +
  1.1035 +  return totalbytesread;
  1.1036 +}
  1.1037 +
  1.1038 +
  1.1039 +/*
  1.1040 + * Function:
  1.1041 + *
  1.1042 + *   mp4_i32 readUnknown(MP4HandleImp handle)
  1.1043 + *
  1.1044 + * Description:
  1.1045 + *
  1.1046 + *   This function reads one atom of unknown type. Atom contents are
  1.1047 + *   discarded.
  1.1048 + *
  1.1049 + * Parameters:
  1.1050 + *
  1.1051 + *   handle             MP4 library handle
  1.1052 + *
  1.1053 + * Return value:
  1.1054 + *
  1.1055 + *   Negative integer   Error
  1.1056 + *   >= 0               Success. Value tells how many bytes were read.
  1.1057 + *
  1.1058 + */
  1.1059 +mp4_i32 readUnknown(MP4HandleImp handle)
  1.1060 +{
  1.1061 +  mp4_i32 bytesread;
  1.1062 +  mp4_i32 totalbytesread = 0;
  1.1063 +  mp4_u32 size;
  1.1064 +
  1.1065 +
  1.1066 +  bytesread = readData(handle, handle->buf, 4);
  1.1067 +  if (bytesread < 0)
  1.1068 +    return -1;
  1.1069 +  totalbytesread += bytesread;
  1.1070 +
  1.1071 +  size = u32endian(*((mp4_u32 *)handle->buf));
  1.1072 +  if ( size < 4 )
  1.1073 +  {
  1.1074 +  	return -1;
  1.1075 +  }
  1.1076 +
  1.1077 +  if ( handle->file )
  1.1078 +  {
  1.1079 +  	if ( seekFile(handle, size - totalbytesread) < 0 )
  1.1080 +  	{
  1.1081 +  	   return -1;	
  1.1082 +  	}
  1.1083 +  	else
  1.1084 +  	{
  1.1085 +  	   return size;	
  1.1086 +  	}
  1.1087 +  }
  1.1088 +  else
  1.1089 +  {
  1.1090 +  	bytesread = discardData(handle, size - totalbytesread);
  1.1091 +	  if (bytesread < 0)
  1.1092 +    	return -1;
  1.1093 +  	totalbytesread += bytesread;
  1.1094 +  }
  1.1095 +  return totalbytesread;
  1.1096 +}
  1.1097 +
  1.1098 +
  1.1099 +/*
  1.1100 + * Function:
  1.1101 + *
  1.1102 + *   mp4_i32 readTKHD(MP4HandleImp handle,
  1.1103 + *                    trackHeaderAtom *tkhd)
  1.1104 + *
  1.1105 + * Description:
  1.1106 + *
  1.1107 + *   This function parses one TKHD atom.
  1.1108 + *
  1.1109 + * Parameters:
  1.1110 + *
  1.1111 + *   handle             MP4 library handle
  1.1112 + *   tkhd               TKHD pointer
  1.1113 + *
  1.1114 + * Return value:
  1.1115 + *
  1.1116 + *   Negative integer   Error
  1.1117 + *   >= 0               Success. Value tells how many bytes were read.
  1.1118 + *
  1.1119 + */
  1.1120 +mp4_i32 readTKHD(MP4HandleImp handle, trackHeaderAtom *tkhd)
  1.1121 +{
  1.1122 +  mp4_i32 bytesread;
  1.1123 +  mp4_i32 totalbytesread = 0;
  1.1124 +
  1.1125 +
  1.1126 +  if ((tkhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1127 +    return -100;
  1.1128 +
  1.1129 +  bytesread = readFullAtomHeader(handle, tkhd->atomhdr);
  1.1130 +  if (bytesread < 0)
  1.1131 +    return -1;
  1.1132 +  totalbytesread += bytesread;
  1.1133 +
  1.1134 +  if (tkhd->atomhdr->type != ATOMTYPE_TKHD)
  1.1135 +    return -1;
  1.1136 +
  1.1137 +  if (tkhd->atomhdr->version == 1) /* 64 bit */
  1.1138 +  {
  1.1139 +    bytesread = readData(handle, handle->buf, 8);
  1.1140 +    if (bytesread < 0)
  1.1141 +      return -1;
  1.1142 +    tkhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
  1.1143 +    totalbytesread += bytesread;
  1.1144 +
  1.1145 +    bytesread = readData(handle, handle->buf, 8);
  1.1146 +    if (bytesread < 0)
  1.1147 +      return -1;
  1.1148 +    tkhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
  1.1149 +    totalbytesread += bytesread;
  1.1150 +
  1.1151 +    bytesread = readData(handle, handle->buf, 4);
  1.1152 +    if (bytesread < 0)
  1.1153 +      return -1;
  1.1154 +    tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf));
  1.1155 +    totalbytesread += bytesread;
  1.1156 +
  1.1157 +    bytesread = readData(handle, handle->buf, 4);
  1.1158 +    if (bytesread < 0)
  1.1159 +      return -1;
  1.1160 +    tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf));
  1.1161 +    totalbytesread += bytesread;
  1.1162 +
  1.1163 +    bytesread = readData(handle, handle->buf, 8);
  1.1164 +    if (bytesread < 0)
  1.1165 +      return -1;
  1.1166 +    tkhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
  1.1167 +    totalbytesread += bytesread;
  1.1168 +  }
  1.1169 +  else /* 32 bit */
  1.1170 +  {
  1.1171 +    bytesread = readData(handle, handle->buf, 4);
  1.1172 +    if (bytesread < 0)
  1.1173 +      return -1;
  1.1174 +    tkhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
  1.1175 +    totalbytesread += bytesread;
  1.1176 +
  1.1177 +    bytesread = readData(handle, handle->buf, 4);
  1.1178 +    if (bytesread < 0)
  1.1179 +      return -1;
  1.1180 +    tkhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
  1.1181 +    totalbytesread += bytesread;
  1.1182 +
  1.1183 +    bytesread = readData(handle, handle->buf, 4);
  1.1184 +    if (bytesread < 0)
  1.1185 +      return -1;
  1.1186 +    tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf));
  1.1187 +    totalbytesread += bytesread;
  1.1188 +
  1.1189 +    bytesread = readData(handle, handle->buf, 4);
  1.1190 +    if (bytesread < 0)
  1.1191 +      return -1;
  1.1192 +    tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf));
  1.1193 +    totalbytesread += bytesread;
  1.1194 +
  1.1195 +    bytesread = readData(handle, handle->buf, 4);
  1.1196 +    if (bytesread < 0)
  1.1197 +      return -1;
  1.1198 +    tkhd->duration = u32endian(*((mp4_u32 *)handle->buf));
  1.1199 +    totalbytesread += bytesread;
  1.1200 +  }
  1.1201 +
  1.1202 +  bytesread = discardData(handle, 52);
  1.1203 +  if (bytesread < 0)
  1.1204 +    return -1;
  1.1205 +  totalbytesread += bytesread;
  1.1206 +
  1.1207 +  bytesread = readData(handle, handle->buf, 4);
  1.1208 +  if (bytesread < 0)
  1.1209 +    return -1;
  1.1210 +  tkhd->width = u16endian(*((mp4_u16 *)handle->buf));
  1.1211 +  totalbytesread += bytesread;
  1.1212 +
  1.1213 +  bytesread = readData(handle, handle->buf, 4);
  1.1214 +  if (bytesread < 0)
  1.1215 +    return -1;
  1.1216 +  tkhd->height = u16endian(*((mp4_u16 *)handle->buf));
  1.1217 +  totalbytesread += bytesread;
  1.1218 +
  1.1219 +  return totalbytesread;
  1.1220 +}
  1.1221 +
  1.1222 +
  1.1223 +/*
  1.1224 + * Function:
  1.1225 + *
  1.1226 + *   mp4_i32 readTREF(MP4HandleImp handle,
  1.1227 + *                    trackReferenceAtom *tref)
  1.1228 + *
  1.1229 + * Description:
  1.1230 + *
  1.1231 + *   This function parses one TREF atom and discards the contents.
  1.1232 + *
  1.1233 + * Parameters:
  1.1234 + *
  1.1235 + *   handle             MP4 library handle
  1.1236 + *   tref               TREF pointer
  1.1237 + *
  1.1238 + * Return value:
  1.1239 + *
  1.1240 + *   Negative integer   Error
  1.1241 + *   >= 0               Success. Value tells how many bytes were read.
  1.1242 + *
  1.1243 + */
  1.1244 +mp4_i32 readTREF(MP4HandleImp handle, trackReferenceAtom *tref)
  1.1245 +{
  1.1246 +  mp4_i32 bytesread;
  1.1247 +  mp4_i32 totalbytesread = 0;
  1.1248 +
  1.1249 +
  1.1250 +  if ((tref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1251 +    return -100;
  1.1252 +
  1.1253 +  bytesread = readAtomHeader(handle, tref->atomhdr);
  1.1254 +  if (bytesread < 0)
  1.1255 +    return -1;
  1.1256 +  totalbytesread += bytesread;
  1.1257 +
  1.1258 +  if (tref->atomhdr->type != ATOMTYPE_TREF)
  1.1259 +    return -1;
  1.1260 +
  1.1261 +  bytesread = discardData(handle, tref->atomhdr->size - totalbytesread);
  1.1262 +  if (bytesread < 0)
  1.1263 +    return -1;
  1.1264 +  totalbytesread += bytesread;
  1.1265 +
  1.1266 +  return totalbytesread;
  1.1267 +}
  1.1268 +
  1.1269 +
  1.1270 +/*
  1.1271 + * Function:
  1.1272 + *
  1.1273 + *   mp4_i32 readEDTS(MP4HandleImp handle,
  1.1274 + *                    editListContainerAtom *edts)
  1.1275 + *
  1.1276 + * Description:
  1.1277 + *
  1.1278 + *   This function parses one EDTS atom and discards the contents.
  1.1279 + *
  1.1280 + * Parameters:
  1.1281 + *
  1.1282 + *   handle             MP4 library handle
  1.1283 + *   edts               EDTS pointer
  1.1284 + *
  1.1285 + * Return value:
  1.1286 + *
  1.1287 + *   Negative integer   Error
  1.1288 + *   >= 0               Success. Value tells how many bytes were read.
  1.1289 + *
  1.1290 + */
  1.1291 +mp4_i32 readEDTS(MP4HandleImp handle, editListContainerAtom *edts)
  1.1292 +{
  1.1293 +  mp4_i32 bytesread;
  1.1294 +  mp4_i32 totalbytesread = 0;
  1.1295 +
  1.1296 +
  1.1297 +  if ((edts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1298 +    return -100;
  1.1299 +
  1.1300 +  bytesread = readAtomHeader(handle, edts->atomhdr);
  1.1301 +  if (bytesread < 0)
  1.1302 +    return -1;
  1.1303 +  totalbytesread += bytesread;
  1.1304 +
  1.1305 +  if (edts->atomhdr->type != ATOMTYPE_EDTS)
  1.1306 +    return -1;
  1.1307 +
  1.1308 +  bytesread = discardData(handle, edts->atomhdr->size - totalbytesread);
  1.1309 +  if (bytesread < 0)
  1.1310 +    return -1;
  1.1311 +  totalbytesread += bytesread;
  1.1312 +
  1.1313 +  return totalbytesread;
  1.1314 +}
  1.1315 +
  1.1316 +
  1.1317 +/*
  1.1318 + * Function:
  1.1319 + *
  1.1320 + *   mp4_i32 readMDIA(MP4HandleImp handle,
  1.1321 + *                    mediaAtom *mdia)
  1.1322 + *
  1.1323 + * Description:
  1.1324 + *
  1.1325 + *   This function parses one MDIA atom.
  1.1326 + *
  1.1327 + * Parameters:
  1.1328 + *
  1.1329 + *   handle             MP4 library handle
  1.1330 + *   mdia               MDIA pointer
  1.1331 + *
  1.1332 + * Return value:
  1.1333 + *
  1.1334 + *   Negative integer   Error
  1.1335 + *   >= 0               Success. Value tells how many bytes were read.
  1.1336 + *
  1.1337 + */
  1.1338 +mp4_i32 readMDIA(MP4HandleImp handle, mediaAtom *mdia)
  1.1339 +{
  1.1340 +  mp4_i32 bytesread;
  1.1341 +  mp4_i32 totalbytesread = 0;
  1.1342 +
  1.1343 +
  1.1344 +  if ((mdia->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1345 +    return -100;
  1.1346 +
  1.1347 +  bytesread = readAtomHeader(handle, mdia->atomhdr);
  1.1348 +  if (bytesread < 0)
  1.1349 +    return -1;
  1.1350 +  totalbytesread += bytesread;
  1.1351 +
  1.1352 +  if (mdia->atomhdr->type != ATOMTYPE_MDIA)
  1.1353 +    return -1;
  1.1354 +
  1.1355 +
  1.1356 +  while ((mp4_u32)totalbytesread < mdia->atomhdr->size)
  1.1357 +  {
  1.1358 +    mp4_u32 type;
  1.1359 +
  1.1360 +
  1.1361 +    if (peekData(handle, handle->buf, 8) < 0)
  1.1362 +      return -1;
  1.1363 +
  1.1364 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.1365 +
  1.1366 +    switch (type)
  1.1367 +    {
  1.1368 +    case ATOMTYPE_MDHD:
  1.1369 +
  1.1370 +      if (mdia->mdhd) /* MDHD has already been read, more than one is not allowed */
  1.1371 +        return -1;
  1.1372 +
  1.1373 +      if ((mdia->mdhd = (mediaHeaderAtom *)mp4malloc(sizeof(mediaHeaderAtom))) == NULL)
  1.1374 +        return -100;
  1.1375 +
  1.1376 +      bytesread = readMDHD(handle, mdia->mdhd);
  1.1377 +      if (bytesread < 0)
  1.1378 +        return -1;
  1.1379 +      totalbytesread += bytesread;
  1.1380 +
  1.1381 +      break;
  1.1382 +
  1.1383 +    case ATOMTYPE_HDLR:
  1.1384 +
  1.1385 +      if (mdia->hdlr) /* HDLR has already been read, more than one is not allowed */
  1.1386 +        return -1;
  1.1387 +
  1.1388 +      if ((mdia->hdlr = (handlerAtom *)mp4malloc(sizeof(handlerAtom))) == NULL)
  1.1389 +        return -100;
  1.1390 +
  1.1391 +      bytesread = readHDLR(handle, mdia->hdlr);
  1.1392 +      if (bytesread < 0)
  1.1393 +        return -1;
  1.1394 +      totalbytesread += bytesread;
  1.1395 +
  1.1396 +      break;
  1.1397 +
  1.1398 +    case ATOMTYPE_MINF:
  1.1399 +
  1.1400 +      if (mdia->minf) /* MINF has already been read, more than one is not allowed */
  1.1401 +        return -1;
  1.1402 +
  1.1403 +      if ((mdia->minf = (mediaInformationAtom *)mp4malloc(sizeof(mediaInformationAtom))) == NULL)
  1.1404 +        return -100;
  1.1405 +
  1.1406 +      bytesread = readMINF(handle, mdia->minf);
  1.1407 +      if (bytesread < 0)
  1.1408 +        return -1;
  1.1409 +      totalbytesread += bytesread;
  1.1410 +
  1.1411 +      break;
  1.1412 +
  1.1413 +    default:
  1.1414 +
  1.1415 +      bytesread = readUnknown(handle);
  1.1416 +      if (bytesread < 0)
  1.1417 +        return -1;
  1.1418 +      totalbytesread += bytesread;
  1.1419 +
  1.1420 +      break;
  1.1421 +    }
  1.1422 +  }
  1.1423 +
  1.1424 +  return totalbytesread;
  1.1425 +}
  1.1426 +
  1.1427 +
  1.1428 +/*
  1.1429 + * Function:
  1.1430 + *
  1.1431 + *   mp4_i32 readMDHD(MP4HandleImp handle,
  1.1432 + *                    mediaHeaderAtom *mdhd)
  1.1433 + *
  1.1434 + * Description:
  1.1435 + *
  1.1436 + *   This function parses one MDHD atom.
  1.1437 + *
  1.1438 + * Parameters:
  1.1439 + *
  1.1440 + *   handle             MP4 library handle
  1.1441 + *   mdhd               MDHD pointer
  1.1442 + *
  1.1443 + * Return value:
  1.1444 + *
  1.1445 + *   Negative integer   Error
  1.1446 + *   >= 0               Success. Value tells how many bytes were read.
  1.1447 + *
  1.1448 + */
  1.1449 +mp4_i32 readMDHD(MP4HandleImp handle, mediaHeaderAtom *mdhd)
  1.1450 +{
  1.1451 +  mp4_i32 bytesread;
  1.1452 +  mp4_i32 totalbytesread = 0;
  1.1453 +
  1.1454 +
  1.1455 +  if ((mdhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1456 +    return -100;
  1.1457 +
  1.1458 +  bytesread = readFullAtomHeader(handle, mdhd->atomhdr);
  1.1459 +  if (bytesread < 0)
  1.1460 +    return -1;
  1.1461 +  totalbytesread += bytesread;
  1.1462 +
  1.1463 +  if (mdhd->atomhdr->type != ATOMTYPE_MDHD)
  1.1464 +    return -1;
  1.1465 +
  1.1466 +
  1.1467 +  if (mdhd->atomhdr->version == 1) /* 64 bit */
  1.1468 +  {
  1.1469 +    bytesread = readData(handle, handle->buf, 8);
  1.1470 +    if (bytesread < 0)
  1.1471 +      return -1;
  1.1472 +    mdhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
  1.1473 +    totalbytesread += bytesread;
  1.1474 +
  1.1475 +    bytesread = readData(handle, handle->buf, 8);
  1.1476 +    if (bytesread < 0)
  1.1477 +      return -1;
  1.1478 +    mdhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
  1.1479 +    totalbytesread += bytesread;
  1.1480 +
  1.1481 +    bytesread = readData(handle, handle->buf, 4);
  1.1482 +    if (bytesread < 0)
  1.1483 +      return -1;
  1.1484 +    mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
  1.1485 +    totalbytesread += bytesread;
  1.1486 +
  1.1487 +    bytesread = readData(handle, handle->buf, 8);
  1.1488 +    if (bytesread < 0)
  1.1489 +      return -1;
  1.1490 +    mdhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
  1.1491 +    totalbytesread += bytesread;
  1.1492 +  }
  1.1493 +  else /* 32 bit */
  1.1494 +  {
  1.1495 +    bytesread = readData(handle, handle->buf, 4);
  1.1496 +    if (bytesread < 0)
  1.1497 +      return -1;
  1.1498 +    mdhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
  1.1499 +    totalbytesread += bytesread;
  1.1500 +
  1.1501 +    bytesread = readData(handle, handle->buf, 4);
  1.1502 +    if (bytesread < 0)
  1.1503 +      return -1;
  1.1504 +    mdhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
  1.1505 +    totalbytesread += bytesread;
  1.1506 +
  1.1507 +    bytesread = readData(handle, handle->buf, 4);
  1.1508 +    if (bytesread < 0)
  1.1509 +      return -1;
  1.1510 +    mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
  1.1511 +    totalbytesread += bytesread;
  1.1512 +
  1.1513 +    bytesread = readData(handle, handle->buf, 4);
  1.1514 +    if (bytesread < 0)
  1.1515 +      return -1;
  1.1516 +    mdhd->duration = u32endian(*((mp4_u32 *)handle->buf));
  1.1517 +    totalbytesread += bytesread;
  1.1518 +  }
  1.1519 +
  1.1520 +  bytesread = discardData(handle, 4);
  1.1521 +  if (bytesread < 0)
  1.1522 +    return -1;
  1.1523 +  totalbytesread += bytesread;
  1.1524 +
  1.1525 +  return totalbytesread;
  1.1526 +}
  1.1527 +
  1.1528 +
  1.1529 +/*
  1.1530 + * Function:
  1.1531 + *
  1.1532 + *   mp4_i32 readHDLR(MP4HandleImp handle,
  1.1533 + *                    handlerAtom *hdlr)
  1.1534 + *
  1.1535 + * Description:
  1.1536 + *
  1.1537 + *   This function parses one HDLR atom.
  1.1538 + *
  1.1539 + * Parameters:
  1.1540 + *
  1.1541 + *   handle             MP4 library handle
  1.1542 + *   hdlr               HDLR pointer
  1.1543 + *
  1.1544 + * Return value:
  1.1545 + *
  1.1546 + *   Negative integer   Error
  1.1547 + *   >= 0               Success. Value tells how many bytes were read.
  1.1548 + *
  1.1549 + */
  1.1550 +mp4_i32 readHDLR(MP4HandleImp handle, handlerAtom *hdlr)
  1.1551 +{
  1.1552 +  mp4_i32 bytesread;
  1.1553 +  mp4_i32 totalbytesread = 0;
  1.1554 +
  1.1555 +
  1.1556 +  if ((hdlr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1557 +    return -100;
  1.1558 +
  1.1559 +  bytesread = readFullAtomHeader(handle, hdlr->atomhdr);
  1.1560 +  if (bytesread < 0)
  1.1561 +    return -1;
  1.1562 +  totalbytesread += bytesread;
  1.1563 +
  1.1564 +  if (hdlr->atomhdr->type != ATOMTYPE_HDLR)
  1.1565 +    return -1;
  1.1566 +
  1.1567 +
  1.1568 +  bytesread = discardData(handle, 4);
  1.1569 +  if (bytesread < 0)
  1.1570 +    return -1;
  1.1571 +  totalbytesread += bytesread;
  1.1572 +
  1.1573 +  bytesread = readData(handle, handle->buf, 4);
  1.1574 +  if (bytesread < 0)
  1.1575 +    return -1;
  1.1576 +  hdlr->handlerType = u32endian(*((mp4_u32 *)handle->buf));
  1.1577 +  totalbytesread += bytesread;
  1.1578 +
  1.1579 +  bytesread = discardData(handle, hdlr->atomhdr->size - totalbytesread);
  1.1580 +  if (bytesread < 0)
  1.1581 +    return -1;
  1.1582 +  totalbytesread += bytesread;
  1.1583 +
  1.1584 +  return totalbytesread;
  1.1585 +}
  1.1586 +
  1.1587 +
  1.1588 +/*
  1.1589 + * Function:
  1.1590 + *
  1.1591 + *   mp4_i32 readMINF(MP4HandleImp handle,
  1.1592 + *                    mediaInformationAtom *minf)
  1.1593 + *
  1.1594 + * Description:
  1.1595 + *
  1.1596 + *   This function parses one MINF atom.
  1.1597 + *
  1.1598 + * Parameters:
  1.1599 + *
  1.1600 + *   handle             MP4 library handle
  1.1601 + *   minf               MINF pointer
  1.1602 + *
  1.1603 + * Return value:
  1.1604 + *
  1.1605 + *   Negative integer   Error
  1.1606 + *   >= 0               Success. Value tells how many bytes were read.
  1.1607 + *
  1.1608 + */
  1.1609 +mp4_i32 readMINF(MP4HandleImp handle, mediaInformationAtom *minf)
  1.1610 +{
  1.1611 +  mp4_i32 bytesread;
  1.1612 +  mp4_i32 totalbytesread = 0;
  1.1613 +
  1.1614 +
  1.1615 +  if ((minf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1616 +    return -100;
  1.1617 +
  1.1618 +  bytesread = readAtomHeader(handle, minf->atomhdr);
  1.1619 +  if (bytesread < 0)
  1.1620 +    return -1;
  1.1621 +  totalbytesread += bytesread;
  1.1622 +
  1.1623 +  if (minf->atomhdr->type != ATOMTYPE_MINF)
  1.1624 +    return -1;
  1.1625 +
  1.1626 +
  1.1627 +  while ((mp4_u32)totalbytesread < minf->atomhdr->size)
  1.1628 +  {
  1.1629 +    mp4_u32 type;
  1.1630 +
  1.1631 +
  1.1632 +    if (peekData(handle, handle->buf, 8) < 0)
  1.1633 +      return -1;
  1.1634 +
  1.1635 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.1636 +
  1.1637 +    switch (type)
  1.1638 +    {
  1.1639 +    case ATOMTYPE_VMHD:
  1.1640 +
  1.1641 +      if (minf->vmhd || minf->smhd) /* VMHD or SMHD has already been read, more than one is not allowed */
  1.1642 +        return -1;
  1.1643 +
  1.1644 +      if ((minf->vmhd = (videoMediaHeaderAtom *)mp4malloc(sizeof(videoMediaHeaderAtom))) == NULL)
  1.1645 +        return -100;
  1.1646 +
  1.1647 +      bytesread = readVMHD(handle, minf->vmhd);
  1.1648 +      if (bytesread < 0)
  1.1649 +        return -1;
  1.1650 +      totalbytesread += bytesread;
  1.1651 +
  1.1652 +      break;
  1.1653 +
  1.1654 +    case ATOMTYPE_SMHD:
  1.1655 +
  1.1656 +      if (minf->smhd || minf->vmhd) /* SMHD or VMHD has already been read, more than one is not allowed */
  1.1657 +        return -1;
  1.1658 +
  1.1659 +      if ((minf->smhd = (soundMediaHeaderAtom *)mp4malloc(sizeof(soundMediaHeaderAtom))) == NULL)
  1.1660 +        return -100;
  1.1661 +
  1.1662 +      bytesread = readSMHD(handle, minf->smhd);
  1.1663 +      if (bytesread < 0)
  1.1664 +        return -1;
  1.1665 +      totalbytesread += bytesread;
  1.1666 +
  1.1667 +      break;
  1.1668 +
  1.1669 +    case ATOMTYPE_DINF:
  1.1670 +
  1.1671 +      if (minf->dinf) /* DINF has already been read, more than one is not allowed */
  1.1672 +        return -1;
  1.1673 +
  1.1674 +      if ((minf->dinf = (dataInformationAtom *)mp4malloc(sizeof(dataInformationAtom))) == NULL)
  1.1675 +        return -100;
  1.1676 +
  1.1677 +      bytesread = readDINF(handle, minf->dinf);
  1.1678 +      if (bytesread < 0)
  1.1679 +        return -1;
  1.1680 +      totalbytesread += bytesread;
  1.1681 +
  1.1682 +      break;
  1.1683 +
  1.1684 +    case ATOMTYPE_STBL:
  1.1685 +
  1.1686 +      if (minf->stbl) /* STBL has already been read, more than one is not allowed */
  1.1687 +        return -1;
  1.1688 +
  1.1689 +      if ((minf->stbl = (sampleTableAtom *)mp4malloc(sizeof(sampleTableAtom))) == NULL)
  1.1690 +        return -100;
  1.1691 +
  1.1692 +      bytesread = readSTBL(handle, minf->stbl);
  1.1693 +      if (bytesread < 0)
  1.1694 +        return -1;
  1.1695 +      totalbytesread += bytesread;
  1.1696 +
  1.1697 +      break;
  1.1698 +
  1.1699 +    default:
  1.1700 +
  1.1701 +      bytesread = readUnknown(handle);
  1.1702 +      if (bytesread < 0)
  1.1703 +        return -1;
  1.1704 +      totalbytesread += bytesread;
  1.1705 +
  1.1706 +      break;
  1.1707 +    }
  1.1708 +  }
  1.1709 +
  1.1710 +  return totalbytesread;
  1.1711 +}
  1.1712 +
  1.1713 +
  1.1714 +/*
  1.1715 + * Function:
  1.1716 + *
  1.1717 + *   mp4_i32 readVMHD(MP4HandleImp handle,
  1.1718 + *                    videoMediaHeaderAtom *vmhd)
  1.1719 + *
  1.1720 + * Description:
  1.1721 + *
  1.1722 + *   This function parses one VMHD atom.
  1.1723 + *
  1.1724 + * Parameters:
  1.1725 + *
  1.1726 + *   handle             MP4 library handle
  1.1727 + *   vmhd               VMHD pointer
  1.1728 + *
  1.1729 + * Return value:
  1.1730 + *
  1.1731 + *   Negative integer   Error
  1.1732 + *   >= 0               Success. Value tells how many bytes were read.
  1.1733 + *
  1.1734 + */
  1.1735 +mp4_i32 readVMHD(MP4HandleImp handle, videoMediaHeaderAtom *vmhd)
  1.1736 +{
  1.1737 +  mp4_i32 bytesread;
  1.1738 +  mp4_i32 totalbytesread = 0;
  1.1739 +
  1.1740 +
  1.1741 +  if ((vmhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1742 +    return -100;
  1.1743 +
  1.1744 +  bytesread = readFullAtomHeader(handle, vmhd->atomhdr);
  1.1745 +  if (bytesread < 0)
  1.1746 +    return -1;
  1.1747 +  totalbytesread += bytesread;
  1.1748 +
  1.1749 +  if (vmhd->atomhdr->type != ATOMTYPE_VMHD)
  1.1750 +    return -1;
  1.1751 +
  1.1752 +
  1.1753 +  bytesread = discardData(handle, vmhd->atomhdr->size - totalbytesread);
  1.1754 +  if (bytesread < 0)
  1.1755 +    return -1;
  1.1756 +  totalbytesread += bytesread;
  1.1757 +
  1.1758 +  return totalbytesread;
  1.1759 +}
  1.1760 +
  1.1761 +
  1.1762 +/*
  1.1763 + * Function:
  1.1764 + *
  1.1765 + *   mp4_i32 readSMHD(MP4HandleImp handle,
  1.1766 + *                    soundMediaHeaderAtom *smhd)
  1.1767 + *
  1.1768 + * Description:
  1.1769 + *
  1.1770 + *   This function parses one SMHD atom.
  1.1771 + *
  1.1772 + * Parameters:
  1.1773 + *
  1.1774 + *   handle             MP4 library handle
  1.1775 + *   smhd               SMHD pointer
  1.1776 + *
  1.1777 + * Return value:
  1.1778 + *
  1.1779 + *   Negative integer   Error
  1.1780 + *   >= 0               Success. Value tells how many bytes were read.
  1.1781 + *
  1.1782 + */
  1.1783 +mp4_i32 readSMHD(MP4HandleImp handle, soundMediaHeaderAtom *smhd)
  1.1784 +{
  1.1785 +  mp4_i32 bytesread;
  1.1786 +  mp4_i32 totalbytesread = 0;
  1.1787 +
  1.1788 +
  1.1789 +  if ((smhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1790 +    return -100;
  1.1791 +
  1.1792 +  bytesread = readFullAtomHeader(handle, smhd->atomhdr);
  1.1793 +  if (bytesread < 0)
  1.1794 +    return -1;
  1.1795 +  totalbytesread += bytesread;
  1.1796 +
  1.1797 +  if (smhd->atomhdr->type != ATOMTYPE_SMHD)
  1.1798 +    return -1;
  1.1799 +
  1.1800 +
  1.1801 +  bytesread = discardData(handle, smhd->atomhdr->size - totalbytesread);
  1.1802 +  if (bytesread < 0)
  1.1803 +    return -1;
  1.1804 +  totalbytesread += bytesread;
  1.1805 +
  1.1806 +  return totalbytesread;
  1.1807 +}
  1.1808 +
  1.1809 +
  1.1810 +/*
  1.1811 + * Function:
  1.1812 + *
  1.1813 + *   mp4_i32 readDINF(MP4HandleImp handle,
  1.1814 + *                    dataInformationAtom *dinf)
  1.1815 + *
  1.1816 + * Description:
  1.1817 + *
  1.1818 + *   This function parses one DINF atom.
  1.1819 + *
  1.1820 + * Parameters:
  1.1821 + *
  1.1822 + *   handle             MP4 library handle
  1.1823 + *   dinf               DINF pointer
  1.1824 + *
  1.1825 + * Return value:
  1.1826 + *
  1.1827 + *   Negative integer   Error
  1.1828 + *   >= 0               Success. Value tells how many bytes were read.
  1.1829 + *
  1.1830 + */
  1.1831 +mp4_i32 readDINF(MP4HandleImp handle, dataInformationAtom *dinf)
  1.1832 +{
  1.1833 +  mp4_i32 bytesread;
  1.1834 +  mp4_i32 totalbytesread = 0;
  1.1835 +
  1.1836 +
  1.1837 +  if ((dinf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1838 +    return -100;
  1.1839 +
  1.1840 +  bytesread = readAtomHeader(handle, dinf->atomhdr);
  1.1841 +  if (bytesread < 0)
  1.1842 +    return -1;
  1.1843 +  totalbytesread += bytesread;
  1.1844 +
  1.1845 +  if (dinf->atomhdr->type != ATOMTYPE_DINF)
  1.1846 +    return -1;
  1.1847 +
  1.1848 +
  1.1849 +  while ((mp4_u32)totalbytesread < dinf->atomhdr->size)
  1.1850 +  {
  1.1851 +    mp4_u32 type;
  1.1852 +
  1.1853 +
  1.1854 +    if (peekData(handle, handle->buf, 8) < 0)
  1.1855 +      return -1;
  1.1856 +
  1.1857 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.1858 +
  1.1859 +    switch (type)
  1.1860 +    {
  1.1861 +    case ATOMTYPE_DREF:
  1.1862 +
  1.1863 +      if (dinf->dref) /* DINF has already been read, more than one is not allowed */
  1.1864 +        return -1;
  1.1865 +
  1.1866 +      if ((dinf->dref = (dataReferenceAtom *)mp4malloc(sizeof(dataReferenceAtom))) == NULL)
  1.1867 +        return -100;
  1.1868 +
  1.1869 +      bytesread = readDREF(handle, dinf->dref);
  1.1870 +      if (bytesread < 0)
  1.1871 +        return -1;
  1.1872 +      totalbytesread += bytesread;
  1.1873 +
  1.1874 +      break;
  1.1875 +
  1.1876 +    default:
  1.1877 +
  1.1878 +      return -1;
  1.1879 +    }
  1.1880 +  }
  1.1881 +
  1.1882 +  return totalbytesread;
  1.1883 +}
  1.1884 +
  1.1885 +
  1.1886 +/*
  1.1887 + * Function:
  1.1888 + *
  1.1889 + *   mp4_i32 readDREF(MP4HandleImp handle,
  1.1890 + *                    dataReferenceAtom *dref)
  1.1891 + *
  1.1892 + * Description:
  1.1893 + *
  1.1894 + *   This function parses one DREF atom.
  1.1895 + *
  1.1896 + * Parameters:
  1.1897 + *
  1.1898 + *   handle             MP4 library handle
  1.1899 + *   dref               DREF pointer
  1.1900 + *
  1.1901 + * Return value:
  1.1902 + *
  1.1903 + *   Negative integer   Error
  1.1904 + *   >= 0               Success. Value tells how many bytes were read.
  1.1905 + *
  1.1906 + */
  1.1907 +mp4_i32 readDREF(MP4HandleImp handle, dataReferenceAtom *dref)
  1.1908 +{
  1.1909 +  mp4_i32 bytesread;
  1.1910 +  mp4_i32 totalbytesread = 0;
  1.1911 +
  1.1912 +
  1.1913 +  if ((dref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1914 +    return -100;
  1.1915 +
  1.1916 +  bytesread = readFullAtomHeader(handle, dref->atomhdr);
  1.1917 +  if (bytesread < 0)
  1.1918 +    return -1;
  1.1919 +  totalbytesread += bytesread;
  1.1920 +
  1.1921 +  if (dref->atomhdr->type != ATOMTYPE_DREF)
  1.1922 +    return -1;
  1.1923 +
  1.1924 +
  1.1925 +  bytesread = readData(handle, handle->buf, 4);
  1.1926 +  if (bytesread < 0)
  1.1927 +    return -1;
  1.1928 +  dref->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.1929 +  totalbytesread += bytesread;
  1.1930 +
  1.1931 +  if (dref->entryCount != 1)
  1.1932 +    return -1;
  1.1933 +
  1.1934 +  while ((mp4_u32)totalbytesread < dref->atomhdr->size)
  1.1935 +  {
  1.1936 +    bytesread = readUnknown(handle);
  1.1937 +    if (bytesread < 0)
  1.1938 +      return -1;
  1.1939 +    totalbytesread += bytesread;
  1.1940 +  }
  1.1941 +  return totalbytesread;
  1.1942 +}
  1.1943 +
  1.1944 +
  1.1945 +/*
  1.1946 + * Function:
  1.1947 + *
  1.1948 + *   mp4_i32 readURL(MP4HandleImp handle,
  1.1949 + *                   dataEntryURLAtom *url)
  1.1950 + *
  1.1951 + * Description:
  1.1952 + *
  1.1953 + *   This function parses one URL atom.
  1.1954 + *
  1.1955 + * Parameters:
  1.1956 + *
  1.1957 + *   handle             MP4 library handle
  1.1958 + *   url                URL pointer
  1.1959 + *
  1.1960 + * Return value:
  1.1961 + *
  1.1962 + *   Negative integer   Error
  1.1963 + *   >= 0               Success. Value tells how many bytes were read.
  1.1964 + *
  1.1965 + */
  1.1966 +mp4_i32 readURL(MP4HandleImp handle, dataEntryURLAtom *url)
  1.1967 +{
  1.1968 +  mp4_i32 bytesread;
  1.1969 +  mp4_i32 totalbytesread = 0;
  1.1970 +
  1.1971 +
  1.1972 +  if ((url->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.1973 +    return -100;
  1.1974 +
  1.1975 +  bytesread = readFullAtomHeader(handle, url->atomhdr);
  1.1976 +  if (bytesread < 0)
  1.1977 +    return -1;
  1.1978 +  totalbytesread += bytesread;
  1.1979 +
  1.1980 +  if (url->atomhdr->type != ATOMTYPE_URL)
  1.1981 +    return -1;
  1.1982 +
  1.1983 +
  1.1984 +  if (!(url->atomhdr->flags[0] == 0x00 &&
  1.1985 +        url->atomhdr->flags[1] == 0x00 &&
  1.1986 +        url->atomhdr->flags[2] == 0x01))
  1.1987 +    return -1;
  1.1988 +
  1.1989 +  return totalbytesread;
  1.1990 +}
  1.1991 +
  1.1992 +
  1.1993 +/*
  1.1994 + * Function:
  1.1995 + *
  1.1996 + *   mp4_i32 readURN(MP4HandleImp handle,
  1.1997 + *                   dataEntryURNAtom *urn)
  1.1998 + *
  1.1999 + * Description:
  1.2000 + *
  1.2001 + *   This function parses one URN atom.
  1.2002 + *
  1.2003 + * Parameters:
  1.2004 + *
  1.2005 + *   handle             MP4 library handle
  1.2006 + *   urn                URN pointer
  1.2007 + *
  1.2008 + * Return value:
  1.2009 + *
  1.2010 + *   Negative integer   Error
  1.2011 + *   >= 0               Success. Value tells how many bytes were read.
  1.2012 + *
  1.2013 + */
  1.2014 +mp4_i32 readURN(MP4HandleImp handle, dataEntryURNAtom *urn)
  1.2015 +{
  1.2016 +  mp4_i32 bytesread;
  1.2017 +  mp4_i32 totalbytesread = 0;
  1.2018 +
  1.2019 +
  1.2020 +  if ((urn->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2021 +    return -100;
  1.2022 +
  1.2023 +  bytesread = readFullAtomHeader(handle, urn->atomhdr);
  1.2024 +  if (bytesread < 0)
  1.2025 +    return -1;
  1.2026 +  totalbytesread += bytesread;
  1.2027 +
  1.2028 +  if (urn->atomhdr->type != ATOMTYPE_URN)
  1.2029 +    return -1;
  1.2030 +
  1.2031 +
  1.2032 +  if (!(urn->atomhdr->flags[0] == 0x00 &&
  1.2033 +        urn->atomhdr->flags[1] == 0x00 &&
  1.2034 +        urn->atomhdr->flags[2] == 0x01))
  1.2035 +    return -1;
  1.2036 +
  1.2037 +  return totalbytesread;
  1.2038 +}
  1.2039 +
  1.2040 +
  1.2041 +/*
  1.2042 + * Function:
  1.2043 + *
  1.2044 + *   mp4_i32 readSTBL(MP4HandleImp handle,
  1.2045 + *                    sampleTableAtom *stbl)
  1.2046 + *
  1.2047 + * Description:
  1.2048 + *
  1.2049 + *   This function parses one STBL atom.
  1.2050 + *
  1.2051 + * Parameters:
  1.2052 + *
  1.2053 + *   handle             MP4 library handle
  1.2054 + *   stbl               STBL pointer
  1.2055 + *
  1.2056 + * Return value:
  1.2057 + *
  1.2058 + *   Negative integer   Error
  1.2059 + *   >= 0               Success. Value tells how many bytes were read.
  1.2060 + *
  1.2061 + */
  1.2062 +mp4_i32 readSTBL(MP4HandleImp handle, sampleTableAtom *stbl)
  1.2063 +{
  1.2064 +  mp4_i32 bytesread;
  1.2065 +  mp4_i32 totalbytesread = 0;
  1.2066 +
  1.2067 +
  1.2068 +  if ((stbl->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2069 +    return -100;
  1.2070 +
  1.2071 +  bytesread = readAtomHeader(handle, stbl->atomhdr);
  1.2072 +  if (bytesread < 0)
  1.2073 +    return -1;
  1.2074 +  totalbytesread += bytesread;
  1.2075 +
  1.2076 +  if (stbl->atomhdr->type != ATOMTYPE_STBL)
  1.2077 +    return -1;
  1.2078 +
  1.2079 +
  1.2080 +  while ((mp4_u32)totalbytesread < stbl->atomhdr->size)
  1.2081 +  {
  1.2082 +    mp4_u32 type;
  1.2083 +
  1.2084 +
  1.2085 +    if (peekData(handle, handle->buf, 8) < 0)
  1.2086 +      return -1;
  1.2087 +
  1.2088 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.2089 +
  1.2090 +    switch (type)
  1.2091 +    {
  1.2092 +    case ATOMTYPE_STTS:
  1.2093 +
  1.2094 +      if (stbl->stts) /* STTS has already been read, more than one is not allowed */
  1.2095 +        return -1;
  1.2096 +
  1.2097 +      if ((stbl->stts = (timeToSampleAtom *)mp4malloc(sizeof(timeToSampleAtom))) == NULL)
  1.2098 +        return -100;
  1.2099 +
  1.2100 +      bytesread = readSTTS(handle, stbl->stts);
  1.2101 +      if (bytesread < 0)
  1.2102 +        return -1;
  1.2103 +      totalbytesread += bytesread;
  1.2104 +
  1.2105 +      break;
  1.2106 +
  1.2107 +    case ATOMTYPE_CTTS:
  1.2108 +
  1.2109 +      if (stbl->ctts) /* CTTS has already been read, more than one is not allowed */
  1.2110 +        return -1;
  1.2111 +
  1.2112 +      if ((stbl->ctts = (compositionTimeToSampleAtom *)mp4malloc(sizeof(compositionTimeToSampleAtom))) == NULL)
  1.2113 +        return -100;
  1.2114 +
  1.2115 +      bytesread = readCTTS(handle, stbl->ctts);
  1.2116 +      if (bytesread < 0)
  1.2117 +        return -1;
  1.2118 +      totalbytesread += bytesread;
  1.2119 +
  1.2120 +      break;
  1.2121 +
  1.2122 +    case ATOMTYPE_STSS:
  1.2123 +
  1.2124 +      if (stbl->stss) /* STSS has already been read, more than one is not allowed */
  1.2125 +        return -1;
  1.2126 +
  1.2127 +      if ((stbl->stss = (syncSampleAtom *)mp4malloc(sizeof(syncSampleAtom))) == NULL)
  1.2128 +        return -100;
  1.2129 +
  1.2130 +      bytesread = readSTSS(handle, stbl->stss);
  1.2131 +      if (bytesread < 0)
  1.2132 +        return -1;
  1.2133 +      totalbytesread += bytesread;
  1.2134 +
  1.2135 +      break;
  1.2136 +
  1.2137 +    case ATOMTYPE_STSD:
  1.2138 +
  1.2139 +      if (stbl->stsd) /* STSD has already been read, more than one is not allowed */
  1.2140 +        return -1;
  1.2141 +
  1.2142 +      if ((stbl->stsd = (sampleDescriptionAtom *)mp4malloc(sizeof(sampleDescriptionAtom))) == NULL)
  1.2143 +        return -100;
  1.2144 +
  1.2145 +      bytesread = readSTSD(handle, stbl->stsd);
  1.2146 +      if (bytesread < 0)
  1.2147 +        return -1;
  1.2148 +      totalbytesread += bytesread;
  1.2149 +
  1.2150 +      break;
  1.2151 +
  1.2152 +    case ATOMTYPE_STSZ:
  1.2153 +
  1.2154 +      if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */
  1.2155 +        return -1;
  1.2156 +
  1.2157 +      if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL)
  1.2158 +        return -100;
  1.2159 +
  1.2160 +      bytesread = readSTSZ(handle, stbl->stsz);
  1.2161 +      if (bytesread < 0)
  1.2162 +        return -1;
  1.2163 +      totalbytesread += bytesread;
  1.2164 +
  1.2165 +      break;
  1.2166 +
  1.2167 +    case ATOMTYPE_STZ2:
  1.2168 +
  1.2169 +      if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */
  1.2170 +        return -1;
  1.2171 +
  1.2172 +      if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL)
  1.2173 +        return -100;
  1.2174 +
  1.2175 +      bytesread = readSTZ2(handle, stbl->stsz);
  1.2176 +      if (bytesread < 0)
  1.2177 +        return -1;
  1.2178 +      totalbytesread += bytesread;
  1.2179 +
  1.2180 +      break;
  1.2181 +
  1.2182 +    case ATOMTYPE_STSC:
  1.2183 +
  1.2184 +      if (stbl->stsc) /* STSC has already been read, more than one is not allowed */
  1.2185 +        return -1;
  1.2186 +
  1.2187 +      if ((stbl->stsc = (sampleToChunkAtom *)mp4malloc(sizeof(sampleToChunkAtom))) == NULL)
  1.2188 +        return -100;
  1.2189 +
  1.2190 +      bytesread = readSTSC(handle, stbl->stsc);
  1.2191 +      if (bytesread < 0)
  1.2192 +        return -1;
  1.2193 +      totalbytesread += bytesread;
  1.2194 +
  1.2195 +      break;
  1.2196 +
  1.2197 +    case ATOMTYPE_STCO:
  1.2198 +
  1.2199 +      if (stbl->stco) /* STCO or CO64 has already been read, more than one is not allowed */
  1.2200 +        return -1;
  1.2201 +
  1.2202 +      if ((stbl->stco = (chunkOffsetAtom *)mp4malloc(sizeof(chunkOffsetAtom))) == NULL)
  1.2203 +        return -100;
  1.2204 +      
  1.2205 +      stbl->is32BitOffsets = ETrue;
  1.2206 +      bytesread = readSTCO(handle, stbl->stco);
  1.2207 +      if (bytesread < 0)
  1.2208 +        return -1;
  1.2209 +      totalbytesread += bytesread;
  1.2210 +
  1.2211 +      break;
  1.2212 +
  1.2213 +    case ATOMTYPE_CO64:
  1.2214 +
  1.2215 +      if (stbl->stco64) /* STCO or CO64 has already been read, more than one is not allowed */
  1.2216 +        return -1;
  1.2217 +
  1.2218 +      if ((stbl->stco64 = (chunkOffset64Atom *)mp4malloc(sizeof(chunkOffset64Atom))) == NULL)
  1.2219 +        return -100;
  1.2220 +      
  1.2221 +      stbl->is32BitOffsets = EFalse;
  1.2222 +      bytesread = readCO64(handle, stbl->stco64);
  1.2223 +      if (bytesread < 0)
  1.2224 +        return -1;
  1.2225 +      totalbytesread += bytesread;
  1.2226 +
  1.2227 +      break;
  1.2228 +
  1.2229 +    case ATOMTYPE_SDTP:
  1.2230 +      if (stbl->sdtp) /* SDTP has already been read, more than one is not allowed */
  1.2231 +        return -1;
  1.2232 +      
  1.2233 +      if ((stbl->sdtp = (sampleDependencyAtom *)mp4malloc(sizeof(sampleDependencyAtom))) == NULL)
  1.2234 +        return -100;
  1.2235 +
  1.2236 +      if (!stbl->stsz)
  1.2237 +    	  {
  1.2238 +    	  return -1;
  1.2239 +    	  }
  1.2240 +
  1.2241 +	  // sample_count of SDTP is taken from the sample_count in the Sample Size Box ('stsz') or
  1.2242 +	  // Compact Sample Size Box (‘stz2’). 
  1.2243 +	  bytesread = readSDTP(handle, stbl->sdtp, stbl->stsz->sampleCount);
  1.2244 +    	  
  1.2245 +      if (bytesread < 0)
  1.2246 +        return -1;
  1.2247 +      totalbytesread += bytesread;
  1.2248 +      break;
  1.2249 +
  1.2250 +    default: /* Other atoms are not needed */
  1.2251 +
  1.2252 +      bytesread = readUnknown(handle);
  1.2253 +      if (bytesread < 0)
  1.2254 +        return -1;
  1.2255 +      totalbytesread += bytesread;
  1.2256 +
  1.2257 +      break;
  1.2258 +    }
  1.2259 +  }
  1.2260 +
  1.2261 +  return totalbytesread;
  1.2262 +}
  1.2263 +
  1.2264 +
  1.2265 +/*
  1.2266 + * Function:
  1.2267 + *
  1.2268 + *   mp4_i32 readSTTS(MP4HandleImp handle,
  1.2269 + *                    timeToSampleAtom *stts)
  1.2270 + *
  1.2271 + * Description:
  1.2272 + *
  1.2273 + *   This function parses one STTS atom.
  1.2274 + *
  1.2275 + * Parameters:
  1.2276 + *
  1.2277 + *   handle             MP4 library handle
  1.2278 + *   stts               STTS pointer
  1.2279 + *
  1.2280 + * Return value:
  1.2281 + *
  1.2282 + *   Negative integer   Error
  1.2283 + *   >= 0               Success. Value tells how many bytes were read.
  1.2284 + *
  1.2285 + */
  1.2286 +mp4_i32 readSTTS(MP4HandleImp handle, timeToSampleAtom *stts)
  1.2287 +{
  1.2288 +  mp4_i32 bytesread;
  1.2289 +  mp4_i32 totalbytesread = 0;
  1.2290 +  mp4_u32 i;
  1.2291 +
  1.2292 +
  1.2293 +  if ((stts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2294 +    return -100;
  1.2295 +
  1.2296 +  bytesread = readFullAtomHeader(handle, stts->atomhdr);
  1.2297 +  if (bytesread < 0)
  1.2298 +    return -1;
  1.2299 +  totalbytesread += bytesread;
  1.2300 +
  1.2301 +  if (stts->atomhdr->type != ATOMTYPE_STTS)
  1.2302 +    return -1;
  1.2303 +
  1.2304 +
  1.2305 +  bytesread = readData(handle, handle->buf, 4);
  1.2306 +  if (bytesread < 0)
  1.2307 +    return -1;
  1.2308 +  stts->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.2309 +  totalbytesread += bytesread;
  1.2310 +  
  1.2311 +  if ( stts->entryCount )
  1.2312 +  {
  1.2313 +	  stts->sampleCount = (mp4_u32 *)mp4malloc(stts->entryCount * sizeof(mp4_u32));
  1.2314 +	  if (stts->sampleCount == NULL)
  1.2315 +	    return -1;
  1.2316 +	  stts->sampleDelta = (mp4_i32 *)mp4malloc(stts->entryCount * sizeof(mp4_i32));
  1.2317 +	  if (stts->sampleDelta == NULL)
  1.2318 +	    return -1;
  1.2319 +
  1.2320 +	  for (i = 0; i < stts->entryCount; i++)
  1.2321 +	  {
  1.2322 +	    bytesread = readData(handle, handle->buf, 8);
  1.2323 +	    if (bytesread < 0)
  1.2324 +	      return -1;
  1.2325 +
  1.2326 +	    stts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf));
  1.2327 +	    stts->sampleDelta[i] = i32endian(*((mp4_i32 *)(handle->buf+4)));
  1.2328 +
  1.2329 +	    totalbytesread += bytesread;
  1.2330 +	  }
  1.2331 +  }
  1.2332 +
  1.2333 +  return totalbytesread;
  1.2334 +}
  1.2335 +
  1.2336 +
  1.2337 +/*
  1.2338 + * Function:
  1.2339 + *
  1.2340 + *   mp4_i32 readCTTS(MP4HandleImp handle,
  1.2341 + *                    compositionTimeToSampleAtom *ctts)
  1.2342 + *
  1.2343 + * Description:
  1.2344 + *
  1.2345 + *   This function parses one CTTS atom.
  1.2346 + *
  1.2347 + * Parameters:
  1.2348 + *
  1.2349 + *   handle             MP4 library handle
  1.2350 + *   ctts               CTTS pointer
  1.2351 + *
  1.2352 + * Return value:
  1.2353 + *
  1.2354 + *   Negative integer   Error
  1.2355 + *   >= 0               Success. Value tells how many bytes were read.
  1.2356 + *
  1.2357 + */
  1.2358 +mp4_i32 readCTTS(MP4HandleImp handle, compositionTimeToSampleAtom *ctts)
  1.2359 +{
  1.2360 +  mp4_i32 bytesread;
  1.2361 +  mp4_i32 totalbytesread = 0;
  1.2362 +  mp4_u32 i;
  1.2363 +
  1.2364 +
  1.2365 +  if ((ctts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2366 +    return -100;
  1.2367 +
  1.2368 +  bytesread = readFullAtomHeader(handle, ctts->atomhdr);
  1.2369 +  if (bytesread < 0)
  1.2370 +    return -1;
  1.2371 +  totalbytesread += bytesread;
  1.2372 +
  1.2373 +  if (ctts->atomhdr->type != ATOMTYPE_CTTS)
  1.2374 +    return -1;
  1.2375 +
  1.2376 +  bytesread = readData(handle, handle->buf, 4);
  1.2377 +  if (bytesread < 0)
  1.2378 +    return -1;
  1.2379 +  ctts->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.2380 +  totalbytesread += bytesread;
  1.2381 +
  1.2382 +  if ( ctts->entryCount )
  1.2383 +  {
  1.2384 +	  ctts->sampleCount = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32));
  1.2385 +	  if (ctts->sampleCount == NULL)
  1.2386 +	    return -1;
  1.2387 +	  ctts->sampleOffset = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32));
  1.2388 +	  if (ctts->sampleOffset == NULL)
  1.2389 +	    return -1;
  1.2390 +
  1.2391 +	  for (i = 0; i < ctts->entryCount; i++)
  1.2392 +	  {
  1.2393 +	    bytesread = readData(handle, handle->buf, 8);
  1.2394 +	    if (bytesread < 0)
  1.2395 +	      return -1;
  1.2396 +
  1.2397 +	    ctts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf));
  1.2398 +	    ctts->sampleOffset[i] = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.2399 +
  1.2400 +	    totalbytesread += bytesread;
  1.2401 +	  }
  1.2402 +  }
  1.2403 +  return totalbytesread;
  1.2404 +}
  1.2405 +
  1.2406 +
  1.2407 +/*
  1.2408 + * Function:
  1.2409 + *
  1.2410 + *   mp4_i32 readSTSS(MP4HandleImp handle,
  1.2411 + *                    syncSampleAtom *stss)
  1.2412 + *
  1.2413 + * Description:
  1.2414 + *
  1.2415 + *   This function parses one STSS atom.
  1.2416 + *
  1.2417 + * Parameters:
  1.2418 + *
  1.2419 + *   handle             MP4 library handle
  1.2420 + *   stss               STSS pointer
  1.2421 + *
  1.2422 + * Return value:
  1.2423 + *
  1.2424 + *   Negative integer   Error
  1.2425 + *   >= 0               Success. Value tells how many bytes were read.
  1.2426 + *
  1.2427 + */
  1.2428 +mp4_i32 readSTSS(MP4HandleImp handle, syncSampleAtom *stss)
  1.2429 +{
  1.2430 +  mp4_i32 bytesread;
  1.2431 +  mp4_i32 totalbytesread = 0;
  1.2432 +  mp4_u32 i;
  1.2433 +
  1.2434 +
  1.2435 +  if ((stss->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2436 +    return -100;
  1.2437 +
  1.2438 +  bytesread = readFullAtomHeader(handle, stss->atomhdr);
  1.2439 +  if (bytesread < 0)
  1.2440 +    return -1;
  1.2441 +  totalbytesread += bytesread;
  1.2442 +
  1.2443 +  if (stss->atomhdr->type != ATOMTYPE_STSS)
  1.2444 +    return -1;
  1.2445 +
  1.2446 +
  1.2447 +  bytesread = readData(handle, handle->buf, 4);
  1.2448 +  if (bytesread < 0)
  1.2449 +    return -1;
  1.2450 +  stss->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.2451 +  totalbytesread += bytesread;
  1.2452 +
  1.2453 +  if ( stss->entryCount )
  1.2454 +  {
  1.2455 +	  stss->sampleNumber = (mp4_u32 *)mp4malloc(stss->entryCount * sizeof(mp4_u32));
  1.2456 +	  if (stss->sampleNumber == NULL)
  1.2457 +	    return -1;
  1.2458 +
  1.2459 +	  for (i = 0; i < stss->entryCount; i++)
  1.2460 +	  {
  1.2461 +	    bytesread = readData(handle, handle->buf, 4);
  1.2462 +	    if (bytesread < 0)
  1.2463 +	      return -1;
  1.2464 +
  1.2465 +	    stss->sampleNumber[i] = u32endian(*((mp4_u32 *)handle->buf));
  1.2466 +
  1.2467 +	    totalbytesread += bytesread;
  1.2468 +	  }
  1.2469 +  }
  1.2470 +
  1.2471 +  return totalbytesread;
  1.2472 +}
  1.2473 +
  1.2474 +
  1.2475 +/*
  1.2476 + * Function:
  1.2477 + *
  1.2478 + *   mp4_i32 readSTSD(MP4HandleImp handle,
  1.2479 + *                    sampleDescriptionAtom *stsd)
  1.2480 + *
  1.2481 + * Description:
  1.2482 + *
  1.2483 + *   This function parses one STSD atom.
  1.2484 + *
  1.2485 + * Parameters:
  1.2486 + *
  1.2487 + *   handle             MP4 library handle
  1.2488 + *   stsd               STSD pointer
  1.2489 + *
  1.2490 + * Return value:
  1.2491 + *
  1.2492 + *   Negative integer   Error
  1.2493 + *   >= 0               Success. Value tells how many bytes were read.
  1.2494 + *
  1.2495 + */
  1.2496 +mp4_i32 readSTSD(MP4HandleImp handle, sampleDescriptionAtom *stsd)
  1.2497 +	{
  1.2498 +	mp4_i32 bytesread;
  1.2499 +	mp4_i32 totalbytesread = 0;
  1.2500 +	mp4_u32 totalsampleentriesread = 0;
  1.2501 +	mp4_u32 unknownsampleentriesread = 0;
  1.2502 +	mp4_bool skipentries = 0;
  1.2503 +
  1.2504 +	if ((stsd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2505 +        {
  1.2506 +        // for memory cleanup set entrycount to allocated num of entries.
  1.2507 +        stsd->entryCount = totalsampleentriesread;
  1.2508 +	    return -100;
  1.2509 +        }
  1.2510 +
  1.2511 +	bytesread = readFullAtomHeader(handle, stsd->atomhdr);
  1.2512 +	if (bytesread < 0)
  1.2513 +	    {
  1.2514 +	    // for memory cleanup set entrycount to allocated num of entries.
  1.2515 +	    stsd->entryCount = totalsampleentriesread;
  1.2516 +	    return -1;
  1.2517 +	    }
  1.2518 +	totalbytesread += bytesread;
  1.2519 +
  1.2520 +	if (stsd->atomhdr->type != ATOMTYPE_STSD)
  1.2521 +	    {
  1.2522 +	    // for memory cleanup set entrycount to allocated num of entries.
  1.2523 +	    stsd->entryCount = totalsampleentriesread;
  1.2524 +	    return -1;
  1.2525 +	    }
  1.2526 +
  1.2527 +	bytesread = readData(handle, handle->buf, 4);
  1.2528 +	if (bytesread < 0)
  1.2529 +	    {
  1.2530 +	    // for memory cleanup set entrycount to allocated num of entries.
  1.2531 +	    stsd->entryCount = totalsampleentriesread;
  1.2532 +	    return -1;
  1.2533 +	    }
  1.2534 +	stsd->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.2535 +	totalbytesread += bytesread;
  1.2536 +
  1.2537 +	mp4_u32 type;
  1.2538 +	while ((mp4_u32)totalbytesread < stsd->atomhdr->size)
  1.2539 +		{	
  1.2540 +		// if the number of entries read already surpasses the number of entries specified 
  1.2541 +		// within the STSD atom, the file is corrupted.
  1.2542 +		if ((totalsampleentriesread + unknownsampleentriesread) >= stsd->entryCount)
  1.2543 +			{
  1.2544 +			// for memory cleanup set entrycount to allocated num of entries.
  1.2545 +			stsd->entryCount = totalsampleentriesread;
  1.2546 +  	  		return -1;    	    	
  1.2547 +			}
  1.2548 +
  1.2549 +		// read the next sample type
  1.2550 +		if (peekData(handle, handle->buf, 8) < 0)
  1.2551 +	        {
  1.2552 +	        // for memory cleanup set entrycount to allocated num of entries.
  1.2553 +	        stsd->entryCount = totalsampleentriesread;
  1.2554 +		    return -1;
  1.2555 +	        }
  1.2556 +		type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.2557 +    
  1.2558 +		// if the max sample entiries supported by the library has been reached 
  1.2559 +		if ((stsd->entryCount > STSDMAXSAMPLEENTRYCOUNT) && (totalsampleentriesread == STSDMAXSAMPLEENTRYCOUNT))
  1.2560 +			{
  1.2561 +			// skip reading the rest of the entries to make sure no more than max count of sample entries 
  1.2562 +			// will be processed, so that cleanup will always work. 
  1.2563 +			type = 0;
  1.2564 +			skipentries = 1;
  1.2565 +			}
  1.2566 +
  1.2567 +		switch (type)
  1.2568 +			{
  1.2569 +			case ATOMTYPE_MP4V:
  1.2570 +				{
  1.2571 +				if (stsd->mp4v[totalsampleentriesread]) /* MP4V[totalsampleentriesread] has already been read, more than one is not allowed */ 
  1.2572 +			        {
  1.2573 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2574 +			        stsd->entryCount = totalsampleentriesread;
  1.2575 +				    return -1;
  1.2576 +			        }
  1.2577 +		
  1.2578 +				if ((stsd->mp4v[totalsampleentriesread] = (visualSampleEntry *)mp4malloc(sizeof(visualSampleEntry))) == NULL)
  1.2579 +			        {
  1.2580 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2581 +			        stsd->entryCount = totalsampleentriesread;
  1.2582 +				    return -100;
  1.2583 +			        }
  1.2584 +		
  1.2585 +				bytesread = readMP4V(handle, stsd->mp4v[totalsampleentriesread]);
  1.2586 +				totalsampleentriesread++;
  1.2587 +				if (bytesread < 0)
  1.2588 +			        {
  1.2589 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2590 +			        stsd->entryCount = totalsampleentriesread;
  1.2591 +				    return -1;
  1.2592 +			        }
  1.2593 +				totalbytesread += bytesread;
  1.2594 +				break;
  1.2595 +				}
  1.2596 +
  1.2597 +			case ATOMTYPE_MP4A:
  1.2598 +				{	
  1.2599 +				if (stsd->mp4a[totalsampleentriesread]) /* MP4A[totalsampleentriesread] has already been read, more than one is not allowed */
  1.2600 +			        {
  1.2601 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2602 +			        stsd->entryCount = totalsampleentriesread;
  1.2603 +				    return -1;
  1.2604 +			        }
  1.2605 +
  1.2606 +				if ((stsd->mp4a[totalsampleentriesread] = (audioSampleEntry *)mp4malloc(sizeof(audioSampleEntry))) == NULL)
  1.2607 +			        {
  1.2608 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2609 +			        stsd->entryCount = totalsampleentriesread;
  1.2610 +				    return -100;
  1.2611 +			        }
  1.2612 +
  1.2613 +				bytesread = readMP4A(handle, stsd->mp4a[totalsampleentriesread]);
  1.2614 +				totalsampleentriesread++;
  1.2615 +				if (bytesread < 0)
  1.2616 +			        {
  1.2617 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2618 +			        stsd->entryCount = totalsampleentriesread;
  1.2619 +				    return -1;
  1.2620 +			        }
  1.2621 +				totalbytesread += bytesread;
  1.2622 +				break;
  1.2623 +				}
  1.2624 +
  1.2625 +			case ATOMTYPE_MP4S:
  1.2626 +				{
  1.2627 +				if (stsd->mp4s[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */
  1.2628 +			        {
  1.2629 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2630 +			        stsd->entryCount = totalsampleentriesread;
  1.2631 +				    return -1;
  1.2632 +			        }
  1.2633 +
  1.2634 +				if ((stsd->mp4s[totalsampleentriesread] = (mpegSampleEntry *)mp4malloc(sizeof(mpegSampleEntry))) == NULL)
  1.2635 +			        {
  1.2636 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2637 +			        stsd->entryCount = totalsampleentriesread;
  1.2638 +				    return -100;
  1.2639 +			        }
  1.2640 +
  1.2641 +				bytesread = readMP4S(handle, stsd->mp4s[totalsampleentriesread]);
  1.2642 +				totalsampleentriesread++;
  1.2643 +				if (bytesread < 0)
  1.2644 +			        {
  1.2645 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2646 +			        stsd->entryCount = totalsampleentriesread;
  1.2647 +				    return -1;
  1.2648 +			        }
  1.2649 +				totalbytesread += bytesread;
  1.2650 +				}
  1.2651 +				break;
  1.2652 +
  1.2653 +			case ATOMTYPE_S263:
  1.2654 +				{
  1.2655 +				if (stsd->s263[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */
  1.2656 +			        {
  1.2657 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2658 +			        stsd->entryCount = totalsampleentriesread;
  1.2659 +				    return -1;
  1.2660 +			        }
  1.2661 +
  1.2662 +				if ((stsd->s263[totalsampleentriesread] = (h263SampleEntry *)mp4malloc(sizeof(h263SampleEntry))) == NULL)
  1.2663 +			        {
  1.2664 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2665 +			        stsd->entryCount = totalsampleentriesread;
  1.2666 +				    return -100;
  1.2667 +			        }
  1.2668 +
  1.2669 +				bytesread = readS263(handle, stsd->s263[totalsampleentriesread]);
  1.2670 +				totalsampleentriesread++;
  1.2671 +				if (bytesread < 0)
  1.2672 +			        {
  1.2673 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2674 +			        stsd->entryCount = totalsampleentriesread;
  1.2675 +				    return -1;
  1.2676 +			        }
  1.2677 +				totalbytesread += bytesread;
  1.2678 +				}
  1.2679 +				break;
  1.2680 +
  1.2681 +			case ATOMTYPE_SAMR:
  1.2682 +				{
  1.2683 +				if (stsd->samr[totalsampleentriesread]) /* SAMR has already been read, more than one is not allowed */
  1.2684 +			        {
  1.2685 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2686 +			        stsd->entryCount = totalsampleentriesread;
  1.2687 +				    return -1;
  1.2688 +			        }
  1.2689 +
  1.2690 +				if ((stsd->samr[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL)
  1.2691 +			        {
  1.2692 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2693 +			        stsd->entryCount = totalsampleentriesread;
  1.2694 +				    return -100;
  1.2695 +			        }
  1.2696 +
  1.2697 +				bytesread = readSAMR(handle, stsd->samr[totalsampleentriesread]);
  1.2698 +				totalsampleentriesread++;
  1.2699 +				if (bytesread < 0)
  1.2700 +			        {
  1.2701 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2702 +			        stsd->entryCount = totalsampleentriesread;
  1.2703 +				    return -1;
  1.2704 +			        }
  1.2705 +				totalbytesread += bytesread;
  1.2706 +				}
  1.2707 +				break;
  1.2708 +
  1.2709 +			case ATOMTYPE_SAWB:
  1.2710 +				{
  1.2711 +				if (stsd->sawb[totalsampleentriesread]) /* SAWB has already been read, more than one is not allowed */
  1.2712 +			        {
  1.2713 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2714 +			        stsd->entryCount = totalsampleentriesread;
  1.2715 +				    return -1;
  1.2716 +			        }
  1.2717 +
  1.2718 +				if ((stsd->sawb[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL)
  1.2719 +			        {
  1.2720 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2721 +			        stsd->entryCount = totalsampleentriesread;
  1.2722 +				    return -100;
  1.2723 +			        }
  1.2724 +
  1.2725 +				bytesread = readSAWB(handle, stsd->sawb[totalsampleentriesread]);
  1.2726 +				totalsampleentriesread++;
  1.2727 +				if (bytesread < 0)
  1.2728 +			        {
  1.2729 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2730 +			        stsd->entryCount = totalsampleentriesread;
  1.2731 +				    return -1;
  1.2732 +			        }
  1.2733 +				totalbytesread += bytesread;
  1.2734 +				}
  1.2735 +				break;
  1.2736 +
  1.2737 +			case ATOMTYPE_AVC1:
  1.2738 +				{
  1.2739 +				if (stsd->avc1[totalsampleentriesread]) /* AVC1 has already been read, more than one is not allowed */
  1.2740 +					{
  1.2741 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2742 +			        stsd->entryCount = totalsampleentriesread;
  1.2743 +				    return -1;
  1.2744 +					}
  1.2745 +				if ((stsd->avc1[totalsampleentriesread] = (avcSampleEntry *)mp4malloc(sizeof(avcSampleEntry))) == NULL)
  1.2746 +			        {
  1.2747 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2748 +			        stsd->entryCount = totalsampleentriesread;
  1.2749 +				    return -100;
  1.2750 +			        }
  1.2751 +
  1.2752 +				bytesread = readAVC1(handle, stsd->avc1[totalsampleentriesread]);
  1.2753 +				totalsampleentriesread++;
  1.2754 +				if (bytesread < 0)
  1.2755 +					{
  1.2756 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2757 +			        stsd->entryCount = totalsampleentriesread;
  1.2758 +				    return -1;
  1.2759 +			        }
  1.2760 +				totalbytesread += bytesread;
  1.2761 +				}
  1.2762 +				break;
  1.2763 +
  1.2764 +			case ATOMTYPE_SQCP:
  1.2765 +				{
  1.2766 +				if (stsd->sqcp[totalsampleentriesread]) /* SQCP has already been read, more than one is not allowed */
  1.2767 +			        {
  1.2768 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2769 +			        stsd->entryCount = totalsampleentriesread;
  1.2770 +				    return -1;
  1.2771 +			        }
  1.2772 +				if ((stsd->sqcp[totalsampleentriesread] = (qcelpSampleEntry *)mp4malloc(sizeof(qcelpSampleEntry))) == NULL)
  1.2773 +			        {
  1.2774 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2775 +			        stsd->entryCount = totalsampleentriesread;
  1.2776 +				    return -100;
  1.2777 +			        }
  1.2778 +
  1.2779 +				bytesread = readSQCP(handle, stsd->sqcp[totalsampleentriesread]);
  1.2780 +				totalsampleentriesread++;
  1.2781 +				if (bytesread < 0)
  1.2782 +					{
  1.2783 +			        // for memory cleanup set entrycount to allocated num of entries.
  1.2784 +			        stsd->entryCount = totalsampleentriesread;
  1.2785 +				    return -1;
  1.2786 +			        }
  1.2787 +				totalbytesread += bytesread;
  1.2788 +				}
  1.2789 +				break;
  1.2790 +
  1.2791 +			default: /* Other atoms are not needed */
  1.2792 +				// no need to increment totalsampleentriesread as no memory is allocated for unsupported 
  1.2793 +				// or unrecognized sample types.  Alternatively, increment the count of unknown samples.   
  1.2794 +				// This is for ensure if a non-audio/video track can properly be parsed without being 
  1.2795 +				// recongized as an invalid format file.
  1.2796 +				unknownsampleentriesread++;
  1.2797 +				bytesread = readUnknown(handle);
  1.2798 +				if (bytesread < 0)
  1.2799 +		    		{
  1.2800 +		    		// for memory cleanup set entrycount to allocated num of entries.
  1.2801 +		    		stsd->entryCount = totalsampleentriesread;
  1.2802 +		    		return -1;
  1.2803 +		    		}
  1.2804 +				totalbytesread += bytesread;
  1.2805 +				break;
  1.2806 +			}
  1.2807 +		}
  1.2808 +
  1.2809 +	// if the STSD atom's entry count is NOT the same as the number (supported & unsupported) entries parsed,
  1.2810 +	// the atom is likely a corrupted one. 
  1.2811 +	if ((totalsampleentriesread + unknownsampleentriesread) != stsd->entryCount)
  1.2812 +		{
  1.2813 +		// for memory cleanup set entrycount to allocated num of entries.
  1.2814 +		stsd->entryCount = totalsampleentriesread;
  1.2815 +		return -1;
  1.2816 +		}
  1.2817 +	else 
  1.2818 +		{
  1.2819 +		// if the STSD atom's entry count is the same as the number of (supported & unsupported) entries 
  1.2820 +		// parsed, check if some entries are skipped because the max sample entry count has been reached  
  1.2821 +		if (skipentries) 
  1.2822 +			{
  1.2823 +			// if STSDMAXSAMPLEENTRYCOUNT was reached edit entrycount to make sure cleanup works.
  1.2824 +			stsd->entryCount = STSDMAXSAMPLEENTRYCOUNT;
  1.2825 +			}
  1.2826 +		else if (unknownsampleentriesread > 0)
  1.2827 +			{
  1.2828 +			// unknown (unsupported) sample entries present, set the STSD entry count to the actual 
  1.2829 +			// number of supported sample entries detected
  1.2830 +			stsd->entryCount = totalsampleentriesread;
  1.2831 +			}
  1.2832 +		}
  1.2833 +  
  1.2834 +	return totalbytesread;
  1.2835 +	}
  1.2836 +
  1.2837 +
  1.2838 +/*
  1.2839 + * Function:
  1.2840 + *
  1.2841 + *   mp4_i32 readSTSZ(MP4HandleImp handle,
  1.2842 + *                    sampleSizeAtom *stsz)
  1.2843 + *
  1.2844 + * Description:
  1.2845 + *
  1.2846 + *   This function parses one STSZ atom.
  1.2847 + *
  1.2848 + * Parameters:
  1.2849 + *
  1.2850 + *   handle             MP4 library handle
  1.2851 + *   stsz               STSZ pointer
  1.2852 + *
  1.2853 + * Return value:
  1.2854 + *
  1.2855 + *   Negative integer   Error
  1.2856 + *   >= 0               Success. Value tells how many bytes were read.
  1.2857 + *
  1.2858 + */
  1.2859 +mp4_i32 readSTSZ(MP4HandleImp handle, sampleSizeAtom *stsz)
  1.2860 +{
  1.2861 +  mp4_i32 bytesread;
  1.2862 +  mp4_i32 totalbytesread = 0;
  1.2863 +
  1.2864 +
  1.2865 +  if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2866 +    return -100;
  1.2867 +
  1.2868 +  bytesread = readFullAtomHeader(handle, stsz->atomhdr);
  1.2869 +  if (bytesread < 0)
  1.2870 +    return -1;
  1.2871 +  totalbytesread += bytesread;
  1.2872 +
  1.2873 +  if (stsz->atomhdr->type != ATOMTYPE_STSZ)
  1.2874 +    return -1;
  1.2875 +
  1.2876 +
  1.2877 +  bytesread = readData(handle, handle->buf, 4);
  1.2878 +  if (bytesread < 0)
  1.2879 +    return -1;
  1.2880 +  stsz->sampleSize = u32endian(*((mp4_u32 *)handle->buf));
  1.2881 +  totalbytesread += bytesread;
  1.2882 +
  1.2883 +  bytesread = readData(handle, handle->buf, 4);
  1.2884 +  if (bytesread < 0)
  1.2885 +    return -1;
  1.2886 +  stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf));
  1.2887 +  totalbytesread += bytesread;
  1.2888 +
  1.2889 +  // zero size samplesize means samples have different sizes, and those sizes are stored in sampleSizeEntries.
  1.2890 +  if ((stsz->sampleCount) && (stsz->sampleSize == 0))
  1.2891 +  {
  1.2892 +    mp4_u32 i;
  1.2893 +
  1.2894 +    // check validity of stsz->sampleCount before allocating entrysize table.
  1.2895 +    if ( handle->moov->mvhd )
  1.2896 +        {
  1.2897 +        if ( handle->moov->mvhd->timeScale > 0 )
  1.2898 +            {
  1.2899 +            TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND;
  1.2900 +            TUint maxSampleCount;
  1.2901 +
  1.2902 +            if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration
  1.2903 +                {
  1.2904 +                maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec;
  1.2905 +                }
  1.2906 +            else    // 32bit duration
  1.2907 +                {
  1.2908 +                maxSampleCount = TUint((TUint( handle->moov->mvhd->duration  ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec;
  1.2909 +                }
  1.2910 +
  1.2911 +            if ( maxSampleCount < stsz->sampleCount )
  1.2912 +                {
  1.2913 +                // corrupted 
  1.2914 +                return -1;
  1.2915 +                }
  1.2916 +            }
  1.2917 +        }
  1.2918 +
  1.2919 +    // allocate stsz->entrySize table
  1.2920 +    stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
  1.2921 +    if (stsz->entrySize == NULL)
  1.2922 +      return -1;
  1.2923 +
  1.2924 +    for (i = 0; i < stsz->sampleCount; i++)
  1.2925 +    {
  1.2926 +      bytesread = readData(handle, handle->buf, 4);
  1.2927 +      if (bytesread < 0)
  1.2928 +        return -1;
  1.2929 +
  1.2930 +      stsz->entrySize[i] = u32endian(*((mp4_u32 *)handle->buf));
  1.2931 +
  1.2932 +      totalbytesread += bytesread;
  1.2933 +    }
  1.2934 +  }
  1.2935 +
  1.2936 +  return totalbytesread;
  1.2937 +}
  1.2938 +
  1.2939 +
  1.2940 +/*
  1.2941 + * Function:
  1.2942 + *
  1.2943 + *   mp4_i32 readSTZ2(MP4HandleImp handle,
  1.2944 + *                    sampleSizeAtom *stsz)
  1.2945 + *
  1.2946 + * Description:
  1.2947 + *
  1.2948 + *   This function parses one STZ2 atom.
  1.2949 + *
  1.2950 + *   The result is placed in STSZ structure.
  1.2951 + *
  1.2952 + * Parameters:
  1.2953 + *
  1.2954 + *   handle             MP4 library handle
  1.2955 + *   stsz               STSZ pointer
  1.2956 + *
  1.2957 + * Return value:
  1.2958 + *
  1.2959 + *   Negative integer   Error
  1.2960 + *   >= 0               Success. Value tells how many bytes were read.
  1.2961 + *
  1.2962 + */
  1.2963 +mp4_i32 readSTZ2(MP4HandleImp handle, sampleSizeAtom *stsz)
  1.2964 +{
  1.2965 +  mp4_i32 bytesread;
  1.2966 +  mp4_i32 totalbytesread = 0;
  1.2967 +  mp4_u8  fieldsize;
  1.2968 +
  1.2969 +
  1.2970 +  if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.2971 +    return -100;
  1.2972 +
  1.2973 +  bytesread = readFullAtomHeader(handle, stsz->atomhdr);
  1.2974 +  if (bytesread < 0)
  1.2975 +    return -1;
  1.2976 +  totalbytesread += bytesread;
  1.2977 +
  1.2978 +  if (stsz->atomhdr->type != ATOMTYPE_STZ2)
  1.2979 +    return -1;
  1.2980 +
  1.2981 +
  1.2982 +  bytesread = discardData(handle, 3);
  1.2983 +  if (bytesread < 0)
  1.2984 +    return -1;
  1.2985 +  totalbytesread += bytesread;
  1.2986 +
  1.2987 +  bytesread = readData(handle, handle->buf, 1);
  1.2988 +  if (bytesread < 0)
  1.2989 +    return -1;
  1.2990 +  fieldsize = handle->buf[0];
  1.2991 +  totalbytesread += bytesread;
  1.2992 +
  1.2993 +  bytesread = readData(handle, handle->buf, 4);
  1.2994 +  if (bytesread < 0)
  1.2995 +    return -1;
  1.2996 +  stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf));
  1.2997 +  totalbytesread += bytesread;
  1.2998 +
  1.2999 +  switch (fieldsize)
  1.3000 +  {
  1.3001 +  case 4: /* Two entries in each byte */
  1.3002 +
  1.3003 +    {
  1.3004 +      mp4_u32 i;
  1.3005 +
  1.3006 +      stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
  1.3007 +      if (stsz->entrySize == NULL)
  1.3008 +        return -1;
  1.3009 +
  1.3010 +      for (i = 0; i < (stsz->sampleCount + 1) / 2; i++)
  1.3011 +      {
  1.3012 +        bytesread = readData(handle, handle->buf, 1);
  1.3013 +        if (bytesread < 0)
  1.3014 +          return -1;
  1.3015 +
  1.3016 +        totalbytesread += bytesread;
  1.3017 +
  1.3018 +        stsz->entrySize[i * 2] = (mp4_u32)(handle->buf[0] >> 4);
  1.3019 +
  1.3020 +        if (stsz->sampleCount % 2 == 0) /* Even number of samples */
  1.3021 +        {
  1.3022 +          stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f);
  1.3023 +          continue;
  1.3024 +        }
  1.3025 +
  1.3026 +        /* This condition is needed to avoid writing after the table */
  1.3027 +
  1.3028 +        if (i == (stsz->sampleCount + 1) / 2 - 1) /* Last sample */
  1.3029 +        {
  1.3030 +        }
  1.3031 +        else
  1.3032 +          stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f);
  1.3033 +      }
  1.3034 +    }
  1.3035 +
  1.3036 +    break;
  1.3037 +
  1.3038 +  case 8: /* One entry for each byte */
  1.3039 +
  1.3040 +    {
  1.3041 +      mp4_u32 i;
  1.3042 +
  1.3043 +      stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
  1.3044 +      if (stsz->entrySize == NULL)
  1.3045 +        return -1;
  1.3046 +
  1.3047 +      for (i = 0; i < stsz->sampleCount; i++)
  1.3048 +      {
  1.3049 +        bytesread = readData(handle, handle->buf, 1);
  1.3050 +        if (bytesread < 0)
  1.3051 +          return -1;
  1.3052 +
  1.3053 +        stsz->entrySize[i] = (mp4_u32)handle->buf[0];
  1.3054 +
  1.3055 +        totalbytesread += bytesread;
  1.3056 +      }
  1.3057 +    }
  1.3058 +
  1.3059 +    break;
  1.3060 +
  1.3061 +  case 16: /* Each entry in 2 bytes */
  1.3062 +
  1.3063 +    {
  1.3064 +      mp4_u32 i;
  1.3065 +
  1.3066 +      stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
  1.3067 +      if (stsz->entrySize == NULL)
  1.3068 +        return -1;
  1.3069 +
  1.3070 +      for (i = 0; i < stsz->sampleCount; i++)
  1.3071 +      {
  1.3072 +        bytesread = readData(handle, handle->buf, 2);
  1.3073 +        if (bytesread < 0)
  1.3074 +          return -1;
  1.3075 +
  1.3076 +        stsz->entrySize[i] = (mp4_u32)u16endian(*((mp4_u16 *)handle->buf));
  1.3077 +
  1.3078 +        totalbytesread += bytesread;
  1.3079 +      }
  1.3080 +    }
  1.3081 +
  1.3082 +    break;
  1.3083 +
  1.3084 +  default: /* Illegal fieldsize */
  1.3085 +
  1.3086 +    return -1;
  1.3087 +  }
  1.3088 +
  1.3089 +
  1.3090 +  return totalbytesread;
  1.3091 +}
  1.3092 +
  1.3093 +
  1.3094 +/*
  1.3095 + * Function:
  1.3096 + *
  1.3097 + *   mp4_i32 readSTSC(MP4HandleImp handle,
  1.3098 + *                    sampleToChunkAtom *stsc)
  1.3099 + *
  1.3100 + * Description:
  1.3101 + *
  1.3102 + *   This function parses one STSC atom.
  1.3103 + *
  1.3104 + * Parameters:
  1.3105 + *
  1.3106 + *   handle             MP4 library handle
  1.3107 + *   stsc               STSC pointer
  1.3108 + *
  1.3109 + * Return value:
  1.3110 + *
  1.3111 + *   Negative integer   Error
  1.3112 + *   >= 0               Success. Value tells how many bytes were read.
  1.3113 + *
  1.3114 + */
  1.3115 +mp4_i32 readSTSC(MP4HandleImp handle, sampleToChunkAtom *stsc)
  1.3116 +{
  1.3117 +  mp4_i32 bytesread;
  1.3118 +  mp4_i32 totalbytesread = 0;
  1.3119 +  mp4_u32 i;
  1.3120 +
  1.3121 +
  1.3122 +  if ((stsc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3123 +    return -100;
  1.3124 +
  1.3125 +  bytesread = readFullAtomHeader(handle, stsc->atomhdr);
  1.3126 +  if (bytesread < 0)
  1.3127 +    return -1;
  1.3128 +  totalbytesread += bytesread;
  1.3129 +
  1.3130 +  if (stsc->atomhdr->type != ATOMTYPE_STSC)
  1.3131 +    return -1;
  1.3132 +
  1.3133 +
  1.3134 +  bytesread = readData(handle, handle->buf, 4);
  1.3135 +  if (bytesread < 0)
  1.3136 +    return -1;
  1.3137 +  stsc->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.3138 +  totalbytesread += bytesread;
  1.3139 +
  1.3140 +  if (stsc->entryCount)
  1.3141 +  {
  1.3142 +	  stsc->firstChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
  1.3143 +	  if (stsc->firstChunk == NULL)
  1.3144 +	    return -1;
  1.3145 +	  stsc->samplesPerChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
  1.3146 +	  if (stsc->samplesPerChunk == NULL)
  1.3147 +	    return -1;
  1.3148 +	  stsc->sampleDescriptionIndex = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
  1.3149 +	  if (stsc->sampleDescriptionIndex == NULL)
  1.3150 +	  {
  1.3151 +		return -1;	  	
  1.3152 +	  }
  1.3153 +
  1.3154 +	  for (i = 0; i < stsc->entryCount; i++)
  1.3155 +	  {
  1.3156 +	    bytesread = readData(handle, handle->buf, 12);
  1.3157 +	    if (bytesread < 0)
  1.3158 +	      return -1;
  1.3159 +
  1.3160 +	    stsc->firstChunk[i] = u32endian(*((mp4_u32 *)handle->buf));
  1.3161 +	    stsc->samplesPerChunk[i] = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.3162 +	    stsc->sampleDescriptionIndex[i] = u32endian(*((mp4_u32 *)(handle->buf+8)));
  1.3163 +	    if ( stsc->sampleDescriptionIndex[i] > stsc->entryCount)
  1.3164 +	    {
  1.3165 +	    	return -1;
  1.3166 +	    }
  1.3167 +
  1.3168 +	    totalbytesread += bytesread;
  1.3169 +	  }
  1.3170 +  }
  1.3171 +  return totalbytesread;
  1.3172 +}
  1.3173 +
  1.3174 +
  1.3175 +/*
  1.3176 + * Function:
  1.3177 + *
  1.3178 + *   mp4_i32 readSTCO(MP4HandleImp handle,
  1.3179 + *                    chunkOffsetAtom *stco)
  1.3180 + *
  1.3181 + * Description:
  1.3182 + *
  1.3183 + *   This function parses one STCO atom.
  1.3184 + *
  1.3185 + * Parameters:
  1.3186 + *
  1.3187 + *   handle             MP4 library handle
  1.3188 + *   stco               STCO pointer
  1.3189 + *
  1.3190 + * Return value:
  1.3191 + *
  1.3192 + *   Negative integer   Error
  1.3193 + *   >= 0               Success. Value tells how many bytes were read.
  1.3194 + *
  1.3195 + */
  1.3196 +mp4_i32 readSTCO(MP4HandleImp handle, chunkOffsetAtom *stco)
  1.3197 +{
  1.3198 +  mp4_i32 bytesread;
  1.3199 +  mp4_i32 totalbytesread = 0;
  1.3200 +  mp4_u32  i;
  1.3201 +
  1.3202 +
  1.3203 +  if ((stco->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3204 +    return -100;
  1.3205 +
  1.3206 +  bytesread = readFullAtomHeader(handle, stco->atomhdr);
  1.3207 +  if (bytesread < 0)
  1.3208 +    return -1;
  1.3209 +  totalbytesread += bytesread;
  1.3210 +
  1.3211 +  if (stco->atomhdr->type != ATOMTYPE_STCO)
  1.3212 +    return -1;
  1.3213 +
  1.3214 +
  1.3215 +  bytesread = readData(handle, handle->buf, 4);
  1.3216 +  if (bytesread < 0)
  1.3217 +    return -1;
  1.3218 +  stco->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.3219 +  totalbytesread += bytesread;
  1.3220 +
  1.3221 +  if (stco->entryCount)
  1.3222 +  {
  1.3223 +	  // validate stco->entryCount before allocating chunkOffsetTable
  1.3224 +	  if ( handle->moov->mvhd )
  1.3225 +	    {
  1.3226 +	    if ( handle->moov->mvhd->timeScale > 0 )
  1.3227 +	        {
  1.3228 +	        TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND;
  1.3229 +	        TUint maxSampleCount;
  1.3230 +
  1.3231 +	        if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration
  1.3232 +	            {
  1.3233 +	            maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec;
  1.3234 +	            }
  1.3235 +	        else    // 32bit duration
  1.3236 +	            {
  1.3237 +	            maxSampleCount = TUint((TUint( handle->moov->mvhd->duration  ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec;
  1.3238 +	            }
  1.3239 +
  1.3240 +	        if ( maxSampleCount < stco->entryCount )
  1.3241 +	            {
  1.3242 +	            // corrupted 
  1.3243 +	            return -1;
  1.3244 +	            }
  1.3245 +	        }
  1.3246 +	    }
  1.3247 +
  1.3248 +	  stco->chunkOffset = (mp4_u32 *)mp4malloc(stco->entryCount * sizeof(mp4_u32));
  1.3249 +	  if (stco->chunkOffset == NULL)
  1.3250 +	    return -1;
  1.3251 +
  1.3252 +	  for (i = 0; i < stco->entryCount; i++)
  1.3253 +	  {
  1.3254 +	    bytesread = readData(handle, handle->buf, 4);
  1.3255 +	    if (bytesread < 0)
  1.3256 +	      return -1;
  1.3257 +
  1.3258 +	    stco->chunkOffset[i] = u32endian(*((mp4_u32 *)handle->buf));
  1.3259 +
  1.3260 +	    totalbytesread += bytesread;
  1.3261 +	  }
  1.3262 +  }
  1.3263 +  return totalbytesread;
  1.3264 +}
  1.3265 +
  1.3266 +
  1.3267 +/*
  1.3268 + * Function:
  1.3269 + *
  1.3270 + *   mp4_i32 readCO64(MP4HandleImp handle,
  1.3271 + *                    chunkOffset64Atom *stco64)
  1.3272 + *
  1.3273 + * Description:
  1.3274 + *
  1.3275 + *   This function parses one CO64 atom.
  1.3276 + *
  1.3277 + * Parameters:
  1.3278 + *
  1.3279 + *   handle             MP4 library handle
  1.3280 + *   stco64               CO64 pointer
  1.3281 + *
  1.3282 + * Return value:
  1.3283 + *
  1.3284 + *   Negative integer   Error
  1.3285 + *   >= 0               Success. Value tells how many bytes were read.
  1.3286 + *
  1.3287 + */
  1.3288 +mp4_i32 readCO64(MP4HandleImp handle, chunkOffset64Atom *stco64)
  1.3289 +{
  1.3290 +  mp4_i32 bytesread;
  1.3291 +  mp4_i32 totalbytesread = 0;
  1.3292 +  mp4_u32 i;
  1.3293 +
  1.3294 +
  1.3295 +  if ((stco64->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3296 +    return -100;
  1.3297 +
  1.3298 +  bytesread = readFullAtomHeader(handle, stco64->atomhdr);
  1.3299 +  if (bytesread < 0)
  1.3300 +    return -1;
  1.3301 +  totalbytesread += bytesread;
  1.3302 +
  1.3303 +  if (stco64->atomhdr->type != ATOMTYPE_CO64)
  1.3304 +    return -1;
  1.3305 +
  1.3306 +
  1.3307 +  bytesread = readData(handle, handle->buf, 4);
  1.3308 +  if (bytesread < 0)
  1.3309 +    return -1;
  1.3310 +  stco64->entryCount = u32endian(*((mp4_u32 *)handle->buf));
  1.3311 +  totalbytesread += bytesread;
  1.3312 +
  1.3313 +  if ( stco64->entryCount )
  1.3314 +  {
  1.3315 +	  stco64->chunkOffset = (mp4_u64 *)mp4malloc(stco64->entryCount * sizeof(mp4_u64));
  1.3316 +	  if (stco64->chunkOffset == NULL)
  1.3317 +	    return -1;
  1.3318 +
  1.3319 +	  for (i = 0; i < stco64->entryCount; i++)
  1.3320 +	  {
  1.3321 +	    bytesread = readData(handle, handle->buf, 8);
  1.3322 +	    if (bytesread < 0)
  1.3323 +	      return -1;
  1.3324 +	    
  1.3325 +	    stco64->chunkOffset[i] = u64endian(*((mp4_u64 *)(handle->buf)));
  1.3326 +
  1.3327 +	    totalbytesread += bytesread;
  1.3328 +	  }
  1.3329 +  }
  1.3330 +  return totalbytesread;
  1.3331 +}
  1.3332 +
  1.3333 +
  1.3334 +/*
  1.3335 + * Function:
  1.3336 + *
  1.3337 + *   mp4_i32 readMP4V(MP4HandleImp handle,
  1.3338 + *                    visualSampleEntry *mp4v)
  1.3339 + *
  1.3340 + * Description:
  1.3341 + *
  1.3342 + *   This function parses one MP4V atom.
  1.3343 + *
  1.3344 + * Parameters:
  1.3345 + *
  1.3346 + *   handle             MP4 library handle
  1.3347 + *   mp4v               MP4V pointer
  1.3348 + *
  1.3349 + * Return value:
  1.3350 + *
  1.3351 + *   Negative integer   Error
  1.3352 + *   >= 0               Success. Value tells how many bytes were read.
  1.3353 + *
  1.3354 + */
  1.3355 +mp4_i32 readMP4V(MP4HandleImp handle, visualSampleEntry *mp4v)
  1.3356 +{
  1.3357 +  mp4_i32 bytesread;
  1.3358 +  mp4_i32 totalbytesread = 0;
  1.3359 +
  1.3360 +
  1.3361 +  if ((mp4v->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3362 +    return -100;
  1.3363 +
  1.3364 +  bytesread = readAtomHeader(handle, mp4v->atomhdr);
  1.3365 +  if (bytesread < 0)
  1.3366 +    return -1;
  1.3367 +  totalbytesread += bytesread;
  1.3368 +
  1.3369 +  if (mp4v->atomhdr->type != ATOMTYPE_MP4V)
  1.3370 +    return -1;
  1.3371 +
  1.3372 +
  1.3373 +  bytesread = discardData(handle, 6);
  1.3374 +  if (bytesread < 0)
  1.3375 +    return -1;
  1.3376 +  totalbytesread += bytesread;
  1.3377 +
  1.3378 +  bytesread = readData(handle, handle->buf, 2);
  1.3379 +  if (bytesread < 0)
  1.3380 +    return -1;
  1.3381 +  mp4v->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.3382 +  totalbytesread += bytesread;
  1.3383 +
  1.3384 +  bytesread = discardData(handle, 16);
  1.3385 +  if (bytesread < 0)
  1.3386 +    return -1;
  1.3387 +  totalbytesread += bytesread;
  1.3388 +
  1.3389 +  bytesread = readData(handle, handle->buf, 2);
  1.3390 +  if (bytesread < 0)
  1.3391 +    return -1;
  1.3392 +  mp4v->width = u16endian(*((mp4_u16 *)handle->buf));
  1.3393 +  totalbytesread += bytesread;
  1.3394 +
  1.3395 +  bytesread = readData(handle, handle->buf, 2);
  1.3396 +  if (bytesread < 0)
  1.3397 +    return -1;
  1.3398 +  mp4v->height = u16endian(*((mp4_u16 *)handle->buf));
  1.3399 +  totalbytesread += bytesread;
  1.3400 +
  1.3401 +  bytesread = discardData(handle, 50);
  1.3402 +  if (bytesread < 0)
  1.3403 +    return -1;
  1.3404 +  totalbytesread += bytesread;
  1.3405 +
  1.3406 +  if ((mp4v->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
  1.3407 +    return -100;
  1.3408 +
  1.3409 +  bytesread = readESD(handle, mp4v->esd);
  1.3410 +  if (bytesread < 0)
  1.3411 +    return -1;
  1.3412 +  totalbytesread += bytesread;
  1.3413 +  
  1.3414 +  if ( totalbytesread < mp4v->atomhdr->size )
  1.3415 +  	{
  1.3416 +    bytesread = discardData(handle, mp4v->atomhdr->size - totalbytesread );
  1.3417 +  	if (bytesread < 0)
  1.3418 +  		{
  1.3419 +    	return -1;	  		
  1.3420 +  		}
  1.3421 +  	totalbytesread += bytesread;
  1.3422 +  	}  
  1.3423 +
  1.3424 +  return totalbytesread;
  1.3425 +}
  1.3426 +
  1.3427 +
  1.3428 +/*
  1.3429 + * Function:
  1.3430 + *
  1.3431 + *   mp4_i32 readMP4A(MP4HandleImp handle,
  1.3432 + *                    audioSampleEntry *mp4a)
  1.3433 + *
  1.3434 + * Description:
  1.3435 + *
  1.3436 + *   This function parses one MP4A atom.
  1.3437 + *
  1.3438 + * Parameters:
  1.3439 + *
  1.3440 + *   handle             MP4 library handle
  1.3441 + *   mp4a               MP4A pointer
  1.3442 + *
  1.3443 + * Return value:
  1.3444 + *
  1.3445 + *   Negative integer   Error
  1.3446 + *   >= 0               Success. Value tells how many bytes were read.
  1.3447 + *
  1.3448 + */
  1.3449 +mp4_i32 readMP4A(MP4HandleImp handle, audioSampleEntry *mp4a)
  1.3450 +{
  1.3451 +  mp4_i32 bytesread;
  1.3452 +  mp4_i32 totalbytesread = 0;
  1.3453 +
  1.3454 +
  1.3455 +  if ((mp4a->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3456 +    return -100;
  1.3457 +
  1.3458 +  bytesread = readAtomHeader(handle, mp4a->atomhdr);
  1.3459 +  if (bytesread < 0)
  1.3460 +    return -1;
  1.3461 +  totalbytesread += bytesread;
  1.3462 +
  1.3463 +  if (mp4a->atomhdr->type != ATOMTYPE_MP4A)
  1.3464 +    return -1;
  1.3465 +
  1.3466 +
  1.3467 +  bytesread = discardData(handle, 6);
  1.3468 +  if (bytesread < 0)
  1.3469 +    return -1;
  1.3470 +  totalbytesread += bytesread;
  1.3471 +
  1.3472 +  bytesread = readData(handle, handle->buf, 2);
  1.3473 +  if (bytesread < 0)
  1.3474 +    return -1;
  1.3475 +  mp4a->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.3476 +  totalbytesread += bytesread;
  1.3477 +
  1.3478 +  bytesread = discardData(handle, 16);
  1.3479 +  if (bytesread < 0)
  1.3480 +    return -1;
  1.3481 +  totalbytesread += bytesread;
  1.3482 +
  1.3483 +  bytesread = readData(handle, handle->buf, 2);
  1.3484 +  if (bytesread < 0)
  1.3485 +    return -1;
  1.3486 +  mp4a->timeScale = u16endian(*((mp4_u16 *)handle->buf));
  1.3487 +  totalbytesread += bytesread;
  1.3488 +
  1.3489 +  bytesread = discardData(handle, 2);
  1.3490 +  if (bytesread < 0)
  1.3491 +    return -1;
  1.3492 +  totalbytesread += bytesread;
  1.3493 +
  1.3494 +  if ((mp4a->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
  1.3495 +    return -100;
  1.3496 +
  1.3497 +  bytesread = readESD(handle, mp4a->esd);
  1.3498 +  if (bytesread < 0)
  1.3499 +    return -1;
  1.3500 +  totalbytesread += bytesread;
  1.3501 +  
  1.3502 +  if ( totalbytesread < mp4a->atomhdr->size )
  1.3503 +  	{
  1.3504 +    bytesread = discardData(handle, mp4a->atomhdr->size - totalbytesread );
  1.3505 +  	if (bytesread < 0)
  1.3506 +  		{
  1.3507 +    	return -1;	  		
  1.3508 +  		}
  1.3509 +  	totalbytesread += bytesread;
  1.3510 +  	}
  1.3511 +
  1.3512 +  return totalbytesread;
  1.3513 +}
  1.3514 +
  1.3515 +
  1.3516 +/*
  1.3517 + * Function:
  1.3518 + *
  1.3519 + *   mp4_i32 readMP4S(MP4HandleImp handle,
  1.3520 + *                    mpegSampleEntry *mp4s)
  1.3521 + *
  1.3522 + * Description:
  1.3523 + *
  1.3524 + *   This function parses one MP4S atom.
  1.3525 + *
  1.3526 + * Parameters:
  1.3527 + *
  1.3528 + *   handle             MP4 library handle
  1.3529 + *   mp4s               MP4S pointer
  1.3530 + *
  1.3531 + * Return value:
  1.3532 + *
  1.3533 + *   Negative integer   Error
  1.3534 + *   >= 0               Success. Value tells how many bytes were read.
  1.3535 + *
  1.3536 + */
  1.3537 +mp4_i32 readMP4S(MP4HandleImp handle, mpegSampleEntry *mp4s)
  1.3538 +{
  1.3539 +  mp4_i32 bytesread;
  1.3540 +  mp4_i32 totalbytesread = 0;
  1.3541 +
  1.3542 +
  1.3543 +  if ((mp4s->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3544 +    return -100;
  1.3545 +
  1.3546 +  bytesread = readAtomHeader(handle, mp4s->atomhdr);
  1.3547 +  if (bytesread < 0)
  1.3548 +    return -1;
  1.3549 +  totalbytesread += bytesread;
  1.3550 +
  1.3551 +  if (mp4s->atomhdr->type != ATOMTYPE_MP4S)
  1.3552 +    return -1;
  1.3553 +
  1.3554 +
  1.3555 +  bytesread = discardData(handle, 6);
  1.3556 +  if (bytesread < 0)
  1.3557 +    return -1;
  1.3558 +  totalbytesread += bytesread;
  1.3559 +
  1.3560 +  bytesread = readData(handle, handle->buf, 2);
  1.3561 +  if (bytesread < 0)
  1.3562 +    return -1;
  1.3563 +  mp4s->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.3564 +  totalbytesread += bytesread;
  1.3565 +
  1.3566 +  if ((mp4s->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
  1.3567 +    return -100;
  1.3568 +
  1.3569 +  bytesread = readESD(handle, mp4s->esd);
  1.3570 +  if (bytesread < 0)
  1.3571 +    return -1;
  1.3572 +  totalbytesread += bytesread;
  1.3573 +  
  1.3574 +  if ( totalbytesread < mp4s->atomhdr->size )
  1.3575 +  	{
  1.3576 +    bytesread = discardData(handle, mp4s->atomhdr->size - totalbytesread );
  1.3577 +  	if (bytesread < 0)
  1.3578 +  		{
  1.3579 +    	return -1;	  		
  1.3580 +  		}
  1.3581 +  	totalbytesread += bytesread;
  1.3582 +  	}    
  1.3583 +
  1.3584 +  return totalbytesread;
  1.3585 +}
  1.3586 +
  1.3587 +
  1.3588 +/*
  1.3589 + * Function:
  1.3590 + *
  1.3591 + *   mp4_i32 readS263(MP4HandleImp handle,
  1.3592 + *                    h263SampleEntry *s263)
  1.3593 + *
  1.3594 + * Description:
  1.3595 + *
  1.3596 + *   This function parses one S263 atom.
  1.3597 + *
  1.3598 + * Parameters:
  1.3599 + *
  1.3600 + *   handle             MP4 library handle
  1.3601 + *   s263               S263 pointer
  1.3602 + *
  1.3603 + * Return value:
  1.3604 + *
  1.3605 + *   Negative integer   Error
  1.3606 + *   >= 0               Success. Value tells how many bytes were read.
  1.3607 + *
  1.3608 + */
  1.3609 +mp4_i32 readS263(MP4HandleImp handle, h263SampleEntry *s263)
  1.3610 +{
  1.3611 +  mp4_i32 bytesread;
  1.3612 +  mp4_i32 totalbytesread = 0;
  1.3613 +
  1.3614 +
  1.3615 +  if ((s263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3616 +    return -100;
  1.3617 +
  1.3618 +  bytesread = readAtomHeader(handle, s263->atomhdr);
  1.3619 +  if (bytesread < 0)
  1.3620 +    return -1;
  1.3621 +  totalbytesread += bytesread;
  1.3622 +
  1.3623 +  if (s263->atomhdr->type != ATOMTYPE_S263)
  1.3624 +    return -1;
  1.3625 +
  1.3626 +
  1.3627 +  bytesread = discardData(handle, 6);
  1.3628 +  if (bytesread < 0)
  1.3629 +    return -1;
  1.3630 +  totalbytesread += bytesread;
  1.3631 +
  1.3632 +  bytesread = readData(handle, handle->buf, 2);
  1.3633 +  if (bytesread < 0)
  1.3634 +    return -1;
  1.3635 +  s263->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.3636 +  totalbytesread += bytesread;
  1.3637 +
  1.3638 +  bytesread = discardData(handle, 16);
  1.3639 +  if (bytesread < 0)
  1.3640 +    return -1;
  1.3641 +  totalbytesread += bytesread;
  1.3642 +
  1.3643 +  bytesread = readData(handle, handle->buf, 2);
  1.3644 +  if (bytesread < 0)
  1.3645 +    return -1;
  1.3646 +  s263->width = u16endian(*((mp4_u16 *)handle->buf));
  1.3647 +  totalbytesread += bytesread;
  1.3648 +
  1.3649 +  bytesread = readData(handle, handle->buf, 2);
  1.3650 +  if (bytesread < 0)
  1.3651 +    return -1;
  1.3652 +  s263->height = u16endian(*((mp4_u16 *)handle->buf));
  1.3653 +  totalbytesread += bytesread;
  1.3654 +
  1.3655 +  bytesread = discardData(handle, 50);
  1.3656 +  if (bytesread < 0)
  1.3657 +    return -1;
  1.3658 +  totalbytesread += bytesread;
  1.3659 +
  1.3660 +  if ((s263->d263 = (h263SpecificAtom *)mp4malloc(sizeof(h263SpecificAtom))) == NULL)
  1.3661 +    return -100;
  1.3662 +
  1.3663 +  bytesread = readD263(handle, s263->d263);
  1.3664 +  if (bytesread < 0)
  1.3665 +    return -1;
  1.3666 +  totalbytesread += bytesread;
  1.3667 +  
  1.3668 +  if ( totalbytesread < s263->atomhdr->size )
  1.3669 +  	{
  1.3670 +    bytesread = discardData(handle, s263->atomhdr->size - totalbytesread );
  1.3671 +  	if (bytesread < 0)
  1.3672 +  		{
  1.3673 +    	return -1;	  		
  1.3674 +  		}
  1.3675 +  	totalbytesread += bytesread;
  1.3676 +  	}      
  1.3677 +
  1.3678 +  return totalbytesread;
  1.3679 +}
  1.3680 +
  1.3681 +
  1.3682 +/*
  1.3683 + * Function:
  1.3684 + *
  1.3685 + *   mp4_i32 readSAMR(MP4HandleImp handle,
  1.3686 + *                    amrSampleEntry *samr)
  1.3687 + *
  1.3688 + * Description:
  1.3689 + *
  1.3690 + *   This function parses one SAMR atom.
  1.3691 + *
  1.3692 + * Parameters:
  1.3693 + *
  1.3694 + *   handle             MP4 library handle
  1.3695 + *   samr               SAMR pointer
  1.3696 + *
  1.3697 + * Return value:
  1.3698 + *
  1.3699 + *   Negative integer   Error
  1.3700 + *   >= 0               Success. Value tells how many bytes were read.
  1.3701 + *
  1.3702 + */
  1.3703 +mp4_i32 readSAMR(MP4HandleImp handle, amrSampleEntry *samr)
  1.3704 +{
  1.3705 +  mp4_i32 bytesread;
  1.3706 +  mp4_i32 totalbytesread = 0;
  1.3707 +
  1.3708 +
  1.3709 +  if ((samr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3710 +    return -100;
  1.3711 +
  1.3712 +  bytesread = readAtomHeader(handle, samr->atomhdr);
  1.3713 +  if (bytesread < 0)
  1.3714 +    return -1;
  1.3715 +  totalbytesread += bytesread;
  1.3716 +
  1.3717 +  if (samr->atomhdr->type != ATOMTYPE_SAMR)
  1.3718 +    return -1;
  1.3719 +
  1.3720 +
  1.3721 +  bytesread = discardData(handle, 6);
  1.3722 +  if (bytesread < 0)
  1.3723 +    return -1;
  1.3724 +  totalbytesread += bytesread;
  1.3725 +
  1.3726 +  bytesread = readData(handle, handle->buf, 2);
  1.3727 +  if (bytesread < 0)
  1.3728 +    return -1;
  1.3729 +  samr->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.3730 +  totalbytesread += bytesread;
  1.3731 +
  1.3732 +  bytesread = discardData(handle, 16);
  1.3733 +  if (bytesread < 0)
  1.3734 +    return -1;
  1.3735 +  totalbytesread += bytesread;
  1.3736 +
  1.3737 +  bytesread = readData(handle, handle->buf, 2);
  1.3738 +  if (bytesread < 0)
  1.3739 +    return -1;
  1.3740 +  samr->timeScale = u16endian(*((mp4_u16 *)handle->buf));
  1.3741 +  totalbytesread += bytesread;
  1.3742 +
  1.3743 +  bytesread = discardData(handle, 2);
  1.3744 +  if (bytesread < 0)
  1.3745 +    return -1;
  1.3746 +  totalbytesread += bytesread;
  1.3747 +
  1.3748 +  if ((samr->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL)
  1.3749 +    return -100;
  1.3750 +
  1.3751 +  bytesread = readDAMR(handle, samr->damr);
  1.3752 +  if (bytesread < 0)
  1.3753 +    return -1;
  1.3754 +  totalbytesread += bytesread;
  1.3755 +  
  1.3756 +  if ( totalbytesread < samr->atomhdr->size )
  1.3757 +  	{
  1.3758 +    bytesread = discardData(handle, samr->atomhdr->size - totalbytesread );
  1.3759 +  	if (bytesread < 0)
  1.3760 +  		{
  1.3761 +    	return -1;	  		
  1.3762 +  		}
  1.3763 +  	totalbytesread += bytesread;
  1.3764 +  	}      
  1.3765 +
  1.3766 +  return totalbytesread;
  1.3767 +}
  1.3768 +
  1.3769 +
  1.3770 +/*
  1.3771 + * Function:
  1.3772 + *
  1.3773 + *   mp4_i32 readSAWB(MP4HandleImp handle,
  1.3774 + *                    amrSampleEntry *sawb)
  1.3775 + *
  1.3776 + * Description:
  1.3777 + *
  1.3778 + *   This function parses one SAWB atom.
  1.3779 + *
  1.3780 + * Parameters:
  1.3781 + *
  1.3782 + *   handle             MP4 library handle
  1.3783 + *   sawb               SAWB pointer
  1.3784 + *
  1.3785 + * Return value:
  1.3786 + *
  1.3787 + *   Negative integer   Error
  1.3788 + *   >= 0               Success. Value tells how many bytes were read.
  1.3789 + *
  1.3790 + */
  1.3791 +mp4_i32 readSAWB(MP4HandleImp handle, amrSampleEntry *sawb)
  1.3792 +{
  1.3793 +  mp4_i32 bytesread;
  1.3794 +  mp4_i32 totalbytesread = 0;
  1.3795 +
  1.3796 +
  1.3797 +  if ((sawb->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3798 +    return -100;
  1.3799 +
  1.3800 +  bytesread = readAtomHeader(handle, sawb->atomhdr);
  1.3801 +  if (bytesread < 0)
  1.3802 +    return -1;
  1.3803 +  totalbytesread += bytesread;
  1.3804 +
  1.3805 +  if (sawb->atomhdr->type != ATOMTYPE_SAWB)
  1.3806 +    return -1;
  1.3807 +
  1.3808 +
  1.3809 +  bytesread = discardData(handle, 6);
  1.3810 +  if (bytesread < 0)
  1.3811 +    return -1;
  1.3812 +  totalbytesread += bytesread;
  1.3813 +
  1.3814 +  bytesread = readData(handle, handle->buf, 2);
  1.3815 +  if (bytesread < 0)
  1.3816 +    return -1;
  1.3817 +  sawb->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.3818 +  totalbytesread += bytesread;
  1.3819 +
  1.3820 +  bytesread = discardData(handle, 16);
  1.3821 +  if (bytesread < 0)
  1.3822 +    return -1;
  1.3823 +  totalbytesread += bytesread;
  1.3824 +
  1.3825 +  bytesread = readData(handle, handle->buf, 2);
  1.3826 +  if (bytesread < 0)
  1.3827 +    return -1;
  1.3828 +  sawb->timeScale = u16endian(*((mp4_u16 *)handle->buf));
  1.3829 +  totalbytesread += bytesread;
  1.3830 +
  1.3831 +  bytesread = discardData(handle, 2);
  1.3832 +  if (bytesread < 0)
  1.3833 +    return -1;
  1.3834 +  totalbytesread += bytesread;
  1.3835 +
  1.3836 +  if ((sawb->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL)
  1.3837 +    return -100;
  1.3838 +
  1.3839 +  bytesread = readDAMR(handle, sawb->damr);
  1.3840 +  if (bytesread < 0)
  1.3841 +    return -1;
  1.3842 +  totalbytesread += bytesread;
  1.3843 +  
  1.3844 +  if ( totalbytesread < sawb->atomhdr->size )
  1.3845 +  	{
  1.3846 +    bytesread = discardData(handle, sawb->atomhdr->size - totalbytesread );
  1.3847 +  	if (bytesread < 0)
  1.3848 +  		{
  1.3849 +    	return -1;	  		
  1.3850 +  		}
  1.3851 +  	totalbytesread += bytesread;
  1.3852 +  	}      
  1.3853 +
  1.3854 +  return totalbytesread;
  1.3855 +}
  1.3856 +
  1.3857 +
  1.3858 +/*
  1.3859 + * Function:
  1.3860 + *
  1.3861 + *   mp4_i32 readESD(MP4HandleImp handle,
  1.3862 + *                   ESDAtom *esd)
  1.3863 + *
  1.3864 + * Description:
  1.3865 + *
  1.3866 + *   This function parses one ESD atom.
  1.3867 + *
  1.3868 + * Parameters:
  1.3869 + *
  1.3870 + *   handle             MP4 library handle
  1.3871 + *   esd                ESD pointer
  1.3872 + *
  1.3873 + * Return value:
  1.3874 + *
  1.3875 + *   Negative integer   Error
  1.3876 + *   >= 0               Success. Value tells how many bytes were read.
  1.3877 + *
  1.3878 + */
  1.3879 +mp4_i32 readESD(MP4HandleImp handle, ESDAtom *esd)
  1.3880 +{
  1.3881 +  mp4_i32 bytesread;
  1.3882 +  mp4_i32 totalbytesread = 0;
  1.3883 +  mp4_i32 decConfDescrBytesRead = 0;
  1.3884 +
  1.3885 +
  1.3886 +  if ((esd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.3887 +    return -100;
  1.3888 +
  1.3889 +  bytesread = readFullAtomHeader(handle, esd->atomhdr);
  1.3890 +  if (bytesread < 0)
  1.3891 +    return -1;
  1.3892 +  totalbytesread += bytesread;
  1.3893 +
  1.3894 +  if (esd->atomhdr->type != ATOMTYPE_ESD)
  1.3895 +    return -1;
  1.3896 +
  1.3897 +
  1.3898 +  bytesread = readData(handle, handle->buf, 1);
  1.3899 +  if (bytesread < 0)
  1.3900 +    return -1;
  1.3901 +  esd->esDescrTag = handle->buf[0];
  1.3902 +  totalbytesread += bytesread;
  1.3903 +  if (esd->esDescrTag != 3) /* ES_DescrTag == 3 */
  1.3904 +    return -1;
  1.3905 +
  1.3906 +  esd->size = 0;
  1.3907 +  do
  1.3908 +  {
  1.3909 +    mp4_u8 c;
  1.3910 +
  1.3911 +    bytesread = readData(handle, handle->buf, 1);
  1.3912 +    if (bytesread < 0)
  1.3913 +      return -1;
  1.3914 +    c = (mp4_u8)(handle->buf[0] & 0x7f);
  1.3915 +    esd->size = (esd->size << 7) | c;
  1.3916 +    totalbytesread += bytesread;
  1.3917 +  }
  1.3918 +  while (handle->buf[0] & 0x80);
  1.3919 +
  1.3920 +  bytesread = readData(handle, handle->buf, 2);
  1.3921 +  if (bytesread < 0)
  1.3922 +    return -1;
  1.3923 +  esd->ESID = u16endian(*((mp4_u16 *)handle->buf));
  1.3924 +  totalbytesread += bytesread;
  1.3925 +
  1.3926 +  bytesread = readData(handle, handle->buf, 1);
  1.3927 +  if (bytesread < 0)
  1.3928 +    return -1;
  1.3929 +  esd->flags = handle->buf[0];
  1.3930 +  totalbytesread += bytesread;
  1.3931 +
  1.3932 +  if (esd->flags & 0x80) /* Stream Dependence flag has been set */
  1.3933 +  {
  1.3934 +    bytesread = readData(handle, handle->buf, 2);
  1.3935 +    if (bytesread < 0)
  1.3936 +      return -1;
  1.3937 +    esd->dependsOnESID = u16endian(*((mp4_u16 *)handle->buf));
  1.3938 +    totalbytesread += bytesread;
  1.3939 +  }
  1.3940 +
  1.3941 +  if (esd->flags & 0x40) /* URL flag has been set */
  1.3942 +  {
  1.3943 +    bytesread = readData(handle, handle->buf, 1);
  1.3944 +    if (bytesread < 0)
  1.3945 +      return -1;
  1.3946 +    esd->URLLength = handle->buf[0];
  1.3947 +    totalbytesread += bytesread;
  1.3948 +
  1.3949 +    bytesread = discardData(handle, esd->URLLength);
  1.3950 +    if (bytesread < 0)
  1.3951 +      return -1;
  1.3952 +    totalbytesread += bytesread;
  1.3953 +  }
  1.3954 +
  1.3955 +  if (esd->flags & 0x20) /* OCR stream flag has been set */
  1.3956 +  {
  1.3957 +    bytesread = readData(handle, handle->buf, 2);
  1.3958 +    if (bytesread < 0)
  1.3959 +      return -1;
  1.3960 +    esd->OCRESID = u16endian(*((mp4_u16 *)handle->buf));
  1.3961 +    totalbytesread += bytesread;
  1.3962 +  }
  1.3963 +
  1.3964 +  bytesread = readData(handle, handle->buf, 1);
  1.3965 +  if (bytesread < 0)
  1.3966 +    return -1;
  1.3967 +  esd->decConfDescrTag = handle->buf[0];
  1.3968 +  totalbytesread += bytesread;
  1.3969 +  if (esd->decConfDescrTag != 4) /* DecoderConfigDescrTag == 4 */
  1.3970 +    return -1;
  1.3971 +
  1.3972 +  esd->decConfDescrSize = 0;
  1.3973 +  do
  1.3974 +  {
  1.3975 +    mp4_u8 c;
  1.3976 +
  1.3977 +    bytesread = readData(handle, handle->buf, 1);
  1.3978 +    if (bytesread < 0)
  1.3979 +      return -1;
  1.3980 +    c = (mp4_u8)(handle->buf[0] & 0x7f);
  1.3981 +    esd->decConfDescrSize = (esd->decConfDescrSize << 7) | c;
  1.3982 +    totalbytesread += bytesread;
  1.3983 +  }
  1.3984 +  while (handle->buf[0] & 0x80);
  1.3985 +
  1.3986 +  bytesread = readData(handle, handle->buf, 1);
  1.3987 +  if (bytesread < 0)
  1.3988 +    return -1;
  1.3989 +  esd->objectTypeIndication = handle->buf[0];
  1.3990 +  totalbytesread += bytesread;
  1.3991 +  decConfDescrBytesRead += bytesread;
  1.3992 +
  1.3993 +  bytesread = readData(handle, handle->buf, 1);
  1.3994 +  if (bytesread < 0)
  1.3995 +    return -1;
  1.3996 +  esd->stream = handle->buf[0];
  1.3997 +  totalbytesread += bytesread;
  1.3998 +  decConfDescrBytesRead += bytesread;
  1.3999 +
  1.4000 +  bytesread = readData(handle, handle->buf, 3);
  1.4001 +  if (bytesread < 0)
  1.4002 +    return -1;
  1.4003 +  esd->bufferSizeDB = ((mp4_u32)handle->buf[0]) << 16 |
  1.4004 +                      ((mp4_u32)handle->buf[1]) << 8 |
  1.4005 +                      ((mp4_u32)handle->buf[2]);
  1.4006 +  totalbytesread += bytesread;
  1.4007 +  decConfDescrBytesRead += bytesread;
  1.4008 +
  1.4009 +  bytesread = readData(handle, handle->buf, 4);
  1.4010 +  if (bytesread < 0)
  1.4011 +    return -1;
  1.4012 +  esd->maxBitrate = u32endian(*((mp4_u32 *)handle->buf));
  1.4013 +  totalbytesread += bytesread;
  1.4014 +  decConfDescrBytesRead += bytesread;
  1.4015 +
  1.4016 +  bytesread = readData(handle, handle->buf, 4);
  1.4017 +  if (bytesread < 0)
  1.4018 +    return -1;
  1.4019 +  esd->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
  1.4020 +  totalbytesread += bytesread;
  1.4021 +  decConfDescrBytesRead += bytesread;
  1.4022 +
  1.4023 +  if ((mp4_u32)decConfDescrBytesRead < esd->decConfDescrSize)
  1.4024 +  {
  1.4025 +    bytesread = readData(handle, handle->buf, 1);
  1.4026 +    if (bytesread < 0)
  1.4027 +      return -1;
  1.4028 +    esd->decSpecificInfoTag = handle->buf[0];
  1.4029 +    totalbytesread += bytesread;
  1.4030 +    decConfDescrBytesRead += bytesread;
  1.4031 +    if (esd->decSpecificInfoTag != 5) /* DecSpecificInfoTag == 5 */
  1.4032 +    {
  1.4033 +      bytesread = discardData(handle, esd->decConfDescrSize - decConfDescrBytesRead);
  1.4034 +      if (bytesread < 0)
  1.4035 +        return -1;
  1.4036 +      totalbytesread += bytesread;
  1.4037 +    }
  1.4038 +    else
  1.4039 +    {
  1.4040 +      esd->decSpecificInfoSize = 0;
  1.4041 +      do
  1.4042 +      {
  1.4043 +        mp4_u8 c;
  1.4044 +
  1.4045 +        bytesread = readData(handle, handle->buf, 1);
  1.4046 +        if (bytesread < 0)
  1.4047 +          return -1;
  1.4048 +        c = (mp4_u8)(handle->buf[0] & 0x7f);
  1.4049 +        esd->decSpecificInfoSize = (esd->decSpecificInfoSize << 7) | c;
  1.4050 +        totalbytesread += bytesread;
  1.4051 +      }
  1.4052 +      while (handle->buf[0] & 0x80);
  1.4053 +
  1.4054 +      if(esd->decSpecificInfoSize)
  1.4055 +      {
  1.4056 +        if ((esd->decSpecificInfo = (mp4_u8 *)mp4malloc(esd->decSpecificInfoSize)) == NULL)
  1.4057 +          return -100;
  1.4058 +
  1.4059 +        bytesread = readData(handle, esd->decSpecificInfo, esd->decSpecificInfoSize);
  1.4060 +        if (bytesread < 0)
  1.4061 +          return -1;
  1.4062 +        totalbytesread += bytesread;
  1.4063 +      }
  1.4064 +    }
  1.4065 +  }
  1.4066 +
  1.4067 +  bytesread = discardData(handle, esd->atomhdr->size - totalbytesread);
  1.4068 +  if (bytesread < 0)
  1.4069 +    return -1;
  1.4070 +  totalbytesread += bytesread;
  1.4071 +
  1.4072 +  return totalbytesread;
  1.4073 +}
  1.4074 +
  1.4075 +
  1.4076 +/*
  1.4077 + * Function:
  1.4078 + *
  1.4079 + *   mp4_i32 readD263(MP4HandleImp handle,
  1.4080 + *                    h263SpecificAtom *d263)
  1.4081 + *
  1.4082 + * Description:
  1.4083 + *
  1.4084 + *   This function parses one D263 atom.
  1.4085 + *
  1.4086 + * Parameters:
  1.4087 + *
  1.4088 + *   handle             MP4 library handle
  1.4089 + *   d263               D263 pointer
  1.4090 + *
  1.4091 + * Return value:
  1.4092 + *
  1.4093 + *   Negative integer   Error
  1.4094 + *   >= 0               Success. Value tells how many bytes were read.
  1.4095 + *
  1.4096 + */
  1.4097 +mp4_i32 readD263(MP4HandleImp handle, h263SpecificAtom *d263)
  1.4098 +{
  1.4099 +  mp4_i32 bytesread;
  1.4100 +  mp4_i32 totalbytesread = 0;
  1.4101 +
  1.4102 +
  1.4103 +  if ((d263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.4104 +    return -100;
  1.4105 +
  1.4106 +  bytesread = readAtomHeader(handle, d263->atomhdr);
  1.4107 +  if (bytesread < 0)
  1.4108 +    return -1;
  1.4109 +  totalbytesread += bytesread;
  1.4110 +
  1.4111 +  if (d263->atomhdr->type != ATOMTYPE_D263)
  1.4112 +    return -1;
  1.4113 +
  1.4114 +
  1.4115 +  bytesread = readData(handle, handle->buf, 4);
  1.4116 +  if (bytesread < 0)
  1.4117 +    return -1;
  1.4118 +  d263->vendor = u32endian(*((mp4_u32 *)handle->buf));
  1.4119 +  totalbytesread += bytesread;
  1.4120 +
  1.4121 +  bytesread = readData(handle, handle->buf, 1);
  1.4122 +  if (bytesread < 0)
  1.4123 +    return -1;
  1.4124 +  d263->decoderVersion = handle->buf[0];
  1.4125 +  totalbytesread += bytesread;
  1.4126 +
  1.4127 +  bytesread = readData(handle, handle->buf, 1);
  1.4128 +  if (bytesread < 0)
  1.4129 +    return -1;
  1.4130 +  d263->h263Level = handle->buf[0];
  1.4131 +  totalbytesread += bytesread;
  1.4132 +
  1.4133 +  bytesread = readData(handle, handle->buf, 1);
  1.4134 +  if (bytesread < 0)
  1.4135 +    return -1;
  1.4136 +  d263->h263Profile = handle->buf[0];
  1.4137 +  totalbytesread += bytesread;
  1.4138 +
  1.4139 +  /* Check for the bitrate atom */
  1.4140 +
  1.4141 +  while ((mp4_u32)totalbytesread < d263->atomhdr->size)
  1.4142 +  {
  1.4143 +    mp4_u32 type;
  1.4144 +
  1.4145 +
  1.4146 +    if (peekData(handle, handle->buf, 8) < 0)
  1.4147 +      return -1;
  1.4148 +
  1.4149 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.4150 +
  1.4151 +    switch (type)
  1.4152 +    {
  1.4153 +    case ATOMTYPE_BITR:
  1.4154 +
  1.4155 +      if (d263->bitr) /* BITR has already been read, more than one is not allowed */
  1.4156 +        return -1;
  1.4157 +
  1.4158 +      if ((d263->bitr = (bitrateAtom *)mp4malloc(sizeof(bitrateAtom))) == NULL)
  1.4159 +        return -100;
  1.4160 +
  1.4161 +      bytesread = readBITR(handle, d263->bitr);
  1.4162 +      if (bytesread < 0)
  1.4163 +        return -1;
  1.4164 +      totalbytesread += bytesread;
  1.4165 +
  1.4166 +      break;
  1.4167 +
  1.4168 +    default: /* Other atoms are not needed */
  1.4169 +
  1.4170 +      bytesread = readUnknown(handle);
  1.4171 +      if (bytesread < 0)
  1.4172 +        return -1;
  1.4173 +      totalbytesread += bytesread;
  1.4174 +
  1.4175 +      break;
  1.4176 +    }
  1.4177 +  }
  1.4178 +
  1.4179 +  return totalbytesread;
  1.4180 +}
  1.4181 +
  1.4182 +
  1.4183 +/*
  1.4184 + * Function:
  1.4185 + *
  1.4186 + *   mp4_i32 readBITR(MP4HandleImp handle,
  1.4187 + *                    bitrateAtom *d263)
  1.4188 + *
  1.4189 + * Description:
  1.4190 + *
  1.4191 + *   This function parses one BITR atom.
  1.4192 + *
  1.4193 + * Parameters:
  1.4194 + *
  1.4195 + *   handle             MP4 library handle
  1.4196 + *   bitr               BITR pointer
  1.4197 + *
  1.4198 + * Return value:
  1.4199 + *
  1.4200 + *   Negative integer   Error
  1.4201 + *   >= 0               Success. Value tells how many bytes were read.
  1.4202 + *
  1.4203 + */
  1.4204 +mp4_i32 readBITR(MP4HandleImp handle, bitrateAtom *bitr)
  1.4205 +{
  1.4206 +  mp4_i32 bytesread;
  1.4207 +  mp4_i32 totalbytesread = 0;
  1.4208 +
  1.4209 +
  1.4210 +  if ((bitr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.4211 +    return -100;
  1.4212 +
  1.4213 +  bytesread = readAtomHeader(handle, bitr->atomhdr);
  1.4214 +  if (bytesread < 0)
  1.4215 +    return -1;
  1.4216 +  totalbytesread += bytesread;
  1.4217 +
  1.4218 +  if (bitr->atomhdr->type != ATOMTYPE_BITR)
  1.4219 +    return -1;
  1.4220 +
  1.4221 +
  1.4222 +  bytesread = readData(handle, handle->buf, 4);
  1.4223 +  if (bytesread < 0)
  1.4224 +    return -1;
  1.4225 +  bitr->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
  1.4226 +  totalbytesread += bytesread;
  1.4227 +
  1.4228 +  bytesread = readData(handle, handle->buf, 4);
  1.4229 +  if (bytesread < 0)
  1.4230 +    return -1;
  1.4231 +  bitr->maxBitrate = u32endian(*((mp4_u32 *)handle->buf));
  1.4232 +  totalbytesread += bytesread;
  1.4233 +
  1.4234 +  return totalbytesread;
  1.4235 +}
  1.4236 +
  1.4237 +
  1.4238 +/*
  1.4239 + * Function:
  1.4240 + *
  1.4241 + *   mp4_i32 readDAMR(MP4HandleImp handle,
  1.4242 + *                    amrDecSpecStruc *damr)
  1.4243 + *
  1.4244 + * Description:
  1.4245 + *
  1.4246 + *   This function parses one DAMR atom.
  1.4247 + *
  1.4248 + * Parameters:
  1.4249 + *
  1.4250 + *   handle             MP4 library handle
  1.4251 + *   damr               DAMR pointer
  1.4252 + *
  1.4253 + * Return value:
  1.4254 + *
  1.4255 + *   Negative integer   Error
  1.4256 + *   >= 0               Success. Value tells how many bytes were read.
  1.4257 + *
  1.4258 + */
  1.4259 +mp4_i32 readDAMR(MP4HandleImp handle, amrDecSpecStruc *damr)
  1.4260 +{
  1.4261 +  mp4_i32 bytesread;
  1.4262 +  mp4_i32 totalbytesread = 0;
  1.4263 +
  1.4264 +
  1.4265 +  if ((damr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.4266 +    return -100;
  1.4267 +
  1.4268 +  bytesread = readAtomHeader(handle, damr->atomhdr);
  1.4269 +  if (bytesread < 0)
  1.4270 +    return -1;
  1.4271 +  totalbytesread += bytesread;
  1.4272 +
  1.4273 +  if (damr->atomhdr->type != ATOMTYPE_DAMR)
  1.4274 +    return -1;
  1.4275 +
  1.4276 +
  1.4277 +  bytesread = readData(handle, handle->buf, 4);
  1.4278 +  if (bytesread < 0)
  1.4279 +    return -1;
  1.4280 +  damr->vendor = u32endian(*((mp4_u32 *)handle->buf));
  1.4281 +  totalbytesread += bytesread;
  1.4282 +
  1.4283 +  bytesread = readData(handle, handle->buf, 1);
  1.4284 +  if (bytesread < 0)
  1.4285 +    return -1;
  1.4286 +  damr->decoderVersion = handle->buf[0];
  1.4287 +  totalbytesread += bytesread;
  1.4288 +
  1.4289 +  bytesread = readData(handle, handle->buf, 2);
  1.4290 +  if (bytesread < 0)
  1.4291 +    return -1;
  1.4292 +  damr->modeSet = u16endian(*((mp4_u16 *)handle->buf));
  1.4293 +  totalbytesread += bytesread;
  1.4294 +
  1.4295 +  bytesread = readData(handle, handle->buf, 1);
  1.4296 +  if (bytesread < 0)
  1.4297 +    return -1;
  1.4298 +  damr->modeChangePeriod = handle->buf[0];
  1.4299 +  totalbytesread += bytesread;
  1.4300 +
  1.4301 +  bytesread = readData(handle, handle->buf, 1);
  1.4302 +  if (bytesread < 0)
  1.4303 +    return -1;
  1.4304 +  damr->framesPerSample = handle->buf[0];
  1.4305 +  totalbytesread += bytesread;
  1.4306 +
  1.4307 +  return totalbytesread;
  1.4308 +}
  1.4309 +
  1.4310 +
  1.4311 +/*
  1.4312 + * Function:
  1.4313 + *
  1.4314 + *   mp4_i32 freeFTYP(MP4HandleImp handle)
  1.4315 + *
  1.4316 + * Description:
  1.4317 + *
  1.4318 + *   This function frees memory for FTYP atom.
  1.4319 + *
  1.4320 + * Parameters:
  1.4321 + *
  1.4322 + *   ftyp       FTYP atom pointer
  1.4323 + *
  1.4324 + * Return value:
  1.4325 + *
  1.4326 + *   0          Success
  1.4327 + *   Negative   Error
  1.4328 + *
  1.4329 + */
  1.4330 +mp4_i32 freeFTYP(fileTypeAtom *ftyp)
  1.4331 +{
  1.4332 +  if (ftyp)
  1.4333 +  {
  1.4334 +    if (freeAtomHeader(ftyp->atomhdr) < 0)
  1.4335 +      return -1;
  1.4336 +    if (ftyp->compatibleBrands)
  1.4337 +      mp4free(ftyp->compatibleBrands);
  1.4338 +
  1.4339 +    mp4free(ftyp);
  1.4340 +  }
  1.4341 +
  1.4342 +  return 0;
  1.4343 +}
  1.4344 +
  1.4345 +
  1.4346 +/*
  1.4347 + * Function:
  1.4348 + *
  1.4349 + *   mp4_i32 freeMOOV(movieAtom *moov)
  1.4350 + *
  1.4351 + * Description:
  1.4352 + *
  1.4353 + *   This function frees memory for MOOV atom.
  1.4354 + *
  1.4355 + * Parameters:
  1.4356 + *
  1.4357 + *   moov       MOOV atom pointer
  1.4358 + *
  1.4359 + * Return value:
  1.4360 + *
  1.4361 + *   0          Success
  1.4362 + *   Negative   Error
  1.4363 + *
  1.4364 + */
  1.4365 +mp4_i32 freeMOOV(movieAtom *moov)
  1.4366 +{
  1.4367 +  if (moov)
  1.4368 +  {
  1.4369 +    if (freeAtomHeader(moov->atomhdr) < 0)
  1.4370 +      return -1;
  1.4371 +    if (freeMVHD(moov->mvhd) < 0)
  1.4372 +      return -1;
  1.4373 +    if (freeTRAK(moov->trakAudio) < 0)
  1.4374 +      return -1;
  1.4375 +    if (freeTRAK(moov->trakVideo) < 0)
  1.4376 +      return -1;
  1.4377 +    if (freeIODS(moov->iods) < 0)
  1.4378 +      return -1;
  1.4379 +    if (freeUDTA(moov->udta) < 0)
  1.4380 +      return -1;
  1.4381 +    if (freeMETA(moov->meta) < 0)
  1.4382 +      return -1;
  1.4383 +
  1.4384 +    mp4free(moov);
  1.4385 +  }
  1.4386 +
  1.4387 +  return 0;
  1.4388 +}
  1.4389 +
  1.4390 +
  1.4391 +/*
  1.4392 + * Function:
  1.4393 + *
  1.4394 + *   mp4_i32 freeAtomHeader(atomHeader *atomhdr)
  1.4395 + *
  1.4396 + * Description:
  1.4397 + *
  1.4398 + *   This function frees memory for atom header.
  1.4399 + *
  1.4400 + * Parameters:
  1.4401 + *
  1.4402 + *   atomhdr    atom header pointer
  1.4403 + *
  1.4404 + * Return value:
  1.4405 + *
  1.4406 + *   0          Success
  1.4407 + *   Negative   Error
  1.4408 + *
  1.4409 + */
  1.4410 +mp4_i32 freeAtomHeader(atomHeader *atomhdr)
  1.4411 +{
  1.4412 +  if (atomhdr)
  1.4413 +    mp4free(atomhdr);
  1.4414 +
  1.4415 +  return 0;
  1.4416 +}
  1.4417 +
  1.4418 +
  1.4419 +/*
  1.4420 + * Function:
  1.4421 + *
  1.4422 + *   mp4_i32 freeMVHD(movieHeaderAtom *mvhd)
  1.4423 + *
  1.4424 + * Description:
  1.4425 + *
  1.4426 + *   This function frees memory for MVHD atom.
  1.4427 + *
  1.4428 + * Parameters:
  1.4429 + *
  1.4430 + *   mvhd       MVHD atom pointer
  1.4431 + *
  1.4432 + * Return value:
  1.4433 + *
  1.4434 + *   0          Success
  1.4435 + *   Negative   Error
  1.4436 + *
  1.4437 + */
  1.4438 +mp4_i32 freeMVHD(movieHeaderAtom *mvhd)
  1.4439 +{
  1.4440 +  if (mvhd)
  1.4441 +  {
  1.4442 +    if (freeAtomHeader(mvhd->atomhdr) < 0)
  1.4443 +      return -1;
  1.4444 +
  1.4445 +    mp4free(mvhd);
  1.4446 +  }
  1.4447 +
  1.4448 +  return 0;
  1.4449 +}
  1.4450 +
  1.4451 +
  1.4452 +/*
  1.4453 + * Function:
  1.4454 + *
  1.4455 + *   mp4_i32 freeTRAK(trackAtom *trak)
  1.4456 + *
  1.4457 + * Description:
  1.4458 + *
  1.4459 + *   This function frees memory for TRAK atom.
  1.4460 + *
  1.4461 + * Parameters:
  1.4462 + *
  1.4463 + *   trak       TRAK atom pointer
  1.4464 + *
  1.4465 + * Return value:
  1.4466 + *
  1.4467 + *   0          Success
  1.4468 + *   Negative   Error
  1.4469 + *
  1.4470 + */
  1.4471 +mp4_i32 freeTRAK(trackAtom *trak)
  1.4472 +{
  1.4473 +  if (trak)
  1.4474 +  {
  1.4475 +    if (freeAtomHeader(trak->atomhdr) < 0)
  1.4476 +      return -1;
  1.4477 +    if (freeTKHD(trak->tkhd) < 0)
  1.4478 +      return -1;
  1.4479 +    if (freeTREF(trak->tref) < 0)
  1.4480 +      return -1;
  1.4481 +    if (freeEDTS(trak->edts) < 0)
  1.4482 +      return -1;
  1.4483 +    if (freeMDIA(trak->mdia) < 0)
  1.4484 +      return -1;
  1.4485 +    if (freeUDTA(trak->udta) < 0)
  1.4486 +      return -1;
  1.4487 +
  1.4488 +    mp4free(trak);
  1.4489 +  }
  1.4490 +
  1.4491 +  return 0;
  1.4492 +}
  1.4493 +
  1.4494 +
  1.4495 +/*
  1.4496 + * Function:
  1.4497 + *
  1.4498 + *   mp4_i32 freeTKHD(trackHeaderAtom *tkhd)
  1.4499 + *
  1.4500 + * Description:
  1.4501 + *
  1.4502 + *   This function frees memory for TKHD atom.
  1.4503 + *
  1.4504 + * Parameters:
  1.4505 + *
  1.4506 + *   tkhd       TKHD atom pointer
  1.4507 + *
  1.4508 + * Return value:
  1.4509 + *
  1.4510 + *   0          Success
  1.4511 + *   Negative   Error
  1.4512 + *
  1.4513 + */
  1.4514 +mp4_i32 freeTKHD(trackHeaderAtom *tkhd)
  1.4515 +{
  1.4516 +  if (tkhd)
  1.4517 +  {
  1.4518 +    if (freeAtomHeader(tkhd->atomhdr) < 0)
  1.4519 +      return -1;
  1.4520 +
  1.4521 +    mp4free(tkhd);
  1.4522 +  }
  1.4523 +
  1.4524 +  return 0;
  1.4525 +}
  1.4526 +
  1.4527 +
  1.4528 +/*
  1.4529 + * Function:
  1.4530 + *
  1.4531 + *   mp4_i32 freeTREF(trackReferenceAtom *tref)
  1.4532 + *
  1.4533 + * Description:
  1.4534 + *
  1.4535 + *   This function frees memory for TREF atom.
  1.4536 + *
  1.4537 + * Parameters:
  1.4538 + *
  1.4539 + *   tref       TREF atom pointer
  1.4540 + *
  1.4541 + * Return value:
  1.4542 + *
  1.4543 + *   0          Success
  1.4544 + *   Negative   Error
  1.4545 + *
  1.4546 + */
  1.4547 +mp4_i32 freeTREF(trackReferenceAtom *tref)
  1.4548 +{
  1.4549 +  if (tref)
  1.4550 +  {
  1.4551 +    if (freeAtomHeader(tref->atomhdr) < 0)
  1.4552 +      return -1;
  1.4553 +
  1.4554 +    mp4free(tref);
  1.4555 +  }
  1.4556 +
  1.4557 +  return 0;
  1.4558 +}
  1.4559 +
  1.4560 +
  1.4561 +/*
  1.4562 + * Function:
  1.4563 + *
  1.4564 + *   mp4_i32 freeEDTS(editListContainerAtom *edts)
  1.4565 + *
  1.4566 + * Description:
  1.4567 + *
  1.4568 + *   This function frees memory for EDTS atom.
  1.4569 + *
  1.4570 + * Parameters:
  1.4571 + *
  1.4572 + *   edts       EDTS atom pointer
  1.4573 + *
  1.4574 + * Return value:
  1.4575 + *
  1.4576 + *   0          Success
  1.4577 + *   Negative   Error
  1.4578 + *
  1.4579 + */
  1.4580 +mp4_i32 freeEDTS(editListContainerAtom *edts)
  1.4581 +{
  1.4582 +  if (edts)
  1.4583 +  {
  1.4584 +    if (freeAtomHeader(edts->atomhdr) < 0)
  1.4585 +      return -1;
  1.4586 +
  1.4587 +    mp4free(edts);
  1.4588 +  }
  1.4589 +
  1.4590 +  return 0;
  1.4591 +}
  1.4592 +
  1.4593 +
  1.4594 +/*
  1.4595 + * Function:
  1.4596 + *
  1.4597 + *   mp4_i32 freeMDIA(mediaAtom *mdia)
  1.4598 + *
  1.4599 + * Description:
  1.4600 + *
  1.4601 + *   This function frees memory for MDIA atom.
  1.4602 + *
  1.4603 + * Parameters:
  1.4604 + *
  1.4605 + *   mdia       MDIA atom pointer
  1.4606 + *
  1.4607 + * Return value:
  1.4608 + *
  1.4609 + *   0          Success
  1.4610 + *   Negative   Error
  1.4611 + *
  1.4612 + */
  1.4613 +mp4_i32 freeMDIA(mediaAtom *mdia)
  1.4614 +{
  1.4615 +  if (mdia)
  1.4616 +  {
  1.4617 +    if (freeAtomHeader(mdia->atomhdr) < 0)
  1.4618 +      return -1;
  1.4619 +    if (freeMDHD(mdia->mdhd) < 0)
  1.4620 +      return -1;
  1.4621 +    if (freeHDLR(mdia->hdlr) < 0)
  1.4622 +      return -1;
  1.4623 +    if (freeMINF(mdia->minf) < 0)
  1.4624 +      return -1;
  1.4625 +
  1.4626 +    mp4free(mdia);
  1.4627 +  }
  1.4628 +
  1.4629 +  return 0;
  1.4630 +}
  1.4631 +
  1.4632 +
  1.4633 +/*
  1.4634 + * Function:
  1.4635 + *
  1.4636 + *   mp4_i32 freeMDHD(mediaHeaderAtom *mdhd)
  1.4637 + *
  1.4638 + * Description:
  1.4639 + *
  1.4640 + *   This function frees memory for MDHD atom.
  1.4641 + *
  1.4642 + * Parameters:
  1.4643 + *
  1.4644 + *   mdhd       MDHD atom pointer
  1.4645 + *
  1.4646 + * Return value:
  1.4647 + *
  1.4648 + *   0          Success
  1.4649 + *   Negative   Error
  1.4650 + *
  1.4651 + */
  1.4652 +mp4_i32 freeMDHD(mediaHeaderAtom *mdhd)
  1.4653 +{
  1.4654 +  if (mdhd)
  1.4655 +  {
  1.4656 +    if (freeAtomHeader(mdhd->atomhdr) < 0)
  1.4657 +      return -1;
  1.4658 +
  1.4659 +    mp4free(mdhd);
  1.4660 +  }
  1.4661 +
  1.4662 +  return 0;
  1.4663 +}
  1.4664 +
  1.4665 +
  1.4666 +/*
  1.4667 + * Function:
  1.4668 + *
  1.4669 + *   mp4_i32 freeHDLR(handlerAtom *hdlr)
  1.4670 + *
  1.4671 + * Description:
  1.4672 + *
  1.4673 + *   This function frees memory for HDLR atom.
  1.4674 + *
  1.4675 + * Parameters:
  1.4676 + *
  1.4677 + *   hdlr       HDLR atom pointer
  1.4678 + *
  1.4679 + * Return value:
  1.4680 + *
  1.4681 + *   0          Success
  1.4682 + *   Negative   Error
  1.4683 + *
  1.4684 + */
  1.4685 +mp4_i32 freeHDLR(handlerAtom *hdlr)
  1.4686 +{
  1.4687 +  if (hdlr)
  1.4688 +  {
  1.4689 +    if (freeAtomHeader(hdlr->atomhdr) < 0)
  1.4690 +      return -1;
  1.4691 +    if (hdlr->name)
  1.4692 +      mp4free(hdlr->name);
  1.4693 +
  1.4694 +    mp4free(hdlr);
  1.4695 +  }
  1.4696 +
  1.4697 +  return 0;
  1.4698 +}
  1.4699 +
  1.4700 +
  1.4701 +/*
  1.4702 + * Function:
  1.4703 + *
  1.4704 + *   mp4_i32 freeMINF(mediaInformationAtom *minf)
  1.4705 + *
  1.4706 + * Description:
  1.4707 + *
  1.4708 + *   This function frees memory for MINF atom.
  1.4709 + *
  1.4710 + * Parameters:
  1.4711 + *
  1.4712 + *   minf       MINF atom pointer
  1.4713 + *
  1.4714 + * Return value:
  1.4715 + *
  1.4716 + *   0          Success
  1.4717 + *   Negative   Error
  1.4718 + *
  1.4719 + */
  1.4720 +mp4_i32 freeMINF(mediaInformationAtom *minf)
  1.4721 +{
  1.4722 +  if (minf)
  1.4723 +  {
  1.4724 +    if (freeAtomHeader(minf->atomhdr) < 0)
  1.4725 +      return -1;
  1.4726 +    if (freeVMHD(minf->vmhd) < 0)
  1.4727 +      return -1;
  1.4728 +    if (freeSMHD(minf->smhd) < 0)
  1.4729 +      return -1;
  1.4730 +    if (freeDINF(minf->dinf) < 0)
  1.4731 +      return -1;
  1.4732 +    if (freeSTBL(minf->stbl) < 0)
  1.4733 +      return -1;
  1.4734 +
  1.4735 +    mp4free(minf);
  1.4736 +  }
  1.4737 +
  1.4738 +  return 0;
  1.4739 +}
  1.4740 +
  1.4741 +
  1.4742 +/*
  1.4743 + * Function:
  1.4744 + *
  1.4745 + *   mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd)
  1.4746 + *
  1.4747 + * Description:
  1.4748 + *
  1.4749 + *   This function frees memory for VMHD atom.
  1.4750 + *
  1.4751 + * Parameters:
  1.4752 + *
  1.4753 + *   vmhd       VMHD atom pointer
  1.4754 + *
  1.4755 + * Return value:
  1.4756 + *
  1.4757 + *   0          Success
  1.4758 + *   Negative   Error
  1.4759 + *
  1.4760 + */
  1.4761 +mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd)
  1.4762 +{
  1.4763 +  if (vmhd)
  1.4764 +  {
  1.4765 +    if (freeAtomHeader(vmhd->atomhdr) < 0)
  1.4766 +      return -1;
  1.4767 +
  1.4768 +    mp4free(vmhd);
  1.4769 +  }
  1.4770 +
  1.4771 +  return 0;
  1.4772 +}
  1.4773 +
  1.4774 +
  1.4775 +/*
  1.4776 + * Function:
  1.4777 + *
  1.4778 + *   mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd)
  1.4779 + *
  1.4780 + * Description:
  1.4781 + *
  1.4782 + *   This function frees memory for SMHD atom.
  1.4783 + *
  1.4784 + * Parameters:
  1.4785 + *
  1.4786 + *   smhd       SMHD atom pointer
  1.4787 + *
  1.4788 + * Return value:
  1.4789 + *
  1.4790 + *   0          Success
  1.4791 + *   Negative   Error
  1.4792 + *
  1.4793 + */
  1.4794 +mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd)
  1.4795 +{
  1.4796 +  if (smhd)
  1.4797 +  {
  1.4798 +    if (freeAtomHeader(smhd->atomhdr) < 0)
  1.4799 +      return -1;
  1.4800 +
  1.4801 +    mp4free(smhd);
  1.4802 +  }
  1.4803 +
  1.4804 +  return 0;
  1.4805 +}
  1.4806 +
  1.4807 +
  1.4808 +/*
  1.4809 + * Function:
  1.4810 + *
  1.4811 + *   mp4_i32 freeDINF(dataInformationAtom *dinf)
  1.4812 + *
  1.4813 + * Description:
  1.4814 + *
  1.4815 + *   This function frees memory for DINF atom.
  1.4816 + *
  1.4817 + * Parameters:
  1.4818 + *
  1.4819 + *   dinf       DINF atom pointer
  1.4820 + *
  1.4821 + * Return value:
  1.4822 + *
  1.4823 + *   0          Success
  1.4824 + *   Negative   Error
  1.4825 + *
  1.4826 + */
  1.4827 +mp4_i32 freeDINF(dataInformationAtom *dinf)
  1.4828 +{
  1.4829 +  if (dinf)
  1.4830 +  {
  1.4831 +    if (freeAtomHeader(dinf->atomhdr) < 0)
  1.4832 +      return -1;
  1.4833 +    if (freeDREF(dinf->dref) < 0)
  1.4834 +      return -1;
  1.4835 +
  1.4836 +    mp4free(dinf);
  1.4837 +  }
  1.4838 +
  1.4839 +  return 0;
  1.4840 +}
  1.4841 +
  1.4842 +
  1.4843 +/*
  1.4844 + * Function:
  1.4845 + *
  1.4846 + *   mp4_i32 freeDREF(dataReferenceAtom *dref)
  1.4847 + *
  1.4848 + * Description:
  1.4849 + *
  1.4850 + *   This function frees memory for DREF atom.
  1.4851 + *
  1.4852 + * Parameters:
  1.4853 + *
  1.4854 + *   dref       DREF atom pointer
  1.4855 + *
  1.4856 + * Return value:
  1.4857 + *
  1.4858 + *   0          Success
  1.4859 + *   Negative   Error
  1.4860 + *
  1.4861 + */
  1.4862 +mp4_i32 freeDREF(dataReferenceAtom *dref)
  1.4863 +{
  1.4864 +  if (dref)
  1.4865 +  {
  1.4866 +    if (freeAtomHeader(dref->atomhdr) < 0)
  1.4867 +      return -1;
  1.4868 +    if (freeURL(dref->url) < 0)
  1.4869 +      return -1;
  1.4870 +    if (freeURN(dref->urn) < 0)
  1.4871 +      return -1;
  1.4872 +
  1.4873 +    mp4free(dref);
  1.4874 +  }
  1.4875 +
  1.4876 +  return 0;
  1.4877 +}
  1.4878 +
  1.4879 +
  1.4880 +/*
  1.4881 + * Function:
  1.4882 + *
  1.4883 + *   mp4_i32 freeURL(dataEntryURLAtom *url)
  1.4884 + *
  1.4885 + * Description:
  1.4886 + *
  1.4887 + *   This function frees memory for URL atom.
  1.4888 + *
  1.4889 + * Parameters:
  1.4890 + *
  1.4891 + *   url        URL atom pointer
  1.4892 + *
  1.4893 + * Return value:
  1.4894 + *
  1.4895 + *   0          Success
  1.4896 + *   Negative   Error
  1.4897 + *
  1.4898 + */
  1.4899 +mp4_i32 freeURL(dataEntryURLAtom *url)
  1.4900 +{
  1.4901 +  if (url)
  1.4902 +  {
  1.4903 +    if (freeAtomHeader(url->atomhdr) < 0)
  1.4904 +      return -1;
  1.4905 +
  1.4906 +    mp4free(url);
  1.4907 +  }
  1.4908 +
  1.4909 +  return 0;
  1.4910 +}
  1.4911 +
  1.4912 +
  1.4913 +/*
  1.4914 + * Function:
  1.4915 + *
  1.4916 + *   mp4_i32 freeURN(dataEntryURNAtom *urn)
  1.4917 + *
  1.4918 + * Description:
  1.4919 + *
  1.4920 + *   This function frees memory for URN atom.
  1.4921 + *
  1.4922 + * Parameters:
  1.4923 + *
  1.4924 + *   urn        URN atom pointer
  1.4925 + *
  1.4926 + * Return value:
  1.4927 + *
  1.4928 + *   0          Success
  1.4929 + *   Negative   Error
  1.4930 + *
  1.4931 + */
  1.4932 +mp4_i32 freeURN(dataEntryURNAtom *urn)
  1.4933 +{
  1.4934 +  if (urn)
  1.4935 +  {
  1.4936 +    if (freeAtomHeader(urn->atomhdr) < 0)
  1.4937 +      return -1;
  1.4938 +
  1.4939 +    mp4free(urn);
  1.4940 +  }
  1.4941 +
  1.4942 +  return 0;
  1.4943 +}
  1.4944 +
  1.4945 +
  1.4946 +/*
  1.4947 + * Function:
  1.4948 + *
  1.4949 + *   mp4_i32 freeSTBL(sampleTableAtom *stbl)
  1.4950 + *
  1.4951 + * Description:
  1.4952 + *
  1.4953 + *   This function frees memory for STBL atom.
  1.4954 + *
  1.4955 + * Parameters:
  1.4956 + *
  1.4957 + *   stbl       STBL atom pointer
  1.4958 + *
  1.4959 + * Return value:
  1.4960 + *
  1.4961 + *   0          Success
  1.4962 + *   Negative   Error
  1.4963 + *
  1.4964 + */
  1.4965 +mp4_i32 freeSTBL(sampleTableAtom *stbl)
  1.4966 +{
  1.4967 +  if (stbl)
  1.4968 +  {
  1.4969 +    if (freeAtomHeader(stbl->atomhdr) < 0)
  1.4970 +      return -1;
  1.4971 +    if (freeSTTS(stbl->stts) < 0)
  1.4972 +      return -1;
  1.4973 +    if (freeCTTS(stbl->ctts) < 0)
  1.4974 +      return -1;
  1.4975 +    if (freeSTSD(stbl->stsd) < 0)
  1.4976 +      return -1;
  1.4977 +    if (freeSTSZ(stbl->stsz) < 0)
  1.4978 +      return -1;
  1.4979 +    if (freeSTSC(stbl->stsc) < 0)
  1.4980 +      return -1;
  1.4981 +    if (stbl->is32BitOffsets)
  1.4982 +    {
  1.4983 +    
  1.4984 +      if (freeSTCO(stbl->stco) < 0)
  1.4985 +        return -1;
  1.4986 +    }
  1.4987 +    else
  1.4988 +    {
  1.4989 +    
  1.4990 +      if (freeSTCO64(stbl->stco64) < 0)
  1.4991 +        return -1;
  1.4992 +    }
  1.4993 +    if (freeSTSS(stbl->stss) < 0)
  1.4994 +      return -1;
  1.4995 +    if (freeSTSH(stbl->stsh) < 0)
  1.4996 +      return -1;
  1.4997 +    if (freeSDTP(stbl->sdtp) < 0)
  1.4998 +      return -1;
  1.4999 +
  1.5000 +    mp4free(stbl);
  1.5001 +  }
  1.5002 +
  1.5003 +  return 0;
  1.5004 +}
  1.5005 +
  1.5006 +
  1.5007 +/*
  1.5008 + * Function:
  1.5009 + *
  1.5010 + *   mp4_i32 freeSTTS(timeToSampleAtom *stts)
  1.5011 + *
  1.5012 + * Description:
  1.5013 + *
  1.5014 + *   This function frees memory for STTS atom.
  1.5015 + *
  1.5016 + * Parameters:
  1.5017 + *
  1.5018 + *   stts       STTS atom pointer
  1.5019 + *
  1.5020 + * Return value:
  1.5021 + *
  1.5022 + *   0          Success
  1.5023 + *   Negative   Error
  1.5024 + *
  1.5025 + */
  1.5026 +mp4_i32 freeSTTS(timeToSampleAtom *stts)
  1.5027 +{
  1.5028 +  if (stts)
  1.5029 +  {
  1.5030 +    if (freeAtomHeader(stts->atomhdr) < 0)
  1.5031 +      return -1;
  1.5032 +    if (stts->sampleCount)
  1.5033 +      mp4free(stts->sampleCount);
  1.5034 +    if (stts->sampleDelta)
  1.5035 +      mp4free(stts->sampleDelta);
  1.5036 +
  1.5037 +    mp4free(stts);
  1.5038 +  }
  1.5039 +
  1.5040 +  return 0;
  1.5041 +}
  1.5042 +
  1.5043 +
  1.5044 +/*
  1.5045 + * Function:
  1.5046 + *
  1.5047 + *   mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts)
  1.5048 + *
  1.5049 + * Description:
  1.5050 + *
  1.5051 + *   This function frees memory for CTTS atom.
  1.5052 + *
  1.5053 + * Parameters:
  1.5054 + *
  1.5055 + *   ctts       CTTS atom pointer
  1.5056 + *
  1.5057 + * Return value:
  1.5058 + *
  1.5059 + *   0          Success
  1.5060 + *   Negative   Error
  1.5061 + *
  1.5062 + */
  1.5063 +mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts)
  1.5064 +{
  1.5065 +  if (ctts)
  1.5066 +  {
  1.5067 +    if (freeAtomHeader(ctts->atomhdr) < 0)
  1.5068 +      return -1;
  1.5069 +    if (ctts->sampleCount)
  1.5070 +      mp4free(ctts->sampleCount);
  1.5071 +    if (ctts->sampleOffset)
  1.5072 +      mp4free(ctts->sampleOffset);
  1.5073 +
  1.5074 +    mp4free(ctts);
  1.5075 +  }
  1.5076 +
  1.5077 +  return 0;
  1.5078 +}
  1.5079 +
  1.5080 +
  1.5081 +/*
  1.5082 + * Function:
  1.5083 + *
  1.5084 + *   mp4_i32 freeSTSD(sampleDescriptionAtom *stsd)
  1.5085 + *
  1.5086 + * Description:
  1.5087 + *
  1.5088 + *   This function frees memory for STSD atom.
  1.5089 + *
  1.5090 + * Parameters:
  1.5091 + *
  1.5092 + *   stsd       STSD atom pointer
  1.5093 + *
  1.5094 + * Return value:
  1.5095 + *
  1.5096 + *   0          Success
  1.5097 + *   Negative   Error
  1.5098 + *
  1.5099 + */
  1.5100 +mp4_i32 freeSTSD(sampleDescriptionAtom *stsd)
  1.5101 +{
  1.5102 +  mp4_u32 sampleentrycount = 0;
  1.5103 +  mp4_u32 entryindex;
  1.5104 +  
  1.5105 +  if (stsd)
  1.5106 +  {
  1.5107 +	sampleentrycount = stsd->entryCount;
  1.5108 +
  1.5109 +    if (freeAtomHeader(stsd->atomhdr) < 0)
  1.5110 +      return -1;
  1.5111 +	for (entryindex = 0; entryindex < sampleentrycount; entryindex++)
  1.5112 +	{
  1.5113 +		if (freeMP4V(stsd->mp4v[entryindex]) < 0)
  1.5114 +		  return -1;
  1.5115 +		if (freeMP4A(stsd->mp4a[entryindex]) < 0)
  1.5116 +		  return -1;
  1.5117 +		if (freeMP4S(stsd->mp4s[entryindex]) < 0)
  1.5118 +		  return -1;
  1.5119 +		if (freeS263(stsd->s263[entryindex]) < 0)
  1.5120 +		  return -1;
  1.5121 +		if (freeSAMR(stsd->samr[entryindex]) < 0)
  1.5122 +		  return -1;
  1.5123 +		if (freeSAWB(stsd->sawb[entryindex]) < 0)
  1.5124 +		  return -1;
  1.5125 +		if (freeAVC1(stsd->avc1[entryindex]) < 0)
  1.5126 +			return -1;
  1.5127 +        if (freeSQCP(stsd->sqcp[entryindex]) < 0)
  1.5128 +          return -1;
  1.5129 +	}
  1.5130 +    mp4free(stsd);
  1.5131 +  }
  1.5132 +
  1.5133 +  return 0;
  1.5134 +}
  1.5135 +
  1.5136 +
  1.5137 +/*
  1.5138 + * Function:
  1.5139 + *
  1.5140 + *   mp4_i32 freeMP4V(visualSampleEntry *mp4v)
  1.5141 + *
  1.5142 + * Description:
  1.5143 + *
  1.5144 + *   This function frees memory for MP4V atom.
  1.5145 + *
  1.5146 + * Parameters:
  1.5147 + *
  1.5148 + *   mp4v       MP4V atom pointer
  1.5149 + *
  1.5150 + * Return value:
  1.5151 + *
  1.5152 + *   0          Success
  1.5153 + *   Negative   Error
  1.5154 + *
  1.5155 + */
  1.5156 +mp4_i32 freeMP4V(visualSampleEntry *mp4v)
  1.5157 +{
  1.5158 +  if (mp4v)
  1.5159 +  {
  1.5160 +    if (freeAtomHeader(mp4v->atomhdr) < 0)
  1.5161 +      return -1;
  1.5162 +    if (freeESD(mp4v->esd) < 0)
  1.5163 +      return -1;
  1.5164 +
  1.5165 +    mp4free(mp4v);
  1.5166 +  }
  1.5167 +
  1.5168 +  return 0;
  1.5169 +}
  1.5170 +
  1.5171 +
  1.5172 +/*
  1.5173 + * Function:
  1.5174 + *
  1.5175 + *   mp4_i32 freeESD(ESDAtom *esd)
  1.5176 + *
  1.5177 + * Description:
  1.5178 + *
  1.5179 + *   This function frees memory for ESD atom.
  1.5180 + *
  1.5181 + * Parameters:
  1.5182 + *
  1.5183 + *   esd        ESD atom pointer
  1.5184 + *
  1.5185 + * Return value:
  1.5186 + *
  1.5187 + *   0          Success
  1.5188 + *   Negative   Error
  1.5189 + *
  1.5190 + */
  1.5191 +mp4_i32 freeESD(ESDAtom *esd)
  1.5192 +{
  1.5193 +  if (esd)
  1.5194 +  {
  1.5195 +    if (freeAtomHeader(esd->atomhdr) < 0)
  1.5196 +      return -1;
  1.5197 +    if (esd->URLString)
  1.5198 +      mp4free(esd->URLString);
  1.5199 +    if (esd->decSpecificInfo)
  1.5200 +      mp4free(esd->decSpecificInfo);
  1.5201 +
  1.5202 +    mp4free(esd);
  1.5203 +  }
  1.5204 +
  1.5205 +  return 0;
  1.5206 +}
  1.5207 +
  1.5208 +
  1.5209 +/*
  1.5210 + * Function:
  1.5211 + *
  1.5212 + *   mp4_i32 freeMP4A(audioSampleEntry *mp4a)
  1.5213 + *
  1.5214 + * Description:
  1.5215 + *
  1.5216 + *   This function frees memory for MP4A atom.
  1.5217 + *
  1.5218 + * Parameters:
  1.5219 + *
  1.5220 + *   mp4a       MP4A atom pointer
  1.5221 + *
  1.5222 + * Return value:
  1.5223 + *
  1.5224 + *   0          Success
  1.5225 + *   Negative   Error
  1.5226 + *
  1.5227 + */
  1.5228 +mp4_i32 freeMP4A(audioSampleEntry *mp4a)
  1.5229 +{
  1.5230 +  if (mp4a)
  1.5231 +  {
  1.5232 +    if (freeAtomHeader(mp4a->atomhdr) < 0)
  1.5233 +      return -1;
  1.5234 +    if (freeESD(mp4a->esd) < 0)
  1.5235 +      return -1;
  1.5236 +
  1.5237 +    mp4free(mp4a);
  1.5238 +  }
  1.5239 +
  1.5240 +  return 0;
  1.5241 +}
  1.5242 +
  1.5243 +
  1.5244 +/*
  1.5245 + * Function:
  1.5246 + *
  1.5247 + *   mp4_i32 freeMP4S(mpegSampleEntry *mp4s)
  1.5248 + *
  1.5249 + * Description:
  1.5250 + *
  1.5251 + *   This function frees memory for MP4S atom.
  1.5252 + *
  1.5253 + * Parameters:
  1.5254 + *
  1.5255 + *   mp4s       MP4S atom pointer
  1.5256 + *
  1.5257 + * Return value:
  1.5258 + *
  1.5259 + *   0          Success
  1.5260 + *   Negative   Error
  1.5261 + *
  1.5262 + */
  1.5263 +mp4_i32 freeMP4S(mpegSampleEntry *mp4s)
  1.5264 +{
  1.5265 +  if (mp4s)
  1.5266 +  {
  1.5267 +    if (freeAtomHeader(mp4s->atomhdr) < 0)
  1.5268 +      return -1;
  1.5269 +    if (freeESD(mp4s->esd) < 0)
  1.5270 +      return -1;
  1.5271 +
  1.5272 +    mp4free(mp4s);
  1.5273 +  }
  1.5274 +
  1.5275 +  return 0;
  1.5276 +}
  1.5277 +
  1.5278 +
  1.5279 +/*
  1.5280 + * Function:
  1.5281 + *
  1.5282 + *   mp4_i32 freeS263(h263SampleEntry *s263)
  1.5283 + *
  1.5284 + * Description:
  1.5285 + *
  1.5286 + *   This function frees memory for S263 atom.
  1.5287 + *
  1.5288 + * Parameters:
  1.5289 + *
  1.5290 + *   s263       S263 atom pointer
  1.5291 + *
  1.5292 + * Return value:
  1.5293 + *
  1.5294 + *   0          Success
  1.5295 + *   Negative   Error
  1.5296 + *
  1.5297 + */
  1.5298 +mp4_i32 freeS263(h263SampleEntry *s263)
  1.5299 +{
  1.5300 +  if (s263)
  1.5301 +  {
  1.5302 +    if (freeAtomHeader(s263->atomhdr) < 0)
  1.5303 +      return -1;
  1.5304 +    if (freeD263(s263->d263) < 0)
  1.5305 +      return -1;
  1.5306 +
  1.5307 +    mp4free(s263);
  1.5308 +  }
  1.5309 +
  1.5310 +  return 0;
  1.5311 +}
  1.5312 +
  1.5313 +
  1.5314 +/*
  1.5315 + * Function:
  1.5316 + *
  1.5317 + *   mp4_i32 freeD263(h263SpecificAtom *d263)
  1.5318 + *
  1.5319 + * Description:
  1.5320 + *
  1.5321 + *   This function frees memory for D263 atom.
  1.5322 + *
  1.5323 + * Parameters:
  1.5324 + *
  1.5325 + *   d263       D263 atom pointer
  1.5326 + *
  1.5327 + * Return value:
  1.5328 + *
  1.5329 + *   0          Success
  1.5330 + *   Negative   Error
  1.5331 + *
  1.5332 + */
  1.5333 +mp4_i32 freeD263(h263SpecificAtom *d263)
  1.5334 +{
  1.5335 +  if (d263)
  1.5336 +  {
  1.5337 +    if (freeAtomHeader(d263->atomhdr) < 0)
  1.5338 +      return -1;
  1.5339 +    if (freeBITR(d263->bitr) < 0)
  1.5340 +      return -1;
  1.5341 +
  1.5342 +    mp4free(d263);
  1.5343 +  }
  1.5344 +
  1.5345 +  return 0;
  1.5346 +}
  1.5347 +
  1.5348 +
  1.5349 +/*
  1.5350 + * Function:
  1.5351 + *
  1.5352 + *   mp4_i32 freeBITR(BitrateAtom *bitr)
  1.5353 + *
  1.5354 + * Description:
  1.5355 + *
  1.5356 + *   This function frees memory for BITR atom.
  1.5357 + *
  1.5358 + * Parameters:
  1.5359 + *
  1.5360 + *   bitr       BITR atom pointer
  1.5361 + *
  1.5362 + * Return value:
  1.5363 + *
  1.5364 + *   0          Success
  1.5365 + *   Negative   Error
  1.5366 + *
  1.5367 + */
  1.5368 +mp4_i32 freeBITR(bitrateAtom *bitr)
  1.5369 +{
  1.5370 +  if (bitr)
  1.5371 +  {
  1.5372 +    if (freeAtomHeader(bitr->atomhdr) < 0)
  1.5373 +      return -1;
  1.5374 +
  1.5375 +    mp4free(bitr);
  1.5376 +  }
  1.5377 +
  1.5378 +  return 0;
  1.5379 +}
  1.5380 +
  1.5381 +
  1.5382 +/*
  1.5383 + * Function:
  1.5384 + *
  1.5385 + *   mp4_i32 freeSAMR(amrSampleEntry *samr)
  1.5386 + *
  1.5387 + * Description:
  1.5388 + *
  1.5389 + *   This function frees memory for SAMR atom.
  1.5390 + *
  1.5391 + * Parameters:
  1.5392 + *
  1.5393 + *   samr       SAMR atom pointer
  1.5394 + *
  1.5395 + * Return value:
  1.5396 + *
  1.5397 + *   0          Success
  1.5398 + *   Negative   Error
  1.5399 + *
  1.5400 + */
  1.5401 +mp4_i32 freeSAMR(amrSampleEntry *samr)
  1.5402 +{
  1.5403 +  if (samr)
  1.5404 +  {
  1.5405 +    if (freeAtomHeader(samr->atomhdr) < 0)
  1.5406 +      return -1;
  1.5407 +    if (freeDAMR(samr->damr) < 0)
  1.5408 +      return -1;
  1.5409 +
  1.5410 +    mp4free(samr);
  1.5411 +  }
  1.5412 +
  1.5413 +  return 0;
  1.5414 +}
  1.5415 +
  1.5416 +
  1.5417 +/*
  1.5418 + * Function:
  1.5419 + *
  1.5420 + *   mp4_i32 freeSAWB(amrSampleEntry *sawb)
  1.5421 + *
  1.5422 + * Description:
  1.5423 + *
  1.5424 + *   This function frees memory for SAWB atom.
  1.5425 + *
  1.5426 + * Parameters:
  1.5427 + *
  1.5428 + *   sawb       SAWB atom pointer
  1.5429 + *
  1.5430 + * Return value:
  1.5431 + *
  1.5432 + *   0          Success
  1.5433 + *   Negative   Error
  1.5434 + *
  1.5435 + */
  1.5436 +mp4_i32 freeSAWB(amrSampleEntry *sawb)
  1.5437 +{
  1.5438 +  if (sawb)
  1.5439 +  {
  1.5440 +    if (freeAtomHeader(sawb->atomhdr) < 0)
  1.5441 +      return -1;
  1.5442 +    if (freeDAMR(sawb->damr) < 0)
  1.5443 +      return -1;
  1.5444 +
  1.5445 +    mp4free(sawb);
  1.5446 +  }
  1.5447 +
  1.5448 +  return 0;
  1.5449 +}
  1.5450 +
  1.5451 +
  1.5452 +/*
  1.5453 + * Function:
  1.5454 + *
  1.5455 + *   mp4_i32 freeDAMR(amrDecSpecStruc *damr)
  1.5456 + *
  1.5457 + * Description:
  1.5458 + *
  1.5459 + *   This function frees memory for DAMR atom.
  1.5460 + *
  1.5461 + * Parameters:
  1.5462 + *
  1.5463 + *   damr       DAMR atom pointer
  1.5464 + *
  1.5465 + * Return value:
  1.5466 + *
  1.5467 + *   0          Success
  1.5468 + *   Negative   Error
  1.5469 + *
  1.5470 + */
  1.5471 +mp4_i32 freeDAMR(amrDecSpecStruc *damr)
  1.5472 +{
  1.5473 +  if (damr)
  1.5474 +  {
  1.5475 +    if (freeAtomHeader(damr->atomhdr) < 0)
  1.5476 +      return -1;
  1.5477 +
  1.5478 +    mp4free(damr);
  1.5479 +  }
  1.5480 +
  1.5481 +  return 0;
  1.5482 +}
  1.5483 +
  1.5484 +
  1.5485 +/*
  1.5486 + * Function:
  1.5487 + *
  1.5488 + *   mp4_i32 freeSTSZ(sampleSizeAtom *stsz)
  1.5489 + *
  1.5490 + * Description:
  1.5491 + *
  1.5492 + *   This function frees memory for STSZ atom.
  1.5493 + *
  1.5494 + * Parameters:
  1.5495 + *
  1.5496 + *   stsz       STSZ atom pointer
  1.5497 + *
  1.5498 + * Return value:
  1.5499 + *
  1.5500 + *   0          Success
  1.5501 + *   Negative   Error
  1.5502 + *
  1.5503 + */
  1.5504 +mp4_i32 freeSTSZ(sampleSizeAtom *stsz)
  1.5505 +{
  1.5506 +  if (stsz)
  1.5507 +  {
  1.5508 +    if (freeAtomHeader(stsz->atomhdr) < 0)
  1.5509 +      return -1;
  1.5510 +    if (stsz->entrySize)
  1.5511 +      mp4free(stsz->entrySize);
  1.5512 +
  1.5513 +    mp4free(stsz);
  1.5514 +  }
  1.5515 +
  1.5516 +  return 0;
  1.5517 +}
  1.5518 +
  1.5519 +
  1.5520 +/*
  1.5521 + * Function:
  1.5522 + *
  1.5523 + *   mp4_i32 freeSTSC(sampleToChunkAtom *stsc)
  1.5524 + *
  1.5525 + * Description:
  1.5526 + *
  1.5527 + *   This function frees memory for STSC atom.
  1.5528 + *
  1.5529 + * Parameters:
  1.5530 + *
  1.5531 + *   stsc       STSC atom pointer
  1.5532 + *
  1.5533 + * Return value:
  1.5534 + *
  1.5535 + *   0          Success
  1.5536 + *   Negative   Error
  1.5537 + *
  1.5538 + */
  1.5539 +mp4_i32 freeSTSC(sampleToChunkAtom *stsc)
  1.5540 +{
  1.5541 +  if (stsc)
  1.5542 +  {
  1.5543 +    if (freeAtomHeader(stsc->atomhdr) < 0)
  1.5544 +      return -1;
  1.5545 +    if (stsc->firstChunk)
  1.5546 +      mp4free(stsc->firstChunk);
  1.5547 +    if (stsc->samplesPerChunk)
  1.5548 +      mp4free(stsc->samplesPerChunk);
  1.5549 +    if (stsc->sampleDescriptionIndex)
  1.5550 +      mp4free(stsc->sampleDescriptionIndex);
  1.5551 +
  1.5552 +    mp4free(stsc);
  1.5553 +  }
  1.5554 +
  1.5555 +  return 0;
  1.5556 +}
  1.5557 +
  1.5558 +
  1.5559 +/*
  1.5560 + * Function:
  1.5561 + *
  1.5562 + *   mp4_i32 freeSTCO(chunkOffsetAtom *stco)
  1.5563 + *
  1.5564 + * Description:
  1.5565 + *
  1.5566 + *   This function frees memory for STCO atom.
  1.5567 + *
  1.5568 + * Parameters:
  1.5569 + *
  1.5570 + *   stco       STCO atom pointer
  1.5571 + *
  1.5572 + * Return value:
  1.5573 + *
  1.5574 + *   0          Success
  1.5575 + *   Negative   Error
  1.5576 + *
  1.5577 + */
  1.5578 +mp4_i32 freeSTCO(chunkOffsetAtom *stco)
  1.5579 +{
  1.5580 +  if (stco)
  1.5581 +  {
  1.5582 +    if (freeAtomHeader(stco->atomhdr) < 0)
  1.5583 +      return -1;
  1.5584 +    if (stco->chunkOffset)
  1.5585 +      mp4free(stco->chunkOffset);
  1.5586 +
  1.5587 +    mp4free(stco);
  1.5588 +  }
  1.5589 +
  1.5590 +  return 0;
  1.5591 +}
  1.5592 +
  1.5593 +/*
  1.5594 + * Function:
  1.5595 + *
  1.5596 + *   mp4_i32 freeSTCO64(chunkOffset64Atom *stco64)
  1.5597 + *
  1.5598 + * Description:
  1.5599 + *
  1.5600 + *   This function frees memory for STCO64 atom.
  1.5601 + *
  1.5602 + * Parameters:
  1.5603 + *
  1.5604 + *   stco64       STCO64 atom pointer
  1.5605 + *
  1.5606 + * Return value:
  1.5607 + *
  1.5608 + *   0          Success
  1.5609 + *   Negative   Error
  1.5610 + *
  1.5611 + */
  1.5612 +mp4_i32 freeSTCO64(chunkOffset64Atom *stco64)
  1.5613 +{
  1.5614 +  if (stco64)
  1.5615 +  {
  1.5616 +    if (freeAtomHeader(stco64->atomhdr) < 0)
  1.5617 +      return -1;
  1.5618 +    if (stco64->chunkOffset)
  1.5619 +      mp4free(stco64->chunkOffset);
  1.5620 +
  1.5621 +    mp4free(stco64);
  1.5622 +  }
  1.5623 +
  1.5624 +  return 0;
  1.5625 +}
  1.5626 +
  1.5627 +
  1.5628 +/*
  1.5629 + * Function:
  1.5630 + *
  1.5631 + *   mp4_i32 freeSTSS(syncSampleAtom *stss)
  1.5632 + *
  1.5633 + * Description:
  1.5634 + *
  1.5635 + *   This function frees memory for STSS atom.
  1.5636 + *
  1.5637 + * Parameters:
  1.5638 + *
  1.5639 + *   stss       STSS atom pointer
  1.5640 + *
  1.5641 + * Return value:
  1.5642 + *
  1.5643 + *   0          Success
  1.5644 + *   Negative   Error
  1.5645 + *
  1.5646 + */
  1.5647 +mp4_i32 freeSTSS(syncSampleAtom *stss)
  1.5648 +{
  1.5649 +  if (stss)
  1.5650 +  {
  1.5651 +    if (freeAtomHeader(stss->atomhdr) < 0)
  1.5652 +      return -1;
  1.5653 +    if (stss->sampleNumber)
  1.5654 +      mp4free(stss->sampleNumber);
  1.5655 +
  1.5656 +    mp4free(stss);
  1.5657 +  }
  1.5658 +
  1.5659 +  return 0;
  1.5660 +}
  1.5661 +
  1.5662 +
  1.5663 +/*
  1.5664 + * Function:
  1.5665 + *
  1.5666 + *   mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh)
  1.5667 + *
  1.5668 + * Description:
  1.5669 + *
  1.5670 + *   This function frees memory for STSH atom.
  1.5671 + *
  1.5672 + * Parameters:
  1.5673 + *
  1.5674 + *   stsh       STSH atom pointer
  1.5675 + *
  1.5676 + * Return value:
  1.5677 + *
  1.5678 + *   0          Success
  1.5679 + *   Negative   Error
  1.5680 + *
  1.5681 + */
  1.5682 +mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh)
  1.5683 +{
  1.5684 +  if (stsh)
  1.5685 +  {
  1.5686 +    if (freeAtomHeader(stsh->atomhdr) < 0)
  1.5687 +      return -1;
  1.5688 +
  1.5689 +    mp4free(stsh);
  1.5690 +  }
  1.5691 +
  1.5692 +  return 0;
  1.5693 +}
  1.5694 +
  1.5695 +
  1.5696 +/*
  1.5697 + * Function:
  1.5698 + *
  1.5699 + *   mp4_i32 freeSDTP(sampleDependencyAtom *sdtp)
  1.5700 + *
  1.5701 + * Description:
  1.5702 + *
  1.5703 + *   This function frees memory for SDTP atom.
  1.5704 + *
  1.5705 + * Parameters:
  1.5706 + *
  1.5707 + *   sdtp       SDTP atom pointer
  1.5708 + *
  1.5709 + * Return value:
  1.5710 + *
  1.5711 + *   0          Success
  1.5712 + *   Negative   Error
  1.5713 + *
  1.5714 + */
  1.5715 +mp4_i32 freeSDTP(sampleDependencyAtom *sdtp)
  1.5716 +	{
  1.5717 +	if (sdtp)
  1.5718 +		{
  1.5719 +		if (freeAtomHeader(sdtp->atomhdr) < 0)
  1.5720 +			{
  1.5721 +			return -1;
  1.5722 +			}
  1.5723 +
  1.5724 +		if (sdtp->dep)
  1.5725 +			{
  1.5726 +			mp4free(sdtp->dep);
  1.5727 +			}		
  1.5728 +    
  1.5729 +		mp4free(sdtp);
  1.5730 +		}
  1.5731 +
  1.5732 +  	return 0;
  1.5733 +	}
  1.5734 +
  1.5735 +/*
  1.5736 + * Function:
  1.5737 + *
  1.5738 + *   mp4_i32 freeIODS(objectDescriptorAtom *iods)
  1.5739 + *
  1.5740 + * Description:
  1.5741 + *
  1.5742 + *   This function frees memory for IODS atom.
  1.5743 + *
  1.5744 + * Parameters:
  1.5745 + *
  1.5746 + *   iods       IODS atom pointer
  1.5747 + *
  1.5748 + * Return value:
  1.5749 + *
  1.5750 + *   0          Success
  1.5751 + *   Negative   Error
  1.5752 + *
  1.5753 + */
  1.5754 +mp4_i32 freeIODS(objectDescriptorAtom *iods)
  1.5755 +{
  1.5756 +  if (iods)
  1.5757 +  {
  1.5758 +    if (freeAtomHeader(iods->atomhdr) < 0)
  1.5759 +      return -1;
  1.5760 +
  1.5761 +    mp4free(iods);
  1.5762 +  }
  1.5763 +
  1.5764 +  return 0;
  1.5765 +}
  1.5766 +
  1.5767 +
  1.5768 +/*
  1.5769 + * Function:
  1.5770 + *
  1.5771 + *   mp4_i32 readUDTA(MP4HandleImp handle,
  1.5772 + *                    userDataAtom *udta)
  1.5773 + *
  1.5774 + * Description:
  1.5775 + *
  1.5776 + *   This function parses one UDTA atom.
  1.5777 + *
  1.5778 + * Parameters:
  1.5779 + *
  1.5780 + *   handle             MP4 library handle
  1.5781 + *   udta               UDTA pointer
  1.5782 + *
  1.5783 + * Return value:
  1.5784 + *
  1.5785 + *   Negative integer   Error
  1.5786 + *   >= 0               Success. Value tells how many bytes were read.
  1.5787 + *
  1.5788 + */
  1.5789 +mp4_i32 readUDTA(MP4HandleImp handle, userDataAtom *udta)
  1.5790 +{
  1.5791 +  mp4_i32 bytesread;
  1.5792 +  mp4_i32 totalbytesread = 0;
  1.5793 +
  1.5794 +  if ((udta->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.5795 +    return -100;
  1.5796 +
  1.5797 +  bytesread = readAtomHeader(handle, udta->atomhdr);
  1.5798 +  if (bytesread < 0)
  1.5799 +    return -1;
  1.5800 +  totalbytesread += bytesread;
  1.5801 +
  1.5802 +  if (udta->atomhdr->type != ATOMTYPE_UDTA)
  1.5803 +    return -1;
  1.5804 +
  1.5805 +  if ( handle->file )
  1.5806 +      {
  1.5807 +      udta->atomcontentloc = handle->diskReadBufStart + handle->diskReadBufPos;
  1.5808 +      }
  1.5809 +  else
  1.5810 +      {
  1.5811 +      udta->atomcontentloc = handle->absPosition;
  1.5812 +      }
  1.5813 +
  1.5814 +  if ( udta->atomhdr->size == 1 )
  1.5815 +      {
  1.5816 +      udta->atomcontentsize = I64INT(udta->atomhdr->largeSize) - (TInt)totalbytesread;
  1.5817 +      }
  1.5818 +  else
  1.5819 +      {
  1.5820 +      udta->atomcontentsize = (TInt)(udta->atomhdr->size - totalbytesread);
  1.5821 +      }
  1.5822 +
  1.5823 +  if ( handle->file )
  1.5824 +  {
  1.5825 +  	if ( seekFile(handle, udta->atomhdr->size - totalbytesread) < 0 )
  1.5826 +  	{
  1.5827 +  	   return -1;	
  1.5828 +  	}
  1.5829 +  	else
  1.5830 +  	{
  1.5831 +  	   return udta->atomhdr->size;	
  1.5832 +  	}
  1.5833 +  }
  1.5834 +  else
  1.5835 +  {
  1.5836 +	  bytesread = discardData(handle, udta->atomhdr->size - totalbytesread);
  1.5837 +	  if (bytesread < 0)
  1.5838 +	    return -1;
  1.5839 +	  totalbytesread += bytesread;
  1.5840 +  }
  1.5841 +  return totalbytesread;
  1.5842 +}
  1.5843 +
  1.5844 +/*
  1.5845 + * Function:
  1.5846 + *
  1.5847 + *   mp4_i32 freeUDTA(userDataAtom *udta)
  1.5848 + *
  1.5849 + * Description:
  1.5850 + *
  1.5851 + *   This function frees memory for UDTA atom.
  1.5852 + *
  1.5853 + * Parameters:
  1.5854 + *
  1.5855 + *   udta       UDTA atom pointer
  1.5856 + *
  1.5857 + * Return value:
  1.5858 + *
  1.5859 + *   0          Success
  1.5860 + *   Negative   Error
  1.5861 + *
  1.5862 + */
  1.5863 +mp4_i32 freeUDTA(userDataAtom *udta)
  1.5864 +{
  1.5865 +  if (udta)
  1.5866 +  {
  1.5867 +    if (freeAtomHeader(udta->atomhdr) < 0)
  1.5868 +      return -1;
  1.5869 +    mp4free(udta);
  1.5870 +  }
  1.5871 +
  1.5872 +  return 0;
  1.5873 +}
  1.5874 +
  1.5875 +
  1.5876 +/*
  1.5877 + * Function:
  1.5878 + *
  1.5879 + *   mp4_i32 determineVideoLength(MP4HandleImp handle,
  1.5880 + *                                mp4_u32 *videolength)
  1.5881 + *
  1.5882 + * Description:
  1.5883 + *
  1.5884 + *   This function determines the length of video in milliseconds.
  1.5885 + *
  1.5886 + * Parameters:
  1.5887 + *
  1.5888 + *   handle       MP4 library handle
  1.5889 + *   videolength  Video length is returned here
  1.5890 + *
  1.5891 + * Return value:
  1.5892 + *
  1.5893 + *   0            Success
  1.5894 + *   Negative     Error
  1.5895 + *
  1.5896 + */
  1.5897 +mp4_i32 determineVideoLength(MP4HandleImp handle, mp4_u32 *videolength)
  1.5898 +{
  1.5899 +  if (!handle->moov)
  1.5900 +    return -1;
  1.5901 +
  1.5902 +  if (!handle->moov->mvhd)
  1.5903 +    return -1;
  1.5904 +
  1.5905 +  if (!handle->moov->trakVideo)
  1.5906 +    return -1;
  1.5907 +
  1.5908 +  if (!handle->moov->trakVideo->tkhd)
  1.5909 +    return -1;
  1.5910 +
  1.5911 +  /* Is timescale set? */
  1.5912 +  if (handle->moov->mvhd->timeScale == 0)
  1.5913 +    return -1;
  1.5914 +
  1.5915 +  *videolength = (mp4_u32)(((mp4_double)handle->moov->trakVideo->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000);
  1.5916 +
  1.5917 +  return 0;
  1.5918 +}
  1.5919 +
  1.5920 +
  1.5921 +/*
  1.5922 + * Function:
  1.5923 + *
  1.5924 + *   mp4_i32 determineFrameRate(MP4HandleImp handle,
  1.5925 + *                              mp4_double *framerate)
  1.5926 + *
  1.5927 + * Description:
  1.5928 + *
  1.5929 + *   This function determines the frame rate of video.
  1.5930 + *
  1.5931 + *   Frame rate is calculated as the average frame rate of the entire video.
  1.5932 + *
  1.5933 + * Parameters:
  1.5934 + *
  1.5935 + *   handle     MP4 library handle
  1.5936 + *   framerate  Frame rate is returned here
  1.5937 + *
  1.5938 + * Return value:
  1.5939 + *
  1.5940 + *   0          Success
  1.5941 + *   Negative   Error
  1.5942 + *
  1.5943 + */
  1.5944 +mp4_i32 determineFrameRate(MP4HandleImp handle, mp4_double *framerate)
  1.5945 +{
  1.5946 +  mp4_double numberofframes;
  1.5947 +  mp4_double length;
  1.5948 +
  1.5949 +
  1.5950 +  if (!handle)
  1.5951 +    return -1;
  1.5952 +  if (!handle->moov)
  1.5953 +    return -1;
  1.5954 +  if (!handle->moov->trakVideo)
  1.5955 +    return -1;
  1.5956 +  if (!handle->moov->trakVideo->mdia)
  1.5957 +    return -1;
  1.5958 +  if (!handle->moov->trakVideo->mdia->minf)
  1.5959 +    return -1;
  1.5960 +  if (!handle->moov->trakVideo->mdia->minf->stbl)
  1.5961 +    return -1;
  1.5962 +  if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
  1.5963 +    return -1;
  1.5964 +  if (!handle->moov->trakVideo->mdia->mdhd)
  1.5965 +    return -1;
  1.5966 +
  1.5967 +
  1.5968 +  	if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
  1.5969 +    	return -1;
  1.5970 +  	
  1.5971 +  	if (handle->moov->trakVideo->mdia->mdhd->duration == 0)
  1.5972 +  		{
  1.5973 +  		*framerate = 0;
  1.5974 +  		}
  1.5975 +	else
  1.5976 +		{
  1.5977 +  		numberofframes = (mp4_double)handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount;
  1.5978 +  		length = (mp4_double)handle->moov->trakVideo->mdia->mdhd->duration /
  1.5979 +           		 (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale;
  1.5980 +
  1.5981 +  		*framerate = numberofframes / length;			
  1.5982 +		}    
  1.5983 +
  1.5984 +  	return 0;
  1.5985 +	}
  1.5986 +
  1.5987 +
  1.5988 +/*
  1.5989 + * Function:
  1.5990 + *
  1.5991 + *   mp4_i32 determineVideoType(MP4HandleImp handle,
  1.5992 + *                              mp4_u32 *videotype)
  1.5993 + *
  1.5994 + * Description:
  1.5995 + *
  1.5996 + *   This function determines the video type of the MP4.
  1.5997 + *
  1.5998 + * Parameters:
  1.5999 + *
  1.6000 + *   handle     MP4 library handle
  1.6001 + *   videotype  Video type is returned here
  1.6002 + *
  1.6003 + * Return value:
  1.6004 + *
  1.6005 + *   0          Success
  1.6006 + *   -1			Error
  1.6007 + *	 -2			Unknown video type
  1.6008 + *
  1.6009 + */
  1.6010 +mp4_i32 determineVideoType(MP4HandleImp handle, mp4_u32 *videotype)
  1.6011 +{
  1.6012 +  *videotype = MP4_TYPE_NONE;
  1.6013 +
  1.6014 +  if (!handle->moov)
  1.6015 +    return -1;
  1.6016 +
  1.6017 +  if (!handle->moov->trakVideo)
  1.6018 +    return -1;
  1.6019 +
  1.6020 +  if (!handle->moov->trakVideo->mdia)
  1.6021 +    return -1;
  1.6022 +
  1.6023 +  if (!handle->moov->trakVideo->mdia->minf)
  1.6024 +    return -1;
  1.6025 +
  1.6026 +  if (!handle->moov->trakVideo->mdia->minf->stbl)
  1.6027 +    return -1;
  1.6028 +
  1.6029 +  if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
  1.6030 +    return -1;
  1.6031 +  
  1.6032 +  if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0)
  1.6033 +    return -1;  
  1.6034 +
  1.6035 +/* Assume that the video type is the same for all sample entries. Just get the video type from the first one */
  1.6036 +
  1.6037 +  if (handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0])
  1.6038 +  {
  1.6039 +    if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd)
  1.6040 +      return -1;
  1.6041 +
  1.6042 +    if ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->objectTypeIndication == 0x20) &&
  1.6043 +        ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->stream >> 2) == 0x04))
  1.6044 +      *videotype = MP4_TYPE_MPEG4_VIDEO;
  1.6045 +  }
  1.6046 +  else
  1.6047 +  if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
  1.6048 +  {
  1.6049 +    if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263)
  1.6050 +      return -1;
  1.6051 +
  1.6052 +    switch (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Profile)
  1.6053 +    {
  1.6054 +    case 0:
  1.6055 +      *videotype = MP4_TYPE_H263_PROFILE_0;
  1.6056 +      break;
  1.6057 +    case 3:
  1.6058 +      *videotype = MP4_TYPE_H263_PROFILE_3;
  1.6059 +      break;
  1.6060 +    default:
  1.6061 +      break;
  1.6062 +    }
  1.6063 +  }
  1.6064 +  else
  1.6065 +   if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0])
  1.6066 +   {
  1.6067 +	   if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc)
  1.6068 +		   return -1;
  1.6069 +
  1.6070 +	   if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize == 0)
  1.6071 +		   return -1;
  1.6072 +
  1.6073 +	   /* AVC profile is in the second byte of the avcconfigrecord */
  1.6074 +	   switch((mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[1]) 
  1.6075 +	   {
  1.6076 +	   case 66:
  1.6077 +		   *videotype = MP4_TYPE_AVC_PROFILE_BASELINE;
  1.6078 +		   break;
  1.6079 +	   case 77:
  1.6080 +		   *videotype = MP4_TYPE_AVC_PROFILE_MAIN;
  1.6081 +		   break;
  1.6082 +	   case 88:
  1.6083 +		   *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED;
  1.6084 +		   break;
  1.6085 +       case 100:
  1.6086 +          *videotype = MP4_TYPE_AVC_PROFILE_HIGH;
  1.6087 +           break;
  1.6088 +	   default:
  1.6089 +		   {
  1.6090 +		   mp4_u8 constraintByte = (mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[2];
  1.6091 +		   if ( (constraintByte & 0x80) || (constraintByte & 0x10) )
  1.6092 +			   {
  1.6093 +			   *videotype = MP4_TYPE_AVC_PROFILE_BASELINE;	
  1.6094 +			   }
  1.6095 +		   else if (constraintByte & 0x40)
  1.6096 +			   {
  1.6097 +			   *videotype = MP4_TYPE_AVC_PROFILE_MAIN;	
  1.6098 +			   }
  1.6099 +		   else if (constraintByte & 0x20)
  1.6100 +			   {
  1.6101 +			   *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED;
  1.6102 +			   }
  1.6103 +		   // NOTE: Cannot reliably determine higher profiles from
  1.6104 +		   // the constraint flags.
  1.6105 +		   break;	   	
  1.6106 +		   }
  1.6107 +	   }
  1.6108 +	}
  1.6109 +   else
  1.6110 +       {}
  1.6111 +   /* Note: Read the AVC level and recreate the actual AVC profile and level in the future! */
  1.6112 +  if (*videotype == MP4_TYPE_NONE)
  1.6113 +    return -2;
  1.6114 +
  1.6115 +  return 0;
  1.6116 +}
  1.6117 +
  1.6118 +
  1.6119 +/*
  1.6120 + * Function:
  1.6121 + *
  1.6122 + *   mp4_i32 determineVideoResolution(MP4HandleImp handle,
  1.6123 + *                                    mp4_u32 *videowidth,
  1.6124 + *                                    mp4_u32 *videoheight)
  1.6125 + *
  1.6126 + * Description:
  1.6127 + *
  1.6128 + *   This function finds out the video width and height from the atom
  1.6129 + *   structure.
  1.6130 + *
  1.6131 + * Parameters:
  1.6132 + *
  1.6133 + *   handle       MP4 library handle
  1.6134 + *   videowidth   Video width is returned here
  1.6135 + *   videoheight  Video height is returned here
  1.6136 + *
  1.6137 + * Return value:
  1.6138 + *
  1.6139 + *   0            Success
  1.6140 + *   Negative     Error
  1.6141 + *
  1.6142 + */
  1.6143 +mp4_i32 determineVideoResolution(MP4HandleImp handle, mp4_u32 *videowidth, mp4_u32 *videoheight)
  1.6144 +{
  1.6145 +  mp4_u32 videotype = MP4_TYPE_NONE;
  1.6146 +
  1.6147 +
  1.6148 +  if (determineVideoType(handle, &videotype) < 0)
  1.6149 +    return -1;
  1.6150 +
  1.6151 +  if (videotype == MP4_TYPE_NONE)
  1.6152 +    return -1;
  1.6153 +
  1.6154 +  if (!handle->moov)
  1.6155 +    return -1;
  1.6156 +
  1.6157 +  if (!handle->moov->trakVideo)
  1.6158 +    return -1;
  1.6159 +
  1.6160 +  if (!handle->moov->trakVideo->mdia)
  1.6161 +    return -1;
  1.6162 +
  1.6163 +  if (!handle->moov->trakVideo->mdia->minf)
  1.6164 +    return -1;
  1.6165 +
  1.6166 +  if (!handle->moov->trakVideo->mdia->minf->stbl)
  1.6167 +    return -1;
  1.6168 +
  1.6169 +  if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
  1.6170 +    return -1;
  1.6171 +
  1.6172 +  if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0)
  1.6173 +    return -1;  
  1.6174 +  
  1.6175 +/* Assume that the video characteristics for all the video sample entries are the same. Just get them from the first one */
  1.6176 +
  1.6177 +  if (videotype == MP4_TYPE_H263_PROFILE_0 ||
  1.6178 +      videotype == MP4_TYPE_H263_PROFILE_3)
  1.6179 +  {
  1.6180 +    if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
  1.6181 +      return -1;
  1.6182 +
  1.6183 +    *videowidth  = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->width;
  1.6184 +    *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->height;
  1.6185 +  }
  1.6186 +  else if (videotype == MP4_TYPE_MPEG4_VIDEO)
  1.6187 +  {
  1.6188 +    if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0])
  1.6189 +      return -1;
  1.6190 +
  1.6191 +    *videowidth  = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->width;
  1.6192 +    *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->height;
  1.6193 +  }
  1.6194 +  else if ( isAvcVideo(videotype) )
  1.6195 +  {
  1.6196 +    if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0])
  1.6197 +      return -1;
  1.6198 +
  1.6199 +    *videowidth  = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->width;
  1.6200 +    *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->height;
  1.6201 +  }
  1.6202 +  else
  1.6203 +  {
  1.6204 +  }
  1.6205 +
  1.6206 +  return 0;
  1.6207 +}
  1.6208 +
  1.6209 +
  1.6210 +/*
  1.6211 + * Function:
  1.6212 + *
  1.6213 + *   mp4_i32 determineVideoTimeScale(MP4HandleImp handle,
  1.6214 + *                                   mp4_u32 *timescale)
  1.6215 + *
  1.6216 + * Description:
  1.6217 + *
  1.6218 + *   This function determines the timescale of video track.
  1.6219 + *
  1.6220 + * Parameters:
  1.6221 + *
  1.6222 + *   handle     MP4 library handle
  1.6223 + *   timescale  Timescale of video track is returned here
  1.6224 + *
  1.6225 + * Return value:
  1.6226 + *
  1.6227 + *   0          Success
  1.6228 + *   Negative   Error
  1.6229 + *
  1.6230 + */
  1.6231 +mp4_i32 determineVideoTimeScale(MP4HandleImp handle, mp4_u32 *timescale)
  1.6232 +{
  1.6233 +  if (timescale == NULL)
  1.6234 +    return 0;
  1.6235 +
  1.6236 +  if (!handle)
  1.6237 +    return -1;
  1.6238 +  if (!handle->moov)
  1.6239 +    return -1;
  1.6240 +  if (!handle->moov->trakVideo)
  1.6241 +    return -1;
  1.6242 +  if (!handle->moov->trakVideo->mdia)
  1.6243 +    return -1;
  1.6244 +  if (!handle->moov->trakVideo->mdia->mdhd)
  1.6245 +    return -1;
  1.6246 +  if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
  1.6247 +    return -1;
  1.6248 +
  1.6249 +  *timescale = handle->moov->trakVideo->mdia->mdhd->timeScale;
  1.6250 +
  1.6251 +  return 0;
  1.6252 +}
  1.6253 +
  1.6254 +
  1.6255 +/*
  1.6256 + * Function:
  1.6257 + *
  1.6258 + *   mp4_i32 determineAudioLength(MP4HandleImp handle,
  1.6259 + *                                mp4_u32 *audiolength)
  1.6260 + *
  1.6261 + * Description:
  1.6262 + *
  1.6263 + *   This function determines the length of audio in milliseconds.
  1.6264 + *
  1.6265 + * Parameters:
  1.6266 + *
  1.6267 + *   handle       MP4 library handle
  1.6268 + *   audiolength  Audio length is returned here
  1.6269 + *
  1.6270 + * Return value:
  1.6271 + *
  1.6272 + *   0            Success
  1.6273 + *   Negative     Error
  1.6274 + *
  1.6275 + */
  1.6276 +mp4_i32 determineAudioLength(MP4HandleImp handle, mp4_u32 *audiolength)
  1.6277 +{
  1.6278 +  if (!handle->moov)
  1.6279 +    return -1;
  1.6280 +
  1.6281 +  if (!handle->moov->mvhd)
  1.6282 +    return -1;
  1.6283 +
  1.6284 +  if (!handle->moov->trakAudio)
  1.6285 +    return -1;
  1.6286 +
  1.6287 +  if (!handle->moov->trakAudio->tkhd)
  1.6288 +    return -1;
  1.6289 +
  1.6290 +  /* Is timescale set? */
  1.6291 +  if (handle->moov->mvhd->timeScale == 0)
  1.6292 +    return -1;
  1.6293 +
  1.6294 +  *audiolength = (mp4_u32)(((mp4_double)handle->moov->trakAudio->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000);
  1.6295 +
  1.6296 +  return 0;
  1.6297 +}
  1.6298 +
  1.6299 +
  1.6300 +/*
  1.6301 + * Function:
  1.6302 + *
  1.6303 + *   mp4_i32 determineAudioType(MP4HandleImp handle,
  1.6304 + *                              mp4_u32 *audiotype)
  1.6305 + *
  1.6306 + * Description:
  1.6307 + *
  1.6308 + *   This function determines the audio type of the MP4.
  1.6309 + *
  1.6310 + * Parameters:
  1.6311 + *
  1.6312 + *   handle     MP4 library handle
  1.6313 + *   audiotype  Audio type is returned here
  1.6314 + *
  1.6315 + * Return value:
  1.6316 + *
  1.6317 + *   0          Success
  1.6318 + *   -1   		Error
  1.6319 + *   -2			Unknown audiotrack
  1.6320 + *
  1.6321 + */
  1.6322 +mp4_i32 determineAudioType(MP4HandleImp handle, mp4_u32 *audiotype)
  1.6323 +{
  1.6324 +  *audiotype = MP4_TYPE_NONE;
  1.6325 +
  1.6326 +
  1.6327 +  if (!handle->moov)
  1.6328 +    return -1;
  1.6329 +
  1.6330 +  if (!handle->moov->trakAudio)
  1.6331 +    return -1;
  1.6332 +
  1.6333 +  if (!handle->moov->trakAudio->mdia)
  1.6334 +    return -1;
  1.6335 +
  1.6336 +  if (!handle->moov->trakAudio->mdia->minf)
  1.6337 +    return -1;
  1.6338 +
  1.6339 +  if (!handle->moov->trakAudio->mdia->minf->stbl)
  1.6340 +    return -1;
  1.6341 +
  1.6342 +  if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
  1.6343 +    return -1;
  1.6344 +  
  1.6345 +  if (handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount == 0)
  1.6346 +    return -1;  
  1.6347 +
  1.6348 +/* Assume that the audio type is the same for all sample entries. Just get the audio type from the first one */
  1.6349 +  if (handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0])
  1.6350 +  {
  1.6351 +    if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd)
  1.6352 +      return -1;
  1.6353 +
  1.6354 +    if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0x40) &&
  1.6355 +        ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05))
  1.6356 +      *audiotype = MP4_TYPE_MPEG4_AUDIO;
  1.6357 +
  1.6358 +   if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0xE1) &&
  1.6359 +     ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05))  
  1.6360 +   {
  1.6361 +      *audiotype = MP4_TYPE_QCELP_13K;
  1.6362 +      handle->qcelpStoredAsMPEGAudio = MP4TRUE;
  1.6363 +   }
  1.6364 +  }
  1.6365 +  else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[0])
  1.6366 +    *audiotype = MP4_TYPE_AMR_NB;
  1.6367 +  else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[0])
  1.6368 +    *audiotype = MP4_TYPE_AMR_WB;
  1.6369 +  else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[0])
  1.6370 +  {
  1.6371 +    *audiotype = MP4_TYPE_QCELP_13K;
  1.6372 +    handle->qcelpStoredAsMPEGAudio = MP4FALSE;
  1.6373 +  }
  1.6374 +  else
  1.6375 +  {
  1.6376 +  }
  1.6377 +
  1.6378 +  if (*audiotype == MP4_TYPE_NONE)
  1.6379 +    return -2;
  1.6380 +
  1.6381 +  return 0;
  1.6382 +}
  1.6383 +
  1.6384 +
  1.6385 +/*
  1.6386 + * Function:
  1.6387 + *
  1.6388 + *   mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle,
  1.6389 + *                                         mp4_u8 *framespersample)
  1.6390 + *
  1.6391 + * Description:
  1.6392 + *
  1.6393 + *   This function determines the number of audio frames in each sample.
  1.6394 + *   The function works with AMR audio type only.
  1.6395 + *
  1.6396 + * Parameters:
  1.6397 + *
  1.6398 + *   handle           MP4 library handle
  1.6399 + *   framespersample  Number of frames in each sample
  1.6400 + *
  1.6401 + * Return value:
  1.6402 + *
  1.6403 + *   0                Success
  1.6404 + *   Negative         Error
  1.6405 + *
  1.6406 + */
  1.6407 +mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle, mp4_u8 *framespersample)
  1.6408 +{
  1.6409 +  mp4_i8 sampleentryindex;
  1.6410 +  
  1.6411 +  *framespersample = 0;
  1.6412 +
  1.6413 +
  1.6414 +  if (!((handle->type & MP4_TYPE_AMR_NB) ||
  1.6415 +        (handle->type & MP4_TYPE_AMR_WB) ||
  1.6416 +        ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))))
  1.6417 +  {
  1.6418 +    *framespersample = 1;
  1.6419 +
  1.6420 +    return 0;
  1.6421 +  }
  1.6422 +
  1.6423 +
  1.6424 +  if (!handle->moov)
  1.6425 +    return -1;
  1.6426 +
  1.6427 +  if (!handle->moov->trakAudio)
  1.6428 +    return -1;
  1.6429 +
  1.6430 +  if (!handle->moov->trakAudio->mdia)
  1.6431 +    return -1;
  1.6432 +
  1.6433 +  if (!handle->moov->trakAudio->mdia->minf)
  1.6434 +    return -1;
  1.6435 +
  1.6436 +  if (!handle->moov->trakAudio->mdia->minf->stbl)
  1.6437 +    return -1;
  1.6438 +
  1.6439 +  if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
  1.6440 +    return -1;
  1.6441 +
  1.6442 +  if (handle->type & MP4_TYPE_AMR_NB)
  1.6443 +  {
  1.6444 +/* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/
  1.6445 +	for (sampleentryindex = 0; (mp4_u8) sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
  1.6446 +	{
  1.6447 +		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex])
  1.6448 +		  return -1;
  1.6449 +
  1.6450 +		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr)
  1.6451 +		  return -1;
  1.6452 +
  1.6453 +		if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample)
  1.6454 +			*framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample;
  1.6455 +	}
  1.6456 +  }
  1.6457 +  else if (handle->type & MP4_TYPE_AMR_WB)
  1.6458 +  {
  1.6459 +/* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/
  1.6460 +	for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
  1.6461 +	{
  1.6462 +		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex])
  1.6463 +		  return -1;
  1.6464 +
  1.6465 +		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr)
  1.6466 +		  return -1;
  1.6467 +
  1.6468 +		if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample)
  1.6469 + 		  *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample;
  1.6470 +	}
  1.6471 +  }
  1.6472 +  else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))
  1.6473 +  {
  1.6474 +/* Now, framespersample returns the maximum frames_per_sample listed in the QCELP-13K sample entries*/
  1.6475 +	for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
  1.6476 +	{
  1.6477 +		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex])
  1.6478 +		  return -1;
  1.6479 +
  1.6480 +		if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp)
  1.6481 +		  return -1;
  1.6482 +
  1.6483 +		if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample)
  1.6484 +		  *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample;
  1.6485 +	}
  1.6486 +  }
  1.6487 +  else
  1.6488 +  {
  1.6489 +  }
  1.6490 +
  1.6491 +  return 0;
  1.6492 +}
  1.6493 +
  1.6494 +
  1.6495 +/*
  1.6496 + * Function:
  1.6497 + *
  1.6498 + *   mp4_i32 determineAudioTimeScale(MP4HandleImp handle,
  1.6499 + *                                   mp4_u32 *timescale)
  1.6500 + *
  1.6501 + * Description:
  1.6502 + *
  1.6503 + *   This function determines the timescale of audio track.
  1.6504 + *
  1.6505 + * Parameters:
  1.6506 + *
  1.6507 + *   handle     MP4 library handle
  1.6508 + *   timescale  Timescale of audio track is returned here
  1.6509 + *
  1.6510 + * Return value:
  1.6511 + *
  1.6512 + *   0          Success
  1.6513 + *   Negative   Error
  1.6514 + *
  1.6515 + */
  1.6516 +mp4_i32 determineAudioTimeScale(MP4HandleImp handle, mp4_u32 *timescale)
  1.6517 +{
  1.6518 +  if (timescale == NULL)
  1.6519 +    return 0;
  1.6520 +
  1.6521 +  if (!handle)
  1.6522 +    return -1;
  1.6523 +  if (!handle->moov)
  1.6524 +    return -1;
  1.6525 +  if (!handle->moov->trakAudio)
  1.6526 +    return -1;
  1.6527 +  if (!handle->moov->trakAudio->mdia)
  1.6528 +    return -1;
  1.6529 +  if (!handle->moov->trakAudio->mdia->mdhd)
  1.6530 +    return -1;
  1.6531 +
  1.6532 +
  1.6533 +  if (handle->moov->trakAudio->mdia->mdhd->timeScale == 0)
  1.6534 +    return -1;
  1.6535 +
  1.6536 +  *timescale = handle->moov->trakAudio->mdia->mdhd->timeScale;
  1.6537 +
  1.6538 +  return 0;
  1.6539 +}
  1.6540 +
  1.6541 +
  1.6542 +/*
  1.6543 + * Function:
  1.6544 + *
  1.6545 + *   mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle,
  1.6546 + *                                        mp4_u32 *averagebitrate)
  1.6547 + *
  1.6548 + * Description:
  1.6549 + *
  1.6550 + *   This function determines the average bitrate of the audio in bits per
  1.6551 + *   second.
  1.6552 + *
  1.6553 + *   The average is calculated so that the audio data length is divided by
  1.6554 + *   the length of the  audio track.
  1.6555 + *
  1.6556 + * Parameters:
  1.6557 + *
  1.6558 + *   handle                MP4 library handle
  1.6559 + *   averagebitrate        Result is returned here
  1.6560 + *
  1.6561 + * Return value:
  1.6562 + *
  1.6563 + *   0           Success
  1.6564 + *   Negative    Error
  1.6565 + *
  1.6566 + */
  1.6567 +mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle, mp4_u32 *averagebitrate)
  1.6568 +	{
  1.6569 +	mp4_u32 audiosize = 0;
  1.6570 +
  1.6571 +  	if (!handle->moov)
  1.6572 +  		{
  1.6573 +  		return -1;	
  1.6574 +  		}
  1.6575 +    	
  1.6576 +  	if (handle->moov->trakAudio)
  1.6577 +  		{
  1.6578 +		if (!handle->moov->trakAudio->mdia)
  1.6579 +			{
  1.6580 +			return -1;		
  1.6581 +			}
  1.6582 +					
  1.6583 +		if (!handle->moov->trakAudio->mdia->minf)
  1.6584 +			{
  1.6585 +			return -1;	
  1.6586 +			}
  1.6587 +		
  1.6588 +		if (!handle->moov->trakAudio->mdia->minf->stbl)
  1.6589 +			{
  1.6590 +			return -1;				
  1.6591 +			}
  1.6592 +
  1.6593 +		if (!handle->moov->trakAudio->mdia->minf->stbl->stsz)
  1.6594 +			{
  1.6595 +			return -1;				
  1.6596 +			}
  1.6597 +
  1.6598 +		if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0)
  1.6599 +			{
  1.6600 +			audiosize += (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount *
  1.6601 +	                   	 handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize);			
  1.6602 +			}
  1.6603 +	    else
  1.6604 +	    	{
  1.6605 +	      	mp4_u32 i;
  1.6606 +	      	for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++)
  1.6607 +	      		{
  1.6608 +	        	audiosize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i];      			
  1.6609 +	      		}
  1.6610 +	    	}
  1.6611 +	  	}
  1.6612 +	else
  1.6613 +		{
  1.6614 +		return -1;  		
  1.6615 +		}
  1.6616 +
  1.6617 +  	if (!handle->moov->trakAudio->mdia->mdhd)
  1.6618 +  		{
  1.6619 +    	return -1;  			
  1.6620 +  		}
  1.6621 +  	
  1.6622 +  	if (!handle->moov->trakAudio->mdia->mdhd->timeScale)
  1.6623 +  		{
  1.6624 +		return -1;  			
  1.6625 +  		}
  1.6626 +
  1.6627 +  	if (handle->moov->trakAudio->mdia->mdhd->duration == 0)
  1.6628 +  		{
  1.6629 +  		*averagebitrate = 0;
  1.6630 +  		}
  1.6631 +	else
  1.6632 +		{
  1.6633 +		*averagebitrate = (mp4_u32)((mp4_double)8 *
  1.6634 +		                  (mp4_double)audiosize /
  1.6635 +		                  ((mp4_double)handle->moov->trakAudio->mdia->mdhd->duration /
  1.6636 +		                  (mp4_double)handle->moov->trakAudio->mdia->mdhd->timeScale));
  1.6637 +		}  	
  1.6638 +
  1.6639 +  	return 0;
  1.6640 +	}
  1.6641 +
  1.6642 +
  1.6643 +/*
  1.6644 + * Function:
  1.6645 + *
  1.6646 + *   mp4_i32 determineStreamSize(MP4HandleImp handle,
  1.6647 + *                              mp4_u32 *streamsize)
  1.6648 + *
  1.6649 + * Description:
  1.6650 + *
  1.6651 + *   This function determines the size of media data in MP4 file/stream.
  1.6652 + *
  1.6653 + * Parameters:
  1.6654 + *
  1.6655 + *   handle      MP4 library handle
  1.6656 + *   streamsize  Size of data
  1.6657 + *
  1.6658 + * Return value:
  1.6659 + *
  1.6660 + *   0           Success
  1.6661 + *   Negative    Error
  1.6662 + *
  1.6663 + */
  1.6664 +mp4_i32 determineStreamSize(MP4HandleImp handle, mp4_u32 *streamsize)
  1.6665 +{
  1.6666 +  *streamsize = 0;
  1.6667 +
  1.6668 +  if (!handle->moov)
  1.6669 +    return -1;
  1.6670 +
  1.6671 +  if ((!handle->moov->trakAudio) && (!handle->moov->trakVideo))
  1.6672 +    return -1;
  1.6673 +
  1.6674 +  if (handle->moov->trakAudio)
  1.6675 +  {
  1.6676 +    if (!handle->moov->trakAudio->mdia)
  1.6677 +      return -1;
  1.6678 +
  1.6679 +    if (!handle->moov->trakAudio->mdia->minf)
  1.6680 +      return -1;
  1.6681 +
  1.6682 +    if (!handle->moov->trakAudio->mdia->minf->stbl)
  1.6683 +      return -1;
  1.6684 +
  1.6685 +    if (!handle->moov->trakAudio->mdia->minf->stbl->stsz)
  1.6686 +      return -1;
  1.6687 +
  1.6688 +    if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0)
  1.6689 +      *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount *
  1.6690 +                     handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize;
  1.6691 +    else
  1.6692 +    {
  1.6693 +      mp4_u32 i;
  1.6694 +
  1.6695 +      for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++)
  1.6696 +        *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i];
  1.6697 +    }
  1.6698 +  }
  1.6699 +
  1.6700 +  if (handle->moov->trakVideo)
  1.6701 +  {
  1.6702 +    if (!handle->moov->trakVideo->mdia)
  1.6703 +      return -1;
  1.6704 +
  1.6705 +    if (!handle->moov->trakVideo->mdia->minf)
  1.6706 +      return -1;
  1.6707 +
  1.6708 +    if (!handle->moov->trakVideo->mdia->minf->stbl)
  1.6709 +      return -1;
  1.6710 +
  1.6711 +    if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
  1.6712 +      return -1;
  1.6713 +
  1.6714 +    if (handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize != 0)
  1.6715 +      *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount *
  1.6716 +                     handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize;
  1.6717 +    else
  1.6718 +    {
  1.6719 +      mp4_u32 i;
  1.6720 +
  1.6721 +      for (i = 0; i < handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount; i++)
  1.6722 +        *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[i];
  1.6723 +    }
  1.6724 +  }
  1.6725 +
  1.6726 +  return 0;
  1.6727 +}
  1.6728 +
  1.6729 +
  1.6730 +/*
  1.6731 + * Function:
  1.6732 + *
  1.6733 + *   mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle,
  1.6734 + *                                         mp4_u32 *streamaveragebitrate,
  1.6735 + *                                         mp4_u32 streamsize)
  1.6736 + *
  1.6737 + * Description:
  1.6738 + *
  1.6739 + *   This function determines the average bitrate of the stream in bits per
  1.6740 + *   second.
  1.6741 + *
  1.6742 + *   The average is calculated so that the media data length is divided by
  1.6743 + *   the length of the presentation.
  1.6744 + *
  1.6745 + * Parameters:
  1.6746 + *
  1.6747 + *   handle                MP4 library handle
  1.6748 + *   streamaveragebitrate  Result is returned here
  1.6749 + *   streamsize            Size of media data in bytes
  1.6750 + *
  1.6751 + * Return value:
  1.6752 + *
  1.6753 + *   0           Success
  1.6754 + *   Negative    Error
  1.6755 + *
  1.6756 + */
  1.6757 +mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle, mp4_u32 *streamaveragebitrate, mp4_u32 streamsize)
  1.6758 +{
  1.6759 +  if (!handle->moov)
  1.6760 +    return -1;
  1.6761 +
  1.6762 +  if (!handle->moov->mvhd)
  1.6763 +    return -1;
  1.6764 +
  1.6765 +  if (!handle->moov->mvhd->timeScale)
  1.6766 +    return -1;
  1.6767 +
  1.6768 +  if (handle->moov->mvhd->atomhdr->version == 1) /* 64 bit */
  1.6769 +      {
  1.6770 +      if (!handle->moov->mvhd->duration64)
  1.6771 +        return -1;
  1.6772 +     
  1.6773 +      *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize /
  1.6774 +                                        ((mp4_double)handle->moov->mvhd->duration64 / handle->moov->mvhd->timeScale));      
  1.6775 +      }
  1.6776 +  else /* 32 bit */
  1.6777 +      {
  1.6778 +      if (!handle->moov->mvhd->duration)
  1.6779 +        return -1;
  1.6780 +
  1.6781 +      *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize /
  1.6782 +                                        ((mp4_double)handle->moov->mvhd->duration / handle->moov->mvhd->timeScale));      
  1.6783 +      }
  1.6784 +
  1.6785 +  return 0;
  1.6786 +}
  1.6787 +
  1.6788 +
  1.6789 +/*
  1.6790 + * Function:
  1.6791 + *
  1.6792 + *   mp4_i32 advanceVideoFrame(MP4HandleImp handle,
  1.6793 + *                             trackAtom *trak)
  1.6794 + *
  1.6795 + * Description:
  1.6796 + *
  1.6797 + *   This function Advances one video frame and finds the frame offset
  1.6798 + *   and size.
  1.6799 + *
  1.6800 + * Parameters:
  1.6801 + *
  1.6802 + *   handle    MP4 library handle
  1.6803 + *   trak      TRAK atom pointer
  1.6804 + *
  1.6805 + * Return value:
  1.6806 + *
  1.6807 + *   0         Success
  1.6808 + *   Negative  Error
  1.6809 + *
  1.6810 + */
  1.6811 +mp4_i32 advanceVideoFrame(MP4HandleImp handle, trackAtom *trak)
  1.6812 +{
  1.6813 +  if (!trak->mdia)
  1.6814 +    return -1;
  1.6815 +  if (!trak->mdia->minf)
  1.6816 +    return -1;
  1.6817 +  if (!trak->mdia->minf->stbl)
  1.6818 +    return -1;
  1.6819 +  if (!trak->mdia->minf->stbl->stsz)
  1.6820 +    return -1;
  1.6821 +
  1.6822 +  /* Are there frames (samples) left? */
  1.6823 +
  1.6824 +  if (trak->mdia->minf->stbl->stsz->sampleCount > handle->videoSampleNum)
  1.6825 +    handle->videoSampleNum++;
  1.6826 +  else
  1.6827 +    return -2;
  1.6828 +
  1.6829 +  /* Find the size of the frame (sample) */
  1.6830 +
  1.6831 +  if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
  1.6832 +    return -1;
  1.6833 +
  1.6834 +  /* Find the offset of the frame (sample) */
  1.6835 +
  1.6836 +  if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0)
  1.6837 +    return -1;
  1.6838 +
  1.6839 +
  1.6840 +  return 0;
  1.6841 +}
  1.6842 +
  1.6843 +
  1.6844 +/*
  1.6845 + * Function:
  1.6846 + *
  1.6847 + *   mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle,
  1.6848 + *                                    sampleTableAtom *stbl)
  1.6849 + *
  1.6850 + * Description:
  1.6851 + *
  1.6852 + *   This function finds the offset of the current video sample.
  1.6853 + *   The result is stored in handle->videoFrameOffset.
  1.6854 + *
  1.6855 + * Parameters:
  1.6856 + *
  1.6857 + *   handle    MP4 library handle
  1.6858 + *   stbl      STBL atom pointer
  1.6859 + *
  1.6860 + * Return value:
  1.6861 + *
  1.6862 + *   0         Success
  1.6863 + *   Negative  Error
  1.6864 + *
  1.6865 + */
  1.6866 +mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl)
  1.6867 +	{
  1.6868 +	mp4_u32  chunk;            /* Current chunk number */
  1.6869 +	mp4_u32  sample;           /* Number of samples before this run of chunks */
  1.6870 +	mp4_u32  entry;            /* Current entry in sample to chunk */
  1.6871 +	mp4_u32  chunksInThisRun;  /* Number of chunks in this run */
  1.6872 +	mp4_u32  sampleNrInChunk = 0;	/* Sample number in the chunk */
  1.6873 +
  1.6874 +	if (!stbl->stsc || stbl->stsc->entryCount == 0)
  1.6875 +		{
  1.6876 +		return -1;
  1.6877 +		}
  1.6878 +	
  1.6879 +	if (!stbl->stco || stbl->stco->entryCount == 0)
  1.6880 +		{
  1.6881 +		return -1;
  1.6882 +		}
  1.6883 +
  1.6884 +	chunk = 0;
  1.6885 +	sample = 0;
  1.6886 +	entry = 0;
  1.6887 +
  1.6888 +  for (;;)
  1.6889 +		{
  1.6890 +		/* Find how many chunks there are in this run */
  1.6891 +		
  1.6892 +		if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */
  1.6893 +			{
  1.6894 +			chunksInThisRun = stbl->stsc->firstChunk[entry + 1] - stbl->stsc->firstChunk[entry];
  1.6895 +			}
  1.6896 +		else
  1.6897 +			{
  1.6898 +			chunksInThisRun = stbl->stco->entryCount - chunk + 1;
  1.6899 +			}
  1.6900 +
  1.6901 +		if (handle->videoSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample)
  1.6902 +			{
  1.6903 +			chunk += (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry];
  1.6904 +			sampleNrInChunk = (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry];
  1.6905 +	  
  1.6906 +			/* The following functions are needed for multiple sample entry support */
  1.6907 +			handle->videoSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry];
  1.6908 +
  1.6909 +			break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/
  1.6910 +			}
  1.6911 +		else
  1.6912 +			{
  1.6913 +			chunk += chunksInThisRun;
  1.6914 +			sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry];
  1.6915 +			}
  1.6916 +
  1.6917 +	    entry++;
  1.6918 +		}
  1.6919 +
  1.6920 +	if (chunk > stbl->stco->entryCount)
  1.6921 +		{
  1.6922 +		return -1;
  1.6923 +		}
  1.6924 +
  1.6925 +	handle->videoFrameOffset = getChunkOffset(stbl, chunk - 1);
  1.6926 +
  1.6927 +	if (sampleNrInChunk)
  1.6928 +		{
  1.6929 +		if (stbl->stsz->sampleSize)
  1.6930 +			{
  1.6931 +			handle->videoFrameOffset += stbl->stsz->sampleSize * sampleNrInChunk;
  1.6932 +			}
  1.6933 +		else
  1.6934 +			{
  1.6935 +			if (stbl->stsz->sampleCount == 0)
  1.6936 +				{
  1.6937 +				return -1;
  1.6938 +				}
  1.6939 +			while (sampleNrInChunk)
  1.6940 +				{
  1.6941 +				handle->videoFrameOffset += stbl->stsz->entrySize[handle->videoSampleNum - sampleNrInChunk - 1];
  1.6942 +				sampleNrInChunk--;
  1.6943 +				}
  1.6944 +			}
  1.6945 +		}
  1.6946 +		
  1.6947 +		
  1.6948 +	//PRINT((_L("videoFrameOffset %Lu"), handle->videoFrameOffset));
  1.6949 +	return 0;
  1.6950 +	}
  1.6951 +
  1.6952 +
  1.6953 +/*
  1.6954 + * Function:
  1.6955 + *
  1.6956 + *   mp4_i32 resolveVideoSampleSize(MP4HandleImp handle,
  1.6957 + *                                  sampleSizeAtom *stsz)
  1.6958 + *
  1.6959 + * Description:
  1.6960 + *
  1.6961 + *   This function finds the size of the current video sample.
  1.6962 + *   The result is stored in handle->videoFrameSize.
  1.6963 + *
  1.6964 + * Parameters:
  1.6965 + *
  1.6966 + *   handle    MP4 library handle
  1.6967 + *   stsz      STSZ atom pointer
  1.6968 + *
  1.6969 + * Return value:
  1.6970 + *
  1.6971 + *   0         Success
  1.6972 + *   Negative  Error
  1.6973 + *
  1.6974 + */
  1.6975 +mp4_i32 resolveVideoSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz)
  1.6976 +	{
  1.6977 +	if (stsz->sampleSize)
  1.6978 +		{
  1.6979 +		handle->videoFrameSize = stsz->sampleSize;
  1.6980 +		return 0;
  1.6981 +		}
  1.6982 +
  1.6983 +	if (stsz->sampleCount == 0)
  1.6984 +		{
  1.6985 +		return -1;
  1.6986 +		}
  1.6987 +	handle->videoFrameSize = stsz->entrySize[handle->videoSampleNum - 1];
  1.6988 +
  1.6989 +	return 0;
  1.6990 +	}
  1.6991 +
  1.6992 +
  1.6993 +/*
  1.6994 + * Function:
  1.6995 + *
  1.6996 + *   mp4_i32 fetchVideoFrame(MP4HandleImp handle,
  1.6997 + *                           trackAtom *trak,
  1.6998 + *                           mp4_u8 *buffer,
  1.6999 + *                           mp4_u32 buffersize,
  1.7000 + *                           mp4_u32 *framesize,
  1.7001 + *                           mp4_u32 *timestamp,
  1.7002 + *                           mp4_bool *keyframe,
  1.7003 + *                           mp4_u32 *timestamp2)
  1.7004 + *
  1.7005 + * Description:
  1.7006 + *
  1.7007 + *   This function fetches one video frame from a file.
  1.7008 + *
  1.7009 + * Parameters:
  1.7010 + *
  1.7011 + *   handle       MP4 library handle
  1.7012 + *   trak         TRAK atom pointer
  1.7013 + *   buffer       Video frame is retuned here
  1.7014 + *   buffersize   Size of buffer
  1.7015 + *   framesize    Size of returned frame in bytes
  1.7016 + *   timestamp    Frame time in milliseconds (from the beginning of the
  1.7017 + *                presentation)
  1.7018 + *   keyframe     True if intra frame, false otherwise
  1.7019 + *   timestamp2   Frame time in timescale (from the beginning of the
  1.7020 + *                presentation)
  1.7021 + *
  1.7022 + * Return value:
  1.7023 + *
  1.7024 + *   0            Success
  1.7025 + *   Negative     Error
  1.7026 + *
  1.7027 + */
  1.7028 +mp4_i32 fetchVideoFrame(MP4HandleImp handle,
  1.7029 +                        trackAtom *trak,
  1.7030 +                        mp4_u8 *buffer,
  1.7031 +                        mp4_u32 buffersize,
  1.7032 +                        mp4_u32 *framesize,
  1.7033 +                        mp4_u32 *timestamp,
  1.7034 +                        mp4_bool *keyframe,
  1.7035 +                        mp4_u32 *timestamp2)
  1.7036 +{
  1.7037 +  mp4_i32 bytesread;
  1.7038 +
  1.7039 +
  1.7040 +  if (!trak->mdia)
  1.7041 +    return -1;
  1.7042 +
  1.7043 +  if (handle->file) /* Input is in a file */
  1.7044 +  {
  1.7045 +    if (seekFileAbs(handle, handle->videoFrameOffset) != 0)
  1.7046 +      return -4;
  1.7047 +  }
  1.7048 +  else /* Input is a stream */
  1.7049 +  {
  1.7050 +      if (handle->videoFrameOffset + handle->videoFrameSize <= getCumulativeBufferedBytes(handle))
  1.7051 +      {
  1.7052 +          handle->absPosition = handle->videoFrameOffset;
  1.7053 +      }
  1.7054 +      else
  1.7055 +        return -3;
  1.7056 +  }
  1.7057 +
  1.7058 +  if (handle->videoFrameSize > buffersize)
  1.7059 +  {
  1.7060 +    *framesize = handle->videoFrameSize;
  1.7061 +    return -2;
  1.7062 +  }
  1.7063 +
  1.7064 +  bytesread = readData(handle, buffer, handle->videoFrameSize);
  1.7065 +  switch (bytesread)
  1.7066 +  {
  1.7067 +    case -1:
  1.7068 +      return -1;
  1.7069 +    case -2:
  1.7070 +      return -4;
  1.7071 +    case -10:
  1.7072 +      return -3;
  1.7073 +    default:
  1.7074 +      break;
  1.7075 +  }
  1.7076 +
  1.7077 +  if (handle->file)
  1.7078 +    if (handle->videoFrameOffset + handle->videoFrameSize - 1 > handle->lastAccessedPosInFile)
  1.7079 +      handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1;
  1.7080 +
  1.7081 +  *framesize = handle->videoFrameSize;
  1.7082 +
  1.7083 +  if (convertVideoSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0)
  1.7084 +    return -1;
  1.7085 +
  1.7086 +  if (isVideoFrameKeyFrame(handle, trak, keyframe) < 0)
  1.7087 +    return -1;
  1.7088 +
  1.7089 +  return 0;
  1.7090 +}
  1.7091 +
  1.7092 +/*
  1.7093 + * Function:
  1.7094 + *
  1.7095 + *   mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle,
  1.7096 + *                           	  trackAtom *trak,
  1.7097 + *                           	  mp4_u8 *buffer,
  1.7098 + *                           	  mp4_u32 buffersize,
  1.7099 + *
  1.7100 + * Description:
  1.7101 + *
  1.7102 + *   This function fetches one video frame from a file asyncronously.
  1.7103 + *
  1.7104 + * Parameters:
  1.7105 + *
  1.7106 + *   handle       MP4 library handle
  1.7107 + *   trak         TRAK atom pointer
  1.7108 + *   buffer       Video frame is retuned here
  1.7109 + *   buffersize   Size of buffer
  1.7110 + *
  1.7111 + * Return value:
  1.7112 + *
  1.7113 + *   0            Success
  1.7114 + *   Negative     Error
  1.7115 + *
  1.7116 + */
  1.7117 +mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle,
  1.7118 +                        trackAtom *trak,
  1.7119 +                        mp4_u8 *buffer,
  1.7120 +                        mp4_u32 *buffersize)
  1.7121 +{
  1.7122 +  if (trak)
  1.7123 +	{
  1.7124 +	if (!trak->mdia)
  1.7125 +		return -1;
  1.7126 +	}
  1.7127 +  else
  1.7128 +    {
  1.7129 +	return -1;
  1.7130 +    }
  1.7131 +  
  1.7132 +  if (handle->videoFrameSize > *buffersize)
  1.7133 +  {
  1.7134 +    *buffersize = handle->videoFrameSize;
  1.7135 +    return -2;
  1.7136 +  }
  1.7137 +  
  1.7138 +  if ( handle->asyncReader == NULL )
  1.7139 +  	{
  1.7140 +	TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile ));
  1.7141 +	if ( error != KErrNone )
  1.7142 +		{
  1.7143 +		if (error == KErrNoMemory )
  1.7144 +			{
  1.7145 +			return MP4_OUT_OF_MEMORY;    		
  1.7146 +			}
  1.7147 +		else
  1.7148 +			{
  1.7149 +			return -1;
  1.7150 +			}
  1.7151 +		}  	
  1.7152 +  	}
  1.7153 +  
  1.7154 +  return handle->asyncReader->ReadVideoFrame( buffer, handle->videoFrameOffset, handle->videoFrameSize);
  1.7155 +}
  1.7156 +
  1.7157 +/*
  1.7158 + * Function:
  1.7159 + *
  1.7160 + *   mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle,
  1.7161 + *                                trackAtom *trak,
  1.7162 + *                                mp4_bool *keyframe)
  1.7163 + *
  1.7164 + * Description:
  1.7165 + *
  1.7166 + *   This function determines if the current frame is a keyframe (intra)
  1.7167 + *   or not.
  1.7168 + *
  1.7169 + * Parameters:
  1.7170 + *
  1.7171 + *   handle       MP4 library handle
  1.7172 + *   trak         TRAK atom pointer
  1.7173 + *   keyframe     Has a value of MP4TRUE if current frame is a keyframe
  1.7174 + *                (intra) or MP4FALSE otherwise
  1.7175 + *
  1.7176 + * Return value:
  1.7177 + *
  1.7178 + *   0            Success
  1.7179 + *   Negative     Error
  1.7180 + *
  1.7181 + */
  1.7182 +mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle, trackAtom *trak, mp4_bool *keyframe)
  1.7183 +{
  1.7184 +  mp4_u32  i;
  1.7185 +
  1.7186 +
  1.7187 +  *keyframe = MP4FALSE;
  1.7188 +
  1.7189 +  if (!trak->mdia)
  1.7190 +    return -1;
  1.7191 +
  1.7192 +  if (!trak->mdia->minf)
  1.7193 +    return -1;
  1.7194 +
  1.7195 +  if (!trak->mdia->minf->stbl)
  1.7196 +    return -1;
  1.7197 +
  1.7198 +  if (!trak->mdia->minf->stbl->stss)
  1.7199 +  {
  1.7200 +    *keyframe = MP4TRUE;
  1.7201 +
  1.7202 +    return 0;
  1.7203 +  }
  1.7204 +
  1.7205 +  for (i = 0; i < trak->mdia->minf->stbl->stss->entryCount; i++)
  1.7206 +  {
  1.7207 +    if (trak->mdia->minf->stbl->stss->sampleNumber[i] == handle->videoSampleNum)
  1.7208 +    {
  1.7209 +      *keyframe = MP4TRUE;
  1.7210 +      break;
  1.7211 +    }
  1.7212 +  }
  1.7213 +
  1.7214 +  return 0;
  1.7215 +}
  1.7216 +
  1.7217 +
  1.7218 +/*
  1.7219 + * Function:
  1.7220 + *
  1.7221 + *   mp4_i32 convertVideoSampleToTime(MP4HandleImp handle,
  1.7222 + *                                    mediaAtom *mdia,
  1.7223 + *                                    mp4_u32 *timestamp,
  1.7224 + *                                    mp4_u32 *timestamp2)
  1.7225 + *
  1.7226 + * Description:
  1.7227 + *
  1.7228 + *   This function converts a video sample to corresponding time.
  1.7229 + *
  1.7230 + * Parameters:
  1.7231 + *
  1.7232 + *   handle       MP4 library handle
  1.7233 + *   mdia         MDIA atom pointer
  1.7234 + *   timestamp    Time in milliseconds is returned here
  1.7235 + *   timestamp2   Time in timescale is returned here
  1.7236 + *
  1.7237 + * Return value:
  1.7238 + *
  1.7239 + *   0            Success
  1.7240 + *   Negative     Error
  1.7241 + *
  1.7242 + */
  1.7243 +mp4_i32 convertVideoSampleToTime(MP4HandleImp handle,
  1.7244 +                                 mediaAtom *mdia,
  1.7245 +                                 mp4_u32 *timestamp,
  1.7246 +                                 mp4_u32 *timestamp2)
  1.7247 +	{
  1.7248 +	mp4_u32      tmptime;
  1.7249 +	mp4_double   tmptime2;
  1.7250 +	mp4_u32      sample;
  1.7251 +	mp4_u32      entry;
  1.7252 +
  1.7253 +	if (!mdia->mdhd)
  1.7254 +		{
  1.7255 +		return -1;
  1.7256 +		}
  1.7257 +	if (!mdia->minf)
  1.7258 +		{
  1.7259 +		return -1;
  1.7260 +		}
  1.7261 +	if (!mdia->minf->stbl)
  1.7262 +		{
  1.7263 +		return -1;
  1.7264 +		}
  1.7265 +	if (!mdia->minf->stbl->stts)
  1.7266 +		{
  1.7267 +		return -1;
  1.7268 +		}
  1.7269 +	if (mdia->minf->stbl->stts->entryCount == 0)
  1.7270 +		{
  1.7271 +		return -1;
  1.7272 +		}
  1.7273 +
  1.7274 +	tmptime = 0;
  1.7275 +	sample = 0;
  1.7276 +	entry = 0;
  1.7277 +
  1.7278 +	for (;;)
  1.7279 +		{
  1.7280 +		if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->videoSampleNum)
  1.7281 +			{
  1.7282 +			sample += mdia->minf->stbl->stts->sampleCount[entry];
  1.7283 +			tmptime += (mdia->minf->stbl->stts->sampleCount[entry] * mdia->minf->stbl->stts->sampleDelta[entry]);
  1.7284 +			entry++;
  1.7285 +			if (entry == mdia->minf->stbl->stts->entryCount)
  1.7286 +				{
  1.7287 +				return -1;
  1.7288 +				}
  1.7289 +			}
  1.7290 +		else
  1.7291 +			{
  1.7292 +			tmptime += ((handle->videoSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry]);
  1.7293 +			break;
  1.7294 +			}
  1.7295 +		}
  1.7296 +	
  1.7297 +  	if (mdia->mdhd->timeScale == 0)
  1.7298 +  		{
  1.7299 +  		return -1;
  1.7300 +  		}
  1.7301 +
  1.7302 +  	if (timestamp2)
  1.7303 +  		{
  1.7304 +  		*timestamp2 = tmptime;
  1.7305 +  		}
  1.7306 +
  1.7307 +  	tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5;
  1.7308 +
  1.7309 +  	*timestamp = (mp4_u32)tmptime2;
  1.7310 +
  1.7311 +  	return 0;
  1.7312 +	}
  1.7313 +
  1.7314 +
  1.7315 +/*
  1.7316 + * Function:
  1.7317 + *
  1.7318 + *   mp4_i32 advanceAudioSample(MP4HandleImp handle,
  1.7319 + *                              trackAtom *trak)
  1.7320 + *
  1.7321 + * Description:
  1.7322 + *
  1.7323 + *   This function advances one audio sample and finds the sample
  1.7324 + *   offset and sample size.
  1.7325 + *
  1.7326 + * Parameters:
  1.7327 + *
  1.7328 + *   handle    MP4 library handle
  1.7329 + *   trak      TRAK atom pointer
  1.7330 + *
  1.7331 + * Return value:
  1.7332 + *
  1.7333 + *   0         Success
  1.7334 + *   Negative  Error
  1.7335 + *
  1.7336 + */
  1.7337 +mp4_i32 advanceAudioSample(MP4HandleImp handle,
  1.7338 +                           trackAtom *trak)
  1.7339 +{
  1.7340 +  if (!trak->mdia)
  1.7341 +    return -1;
  1.7342 +  if (!trak->mdia->minf)
  1.7343 +    return -1;
  1.7344 +  if (!trak->mdia->minf->stbl)
  1.7345 +    return -1;
  1.7346 +  if (!trak->mdia->minf->stbl->stsz)
  1.7347 +    return -1;
  1.7348 +
  1.7349 +
  1.7350 +  /* Are there samples left? */
  1.7351 +
  1.7352 +  if (trak->mdia->minf->stbl->stsz->sampleCount > handle->audioSampleNum)
  1.7353 +    handle->audioSampleNum++;
  1.7354 +  else
  1.7355 +    return -2;
  1.7356 +
  1.7357 +  /* Find the size of the sample */
  1.7358 +
  1.7359 +  if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
  1.7360 +    return -1;
  1.7361 +
  1.7362 +  /* Find the offset of the sample */
  1.7363 +
  1.7364 +  if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0)
  1.7365 +    return -1;
  1.7366 +
  1.7367 +
  1.7368 +  return 0;
  1.7369 +}
  1.7370 +
  1.7371 +
  1.7372 +/*
  1.7373 + * Function:
  1.7374 + *
  1.7375 + *   mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle,
  1.7376 + *                                    sampleTableAtom *stbl)
  1.7377 + *
  1.7378 + * Description:
  1.7379 + *
  1.7380 + *   This function finds the offset of the current audio sample.
  1.7381 + *   The result is stored in handle->audioSampleOffset.
  1.7382 + *
  1.7383 + * Parameters:
  1.7384 + *
  1.7385 + *   handle    MP4 library handle
  1.7386 + *   stbl      STBL atom pointer
  1.7387 + *
  1.7388 + * Return value:
  1.7389 + *
  1.7390 + *   0         Success
  1.7391 + *   Negative  Error
  1.7392 + *
  1.7393 + */
  1.7394 +mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl)
  1.7395 +{
  1.7396 +  mp4_u32  chunk;            /* Current chunk number */
  1.7397 +  mp4_u32  sample;            /* Number of samples before this run of chunks */
  1.7398 +  mp4_u32  entry;            /* Current entry in sample to chunk */
  1.7399 +  mp4_u32 chunksInThisRun;  /* Number of chunks in this run */
  1.7400 +  mp4_u32  sampleNrInChunk;  /* Sample number in the chunk */
  1.7401 +
  1.7402 +
  1.7403 +  if (!stbl->stsc || stbl->stsc->entryCount == 0)
  1.7404 +    return -1;
  1.7405 +  if (!stbl->stco || stbl->stco->entryCount == 0)
  1.7406 +    return -1;
  1.7407 +
  1.7408 +  chunk = 0;
  1.7409 +  sample = 0;
  1.7410 +  entry = 0;
  1.7411 +
  1.7412 +  for (;;)
  1.7413 +  {
  1.7414 +    /* Find how many chunks there are in this run */
  1.7415 +
  1.7416 +    if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */
  1.7417 +    {
  1.7418 +      chunksInThisRun = stbl->stsc->firstChunk[entry + 1] -
  1.7419 +                        stbl->stsc->firstChunk[entry];
  1.7420 +    }
  1.7421 +    else
  1.7422 +      chunksInThisRun = stbl->stco->entryCount - chunk + 1;
  1.7423 +
  1.7424 +
  1.7425 +    if (handle->audioSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample)
  1.7426 +    {
  1.7427 +      chunk += (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry];
  1.7428 +      sampleNrInChunk = (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry];
  1.7429 +
  1.7430 +	  /* The following functions are needed for multiple sample entry support */
  1.7431 +	  handle->audioSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry];
  1.7432 +
  1.7433 +      break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/
  1.7434 +    }
  1.7435 +    else
  1.7436 +    {
  1.7437 +      chunk += chunksInThisRun;
  1.7438 +      sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry];
  1.7439 +    }
  1.7440 +
  1.7441 +    entry++;
  1.7442 +  }
  1.7443 +
  1.7444 +  if (chunk > stbl->stco->entryCount)
  1.7445 +    return -1;
  1.7446 +
  1.7447 +  handle->audioSampleOffset = getChunkOffset(stbl, chunk - 1);
  1.7448 +
  1.7449 +  	if (sampleNrInChunk)
  1.7450 +  		{
  1.7451 +  		if (stbl->stsz->sampleSize)
  1.7452 +  			{
  1.7453 +  			handle->audioSampleOffset += stbl->stsz->sampleSize * sampleNrInChunk;
  1.7454 +  			}
  1.7455 +  		else
  1.7456 +  			{
  1.7457 +  			if (stbl->stsz->sampleCount == 0)
  1.7458 +  				{
  1.7459 +  				// ensure there are entries in the entrySize array
  1.7460 +  				return -1;
  1.7461 +  				}
  1.7462 +    
  1.7463 +  			while (sampleNrInChunk)
  1.7464 +  				{
  1.7465 +  				handle->audioSampleOffset += stbl->stsz->entrySize[handle->audioSampleNum - sampleNrInChunk - 1];
  1.7466 +  				sampleNrInChunk--;
  1.7467 +  				}
  1.7468 +  			}
  1.7469 +  		}
  1.7470 +  		
  1.7471 +  //PRINT((_L("audioSampleOffset %Lu"), handle->audioSampleOffset));
  1.7472 +  return 0;
  1.7473 +}
  1.7474 +
  1.7475 +
  1.7476 +/*
  1.7477 + * Function:
  1.7478 + *
  1.7479 + *   mp4_i32 resolveAudioSampleSize(MP4HandleImp handle,
  1.7480 + *                                  sampleSizeAtom *stsz)
  1.7481 + *
  1.7482 + * Description:
  1.7483 + *
  1.7484 + *   This function finds the size of the current audio sample.
  1.7485 + *   The result is stored in handle->audioSampleSize.
  1.7486 + *
  1.7487 + * Parameters:
  1.7488 + *
  1.7489 + *   handle    MP4 library handle
  1.7490 + *   stsz      STSZ atom pointer
  1.7491 + *
  1.7492 + * Return value:
  1.7493 + *
  1.7494 + *   0         Success
  1.7495 + *   Negative  Error
  1.7496 + *
  1.7497 + */
  1.7498 +mp4_i32 resolveAudioSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz)
  1.7499 +	{
  1.7500 +	if (stsz->sampleSize)
  1.7501 +		{
  1.7502 +		handle->audioSampleSize = stsz->sampleSize;
  1.7503 +		return 0;
  1.7504 +		}
  1.7505 +
  1.7506 +	if (stsz->sampleCount == 0)
  1.7507 +		{
  1.7508 +		return -1;
  1.7509 +		}
  1.7510 +	handle->audioSampleSize = stsz->entrySize[handle->audioSampleNum - 1];
  1.7511 +
  1.7512 +	return 0;
  1.7513 +	}
  1.7514 +
  1.7515 +
  1.7516 +/*
  1.7517 + * Function:
  1.7518 + *
  1.7519 + *   mp4_i32 fetchAudioSample(MP4HandleImp handle,
  1.7520 + *                            trackAtom *trak,
  1.7521 + *                            mp4_u8 *buffer,
  1.7522 + *                            mp4_u32 buffersize,
  1.7523 + *                            mp4_u32 *framesize,
  1.7524 + *                            mp4_u32 *timestamp,
  1.7525 + *                            mp4_u32 *returnedframes,
  1.7526 + *                            mp4_u32 *timestamp2)
  1.7527 + *
  1.7528 + * Description:
  1.7529 + *
  1.7530 + *   This function fetches one audio sample from a file.
  1.7531 + *
  1.7532 + *   Note: returnedframes may differ from the correct value when accessing
  1.7533 + *         the last audio sample.
  1.7534 + *
  1.7535 + * Parameters:
  1.7536 + *
  1.7537 + *   handle           MP4 library handle
  1.7538 + *   trak             TRAK atom pointer
  1.7539 + *   buffer           Audio frame is retuned here
  1.7540 + *   buffersize       Size of buffer
  1.7541 + *   framesize        Size of returned frame in bytes
  1.7542 + *   timestamp        Frame time in milliseconds (from the beginning of the
  1.7543 + *                    presentation)
  1.7544 + *   returnedframes   Number of frames returned, of 0 if not known
  1.7545 + *   timestamp2       Frame time in timescale (from the beginning of the
  1.7546 + *                    presentation)
  1.7547 + *
  1.7548 + * Return value:
  1.7549 + *
  1.7550 + *   0                Success
  1.7551 + *   Negative         Error
  1.7552 + *
  1.7553 + */
  1.7554 +mp4_i32 fetchAudioSample(MP4HandleImp handle,
  1.7555 +                         trackAtom *trak,
  1.7556 +                         mp4_u8 *buffer,
  1.7557 +                         mp4_u32 buffersize,
  1.7558 +                         mp4_u32 *framesize,
  1.7559 +                         mp4_u32 *timestamp,
  1.7560 +                         mp4_u32 *returnedframes,
  1.7561 +                         mp4_u32 *timestamp2)
  1.7562 +{
  1.7563 +  mp4_i32 bytesread;
  1.7564 +  mp4_i32 frameLength;
  1.7565 +  mp4_u32 numOfFrames;
  1.7566 +  mp4_u8 *framepointer;
  1.7567 +  mp4_u32 rawAmrFrameLength[16] = {13,14,16,18,20,21,27,32,6,0,0,0,0,0,0,1};
  1.7568 +
  1.7569 +  if (!trak->mdia)
  1.7570 +    return -1;
  1.7571 +
  1.7572 +  if (handle->file) /* Input is in a file */
  1.7573 +  {
  1.7574 +    if (seekFileAbs(handle, handle->audioSampleOffset) != 0)
  1.7575 +      return -4;
  1.7576 +  }
  1.7577 +  else /* Input is a stream */
  1.7578 +  {
  1.7579 +      if (handle->audioSampleOffset + handle->audioSampleSize <= getCumulativeBufferedBytes(handle))
  1.7580 +      {
  1.7581 +          handle->absPosition = handle->audioSampleOffset;
  1.7582 +      }
  1.7583 +      else
  1.7584 +        return -3;
  1.7585 +  }
  1.7586 +
  1.7587 +  if (handle->audioSampleSize > buffersize)
  1.7588 +  {
  1.7589 +    *framesize = handle->audioSampleSize;
  1.7590 +    return -2;
  1.7591 +  }
  1.7592 +
  1.7593 +  bytesread = readData(handle, buffer, handle->audioSampleSize);
  1.7594 +  switch (bytesread)
  1.7595 +  {
  1.7596 +    case -1:
  1.7597 +      return -1;
  1.7598 +    case -2:
  1.7599 +      return -4;
  1.7600 +    case -10:
  1.7601 +      return -3;
  1.7602 +    default:
  1.7603 +      break;
  1.7604 +  }
  1.7605 +
  1.7606 +  if (handle->file)
  1.7607 +    if (handle->audioSampleOffset + handle->audioSampleSize - 1 > handle->lastAccessedPosInFile)
  1.7608 +      handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1;
  1.7609 +
  1.7610 +  *framesize = handle->audioSampleSize;
  1.7611 +  if (convertAudioSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0)
  1.7612 +    return -1;
  1.7613 +
  1.7614 +  *returnedframes = 0;
  1.7615 +
  1.7616 +  /* AMR */
  1.7617 +  if (trak->mdia->minf)
  1.7618 +    if (trak->mdia->minf->stbl)
  1.7619 +      if (trak->mdia->minf->stbl->stsd)
  1.7620 +        if (handle->type & MP4_TYPE_AMR_NB)
  1.7621 +        {
  1.7622 +            framepointer = buffer;
  1.7623 +            numOfFrames = 0;
  1.7624 +            while ( bytesread > 0 )
  1.7625 +            {
  1.7626 +                frameLength = rawAmrFrameLength[(TInt)(((*framepointer) & 0x78) >> 3)];
  1.7627 +                if ( frameLength == 0)
  1.7628 +                {
  1.7629 +                    return -4;
  1.7630 +                }
  1.7631 +                bytesread -= frameLength;
  1.7632 +                framepointer += frameLength;
  1.7633 +                numOfFrames++;
  1.7634 +            }
  1.7635 +            *returnedframes = numOfFrames;
  1.7636 +
  1.7637 +		  /* Return the number of sample entries listed for this particular sample entry index 
  1.7638 +          if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1])
  1.7639 +            if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr)
  1.7640 +              *returnedframes = trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr->framesPerSample;*/
  1.7641 +        }
  1.7642 +        else if (handle->type & MP4_TYPE_AMR_WB)
  1.7643 +        {
  1.7644 +		  /* Return the number of sample entries listed for this particular sample entry index */
  1.7645 +          if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1])
  1.7646 +            if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr)
  1.7647 +              *returnedframes = trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr->framesPerSample;
  1.7648 +        }
  1.7649 +        else
  1.7650 +        {
  1.7651 +        }
  1.7652 +
  1.7653 +  /* MPEG-4 audio */
  1.7654 +  if (trak->mdia->minf)
  1.7655 +    if (trak->mdia->minf->stbl)
  1.7656 +      if (trak->mdia->minf->stbl->stsd)
  1.7657 +        if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1])
  1.7658 +          *returnedframes = 1;
  1.7659 +
  1.7660 +  /* QCELP 13K as QCELPSampleEntry*/
  1.7661 +  if (trak->mdia->minf)
  1.7662 +    if (trak->mdia->minf->stbl)
  1.7663 +      if (trak->mdia->minf->stbl->stsd)
  1.7664 +        if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))
  1.7665 +        {
  1.7666 +		  /* Return the number of sample entries listed for this particular sample entry index */
  1.7667 +          if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1])
  1.7668 +            if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp)
  1.7669 +              *returnedframes = trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp->framesPerSample;
  1.7670 +        }
  1.7671 +
  1.7672 +  /* QCELP 13K as MPEG-4 audio */
  1.7673 +  if (trak->mdia->minf)
  1.7674 +    if (trak->mdia->minf->stbl)
  1.7675 +      if (trak->mdia->minf->stbl->stsd)
  1.7676 +        if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1])
  1.7677 +          *returnedframes = 1;
  1.7678 +
  1.7679 +  return 0;
  1.7680 +}
  1.7681 +
  1.7682 +/*
  1.7683 + * Function:
  1.7684 + *
  1.7685 + *   mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle,
  1.7686 + *                            trackAtom *trak,
  1.7687 + *                            mp4_u8 *buffer,
  1.7688 + *                            mp4_u32 buffersize,
  1.7689 + *
  1.7690 + * Description:
  1.7691 + *
  1.7692 + *   This function fetches one audio sample from a file asyncronously.
  1.7693 + *
  1.7694 + * Parameters:
  1.7695 + *
  1.7696 + *   handle           MP4 library handle
  1.7697 + *   trak             TRAK atom pointer
  1.7698 + *   buffer           Audio frame is retuned here
  1.7699 + *   buffersize       Size of buffer
  1.7700 + *
  1.7701 + * Return value:
  1.7702 + *
  1.7703 + *   0                Success
  1.7704 + *   Negative         Error
  1.7705 + *
  1.7706 + */
  1.7707 +mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle,
  1.7708 +                         	  trackAtom *trak,
  1.7709 +                         	  mp4_u8 *buffer,
  1.7710 +                         	  mp4_u32 *buffersize)
  1.7711 +{
  1.7712 +  if (trak)
  1.7713 +	{
  1.7714 +	if (!trak->mdia)
  1.7715 +		return -1;
  1.7716 +	}
  1.7717 +  else
  1.7718 +    {
  1.7719 +	return -1;
  1.7720 +    }
  1.7721 +  
  1.7722 +  if (handle->audioSampleSize > *buffersize)
  1.7723 +		{
  1.7724 +		*buffersize = handle->audioSampleSize;
  1.7725 +		return -2;
  1.7726 +		}
  1.7727 +  
  1.7728 +  if (!handle->file) // Other input than file is not supported
  1.7729 +	  {
  1.7730 +	  return -1;
  1.7731 +	  }
  1.7732 +  
  1.7733 +  if ( handle->asyncReader == NULL )
  1.7734 +  	{
  1.7735 +	TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile ));
  1.7736 +	if ( error != KErrNone )
  1.7737 +		{
  1.7738 +		if (error == KErrNoMemory )
  1.7739 +			{
  1.7740 +			return MP4_OUT_OF_MEMORY;    		
  1.7741 +			}
  1.7742 +		else
  1.7743 +			{
  1.7744 +			return -1;
  1.7745 +			}
  1.7746 +		}  	
  1.7747 +  	}
  1.7748 +    
  1.7749 +  return handle->asyncReader->ReadAudioFrames( buffer, handle->audioSampleOffset, handle->audioSampleSize);
  1.7750 +}
  1.7751 +
  1.7752 +/*
  1.7753 + * Function:
  1.7754 + *
  1.7755 + *   mp4_i32 convertAudioSampleToTime(MP4HandleImp handle,
  1.7756 + *                                    mediaAtom *mdia,
  1.7757 + *                                    mp4_u32 *timestamp,
  1.7758 + *                                    mp4_u32 *timestamp2)
  1.7759 + *
  1.7760 + * Description:
  1.7761 + *
  1.7762 + *   This function converts an audio sample to corresponding time.
  1.7763 + *
  1.7764 + * Parameters:
  1.7765 + *
  1.7766 + *   handle       MP4 library handle
  1.7767 + *   mdia         MDIA atom pointer
  1.7768 + *   timestamp    Time in milliseconds is returned here
  1.7769 + *   timestamp2   Time in timescale is returned here
  1.7770 + *
  1.7771 + * Return value:
  1.7772 + *
  1.7773 + *   0            Success
  1.7774 + *   Negative     Error
  1.7775 + *
  1.7776 + */
  1.7777 +mp4_i32 convertAudioSampleToTime(MP4HandleImp handle,
  1.7778 +                                 mediaAtom *mdia,
  1.7779 +                                 mp4_u32 *timestamp,
  1.7780 +                                 mp4_u32 *timestamp2)
  1.7781 +	{
  1.7782 +	mp4_u32      tmptime;
  1.7783 +	mp4_double  tmptime2;
  1.7784 +	mp4_u32      sample;
  1.7785 +	mp4_u32      entry;
  1.7786 +
  1.7787 +  	if (!mdia->mdhd)
  1.7788 +  		{
  1.7789 +  		return -1;
  1.7790 +  		}
  1.7791 +  	if (!mdia->minf)
  1.7792 +  		{
  1.7793 +  		return -1;
  1.7794 +  		}
  1.7795 +  	if (!mdia->minf->stbl)
  1.7796 +  		{
  1.7797 +  		return -1;
  1.7798 +  		}
  1.7799 +  	if (!mdia->minf->stbl->stts)
  1.7800 +  		{
  1.7801 +  		return -1;
  1.7802 +  		}
  1.7803 +  	if (mdia->minf->stbl->stts->entryCount == 0)
  1.7804 +  		{
  1.7805 +  		return -1;
  1.7806 +  		}
  1.7807 +
  1.7808 +  	tmptime = 0;
  1.7809 +  	sample = 0;
  1.7810 +  	entry = 0;
  1.7811 +
  1.7812 +  	for (;;)
  1.7813 +  		{
  1.7814 +  		if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->audioSampleNum)
  1.7815 +  			{
  1.7816 +  			sample += mdia->minf->stbl->stts->sampleCount[entry];
  1.7817 +  			tmptime += mdia->minf->stbl->stts->sampleCount[entry] *
  1.7818 +                 	mdia->minf->stbl->stts->sampleDelta[entry];
  1.7819 +  			entry++;
  1.7820 +  			
  1.7821 +  			if (entry == mdia->minf->stbl->stts->entryCount)
  1.7822 +  				return -1;
  1.7823 +  			}
  1.7824 +  		else
  1.7825 +  			{
  1.7826 +  			tmptime += (handle->audioSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry];
  1.7827 +  			break;
  1.7828 +  			}
  1.7829 +  		}
  1.7830 +
  1.7831 +  	if (mdia->mdhd->timeScale == 0)
  1.7832 +  		{
  1.7833 +  		return -1;
  1.7834 +  		}
  1.7835 +
  1.7836 +  	if (timestamp2)
  1.7837 +  		{
  1.7838 +  		*timestamp2 = tmptime;
  1.7839 +  		}
  1.7840 +
  1.7841 +  	tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5;
  1.7842 +
  1.7843 +  	*timestamp = (mp4_u32)tmptime2;
  1.7844 +
  1.7845 +  	return 0;
  1.7846 +	}
  1.7847 +
  1.7848 +
  1.7849 +/*
  1.7850 + * Function:
  1.7851 + *
  1.7852 + *   mp4_i32 convertTimeToSample(MP4HandleImp handle,
  1.7853 + *                               trackAtom *trak,
  1.7854 + *                               mp4_u32 position,
  1.7855 + *                               mp4_u32 *sample)
  1.7856 + *
  1.7857 + * Description:
  1.7858 + *
  1.7859 + *   This function converts time to corresponding sample number.
  1.7860 + *
  1.7861 + * Parameters:
  1.7862 + *
  1.7863 + *   handle       MP4 library handle
  1.7864 + *   trak         trackAtom pointer
  1.7865 + *   position     Time in milliseconds
  1.7866 + *   sample       Sample number is returned here
  1.7867 + *
  1.7868 + * Return value:
  1.7869 + *
  1.7870 + *   0            Success
  1.7871 + *   Negative     Error
  1.7872 + *
  1.7873 + */
  1.7874 +mp4_i32 convertTimeToSample(MP4HandleImp handle,
  1.7875 +                            trackAtom *trak,
  1.7876 +                            mp4_u32 position,
  1.7877 +                            mp4_u32 *sample)
  1.7878 +{
  1.7879 +  mp4_u32 pos;      /* Target position in media timescale */
  1.7880 +  mp4_u32 tmppos;   /* Temporary position counter */
  1.7881 +  mp4_u32 i;
  1.7882 +
  1.7883 +
  1.7884 +  if (!handle)
  1.7885 +    return -1;
  1.7886 +  if (!trak)
  1.7887 +    return -1;
  1.7888 +  if (!trak->mdia)
  1.7889 +    return -1;
  1.7890 +  if (!trak->mdia->mdhd)
  1.7891 +    return -1;
  1.7892 +  if (!trak->mdia->minf)
  1.7893 +    return -1;
  1.7894 +  if (!trak->mdia->minf->stbl)
  1.7895 +    return -1;
  1.7896 +  if (!trak->mdia->minf->stbl->stts)
  1.7897 +    return -1;
  1.7898 +  if (trak->mdia->minf->stbl->stts->entryCount == 0)
  1.7899 +    return -1;
  1.7900 +
  1.7901 +  *sample = 1;
  1.7902 +  tmppos = 0;
  1.7903 +
  1.7904 +  pos = (mp4_u32)((mp4_double)position / (mp4_double)1000 * (mp4_double)trak->mdia->mdhd->timeScale + (mp4_double)0.5);
  1.7905 +
  1.7906 +  for (i = 0; i < trak->mdia->minf->stbl->stts->entryCount; i++)
  1.7907 +  {
  1.7908 +    if (pos >= (tmppos + trak->mdia->minf->stbl->stts->sampleCount[i] *
  1.7909 +                         trak->mdia->minf->stbl->stts->sampleDelta[i]))
  1.7910 +    {
  1.7911 +      *sample += trak->mdia->minf->stbl->stts->sampleCount[i];
  1.7912 +      tmppos += (trak->mdia->minf->stbl->stts->sampleCount[i] *
  1.7913 +                 trak->mdia->minf->stbl->stts->sampleDelta[i]);
  1.7914 +
  1.7915 +      if (i == trak->mdia->minf->stbl->stts->entryCount - 1) /* Last entry */
  1.7916 +        *sample = *sample - 1;
  1.7917 +    }
  1.7918 +    else
  1.7919 +    {
  1.7920 +      if (trak->mdia->minf->stbl->stts->sampleDelta[i] == 0)
  1.7921 +        return -1;
  1.7922 +
  1.7923 +      *sample += ((pos - tmppos) / trak->mdia->minf->stbl->stts->sampleDelta[i]);
  1.7924 +
  1.7925 +      break;
  1.7926 +    }
  1.7927 +  }
  1.7928 +
  1.7929 +  return 0;
  1.7930 +}
  1.7931 +
  1.7932 +
  1.7933 +/*
  1.7934 + * Function:
  1.7935 + *
  1.7936 + *   mp4_i32 goToVideoSample(MP4HandleImp handle,
  1.7937 + *                           trackAtom *trak,
  1.7938 + *                           mp4_u32 sample)
  1.7939 + *
  1.7940 + * Description:
  1.7941 + *
  1.7942 + *   This function moves to video sample indicated by sample and finds the
  1.7943 + *   sample offset and sample size.
  1.7944 + *
  1.7945 + * Parameters:
  1.7946 + *
  1.7947 + *   handle    MP4 library handle
  1.7948 + *   trak      TRAK atom pointer
  1.7949 + *   sample    Sample to go to
  1.7950 + *
  1.7951 + * Return value:
  1.7952 + *
  1.7953 + *   0         Success
  1.7954 + *   Negative  Error
  1.7955 + *
  1.7956 + */
  1.7957 +mp4_i32 goToVideoSample(MP4HandleImp handle,
  1.7958 +                        trackAtom *trak,
  1.7959 +                        mp4_u32 sample)
  1.7960 +{
  1.7961 +  if (!trak->mdia)
  1.7962 +    return -1;
  1.7963 +  if (!trak->mdia->minf)
  1.7964 +    return -1;
  1.7965 +  if (!trak->mdia->minf->stbl)
  1.7966 +    return -1;
  1.7967 +  if (!trak->mdia->minf->stbl->stsz)
  1.7968 +    return -1;
  1.7969 +
  1.7970 +
  1.7971 +  /* Is the sample valid? */
  1.7972 +
  1.7973 +  if (sample <= trak->mdia->minf->stbl->stsz->sampleCount)
  1.7974 +    handle->videoSampleNum = sample;
  1.7975 +  else
  1.7976 +    return -1;
  1.7977 +
  1.7978 +  /* Find the size of the sample */
  1.7979 +
  1.7980 +  if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
  1.7981 +    return -1;
  1.7982 +
  1.7983 +  /* Find the offset of the sample */
  1.7984 +
  1.7985 +  if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0)
  1.7986 +    return -1;
  1.7987 +
  1.7988 +
  1.7989 +  return 0;
  1.7990 +}
  1.7991 +
  1.7992 +
  1.7993 +/*
  1.7994 + * Function:
  1.7995 + *
  1.7996 + *   mp4_i32 goToAudioSample(MP4HandleImp handle,
  1.7997 + *                           trackAtom *trak,
  1.7998 + *                           mp4_u32 sample)
  1.7999 + *
  1.8000 + * Description:
  1.8001 + *
  1.8002 + *   This function moves to audio sample indicated by sample and finds the
  1.8003 + *   sample offset and sample size.
  1.8004 + *
  1.8005 + * Parameters:
  1.8006 + *
  1.8007 + *   handle    MP4 library handle
  1.8008 + *   trak      TRAK atom pointer
  1.8009 + *   sample    Sample to go to
  1.8010 + *
  1.8011 + * Return value:
  1.8012 + *
  1.8013 + *   0         Success
  1.8014 + *   Negative  Error
  1.8015 + *
  1.8016 + */
  1.8017 +mp4_i32 goToAudioSample(MP4HandleImp handle,
  1.8018 +                        trackAtom *trak,
  1.8019 +                        mp4_u32 sample)
  1.8020 +{
  1.8021 +  if (!trak->mdia)
  1.8022 +    return -1;
  1.8023 +  if (!trak->mdia->minf)
  1.8024 +    return -1;
  1.8025 +  if (!trak->mdia->minf->stbl)
  1.8026 +    return -1;
  1.8027 +  if (!trak->mdia->minf->stbl->stsz)
  1.8028 +    return -1;
  1.8029 +
  1.8030 +
  1.8031 +  /* Is the sample valid? */
  1.8032 +
  1.8033 +  if (sample <= trak->mdia->minf->stbl->stsz->sampleCount)
  1.8034 +    handle->audioSampleNum = sample;
  1.8035 +  else
  1.8036 +    return -1;
  1.8037 +
  1.8038 +  /* Find the size of the sample */
  1.8039 +
  1.8040 +  if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
  1.8041 +    return -1;
  1.8042 +
  1.8043 +  /* Find the offset of the sample */
  1.8044 +
  1.8045 +  if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0)
  1.8046 +    return -1;
  1.8047 +
  1.8048 +
  1.8049 +  return 0;
  1.8050 +}
  1.8051 +
  1.8052 +
  1.8053 +/*
  1.8054 + * Function:
  1.8055 + *
  1.8056 + *   mp4_i32 findVideoKeyFrame(MP4HandleImp handle,
  1.8057 + *                             trackAtom *trak,
  1.8058 + *                             mp4_u32 sample,
  1.8059 + *                             mp4_u32 *newsample)
  1.8060 + *
  1.8061 + * Description:
  1.8062 + *
  1.8063 + *   This function finds the video keyframe that is identical to or precedes
  1.8064 + *   the sample indicated by sample.
  1.8065 + *
  1.8066 + * Parameters:
  1.8067 + *
  1.8068 + *   handle       MP4 library handle
  1.8069 + *   trak         TRAK atom pointer
  1.8070 + *   sample       Sample number
  1.8071 + *   newsample    Sample number of found keyframe
  1.8072 + *
  1.8073 + * Return value:
  1.8074 + *
  1.8075 + *   0            Success
  1.8076 + *   Negative     Error
  1.8077 + *
  1.8078 + */
  1.8079 +mp4_i32 findVideoKeyFrame(MP4HandleImp handle,
  1.8080 +                          trackAtom *trak,
  1.8081 +                          mp4_u32 sample,
  1.8082 +                          mp4_u32 *newsample)
  1.8083 +{
  1.8084 +  mp4_i32  i;
  1.8085 +
  1.8086 +
  1.8087 +  if (!handle)
  1.8088 +    return -1;
  1.8089 +  if (!trak->mdia)
  1.8090 +    return -1;
  1.8091 +  if (!trak->mdia->minf)
  1.8092 +    return -1;
  1.8093 +  if (!trak->mdia->minf->stbl)
  1.8094 +    return -1;
  1.8095 +
  1.8096 +  if (!trak->mdia->minf->stbl->stss) /* No sync sample atom => all samples are
  1.8097 +                                        random access points */
  1.8098 +  {
  1.8099 +    *newsample = sample;
  1.8100 +
  1.8101 +    return 0;
  1.8102 +  }
  1.8103 +  *newsample = 0;
  1.8104 +
  1.8105 +  for (i = trak->mdia->minf->stbl->stss->entryCount - 1; i >= 0; i--)
  1.8106 +  {
  1.8107 +    if (sample >= trak->mdia->minf->stbl->stss->sampleNumber[i])
  1.8108 +    {
  1.8109 +      *newsample = trak->mdia->minf->stbl->stss->sampleNumber[i];
  1.8110 +      break;
  1.8111 +    }
  1.8112 +  }
  1.8113 +
  1.8114 +  if (*newsample == 0)
  1.8115 +    return -1;
  1.8116 +
  1.8117 +  return 0;
  1.8118 +}
  1.8119 +
  1.8120 +
  1.8121 +/*
  1.8122 + * Function:
  1.8123 + *
  1.8124 + *   mp4_i32 readAVCC(MP4HandleImp handle,
  1.8125 + *                    avcConfigurationAtom *avcc)
  1.8126 + *
  1.8127 + * Description:
  1.8128 + *
  1.8129 + *   This function parses one avcc atom.
  1.8130 + *
  1.8131 + * Parameters:
  1.8132 + *
  1.8133 + *   handle             MP4 library handle
  1.8134 + *   avcc               avcC pointer
  1.8135 + *
  1.8136 + * Return value:
  1.8137 + *
  1.8138 + *   Negative integer   Error
  1.8139 + *   >= 0               Success. Value tells how many bytes were read.
  1.8140 + *
  1.8141 + */
  1.8142 +mp4_i32 readAVCC(MP4HandleImp handle, avcConfigurationAtom *avcc)
  1.8143 +{
  1.8144 +	mp4_i32 bytesread;
  1.8145 +	mp4_i32 totalbytesread = 0;
  1.8146 +
  1.8147 +	avcc->avcConfigSize = 0;
  1.8148 +
  1.8149 +	if ((avcc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8150 +		return -100;
  1.8151 +
  1.8152 +	bytesread = readAtomHeader(handle, avcc->atomhdr);
  1.8153 +	if (bytesread < 0)
  1.8154 +		return -1;
  1.8155 +	totalbytesread +=bytesread;
  1.8156 +
  1.8157 +	if (avcc->atomhdr->type != ATOMTYPE_AVCC)
  1.8158 +		return -1;
  1.8159 +
  1.8160 +    /* read the avcDecoderConfigurationRecord */
  1.8161 +    if  (avcc->atomhdr->size != 1)
  1.8162 +    	avcc->avcConfigSize = avcc->atomhdr->size - 8;
  1.8163 +    else
  1.8164 +    	avcc->avcConfigSize = (mp4_u32)(I64INT(avcc->atomhdr->largeSize) - 16);
  1.8165 +
  1.8166 +   	avcc->avcConfig = (mp4_u8 *)mp4malloc(avcc->avcConfigSize);
  1.8167 +	if (avcc->avcConfig == 0)
  1.8168 +		return -100;
  1.8169 +	
  1.8170 +	bytesread = readData(handle, avcc->avcConfig, avcc->avcConfigSize );
  1.8171 +    
  1.8172 +	if (bytesread < 0)
  1.8173 +		return -1;
  1.8174 +	totalbytesread +=bytesread;
  1.8175 +	return totalbytesread;
  1.8176 +}
  1.8177 +
  1.8178 +
  1.8179 +/*
  1.8180 + * Function:
  1.8181 + *
  1.8182 + *   mp4_i32 readBTRT(MP4HandleImp handle,
  1.8183 + *                    mpeg4BitrateAtom *btrt)
  1.8184 + *
  1.8185 + * Description:
  1.8186 + *
  1.8187 + *   This function parses one btrt atom.
  1.8188 + *
  1.8189 + * Parameters:
  1.8190 + *
  1.8191 + *   handle             MP4 library handle
  1.8192 + *   btrt					btrt pointer
  1.8193 + *
  1.8194 + * Return value:
  1.8195 + *
  1.8196 + *   Negative integer   Error
  1.8197 + *   >= 0               Success. Value tells how many bytes were read.
  1.8198 + *
  1.8199 + */
  1.8200 +mp4_i32 readBTRT(MP4HandleImp handle, mpeg4BitrateAtom *btrt)
  1.8201 +{
  1.8202 +	mp4_i32 bytesread;
  1.8203 +	mp4_i32 totalbytesread = 0;
  1.8204 +
  1.8205 +
  1.8206 +	if ((btrt->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8207 +		return -100;
  1.8208 +
  1.8209 +	bytesread = readAtomHeader(handle, btrt->atomhdr);
  1.8210 +	if (bytesread < 0)
  1.8211 +		return -1;
  1.8212 +	totalbytesread +=bytesread;
  1.8213 +
  1.8214 +	if (btrt->atomhdr->type != ATOMTYPE_BTRT)
  1.8215 +		return -1;
  1.8216 +
  1.8217 +    /* read the mpeg4BitrateAtom */
  1.8218 +   bytesread = readData(handle, handle->buf, 4);
  1.8219 +   if (bytesread < 0)
  1.8220 +	   return -1;
  1.8221 +   btrt->bufferSizeDB = u32endian(*((mp4_u32 *)handle->buf));
  1.8222 +   totalbytesread +=bytesread;
  1.8223 +
  1.8224 +   bytesread = readData(handle, handle->buf, 4);
  1.8225 +   if (bytesread < 0)
  1.8226 +	   return -1;
  1.8227 +   btrt->maxBitRate = u32endian(*((mp4_u32 *)handle->buf));
  1.8228 +   totalbytesread +=bytesread;
  1.8229 +
  1.8230 +   bytesread = readData(handle, handle->buf, 4);
  1.8231 +   if (bytesread < 0)
  1.8232 +	   return -1;
  1.8233 +   btrt->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
  1.8234 +   totalbytesread +=bytesread;
  1.8235 +
  1.8236 +	return totalbytesread;
  1.8237 +}
  1.8238 +
  1.8239 +/*
  1.8240 + * Function:
  1.8241 + *
  1.8242 + *   mp4_i32 readM4DS(MP4HandleImp handle,
  1.8243 + *                    mpeg4ExtensionDescriptorsAtom *m4ds)
  1.8244 + *
  1.8245 + * Description:
  1.8246 + *
  1.8247 + *   This function parses one m4ds atom.
  1.8248 + *
  1.8249 + * Parameters:
  1.8250 + *
  1.8251 + *   handle             MP4 library handle
  1.8252 + *   m4ds               m4ds pointer
  1.8253 + *
  1.8254 + * Return value:
  1.8255 + *
  1.8256 + *   Negative integer   Error
  1.8257 + *   >= 0               Success. Value tells how many bytes were read.
  1.8258 + *
  1.8259 + */
  1.8260 +mp4_i32 readM4DS(MP4HandleImp handle, mpeg4ExtensionDescriptorsAtom *m4ds)
  1.8261 +{
  1.8262 +	mp4_i32 bytesread;
  1.8263 +	mp4_i32 totalbytesread = 0;
  1.8264 +	mp4_u32 i;
  1.8265 +
  1.8266 +	m4ds->descrSize = 0;
  1.8267 +
  1.8268 +	if ((m4ds->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8269 +		return -100;
  1.8270 +
  1.8271 +	bytesread = readAtomHeader(handle, m4ds->atomhdr);
  1.8272 +	if (bytesread < 0)
  1.8273 +		return -1;
  1.8274 +	totalbytesread +=bytesread;
  1.8275 +
  1.8276 +	if (m4ds->atomhdr->type != ATOMTYPE_M4DS)
  1.8277 +		return -1;
  1.8278 +
  1.8279 +    /* read the avcDecoderConfigurationRecord */
  1.8280 +	if  (m4ds->atomhdr->size != 1)
  1.8281 +		bytesread = readData(handle, handle->buf, m4ds->atomhdr->size - 8);
  1.8282 +	else
  1.8283 +        bytesread = readData(handle, handle->buf, (mp4_u32)(I64INT(m4ds->atomhdr->largeSize) - 16) );
  1.8284 +
  1.8285 +	if (bytesread < 0)
  1.8286 +		return -1;
  1.8287 +	m4ds->descrSize = bytesread;
  1.8288 +	m4ds->descr = (mp4_u8 *)mp4malloc(m4ds->descrSize * sizeof(mp4_u8));
  1.8289 +	
  1.8290 +	/* copy the mpeg4ExtensionDescriptors from the temp. buffer */
  1.8291 +	for(i = 0; i <  m4ds->descrSize; i++)
  1.8292 +		m4ds->descr[i] = handle->buf[i];
  1.8293 +	
  1.8294 +	totalbytesread +=bytesread;
  1.8295 +
  1.8296 +	return totalbytesread;
  1.8297 +}
  1.8298 +
  1.8299 +/*
  1.8300 + * Function:
  1.8301 + *
  1.8302 + *   mp4_i32 readAVC1(MP4HandleImp handle,
  1.8303 + *                    avcSampleEntry *avc1)
  1.8304 + *
  1.8305 + * Description:
  1.8306 + *
  1.8307 + *   This function parses one avc1 atom.
  1.8308 + *
  1.8309 + * Parameters:
  1.8310 + *
  1.8311 + *   handle             MP4 library handle
  1.8312 + *   avc1               avc1 pointer
  1.8313 + *
  1.8314 + * Return value:
  1.8315 + *
  1.8316 + *   Negative integer   Error
  1.8317 + *   >= 0               Success. Value tells how many bytes were read.
  1.8318 + *
  1.8319 + */
  1.8320 +mp4_i32 readAVC1(MP4HandleImp handle, avcSampleEntry *avc1)
  1.8321 +{
  1.8322 +  mp4_i32 bytesread;
  1.8323 +  mp4_i32 totalbytesread = 0;
  1.8324 +
  1.8325 +  if ((avc1->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8326 +    return -100;
  1.8327 +
  1.8328 +  bytesread = readAtomHeader(handle, avc1->atomhdr);
  1.8329 +
  1.8330 +  if (bytesread < 0)
  1.8331 +    return -1;
  1.8332 +  totalbytesread += bytesread;
  1.8333 +
  1.8334 +  if (avc1->atomhdr->type != ATOMTYPE_AVC1)
  1.8335 +    return -1;
  1.8336 +
  1.8337 +  bytesread = discardData(handle, 6);
  1.8338 +  if (bytesread < 0)
  1.8339 +    return -1;
  1.8340 +  totalbytesread += bytesread;
  1.8341 +
  1.8342 +  bytesread = readData(handle, handle->buf, 2);
  1.8343 +  if (bytesread < 0)
  1.8344 +    return -1;
  1.8345 +  avc1->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.8346 +  totalbytesread += bytesread;
  1.8347 +
  1.8348 +  bytesread = discardData(handle, 16);
  1.8349 +  if (bytesread < 0)
  1.8350 +    return -1;
  1.8351 +  totalbytesread += bytesread;
  1.8352 +
  1.8353 +  bytesread = readData(handle, handle->buf, 2);
  1.8354 +  if (bytesread < 0)
  1.8355 +    return -1;
  1.8356 +  avc1->width = u16endian(*((mp4_u16 *)handle->buf));
  1.8357 +  totalbytesread += bytesread;
  1.8358 +
  1.8359 +  bytesread = readData(handle, handle->buf, 2);
  1.8360 +  if (bytesread < 0)
  1.8361 +    return -1;
  1.8362 +  avc1->height = u16endian(*((mp4_u16 *)handle->buf));
  1.8363 +  totalbytesread += bytesread;
  1.8364 +
  1.8365 +  bytesread = discardData(handle, 50);
  1.8366 +  if (bytesread < 0)
  1.8367 +    return -1;
  1.8368 +  totalbytesread += bytesread;
  1.8369 +
  1.8370 +  /* Check for the present atoms */
  1.8371 +  while ((mp4_u32)totalbytesread < avc1->atomhdr->size)
  1.8372 +  {
  1.8373 +    mp4_u32 type;
  1.8374 +
  1.8375 +    if (peekData(handle, handle->buf, 8) < 0)
  1.8376 +      return -1;
  1.8377 +
  1.8378 +    type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.8379 +
  1.8380 +    switch (type)
  1.8381 +    {
  1.8382 +    case ATOMTYPE_AVCC:
  1.8383 +
  1.8384 +		if (avc1->avcc) /* avcC has already been read, more than one is not allowed. */
  1.8385 +			return -1;
  1.8386 +
  1.8387 +		if ((avc1->avcc = (avcConfigurationAtom *)mp4malloc(sizeof(avcConfigurationAtom))) == NULL)
  1.8388 +			return -100;
  1.8389 +
  1.8390 +		bytesread = readAVCC(handle, avc1->avcc);  
  1.8391 +		if(bytesread < 0)
  1.8392 +			return -1;
  1.8393 +		totalbytesread +=bytesread;
  1.8394 +  	    break;
  1.8395 +
  1.8396 +    case ATOMTYPE_BTRT:
  1.8397 +
  1.8398 +		if (avc1->btrt) /* btrt has already been read, more than one is not allowed. */
  1.8399 +			return -1;
  1.8400 +
  1.8401 +		if ((avc1->btrt = (mpeg4BitrateAtom *)mp4malloc(sizeof(mpeg4BitrateAtom))) == NULL)
  1.8402 +			return -100;
  1.8403 +
  1.8404 +		bytesread = readBTRT(handle, avc1->btrt);  
  1.8405 +		if(bytesread < 0)
  1.8406 +			return -1;
  1.8407 +		totalbytesread +=bytesread;
  1.8408 +	    break;
  1.8409 +
  1.8410 +    case ATOMTYPE_M4DS:
  1.8411 +
  1.8412 +		if (avc1->m4ds) /* m4ds has already been read, more than one is not allowed. */
  1.8413 +			return -1;
  1.8414 +
  1.8415 +		if ((avc1->m4ds = (mpeg4ExtensionDescriptorsAtom *)mp4malloc(sizeof(mpeg4ExtensionDescriptorsAtom))) == NULL)
  1.8416 +			return -100;
  1.8417 +
  1.8418 +		bytesread = readM4DS(handle, avc1->m4ds);  
  1.8419 +		if(bytesread < 0)
  1.8420 +			return -1;
  1.8421 +		totalbytesread +=bytesread;
  1.8422 +	    break;
  1.8423 +	 
  1.8424 +	 default:
  1.8425 +
  1.8426 +        bytesread = readUnknown(handle);
  1.8427 +        if (bytesread < 0)
  1.8428 +            return -1;
  1.8429 +        totalbytesread += bytesread;
  1.8430 +
  1.8431 +        break;
  1.8432 +
  1.8433 +	}
  1.8434 +  }
  1.8435 +
  1.8436 +  return totalbytesread;
  1.8437 +}
  1.8438 +
  1.8439 +/*
  1.8440 + * Function:
  1.8441 + *
  1.8442 + *   mp4_i32 freeAVCC(avcConfigurationAtom *avcc)
  1.8443 + *
  1.8444 + * Description:
  1.8445 + *
  1.8446 + *   This function frees memory for avcc atom.
  1.8447 + *
  1.8448 + * Parameters:
  1.8449 + *
  1.8450 + *   avcc       avcc atom pointer
  1.8451 + *
  1.8452 + * Return value:
  1.8453 + *
  1.8454 + *   0          Success
  1.8455 + *   Negative   Error
  1.8456 + *
  1.8457 + */
  1.8458 +mp4_i32 freeAVCC(avcConfigurationAtom *avcc)
  1.8459 +{
  1.8460 +  if (avcc)
  1.8461 +  {
  1.8462 +    if (freeAtomHeader(avcc->atomhdr) < 0)
  1.8463 +      return -1;
  1.8464 +	if(avcc->avcConfig)
  1.8465 +		mp4free(avcc->avcConfig);
  1.8466 +
  1.8467 +    mp4free(avcc);
  1.8468 +  }
  1.8469 +
  1.8470 +  return 0;
  1.8471 +}
  1.8472 +
  1.8473 +/*
  1.8474 + * Function:
  1.8475 + *
  1.8476 + *   mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt)
  1.8477 + *
  1.8478 + * Description:
  1.8479 + *
  1.8480 + *   This function frees memory for btrt atom.
  1.8481 + *
  1.8482 + * Parameters:
  1.8483 + *
  1.8484 + *   btrt       btrt atom pointer
  1.8485 + *
  1.8486 + * Return value:
  1.8487 + *
  1.8488 + *   0          Success
  1.8489 + *   Negative   Error
  1.8490 + *
  1.8491 + */
  1.8492 +mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt)
  1.8493 +{
  1.8494 +  if (btrt)
  1.8495 +  {
  1.8496 +    if (freeAtomHeader(btrt->atomhdr) < 0)
  1.8497 +      return -1;
  1.8498 +
  1.8499 +    mp4free(btrt);
  1.8500 +  }
  1.8501 +
  1.8502 +  return 0;
  1.8503 +}
  1.8504 +
  1.8505 +/*
  1.8506 + * Function:
  1.8507 + *
  1.8508 + *   mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds)
  1.8509 + *
  1.8510 + * Description:
  1.8511 + *
  1.8512 + *   This function frees memory for m4ds atom.
  1.8513 + *
  1.8514 + * Parameters:
  1.8515 + *
  1.8516 + *   m4ds       m4ds atom pointer
  1.8517 + *
  1.8518 + * Return value:
  1.8519 + *
  1.8520 + *   0          Success
  1.8521 + *   Negative   Error
  1.8522 + *
  1.8523 + */
  1.8524 +mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds)
  1.8525 +{
  1.8526 +  if (m4ds)
  1.8527 +  {
  1.8528 +    if (freeAtomHeader(m4ds->atomhdr) < 0)
  1.8529 +      return -1;
  1.8530 +	if(m4ds->descr)
  1.8531 +		mp4free(m4ds->descr);
  1.8532 +
  1.8533 +    mp4free(m4ds);
  1.8534 +  }
  1.8535 +
  1.8536 +  return 0;
  1.8537 +}
  1.8538 +
  1.8539 +/*
  1.8540 + * Function:
  1.8541 + *
  1.8542 + *   mp4_i32 freeAVC1(avcSampleEntry *avc1)
  1.8543 + *
  1.8544 + * Description:
  1.8545 + *
  1.8546 + *   This function frees memory for avc1 atom.
  1.8547 + *
  1.8548 + * Parameters:
  1.8549 + *
  1.8550 + *   avc1       avc1 atom pointer
  1.8551 + *
  1.8552 + * Return value:
  1.8553 + *
  1.8554 + *   0          Success
  1.8555 + *   Negative   Error
  1.8556 + *
  1.8557 + */
  1.8558 +mp4_i32 freeAVC1(avcSampleEntry *avc1)
  1.8559 +{
  1.8560 +  if (avc1)
  1.8561 +  {
  1.8562 +    if (freeAtomHeader(avc1->atomhdr) < 0)
  1.8563 +      return -1;
  1.8564 +    if (freeAVCC(avc1->avcc) < 0)
  1.8565 +      return -1;
  1.8566 +	if (freeBTRT(avc1->btrt) < 0)
  1.8567 +		return -1;
  1.8568 +	if (freeM4DS(avc1->m4ds) < 0)
  1.8569 +		return -1;
  1.8570 +
  1.8571 +    mp4free(avc1);
  1.8572 +  }
  1.8573 +
  1.8574 +  return 0;
  1.8575 +}
  1.8576 +
  1.8577 +/*
  1.8578 + * Function:
  1.8579 + *
  1.8580 + *   mp4_i32 readSQCP(MP4HandleImp handle,
  1.8581 + *                    qcelpSampleEntry *sqcp)
  1.8582 + *
  1.8583 + * Description:
  1.8584 + *
  1.8585 + *   This function parses one SQCP atom.
  1.8586 + *
  1.8587 + * Parameters:
  1.8588 + *
  1.8589 + *   handle             MP4 library handle
  1.8590 + *   sqcp               SQCP pointer
  1.8591 + *
  1.8592 + * Return value:
  1.8593 + *
  1.8594 + *   Negative integer   Error
  1.8595 + *   >= 0               Success. Value tells how many bytes were read.
  1.8596 + *
  1.8597 + */
  1.8598 +mp4_i32 readSQCP(MP4HandleImp handle, qcelpSampleEntry *sqcp)
  1.8599 +{
  1.8600 +  mp4_i32 bytesread;
  1.8601 +  mp4_i32 totalbytesread = 0;
  1.8602 +
  1.8603 +
  1.8604 +  if ((sqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8605 +    return -100;
  1.8606 +
  1.8607 +  bytesread = readAtomHeader(handle, sqcp->atomhdr);
  1.8608 +  if (bytesread < 0)
  1.8609 +    return -1;
  1.8610 +  totalbytesread += bytesread;
  1.8611 +
  1.8612 +  if (sqcp->atomhdr->type != ATOMTYPE_SQCP)
  1.8613 +    return -1;
  1.8614 +
  1.8615 +
  1.8616 +  bytesread = discardData(handle, 6);
  1.8617 +  if (bytesread < 0)
  1.8618 +    return -1;
  1.8619 +  totalbytesread += bytesread;
  1.8620 +
  1.8621 +  bytesread = readData(handle, handle->buf, 2);
  1.8622 +  if (bytesread < 0)
  1.8623 +    return -1;
  1.8624 +  sqcp->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
  1.8625 +  totalbytesread += bytesread;
  1.8626 +
  1.8627 +  bytesread = discardData(handle, 16);
  1.8628 +  if (bytesread < 0)
  1.8629 +    return -1;
  1.8630 +  totalbytesread += bytesread;
  1.8631 +
  1.8632 +  bytesread = readData(handle, handle->buf, 2);
  1.8633 +  if (bytesread < 0)
  1.8634 +    return -1;
  1.8635 +  sqcp->timeScale = u16endian(*((mp4_u16 *)handle->buf));
  1.8636 +  totalbytesread += bytesread;
  1.8637 +
  1.8638 +  bytesread = discardData(handle, 2);
  1.8639 +  if (bytesread < 0)
  1.8640 +    return -1;
  1.8641 +  totalbytesread += bytesread;
  1.8642 +
  1.8643 +  if ((sqcp->dqcp = (qcelpDecSpecStruc *)mp4malloc(sizeof(qcelpDecSpecStruc))) == NULL)
  1.8644 +    return -100;
  1.8645 +
  1.8646 +  bytesread = readDQCP(handle, sqcp->dqcp);
  1.8647 +  if (bytesread < 0)
  1.8648 +    return -1;
  1.8649 +  totalbytesread += bytesread;
  1.8650 +  
  1.8651 +  if ( totalbytesread < sqcp->atomhdr->size )
  1.8652 +  	{
  1.8653 +    bytesread = discardData(handle, sqcp->atomhdr->size - totalbytesread );
  1.8654 +  	if (bytesread < 0)
  1.8655 +  		{
  1.8656 +    	return -1;	  		
  1.8657 +  		}
  1.8658 +  	totalbytesread += bytesread;
  1.8659 +  	}  
  1.8660 +
  1.8661 +  return totalbytesread;
  1.8662 +}
  1.8663 +
  1.8664 +/*
  1.8665 + * Function:
  1.8666 + *
  1.8667 + *   mp4_i32 freeSQCP(qcelpSampleEntry *sqcp)
  1.8668 + *
  1.8669 + * Description:
  1.8670 + *
  1.8671 + *   This function frees memory for SQCP atom.
  1.8672 + *
  1.8673 + * Parameters:
  1.8674 + *
  1.8675 + *   sqcp       SQCP atom pointer
  1.8676 + *
  1.8677 + * Return value:
  1.8678 + *
  1.8679 + *   0          Success
  1.8680 + *   Negative   Error
  1.8681 + *
  1.8682 + */
  1.8683 +mp4_i32 freeSQCP(qcelpSampleEntry *sqcp)
  1.8684 +{
  1.8685 +  if (sqcp)
  1.8686 +  {
  1.8687 +    if (freeAtomHeader(sqcp->atomhdr) < 0)
  1.8688 +      return -1;
  1.8689 +    if (freeDQCP(sqcp->dqcp) < 0)
  1.8690 +      return -1;
  1.8691 +
  1.8692 +    mp4free(sqcp);
  1.8693 +  }
  1.8694 +
  1.8695 +  return 0;
  1.8696 +}
  1.8697 +
  1.8698 +/*
  1.8699 + * Function:
  1.8700 + *
  1.8701 + *   mp4_i32 readDQCP(MP4HandleImp handle,
  1.8702 + *                    qcelpDecSpecStruc *dqcp)
  1.8703 + *
  1.8704 + * Description:
  1.8705 + *
  1.8706 + *   This function parses one DQCP atom.
  1.8707 + *
  1.8708 + * Parameters:
  1.8709 + *
  1.8710 + *   handle             MP4 library handle
  1.8711 + *   dqcp               DQCP pointer
  1.8712 + *
  1.8713 + * Return value:
  1.8714 + *
  1.8715 + *   Negative integer   Error
  1.8716 + *   >= 0               Success. Value tells how many bytes were read.
  1.8717 + *
  1.8718 + */
  1.8719 +mp4_i32 readDQCP(MP4HandleImp handle, qcelpDecSpecStruc *dqcp)
  1.8720 +{
  1.8721 +  mp4_i32 bytesread;
  1.8722 +  mp4_i32 totalbytesread = 0;
  1.8723 +
  1.8724 +
  1.8725 +  if ((dqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8726 +    return -100;
  1.8727 +
  1.8728 +  bytesread = readAtomHeader(handle, dqcp->atomhdr);
  1.8729 +  if (bytesread < 0)
  1.8730 +    return -1;
  1.8731 +  totalbytesread += bytesread;
  1.8732 +
  1.8733 +  if (dqcp->atomhdr->type != ATOMTYPE_DQCP)
  1.8734 +    return -1;
  1.8735 +
  1.8736 +
  1.8737 +  bytesread = readData(handle, handle->buf, 4);
  1.8738 +  if (bytesread < 0)
  1.8739 +    return -1;
  1.8740 +  dqcp->vendor = u32endian(*((mp4_u32 *)handle->buf));
  1.8741 +  totalbytesread += bytesread;
  1.8742 +
  1.8743 +  bytesread = readData(handle, handle->buf, 1);
  1.8744 +  if (bytesread < 0)
  1.8745 +    return -1;
  1.8746 +  dqcp->decoderVersion = handle->buf[0];
  1.8747 +  totalbytesread += bytesread;
  1.8748 +
  1.8749 +  bytesread = readData(handle, handle->buf, 1);
  1.8750 +  if (bytesread < 0)
  1.8751 +    return -1;
  1.8752 +  dqcp->framesPerSample = handle->buf[0];
  1.8753 +  totalbytesread += bytesread;
  1.8754 +
  1.8755 +  return totalbytesread;
  1.8756 +}
  1.8757 +
  1.8758 +/*
  1.8759 + * Function:
  1.8760 + *
  1.8761 + *   mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp)
  1.8762 + *
  1.8763 + * Description:
  1.8764 + *
  1.8765 + *   This function frees memory for DQCP atom.
  1.8766 + *
  1.8767 + * Parameters:
  1.8768 + *
  1.8769 + *   damr       DQCP atom pointer
  1.8770 + *
  1.8771 + * Return value:
  1.8772 + *
  1.8773 + *   0          Success
  1.8774 + *   Negative   Error
  1.8775 + *
  1.8776 + */
  1.8777 +mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp)
  1.8778 +{
  1.8779 +  if (dqcp)
  1.8780 +  {
  1.8781 +    if (freeAtomHeader(dqcp->atomhdr) < 0)
  1.8782 +      return -1;
  1.8783 +
  1.8784 +    mp4free(dqcp);
  1.8785 +  }
  1.8786 +
  1.8787 +  return 0;
  1.8788 +}
  1.8789 +
  1.8790 +/*
  1.8791 + * Function:
  1.8792 + *
  1.8793 + *   mp4_i32 readSDTP(MP4HandleImp handle, sampleDependencyAtom *sdtp, 
  1.8794 + * 				      mp4_i32 sample_count)
  1.8795 + *
  1.8796 + * Description:
  1.8797 + *
  1.8798 + *   This function parses one SDTP atom.
  1.8799 + *
  1.8800 + * Parameters:
  1.8801 + *
  1.8802 + *   handle             MP4 library handle
  1.8803 + *   sdtp               SDTP atom pointer
  1.8804 + *
  1.8805 + * Return value:
  1.8806 + *
  1.8807 + *   Negative integer   Error
  1.8808 + *   >= 0               Success. Value tells how many bytes were read.
  1.8809 + *
  1.8810 + */
  1.8811 +
  1.8812 +mp4_i32 readSDTP(MP4HandleImp handle, 
  1.8813 +				 sampleDependencyAtom *sdtp, 
  1.8814 +				 mp4_i32 sample_count)
  1.8815 +{
  1.8816 +  mp4_i32 bytesread = 0;
  1.8817 +  mp4_i32 totalbytesread = 0;
  1.8818 +  mp4_u32 i = 0;
  1.8819 +
  1.8820 +  if ((sdtp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8821 +    return -100;
  1.8822 +
  1.8823 +  bytesread = readAtomHeader(handle, sdtp->atomhdr);
  1.8824 +  if (bytesread < 0)
  1.8825 +    return -1;
  1.8826 +  totalbytesread += bytesread;
  1.8827 +
  1.8828 +  if (sdtp->atomhdr->type != ATOMTYPE_SDTP)
  1.8829 +    return -1;
  1.8830 +  
  1.8831 +  bytesread = readData(handle, handle->buf, 1); //Version must be 0
  1.8832 +  if (bytesread < 0 || handle->buf[0] != 0)
  1.8833 +    return -1;
  1.8834 +  totalbytesread += bytesread;
  1.8835 +  bytesread = readData(handle, handle->buf, 3); // Flags must be 0
  1.8836 +  if (bytesread < 0 || handle->buf[0] != 0 || handle->buf[1] != 0 || handle->buf[2] != 0)
  1.8837 +    return -1;
  1.8838 +  totalbytesread += bytesread;
  1.8839 +
  1.8840 +  // sample_count == (size_of_atom - 12) ???  12 = size + 'sdtp' + ver + flags = 4 + 4 + 1 + 3 ???
  1.8841 +  //
  1.8842 +  // sample_count is taken from the sample_count in the Sample Size Box ('stsz') or
  1.8843 +  // Compact Sample Size Box (‘stz2’).
  1.8844 +  if (sample_count != sdtp->atomhdr->size-12 || sample_count < 0)
  1.8845 +	  {
  1.8846 +	  // as each byte consititue one entry in the table, the number of remaining bytes in this
  1.8847 +	  // atom should match the sample count.  If not, the file is corrupted.
  1.8848 +	  return -1;
  1.8849 +	  }
  1.8850 +  
  1.8851 +  if ((sdtp->dep = (sampleDependency *)mp4malloc(sample_count * sizeof(sampleDependency))) == NULL)
  1.8852 +    return -100;
  1.8853 +  
  1.8854 +  for(i=0;i<sample_count;i++)
  1.8855 +  {
  1.8856 +    bytesread = readData(handle, handle->buf, 1);
  1.8857 +    if (bytesread < 0)
  1.8858 +      return -1;
  1.8859 +    
  1.8860 +    sdtp->dep[i].sDependsOn = (handle->buf[0] >> 4) & 0x03; // value from 0 to 3
  1.8861 +    sdtp->dep[i].sIsDependentOn = (handle->buf[0] >> 2) & 0x03; // value from 0 to 3
  1.8862 +    sdtp->dep[i].sHasRedundancy = handle->buf[0] & 0x03; // value from 0 to 3
  1.8863 +    totalbytesread += bytesread;
  1.8864 +  }
  1.8865 +
  1.8866 +  sdtp->sampleCount = sample_count;
  1.8867 +  return totalbytesread;	
  1.8868 +}
  1.8869 +
  1.8870 +/*
  1.8871 + * Function:
  1.8872 + *
  1.8873 + *   mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type)
  1.8874 + * 				      
  1.8875 + *
  1.8876 + * Description:
  1.8877 + *
  1.8878 + *   This function parses the size and type information for a box. 
  1.8879 + *   Taking into account largesize if needed.
  1.8880 + *
  1.8881 + * Parameters:
  1.8882 + *
  1.8883 + *   handle             MP4 library handle
  1.8884 + *   size               Size of box is returned here
  1.8885 + *   type               Type of the box is returned here
  1.8886 + * Return value:
  1.8887 + *
  1.8888 + *   Negative integer   Error
  1.8889 + *   0               Success.
  1.8890 + *
  1.8891 + */
  1.8892 +mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type)
  1.8893 +{
  1.8894 +  if (peekData(handle, handle->buf, 8) < 0)
  1.8895 +    return -1;
  1.8896 +
  1.8897 +  *size = u32endian(*((mp4_u32 *)handle->buf));
  1.8898 +  *type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.8899 +
  1.8900 +  if (*size == 1)
  1.8901 +  {
  1.8902 +    if (peekData(handle, handle->buf, 16) < 0)
  1.8903 +      return -1;
  1.8904 +    
  1.8905 +    *size = u64endian(*((mp4_u64 *)(handle->buf+8)));
  1.8906 +  }
  1.8907 +
  1.8908 +  return 0;
  1.8909 +}
  1.8910 +
  1.8911 +/*
  1.8912 + */
  1.8913 +
  1.8914 +mp4_i64 getChunkOffset(sampleTableAtom *stbl, mp4_u32 index)
  1.8915 +{
  1.8916 +  if (stbl->is32BitOffsets)
  1.8917 +  	return (mp4_i64)stbl->stco->chunkOffset[index];
  1.8918 +  else
  1.8919 +    return stbl->stco64->chunkOffset[index];
  1.8920 +}
  1.8921 +
  1.8922 +/*
  1.8923 + * Function:
  1.8924 + *
  1.8925 + *   mp4_i32 readMeta(MP4HandleImp handle,
  1.8926 + *                    metaAtom *meta)
  1.8927 + *
  1.8928 + * Description:
  1.8929 + *
  1.8930 + *   This function parses one META atom.
  1.8931 + *
  1.8932 + * Parameters:
  1.8933 + *
  1.8934 + *   handle             MP4 library handle
  1.8935 + *   meta               META pointer
  1.8936 + *
  1.8937 + * Return value:
  1.8938 + *
  1.8939 + *   Negative integer   Error
  1.8940 + *   >= 0               Success. Value tells how many bytes were read.
  1.8941 + *
  1.8942 + */
  1.8943 +mp4_i32 readMeta(MP4HandleImp handle, metaAtom *meta)
  1.8944 +{
  1.8945 +    mp4_i32 bytesread;
  1.8946 +    mp4_i32 totalbytesread = 0;
  1.8947 +
  1.8948 +
  1.8949 +    if ((meta->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.8950 +      return -100;
  1.8951 +
  1.8952 +    bytesread = readFullAtomHeader(handle, meta->atomhdr);
  1.8953 +    if (bytesread < 0)
  1.8954 +      return -1;
  1.8955 +    totalbytesread += bytesread;
  1.8956 +
  1.8957 +    if (meta->atomhdr->type != ATOMTYPE_META)
  1.8958 +      return -1;
  1.8959 +
  1.8960 +
  1.8961 +    while ((mp4_u32)totalbytesread < meta->atomhdr->size)
  1.8962 +    {
  1.8963 +      mp4_u32 type;
  1.8964 +
  1.8965 +
  1.8966 +      if (peekData(handle, handle->buf, 8) < 0)
  1.8967 +        return -1;
  1.8968 +      
  1.8969 +      type = u32endian(*((mp4_u32 *)(handle->buf+4)));
  1.8970 +
  1.8971 +      switch (type)
  1.8972 +      {
  1.8973 +      case ATOMTYPE_HDLR:
  1.8974 +
  1.8975 +        if (meta->hdlr) /* HDLR has already been read, more than one is not allowed */
  1.8976 +          return -1;
  1.8977 +
  1.8978 +        if ((meta->hdlr = (handlerAtom *)mp4malloc(sizeof(handlerAtom))) == NULL)
  1.8979 +          return -100;
  1.8980 +
  1.8981 +        bytesread = readHDLR(handle, meta->hdlr);
  1.8982 +        if (bytesread < 0)
  1.8983 +          return -1;
  1.8984 +        totalbytesread += bytesread;
  1.8985 +
  1.8986 +        break;
  1.8987 +          
  1.8988 +      case ATOMTYPE_ID32:
  1.8989 +          
  1.8990 +        if (meta->ID32) /* ID32 has already been read, more than one is not allowed */
  1.8991 +          return -1;
  1.8992 +
  1.8993 +        if ((meta->ID32 = (ID32Atom *)mp4malloc(sizeof(ID32Atom))) == NULL)
  1.8994 +          return -100;
  1.8995 +
  1.8996 +        bytesread = readID32(handle, meta->ID32);
  1.8997 +        if (bytesread < 0)
  1.8998 +          return -1;
  1.8999 +        totalbytesread += bytesread;
  1.9000 +          
  1.9001 +        break;
  1.9002 +        
  1.9003 +      default:
  1.9004 +
  1.9005 +        bytesread = readUnknown(handle);
  1.9006 +        if (bytesread < 0)
  1.9007 +          return -1;
  1.9008 +        totalbytesread += bytesread;
  1.9009 +
  1.9010 +        break;
  1.9011 +      }
  1.9012 +    }
  1.9013 +
  1.9014 +    return totalbytesread;
  1.9015 +}
  1.9016 +
  1.9017 +/*
  1.9018 + * Function:
  1.9019 + *
  1.9020 + *   mp4_i32 readID32(MP4HandleImp handle,
  1.9021 + *                    ID32Atom *ID32)
  1.9022 + *
  1.9023 + * Description:
  1.9024 + *
  1.9025 + *   This function parses one ID32 atom.
  1.9026 + *
  1.9027 + * Parameters:
  1.9028 + *
  1.9029 + *   handle             MP4 library handle
  1.9030 + *   ID32               ID32 pointer
  1.9031 + *
  1.9032 + * Return value:
  1.9033 + *
  1.9034 + *   Negative integer   Error
  1.9035 + *   >= 0               Success. Value tells how many bytes were read.
  1.9036 + *
  1.9037 + */
  1.9038 +mp4_i32 readID32(MP4HandleImp handle, ID32Atom *ID32)
  1.9039 +{
  1.9040 +   mp4_i32 bytesread;
  1.9041 +   mp4_i32 totalbytesread = 0;
  1.9042 +
  1.9043 +
  1.9044 +   if ((ID32->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
  1.9045 +     return -100;
  1.9046 +
  1.9047 +   bytesread = readFullAtomHeader(handle, ID32->atomhdr);
  1.9048 +   if (bytesread < 0)
  1.9049 +     return -1;
  1.9050 +   totalbytesread += bytesread;
  1.9051 +
  1.9052 +   if (ID32->atomhdr->type != ATOMTYPE_ID32)
  1.9053 +     return -1;
  1.9054 +
  1.9055 +   // next 2 bytes: top bit is padding, remaining 15 bits is Packed ISO-639-2/T language code 
  1.9056 +   bytesread = readData(handle, handle->buf, 2);
  1.9057 +   if (bytesread < 0)
  1.9058 +     return -1;
  1.9059 +   ID32->language = u16endian(*((mp4_u16 *)handle->buf));
  1.9060 +   totalbytesread += bytesread;
  1.9061 +   
  1.9062 +   if ( handle->file )
  1.9063 +       {
  1.9064 +       ID32->atomcontentloc = handle->diskReadBufStart + handle->diskReadBufPos;
  1.9065 +       }
  1.9066 +   else
  1.9067 +       {
  1.9068 +       ID32->atomcontentloc = handle->absPosition;
  1.9069 +       }
  1.9070 +   
  1.9071 +   bytesread = discardData(handle, ID32->atomhdr->size - totalbytesread );
  1.9072 +   if (bytesread < 0)
  1.9073 +     return -1;
  1.9074 +   totalbytesread += bytesread;     
  1.9075 +   
  1.9076 +   return totalbytesread;
  1.9077 +}
  1.9078 +
  1.9079 +/*
  1.9080 + * Function:
  1.9081 + *
  1.9082 + *   mp4_i32 freeMETA(metaAtom *meta)
  1.9083 + *
  1.9084 + * Description:
  1.9085 + *
  1.9086 + *   This function frees memory for META atom.
  1.9087 + *
  1.9088 + * Parameters:
  1.9089 + *
  1.9090 + *   meta       META atom pointer
  1.9091 + *
  1.9092 + * Return value:
  1.9093 + *
  1.9094 + *   0          Success
  1.9095 + *   Negative   Error
  1.9096 + *
  1.9097 + */
  1.9098 +mp4_i32 freeMETA(metaAtom *meta)
  1.9099 +{
  1.9100 +  if (meta)
  1.9101 +  {
  1.9102 +    if (freeAtomHeader(meta->atomhdr) < 0)
  1.9103 +      return -1;
  1.9104 +    if (freeHDLR(meta->hdlr) < 0)
  1.9105 +       return -1;
  1.9106 +    if (freeID32(meta->ID32) < 0)
  1.9107 +      return -1;
  1.9108 +
  1.9109 +    mp4free(meta);
  1.9110 +  }
  1.9111 +
  1.9112 +  return 0;
  1.9113 +}
  1.9114 +
  1.9115 +/*
  1.9116 + * Function:
  1.9117 + *
  1.9118 + *   mp4_i32 freeID32(ID32Atom *ID32)
  1.9119 + *
  1.9120 + * Description:
  1.9121 + *
  1.9122 + *   This function frees memory for ID32 atom.
  1.9123 + *
  1.9124 + * Parameters:
  1.9125 + *
  1.9126 + *   ID32       ID32 atom pointer
  1.9127 + *
  1.9128 + * Return value:
  1.9129 + *
  1.9130 + *   0          Success
  1.9131 + *   Negative   Error
  1.9132 + *
  1.9133 + */
  1.9134 +mp4_i32 freeID32(ID32Atom *ID32)
  1.9135 +{
  1.9136 +  if (ID32)
  1.9137 +  {
  1.9138 +    if (freeAtomHeader(ID32->atomhdr) < 0)
  1.9139 +      return -1;
  1.9140 +
  1.9141 +    mp4free(ID32);
  1.9142 +  }
  1.9143 +
  1.9144 +  return 0;
  1.9145 +}
  1.9146 +// End of File