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