sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include <3gplibrary/mp4config.h> sl@0: #include <3gplibrary/mp4lib.h> sl@0: #include "mp4atom.h" sl@0: #include "mp4memwrap.h" sl@0: #include "mp4buffer.h" sl@0: #include "mp4endian.h" sl@0: #include "mp4file.h" sl@0: #include "mp4utils.h" sl@0: sl@0: // MACROS sl@0: // Debug print macro sl@0: #ifdef _DEBUG sl@0: #include sl@0: //#define PRINT(x) RDebug::Print x sl@0: #define PRINT(x) sl@0: #else sl@0: #define PRINT(x) sl@0: #endif sl@0: sl@0: mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type); sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 metaDataAvailable(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines whether meta data is available for reading sl@0: * or not. sl@0: * sl@0: * Meta data is available if the input is in a file. sl@0: * sl@0: * When reading from a stream, meta data is considered available if sl@0: * it is in the beginning of the stream and the entire Moov atom has sl@0: * been received. FTYP atom is allowed before MOOV atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Meta data is not available because enough data has not sl@0: * been inserted into the library sl@0: * 1 Meta data is available sl@0: * Negative value Meta data is not available because of fatal error sl@0: * sl@0: */ sl@0: mp4_i32 metaDataAvailable(MP4HandleImp handle) sl@0: { sl@0: mp4_u32 size; sl@0: mp4_u32 type; sl@0: sl@0: sl@0: /* Meta data is available if the input is in a file or if a complete file has been inputted as a stream*/ sl@0: sl@0: if (handle->file) sl@0: return 1; sl@0: sl@0: /* When reading from a stream, meta data is considered available if sl@0: it is in the beginning of the stream and the entire MOOV atom has sl@0: been received. FTYP atom is allowed before MOOV atom. */ sl@0: sl@0: if (!handle->ftypRead) sl@0: { sl@0: if (peekData(handle, handle->buf, 8) < 0) /* 8 bytes are not available */ sl@0: return 0; sl@0: sl@0: size = u32endian(*((mp4_u32 *)handle->buf)); sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: if (type == ATOMTYPE_FTYP) sl@0: { sl@0: if (getBufferedBytes(handle) - handle->position < size) /* FTYP is not available */ sl@0: return 0; sl@0: if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL) sl@0: return -100; sl@0: if (readFTYP(handle, handle->ftyp) < 0) sl@0: return -2; sl@0: } sl@0: } sl@0: sl@0: // Now the ftyp is read. No need to chedk MOOV presence for full files in the memory. sl@0: if (handle->LastWriteDataCalled == MP4TRUE) sl@0: return 1; sl@0: sl@0: if (handle->LastWriteDataCalled == MP4FALSE) sl@0: {//Whole stream is not fed to the internal memory yet. sl@0: for (;;) sl@0: { sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return 0; sl@0: sl@0: size = u32endian(*((mp4_u32 *)handle->buf)); sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: if (type == ATOMTYPE_MOOV) sl@0: { sl@0: if (getBufferedBytes(handle) - handle->absPosition >= size) /* Entire Moov is available */ sl@0: { sl@0: return 1; sl@0: } sl@0: else sl@0: { sl@0: return 0; sl@0: } sl@0: } sl@0: sl@0: if ((mp4_i32)size <= 0) sl@0: return -1; sl@0: sl@0: handle->absPosition+=size; sl@0: } sl@0: } sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readFTYP(MP4HandleImp handle, sl@0: * fileTypeAtom *ftyp) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one FTYP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ftyp FTYP pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readFTYP(MP4HandleImp handle, fileTypeAtom *ftyp) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 n = 0; sl@0: mp4_i32 compatiblebrandsize = 0; sl@0: sl@0: sl@0: if ((ftyp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, ftyp->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (ftyp->atomhdr->type != ATOMTYPE_FTYP) sl@0: return -1; sl@0: sl@0: if (ftyp->atomhdr->size < 16) // 8(header)+8bytes needed for major and minor brand sl@0: return -1; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ftyp->majorBrand = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ftyp->minorVersion = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if (ftyp->atomhdr->size == (mp4_u32)totalbytesread) sl@0: return totalbytesread; sl@0: sl@0: compatiblebrandsize = (mp4_i32)ftyp->atomhdr->size - totalbytesread; sl@0: if ( compatiblebrandsize < 4 ) // at this point we must have at least 1 compatible brand sl@0: return -1; sl@0: if ( compatiblebrandsize > 20*4) // maximum of 20 compatible brands 4byte entries sl@0: return -1; sl@0: if ( compatiblebrandsize % 4 ) // must be able to divide by 4 sl@0: return -1; sl@0: sl@0: ftyp->compatibleBrands = (mp4_u32 *)mp4malloc( compatiblebrandsize ); sl@0: if (ftyp->compatibleBrands == NULL) sl@0: return -1; sl@0: sl@0: while ((mp4_u32)totalbytesread < ftyp->atomhdr->size) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: ftyp->compatibleBrands[n] = u32endian(*((mp4_u32 *)handle->buf)); sl@0: sl@0: n++; sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMetaData(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function reads the meta data from the file/stream and stores sl@0: * the information in the atom structures available via handle. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative value Error sl@0: * >= 0 Success. Value tells the number of bytes read. sl@0: * sl@0: */ sl@0: mp4_i32 readMetaData(MP4HandleImp handle) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if (handle->file) sl@0: { sl@0: mp4_u64 size; sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (seekFileAbs(handle, 0) < 0) sl@0: return -1; sl@0: sl@0: /* Seek to the start of FTYP atom */ sl@0: sl@0: for (;;) sl@0: { sl@0: if (readBoxHeader(handle, &size, &type) <0) sl@0: return -1; sl@0: sl@0: if (type == ATOMTYPE_FTYP) sl@0: { sl@0: /* Read FTYP */ sl@0: sl@0: if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL) sl@0: return -100; sl@0: bytesread = readFTYP(handle, handle->ftyp); sl@0: if (bytesread < 0) sl@0: return -3; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: sl@0: if (size <= 0) sl@0: return -1; sl@0: sl@0: if (seekFile(handle, size) != 0) sl@0: return -1; sl@0: } sl@0: sl@0: if (seekFileAbs(handle, 0) < 0) sl@0: return -1; sl@0: sl@0: /* Seek to the start of MOOV atom */ sl@0: for (;;) sl@0: { sl@0: if (readBoxHeader(handle, &size, &type) <0) sl@0: return -1; sl@0: sl@0: if (type == ATOMTYPE_MOOV) sl@0: break; sl@0: sl@0: if (size <= 0) sl@0: return -1; sl@0: sl@0: if (seekFile(handle, size) != 0) sl@0: return -1; sl@0: } sl@0: } sl@0: sl@0: // If all data of a file is in the memory and the file does not have MOOV box right after FTYP, sl@0: // then we need to seek for the location of the MOOV first sl@0: sl@0: if (handle->LastWriteDataCalled == MP4TRUE) sl@0: { sl@0: mp4_u32 size; sl@0: mp4_u32 type; sl@0: // Seek until the beginning of MOOV box. sl@0: for(;;) sl@0: { sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: size = u32endian(*((mp4_u32 *)handle->buf)); sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: if (type == ATOMTYPE_MOOV) sl@0: break; sl@0: sl@0: if ((mp4_i32)size <= 0) sl@0: return -1; sl@0: sl@0: if (discardData(handle, size) < 0) sl@0: return -1; sl@0: } sl@0: } sl@0: sl@0: if ((handle->moov = (movieAtom *)mp4malloc(sizeof(movieAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readMoov(handle, handle->moov); sl@0: if (bytesread < 0) sl@0: return -3; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (handle->moov->trakAudio) sl@0: { sl@0: mp4_u32 audiotype; sl@0: mp4_i32 errorAudio = 0; sl@0: sl@0: errorAudio = determineAudioType(handle, &audiotype); sl@0: if ( errorAudio == 0 ) sl@0: { sl@0: handle->type |= audiotype; sl@0: sl@0: /* Move to the beginning of the 1st audio frame */ sl@0: switch (advanceAudioSample(handle, handle->moov->trakAudio)) sl@0: { sl@0: case -1: sl@0: return -1; sl@0: case -2: sl@0: handle->audioLast = MP4TRUE; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: else if (errorAudio == -2) sl@0: { sl@0: handle->type |= audiotype; sl@0: } sl@0: else sl@0: { sl@0: return -1; sl@0: } sl@0: } sl@0: sl@0: if (handle->moov->trakVideo) sl@0: { sl@0: mp4_u32 videotype; sl@0: mp4_i32 errorVideo = 0; sl@0: sl@0: errorVideo = determineVideoType(handle, &videotype); sl@0: if ( errorVideo == 0 ) sl@0: { sl@0: handle->type |= videotype; sl@0: sl@0: /* Move to the beginning of the 1st video frame */ sl@0: switch (advanceVideoFrame(handle, handle->moov->trakVideo)) sl@0: { sl@0: case -1: sl@0: return -1; sl@0: case -2: sl@0: handle->videoLast = MP4TRUE; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: else if (errorVideo == -2) sl@0: { sl@0: handle->type |= videotype; sl@0: } sl@0: else sl@0: { sl@0: return -1; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMoov(MP4HandleImp handle, sl@0: * movieAtom *moov) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MOOV atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * moov MOOV pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMoov(MP4HandleImp handle, movieAtom *moov) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((moov->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, moov->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (moov->atomhdr->type != ATOMTYPE_MOOV) sl@0: return -1; sl@0: sl@0: while ((mp4_u32)totalbytesread < handle->moov->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_MVHD: sl@0: sl@0: if (moov->mvhd) /* MVHD has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((moov->mvhd = (movieHeaderAtom *)mp4malloc(sizeof(movieHeaderAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readMVHD(handle, moov->mvhd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_IODS: sl@0: sl@0: if (moov->iods) /* IODS has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((moov->iods = (objectDescriptorAtom *)mp4malloc(sizeof(objectDescriptorAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readIODS(handle, moov->iods); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_TRAK: sl@0: sl@0: { sl@0: trackAtom *ta; sl@0: sl@0: if ((ta = (trackAtom *)mp4malloc(sizeof(trackAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readTRAK(handle, ta); sl@0: if (bytesread < 0) sl@0: { sl@0: if (freeTRAK(ta) < 0) sl@0: return -1; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: sl@0: if (!ta->mdia) sl@0: { sl@0: if (freeTRAK(ta) < 0) sl@0: return -1; sl@0: return -1; sl@0: } sl@0: if (!ta->mdia->hdlr) sl@0: { sl@0: if (freeTRAK(ta) < 0) sl@0: return -1; sl@0: return -1; sl@0: } sl@0: sl@0: if (ta->mdia->hdlr->handlerType != HANDLERTYPE_VIDE && sl@0: ta->mdia->hdlr->handlerType != HANDLERTYPE_SOUN) /* Track is neither video nor audio */ sl@0: { sl@0: /* Do nothing with the unknown track */ sl@0: if (freeTRAK(ta) < 0) sl@0: return -1; sl@0: break; sl@0: } sl@0: sl@0: if (ta->mdia->hdlr->handlerType == HANDLERTYPE_VIDE) sl@0: { sl@0: if (moov->trakVideo) /* Video Track already read */ sl@0: { sl@0: if (freeTRAK(ta) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: moov->trakVideo = ta; sl@0: } sl@0: } sl@0: else if (ta->mdia->hdlr->handlerType == HANDLERTYPE_SOUN) sl@0: { sl@0: if (moov->trakAudio) /* Audio Track already read */ sl@0: { sl@0: if (freeTRAK(ta) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: moov->trakAudio = ta; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: } sl@0: break; sl@0: } sl@0: sl@0: case ATOMTYPE_UDTA: sl@0: sl@0: { sl@0: if (moov->udta) /* UDTA has already been read */ sl@0: { sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: break; sl@0: } sl@0: sl@0: sl@0: if ((moov->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readUDTA(handle, moov->udta); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: sl@0: case ATOMTYPE_META: sl@0: sl@0: { sl@0: if (moov->meta) /* META has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((moov->meta = (metaAtom *)mp4malloc(sizeof(metaAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readMeta(handle, moov->meta); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readAtomheader(MP4HandleImp handle, sl@0: * atomHeader *ah) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function reads an atom header and stores the information sl@0: * in ah. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ah atomHeader structure that is used to store the sl@0: * information sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative value Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readAtomHeader(MP4HandleImp handle, atomHeader *ah) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: //PRINT((_L("readAtomHeader"))); sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ah->size = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ah->type = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if (ah->size == 1) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ah->largeSize = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: if (ah->type == ATOMTYPE_UUID) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4memcpy(ah->extendedType, handle->buf, 16); sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: //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])); sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readFullAtomHeader(MP4HandleImp handle, sl@0: * atomHeader *ah) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function reads a full atom header and stores the information sl@0: * in ah. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ah atomHeader structure that is used to store the sl@0: * information sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative value Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readFullAtomHeader(MP4HandleImp handle, atomHeader *ah) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: //PRINT((_L("readFullAtomHeader"))); sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ah->size = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ah->type = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ah->version = *(handle->buf); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 3); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4memcpy(ah->flags, handle->buf, 3); sl@0: totalbytesread += bytesread; sl@0: sl@0: //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])); sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMVHD(MP4HandleImp handle, sl@0: * movieHeaderAtom *mvhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MVHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mvhd MVHD pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMVHD(MP4HandleImp handle, movieHeaderAtom *mvhd) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((mvhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, mvhd->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (mvhd->atomhdr->type != ATOMTYPE_MVHD) sl@0: return -1; sl@0: sl@0: if (mvhd->atomhdr->version == 1) /* 64 bit */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->duration64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: else /* 32 bit */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->creationTime = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->duration = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: bytesread = discardData(handle, 76); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mvhd->nextTrackID = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readIODS(MP4HandleImp handle, sl@0: * objectDescriptorAtom *iods) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one IODS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * iods IODS pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readIODS(MP4HandleImp handle, objectDescriptorAtom *iods) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((iods->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, iods->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (iods->atomhdr->type != ATOMTYPE_IODS) sl@0: return -1; sl@0: sl@0: bytesread = discardData(handle, iods->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readTRAK(MP4HandleImp handle, sl@0: * trackAtom *trak) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one TRAK atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readTRAK(MP4HandleImp handle, trackAtom *trak) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((trak->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, trak->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (trak->atomhdr->type != ATOMTYPE_TRAK) sl@0: return -1; sl@0: sl@0: sl@0: while ((mp4_u32)totalbytesread < trak->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_TKHD: sl@0: sl@0: if (trak->tkhd) /* MVHD has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((trak->tkhd = (trackHeaderAtom *)mp4malloc(sizeof(trackHeaderAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readTKHD(handle, trak->tkhd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_TREF: sl@0: sl@0: if (trak->tref) /* TREF has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((trak->tref = (trackReferenceAtom *)mp4malloc(sizeof(trackReferenceAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readTREF(handle, trak->tref); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_EDTS: sl@0: sl@0: if (trak->edts) /* EDTS has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((trak->edts = (editListContainerAtom *)mp4malloc(sizeof(editListContainerAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readEDTS(handle, trak->edts); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_MDIA: sl@0: sl@0: if (trak->mdia) /* MDIA has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((trak->mdia = (mediaAtom *)mp4malloc(sizeof(mediaAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readMDIA(handle, trak->mdia); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_UDTA: sl@0: { sl@0: if (trak->udta) /* UDTA has already been read */ sl@0: { sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: break; sl@0: } sl@0: sl@0: if ((trak->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readUDTA(handle, trak->udta); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: sl@0: default: sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readUnknown(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function reads one atom of unknown type. Atom contents are sl@0: * discarded. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readUnknown(MP4HandleImp handle) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 size; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: size = u32endian(*((mp4_u32 *)handle->buf)); sl@0: if ( size < 4 ) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if ( handle->file ) sl@0: { sl@0: if ( seekFile(handle, size - totalbytesread) < 0 ) sl@0: { sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: return size; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: bytesread = discardData(handle, size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: } sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readTKHD(MP4HandleImp handle, sl@0: * trackHeaderAtom *tkhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one TKHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * tkhd TKHD pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readTKHD(MP4HandleImp handle, trackHeaderAtom *tkhd) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((tkhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, tkhd->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (tkhd->atomhdr->type != ATOMTYPE_TKHD) sl@0: return -1; sl@0: sl@0: if (tkhd->atomhdr->version == 1) /* 64 bit */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->duration64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: else /* 32 bit */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->creationTime = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->duration = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: bytesread = discardData(handle, 52); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->width = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: tkhd->height = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readTREF(MP4HandleImp handle, sl@0: * trackReferenceAtom *tref) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one TREF atom and discards the contents. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * tref TREF pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readTREF(MP4HandleImp handle, trackReferenceAtom *tref) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((tref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, tref->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (tref->atomhdr->type != ATOMTYPE_TREF) sl@0: return -1; sl@0: sl@0: bytesread = discardData(handle, tref->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readEDTS(MP4HandleImp handle, sl@0: * editListContainerAtom *edts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one EDTS atom and discards the contents. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * edts EDTS pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readEDTS(MP4HandleImp handle, editListContainerAtom *edts) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((edts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, edts->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (edts->atomhdr->type != ATOMTYPE_EDTS) sl@0: return -1; sl@0: sl@0: bytesread = discardData(handle, edts->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMDIA(MP4HandleImp handle, sl@0: * mediaAtom *mdia) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MDIA atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mdia MDIA pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMDIA(MP4HandleImp handle, mediaAtom *mdia) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((mdia->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, mdia->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (mdia->atomhdr->type != ATOMTYPE_MDIA) sl@0: return -1; sl@0: sl@0: sl@0: while ((mp4_u32)totalbytesread < mdia->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_MDHD: sl@0: sl@0: if (mdia->mdhd) /* MDHD has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((mdia->mdhd = (mediaHeaderAtom *)mp4malloc(sizeof(mediaHeaderAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readMDHD(handle, mdia->mdhd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_HDLR: sl@0: sl@0: if (mdia->hdlr) /* HDLR has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((mdia->hdlr = (handlerAtom *)mp4malloc(sizeof(handlerAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readHDLR(handle, mdia->hdlr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_MINF: sl@0: sl@0: if (mdia->minf) /* MINF has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((mdia->minf = (mediaInformationAtom *)mp4malloc(sizeof(mediaInformationAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readMINF(handle, mdia->minf); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: default: sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMDHD(MP4HandleImp handle, sl@0: * mediaHeaderAtom *mdhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MDHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mdhd MDHD pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMDHD(MP4HandleImp handle, mediaHeaderAtom *mdhd) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((mdhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, mdhd->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (mdhd->atomhdr->type != ATOMTYPE_MDHD) sl@0: return -1; sl@0: sl@0: sl@0: if (mdhd->atomhdr->version == 1) /* 64 bit */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->duration64 = u64endian(*((mp4_u64 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: else /* 32 bit */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->creationTime = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mdhd->duration = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: bytesread = discardData(handle, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readHDLR(MP4HandleImp handle, sl@0: * handlerAtom *hdlr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one HDLR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * hdlr HDLR pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readHDLR(MP4HandleImp handle, handlerAtom *hdlr) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((hdlr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, hdlr->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (hdlr->atomhdr->type != ATOMTYPE_HDLR) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: hdlr->handlerType = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, hdlr->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMINF(MP4HandleImp handle, sl@0: * mediaInformationAtom *minf) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MINF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * minf MINF pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMINF(MP4HandleImp handle, mediaInformationAtom *minf) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((minf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, minf->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (minf->atomhdr->type != ATOMTYPE_MINF) sl@0: return -1; sl@0: sl@0: sl@0: while ((mp4_u32)totalbytesread < minf->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_VMHD: sl@0: sl@0: if (minf->vmhd || minf->smhd) /* VMHD or SMHD has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((minf->vmhd = (videoMediaHeaderAtom *)mp4malloc(sizeof(videoMediaHeaderAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readVMHD(handle, minf->vmhd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_SMHD: sl@0: sl@0: if (minf->smhd || minf->vmhd) /* SMHD or VMHD has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((minf->smhd = (soundMediaHeaderAtom *)mp4malloc(sizeof(soundMediaHeaderAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSMHD(handle, minf->smhd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_DINF: sl@0: sl@0: if (minf->dinf) /* DINF has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((minf->dinf = (dataInformationAtom *)mp4malloc(sizeof(dataInformationAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readDINF(handle, minf->dinf); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_STBL: sl@0: sl@0: if (minf->stbl) /* STBL has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((minf->stbl = (sampleTableAtom *)mp4malloc(sizeof(sampleTableAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSTBL(handle, minf->stbl); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: default: sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readVMHD(MP4HandleImp handle, sl@0: * videoMediaHeaderAtom *vmhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one VMHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * vmhd VMHD pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readVMHD(MP4HandleImp handle, videoMediaHeaderAtom *vmhd) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((vmhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, vmhd->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (vmhd->atomhdr->type != ATOMTYPE_VMHD) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, vmhd->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSMHD(MP4HandleImp handle, sl@0: * soundMediaHeaderAtom *smhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one SMHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * smhd SMHD pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSMHD(MP4HandleImp handle, soundMediaHeaderAtom *smhd) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((smhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, smhd->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (smhd->atomhdr->type != ATOMTYPE_SMHD) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, smhd->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readDINF(MP4HandleImp handle, sl@0: * dataInformationAtom *dinf) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one DINF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * dinf DINF pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readDINF(MP4HandleImp handle, dataInformationAtom *dinf) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((dinf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, dinf->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (dinf->atomhdr->type != ATOMTYPE_DINF) sl@0: return -1; sl@0: sl@0: sl@0: while ((mp4_u32)totalbytesread < dinf->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_DREF: sl@0: sl@0: if (dinf->dref) /* DINF has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((dinf->dref = (dataReferenceAtom *)mp4malloc(sizeof(dataReferenceAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readDREF(handle, dinf->dref); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: default: sl@0: sl@0: return -1; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readDREF(MP4HandleImp handle, sl@0: * dataReferenceAtom *dref) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one DREF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * dref DREF pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readDREF(MP4HandleImp handle, dataReferenceAtom *dref) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((dref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, dref->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (dref->atomhdr->type != ATOMTYPE_DREF) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: dref->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if (dref->entryCount != 1) sl@0: return -1; sl@0: sl@0: while ((mp4_u32)totalbytesread < dref->atomhdr->size) sl@0: { sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: } sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readURL(MP4HandleImp handle, sl@0: * dataEntryURLAtom *url) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one URL atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * url URL pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readURL(MP4HandleImp handle, dataEntryURLAtom *url) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((url->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, url->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (url->atomhdr->type != ATOMTYPE_URL) sl@0: return -1; sl@0: sl@0: sl@0: if (!(url->atomhdr->flags[0] == 0x00 && sl@0: url->atomhdr->flags[1] == 0x00 && sl@0: url->atomhdr->flags[2] == 0x01)) sl@0: return -1; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readURN(MP4HandleImp handle, sl@0: * dataEntryURNAtom *urn) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one URN atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * urn URN pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readURN(MP4HandleImp handle, dataEntryURNAtom *urn) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((urn->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, urn->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (urn->atomhdr->type != ATOMTYPE_URN) sl@0: return -1; sl@0: sl@0: sl@0: if (!(urn->atomhdr->flags[0] == 0x00 && sl@0: urn->atomhdr->flags[1] == 0x00 && sl@0: urn->atomhdr->flags[2] == 0x01)) sl@0: return -1; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTBL(MP4HandleImp handle, sl@0: * sampleTableAtom *stbl) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STBL atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stbl STBL pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTBL(MP4HandleImp handle, sampleTableAtom *stbl) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((stbl->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, stbl->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stbl->atomhdr->type != ATOMTYPE_STBL) sl@0: return -1; sl@0: sl@0: sl@0: while ((mp4_u32)totalbytesread < stbl->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_STTS: sl@0: sl@0: if (stbl->stts) /* STTS has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stts = (timeToSampleAtom *)mp4malloc(sizeof(timeToSampleAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSTTS(handle, stbl->stts); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_CTTS: sl@0: sl@0: if (stbl->ctts) /* CTTS has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->ctts = (compositionTimeToSampleAtom *)mp4malloc(sizeof(compositionTimeToSampleAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readCTTS(handle, stbl->ctts); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_STSS: sl@0: sl@0: if (stbl->stss) /* STSS has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stss = (syncSampleAtom *)mp4malloc(sizeof(syncSampleAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSTSS(handle, stbl->stss); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_STSD: sl@0: sl@0: if (stbl->stsd) /* STSD has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stsd = (sampleDescriptionAtom *)mp4malloc(sizeof(sampleDescriptionAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSTSD(handle, stbl->stsd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_STSZ: sl@0: sl@0: if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSTSZ(handle, stbl->stsz); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_STZ2: sl@0: sl@0: if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSTZ2(handle, stbl->stsz); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_STSC: sl@0: sl@0: if (stbl->stsc) /* STSC has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stsc = (sampleToChunkAtom *)mp4malloc(sizeof(sampleToChunkAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readSTSC(handle, stbl->stsc); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_STCO: sl@0: sl@0: if (stbl->stco) /* STCO or CO64 has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stco = (chunkOffsetAtom *)mp4malloc(sizeof(chunkOffsetAtom))) == NULL) sl@0: return -100; sl@0: sl@0: stbl->is32BitOffsets = ETrue; sl@0: bytesread = readSTCO(handle, stbl->stco); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_CO64: sl@0: sl@0: if (stbl->stco64) /* STCO or CO64 has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->stco64 = (chunkOffset64Atom *)mp4malloc(sizeof(chunkOffset64Atom))) == NULL) sl@0: return -100; sl@0: sl@0: stbl->is32BitOffsets = EFalse; sl@0: bytesread = readCO64(handle, stbl->stco64); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_SDTP: sl@0: if (stbl->sdtp) /* SDTP has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((stbl->sdtp = (sampleDependencyAtom *)mp4malloc(sizeof(sampleDependencyAtom))) == NULL) sl@0: return -100; sl@0: sl@0: if (!stbl->stsz) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: // sample_count of SDTP is taken from the sample_count in the Sample Size Box ('stsz') or sl@0: // Compact Sample Size Box (‘stz2’). sl@0: bytesread = readSDTP(handle, stbl->sdtp, stbl->stsz->sampleCount); sl@0: sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: break; sl@0: sl@0: default: /* Other atoms are not needed */ sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTTS(MP4HandleImp handle, sl@0: * timeToSampleAtom *stts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stts STTS pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTTS(MP4HandleImp handle, timeToSampleAtom *stts) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i; sl@0: sl@0: sl@0: if ((stts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, stts->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stts->atomhdr->type != ATOMTYPE_STTS) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stts->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( stts->entryCount ) sl@0: { sl@0: stts->sampleCount = (mp4_u32 *)mp4malloc(stts->entryCount * sizeof(mp4_u32)); sl@0: if (stts->sampleCount == NULL) sl@0: return -1; sl@0: stts->sampleDelta = (mp4_i32 *)mp4malloc(stts->entryCount * sizeof(mp4_i32)); sl@0: if (stts->sampleDelta == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < stts->entryCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf)); sl@0: stts->sampleDelta[i] = i32endian(*((mp4_i32 *)(handle->buf+4))); sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readCTTS(MP4HandleImp handle, sl@0: * compositionTimeToSampleAtom *ctts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one CTTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ctts CTTS pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readCTTS(MP4HandleImp handle, compositionTimeToSampleAtom *ctts) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i; sl@0: sl@0: sl@0: if ((ctts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, ctts->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (ctts->atomhdr->type != ATOMTYPE_CTTS) sl@0: return -1; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ctts->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( ctts->entryCount ) sl@0: { sl@0: ctts->sampleCount = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32)); sl@0: if (ctts->sampleCount == NULL) sl@0: return -1; sl@0: ctts->sampleOffset = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32)); sl@0: if (ctts->sampleOffset == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < ctts->entryCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: ctts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf)); sl@0: ctts->sampleOffset[i] = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTSS(MP4HandleImp handle, sl@0: * syncSampleAtom *stss) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STSS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stss STSS pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTSS(MP4HandleImp handle, syncSampleAtom *stss) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i; sl@0: sl@0: sl@0: if ((stss->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, stss->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stss->atomhdr->type != ATOMTYPE_STSS) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stss->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( stss->entryCount ) sl@0: { sl@0: stss->sampleNumber = (mp4_u32 *)mp4malloc(stss->entryCount * sizeof(mp4_u32)); sl@0: if (stss->sampleNumber == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < stss->entryCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stss->sampleNumber[i] = u32endian(*((mp4_u32 *)handle->buf)); sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTSD(MP4HandleImp handle, sl@0: * sampleDescriptionAtom *stsd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STSD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stsd STSD pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTSD(MP4HandleImp handle, sampleDescriptionAtom *stsd) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 totalsampleentriesread = 0; sl@0: mp4_u32 unknownsampleentriesread = 0; sl@0: mp4_bool skipentries = 0; sl@0: sl@0: if ((stsd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readFullAtomHeader(handle, stsd->atomhdr); sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stsd->atomhdr->type != ATOMTYPE_STSD) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: stsd->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: mp4_u32 type; sl@0: while ((mp4_u32)totalbytesread < stsd->atomhdr->size) sl@0: { sl@0: // if the number of entries read already surpasses the number of entries specified sl@0: // within the STSD atom, the file is corrupted. sl@0: if ((totalsampleentriesread + unknownsampleentriesread) >= stsd->entryCount) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: // read the next sample type sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: // if the max sample entiries supported by the library has been reached sl@0: if ((stsd->entryCount > STSDMAXSAMPLEENTRYCOUNT) && (totalsampleentriesread == STSDMAXSAMPLEENTRYCOUNT)) sl@0: { sl@0: // skip reading the rest of the entries to make sure no more than max count of sample entries sl@0: // will be processed, so that cleanup will always work. sl@0: type = 0; sl@0: skipentries = 1; sl@0: } sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_MP4V: sl@0: { sl@0: if (stsd->mp4v[totalsampleentriesread]) /* MP4V[totalsampleentriesread] has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: if ((stsd->mp4v[totalsampleentriesread] = (visualSampleEntry *)mp4malloc(sizeof(visualSampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readMP4V(handle, stsd->mp4v[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: break; sl@0: } sl@0: sl@0: case ATOMTYPE_MP4A: sl@0: { sl@0: if (stsd->mp4a[totalsampleentriesread]) /* MP4A[totalsampleentriesread] has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: if ((stsd->mp4a[totalsampleentriesread] = (audioSampleEntry *)mp4malloc(sizeof(audioSampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readMP4A(handle, stsd->mp4a[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: break; sl@0: } sl@0: sl@0: case ATOMTYPE_MP4S: sl@0: { sl@0: if (stsd->mp4s[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: if ((stsd->mp4s[totalsampleentriesread] = (mpegSampleEntry *)mp4malloc(sizeof(mpegSampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readMP4S(handle, stsd->mp4s[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: break; sl@0: sl@0: case ATOMTYPE_S263: sl@0: { sl@0: if (stsd->s263[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: if ((stsd->s263[totalsampleentriesread] = (h263SampleEntry *)mp4malloc(sizeof(h263SampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readS263(handle, stsd->s263[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: break; sl@0: sl@0: case ATOMTYPE_SAMR: sl@0: { sl@0: if (stsd->samr[totalsampleentriesread]) /* SAMR has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: if ((stsd->samr[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readSAMR(handle, stsd->samr[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: break; sl@0: sl@0: case ATOMTYPE_SAWB: sl@0: { sl@0: if (stsd->sawb[totalsampleentriesread]) /* SAWB has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: sl@0: if ((stsd->sawb[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readSAWB(handle, stsd->sawb[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: break; sl@0: sl@0: case ATOMTYPE_AVC1: sl@0: { sl@0: if (stsd->avc1[totalsampleentriesread]) /* AVC1 has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: if ((stsd->avc1[totalsampleentriesread] = (avcSampleEntry *)mp4malloc(sizeof(avcSampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readAVC1(handle, stsd->avc1[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: break; sl@0: sl@0: case ATOMTYPE_SQCP: sl@0: { sl@0: if (stsd->sqcp[totalsampleentriesread]) /* SQCP has already been read, more than one is not allowed */ sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: if ((stsd->sqcp[totalsampleentriesread] = (qcelpSampleEntry *)mp4malloc(sizeof(qcelpSampleEntry))) == NULL) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -100; sl@0: } sl@0: sl@0: bytesread = readSQCP(handle, stsd->sqcp[totalsampleentriesread]); sl@0: totalsampleentriesread++; sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: break; sl@0: sl@0: default: /* Other atoms are not needed */ sl@0: // no need to increment totalsampleentriesread as no memory is allocated for unsupported sl@0: // or unrecognized sample types. Alternatively, increment the count of unknown samples. sl@0: // This is for ensure if a non-audio/video track can properly be parsed without being sl@0: // recongized as an invalid format file. sl@0: unknownsampleentriesread++; sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: // if the STSD atom's entry count is NOT the same as the number (supported & unsupported) entries parsed, sl@0: // the atom is likely a corrupted one. sl@0: if ((totalsampleentriesread + unknownsampleentriesread) != stsd->entryCount) sl@0: { sl@0: // for memory cleanup set entrycount to allocated num of entries. sl@0: stsd->entryCount = totalsampleentriesread; sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: // if the STSD atom's entry count is the same as the number of (supported & unsupported) entries sl@0: // parsed, check if some entries are skipped because the max sample entry count has been reached sl@0: if (skipentries) sl@0: { sl@0: // if STSDMAXSAMPLEENTRYCOUNT was reached edit entrycount to make sure cleanup works. sl@0: stsd->entryCount = STSDMAXSAMPLEENTRYCOUNT; sl@0: } sl@0: else if (unknownsampleentriesread > 0) sl@0: { sl@0: // unknown (unsupported) sample entries present, set the STSD entry count to the actual sl@0: // number of supported sample entries detected sl@0: stsd->entryCount = totalsampleentriesread; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTSZ(MP4HandleImp handle, sl@0: * sampleSizeAtom *stsz) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STSZ atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stsz STSZ pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTSZ(MP4HandleImp handle, sampleSizeAtom *stsz) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, stsz->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stsz->atomhdr->type != ATOMTYPE_STSZ) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stsz->sampleSize = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: // zero size samplesize means samples have different sizes, and those sizes are stored in sampleSizeEntries. sl@0: if ((stsz->sampleCount) && (stsz->sampleSize == 0)) sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: // check validity of stsz->sampleCount before allocating entrysize table. sl@0: if ( handle->moov->mvhd ) sl@0: { sl@0: if ( handle->moov->mvhd->timeScale > 0 ) sl@0: { sl@0: TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND; sl@0: TUint maxSampleCount; sl@0: sl@0: if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration sl@0: { sl@0: maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec; sl@0: } sl@0: else // 32bit duration sl@0: { sl@0: maxSampleCount = TUint((TUint( handle->moov->mvhd->duration ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec; sl@0: } sl@0: sl@0: if ( maxSampleCount < stsz->sampleCount ) sl@0: { sl@0: // corrupted sl@0: return -1; sl@0: } sl@0: } sl@0: } sl@0: sl@0: // allocate stsz->entrySize table sl@0: stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32)); sl@0: if (stsz->entrySize == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < stsz->sampleCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stsz->entrySize[i] = u32endian(*((mp4_u32 *)handle->buf)); sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTZ2(MP4HandleImp handle, sl@0: * sampleSizeAtom *stsz) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STZ2 atom. sl@0: * sl@0: * The result is placed in STSZ structure. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stsz STSZ pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTZ2(MP4HandleImp handle, sampleSizeAtom *stsz) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u8 fieldsize; sl@0: sl@0: sl@0: if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, stsz->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stsz->atomhdr->type != ATOMTYPE_STZ2) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 3); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: fieldsize = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: switch (fieldsize) sl@0: { sl@0: case 4: /* Two entries in each byte */ sl@0: sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32)); sl@0: if (stsz->entrySize == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < (stsz->sampleCount + 1) / 2; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: totalbytesread += bytesread; sl@0: sl@0: stsz->entrySize[i * 2] = (mp4_u32)(handle->buf[0] >> 4); sl@0: sl@0: if (stsz->sampleCount % 2 == 0) /* Even number of samples */ sl@0: { sl@0: stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f); sl@0: continue; sl@0: } sl@0: sl@0: /* This condition is needed to avoid writing after the table */ sl@0: sl@0: if (i == (stsz->sampleCount + 1) / 2 - 1) /* Last sample */ sl@0: { sl@0: } sl@0: else sl@0: stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f); sl@0: } sl@0: } sl@0: sl@0: break; sl@0: sl@0: case 8: /* One entry for each byte */ sl@0: sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32)); sl@0: if (stsz->entrySize == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < stsz->sampleCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stsz->entrySize[i] = (mp4_u32)handle->buf[0]; sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: sl@0: break; sl@0: sl@0: case 16: /* Each entry in 2 bytes */ sl@0: sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32)); sl@0: if (stsz->entrySize == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < stsz->sampleCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stsz->entrySize[i] = (mp4_u32)u16endian(*((mp4_u16 *)handle->buf)); sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: sl@0: break; sl@0: sl@0: default: /* Illegal fieldsize */ sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTSC(MP4HandleImp handle, sl@0: * sampleToChunkAtom *stsc) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STSC atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stsc STSC pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTSC(MP4HandleImp handle, sampleToChunkAtom *stsc) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i; sl@0: sl@0: sl@0: if ((stsc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, stsc->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stsc->atomhdr->type != ATOMTYPE_STSC) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stsc->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stsc->entryCount) sl@0: { sl@0: stsc->firstChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32)); sl@0: if (stsc->firstChunk == NULL) sl@0: return -1; sl@0: stsc->samplesPerChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32)); sl@0: if (stsc->samplesPerChunk == NULL) sl@0: return -1; sl@0: stsc->sampleDescriptionIndex = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32)); sl@0: if (stsc->sampleDescriptionIndex == NULL) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: for (i = 0; i < stsc->entryCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 12); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stsc->firstChunk[i] = u32endian(*((mp4_u32 *)handle->buf)); sl@0: stsc->samplesPerChunk[i] = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: stsc->sampleDescriptionIndex[i] = u32endian(*((mp4_u32 *)(handle->buf+8))); sl@0: if ( stsc->sampleDescriptionIndex[i] > stsc->entryCount) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSTCO(MP4HandleImp handle, sl@0: * chunkOffsetAtom *stco) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one STCO atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stco STCO pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSTCO(MP4HandleImp handle, chunkOffsetAtom *stco) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i; sl@0: sl@0: sl@0: if ((stco->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, stco->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stco->atomhdr->type != ATOMTYPE_STCO) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stco->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stco->entryCount) sl@0: { sl@0: // validate stco->entryCount before allocating chunkOffsetTable sl@0: if ( handle->moov->mvhd ) sl@0: { sl@0: if ( handle->moov->mvhd->timeScale > 0 ) sl@0: { sl@0: TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND; sl@0: TUint maxSampleCount; sl@0: sl@0: if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration sl@0: { sl@0: maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec; sl@0: } sl@0: else // 32bit duration sl@0: { sl@0: maxSampleCount = TUint((TUint( handle->moov->mvhd->duration ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec; sl@0: } sl@0: sl@0: if ( maxSampleCount < stco->entryCount ) sl@0: { sl@0: // corrupted sl@0: return -1; sl@0: } sl@0: } sl@0: } sl@0: sl@0: stco->chunkOffset = (mp4_u32 *)mp4malloc(stco->entryCount * sizeof(mp4_u32)); sl@0: if (stco->chunkOffset == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < stco->entryCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stco->chunkOffset[i] = u32endian(*((mp4_u32 *)handle->buf)); sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readCO64(MP4HandleImp handle, sl@0: * chunkOffset64Atom *stco64) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one CO64 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stco64 CO64 pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readCO64(MP4HandleImp handle, chunkOffset64Atom *stco64) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i; sl@0: sl@0: sl@0: if ((stco64->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, stco64->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (stco64->atomhdr->type != ATOMTYPE_CO64) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: stco64->entryCount = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( stco64->entryCount ) sl@0: { sl@0: stco64->chunkOffset = (mp4_u64 *)mp4malloc(stco64->entryCount * sizeof(mp4_u64)); sl@0: if (stco64->chunkOffset == NULL) sl@0: return -1; sl@0: sl@0: for (i = 0; i < stco64->entryCount; i++) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 8); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: stco64->chunkOffset[i] = u64endian(*((mp4_u64 *)(handle->buf))); sl@0: sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMP4V(MP4HandleImp handle, sl@0: * visualSampleEntry *mp4v) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MP4V atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mp4v MP4V pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMP4V(MP4HandleImp handle, visualSampleEntry *mp4v) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((mp4v->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, mp4v->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (mp4v->atomhdr->type != ATOMTYPE_MP4V) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4v->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4v->width = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4v->height = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 50); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ((mp4v->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readESD(handle, mp4v->esd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( totalbytesread < mp4v->atomhdr->size ) sl@0: { sl@0: bytesread = discardData(handle, mp4v->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMP4A(MP4HandleImp handle, sl@0: * audioSampleEntry *mp4a) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MP4A atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mp4a MP4A pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMP4A(MP4HandleImp handle, audioSampleEntry *mp4a) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((mp4a->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, mp4a->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (mp4a->atomhdr->type != ATOMTYPE_MP4A) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4a->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4a->timeScale = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ((mp4a->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readESD(handle, mp4a->esd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( totalbytesread < mp4a->atomhdr->size ) sl@0: { sl@0: bytesread = discardData(handle, mp4a->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMP4S(MP4HandleImp handle, sl@0: * mpegSampleEntry *mp4s) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one MP4S atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mp4s MP4S pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMP4S(MP4HandleImp handle, mpegSampleEntry *mp4s) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((mp4s->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, mp4s->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (mp4s->atomhdr->type != ATOMTYPE_MP4S) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: mp4s->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if ((mp4s->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readESD(handle, mp4s->esd); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( totalbytesread < mp4s->atomhdr->size ) sl@0: { sl@0: bytesread = discardData(handle, mp4s->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readS263(MP4HandleImp handle, sl@0: * h263SampleEntry *s263) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one S263 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * s263 S263 pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readS263(MP4HandleImp handle, h263SampleEntry *s263) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((s263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, s263->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (s263->atomhdr->type != ATOMTYPE_S263) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: s263->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: s263->width = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: s263->height = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 50); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ((s263->d263 = (h263SpecificAtom *)mp4malloc(sizeof(h263SpecificAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readD263(handle, s263->d263); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( totalbytesread < s263->atomhdr->size ) sl@0: { sl@0: bytesread = discardData(handle, s263->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSAMR(MP4HandleImp handle, sl@0: * amrSampleEntry *samr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one SAMR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * samr SAMR pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSAMR(MP4HandleImp handle, amrSampleEntry *samr) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((samr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, samr->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (samr->atomhdr->type != ATOMTYPE_SAMR) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: samr->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: samr->timeScale = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ((samr->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readDAMR(handle, samr->damr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( totalbytesread < samr->atomhdr->size ) sl@0: { sl@0: bytesread = discardData(handle, samr->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSAWB(MP4HandleImp handle, sl@0: * amrSampleEntry *sawb) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one SAWB atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sawb SAWB pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSAWB(MP4HandleImp handle, amrSampleEntry *sawb) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((sawb->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, sawb->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (sawb->atomhdr->type != ATOMTYPE_SAWB) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sawb->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sawb->timeScale = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ((sawb->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readDAMR(handle, sawb->damr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( totalbytesread < sawb->atomhdr->size ) sl@0: { sl@0: bytesread = discardData(handle, sawb->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readESD(MP4HandleImp handle, sl@0: * ESDAtom *esd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one ESD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * esd ESD pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readESD(MP4HandleImp handle, ESDAtom *esd) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_i32 decConfDescrBytesRead = 0; sl@0: sl@0: sl@0: if ((esd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, esd->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (esd->atomhdr->type != ATOMTYPE_ESD) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->esDescrTag = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: if (esd->esDescrTag != 3) /* ES_DescrTag == 3 */ sl@0: return -1; sl@0: sl@0: esd->size = 0; sl@0: do sl@0: { sl@0: mp4_u8 c; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: c = (mp4_u8)(handle->buf[0] & 0x7f); sl@0: esd->size = (esd->size << 7) | c; sl@0: totalbytesread += bytesread; sl@0: } sl@0: while (handle->buf[0] & 0x80); sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->ESID = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->flags = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (esd->flags & 0x80) /* Stream Dependence flag has been set */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->dependsOnESID = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: if (esd->flags & 0x40) /* URL flag has been set */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->URLLength = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, esd->URLLength); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: if (esd->flags & 0x20) /* OCR stream flag has been set */ sl@0: { sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->OCRESID = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->decConfDescrTag = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: if (esd->decConfDescrTag != 4) /* DecoderConfigDescrTag == 4 */ sl@0: return -1; sl@0: sl@0: esd->decConfDescrSize = 0; sl@0: do sl@0: { sl@0: mp4_u8 c; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: c = (mp4_u8)(handle->buf[0] & 0x7f); sl@0: esd->decConfDescrSize = (esd->decConfDescrSize << 7) | c; sl@0: totalbytesread += bytesread; sl@0: } sl@0: while (handle->buf[0] & 0x80); sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->objectTypeIndication = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: decConfDescrBytesRead += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->stream = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: decConfDescrBytesRead += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 3); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->bufferSizeDB = ((mp4_u32)handle->buf[0]) << 16 | sl@0: ((mp4_u32)handle->buf[1]) << 8 | sl@0: ((mp4_u32)handle->buf[2]); sl@0: totalbytesread += bytesread; sl@0: decConfDescrBytesRead += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->maxBitrate = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: decConfDescrBytesRead += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->avgBitrate = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: decConfDescrBytesRead += bytesread; sl@0: sl@0: if ((mp4_u32)decConfDescrBytesRead < esd->decConfDescrSize) sl@0: { sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: esd->decSpecificInfoTag = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: decConfDescrBytesRead += bytesread; sl@0: if (esd->decSpecificInfoTag != 5) /* DecSpecificInfoTag == 5 */ sl@0: { sl@0: bytesread = discardData(handle, esd->decConfDescrSize - decConfDescrBytesRead); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: } sl@0: else sl@0: { sl@0: esd->decSpecificInfoSize = 0; sl@0: do sl@0: { sl@0: mp4_u8 c; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: c = (mp4_u8)(handle->buf[0] & 0x7f); sl@0: esd->decSpecificInfoSize = (esd->decSpecificInfoSize << 7) | c; sl@0: totalbytesread += bytesread; sl@0: } sl@0: while (handle->buf[0] & 0x80); sl@0: sl@0: if(esd->decSpecificInfoSize) sl@0: { sl@0: if ((esd->decSpecificInfo = (mp4_u8 *)mp4malloc(esd->decSpecificInfoSize)) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readData(handle, esd->decSpecificInfo, esd->decSpecificInfoSize); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: } sl@0: } sl@0: } sl@0: sl@0: bytesread = discardData(handle, esd->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readD263(MP4HandleImp handle, sl@0: * h263SpecificAtom *d263) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one D263 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * d263 D263 pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readD263(MP4HandleImp handle, h263SpecificAtom *d263) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((d263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, d263->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (d263->atomhdr->type != ATOMTYPE_D263) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: d263->vendor = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: d263->decoderVersion = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: d263->h263Level = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: d263->h263Profile = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: /* Check for the bitrate atom */ sl@0: sl@0: while ((mp4_u32)totalbytesread < d263->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_BITR: sl@0: sl@0: if (d263->bitr) /* BITR has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((d263->bitr = (bitrateAtom *)mp4malloc(sizeof(bitrateAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readBITR(handle, d263->bitr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: default: /* Other atoms are not needed */ sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readBITR(MP4HandleImp handle, sl@0: * bitrateAtom *d263) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one BITR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * bitr BITR pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readBITR(MP4HandleImp handle, bitrateAtom *bitr) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((bitr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, bitr->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (bitr->atomhdr->type != ATOMTYPE_BITR) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: bitr->avgBitrate = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: bitr->maxBitrate = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readDAMR(MP4HandleImp handle, sl@0: * amrDecSpecStruc *damr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one DAMR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * damr DAMR pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readDAMR(MP4HandleImp handle, amrDecSpecStruc *damr) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((damr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, damr->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (damr->atomhdr->type != ATOMTYPE_DAMR) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: damr->vendor = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: damr->decoderVersion = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: damr->modeSet = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: damr->modeChangePeriod = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: damr->framesPerSample = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeFTYP(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for FTYP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * ftyp FTYP atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeFTYP(fileTypeAtom *ftyp) sl@0: { sl@0: if (ftyp) sl@0: { sl@0: if (freeAtomHeader(ftyp->atomhdr) < 0) sl@0: return -1; sl@0: if (ftyp->compatibleBrands) sl@0: mp4free(ftyp->compatibleBrands); sl@0: sl@0: mp4free(ftyp); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMOOV(movieAtom *moov) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MOOV atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * moov MOOV atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMOOV(movieAtom *moov) sl@0: { sl@0: if (moov) sl@0: { sl@0: if (freeAtomHeader(moov->atomhdr) < 0) sl@0: return -1; sl@0: if (freeMVHD(moov->mvhd) < 0) sl@0: return -1; sl@0: if (freeTRAK(moov->trakAudio) < 0) sl@0: return -1; sl@0: if (freeTRAK(moov->trakVideo) < 0) sl@0: return -1; sl@0: if (freeIODS(moov->iods) < 0) sl@0: return -1; sl@0: if (freeUDTA(moov->udta) < 0) sl@0: return -1; sl@0: if (freeMETA(moov->meta) < 0) sl@0: return -1; sl@0: sl@0: mp4free(moov); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeAtomHeader(atomHeader *atomhdr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for atom header. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * atomhdr atom header pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeAtomHeader(atomHeader *atomhdr) sl@0: { sl@0: if (atomhdr) sl@0: mp4free(atomhdr); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMVHD(movieHeaderAtom *mvhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MVHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * mvhd MVHD atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMVHD(movieHeaderAtom *mvhd) sl@0: { sl@0: if (mvhd) sl@0: { sl@0: if (freeAtomHeader(mvhd->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(mvhd); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeTRAK(trackAtom *trak) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for TRAK atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * trak TRAK atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeTRAK(trackAtom *trak) sl@0: { sl@0: if (trak) sl@0: { sl@0: if (freeAtomHeader(trak->atomhdr) < 0) sl@0: return -1; sl@0: if (freeTKHD(trak->tkhd) < 0) sl@0: return -1; sl@0: if (freeTREF(trak->tref) < 0) sl@0: return -1; sl@0: if (freeEDTS(trak->edts) < 0) sl@0: return -1; sl@0: if (freeMDIA(trak->mdia) < 0) sl@0: return -1; sl@0: if (freeUDTA(trak->udta) < 0) sl@0: return -1; sl@0: sl@0: mp4free(trak); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeTKHD(trackHeaderAtom *tkhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for TKHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * tkhd TKHD atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeTKHD(trackHeaderAtom *tkhd) sl@0: { sl@0: if (tkhd) sl@0: { sl@0: if (freeAtomHeader(tkhd->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(tkhd); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeTREF(trackReferenceAtom *tref) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for TREF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * tref TREF atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeTREF(trackReferenceAtom *tref) sl@0: { sl@0: if (tref) sl@0: { sl@0: if (freeAtomHeader(tref->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(tref); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeEDTS(editListContainerAtom *edts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for EDTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * edts EDTS atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeEDTS(editListContainerAtom *edts) sl@0: { sl@0: if (edts) sl@0: { sl@0: if (freeAtomHeader(edts->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(edts); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMDIA(mediaAtom *mdia) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MDIA atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * mdia MDIA atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMDIA(mediaAtom *mdia) sl@0: { sl@0: if (mdia) sl@0: { sl@0: if (freeAtomHeader(mdia->atomhdr) < 0) sl@0: return -1; sl@0: if (freeMDHD(mdia->mdhd) < 0) sl@0: return -1; sl@0: if (freeHDLR(mdia->hdlr) < 0) sl@0: return -1; sl@0: if (freeMINF(mdia->minf) < 0) sl@0: return -1; sl@0: sl@0: mp4free(mdia); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMDHD(mediaHeaderAtom *mdhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MDHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * mdhd MDHD atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMDHD(mediaHeaderAtom *mdhd) sl@0: { sl@0: if (mdhd) sl@0: { sl@0: if (freeAtomHeader(mdhd->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(mdhd); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeHDLR(handlerAtom *hdlr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for HDLR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * hdlr HDLR atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeHDLR(handlerAtom *hdlr) sl@0: { sl@0: if (hdlr) sl@0: { sl@0: if (freeAtomHeader(hdlr->atomhdr) < 0) sl@0: return -1; sl@0: if (hdlr->name) sl@0: mp4free(hdlr->name); sl@0: sl@0: mp4free(hdlr); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMINF(mediaInformationAtom *minf) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MINF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * minf MINF atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMINF(mediaInformationAtom *minf) sl@0: { sl@0: if (minf) sl@0: { sl@0: if (freeAtomHeader(minf->atomhdr) < 0) sl@0: return -1; sl@0: if (freeVMHD(minf->vmhd) < 0) sl@0: return -1; sl@0: if (freeSMHD(minf->smhd) < 0) sl@0: return -1; sl@0: if (freeDINF(minf->dinf) < 0) sl@0: return -1; sl@0: if (freeSTBL(minf->stbl) < 0) sl@0: return -1; sl@0: sl@0: mp4free(minf); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for VMHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * vmhd VMHD atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd) sl@0: { sl@0: if (vmhd) sl@0: { sl@0: if (freeAtomHeader(vmhd->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(vmhd); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for SMHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * smhd SMHD atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd) sl@0: { sl@0: if (smhd) sl@0: { sl@0: if (freeAtomHeader(smhd->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(smhd); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeDINF(dataInformationAtom *dinf) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for DINF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * dinf DINF atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeDINF(dataInformationAtom *dinf) sl@0: { sl@0: if (dinf) sl@0: { sl@0: if (freeAtomHeader(dinf->atomhdr) < 0) sl@0: return -1; sl@0: if (freeDREF(dinf->dref) < 0) sl@0: return -1; sl@0: sl@0: mp4free(dinf); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeDREF(dataReferenceAtom *dref) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for DREF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * dref DREF atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeDREF(dataReferenceAtom *dref) sl@0: { sl@0: if (dref) sl@0: { sl@0: if (freeAtomHeader(dref->atomhdr) < 0) sl@0: return -1; sl@0: if (freeURL(dref->url) < 0) sl@0: return -1; sl@0: if (freeURN(dref->urn) < 0) sl@0: return -1; sl@0: sl@0: mp4free(dref); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeURL(dataEntryURLAtom *url) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for URL atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * url URL atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeURL(dataEntryURLAtom *url) sl@0: { sl@0: if (url) sl@0: { sl@0: if (freeAtomHeader(url->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(url); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeURN(dataEntryURNAtom *urn) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for URN atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * urn URN atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeURN(dataEntryURNAtom *urn) sl@0: { sl@0: if (urn) sl@0: { sl@0: if (freeAtomHeader(urn->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(urn); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTBL(sampleTableAtom *stbl) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STBL atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stbl STBL atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTBL(sampleTableAtom *stbl) sl@0: { sl@0: if (stbl) sl@0: { sl@0: if (freeAtomHeader(stbl->atomhdr) < 0) sl@0: return -1; sl@0: if (freeSTTS(stbl->stts) < 0) sl@0: return -1; sl@0: if (freeCTTS(stbl->ctts) < 0) sl@0: return -1; sl@0: if (freeSTSD(stbl->stsd) < 0) sl@0: return -1; sl@0: if (freeSTSZ(stbl->stsz) < 0) sl@0: return -1; sl@0: if (freeSTSC(stbl->stsc) < 0) sl@0: return -1; sl@0: if (stbl->is32BitOffsets) sl@0: { sl@0: sl@0: if (freeSTCO(stbl->stco) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: sl@0: if (freeSTCO64(stbl->stco64) < 0) sl@0: return -1; sl@0: } sl@0: if (freeSTSS(stbl->stss) < 0) sl@0: return -1; sl@0: if (freeSTSH(stbl->stsh) < 0) sl@0: return -1; sl@0: if (freeSDTP(stbl->sdtp) < 0) sl@0: return -1; sl@0: sl@0: mp4free(stbl); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTTS(timeToSampleAtom *stts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stts STTS atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTTS(timeToSampleAtom *stts) sl@0: { sl@0: if (stts) sl@0: { sl@0: if (freeAtomHeader(stts->atomhdr) < 0) sl@0: return -1; sl@0: if (stts->sampleCount) sl@0: mp4free(stts->sampleCount); sl@0: if (stts->sampleDelta) sl@0: mp4free(stts->sampleDelta); sl@0: sl@0: mp4free(stts); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for CTTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * ctts CTTS atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts) sl@0: { sl@0: if (ctts) sl@0: { sl@0: if (freeAtomHeader(ctts->atomhdr) < 0) sl@0: return -1; sl@0: if (ctts->sampleCount) sl@0: mp4free(ctts->sampleCount); sl@0: if (ctts->sampleOffset) sl@0: mp4free(ctts->sampleOffset); sl@0: sl@0: mp4free(ctts); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTSD(sampleDescriptionAtom *stsd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STSD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stsd STSD atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTSD(sampleDescriptionAtom *stsd) sl@0: { sl@0: mp4_u32 sampleentrycount = 0; sl@0: mp4_u32 entryindex; sl@0: sl@0: if (stsd) sl@0: { sl@0: sampleentrycount = stsd->entryCount; sl@0: sl@0: if (freeAtomHeader(stsd->atomhdr) < 0) sl@0: return -1; sl@0: for (entryindex = 0; entryindex < sampleentrycount; entryindex++) sl@0: { sl@0: if (freeMP4V(stsd->mp4v[entryindex]) < 0) sl@0: return -1; sl@0: if (freeMP4A(stsd->mp4a[entryindex]) < 0) sl@0: return -1; sl@0: if (freeMP4S(stsd->mp4s[entryindex]) < 0) sl@0: return -1; sl@0: if (freeS263(stsd->s263[entryindex]) < 0) sl@0: return -1; sl@0: if (freeSAMR(stsd->samr[entryindex]) < 0) sl@0: return -1; sl@0: if (freeSAWB(stsd->sawb[entryindex]) < 0) sl@0: return -1; sl@0: if (freeAVC1(stsd->avc1[entryindex]) < 0) sl@0: return -1; sl@0: if (freeSQCP(stsd->sqcp[entryindex]) < 0) sl@0: return -1; sl@0: } sl@0: mp4free(stsd); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMP4V(visualSampleEntry *mp4v) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MP4V atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * mp4v MP4V atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMP4V(visualSampleEntry *mp4v) sl@0: { sl@0: if (mp4v) sl@0: { sl@0: if (freeAtomHeader(mp4v->atomhdr) < 0) sl@0: return -1; sl@0: if (freeESD(mp4v->esd) < 0) sl@0: return -1; sl@0: sl@0: mp4free(mp4v); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeESD(ESDAtom *esd) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for ESD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * esd ESD atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeESD(ESDAtom *esd) sl@0: { sl@0: if (esd) sl@0: { sl@0: if (freeAtomHeader(esd->atomhdr) < 0) sl@0: return -1; sl@0: if (esd->URLString) sl@0: mp4free(esd->URLString); sl@0: if (esd->decSpecificInfo) sl@0: mp4free(esd->decSpecificInfo); sl@0: sl@0: mp4free(esd); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMP4A(audioSampleEntry *mp4a) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MP4A atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * mp4a MP4A atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMP4A(audioSampleEntry *mp4a) sl@0: { sl@0: if (mp4a) sl@0: { sl@0: if (freeAtomHeader(mp4a->atomhdr) < 0) sl@0: return -1; sl@0: if (freeESD(mp4a->esd) < 0) sl@0: return -1; sl@0: sl@0: mp4free(mp4a); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMP4S(mpegSampleEntry *mp4s) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for MP4S atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * mp4s MP4S atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMP4S(mpegSampleEntry *mp4s) sl@0: { sl@0: if (mp4s) sl@0: { sl@0: if (freeAtomHeader(mp4s->atomhdr) < 0) sl@0: return -1; sl@0: if (freeESD(mp4s->esd) < 0) sl@0: return -1; sl@0: sl@0: mp4free(mp4s); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeS263(h263SampleEntry *s263) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for S263 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * s263 S263 atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeS263(h263SampleEntry *s263) sl@0: { sl@0: if (s263) sl@0: { sl@0: if (freeAtomHeader(s263->atomhdr) < 0) sl@0: return -1; sl@0: if (freeD263(s263->d263) < 0) sl@0: return -1; sl@0: sl@0: mp4free(s263); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeD263(h263SpecificAtom *d263) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for D263 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * d263 D263 atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeD263(h263SpecificAtom *d263) sl@0: { sl@0: if (d263) sl@0: { sl@0: if (freeAtomHeader(d263->atomhdr) < 0) sl@0: return -1; sl@0: if (freeBITR(d263->bitr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(d263); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeBITR(BitrateAtom *bitr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for BITR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * bitr BITR atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeBITR(bitrateAtom *bitr) sl@0: { sl@0: if (bitr) sl@0: { sl@0: if (freeAtomHeader(bitr->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(bitr); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSAMR(amrSampleEntry *samr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for SAMR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * samr SAMR atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSAMR(amrSampleEntry *samr) sl@0: { sl@0: if (samr) sl@0: { sl@0: if (freeAtomHeader(samr->atomhdr) < 0) sl@0: return -1; sl@0: if (freeDAMR(samr->damr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(samr); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSAWB(amrSampleEntry *sawb) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for SAWB atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * sawb SAWB atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSAWB(amrSampleEntry *sawb) sl@0: { sl@0: if (sawb) sl@0: { sl@0: if (freeAtomHeader(sawb->atomhdr) < 0) sl@0: return -1; sl@0: if (freeDAMR(sawb->damr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(sawb); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeDAMR(amrDecSpecStruc *damr) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for DAMR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * damr DAMR atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeDAMR(amrDecSpecStruc *damr) sl@0: { sl@0: if (damr) sl@0: { sl@0: if (freeAtomHeader(damr->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(damr); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTSZ(sampleSizeAtom *stsz) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STSZ atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stsz STSZ atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTSZ(sampleSizeAtom *stsz) sl@0: { sl@0: if (stsz) sl@0: { sl@0: if (freeAtomHeader(stsz->atomhdr) < 0) sl@0: return -1; sl@0: if (stsz->entrySize) sl@0: mp4free(stsz->entrySize); sl@0: sl@0: mp4free(stsz); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTSC(sampleToChunkAtom *stsc) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STSC atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stsc STSC atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTSC(sampleToChunkAtom *stsc) sl@0: { sl@0: if (stsc) sl@0: { sl@0: if (freeAtomHeader(stsc->atomhdr) < 0) sl@0: return -1; sl@0: if (stsc->firstChunk) sl@0: mp4free(stsc->firstChunk); sl@0: if (stsc->samplesPerChunk) sl@0: mp4free(stsc->samplesPerChunk); sl@0: if (stsc->sampleDescriptionIndex) sl@0: mp4free(stsc->sampleDescriptionIndex); sl@0: sl@0: mp4free(stsc); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTCO(chunkOffsetAtom *stco) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STCO atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stco STCO atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTCO(chunkOffsetAtom *stco) sl@0: { sl@0: if (stco) sl@0: { sl@0: if (freeAtomHeader(stco->atomhdr) < 0) sl@0: return -1; sl@0: if (stco->chunkOffset) sl@0: mp4free(stco->chunkOffset); sl@0: sl@0: mp4free(stco); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTCO64(chunkOffset64Atom *stco64) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STCO64 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stco64 STCO64 atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTCO64(chunkOffset64Atom *stco64) sl@0: { sl@0: if (stco64) sl@0: { sl@0: if (freeAtomHeader(stco64->atomhdr) < 0) sl@0: return -1; sl@0: if (stco64->chunkOffset) sl@0: mp4free(stco64->chunkOffset); sl@0: sl@0: mp4free(stco64); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTSS(syncSampleAtom *stss) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STSS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stss STSS atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTSS(syncSampleAtom *stss) sl@0: { sl@0: if (stss) sl@0: { sl@0: if (freeAtomHeader(stss->atomhdr) < 0) sl@0: return -1; sl@0: if (stss->sampleNumber) sl@0: mp4free(stss->sampleNumber); sl@0: sl@0: mp4free(stss); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for STSH atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * stsh STSH atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh) sl@0: { sl@0: if (stsh) sl@0: { sl@0: if (freeAtomHeader(stsh->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(stsh); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSDTP(sampleDependencyAtom *sdtp) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for SDTP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * sdtp SDTP atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSDTP(sampleDependencyAtom *sdtp) sl@0: { sl@0: if (sdtp) sl@0: { sl@0: if (freeAtomHeader(sdtp->atomhdr) < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (sdtp->dep) sl@0: { sl@0: mp4free(sdtp->dep); sl@0: } sl@0: sl@0: mp4free(sdtp); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeIODS(objectDescriptorAtom *iods) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for IODS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * iods IODS atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeIODS(objectDescriptorAtom *iods) sl@0: { sl@0: if (iods) sl@0: { sl@0: if (freeAtomHeader(iods->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(iods); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readUDTA(MP4HandleImp handle, sl@0: * userDataAtom *udta) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one UDTA atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * udta UDTA pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readUDTA(MP4HandleImp handle, userDataAtom *udta) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: if ((udta->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, udta->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (udta->atomhdr->type != ATOMTYPE_UDTA) sl@0: return -1; sl@0: sl@0: if ( handle->file ) sl@0: { sl@0: udta->atomcontentloc = handle->diskReadBufStart + handle->diskReadBufPos; sl@0: } sl@0: else sl@0: { sl@0: udta->atomcontentloc = handle->absPosition; sl@0: } sl@0: sl@0: if ( udta->atomhdr->size == 1 ) sl@0: { sl@0: udta->atomcontentsize = I64INT(udta->atomhdr->largeSize) - (TInt)totalbytesread; sl@0: } sl@0: else sl@0: { sl@0: udta->atomcontentsize = (TInt)(udta->atomhdr->size - totalbytesread); sl@0: } sl@0: sl@0: if ( handle->file ) sl@0: { sl@0: if ( seekFile(handle, udta->atomhdr->size - totalbytesread) < 0 ) sl@0: { sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: return udta->atomhdr->size; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: bytesread = discardData(handle, udta->atomhdr->size - totalbytesread); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: } sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeUDTA(userDataAtom *udta) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for UDTA atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * udta UDTA atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeUDTA(userDataAtom *udta) sl@0: { sl@0: if (udta) sl@0: { sl@0: if (freeAtomHeader(udta->atomhdr) < 0) sl@0: return -1; sl@0: mp4free(udta); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineVideoLength(MP4HandleImp handle, sl@0: * mp4_u32 *videolength) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the length of video in milliseconds. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * videolength Video length is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineVideoLength(MP4HandleImp handle, mp4_u32 *videolength) sl@0: { sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if (!handle->moov->mvhd) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->tkhd) sl@0: return -1; sl@0: sl@0: /* Is timescale set? */ sl@0: if (handle->moov->mvhd->timeScale == 0) sl@0: return -1; sl@0: sl@0: *videolength = (mp4_u32)(((mp4_double)handle->moov->trakVideo->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineFrameRate(MP4HandleImp handle, sl@0: * mp4_double *framerate) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the frame rate of video. sl@0: * sl@0: * Frame rate is calculated as the average frame rate of the entire video. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * framerate Frame rate is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineFrameRate(MP4HandleImp handle, mp4_double *framerate) sl@0: { sl@0: mp4_double numberofframes; sl@0: mp4_double length; sl@0: sl@0: sl@0: if (!handle) sl@0: return -1; sl@0: if (!handle->moov) sl@0: return -1; sl@0: if (!handle->moov->trakVideo) sl@0: return -1; sl@0: if (!handle->moov->trakVideo->mdia) sl@0: return -1; sl@0: if (!handle->moov->trakVideo->mdia->minf) sl@0: return -1; sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl) sl@0: return -1; sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsz) sl@0: return -1; sl@0: if (!handle->moov->trakVideo->mdia->mdhd) sl@0: return -1; sl@0: sl@0: sl@0: if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakVideo->mdia->mdhd->duration == 0) sl@0: { sl@0: *framerate = 0; sl@0: } sl@0: else sl@0: { sl@0: numberofframes = (mp4_double)handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount; sl@0: length = (mp4_double)handle->moov->trakVideo->mdia->mdhd->duration / sl@0: (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale; sl@0: sl@0: *framerate = numberofframes / length; sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineVideoType(MP4HandleImp handle, sl@0: * mp4_u32 *videotype) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the video type of the MP4. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * videotype Video type is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * -2 Unknown video type sl@0: * sl@0: */ sl@0: mp4_i32 determineVideoType(MP4HandleImp handle, mp4_u32 *videotype) sl@0: { sl@0: *videotype = MP4_TYPE_NONE; sl@0: sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0) sl@0: return -1; sl@0: sl@0: /* Assume that the video type is the same for all sample entries. Just get the video type from the first one */ sl@0: sl@0: if (handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]) sl@0: { sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd) sl@0: return -1; sl@0: sl@0: if ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->objectTypeIndication == 0x20) && sl@0: ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->stream >> 2) == 0x04)) sl@0: *videotype = MP4_TYPE_MPEG4_VIDEO; sl@0: } sl@0: else sl@0: if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]) sl@0: { sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263) sl@0: return -1; sl@0: sl@0: switch (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Profile) sl@0: { sl@0: case 0: sl@0: *videotype = MP4_TYPE_H263_PROFILE_0; sl@0: break; sl@0: case 3: sl@0: *videotype = MP4_TYPE_H263_PROFILE_3; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: else sl@0: if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]) sl@0: { sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize == 0) sl@0: return -1; sl@0: sl@0: /* AVC profile is in the second byte of the avcconfigrecord */ sl@0: switch((mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[1]) sl@0: { sl@0: case 66: sl@0: *videotype = MP4_TYPE_AVC_PROFILE_BASELINE; sl@0: break; sl@0: case 77: sl@0: *videotype = MP4_TYPE_AVC_PROFILE_MAIN; sl@0: break; sl@0: case 88: sl@0: *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED; sl@0: break; sl@0: case 100: sl@0: *videotype = MP4_TYPE_AVC_PROFILE_HIGH; sl@0: break; sl@0: default: sl@0: { sl@0: mp4_u8 constraintByte = (mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[2]; sl@0: if ( (constraintByte & 0x80) || (constraintByte & 0x10) ) sl@0: { sl@0: *videotype = MP4_TYPE_AVC_PROFILE_BASELINE; sl@0: } sl@0: else if (constraintByte & 0x40) sl@0: { sl@0: *videotype = MP4_TYPE_AVC_PROFILE_MAIN; sl@0: } sl@0: else if (constraintByte & 0x20) sl@0: { sl@0: *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED; sl@0: } sl@0: // NOTE: Cannot reliably determine higher profiles from sl@0: // the constraint flags. sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: else sl@0: {} sl@0: /* Note: Read the AVC level and recreate the actual AVC profile and level in the future! */ sl@0: if (*videotype == MP4_TYPE_NONE) sl@0: return -2; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineVideoResolution(MP4HandleImp handle, sl@0: * mp4_u32 *videowidth, sl@0: * mp4_u32 *videoheight) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function finds out the video width and height from the atom sl@0: * structure. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * videowidth Video width is returned here sl@0: * videoheight Video height is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineVideoResolution(MP4HandleImp handle, mp4_u32 *videowidth, mp4_u32 *videoheight) sl@0: { sl@0: mp4_u32 videotype = MP4_TYPE_NONE; sl@0: sl@0: sl@0: if (determineVideoType(handle, &videotype) < 0) sl@0: return -1; sl@0: sl@0: if (videotype == MP4_TYPE_NONE) sl@0: return -1; sl@0: sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0) sl@0: return -1; sl@0: sl@0: /* Assume that the video characteristics for all the video sample entries are the same. Just get them from the first one */ sl@0: sl@0: if (videotype == MP4_TYPE_H263_PROFILE_0 || sl@0: videotype == MP4_TYPE_H263_PROFILE_3) sl@0: { sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]) sl@0: return -1; sl@0: sl@0: *videowidth = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->width; sl@0: *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->height; sl@0: } sl@0: else if (videotype == MP4_TYPE_MPEG4_VIDEO) sl@0: { sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]) sl@0: return -1; sl@0: sl@0: *videowidth = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->width; sl@0: *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->height; sl@0: } sl@0: else if ( isAvcVideo(videotype) ) sl@0: { sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]) sl@0: return -1; sl@0: sl@0: *videowidth = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->width; sl@0: *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->height; sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineVideoTimeScale(MP4HandleImp handle, sl@0: * mp4_u32 *timescale) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the timescale of video track. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * timescale Timescale of video track is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineVideoTimeScale(MP4HandleImp handle, mp4_u32 *timescale) sl@0: { sl@0: if (timescale == NULL) sl@0: return 0; sl@0: sl@0: if (!handle) sl@0: return -1; sl@0: if (!handle->moov) sl@0: return -1; sl@0: if (!handle->moov->trakVideo) sl@0: return -1; sl@0: if (!handle->moov->trakVideo->mdia) sl@0: return -1; sl@0: if (!handle->moov->trakVideo->mdia->mdhd) sl@0: return -1; sl@0: if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0) sl@0: return -1; sl@0: sl@0: *timescale = handle->moov->trakVideo->mdia->mdhd->timeScale; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineAudioLength(MP4HandleImp handle, sl@0: * mp4_u32 *audiolength) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the length of audio in milliseconds. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * audiolength Audio length is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineAudioLength(MP4HandleImp handle, mp4_u32 *audiolength) sl@0: { sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if (!handle->moov->mvhd) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->tkhd) sl@0: return -1; sl@0: sl@0: /* Is timescale set? */ sl@0: if (handle->moov->mvhd->timeScale == 0) sl@0: return -1; sl@0: sl@0: *audiolength = (mp4_u32)(((mp4_double)handle->moov->trakAudio->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineAudioType(MP4HandleImp handle, sl@0: * mp4_u32 *audiotype) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the audio type of the MP4. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * audiotype Audio type is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * -2 Unknown audiotrack sl@0: * sl@0: */ sl@0: mp4_i32 determineAudioType(MP4HandleImp handle, mp4_u32 *audiotype) sl@0: { sl@0: *audiotype = MP4_TYPE_NONE; sl@0: sl@0: sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount == 0) sl@0: return -1; sl@0: sl@0: /* Assume that the audio type is the same for all sample entries. Just get the audio type from the first one */ sl@0: if (handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]) sl@0: { sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd) sl@0: return -1; sl@0: sl@0: if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0x40) && sl@0: ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05)) sl@0: *audiotype = MP4_TYPE_MPEG4_AUDIO; sl@0: sl@0: if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0xE1) && sl@0: ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05)) sl@0: { sl@0: *audiotype = MP4_TYPE_QCELP_13K; sl@0: handle->qcelpStoredAsMPEGAudio = MP4TRUE; sl@0: } sl@0: } sl@0: else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[0]) sl@0: *audiotype = MP4_TYPE_AMR_NB; sl@0: else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[0]) sl@0: *audiotype = MP4_TYPE_AMR_WB; sl@0: else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[0]) sl@0: { sl@0: *audiotype = MP4_TYPE_QCELP_13K; sl@0: handle->qcelpStoredAsMPEGAudio = MP4FALSE; sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: if (*audiotype == MP4_TYPE_NONE) sl@0: return -2; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle, sl@0: * mp4_u8 *framespersample) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the number of audio frames in each sample. sl@0: * The function works with AMR audio type only. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * framespersample Number of frames in each sample sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle, mp4_u8 *framespersample) sl@0: { sl@0: mp4_i8 sampleentryindex; sl@0: sl@0: *framespersample = 0; sl@0: sl@0: sl@0: if (!((handle->type & MP4_TYPE_AMR_NB) || sl@0: (handle->type & MP4_TYPE_AMR_WB) || sl@0: ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)))) sl@0: { sl@0: *framespersample = 1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd) sl@0: return -1; sl@0: sl@0: if (handle->type & MP4_TYPE_AMR_NB) sl@0: { sl@0: /* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/ sl@0: for (sampleentryindex = 0; (mp4_u8) sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++) sl@0: { sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr) sl@0: return -1; sl@0: sl@0: if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample) sl@0: *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample; sl@0: } sl@0: } sl@0: else if (handle->type & MP4_TYPE_AMR_WB) sl@0: { sl@0: /* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/ sl@0: for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++) sl@0: { sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr) sl@0: return -1; sl@0: sl@0: if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample) sl@0: *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample; sl@0: } sl@0: } sl@0: else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)) sl@0: { sl@0: /* Now, framespersample returns the maximum frames_per_sample listed in the QCELP-13K sample entries*/ sl@0: for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++) sl@0: { sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp) sl@0: return -1; sl@0: sl@0: if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample) sl@0: *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineAudioTimeScale(MP4HandleImp handle, sl@0: * mp4_u32 *timescale) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the timescale of audio track. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * timescale Timescale of audio track is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineAudioTimeScale(MP4HandleImp handle, mp4_u32 *timescale) sl@0: { sl@0: if (timescale == NULL) sl@0: return 0; sl@0: sl@0: if (!handle) sl@0: return -1; sl@0: if (!handle->moov) sl@0: return -1; sl@0: if (!handle->moov->trakAudio) sl@0: return -1; sl@0: if (!handle->moov->trakAudio->mdia) sl@0: return -1; sl@0: if (!handle->moov->trakAudio->mdia->mdhd) sl@0: return -1; sl@0: sl@0: sl@0: if (handle->moov->trakAudio->mdia->mdhd->timeScale == 0) sl@0: return -1; sl@0: sl@0: *timescale = handle->moov->trakAudio->mdia->mdhd->timeScale; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle, sl@0: * mp4_u32 *averagebitrate) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the average bitrate of the audio in bits per sl@0: * second. sl@0: * sl@0: * The average is calculated so that the audio data length is divided by sl@0: * the length of the audio track. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * averagebitrate Result is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle, mp4_u32 *averagebitrate) sl@0: { sl@0: mp4_u32 audiosize = 0; sl@0: sl@0: if (!handle->moov) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (handle->moov->trakAudio) sl@0: { sl@0: if (!handle->moov->trakAudio->mdia) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsz) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0) sl@0: { sl@0: audiosize += (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount * sl@0: handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize); sl@0: } sl@0: else sl@0: { sl@0: mp4_u32 i; sl@0: for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++) sl@0: { sl@0: audiosize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i]; sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (!handle->moov->trakAudio->mdia->mdhd) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (!handle->moov->trakAudio->mdia->mdhd->timeScale) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (handle->moov->trakAudio->mdia->mdhd->duration == 0) sl@0: { sl@0: *averagebitrate = 0; sl@0: } sl@0: else sl@0: { sl@0: *averagebitrate = (mp4_u32)((mp4_double)8 * sl@0: (mp4_double)audiosize / sl@0: ((mp4_double)handle->moov->trakAudio->mdia->mdhd->duration / sl@0: (mp4_double)handle->moov->trakAudio->mdia->mdhd->timeScale)); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineStreamSize(MP4HandleImp handle, sl@0: * mp4_u32 *streamsize) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the size of media data in MP4 file/stream. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * streamsize Size of data sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineStreamSize(MP4HandleImp handle, mp4_u32 *streamsize) sl@0: { sl@0: *streamsize = 0; sl@0: sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if ((!handle->moov->trakAudio) && (!handle->moov->trakVideo)) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakAudio) sl@0: { sl@0: if (!handle->moov->trakAudio->mdia) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakAudio->mdia->minf->stbl->stsz) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0) sl@0: *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount * sl@0: handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize; sl@0: else sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++) sl@0: *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i]; sl@0: } sl@0: } sl@0: sl@0: if (handle->moov->trakVideo) sl@0: { sl@0: if (!handle->moov->trakVideo->mdia) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!handle->moov->trakVideo->mdia->minf->stbl->stsz) sl@0: return -1; sl@0: sl@0: if (handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize != 0) sl@0: *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount * sl@0: handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize; sl@0: else sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: for (i = 0; i < handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount; i++) sl@0: *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[i]; sl@0: } sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle, sl@0: * mp4_u32 *streamaveragebitrate, sl@0: * mp4_u32 streamsize) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines the average bitrate of the stream in bits per sl@0: * second. sl@0: * sl@0: * The average is calculated so that the media data length is divided by sl@0: * the length of the presentation. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * streamaveragebitrate Result is returned here sl@0: * streamsize Size of media data in bytes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle, mp4_u32 *streamaveragebitrate, mp4_u32 streamsize) sl@0: { sl@0: if (!handle->moov) sl@0: return -1; sl@0: sl@0: if (!handle->moov->mvhd) sl@0: return -1; sl@0: sl@0: if (!handle->moov->mvhd->timeScale) sl@0: return -1; sl@0: sl@0: if (handle->moov->mvhd->atomhdr->version == 1) /* 64 bit */ sl@0: { sl@0: if (!handle->moov->mvhd->duration64) sl@0: return -1; sl@0: sl@0: *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize / sl@0: ((mp4_double)handle->moov->mvhd->duration64 / handle->moov->mvhd->timeScale)); sl@0: } sl@0: else /* 32 bit */ sl@0: { sl@0: if (!handle->moov->mvhd->duration) sl@0: return -1; sl@0: sl@0: *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize / sl@0: ((mp4_double)handle->moov->mvhd->duration / handle->moov->mvhd->timeScale)); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 advanceVideoFrame(MP4HandleImp handle, sl@0: * trackAtom *trak) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function Advances one video frame and finds the frame offset sl@0: * and size. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 advanceVideoFrame(MP4HandleImp handle, trackAtom *trak) sl@0: { sl@0: if (!trak->mdia) sl@0: return -1; sl@0: if (!trak->mdia->minf) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl->stsz) sl@0: return -1; sl@0: sl@0: /* Are there frames (samples) left? */ sl@0: sl@0: if (trak->mdia->minf->stbl->stsz->sampleCount > handle->videoSampleNum) sl@0: handle->videoSampleNum++; sl@0: else sl@0: return -2; sl@0: sl@0: /* Find the size of the frame (sample) */ sl@0: sl@0: if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0) sl@0: return -1; sl@0: sl@0: /* Find the offset of the frame (sample) */ sl@0: sl@0: if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0) sl@0: return -1; sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle, sl@0: * sampleTableAtom *stbl) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function finds the offset of the current video sample. sl@0: * The result is stored in handle->videoFrameOffset. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stbl STBL atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl) sl@0: { sl@0: mp4_u32 chunk; /* Current chunk number */ sl@0: mp4_u32 sample; /* Number of samples before this run of chunks */ sl@0: mp4_u32 entry; /* Current entry in sample to chunk */ sl@0: mp4_u32 chunksInThisRun; /* Number of chunks in this run */ sl@0: mp4_u32 sampleNrInChunk = 0; /* Sample number in the chunk */ sl@0: sl@0: if (!stbl->stsc || stbl->stsc->entryCount == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (!stbl->stco || stbl->stco->entryCount == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: chunk = 0; sl@0: sample = 0; sl@0: entry = 0; sl@0: sl@0: for (;;) sl@0: { sl@0: /* Find how many chunks there are in this run */ sl@0: sl@0: if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */ sl@0: { sl@0: chunksInThisRun = stbl->stsc->firstChunk[entry + 1] - stbl->stsc->firstChunk[entry]; sl@0: } sl@0: else sl@0: { sl@0: chunksInThisRun = stbl->stco->entryCount - chunk + 1; sl@0: } sl@0: sl@0: if (handle->videoSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample) sl@0: { sl@0: chunk += (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry]; sl@0: sampleNrInChunk = (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry]; sl@0: sl@0: /* The following functions are needed for multiple sample entry support */ sl@0: handle->videoSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry]; sl@0: sl@0: break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/ sl@0: } sl@0: else sl@0: { sl@0: chunk += chunksInThisRun; sl@0: sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry]; sl@0: } sl@0: sl@0: entry++; sl@0: } sl@0: sl@0: if (chunk > stbl->stco->entryCount) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: handle->videoFrameOffset = getChunkOffset(stbl, chunk - 1); sl@0: sl@0: if (sampleNrInChunk) sl@0: { sl@0: if (stbl->stsz->sampleSize) sl@0: { sl@0: handle->videoFrameOffset += stbl->stsz->sampleSize * sampleNrInChunk; sl@0: } sl@0: else sl@0: { sl@0: if (stbl->stsz->sampleCount == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: while (sampleNrInChunk) sl@0: { sl@0: handle->videoFrameOffset += stbl->stsz->entrySize[handle->videoSampleNum - sampleNrInChunk - 1]; sl@0: sampleNrInChunk--; sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: //PRINT((_L("videoFrameOffset %Lu"), handle->videoFrameOffset)); sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 resolveVideoSampleSize(MP4HandleImp handle, sl@0: * sampleSizeAtom *stsz) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function finds the size of the current video sample. sl@0: * The result is stored in handle->videoFrameSize. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stsz STSZ atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 resolveVideoSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz) sl@0: { sl@0: if (stsz->sampleSize) sl@0: { sl@0: handle->videoFrameSize = stsz->sampleSize; sl@0: return 0; sl@0: } sl@0: sl@0: if (stsz->sampleCount == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: handle->videoFrameSize = stsz->entrySize[handle->videoSampleNum - 1]; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 fetchVideoFrame(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u8 *buffer, sl@0: * mp4_u32 buffersize, sl@0: * mp4_u32 *framesize, sl@0: * mp4_u32 *timestamp, sl@0: * mp4_bool *keyframe, sl@0: * mp4_u32 *timestamp2) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function fetches one video frame from a file. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * buffer Video frame is retuned here sl@0: * buffersize Size of buffer sl@0: * framesize Size of returned frame in bytes sl@0: * timestamp Frame time in milliseconds (from the beginning of the sl@0: * presentation) sl@0: * keyframe True if intra frame, false otherwise sl@0: * timestamp2 Frame time in timescale (from the beginning of the sl@0: * presentation) sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 fetchVideoFrame(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u8 *buffer, sl@0: mp4_u32 buffersize, sl@0: mp4_u32 *framesize, sl@0: mp4_u32 *timestamp, sl@0: mp4_bool *keyframe, sl@0: mp4_u32 *timestamp2) sl@0: { sl@0: mp4_i32 bytesread; sl@0: sl@0: sl@0: if (!trak->mdia) sl@0: return -1; sl@0: sl@0: if (handle->file) /* Input is in a file */ sl@0: { sl@0: if (seekFileAbs(handle, handle->videoFrameOffset) != 0) sl@0: return -4; sl@0: } sl@0: else /* Input is a stream */ sl@0: { sl@0: if (handle->videoFrameOffset + handle->videoFrameSize <= getCumulativeBufferedBytes(handle)) sl@0: { sl@0: handle->absPosition = handle->videoFrameOffset; sl@0: } sl@0: else sl@0: return -3; sl@0: } sl@0: sl@0: if (handle->videoFrameSize > buffersize) sl@0: { sl@0: *framesize = handle->videoFrameSize; sl@0: return -2; sl@0: } sl@0: sl@0: bytesread = readData(handle, buffer, handle->videoFrameSize); sl@0: switch (bytesread) sl@0: { sl@0: case -1: sl@0: return -1; sl@0: case -2: sl@0: return -4; sl@0: case -10: sl@0: return -3; sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: if (handle->file) sl@0: if (handle->videoFrameOffset + handle->videoFrameSize - 1 > handle->lastAccessedPosInFile) sl@0: handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1; sl@0: sl@0: *framesize = handle->videoFrameSize; sl@0: sl@0: if (convertVideoSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0) sl@0: return -1; sl@0: sl@0: if (isVideoFrameKeyFrame(handle, trak, keyframe) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u8 *buffer, sl@0: * mp4_u32 buffersize, sl@0: * sl@0: * Description: sl@0: * sl@0: * This function fetches one video frame from a file asyncronously. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * buffer Video frame is retuned here sl@0: * buffersize Size of buffer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u8 *buffer, sl@0: mp4_u32 *buffersize) sl@0: { sl@0: if (trak) sl@0: { sl@0: if (!trak->mdia) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (handle->videoFrameSize > *buffersize) sl@0: { sl@0: *buffersize = handle->videoFrameSize; sl@0: return -2; sl@0: } sl@0: sl@0: if ( handle->asyncReader == NULL ) sl@0: { sl@0: TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile )); sl@0: if ( error != KErrNone ) sl@0: { sl@0: if (error == KErrNoMemory ) sl@0: { sl@0: return MP4_OUT_OF_MEMORY; sl@0: } sl@0: else sl@0: { sl@0: return -1; sl@0: } sl@0: } sl@0: } sl@0: sl@0: return handle->asyncReader->ReadVideoFrame( buffer, handle->videoFrameOffset, handle->videoFrameSize); sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_bool *keyframe) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function determines if the current frame is a keyframe (intra) sl@0: * or not. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * keyframe Has a value of MP4TRUE if current frame is a keyframe sl@0: * (intra) or MP4FALSE otherwise sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle, trackAtom *trak, mp4_bool *keyframe) sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: sl@0: *keyframe = MP4FALSE; sl@0: sl@0: if (!trak->mdia) sl@0: return -1; sl@0: sl@0: if (!trak->mdia->minf) sl@0: return -1; sl@0: sl@0: if (!trak->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!trak->mdia->minf->stbl->stss) sl@0: { sl@0: *keyframe = MP4TRUE; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: for (i = 0; i < trak->mdia->minf->stbl->stss->entryCount; i++) sl@0: { sl@0: if (trak->mdia->minf->stbl->stss->sampleNumber[i] == handle->videoSampleNum) sl@0: { sl@0: *keyframe = MP4TRUE; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 convertVideoSampleToTime(MP4HandleImp handle, sl@0: * mediaAtom *mdia, sl@0: * mp4_u32 *timestamp, sl@0: * mp4_u32 *timestamp2) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function converts a video sample to corresponding time. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mdia MDIA atom pointer sl@0: * timestamp Time in milliseconds is returned here sl@0: * timestamp2 Time in timescale is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 convertVideoSampleToTime(MP4HandleImp handle, sl@0: mediaAtom *mdia, sl@0: mp4_u32 *timestamp, sl@0: mp4_u32 *timestamp2) sl@0: { sl@0: mp4_u32 tmptime; sl@0: mp4_double tmptime2; sl@0: mp4_u32 sample; sl@0: mp4_u32 entry; sl@0: sl@0: if (!mdia->mdhd) sl@0: { sl@0: return -1; sl@0: } sl@0: if (!mdia->minf) sl@0: { sl@0: return -1; sl@0: } sl@0: if (!mdia->minf->stbl) sl@0: { sl@0: return -1; sl@0: } sl@0: if (!mdia->minf->stbl->stts) sl@0: { sl@0: return -1; sl@0: } sl@0: if (mdia->minf->stbl->stts->entryCount == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: tmptime = 0; sl@0: sample = 0; sl@0: entry = 0; sl@0: sl@0: for (;;) sl@0: { sl@0: if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->videoSampleNum) sl@0: { sl@0: sample += mdia->minf->stbl->stts->sampleCount[entry]; sl@0: tmptime += (mdia->minf->stbl->stts->sampleCount[entry] * mdia->minf->stbl->stts->sampleDelta[entry]); sl@0: entry++; sl@0: if (entry == mdia->minf->stbl->stts->entryCount) sl@0: { sl@0: return -1; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: tmptime += ((handle->videoSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry]); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if (mdia->mdhd->timeScale == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (timestamp2) sl@0: { sl@0: *timestamp2 = tmptime; sl@0: } sl@0: sl@0: tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5; sl@0: sl@0: *timestamp = (mp4_u32)tmptime2; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 advanceAudioSample(MP4HandleImp handle, sl@0: * trackAtom *trak) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function advances one audio sample and finds the sample sl@0: * offset and sample size. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 advanceAudioSample(MP4HandleImp handle, sl@0: trackAtom *trak) sl@0: { sl@0: if (!trak->mdia) sl@0: return -1; sl@0: if (!trak->mdia->minf) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl->stsz) sl@0: return -1; sl@0: sl@0: sl@0: /* Are there samples left? */ sl@0: sl@0: if (trak->mdia->minf->stbl->stsz->sampleCount > handle->audioSampleNum) sl@0: handle->audioSampleNum++; sl@0: else sl@0: return -2; sl@0: sl@0: /* Find the size of the sample */ sl@0: sl@0: if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0) sl@0: return -1; sl@0: sl@0: /* Find the offset of the sample */ sl@0: sl@0: if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0) sl@0: return -1; sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle, sl@0: * sampleTableAtom *stbl) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function finds the offset of the current audio sample. sl@0: * The result is stored in handle->audioSampleOffset. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stbl STBL atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl) sl@0: { sl@0: mp4_u32 chunk; /* Current chunk number */ sl@0: mp4_u32 sample; /* Number of samples before this run of chunks */ sl@0: mp4_u32 entry; /* Current entry in sample to chunk */ sl@0: mp4_u32 chunksInThisRun; /* Number of chunks in this run */ sl@0: mp4_u32 sampleNrInChunk; /* Sample number in the chunk */ sl@0: sl@0: sl@0: if (!stbl->stsc || stbl->stsc->entryCount == 0) sl@0: return -1; sl@0: if (!stbl->stco || stbl->stco->entryCount == 0) sl@0: return -1; sl@0: sl@0: chunk = 0; sl@0: sample = 0; sl@0: entry = 0; sl@0: sl@0: for (;;) sl@0: { sl@0: /* Find how many chunks there are in this run */ sl@0: sl@0: if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */ sl@0: { sl@0: chunksInThisRun = stbl->stsc->firstChunk[entry + 1] - sl@0: stbl->stsc->firstChunk[entry]; sl@0: } sl@0: else sl@0: chunksInThisRun = stbl->stco->entryCount - chunk + 1; sl@0: sl@0: sl@0: if (handle->audioSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample) sl@0: { sl@0: chunk += (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry]; sl@0: sampleNrInChunk = (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry]; sl@0: sl@0: /* The following functions are needed for multiple sample entry support */ sl@0: handle->audioSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry]; sl@0: sl@0: break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/ sl@0: } sl@0: else sl@0: { sl@0: chunk += chunksInThisRun; sl@0: sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry]; sl@0: } sl@0: sl@0: entry++; sl@0: } sl@0: sl@0: if (chunk > stbl->stco->entryCount) sl@0: return -1; sl@0: sl@0: handle->audioSampleOffset = getChunkOffset(stbl, chunk - 1); sl@0: sl@0: if (sampleNrInChunk) sl@0: { sl@0: if (stbl->stsz->sampleSize) sl@0: { sl@0: handle->audioSampleOffset += stbl->stsz->sampleSize * sampleNrInChunk; sl@0: } sl@0: else sl@0: { sl@0: if (stbl->stsz->sampleCount == 0) sl@0: { sl@0: // ensure there are entries in the entrySize array sl@0: return -1; sl@0: } sl@0: sl@0: while (sampleNrInChunk) sl@0: { sl@0: handle->audioSampleOffset += stbl->stsz->entrySize[handle->audioSampleNum - sampleNrInChunk - 1]; sl@0: sampleNrInChunk--; sl@0: } sl@0: } sl@0: } sl@0: sl@0: //PRINT((_L("audioSampleOffset %Lu"), handle->audioSampleOffset)); sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 resolveAudioSampleSize(MP4HandleImp handle, sl@0: * sampleSizeAtom *stsz) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function finds the size of the current audio sample. sl@0: * The result is stored in handle->audioSampleSize. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * stsz STSZ atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 resolveAudioSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz) sl@0: { sl@0: if (stsz->sampleSize) sl@0: { sl@0: handle->audioSampleSize = stsz->sampleSize; sl@0: return 0; sl@0: } sl@0: sl@0: if (stsz->sampleCount == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: handle->audioSampleSize = stsz->entrySize[handle->audioSampleNum - 1]; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 fetchAudioSample(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u8 *buffer, sl@0: * mp4_u32 buffersize, sl@0: * mp4_u32 *framesize, sl@0: * mp4_u32 *timestamp, sl@0: * mp4_u32 *returnedframes, sl@0: * mp4_u32 *timestamp2) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function fetches one audio sample from a file. sl@0: * sl@0: * Note: returnedframes may differ from the correct value when accessing sl@0: * the last audio sample. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * buffer Audio frame is retuned here sl@0: * buffersize Size of buffer sl@0: * framesize Size of returned frame in bytes sl@0: * timestamp Frame time in milliseconds (from the beginning of the sl@0: * presentation) sl@0: * returnedframes Number of frames returned, of 0 if not known sl@0: * timestamp2 Frame time in timescale (from the beginning of the sl@0: * presentation) sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 fetchAudioSample(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u8 *buffer, sl@0: mp4_u32 buffersize, sl@0: mp4_u32 *framesize, sl@0: mp4_u32 *timestamp, sl@0: mp4_u32 *returnedframes, sl@0: mp4_u32 *timestamp2) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 frameLength; sl@0: mp4_u32 numOfFrames; sl@0: mp4_u8 *framepointer; sl@0: mp4_u32 rawAmrFrameLength[16] = {13,14,16,18,20,21,27,32,6,0,0,0,0,0,0,1}; sl@0: sl@0: if (!trak->mdia) sl@0: return -1; sl@0: sl@0: if (handle->file) /* Input is in a file */ sl@0: { sl@0: if (seekFileAbs(handle, handle->audioSampleOffset) != 0) sl@0: return -4; sl@0: } sl@0: else /* Input is a stream */ sl@0: { sl@0: if (handle->audioSampleOffset + handle->audioSampleSize <= getCumulativeBufferedBytes(handle)) sl@0: { sl@0: handle->absPosition = handle->audioSampleOffset; sl@0: } sl@0: else sl@0: return -3; sl@0: } sl@0: sl@0: if (handle->audioSampleSize > buffersize) sl@0: { sl@0: *framesize = handle->audioSampleSize; sl@0: return -2; sl@0: } sl@0: sl@0: bytesread = readData(handle, buffer, handle->audioSampleSize); sl@0: switch (bytesread) sl@0: { sl@0: case -1: sl@0: return -1; sl@0: case -2: sl@0: return -4; sl@0: case -10: sl@0: return -3; sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: if (handle->file) sl@0: if (handle->audioSampleOffset + handle->audioSampleSize - 1 > handle->lastAccessedPosInFile) sl@0: handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1; sl@0: sl@0: *framesize = handle->audioSampleSize; sl@0: if (convertAudioSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0) sl@0: return -1; sl@0: sl@0: *returnedframes = 0; sl@0: sl@0: /* AMR */ sl@0: if (trak->mdia->minf) sl@0: if (trak->mdia->minf->stbl) sl@0: if (trak->mdia->minf->stbl->stsd) sl@0: if (handle->type & MP4_TYPE_AMR_NB) sl@0: { sl@0: framepointer = buffer; sl@0: numOfFrames = 0; sl@0: while ( bytesread > 0 ) sl@0: { sl@0: frameLength = rawAmrFrameLength[(TInt)(((*framepointer) & 0x78) >> 3)]; sl@0: if ( frameLength == 0) sl@0: { sl@0: return -4; sl@0: } sl@0: bytesread -= frameLength; sl@0: framepointer += frameLength; sl@0: numOfFrames++; sl@0: } sl@0: *returnedframes = numOfFrames; sl@0: sl@0: /* Return the number of sample entries listed for this particular sample entry index sl@0: if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]) sl@0: if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr) sl@0: *returnedframes = trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr->framesPerSample;*/ sl@0: } sl@0: else if (handle->type & MP4_TYPE_AMR_WB) sl@0: { sl@0: /* Return the number of sample entries listed for this particular sample entry index */ sl@0: if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]) sl@0: if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr) sl@0: *returnedframes = trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr->framesPerSample; sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: /* MPEG-4 audio */ sl@0: if (trak->mdia->minf) sl@0: if (trak->mdia->minf->stbl) sl@0: if (trak->mdia->minf->stbl->stsd) sl@0: if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1]) sl@0: *returnedframes = 1; sl@0: sl@0: /* QCELP 13K as QCELPSampleEntry*/ sl@0: if (trak->mdia->minf) sl@0: if (trak->mdia->minf->stbl) sl@0: if (trak->mdia->minf->stbl->stsd) sl@0: if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)) sl@0: { sl@0: /* Return the number of sample entries listed for this particular sample entry index */ sl@0: if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]) sl@0: if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp) sl@0: *returnedframes = trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp->framesPerSample; sl@0: } sl@0: sl@0: /* QCELP 13K as MPEG-4 audio */ sl@0: if (trak->mdia->minf) sl@0: if (trak->mdia->minf->stbl) sl@0: if (trak->mdia->minf->stbl->stsd) sl@0: if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1]) sl@0: *returnedframes = 1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u8 *buffer, sl@0: * mp4_u32 buffersize, sl@0: * sl@0: * Description: sl@0: * sl@0: * This function fetches one audio sample from a file asyncronously. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * buffer Audio frame is retuned here sl@0: * buffersize Size of buffer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u8 *buffer, sl@0: mp4_u32 *buffersize) sl@0: { sl@0: if (trak) sl@0: { sl@0: if (!trak->mdia) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (handle->audioSampleSize > *buffersize) sl@0: { sl@0: *buffersize = handle->audioSampleSize; sl@0: return -2; sl@0: } sl@0: sl@0: if (!handle->file) // Other input than file is not supported sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if ( handle->asyncReader == NULL ) sl@0: { sl@0: TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile )); sl@0: if ( error != KErrNone ) sl@0: { sl@0: if (error == KErrNoMemory ) sl@0: { sl@0: return MP4_OUT_OF_MEMORY; sl@0: } sl@0: else sl@0: { sl@0: return -1; sl@0: } sl@0: } sl@0: } sl@0: sl@0: return handle->asyncReader->ReadAudioFrames( buffer, handle->audioSampleOffset, handle->audioSampleSize); sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 convertAudioSampleToTime(MP4HandleImp handle, sl@0: * mediaAtom *mdia, sl@0: * mp4_u32 *timestamp, sl@0: * mp4_u32 *timestamp2) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function converts an audio sample to corresponding time. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * mdia MDIA atom pointer sl@0: * timestamp Time in milliseconds is returned here sl@0: * timestamp2 Time in timescale is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 convertAudioSampleToTime(MP4HandleImp handle, sl@0: mediaAtom *mdia, sl@0: mp4_u32 *timestamp, sl@0: mp4_u32 *timestamp2) sl@0: { sl@0: mp4_u32 tmptime; sl@0: mp4_double tmptime2; sl@0: mp4_u32 sample; sl@0: mp4_u32 entry; sl@0: sl@0: if (!mdia->mdhd) sl@0: { sl@0: return -1; sl@0: } sl@0: if (!mdia->minf) sl@0: { sl@0: return -1; sl@0: } sl@0: if (!mdia->minf->stbl) sl@0: { sl@0: return -1; sl@0: } sl@0: if (!mdia->minf->stbl->stts) sl@0: { sl@0: return -1; sl@0: } sl@0: if (mdia->minf->stbl->stts->entryCount == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: tmptime = 0; sl@0: sample = 0; sl@0: entry = 0; sl@0: sl@0: for (;;) sl@0: { sl@0: if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->audioSampleNum) sl@0: { sl@0: sample += mdia->minf->stbl->stts->sampleCount[entry]; sl@0: tmptime += mdia->minf->stbl->stts->sampleCount[entry] * sl@0: mdia->minf->stbl->stts->sampleDelta[entry]; sl@0: entry++; sl@0: sl@0: if (entry == mdia->minf->stbl->stts->entryCount) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: tmptime += (handle->audioSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry]; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if (mdia->mdhd->timeScale == 0) sl@0: { sl@0: return -1; sl@0: } sl@0: sl@0: if (timestamp2) sl@0: { sl@0: *timestamp2 = tmptime; sl@0: } sl@0: sl@0: tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5; sl@0: sl@0: *timestamp = (mp4_u32)tmptime2; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 convertTimeToSample(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u32 position, sl@0: * mp4_u32 *sample) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function converts time to corresponding sample number. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak trackAtom pointer sl@0: * position Time in milliseconds sl@0: * sample Sample number is returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 convertTimeToSample(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u32 position, sl@0: mp4_u32 *sample) sl@0: { sl@0: mp4_u32 pos; /* Target position in media timescale */ sl@0: mp4_u32 tmppos; /* Temporary position counter */ sl@0: mp4_u32 i; sl@0: sl@0: sl@0: if (!handle) sl@0: return -1; sl@0: if (!trak) sl@0: return -1; sl@0: if (!trak->mdia) sl@0: return -1; sl@0: if (!trak->mdia->mdhd) sl@0: return -1; sl@0: if (!trak->mdia->minf) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl->stts) sl@0: return -1; sl@0: if (trak->mdia->minf->stbl->stts->entryCount == 0) sl@0: return -1; sl@0: sl@0: *sample = 1; sl@0: tmppos = 0; sl@0: sl@0: pos = (mp4_u32)((mp4_double)position / (mp4_double)1000 * (mp4_double)trak->mdia->mdhd->timeScale + (mp4_double)0.5); sl@0: sl@0: for (i = 0; i < trak->mdia->minf->stbl->stts->entryCount; i++) sl@0: { sl@0: if (pos >= (tmppos + trak->mdia->minf->stbl->stts->sampleCount[i] * sl@0: trak->mdia->minf->stbl->stts->sampleDelta[i])) sl@0: { sl@0: *sample += trak->mdia->minf->stbl->stts->sampleCount[i]; sl@0: tmppos += (trak->mdia->minf->stbl->stts->sampleCount[i] * sl@0: trak->mdia->minf->stbl->stts->sampleDelta[i]); sl@0: sl@0: if (i == trak->mdia->minf->stbl->stts->entryCount - 1) /* Last entry */ sl@0: *sample = *sample - 1; sl@0: } sl@0: else sl@0: { sl@0: if (trak->mdia->minf->stbl->stts->sampleDelta[i] == 0) sl@0: return -1; sl@0: sl@0: *sample += ((pos - tmppos) / trak->mdia->minf->stbl->stts->sampleDelta[i]); sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 goToVideoSample(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u32 sample) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function moves to video sample indicated by sample and finds the sl@0: * sample offset and sample size. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * sample Sample to go to sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 goToVideoSample(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u32 sample) sl@0: { sl@0: if (!trak->mdia) sl@0: return -1; sl@0: if (!trak->mdia->minf) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl->stsz) sl@0: return -1; sl@0: sl@0: sl@0: /* Is the sample valid? */ sl@0: sl@0: if (sample <= trak->mdia->minf->stbl->stsz->sampleCount) sl@0: handle->videoSampleNum = sample; sl@0: else sl@0: return -1; sl@0: sl@0: /* Find the size of the sample */ sl@0: sl@0: if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0) sl@0: return -1; sl@0: sl@0: /* Find the offset of the sample */ sl@0: sl@0: if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0) sl@0: return -1; sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 goToAudioSample(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u32 sample) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function moves to audio sample indicated by sample and finds the sl@0: * sample offset and sample size. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * sample Sample to go to sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 goToAudioSample(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u32 sample) sl@0: { sl@0: if (!trak->mdia) sl@0: return -1; sl@0: if (!trak->mdia->minf) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl->stsz) sl@0: return -1; sl@0: sl@0: sl@0: /* Is the sample valid? */ sl@0: sl@0: if (sample <= trak->mdia->minf->stbl->stsz->sampleCount) sl@0: handle->audioSampleNum = sample; sl@0: else sl@0: return -1; sl@0: sl@0: /* Find the size of the sample */ sl@0: sl@0: if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0) sl@0: return -1; sl@0: sl@0: /* Find the offset of the sample */ sl@0: sl@0: if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0) sl@0: return -1; sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 findVideoKeyFrame(MP4HandleImp handle, sl@0: * trackAtom *trak, sl@0: * mp4_u32 sample, sl@0: * mp4_u32 *newsample) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function finds the video keyframe that is identical to or precedes sl@0: * the sample indicated by sample. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * trak TRAK atom pointer sl@0: * sample Sample number sl@0: * newsample Sample number of found keyframe sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 findVideoKeyFrame(MP4HandleImp handle, sl@0: trackAtom *trak, sl@0: mp4_u32 sample, sl@0: mp4_u32 *newsample) sl@0: { sl@0: mp4_i32 i; sl@0: sl@0: sl@0: if (!handle) sl@0: return -1; sl@0: if (!trak->mdia) sl@0: return -1; sl@0: if (!trak->mdia->minf) sl@0: return -1; sl@0: if (!trak->mdia->minf->stbl) sl@0: return -1; sl@0: sl@0: if (!trak->mdia->minf->stbl->stss) /* No sync sample atom => all samples are sl@0: random access points */ sl@0: { sl@0: *newsample = sample; sl@0: sl@0: return 0; sl@0: } sl@0: *newsample = 0; sl@0: sl@0: for (i = trak->mdia->minf->stbl->stss->entryCount - 1; i >= 0; i--) sl@0: { sl@0: if (sample >= trak->mdia->minf->stbl->stss->sampleNumber[i]) sl@0: { sl@0: *newsample = trak->mdia->minf->stbl->stss->sampleNumber[i]; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: if (*newsample == 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readAVCC(MP4HandleImp handle, sl@0: * avcConfigurationAtom *avcc) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one avcc atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * avcc avcC pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readAVCC(MP4HandleImp handle, avcConfigurationAtom *avcc) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: avcc->avcConfigSize = 0; sl@0: sl@0: if ((avcc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, avcc->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread +=bytesread; sl@0: sl@0: if (avcc->atomhdr->type != ATOMTYPE_AVCC) sl@0: return -1; sl@0: sl@0: /* read the avcDecoderConfigurationRecord */ sl@0: if (avcc->atomhdr->size != 1) sl@0: avcc->avcConfigSize = avcc->atomhdr->size - 8; sl@0: else sl@0: avcc->avcConfigSize = (mp4_u32)(I64INT(avcc->atomhdr->largeSize) - 16); sl@0: sl@0: avcc->avcConfig = (mp4_u8 *)mp4malloc(avcc->avcConfigSize); sl@0: if (avcc->avcConfig == 0) sl@0: return -100; sl@0: sl@0: bytesread = readData(handle, avcc->avcConfig, avcc->avcConfigSize ); sl@0: sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread +=bytesread; sl@0: return totalbytesread; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readBTRT(MP4HandleImp handle, sl@0: * mpeg4BitrateAtom *btrt) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one btrt atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * btrt btrt pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readBTRT(MP4HandleImp handle, mpeg4BitrateAtom *btrt) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((btrt->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, btrt->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread +=bytesread; sl@0: sl@0: if (btrt->atomhdr->type != ATOMTYPE_BTRT) sl@0: return -1; sl@0: sl@0: /* read the mpeg4BitrateAtom */ sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: btrt->bufferSizeDB = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread +=bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: btrt->maxBitRate = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread +=bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: btrt->avgBitrate = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread +=bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readM4DS(MP4HandleImp handle, sl@0: * mpeg4ExtensionDescriptorsAtom *m4ds) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one m4ds atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * m4ds m4ds pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readM4DS(MP4HandleImp handle, mpeg4ExtensionDescriptorsAtom *m4ds) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i; sl@0: sl@0: m4ds->descrSize = 0; sl@0: sl@0: if ((m4ds->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, m4ds->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread +=bytesread; sl@0: sl@0: if (m4ds->atomhdr->type != ATOMTYPE_M4DS) sl@0: return -1; sl@0: sl@0: /* read the avcDecoderConfigurationRecord */ sl@0: if (m4ds->atomhdr->size != 1) sl@0: bytesread = readData(handle, handle->buf, m4ds->atomhdr->size - 8); sl@0: else sl@0: bytesread = readData(handle, handle->buf, (mp4_u32)(I64INT(m4ds->atomhdr->largeSize) - 16) ); sl@0: sl@0: if (bytesread < 0) sl@0: return -1; sl@0: m4ds->descrSize = bytesread; sl@0: m4ds->descr = (mp4_u8 *)mp4malloc(m4ds->descrSize * sizeof(mp4_u8)); sl@0: sl@0: /* copy the mpeg4ExtensionDescriptors from the temp. buffer */ sl@0: for(i = 0; i < m4ds->descrSize; i++) sl@0: m4ds->descr[i] = handle->buf[i]; sl@0: sl@0: totalbytesread +=bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readAVC1(MP4HandleImp handle, sl@0: * avcSampleEntry *avc1) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one avc1 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * avc1 avc1 pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readAVC1(MP4HandleImp handle, avcSampleEntry *avc1) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: if ((avc1->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, avc1->atomhdr); sl@0: sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (avc1->atomhdr->type != ATOMTYPE_AVC1) sl@0: return -1; sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: avc1->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: avc1->width = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: avc1->height = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 50); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: /* Check for the present atoms */ sl@0: while ((mp4_u32)totalbytesread < avc1->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_AVCC: sl@0: sl@0: if (avc1->avcc) /* avcC has already been read, more than one is not allowed. */ sl@0: return -1; sl@0: sl@0: if ((avc1->avcc = (avcConfigurationAtom *)mp4malloc(sizeof(avcConfigurationAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAVCC(handle, avc1->avcc); sl@0: if(bytesread < 0) sl@0: return -1; sl@0: totalbytesread +=bytesread; sl@0: break; sl@0: sl@0: case ATOMTYPE_BTRT: sl@0: sl@0: if (avc1->btrt) /* btrt has already been read, more than one is not allowed. */ sl@0: return -1; sl@0: sl@0: if ((avc1->btrt = (mpeg4BitrateAtom *)mp4malloc(sizeof(mpeg4BitrateAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readBTRT(handle, avc1->btrt); sl@0: if(bytesread < 0) sl@0: return -1; sl@0: totalbytesread +=bytesread; sl@0: break; sl@0: sl@0: case ATOMTYPE_M4DS: sl@0: sl@0: if (avc1->m4ds) /* m4ds has already been read, more than one is not allowed. */ sl@0: return -1; sl@0: sl@0: if ((avc1->m4ds = (mpeg4ExtensionDescriptorsAtom *)mp4malloc(sizeof(mpeg4ExtensionDescriptorsAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readM4DS(handle, avc1->m4ds); sl@0: if(bytesread < 0) sl@0: return -1; sl@0: totalbytesread +=bytesread; sl@0: break; sl@0: sl@0: default: sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeAVCC(avcConfigurationAtom *avcc) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for avcc atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * avcc avcc atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeAVCC(avcConfigurationAtom *avcc) sl@0: { sl@0: if (avcc) sl@0: { sl@0: if (freeAtomHeader(avcc->atomhdr) < 0) sl@0: return -1; sl@0: if(avcc->avcConfig) sl@0: mp4free(avcc->avcConfig); sl@0: sl@0: mp4free(avcc); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for btrt atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * btrt btrt atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt) sl@0: { sl@0: if (btrt) sl@0: { sl@0: if (freeAtomHeader(btrt->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(btrt); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for m4ds atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * m4ds m4ds atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds) sl@0: { sl@0: if (m4ds) sl@0: { sl@0: if (freeAtomHeader(m4ds->atomhdr) < 0) sl@0: return -1; sl@0: if(m4ds->descr) sl@0: mp4free(m4ds->descr); sl@0: sl@0: mp4free(m4ds); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeAVC1(avcSampleEntry *avc1) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for avc1 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * avc1 avc1 atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeAVC1(avcSampleEntry *avc1) sl@0: { sl@0: if (avc1) sl@0: { sl@0: if (freeAtomHeader(avc1->atomhdr) < 0) sl@0: return -1; sl@0: if (freeAVCC(avc1->avcc) < 0) sl@0: return -1; sl@0: if (freeBTRT(avc1->btrt) < 0) sl@0: return -1; sl@0: if (freeM4DS(avc1->m4ds) < 0) sl@0: return -1; sl@0: sl@0: mp4free(avc1); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSQCP(MP4HandleImp handle, sl@0: * qcelpSampleEntry *sqcp) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one SQCP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sqcp SQCP pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readSQCP(MP4HandleImp handle, qcelpSampleEntry *sqcp) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((sqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, sqcp->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (sqcp->atomhdr->type != ATOMTYPE_SQCP) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = discardData(handle, 6); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sqcp->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 16); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sqcp->timeScale = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = discardData(handle, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ((sqcp->dqcp = (qcelpDecSpecStruc *)mp4malloc(sizeof(qcelpDecSpecStruc))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readDQCP(handle, sqcp->dqcp); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( totalbytesread < sqcp->atomhdr->size ) sl@0: { sl@0: bytesread = discardData(handle, sqcp->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeSQCP(qcelpSampleEntry *sqcp) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for SQCP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * sqcp SQCP atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeSQCP(qcelpSampleEntry *sqcp) sl@0: { sl@0: if (sqcp) sl@0: { sl@0: if (freeAtomHeader(sqcp->atomhdr) < 0) sl@0: return -1; sl@0: if (freeDQCP(sqcp->dqcp) < 0) sl@0: return -1; sl@0: sl@0: mp4free(sqcp); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readDQCP(MP4HandleImp handle, sl@0: * qcelpDecSpecStruc *dqcp) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one DQCP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * dqcp DQCP pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readDQCP(MP4HandleImp handle, qcelpDecSpecStruc *dqcp) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((dqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, dqcp->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (dqcp->atomhdr->type != ATOMTYPE_DQCP) sl@0: return -1; sl@0: sl@0: sl@0: bytesread = readData(handle, handle->buf, 4); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: dqcp->vendor = u32endian(*((mp4_u32 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: dqcp->decoderVersion = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: dqcp->framesPerSample = handle->buf[0]; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for DQCP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * damr DQCP atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp) sl@0: { sl@0: if (dqcp) sl@0: { sl@0: if (freeAtomHeader(dqcp->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(dqcp); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readSDTP(MP4HandleImp handle, sampleDependencyAtom *sdtp, sl@0: * mp4_i32 sample_count) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one SDTP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sdtp SDTP atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: sl@0: mp4_i32 readSDTP(MP4HandleImp handle, sl@0: sampleDependencyAtom *sdtp, sl@0: mp4_i32 sample_count) sl@0: { sl@0: mp4_i32 bytesread = 0; sl@0: mp4_i32 totalbytesread = 0; sl@0: mp4_u32 i = 0; sl@0: sl@0: if ((sdtp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readAtomHeader(handle, sdtp->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (sdtp->atomhdr->type != ATOMTYPE_SDTP) sl@0: return -1; sl@0: sl@0: bytesread = readData(handle, handle->buf, 1); //Version must be 0 sl@0: if (bytesread < 0 || handle->buf[0] != 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: bytesread = readData(handle, handle->buf, 3); // Flags must be 0 sl@0: if (bytesread < 0 || handle->buf[0] != 0 || handle->buf[1] != 0 || handle->buf[2] != 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: // sample_count == (size_of_atom - 12) ??? 12 = size + 'sdtp' + ver + flags = 4 + 4 + 1 + 3 ??? sl@0: // sl@0: // sample_count is taken from the sample_count in the Sample Size Box ('stsz') or sl@0: // Compact Sample Size Box (‘stz2’). sl@0: if (sample_count != sdtp->atomhdr->size-12 || sample_count < 0) sl@0: { sl@0: // as each byte consititue one entry in the table, the number of remaining bytes in this sl@0: // atom should match the sample count. If not, the file is corrupted. sl@0: return -1; sl@0: } sl@0: sl@0: if ((sdtp->dep = (sampleDependency *)mp4malloc(sample_count * sizeof(sampleDependency))) == NULL) sl@0: return -100; sl@0: sl@0: for(i=0;ibuf, 1); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: sl@0: sdtp->dep[i].sDependsOn = (handle->buf[0] >> 4) & 0x03; // value from 0 to 3 sl@0: sdtp->dep[i].sIsDependentOn = (handle->buf[0] >> 2) & 0x03; // value from 0 to 3 sl@0: sdtp->dep[i].sHasRedundancy = handle->buf[0] & 0x03; // value from 0 to 3 sl@0: totalbytesread += bytesread; sl@0: } sl@0: sl@0: sdtp->sampleCount = sample_count; sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type) sl@0: * sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses the size and type information for a box. sl@0: * Taking into account largesize if needed. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * size Size of box is returned here sl@0: * type Type of the box is returned here sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * 0 Success. sl@0: * sl@0: */ sl@0: mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type) sl@0: { sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: *size = u32endian(*((mp4_u32 *)handle->buf)); sl@0: *type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: if (*size == 1) sl@0: { sl@0: if (peekData(handle, handle->buf, 16) < 0) sl@0: return -1; sl@0: sl@0: *size = u64endian(*((mp4_u64 *)(handle->buf+8))); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: */ sl@0: sl@0: mp4_i64 getChunkOffset(sampleTableAtom *stbl, mp4_u32 index) sl@0: { sl@0: if (stbl->is32BitOffsets) sl@0: return (mp4_i64)stbl->stco->chunkOffset[index]; sl@0: else sl@0: return stbl->stco64->chunkOffset[index]; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readMeta(MP4HandleImp handle, sl@0: * metaAtom *meta) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one META atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * meta META pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readMeta(MP4HandleImp handle, metaAtom *meta) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((meta->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, meta->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (meta->atomhdr->type != ATOMTYPE_META) sl@0: return -1; sl@0: sl@0: sl@0: while ((mp4_u32)totalbytesread < meta->atomhdr->size) sl@0: { sl@0: mp4_u32 type; sl@0: sl@0: sl@0: if (peekData(handle, handle->buf, 8) < 0) sl@0: return -1; sl@0: sl@0: type = u32endian(*((mp4_u32 *)(handle->buf+4))); sl@0: sl@0: switch (type) sl@0: { sl@0: case ATOMTYPE_HDLR: sl@0: sl@0: if (meta->hdlr) /* HDLR has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((meta->hdlr = (handlerAtom *)mp4malloc(sizeof(handlerAtom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readHDLR(handle, meta->hdlr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: case ATOMTYPE_ID32: sl@0: sl@0: if (meta->ID32) /* ID32 has already been read, more than one is not allowed */ sl@0: return -1; sl@0: sl@0: if ((meta->ID32 = (ID32Atom *)mp4malloc(sizeof(ID32Atom))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readID32(handle, meta->ID32); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: sl@0: default: sl@0: sl@0: bytesread = readUnknown(handle); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 readID32(MP4HandleImp handle, sl@0: * ID32Atom *ID32) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function parses one ID32 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ID32 ID32 pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * Negative integer Error sl@0: * >= 0 Success. Value tells how many bytes were read. sl@0: * sl@0: */ sl@0: mp4_i32 readID32(MP4HandleImp handle, ID32Atom *ID32) sl@0: { sl@0: mp4_i32 bytesread; sl@0: mp4_i32 totalbytesread = 0; sl@0: sl@0: sl@0: if ((ID32->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL) sl@0: return -100; sl@0: sl@0: bytesread = readFullAtomHeader(handle, ID32->atomhdr); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: if (ID32->atomhdr->type != ATOMTYPE_ID32) sl@0: return -1; sl@0: sl@0: // next 2 bytes: top bit is padding, remaining 15 bits is Packed ISO-639-2/T language code sl@0: bytesread = readData(handle, handle->buf, 2); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: ID32->language = u16endian(*((mp4_u16 *)handle->buf)); sl@0: totalbytesread += bytesread; sl@0: sl@0: if ( handle->file ) sl@0: { sl@0: ID32->atomcontentloc = handle->diskReadBufStart + handle->diskReadBufPos; sl@0: } sl@0: else sl@0: { sl@0: ID32->atomcontentloc = handle->absPosition; sl@0: } sl@0: sl@0: bytesread = discardData(handle, ID32->atomhdr->size - totalbytesread ); sl@0: if (bytesread < 0) sl@0: return -1; sl@0: totalbytesread += bytesread; sl@0: sl@0: return totalbytesread; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeMETA(metaAtom *meta) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for META atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * meta META atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeMETA(metaAtom *meta) sl@0: { sl@0: if (meta) sl@0: { sl@0: if (freeAtomHeader(meta->atomhdr) < 0) sl@0: return -1; sl@0: if (freeHDLR(meta->hdlr) < 0) sl@0: return -1; sl@0: if (freeID32(meta->ID32) < 0) sl@0: return -1; sl@0: sl@0: mp4free(meta); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 freeID32(ID32Atom *ID32) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function frees memory for ID32 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * ID32 ID32 atom pointer sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * Negative Error sl@0: * sl@0: */ sl@0: mp4_i32 freeID32(ID32Atom *ID32) sl@0: { sl@0: if (ID32) sl@0: { sl@0: if (freeAtomHeader(ID32->atomhdr) < 0) sl@0: return -1; sl@0: sl@0: mp4free(ID32); sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: // End of File