First public contribution.
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <3gplibrary/mp4config.h>
17 #include <3gplibrary/mp4lib.h>
19 #include "mp4memwrap.h"
20 #include "mp4buffer.h"
21 #include "mp4endian.h"
29 //#define PRINT(x) RDebug::Print x
35 mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type);
40 * mp4_i32 metaDataAvailable(MP4HandleImp handle)
44 * This function determines whether meta data is available for reading
47 * Meta data is available if the input is in a file.
49 * When reading from a stream, meta data is considered available if
50 * it is in the beginning of the stream and the entire Moov atom has
51 * been received. FTYP atom is allowed before MOOV atom.
55 * handle MP4 library handle
59 * 0 Meta data is not available because enough data has not
60 * been inserted into the library
61 * 1 Meta data is available
62 * Negative value Meta data is not available because of fatal error
65 mp4_i32 metaDataAvailable(MP4HandleImp handle)
71 /* Meta data is available if the input is in a file or if a complete file has been inputted as a stream*/
76 /* When reading from a stream, meta data is considered available if
77 it is in the beginning of the stream and the entire MOOV atom has
78 been received. FTYP atom is allowed before MOOV atom. */
80 if (!handle->ftypRead)
82 if (peekData(handle, handle->buf, 8) < 0) /* 8 bytes are not available */
85 size = u32endian(*((mp4_u32 *)handle->buf));
86 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
88 if (type == ATOMTYPE_FTYP)
90 if (getBufferedBytes(handle) - handle->position < size) /* FTYP is not available */
92 if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL)
94 if (readFTYP(handle, handle->ftyp) < 0)
99 // Now the ftyp is read. No need to chedk MOOV presence for full files in the memory.
100 if (handle->LastWriteDataCalled == MP4TRUE)
103 if (handle->LastWriteDataCalled == MP4FALSE)
104 {//Whole stream is not fed to the internal memory yet.
107 if (peekData(handle, handle->buf, 8) < 0)
110 size = u32endian(*((mp4_u32 *)handle->buf));
111 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
113 if (type == ATOMTYPE_MOOV)
115 if (getBufferedBytes(handle) - handle->absPosition >= size) /* Entire Moov is available */
125 if ((mp4_i32)size <= 0)
128 handle->absPosition+=size;
138 * mp4_i32 readFTYP(MP4HandleImp handle,
139 * fileTypeAtom *ftyp)
143 * This function parses one FTYP atom.
147 * handle MP4 library handle
152 * Negative integer Error
153 * >= 0 Success. Value tells how many bytes were read.
156 mp4_i32 readFTYP(MP4HandleImp handle, fileTypeAtom *ftyp)
159 mp4_i32 totalbytesread = 0;
161 mp4_i32 compatiblebrandsize = 0;
164 if ((ftyp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
167 bytesread = readAtomHeader(handle, ftyp->atomhdr);
170 totalbytesread += bytesread;
172 if (ftyp->atomhdr->type != ATOMTYPE_FTYP)
175 if (ftyp->atomhdr->size < 16) // 8(header)+8bytes needed for major and minor brand
178 bytesread = readData(handle, handle->buf, 4);
181 ftyp->majorBrand = u32endian(*((mp4_u32 *)handle->buf));
182 totalbytesread += bytesread;
184 bytesread = readData(handle, handle->buf, 4);
187 ftyp->minorVersion = u32endian(*((mp4_u32 *)handle->buf));
188 totalbytesread += bytesread;
190 if (ftyp->atomhdr->size == (mp4_u32)totalbytesread)
191 return totalbytesread;
193 compatiblebrandsize = (mp4_i32)ftyp->atomhdr->size - totalbytesread;
194 if ( compatiblebrandsize < 4 ) // at this point we must have at least 1 compatible brand
196 if ( compatiblebrandsize > 20*4) // maximum of 20 compatible brands 4byte entries
198 if ( compatiblebrandsize % 4 ) // must be able to divide by 4
201 ftyp->compatibleBrands = (mp4_u32 *)mp4malloc( compatiblebrandsize );
202 if (ftyp->compatibleBrands == NULL)
205 while ((mp4_u32)totalbytesread < ftyp->atomhdr->size)
207 bytesread = readData(handle, handle->buf, 4);
211 ftyp->compatibleBrands[n] = u32endian(*((mp4_u32 *)handle->buf));
214 totalbytesread += bytesread;
217 return totalbytesread;
224 * mp4_i32 readMetaData(MP4HandleImp handle)
228 * This function reads the meta data from the file/stream and stores
229 * the information in the atom structures available via handle.
233 * handle MP4 library handle
237 * Negative value Error
238 * >= 0 Success. Value tells the number of bytes read.
241 mp4_i32 readMetaData(MP4HandleImp handle)
244 mp4_i32 totalbytesread = 0;
253 if (seekFileAbs(handle, 0) < 0)
256 /* Seek to the start of FTYP atom */
260 if (readBoxHeader(handle, &size, &type) <0)
263 if (type == ATOMTYPE_FTYP)
267 if ((handle->ftyp = (fileTypeAtom *)mp4malloc(sizeof(fileTypeAtom))) == NULL)
269 bytesread = readFTYP(handle, handle->ftyp);
272 totalbytesread += bytesread;
280 if (seekFile(handle, size) != 0)
284 if (seekFileAbs(handle, 0) < 0)
287 /* Seek to the start of MOOV atom */
290 if (readBoxHeader(handle, &size, &type) <0)
293 if (type == ATOMTYPE_MOOV)
299 if (seekFile(handle, size) != 0)
304 // If all data of a file is in the memory and the file does not have MOOV box right after FTYP,
305 // then we need to seek for the location of the MOOV first
307 if (handle->LastWriteDataCalled == MP4TRUE)
311 // Seek until the beginning of MOOV box.
314 if (peekData(handle, handle->buf, 8) < 0)
317 size = u32endian(*((mp4_u32 *)handle->buf));
318 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
320 if (type == ATOMTYPE_MOOV)
323 if ((mp4_i32)size <= 0)
326 if (discardData(handle, size) < 0)
331 if ((handle->moov = (movieAtom *)mp4malloc(sizeof(movieAtom))) == NULL)
334 bytesread = readMoov(handle, handle->moov);
337 totalbytesread += bytesread;
339 if (handle->moov->trakAudio)
342 mp4_i32 errorAudio = 0;
344 errorAudio = determineAudioType(handle, &audiotype);
345 if ( errorAudio == 0 )
347 handle->type |= audiotype;
349 /* Move to the beginning of the 1st audio frame */
350 switch (advanceAudioSample(handle, handle->moov->trakAudio))
355 handle->audioLast = MP4TRUE;
361 else if (errorAudio == -2)
363 handle->type |= audiotype;
371 if (handle->moov->trakVideo)
374 mp4_i32 errorVideo = 0;
376 errorVideo = determineVideoType(handle, &videotype);
377 if ( errorVideo == 0 )
379 handle->type |= videotype;
381 /* Move to the beginning of the 1st video frame */
382 switch (advanceVideoFrame(handle, handle->moov->trakVideo))
387 handle->videoLast = MP4TRUE;
393 else if (errorVideo == -2)
395 handle->type |= videotype;
403 return totalbytesread;
410 * mp4_i32 readMoov(MP4HandleImp handle,
415 * This function parses one MOOV atom.
419 * handle MP4 library handle
424 * Negative integer Error
425 * >= 0 Success. Value tells how many bytes were read.
428 mp4_i32 readMoov(MP4HandleImp handle, movieAtom *moov)
431 mp4_i32 totalbytesread = 0;
434 if ((moov->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
437 bytesread = readAtomHeader(handle, moov->atomhdr);
440 totalbytesread += bytesread;
442 if (moov->atomhdr->type != ATOMTYPE_MOOV)
445 while ((mp4_u32)totalbytesread < handle->moov->atomhdr->size)
450 if (peekData(handle, handle->buf, 8) < 0)
453 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
459 if (moov->mvhd) /* MVHD has already been read, more than one is not allowed */
462 if ((moov->mvhd = (movieHeaderAtom *)mp4malloc(sizeof(movieHeaderAtom))) == NULL)
465 bytesread = readMVHD(handle, moov->mvhd);
468 totalbytesread += bytesread;
474 if (moov->iods) /* IODS has already been read, more than one is not allowed */
477 if ((moov->iods = (objectDescriptorAtom *)mp4malloc(sizeof(objectDescriptorAtom))) == NULL)
480 bytesread = readIODS(handle, moov->iods);
483 totalbytesread += bytesread;
492 if ((ta = (trackAtom *)mp4malloc(sizeof(trackAtom))) == NULL)
495 bytesread = readTRAK(handle, ta);
498 if (freeTRAK(ta) < 0)
502 totalbytesread += bytesread;
506 if (freeTRAK(ta) < 0)
512 if (freeTRAK(ta) < 0)
517 if (ta->mdia->hdlr->handlerType != HANDLERTYPE_VIDE &&
518 ta->mdia->hdlr->handlerType != HANDLERTYPE_SOUN) /* Track is neither video nor audio */
520 /* Do nothing with the unknown track */
521 if (freeTRAK(ta) < 0)
526 if (ta->mdia->hdlr->handlerType == HANDLERTYPE_VIDE)
528 if (moov->trakVideo) /* Video Track already read */
530 if (freeTRAK(ta) < 0)
535 moov->trakVideo = ta;
538 else if (ta->mdia->hdlr->handlerType == HANDLERTYPE_SOUN)
540 if (moov->trakAudio) /* Audio Track already read */
542 if (freeTRAK(ta) < 0)
547 moov->trakAudio = ta;
559 if (moov->udta) /* UDTA has already been read */
561 bytesread = readUnknown(handle);
564 totalbytesread += bytesread;
569 if ((moov->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL)
572 bytesread = readUDTA(handle, moov->udta);
575 totalbytesread += bytesread;
583 if (moov->meta) /* META has already been read, more than one is not allowed */
586 if ((moov->meta = (metaAtom *)mp4malloc(sizeof(metaAtom))) == NULL)
589 bytesread = readMeta(handle, moov->meta);
592 totalbytesread += bytesread;
599 bytesread = readUnknown(handle);
602 totalbytesread += bytesread;
608 return totalbytesread;
615 * mp4_i32 readAtomheader(MP4HandleImp handle,
620 * This function reads an atom header and stores the information
625 * handle MP4 library handle
626 * ah atomHeader structure that is used to store the
631 * Negative value Error
632 * >= 0 Success. Value tells how many bytes were read.
635 mp4_i32 readAtomHeader(MP4HandleImp handle, atomHeader *ah)
638 mp4_i32 totalbytesread = 0;
640 //PRINT((_L("readAtomHeader")));
641 bytesread = readData(handle, handle->buf, 4);
644 ah->size = u32endian(*((mp4_u32 *)handle->buf));
645 totalbytesread += bytesread;
647 bytesread = readData(handle, handle->buf, 4);
650 ah->type = u32endian(*((mp4_u32 *)handle->buf));
651 totalbytesread += bytesread;
655 bytesread = readData(handle, handle->buf, 8);
658 ah->largeSize = u64endian(*((mp4_u64 *)handle->buf));
659 totalbytesread += bytesread;
662 if (ah->type == ATOMTYPE_UUID)
664 bytesread = readData(handle, handle->buf, 16);
667 mp4memcpy(ah->extendedType, handle->buf, 16);
668 totalbytesread += bytesread;
671 //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]));
672 return totalbytesread;
679 * mp4_i32 readFullAtomHeader(MP4HandleImp handle,
684 * This function reads a full atom header and stores the information
689 * handle MP4 library handle
690 * ah atomHeader structure that is used to store the
695 * Negative value Error
696 * >= 0 Success. Value tells how many bytes were read.
699 mp4_i32 readFullAtomHeader(MP4HandleImp handle, atomHeader *ah)
702 mp4_i32 totalbytesread = 0;
704 //PRINT((_L("readFullAtomHeader")));
706 bytesread = readData(handle, handle->buf, 4);
709 ah->size = u32endian(*((mp4_u32 *)handle->buf));
710 totalbytesread += bytesread;
712 bytesread = readData(handle, handle->buf, 4);
715 ah->type = u32endian(*((mp4_u32 *)handle->buf));
716 totalbytesread += bytesread;
718 bytesread = readData(handle, handle->buf, 1);
721 ah->version = *(handle->buf);
722 totalbytesread += bytesread;
724 bytesread = readData(handle, handle->buf, 3);
727 mp4memcpy(ah->flags, handle->buf, 3);
728 totalbytesread += bytesread;
730 //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]));
731 return totalbytesread;
738 * mp4_i32 readMVHD(MP4HandleImp handle,
739 * movieHeaderAtom *mvhd)
743 * This function parses one MVHD atom.
747 * handle MP4 library handle
752 * Negative integer Error
753 * >= 0 Success. Value tells how many bytes were read.
756 mp4_i32 readMVHD(MP4HandleImp handle, movieHeaderAtom *mvhd)
759 mp4_i32 totalbytesread = 0;
762 if ((mvhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
765 bytesread = readFullAtomHeader(handle, mvhd->atomhdr);
768 totalbytesread += bytesread;
770 if (mvhd->atomhdr->type != ATOMTYPE_MVHD)
773 if (mvhd->atomhdr->version == 1) /* 64 bit */
775 bytesread = readData(handle, handle->buf, 8);
778 mvhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
779 totalbytesread += bytesread;
781 bytesread = readData(handle, handle->buf, 8);
784 mvhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
785 totalbytesread += bytesread;
787 bytesread = readData(handle, handle->buf, 4);
790 mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
791 totalbytesread += bytesread;
793 bytesread = readData(handle, handle->buf, 8);
796 mvhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
797 totalbytesread += bytesread;
801 bytesread = readData(handle, handle->buf, 4);
804 mvhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
805 totalbytesread += bytesread;
807 bytesread = readData(handle, handle->buf, 4);
810 mvhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
811 totalbytesread += bytesread;
813 bytesread = readData(handle, handle->buf, 4);
816 mvhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
817 totalbytesread += bytesread;
819 bytesread = readData(handle, handle->buf, 4);
822 mvhd->duration = u32endian(*((mp4_u32 *)handle->buf));
823 totalbytesread += bytesread;
826 bytesread = discardData(handle, 76);
829 totalbytesread += bytesread;
831 bytesread = readData(handle, handle->buf, 4);
834 mvhd->nextTrackID = u32endian(*((mp4_u32 *)handle->buf));
835 totalbytesread += bytesread;
837 return totalbytesread;
844 * mp4_i32 readIODS(MP4HandleImp handle,
845 * objectDescriptorAtom *iods)
849 * This function parses one IODS atom.
853 * handle MP4 library handle
858 * Negative integer Error
859 * >= 0 Success. Value tells how many bytes were read.
862 mp4_i32 readIODS(MP4HandleImp handle, objectDescriptorAtom *iods)
865 mp4_i32 totalbytesread = 0;
868 if ((iods->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
871 bytesread = readFullAtomHeader(handle, iods->atomhdr);
874 totalbytesread += bytesread;
876 if (iods->atomhdr->type != ATOMTYPE_IODS)
879 bytesread = discardData(handle, iods->atomhdr->size - totalbytesread);
882 totalbytesread += bytesread;
884 return totalbytesread;
891 * mp4_i32 readTRAK(MP4HandleImp handle,
896 * This function parses one TRAK atom.
900 * handle MP4 library handle
905 * Negative integer Error
906 * >= 0 Success. Value tells how many bytes were read.
909 mp4_i32 readTRAK(MP4HandleImp handle, trackAtom *trak)
912 mp4_i32 totalbytesread = 0;
915 if ((trak->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
918 bytesread = readAtomHeader(handle, trak->atomhdr);
921 totalbytesread += bytesread;
923 if (trak->atomhdr->type != ATOMTYPE_TRAK)
927 while ((mp4_u32)totalbytesread < trak->atomhdr->size)
932 if (peekData(handle, handle->buf, 8) < 0)
935 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
941 if (trak->tkhd) /* MVHD has already been read, more than one is not allowed */
944 if ((trak->tkhd = (trackHeaderAtom *)mp4malloc(sizeof(trackHeaderAtom))) == NULL)
947 bytesread = readTKHD(handle, trak->tkhd);
950 totalbytesread += bytesread;
956 if (trak->tref) /* TREF has already been read, more than one is not allowed */
959 if ((trak->tref = (trackReferenceAtom *)mp4malloc(sizeof(trackReferenceAtom))) == NULL)
962 bytesread = readTREF(handle, trak->tref);
965 totalbytesread += bytesread;
971 if (trak->edts) /* EDTS has already been read, more than one is not allowed */
974 if ((trak->edts = (editListContainerAtom *)mp4malloc(sizeof(editListContainerAtom))) == NULL)
977 bytesread = readEDTS(handle, trak->edts);
980 totalbytesread += bytesread;
986 if (trak->mdia) /* MDIA has already been read, more than one is not allowed */
989 if ((trak->mdia = (mediaAtom *)mp4malloc(sizeof(mediaAtom))) == NULL)
992 bytesread = readMDIA(handle, trak->mdia);
995 totalbytesread += bytesread;
1001 if (trak->udta) /* UDTA has already been read */
1003 bytesread = readUnknown(handle);
1006 totalbytesread += bytesread;
1010 if ((trak->udta = (userDataAtom *)mp4malloc(sizeof(userDataAtom))) == NULL)
1013 bytesread = readUDTA(handle, trak->udta);
1016 totalbytesread += bytesread;
1023 bytesread = readUnknown(handle);
1026 totalbytesread += bytesread;
1032 return totalbytesread;
1039 * mp4_i32 readUnknown(MP4HandleImp handle)
1043 * This function reads one atom of unknown type. Atom contents are
1048 * handle MP4 library handle
1052 * Negative integer Error
1053 * >= 0 Success. Value tells how many bytes were read.
1056 mp4_i32 readUnknown(MP4HandleImp handle)
1059 mp4_i32 totalbytesread = 0;
1063 bytesread = readData(handle, handle->buf, 4);
1066 totalbytesread += bytesread;
1068 size = u32endian(*((mp4_u32 *)handle->buf));
1076 if ( seekFile(handle, size - totalbytesread) < 0 )
1087 bytesread = discardData(handle, size - totalbytesread);
1090 totalbytesread += bytesread;
1092 return totalbytesread;
1099 * mp4_i32 readTKHD(MP4HandleImp handle,
1100 * trackHeaderAtom *tkhd)
1104 * This function parses one TKHD atom.
1108 * handle MP4 library handle
1113 * Negative integer Error
1114 * >= 0 Success. Value tells how many bytes were read.
1117 mp4_i32 readTKHD(MP4HandleImp handle, trackHeaderAtom *tkhd)
1120 mp4_i32 totalbytesread = 0;
1123 if ((tkhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1126 bytesread = readFullAtomHeader(handle, tkhd->atomhdr);
1129 totalbytesread += bytesread;
1131 if (tkhd->atomhdr->type != ATOMTYPE_TKHD)
1134 if (tkhd->atomhdr->version == 1) /* 64 bit */
1136 bytesread = readData(handle, handle->buf, 8);
1139 tkhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
1140 totalbytesread += bytesread;
1142 bytesread = readData(handle, handle->buf, 8);
1145 tkhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
1146 totalbytesread += bytesread;
1148 bytesread = readData(handle, handle->buf, 4);
1151 tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf));
1152 totalbytesread += bytesread;
1154 bytesread = readData(handle, handle->buf, 4);
1157 tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf));
1158 totalbytesread += bytesread;
1160 bytesread = readData(handle, handle->buf, 8);
1163 tkhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
1164 totalbytesread += bytesread;
1168 bytesread = readData(handle, handle->buf, 4);
1171 tkhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
1172 totalbytesread += bytesread;
1174 bytesread = readData(handle, handle->buf, 4);
1177 tkhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
1178 totalbytesread += bytesread;
1180 bytesread = readData(handle, handle->buf, 4);
1183 tkhd->trackID = u32endian(*((mp4_u32 *)handle->buf));
1184 totalbytesread += bytesread;
1186 bytesread = readData(handle, handle->buf, 4);
1189 tkhd->reserved = u32endian(*((mp4_u32 *)handle->buf));
1190 totalbytesread += bytesread;
1192 bytesread = readData(handle, handle->buf, 4);
1195 tkhd->duration = u32endian(*((mp4_u32 *)handle->buf));
1196 totalbytesread += bytesread;
1199 bytesread = discardData(handle, 52);
1202 totalbytesread += bytesread;
1204 bytesread = readData(handle, handle->buf, 4);
1207 tkhd->width = u16endian(*((mp4_u16 *)handle->buf));
1208 totalbytesread += bytesread;
1210 bytesread = readData(handle, handle->buf, 4);
1213 tkhd->height = u16endian(*((mp4_u16 *)handle->buf));
1214 totalbytesread += bytesread;
1216 return totalbytesread;
1223 * mp4_i32 readTREF(MP4HandleImp handle,
1224 * trackReferenceAtom *tref)
1228 * This function parses one TREF atom and discards the contents.
1232 * handle MP4 library handle
1237 * Negative integer Error
1238 * >= 0 Success. Value tells how many bytes were read.
1241 mp4_i32 readTREF(MP4HandleImp handle, trackReferenceAtom *tref)
1244 mp4_i32 totalbytesread = 0;
1247 if ((tref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1250 bytesread = readAtomHeader(handle, tref->atomhdr);
1253 totalbytesread += bytesread;
1255 if (tref->atomhdr->type != ATOMTYPE_TREF)
1258 bytesread = discardData(handle, tref->atomhdr->size - totalbytesread);
1261 totalbytesread += bytesread;
1263 return totalbytesread;
1270 * mp4_i32 readEDTS(MP4HandleImp handle,
1271 * editListContainerAtom *edts)
1275 * This function parses one EDTS atom and discards the contents.
1279 * handle MP4 library handle
1284 * Negative integer Error
1285 * >= 0 Success. Value tells how many bytes were read.
1288 mp4_i32 readEDTS(MP4HandleImp handle, editListContainerAtom *edts)
1291 mp4_i32 totalbytesread = 0;
1294 if ((edts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1297 bytesread = readAtomHeader(handle, edts->atomhdr);
1300 totalbytesread += bytesread;
1302 if (edts->atomhdr->type != ATOMTYPE_EDTS)
1305 bytesread = discardData(handle, edts->atomhdr->size - totalbytesread);
1308 totalbytesread += bytesread;
1310 return totalbytesread;
1317 * mp4_i32 readMDIA(MP4HandleImp handle,
1322 * This function parses one MDIA atom.
1326 * handle MP4 library handle
1331 * Negative integer Error
1332 * >= 0 Success. Value tells how many bytes were read.
1335 mp4_i32 readMDIA(MP4HandleImp handle, mediaAtom *mdia)
1338 mp4_i32 totalbytesread = 0;
1341 if ((mdia->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1344 bytesread = readAtomHeader(handle, mdia->atomhdr);
1347 totalbytesread += bytesread;
1349 if (mdia->atomhdr->type != ATOMTYPE_MDIA)
1353 while ((mp4_u32)totalbytesread < mdia->atomhdr->size)
1358 if (peekData(handle, handle->buf, 8) < 0)
1361 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
1367 if (mdia->mdhd) /* MDHD has already been read, more than one is not allowed */
1370 if ((mdia->mdhd = (mediaHeaderAtom *)mp4malloc(sizeof(mediaHeaderAtom))) == NULL)
1373 bytesread = readMDHD(handle, mdia->mdhd);
1376 totalbytesread += bytesread;
1382 if (mdia->hdlr) /* HDLR has already been read, more than one is not allowed */
1385 if ((mdia->hdlr = (handlerAtom *)mp4malloc(sizeof(handlerAtom))) == NULL)
1388 bytesread = readHDLR(handle, mdia->hdlr);
1391 totalbytesread += bytesread;
1397 if (mdia->minf) /* MINF has already been read, more than one is not allowed */
1400 if ((mdia->minf = (mediaInformationAtom *)mp4malloc(sizeof(mediaInformationAtom))) == NULL)
1403 bytesread = readMINF(handle, mdia->minf);
1406 totalbytesread += bytesread;
1412 bytesread = readUnknown(handle);
1415 totalbytesread += bytesread;
1421 return totalbytesread;
1428 * mp4_i32 readMDHD(MP4HandleImp handle,
1429 * mediaHeaderAtom *mdhd)
1433 * This function parses one MDHD atom.
1437 * handle MP4 library handle
1442 * Negative integer Error
1443 * >= 0 Success. Value tells how many bytes were read.
1446 mp4_i32 readMDHD(MP4HandleImp handle, mediaHeaderAtom *mdhd)
1449 mp4_i32 totalbytesread = 0;
1452 if ((mdhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1455 bytesread = readFullAtomHeader(handle, mdhd->atomhdr);
1458 totalbytesread += bytesread;
1460 if (mdhd->atomhdr->type != ATOMTYPE_MDHD)
1464 if (mdhd->atomhdr->version == 1) /* 64 bit */
1466 bytesread = readData(handle, handle->buf, 8);
1469 mdhd->creationTime64 = u64endian(*((mp4_u64 *)handle->buf));
1470 totalbytesread += bytesread;
1472 bytesread = readData(handle, handle->buf, 8);
1475 mdhd->modificationTime64 = u64endian(*((mp4_u64 *)handle->buf));
1476 totalbytesread += bytesread;
1478 bytesread = readData(handle, handle->buf, 4);
1481 mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
1482 totalbytesread += bytesread;
1484 bytesread = readData(handle, handle->buf, 8);
1487 mdhd->duration64 = u64endian(*((mp4_u64 *)handle->buf));
1488 totalbytesread += bytesread;
1492 bytesread = readData(handle, handle->buf, 4);
1495 mdhd->creationTime = u32endian(*((mp4_u32 *)handle->buf));
1496 totalbytesread += bytesread;
1498 bytesread = readData(handle, handle->buf, 4);
1501 mdhd->modificationTime = u32endian(*((mp4_u32 *)handle->buf));
1502 totalbytesread += bytesread;
1504 bytesread = readData(handle, handle->buf, 4);
1507 mdhd->timeScale = u32endian(*((mp4_u32 *)handle->buf));
1508 totalbytesread += bytesread;
1510 bytesread = readData(handle, handle->buf, 4);
1513 mdhd->duration = u32endian(*((mp4_u32 *)handle->buf));
1514 totalbytesread += bytesread;
1517 bytesread = discardData(handle, 4);
1520 totalbytesread += bytesread;
1522 return totalbytesread;
1529 * mp4_i32 readHDLR(MP4HandleImp handle,
1530 * handlerAtom *hdlr)
1534 * This function parses one HDLR atom.
1538 * handle MP4 library handle
1543 * Negative integer Error
1544 * >= 0 Success. Value tells how many bytes were read.
1547 mp4_i32 readHDLR(MP4HandleImp handle, handlerAtom *hdlr)
1550 mp4_i32 totalbytesread = 0;
1553 if ((hdlr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1556 bytesread = readFullAtomHeader(handle, hdlr->atomhdr);
1559 totalbytesread += bytesread;
1561 if (hdlr->atomhdr->type != ATOMTYPE_HDLR)
1565 bytesread = discardData(handle, 4);
1568 totalbytesread += bytesread;
1570 bytesread = readData(handle, handle->buf, 4);
1573 hdlr->handlerType = u32endian(*((mp4_u32 *)handle->buf));
1574 totalbytesread += bytesread;
1576 bytesread = discardData(handle, hdlr->atomhdr->size - totalbytesread);
1579 totalbytesread += bytesread;
1581 return totalbytesread;
1588 * mp4_i32 readMINF(MP4HandleImp handle,
1589 * mediaInformationAtom *minf)
1593 * This function parses one MINF atom.
1597 * handle MP4 library handle
1602 * Negative integer Error
1603 * >= 0 Success. Value tells how many bytes were read.
1606 mp4_i32 readMINF(MP4HandleImp handle, mediaInformationAtom *minf)
1609 mp4_i32 totalbytesread = 0;
1612 if ((minf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1615 bytesread = readAtomHeader(handle, minf->atomhdr);
1618 totalbytesread += bytesread;
1620 if (minf->atomhdr->type != ATOMTYPE_MINF)
1624 while ((mp4_u32)totalbytesread < minf->atomhdr->size)
1629 if (peekData(handle, handle->buf, 8) < 0)
1632 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
1638 if (minf->vmhd || minf->smhd) /* VMHD or SMHD has already been read, more than one is not allowed */
1641 if ((minf->vmhd = (videoMediaHeaderAtom *)mp4malloc(sizeof(videoMediaHeaderAtom))) == NULL)
1644 bytesread = readVMHD(handle, minf->vmhd);
1647 totalbytesread += bytesread;
1653 if (minf->smhd || minf->vmhd) /* SMHD or VMHD has already been read, more than one is not allowed */
1656 if ((minf->smhd = (soundMediaHeaderAtom *)mp4malloc(sizeof(soundMediaHeaderAtom))) == NULL)
1659 bytesread = readSMHD(handle, minf->smhd);
1662 totalbytesread += bytesread;
1668 if (minf->dinf) /* DINF has already been read, more than one is not allowed */
1671 if ((minf->dinf = (dataInformationAtom *)mp4malloc(sizeof(dataInformationAtom))) == NULL)
1674 bytesread = readDINF(handle, minf->dinf);
1677 totalbytesread += bytesread;
1683 if (minf->stbl) /* STBL has already been read, more than one is not allowed */
1686 if ((minf->stbl = (sampleTableAtom *)mp4malloc(sizeof(sampleTableAtom))) == NULL)
1689 bytesread = readSTBL(handle, minf->stbl);
1692 totalbytesread += bytesread;
1698 bytesread = readUnknown(handle);
1701 totalbytesread += bytesread;
1707 return totalbytesread;
1714 * mp4_i32 readVMHD(MP4HandleImp handle,
1715 * videoMediaHeaderAtom *vmhd)
1719 * This function parses one VMHD atom.
1723 * handle MP4 library handle
1728 * Negative integer Error
1729 * >= 0 Success. Value tells how many bytes were read.
1732 mp4_i32 readVMHD(MP4HandleImp handle, videoMediaHeaderAtom *vmhd)
1735 mp4_i32 totalbytesread = 0;
1738 if ((vmhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1741 bytesread = readFullAtomHeader(handle, vmhd->atomhdr);
1744 totalbytesread += bytesread;
1746 if (vmhd->atomhdr->type != ATOMTYPE_VMHD)
1750 bytesread = discardData(handle, vmhd->atomhdr->size - totalbytesread);
1753 totalbytesread += bytesread;
1755 return totalbytesread;
1762 * mp4_i32 readSMHD(MP4HandleImp handle,
1763 * soundMediaHeaderAtom *smhd)
1767 * This function parses one SMHD atom.
1771 * handle MP4 library handle
1776 * Negative integer Error
1777 * >= 0 Success. Value tells how many bytes were read.
1780 mp4_i32 readSMHD(MP4HandleImp handle, soundMediaHeaderAtom *smhd)
1783 mp4_i32 totalbytesread = 0;
1786 if ((smhd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1789 bytesread = readFullAtomHeader(handle, smhd->atomhdr);
1792 totalbytesread += bytesread;
1794 if (smhd->atomhdr->type != ATOMTYPE_SMHD)
1798 bytesread = discardData(handle, smhd->atomhdr->size - totalbytesread);
1801 totalbytesread += bytesread;
1803 return totalbytesread;
1810 * mp4_i32 readDINF(MP4HandleImp handle,
1811 * dataInformationAtom *dinf)
1815 * This function parses one DINF atom.
1819 * handle MP4 library handle
1824 * Negative integer Error
1825 * >= 0 Success. Value tells how many bytes were read.
1828 mp4_i32 readDINF(MP4HandleImp handle, dataInformationAtom *dinf)
1831 mp4_i32 totalbytesread = 0;
1834 if ((dinf->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1837 bytesread = readAtomHeader(handle, dinf->atomhdr);
1840 totalbytesread += bytesread;
1842 if (dinf->atomhdr->type != ATOMTYPE_DINF)
1846 while ((mp4_u32)totalbytesread < dinf->atomhdr->size)
1851 if (peekData(handle, handle->buf, 8) < 0)
1854 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
1860 if (dinf->dref) /* DINF has already been read, more than one is not allowed */
1863 if ((dinf->dref = (dataReferenceAtom *)mp4malloc(sizeof(dataReferenceAtom))) == NULL)
1866 bytesread = readDREF(handle, dinf->dref);
1869 totalbytesread += bytesread;
1879 return totalbytesread;
1886 * mp4_i32 readDREF(MP4HandleImp handle,
1887 * dataReferenceAtom *dref)
1891 * This function parses one DREF atom.
1895 * handle MP4 library handle
1900 * Negative integer Error
1901 * >= 0 Success. Value tells how many bytes were read.
1904 mp4_i32 readDREF(MP4HandleImp handle, dataReferenceAtom *dref)
1907 mp4_i32 totalbytesread = 0;
1910 if ((dref->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1913 bytesread = readFullAtomHeader(handle, dref->atomhdr);
1916 totalbytesread += bytesread;
1918 if (dref->atomhdr->type != ATOMTYPE_DREF)
1922 bytesread = readData(handle, handle->buf, 4);
1925 dref->entryCount = u32endian(*((mp4_u32 *)handle->buf));
1926 totalbytesread += bytesread;
1928 if (dref->entryCount != 1)
1931 while ((mp4_u32)totalbytesread < dref->atomhdr->size)
1933 bytesread = readUnknown(handle);
1936 totalbytesread += bytesread;
1938 return totalbytesread;
1945 * mp4_i32 readURL(MP4HandleImp handle,
1946 * dataEntryURLAtom *url)
1950 * This function parses one URL atom.
1954 * handle MP4 library handle
1959 * Negative integer Error
1960 * >= 0 Success. Value tells how many bytes were read.
1963 mp4_i32 readURL(MP4HandleImp handle, dataEntryURLAtom *url)
1966 mp4_i32 totalbytesread = 0;
1969 if ((url->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
1972 bytesread = readFullAtomHeader(handle, url->atomhdr);
1975 totalbytesread += bytesread;
1977 if (url->atomhdr->type != ATOMTYPE_URL)
1981 if (!(url->atomhdr->flags[0] == 0x00 &&
1982 url->atomhdr->flags[1] == 0x00 &&
1983 url->atomhdr->flags[2] == 0x01))
1986 return totalbytesread;
1993 * mp4_i32 readURN(MP4HandleImp handle,
1994 * dataEntryURNAtom *urn)
1998 * This function parses one URN atom.
2002 * handle MP4 library handle
2007 * Negative integer Error
2008 * >= 0 Success. Value tells how many bytes were read.
2011 mp4_i32 readURN(MP4HandleImp handle, dataEntryURNAtom *urn)
2014 mp4_i32 totalbytesread = 0;
2017 if ((urn->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2020 bytesread = readFullAtomHeader(handle, urn->atomhdr);
2023 totalbytesread += bytesread;
2025 if (urn->atomhdr->type != ATOMTYPE_URN)
2029 if (!(urn->atomhdr->flags[0] == 0x00 &&
2030 urn->atomhdr->flags[1] == 0x00 &&
2031 urn->atomhdr->flags[2] == 0x01))
2034 return totalbytesread;
2041 * mp4_i32 readSTBL(MP4HandleImp handle,
2042 * sampleTableAtom *stbl)
2046 * This function parses one STBL atom.
2050 * handle MP4 library handle
2055 * Negative integer Error
2056 * >= 0 Success. Value tells how many bytes were read.
2059 mp4_i32 readSTBL(MP4HandleImp handle, sampleTableAtom *stbl)
2062 mp4_i32 totalbytesread = 0;
2065 if ((stbl->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2068 bytesread = readAtomHeader(handle, stbl->atomhdr);
2071 totalbytesread += bytesread;
2073 if (stbl->atomhdr->type != ATOMTYPE_STBL)
2077 while ((mp4_u32)totalbytesread < stbl->atomhdr->size)
2082 if (peekData(handle, handle->buf, 8) < 0)
2085 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
2091 if (stbl->stts) /* STTS has already been read, more than one is not allowed */
2094 if ((stbl->stts = (timeToSampleAtom *)mp4malloc(sizeof(timeToSampleAtom))) == NULL)
2097 bytesread = readSTTS(handle, stbl->stts);
2100 totalbytesread += bytesread;
2106 if (stbl->ctts) /* CTTS has already been read, more than one is not allowed */
2109 if ((stbl->ctts = (compositionTimeToSampleAtom *)mp4malloc(sizeof(compositionTimeToSampleAtom))) == NULL)
2112 bytesread = readCTTS(handle, stbl->ctts);
2115 totalbytesread += bytesread;
2121 if (stbl->stss) /* STSS has already been read, more than one is not allowed */
2124 if ((stbl->stss = (syncSampleAtom *)mp4malloc(sizeof(syncSampleAtom))) == NULL)
2127 bytesread = readSTSS(handle, stbl->stss);
2130 totalbytesread += bytesread;
2136 if (stbl->stsd) /* STSD has already been read, more than one is not allowed */
2139 if ((stbl->stsd = (sampleDescriptionAtom *)mp4malloc(sizeof(sampleDescriptionAtom))) == NULL)
2142 bytesread = readSTSD(handle, stbl->stsd);
2145 totalbytesread += bytesread;
2151 if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */
2154 if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL)
2157 bytesread = readSTSZ(handle, stbl->stsz);
2160 totalbytesread += bytesread;
2166 if (stbl->stsz) /* STSZ or STZ2 has already been read, more than one is not allowed */
2169 if ((stbl->stsz = (sampleSizeAtom *)mp4malloc(sizeof(sampleSizeAtom))) == NULL)
2172 bytesread = readSTZ2(handle, stbl->stsz);
2175 totalbytesread += bytesread;
2181 if (stbl->stsc) /* STSC has already been read, more than one is not allowed */
2184 if ((stbl->stsc = (sampleToChunkAtom *)mp4malloc(sizeof(sampleToChunkAtom))) == NULL)
2187 bytesread = readSTSC(handle, stbl->stsc);
2190 totalbytesread += bytesread;
2196 if (stbl->stco) /* STCO or CO64 has already been read, more than one is not allowed */
2199 if ((stbl->stco = (chunkOffsetAtom *)mp4malloc(sizeof(chunkOffsetAtom))) == NULL)
2202 stbl->is32BitOffsets = ETrue;
2203 bytesread = readSTCO(handle, stbl->stco);
2206 totalbytesread += bytesread;
2212 if (stbl->stco64) /* STCO or CO64 has already been read, more than one is not allowed */
2215 if ((stbl->stco64 = (chunkOffset64Atom *)mp4malloc(sizeof(chunkOffset64Atom))) == NULL)
2218 stbl->is32BitOffsets = EFalse;
2219 bytesread = readCO64(handle, stbl->stco64);
2222 totalbytesread += bytesread;
2227 if (stbl->sdtp) /* SDTP has already been read, more than one is not allowed */
2230 if ((stbl->sdtp = (sampleDependencyAtom *)mp4malloc(sizeof(sampleDependencyAtom))) == NULL)
2238 // sample_count of SDTP is taken from the sample_count in the Sample Size Box ('stsz') or
2239 // Compact Sample Size Box (‘stz2’).
2240 bytesread = readSDTP(handle, stbl->sdtp, stbl->stsz->sampleCount);
2244 totalbytesread += bytesread;
2247 default: /* Other atoms are not needed */
2249 bytesread = readUnknown(handle);
2252 totalbytesread += bytesread;
2258 return totalbytesread;
2265 * mp4_i32 readSTTS(MP4HandleImp handle,
2266 * timeToSampleAtom *stts)
2270 * This function parses one STTS atom.
2274 * handle MP4 library handle
2279 * Negative integer Error
2280 * >= 0 Success. Value tells how many bytes were read.
2283 mp4_i32 readSTTS(MP4HandleImp handle, timeToSampleAtom *stts)
2286 mp4_i32 totalbytesread = 0;
2290 if ((stts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2293 bytesread = readFullAtomHeader(handle, stts->atomhdr);
2296 totalbytesread += bytesread;
2298 if (stts->atomhdr->type != ATOMTYPE_STTS)
2302 bytesread = readData(handle, handle->buf, 4);
2305 stts->entryCount = u32endian(*((mp4_u32 *)handle->buf));
2306 totalbytesread += bytesread;
2308 if ( stts->entryCount )
2310 stts->sampleCount = (mp4_u32 *)mp4malloc(stts->entryCount * sizeof(mp4_u32));
2311 if (stts->sampleCount == NULL)
2313 stts->sampleDelta = (mp4_i32 *)mp4malloc(stts->entryCount * sizeof(mp4_i32));
2314 if (stts->sampleDelta == NULL)
2317 for (i = 0; i < stts->entryCount; i++)
2319 bytesread = readData(handle, handle->buf, 8);
2323 stts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf));
2324 stts->sampleDelta[i] = i32endian(*((mp4_i32 *)(handle->buf+4)));
2326 totalbytesread += bytesread;
2330 return totalbytesread;
2337 * mp4_i32 readCTTS(MP4HandleImp handle,
2338 * compositionTimeToSampleAtom *ctts)
2342 * This function parses one CTTS atom.
2346 * handle MP4 library handle
2351 * Negative integer Error
2352 * >= 0 Success. Value tells how many bytes were read.
2355 mp4_i32 readCTTS(MP4HandleImp handle, compositionTimeToSampleAtom *ctts)
2358 mp4_i32 totalbytesread = 0;
2362 if ((ctts->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2365 bytesread = readFullAtomHeader(handle, ctts->atomhdr);
2368 totalbytesread += bytesread;
2370 if (ctts->atomhdr->type != ATOMTYPE_CTTS)
2373 bytesread = readData(handle, handle->buf, 4);
2376 ctts->entryCount = u32endian(*((mp4_u32 *)handle->buf));
2377 totalbytesread += bytesread;
2379 if ( ctts->entryCount )
2381 ctts->sampleCount = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32));
2382 if (ctts->sampleCount == NULL)
2384 ctts->sampleOffset = (mp4_u32 *)mp4malloc(ctts->entryCount * sizeof(mp4_u32));
2385 if (ctts->sampleOffset == NULL)
2388 for (i = 0; i < ctts->entryCount; i++)
2390 bytesread = readData(handle, handle->buf, 8);
2394 ctts->sampleCount[i] = u32endian(*((mp4_u32 *)handle->buf));
2395 ctts->sampleOffset[i] = u32endian(*((mp4_u32 *)(handle->buf+4)));
2397 totalbytesread += bytesread;
2400 return totalbytesread;
2407 * mp4_i32 readSTSS(MP4HandleImp handle,
2408 * syncSampleAtom *stss)
2412 * This function parses one STSS atom.
2416 * handle MP4 library handle
2421 * Negative integer Error
2422 * >= 0 Success. Value tells how many bytes were read.
2425 mp4_i32 readSTSS(MP4HandleImp handle, syncSampleAtom *stss)
2428 mp4_i32 totalbytesread = 0;
2432 if ((stss->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2435 bytesread = readFullAtomHeader(handle, stss->atomhdr);
2438 totalbytesread += bytesread;
2440 if (stss->atomhdr->type != ATOMTYPE_STSS)
2444 bytesread = readData(handle, handle->buf, 4);
2447 stss->entryCount = u32endian(*((mp4_u32 *)handle->buf));
2448 totalbytesread += bytesread;
2450 if ( stss->entryCount )
2452 stss->sampleNumber = (mp4_u32 *)mp4malloc(stss->entryCount * sizeof(mp4_u32));
2453 if (stss->sampleNumber == NULL)
2456 for (i = 0; i < stss->entryCount; i++)
2458 bytesread = readData(handle, handle->buf, 4);
2462 stss->sampleNumber[i] = u32endian(*((mp4_u32 *)handle->buf));
2464 totalbytesread += bytesread;
2468 return totalbytesread;
2475 * mp4_i32 readSTSD(MP4HandleImp handle,
2476 * sampleDescriptionAtom *stsd)
2480 * This function parses one STSD atom.
2484 * handle MP4 library handle
2489 * Negative integer Error
2490 * >= 0 Success. Value tells how many bytes were read.
2493 mp4_i32 readSTSD(MP4HandleImp handle, sampleDescriptionAtom *stsd)
2496 mp4_i32 totalbytesread = 0;
2497 mp4_u32 totalsampleentriesread = 0;
2498 mp4_u32 unknownsampleentriesread = 0;
2499 mp4_bool skipentries = 0;
2501 if ((stsd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2503 // for memory cleanup set entrycount to allocated num of entries.
2504 stsd->entryCount = totalsampleentriesread;
2508 bytesread = readFullAtomHeader(handle, stsd->atomhdr);
2511 // for memory cleanup set entrycount to allocated num of entries.
2512 stsd->entryCount = totalsampleentriesread;
2515 totalbytesread += bytesread;
2517 if (stsd->atomhdr->type != ATOMTYPE_STSD)
2519 // for memory cleanup set entrycount to allocated num of entries.
2520 stsd->entryCount = totalsampleentriesread;
2524 bytesread = readData(handle, handle->buf, 4);
2527 // for memory cleanup set entrycount to allocated num of entries.
2528 stsd->entryCount = totalsampleentriesread;
2531 stsd->entryCount = u32endian(*((mp4_u32 *)handle->buf));
2532 totalbytesread += bytesread;
2535 while ((mp4_u32)totalbytesread < stsd->atomhdr->size)
2537 // if the number of entries read already surpasses the number of entries specified
2538 // within the STSD atom, the file is corrupted.
2539 if ((totalsampleentriesread + unknownsampleentriesread) >= stsd->entryCount)
2541 // for memory cleanup set entrycount to allocated num of entries.
2542 stsd->entryCount = totalsampleentriesread;
2546 // read the next sample type
2547 if (peekData(handle, handle->buf, 8) < 0)
2549 // for memory cleanup set entrycount to allocated num of entries.
2550 stsd->entryCount = totalsampleentriesread;
2553 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
2555 // if the max sample entiries supported by the library has been reached
2556 if ((stsd->entryCount > STSDMAXSAMPLEENTRYCOUNT) && (totalsampleentriesread == STSDMAXSAMPLEENTRYCOUNT))
2558 // skip reading the rest of the entries to make sure no more than max count of sample entries
2559 // will be processed, so that cleanup will always work.
2568 if (stsd->mp4v[totalsampleentriesread]) /* MP4V[totalsampleentriesread] has already been read, more than one is not allowed */
2570 // for memory cleanup set entrycount to allocated num of entries.
2571 stsd->entryCount = totalsampleentriesread;
2575 if ((stsd->mp4v[totalsampleentriesread] = (visualSampleEntry *)mp4malloc(sizeof(visualSampleEntry))) == NULL)
2577 // for memory cleanup set entrycount to allocated num of entries.
2578 stsd->entryCount = totalsampleentriesread;
2582 bytesread = readMP4V(handle, stsd->mp4v[totalsampleentriesread]);
2583 totalsampleentriesread++;
2586 // for memory cleanup set entrycount to allocated num of entries.
2587 stsd->entryCount = totalsampleentriesread;
2590 totalbytesread += bytesread;
2596 if (stsd->mp4a[totalsampleentriesread]) /* MP4A[totalsampleentriesread] has already been read, more than one is not allowed */
2598 // for memory cleanup set entrycount to allocated num of entries.
2599 stsd->entryCount = totalsampleentriesread;
2603 if ((stsd->mp4a[totalsampleentriesread] = (audioSampleEntry *)mp4malloc(sizeof(audioSampleEntry))) == NULL)
2605 // for memory cleanup set entrycount to allocated num of entries.
2606 stsd->entryCount = totalsampleentriesread;
2610 bytesread = readMP4A(handle, stsd->mp4a[totalsampleentriesread]);
2611 totalsampleentriesread++;
2614 // for memory cleanup set entrycount to allocated num of entries.
2615 stsd->entryCount = totalsampleentriesread;
2618 totalbytesread += bytesread;
2624 if (stsd->mp4s[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */
2626 // for memory cleanup set entrycount to allocated num of entries.
2627 stsd->entryCount = totalsampleentriesread;
2631 if ((stsd->mp4s[totalsampleentriesread] = (mpegSampleEntry *)mp4malloc(sizeof(mpegSampleEntry))) == NULL)
2633 // for memory cleanup set entrycount to allocated num of entries.
2634 stsd->entryCount = totalsampleentriesread;
2638 bytesread = readMP4S(handle, stsd->mp4s[totalsampleentriesread]);
2639 totalsampleentriesread++;
2642 // for memory cleanup set entrycount to allocated num of entries.
2643 stsd->entryCount = totalsampleentriesread;
2646 totalbytesread += bytesread;
2652 if (stsd->s263[totalsampleentriesread]) /* MP4S has already been read, more than one is not allowed */
2654 // for memory cleanup set entrycount to allocated num of entries.
2655 stsd->entryCount = totalsampleentriesread;
2659 if ((stsd->s263[totalsampleentriesread] = (h263SampleEntry *)mp4malloc(sizeof(h263SampleEntry))) == NULL)
2661 // for memory cleanup set entrycount to allocated num of entries.
2662 stsd->entryCount = totalsampleentriesread;
2666 bytesread = readS263(handle, stsd->s263[totalsampleentriesread]);
2667 totalsampleentriesread++;
2670 // for memory cleanup set entrycount to allocated num of entries.
2671 stsd->entryCount = totalsampleentriesread;
2674 totalbytesread += bytesread;
2680 if (stsd->samr[totalsampleentriesread]) /* SAMR has already been read, more than one is not allowed */
2682 // for memory cleanup set entrycount to allocated num of entries.
2683 stsd->entryCount = totalsampleentriesread;
2687 if ((stsd->samr[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL)
2689 // for memory cleanup set entrycount to allocated num of entries.
2690 stsd->entryCount = totalsampleentriesread;
2694 bytesread = readSAMR(handle, stsd->samr[totalsampleentriesread]);
2695 totalsampleentriesread++;
2698 // for memory cleanup set entrycount to allocated num of entries.
2699 stsd->entryCount = totalsampleentriesread;
2702 totalbytesread += bytesread;
2708 if (stsd->sawb[totalsampleentriesread]) /* SAWB has already been read, more than one is not allowed */
2710 // for memory cleanup set entrycount to allocated num of entries.
2711 stsd->entryCount = totalsampleentriesread;
2715 if ((stsd->sawb[totalsampleentriesread] = (amrSampleEntry *)mp4malloc(sizeof(amrSampleEntry))) == NULL)
2717 // for memory cleanup set entrycount to allocated num of entries.
2718 stsd->entryCount = totalsampleentriesread;
2722 bytesread = readSAWB(handle, stsd->sawb[totalsampleentriesread]);
2723 totalsampleentriesread++;
2726 // for memory cleanup set entrycount to allocated num of entries.
2727 stsd->entryCount = totalsampleentriesread;
2730 totalbytesread += bytesread;
2736 if (stsd->avc1[totalsampleentriesread]) /* AVC1 has already been read, more than one is not allowed */
2738 // for memory cleanup set entrycount to allocated num of entries.
2739 stsd->entryCount = totalsampleentriesread;
2742 if ((stsd->avc1[totalsampleentriesread] = (avcSampleEntry *)mp4malloc(sizeof(avcSampleEntry))) == NULL)
2744 // for memory cleanup set entrycount to allocated num of entries.
2745 stsd->entryCount = totalsampleentriesread;
2749 bytesread = readAVC1(handle, stsd->avc1[totalsampleentriesread]);
2750 totalsampleentriesread++;
2753 // for memory cleanup set entrycount to allocated num of entries.
2754 stsd->entryCount = totalsampleentriesread;
2757 totalbytesread += bytesread;
2763 if (stsd->sqcp[totalsampleentriesread]) /* SQCP has already been read, more than one is not allowed */
2765 // for memory cleanup set entrycount to allocated num of entries.
2766 stsd->entryCount = totalsampleentriesread;
2769 if ((stsd->sqcp[totalsampleentriesread] = (qcelpSampleEntry *)mp4malloc(sizeof(qcelpSampleEntry))) == NULL)
2771 // for memory cleanup set entrycount to allocated num of entries.
2772 stsd->entryCount = totalsampleentriesread;
2776 bytesread = readSQCP(handle, stsd->sqcp[totalsampleentriesread]);
2777 totalsampleentriesread++;
2780 // for memory cleanup set entrycount to allocated num of entries.
2781 stsd->entryCount = totalsampleentriesread;
2784 totalbytesread += bytesread;
2788 default: /* Other atoms are not needed */
2789 // no need to increment totalsampleentriesread as no memory is allocated for unsupported
2790 // or unrecognized sample types. Alternatively, increment the count of unknown samples.
2791 // This is for ensure if a non-audio/video track can properly be parsed without being
2792 // recongized as an invalid format file.
2793 unknownsampleentriesread++;
2794 bytesread = readUnknown(handle);
2797 // for memory cleanup set entrycount to allocated num of entries.
2798 stsd->entryCount = totalsampleentriesread;
2801 totalbytesread += bytesread;
2806 // if the STSD atom's entry count is NOT the same as the number (supported & unsupported) entries parsed,
2807 // the atom is likely a corrupted one.
2808 if ((totalsampleentriesread + unknownsampleentriesread) != stsd->entryCount)
2810 // for memory cleanup set entrycount to allocated num of entries.
2811 stsd->entryCount = totalsampleentriesread;
2816 // if the STSD atom's entry count is the same as the number of (supported & unsupported) entries
2817 // parsed, check if some entries are skipped because the max sample entry count has been reached
2820 // if STSDMAXSAMPLEENTRYCOUNT was reached edit entrycount to make sure cleanup works.
2821 stsd->entryCount = STSDMAXSAMPLEENTRYCOUNT;
2823 else if (unknownsampleentriesread > 0)
2825 // unknown (unsupported) sample entries present, set the STSD entry count to the actual
2826 // number of supported sample entries detected
2827 stsd->entryCount = totalsampleentriesread;
2831 return totalbytesread;
2838 * mp4_i32 readSTSZ(MP4HandleImp handle,
2839 * sampleSizeAtom *stsz)
2843 * This function parses one STSZ atom.
2847 * handle MP4 library handle
2852 * Negative integer Error
2853 * >= 0 Success. Value tells how many bytes were read.
2856 mp4_i32 readSTSZ(MP4HandleImp handle, sampleSizeAtom *stsz)
2859 mp4_i32 totalbytesread = 0;
2862 if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2865 bytesread = readFullAtomHeader(handle, stsz->atomhdr);
2868 totalbytesread += bytesread;
2870 if (stsz->atomhdr->type != ATOMTYPE_STSZ)
2874 bytesread = readData(handle, handle->buf, 4);
2877 stsz->sampleSize = u32endian(*((mp4_u32 *)handle->buf));
2878 totalbytesread += bytesread;
2880 bytesread = readData(handle, handle->buf, 4);
2883 stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf));
2884 totalbytesread += bytesread;
2886 // zero size samplesize means samples have different sizes, and those sizes are stored in sampleSizeEntries.
2887 if ((stsz->sampleCount) && (stsz->sampleSize == 0))
2891 // check validity of stsz->sampleCount before allocating entrysize table.
2892 if ( handle->moov->mvhd )
2894 if ( handle->moov->mvhd->timeScale > 0 )
2896 TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND;
2897 TUint maxSampleCount;
2899 if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration
2901 maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec;
2903 else // 32bit duration
2905 maxSampleCount = TUint((TUint( handle->moov->mvhd->duration ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec;
2908 if ( maxSampleCount < stsz->sampleCount )
2916 // allocate stsz->entrySize table
2917 stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
2918 if (stsz->entrySize == NULL)
2921 for (i = 0; i < stsz->sampleCount; i++)
2923 bytesread = readData(handle, handle->buf, 4);
2927 stsz->entrySize[i] = u32endian(*((mp4_u32 *)handle->buf));
2929 totalbytesread += bytesread;
2933 return totalbytesread;
2940 * mp4_i32 readSTZ2(MP4HandleImp handle,
2941 * sampleSizeAtom *stsz)
2945 * This function parses one STZ2 atom.
2947 * The result is placed in STSZ structure.
2951 * handle MP4 library handle
2956 * Negative integer Error
2957 * >= 0 Success. Value tells how many bytes were read.
2960 mp4_i32 readSTZ2(MP4HandleImp handle, sampleSizeAtom *stsz)
2963 mp4_i32 totalbytesread = 0;
2967 if ((stsz->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
2970 bytesread = readFullAtomHeader(handle, stsz->atomhdr);
2973 totalbytesread += bytesread;
2975 if (stsz->atomhdr->type != ATOMTYPE_STZ2)
2979 bytesread = discardData(handle, 3);
2982 totalbytesread += bytesread;
2984 bytesread = readData(handle, handle->buf, 1);
2987 fieldsize = handle->buf[0];
2988 totalbytesread += bytesread;
2990 bytesread = readData(handle, handle->buf, 4);
2993 stsz->sampleCount = u32endian(*((mp4_u32 *)handle->buf));
2994 totalbytesread += bytesread;
2998 case 4: /* Two entries in each byte */
3003 stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
3004 if (stsz->entrySize == NULL)
3007 for (i = 0; i < (stsz->sampleCount + 1) / 2; i++)
3009 bytesread = readData(handle, handle->buf, 1);
3013 totalbytesread += bytesread;
3015 stsz->entrySize[i * 2] = (mp4_u32)(handle->buf[0] >> 4);
3017 if (stsz->sampleCount % 2 == 0) /* Even number of samples */
3019 stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f);
3023 /* This condition is needed to avoid writing after the table */
3025 if (i == (stsz->sampleCount + 1) / 2 - 1) /* Last sample */
3029 stsz->entrySize[i * 2 + 1] = (mp4_u32)(handle->buf[0] & 0x0f);
3035 case 8: /* One entry for each byte */
3040 stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
3041 if (stsz->entrySize == NULL)
3044 for (i = 0; i < stsz->sampleCount; i++)
3046 bytesread = readData(handle, handle->buf, 1);
3050 stsz->entrySize[i] = (mp4_u32)handle->buf[0];
3052 totalbytesread += bytesread;
3058 case 16: /* Each entry in 2 bytes */
3063 stsz->entrySize = (mp4_u32 *)mp4malloc(stsz->sampleCount * sizeof(mp4_u32));
3064 if (stsz->entrySize == NULL)
3067 for (i = 0; i < stsz->sampleCount; i++)
3069 bytesread = readData(handle, handle->buf, 2);
3073 stsz->entrySize[i] = (mp4_u32)u16endian(*((mp4_u16 *)handle->buf));
3075 totalbytesread += bytesread;
3081 default: /* Illegal fieldsize */
3087 return totalbytesread;
3094 * mp4_i32 readSTSC(MP4HandleImp handle,
3095 * sampleToChunkAtom *stsc)
3099 * This function parses one STSC atom.
3103 * handle MP4 library handle
3108 * Negative integer Error
3109 * >= 0 Success. Value tells how many bytes were read.
3112 mp4_i32 readSTSC(MP4HandleImp handle, sampleToChunkAtom *stsc)
3115 mp4_i32 totalbytesread = 0;
3119 if ((stsc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3122 bytesread = readFullAtomHeader(handle, stsc->atomhdr);
3125 totalbytesread += bytesread;
3127 if (stsc->atomhdr->type != ATOMTYPE_STSC)
3131 bytesread = readData(handle, handle->buf, 4);
3134 stsc->entryCount = u32endian(*((mp4_u32 *)handle->buf));
3135 totalbytesread += bytesread;
3137 if (stsc->entryCount)
3139 stsc->firstChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
3140 if (stsc->firstChunk == NULL)
3142 stsc->samplesPerChunk = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
3143 if (stsc->samplesPerChunk == NULL)
3145 stsc->sampleDescriptionIndex = (mp4_u32 *)mp4malloc(stsc->entryCount * sizeof(mp4_u32));
3146 if (stsc->sampleDescriptionIndex == NULL)
3151 for (i = 0; i < stsc->entryCount; i++)
3153 bytesread = readData(handle, handle->buf, 12);
3157 stsc->firstChunk[i] = u32endian(*((mp4_u32 *)handle->buf));
3158 stsc->samplesPerChunk[i] = u32endian(*((mp4_u32 *)(handle->buf+4)));
3159 stsc->sampleDescriptionIndex[i] = u32endian(*((mp4_u32 *)(handle->buf+8)));
3160 if ( stsc->sampleDescriptionIndex[i] > stsc->entryCount)
3165 totalbytesread += bytesread;
3168 return totalbytesread;
3175 * mp4_i32 readSTCO(MP4HandleImp handle,
3176 * chunkOffsetAtom *stco)
3180 * This function parses one STCO atom.
3184 * handle MP4 library handle
3189 * Negative integer Error
3190 * >= 0 Success. Value tells how many bytes were read.
3193 mp4_i32 readSTCO(MP4HandleImp handle, chunkOffsetAtom *stco)
3196 mp4_i32 totalbytesread = 0;
3200 if ((stco->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3203 bytesread = readFullAtomHeader(handle, stco->atomhdr);
3206 totalbytesread += bytesread;
3208 if (stco->atomhdr->type != ATOMTYPE_STCO)
3212 bytesread = readData(handle, handle->buf, 4);
3215 stco->entryCount = u32endian(*((mp4_u32 *)handle->buf));
3216 totalbytesread += bytesread;
3218 if (stco->entryCount)
3220 // validate stco->entryCount before allocating chunkOffsetTable
3221 if ( handle->moov->mvhd )
3223 if ( handle->moov->mvhd->timeScale > 0 )
3225 TUint magicNumberMaxSamplesInSec = MAXSAMPLESPERSECOND;
3226 TUint maxSampleCount;
3228 if ( handle->moov->mvhd->atomhdr->version == 1 ) // 64bit duration
3230 maxSampleCount = I64INT(handle->moov->mvhd->duration64 / TUint(handle->moov->mvhd->timeScale) + 1) * magicNumberMaxSamplesInSec;
3232 else // 32bit duration
3234 maxSampleCount = TUint((TUint( handle->moov->mvhd->duration ) / TUint(handle->moov->mvhd->timeScale) + 1)) * magicNumberMaxSamplesInSec;
3237 if ( maxSampleCount < stco->entryCount )
3245 stco->chunkOffset = (mp4_u32 *)mp4malloc(stco->entryCount * sizeof(mp4_u32));
3246 if (stco->chunkOffset == NULL)
3249 for (i = 0; i < stco->entryCount; i++)
3251 bytesread = readData(handle, handle->buf, 4);
3255 stco->chunkOffset[i] = u32endian(*((mp4_u32 *)handle->buf));
3257 totalbytesread += bytesread;
3260 return totalbytesread;
3267 * mp4_i32 readCO64(MP4HandleImp handle,
3268 * chunkOffset64Atom *stco64)
3272 * This function parses one CO64 atom.
3276 * handle MP4 library handle
3277 * stco64 CO64 pointer
3281 * Negative integer Error
3282 * >= 0 Success. Value tells how many bytes were read.
3285 mp4_i32 readCO64(MP4HandleImp handle, chunkOffset64Atom *stco64)
3288 mp4_i32 totalbytesread = 0;
3292 if ((stco64->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3295 bytesread = readFullAtomHeader(handle, stco64->atomhdr);
3298 totalbytesread += bytesread;
3300 if (stco64->atomhdr->type != ATOMTYPE_CO64)
3304 bytesread = readData(handle, handle->buf, 4);
3307 stco64->entryCount = u32endian(*((mp4_u32 *)handle->buf));
3308 totalbytesread += bytesread;
3310 if ( stco64->entryCount )
3312 stco64->chunkOffset = (mp4_u64 *)mp4malloc(stco64->entryCount * sizeof(mp4_u64));
3313 if (stco64->chunkOffset == NULL)
3316 for (i = 0; i < stco64->entryCount; i++)
3318 bytesread = readData(handle, handle->buf, 8);
3322 stco64->chunkOffset[i] = u64endian(*((mp4_u64 *)(handle->buf)));
3324 totalbytesread += bytesread;
3327 return totalbytesread;
3334 * mp4_i32 readMP4V(MP4HandleImp handle,
3335 * visualSampleEntry *mp4v)
3339 * This function parses one MP4V atom.
3343 * handle MP4 library handle
3348 * Negative integer Error
3349 * >= 0 Success. Value tells how many bytes were read.
3352 mp4_i32 readMP4V(MP4HandleImp handle, visualSampleEntry *mp4v)
3355 mp4_i32 totalbytesread = 0;
3358 if ((mp4v->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3361 bytesread = readAtomHeader(handle, mp4v->atomhdr);
3364 totalbytesread += bytesread;
3366 if (mp4v->atomhdr->type != ATOMTYPE_MP4V)
3370 bytesread = discardData(handle, 6);
3373 totalbytesread += bytesread;
3375 bytesread = readData(handle, handle->buf, 2);
3378 mp4v->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
3379 totalbytesread += bytesread;
3381 bytesread = discardData(handle, 16);
3384 totalbytesread += bytesread;
3386 bytesread = readData(handle, handle->buf, 2);
3389 mp4v->width = u16endian(*((mp4_u16 *)handle->buf));
3390 totalbytesread += bytesread;
3392 bytesread = readData(handle, handle->buf, 2);
3395 mp4v->height = u16endian(*((mp4_u16 *)handle->buf));
3396 totalbytesread += bytesread;
3398 bytesread = discardData(handle, 50);
3401 totalbytesread += bytesread;
3403 if ((mp4v->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
3406 bytesread = readESD(handle, mp4v->esd);
3409 totalbytesread += bytesread;
3411 if ( totalbytesread < mp4v->atomhdr->size )
3413 bytesread = discardData(handle, mp4v->atomhdr->size - totalbytesread );
3418 totalbytesread += bytesread;
3421 return totalbytesread;
3428 * mp4_i32 readMP4A(MP4HandleImp handle,
3429 * audioSampleEntry *mp4a)
3433 * This function parses one MP4A atom.
3437 * handle MP4 library handle
3442 * Negative integer Error
3443 * >= 0 Success. Value tells how many bytes were read.
3446 mp4_i32 readMP4A(MP4HandleImp handle, audioSampleEntry *mp4a)
3449 mp4_i32 totalbytesread = 0;
3452 if ((mp4a->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3455 bytesread = readAtomHeader(handle, mp4a->atomhdr);
3458 totalbytesread += bytesread;
3460 if (mp4a->atomhdr->type != ATOMTYPE_MP4A)
3464 bytesread = discardData(handle, 6);
3467 totalbytesread += bytesread;
3469 bytesread = readData(handle, handle->buf, 2);
3472 mp4a->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
3473 totalbytesread += bytesread;
3475 bytesread = discardData(handle, 16);
3478 totalbytesread += bytesread;
3480 bytesread = readData(handle, handle->buf, 2);
3483 mp4a->timeScale = u16endian(*((mp4_u16 *)handle->buf));
3484 totalbytesread += bytesread;
3486 bytesread = discardData(handle, 2);
3489 totalbytesread += bytesread;
3491 if ((mp4a->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
3494 bytesread = readESD(handle, mp4a->esd);
3497 totalbytesread += bytesread;
3499 if ( totalbytesread < mp4a->atomhdr->size )
3501 bytesread = discardData(handle, mp4a->atomhdr->size - totalbytesread );
3506 totalbytesread += bytesread;
3509 return totalbytesread;
3516 * mp4_i32 readMP4S(MP4HandleImp handle,
3517 * mpegSampleEntry *mp4s)
3521 * This function parses one MP4S atom.
3525 * handle MP4 library handle
3530 * Negative integer Error
3531 * >= 0 Success. Value tells how many bytes were read.
3534 mp4_i32 readMP4S(MP4HandleImp handle, mpegSampleEntry *mp4s)
3537 mp4_i32 totalbytesread = 0;
3540 if ((mp4s->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3543 bytesread = readAtomHeader(handle, mp4s->atomhdr);
3546 totalbytesread += bytesread;
3548 if (mp4s->atomhdr->type != ATOMTYPE_MP4S)
3552 bytesread = discardData(handle, 6);
3555 totalbytesread += bytesread;
3557 bytesread = readData(handle, handle->buf, 2);
3560 mp4s->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
3561 totalbytesread += bytesread;
3563 if ((mp4s->esd = (ESDAtom *)mp4malloc(sizeof(ESDAtom))) == NULL)
3566 bytesread = readESD(handle, mp4s->esd);
3569 totalbytesread += bytesread;
3571 if ( totalbytesread < mp4s->atomhdr->size )
3573 bytesread = discardData(handle, mp4s->atomhdr->size - totalbytesread );
3578 totalbytesread += bytesread;
3581 return totalbytesread;
3588 * mp4_i32 readS263(MP4HandleImp handle,
3589 * h263SampleEntry *s263)
3593 * This function parses one S263 atom.
3597 * handle MP4 library handle
3602 * Negative integer Error
3603 * >= 0 Success. Value tells how many bytes were read.
3606 mp4_i32 readS263(MP4HandleImp handle, h263SampleEntry *s263)
3609 mp4_i32 totalbytesread = 0;
3612 if ((s263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3615 bytesread = readAtomHeader(handle, s263->atomhdr);
3618 totalbytesread += bytesread;
3620 if (s263->atomhdr->type != ATOMTYPE_S263)
3624 bytesread = discardData(handle, 6);
3627 totalbytesread += bytesread;
3629 bytesread = readData(handle, handle->buf, 2);
3632 s263->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
3633 totalbytesread += bytesread;
3635 bytesread = discardData(handle, 16);
3638 totalbytesread += bytesread;
3640 bytesread = readData(handle, handle->buf, 2);
3643 s263->width = u16endian(*((mp4_u16 *)handle->buf));
3644 totalbytesread += bytesread;
3646 bytesread = readData(handle, handle->buf, 2);
3649 s263->height = u16endian(*((mp4_u16 *)handle->buf));
3650 totalbytesread += bytesread;
3652 bytesread = discardData(handle, 50);
3655 totalbytesread += bytesread;
3657 if ((s263->d263 = (h263SpecificAtom *)mp4malloc(sizeof(h263SpecificAtom))) == NULL)
3660 bytesread = readD263(handle, s263->d263);
3663 totalbytesread += bytesread;
3665 if ( totalbytesread < s263->atomhdr->size )
3667 bytesread = discardData(handle, s263->atomhdr->size - totalbytesread );
3672 totalbytesread += bytesread;
3675 return totalbytesread;
3682 * mp4_i32 readSAMR(MP4HandleImp handle,
3683 * amrSampleEntry *samr)
3687 * This function parses one SAMR atom.
3691 * handle MP4 library handle
3696 * Negative integer Error
3697 * >= 0 Success. Value tells how many bytes were read.
3700 mp4_i32 readSAMR(MP4HandleImp handle, amrSampleEntry *samr)
3703 mp4_i32 totalbytesread = 0;
3706 if ((samr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3709 bytesread = readAtomHeader(handle, samr->atomhdr);
3712 totalbytesread += bytesread;
3714 if (samr->atomhdr->type != ATOMTYPE_SAMR)
3718 bytesread = discardData(handle, 6);
3721 totalbytesread += bytesread;
3723 bytesread = readData(handle, handle->buf, 2);
3726 samr->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
3727 totalbytesread += bytesread;
3729 bytesread = discardData(handle, 16);
3732 totalbytesread += bytesread;
3734 bytesread = readData(handle, handle->buf, 2);
3737 samr->timeScale = u16endian(*((mp4_u16 *)handle->buf));
3738 totalbytesread += bytesread;
3740 bytesread = discardData(handle, 2);
3743 totalbytesread += bytesread;
3745 if ((samr->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL)
3748 bytesread = readDAMR(handle, samr->damr);
3751 totalbytesread += bytesread;
3753 if ( totalbytesread < samr->atomhdr->size )
3755 bytesread = discardData(handle, samr->atomhdr->size - totalbytesread );
3760 totalbytesread += bytesread;
3763 return totalbytesread;
3770 * mp4_i32 readSAWB(MP4HandleImp handle,
3771 * amrSampleEntry *sawb)
3775 * This function parses one SAWB atom.
3779 * handle MP4 library handle
3784 * Negative integer Error
3785 * >= 0 Success. Value tells how many bytes were read.
3788 mp4_i32 readSAWB(MP4HandleImp handle, amrSampleEntry *sawb)
3791 mp4_i32 totalbytesread = 0;
3794 if ((sawb->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3797 bytesread = readAtomHeader(handle, sawb->atomhdr);
3800 totalbytesread += bytesread;
3802 if (sawb->atomhdr->type != ATOMTYPE_SAWB)
3806 bytesread = discardData(handle, 6);
3809 totalbytesread += bytesread;
3811 bytesread = readData(handle, handle->buf, 2);
3814 sawb->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
3815 totalbytesread += bytesread;
3817 bytesread = discardData(handle, 16);
3820 totalbytesread += bytesread;
3822 bytesread = readData(handle, handle->buf, 2);
3825 sawb->timeScale = u16endian(*((mp4_u16 *)handle->buf));
3826 totalbytesread += bytesread;
3828 bytesread = discardData(handle, 2);
3831 totalbytesread += bytesread;
3833 if ((sawb->damr = (amrDecSpecStruc *)mp4malloc(sizeof(amrDecSpecStruc))) == NULL)
3836 bytesread = readDAMR(handle, sawb->damr);
3839 totalbytesread += bytesread;
3841 if ( totalbytesread < sawb->atomhdr->size )
3843 bytesread = discardData(handle, sawb->atomhdr->size - totalbytesread );
3848 totalbytesread += bytesread;
3851 return totalbytesread;
3858 * mp4_i32 readESD(MP4HandleImp handle,
3863 * This function parses one ESD atom.
3867 * handle MP4 library handle
3872 * Negative integer Error
3873 * >= 0 Success. Value tells how many bytes were read.
3876 mp4_i32 readESD(MP4HandleImp handle, ESDAtom *esd)
3879 mp4_i32 totalbytesread = 0;
3880 mp4_i32 decConfDescrBytesRead = 0;
3883 if ((esd->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
3886 bytesread = readFullAtomHeader(handle, esd->atomhdr);
3889 totalbytesread += bytesread;
3891 if (esd->atomhdr->type != ATOMTYPE_ESD)
3895 bytesread = readData(handle, handle->buf, 1);
3898 esd->esDescrTag = handle->buf[0];
3899 totalbytesread += bytesread;
3900 if (esd->esDescrTag != 3) /* ES_DescrTag == 3 */
3908 bytesread = readData(handle, handle->buf, 1);
3911 c = (mp4_u8)(handle->buf[0] & 0x7f);
3912 esd->size = (esd->size << 7) | c;
3913 totalbytesread += bytesread;
3915 while (handle->buf[0] & 0x80);
3917 bytesread = readData(handle, handle->buf, 2);
3920 esd->ESID = u16endian(*((mp4_u16 *)handle->buf));
3921 totalbytesread += bytesread;
3923 bytesread = readData(handle, handle->buf, 1);
3926 esd->flags = handle->buf[0];
3927 totalbytesread += bytesread;
3929 if (esd->flags & 0x80) /* Stream Dependence flag has been set */
3931 bytesread = readData(handle, handle->buf, 2);
3934 esd->dependsOnESID = u16endian(*((mp4_u16 *)handle->buf));
3935 totalbytesread += bytesread;
3938 if (esd->flags & 0x40) /* URL flag has been set */
3940 bytesread = readData(handle, handle->buf, 1);
3943 esd->URLLength = handle->buf[0];
3944 totalbytesread += bytesread;
3946 bytesread = discardData(handle, esd->URLLength);
3949 totalbytesread += bytesread;
3952 if (esd->flags & 0x20) /* OCR stream flag has been set */
3954 bytesread = readData(handle, handle->buf, 2);
3957 esd->OCRESID = u16endian(*((mp4_u16 *)handle->buf));
3958 totalbytesread += bytesread;
3961 bytesread = readData(handle, handle->buf, 1);
3964 esd->decConfDescrTag = handle->buf[0];
3965 totalbytesread += bytesread;
3966 if (esd->decConfDescrTag != 4) /* DecoderConfigDescrTag == 4 */
3969 esd->decConfDescrSize = 0;
3974 bytesread = readData(handle, handle->buf, 1);
3977 c = (mp4_u8)(handle->buf[0] & 0x7f);
3978 esd->decConfDescrSize = (esd->decConfDescrSize << 7) | c;
3979 totalbytesread += bytesread;
3981 while (handle->buf[0] & 0x80);
3983 bytesread = readData(handle, handle->buf, 1);
3986 esd->objectTypeIndication = handle->buf[0];
3987 totalbytesread += bytesread;
3988 decConfDescrBytesRead += bytesread;
3990 bytesread = readData(handle, handle->buf, 1);
3993 esd->stream = handle->buf[0];
3994 totalbytesread += bytesread;
3995 decConfDescrBytesRead += bytesread;
3997 bytesread = readData(handle, handle->buf, 3);
4000 esd->bufferSizeDB = ((mp4_u32)handle->buf[0]) << 16 |
4001 ((mp4_u32)handle->buf[1]) << 8 |
4002 ((mp4_u32)handle->buf[2]);
4003 totalbytesread += bytesread;
4004 decConfDescrBytesRead += bytesread;
4006 bytesread = readData(handle, handle->buf, 4);
4009 esd->maxBitrate = u32endian(*((mp4_u32 *)handle->buf));
4010 totalbytesread += bytesread;
4011 decConfDescrBytesRead += bytesread;
4013 bytesread = readData(handle, handle->buf, 4);
4016 esd->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
4017 totalbytesread += bytesread;
4018 decConfDescrBytesRead += bytesread;
4020 if ((mp4_u32)decConfDescrBytesRead < esd->decConfDescrSize)
4022 bytesread = readData(handle, handle->buf, 1);
4025 esd->decSpecificInfoTag = handle->buf[0];
4026 totalbytesread += bytesread;
4027 decConfDescrBytesRead += bytesread;
4028 if (esd->decSpecificInfoTag != 5) /* DecSpecificInfoTag == 5 */
4030 bytesread = discardData(handle, esd->decConfDescrSize - decConfDescrBytesRead);
4033 totalbytesread += bytesread;
4037 esd->decSpecificInfoSize = 0;
4042 bytesread = readData(handle, handle->buf, 1);
4045 c = (mp4_u8)(handle->buf[0] & 0x7f);
4046 esd->decSpecificInfoSize = (esd->decSpecificInfoSize << 7) | c;
4047 totalbytesread += bytesread;
4049 while (handle->buf[0] & 0x80);
4051 if(esd->decSpecificInfoSize)
4053 if ((esd->decSpecificInfo = (mp4_u8 *)mp4malloc(esd->decSpecificInfoSize)) == NULL)
4056 bytesread = readData(handle, esd->decSpecificInfo, esd->decSpecificInfoSize);
4059 totalbytesread += bytesread;
4064 bytesread = discardData(handle, esd->atomhdr->size - totalbytesread);
4067 totalbytesread += bytesread;
4069 return totalbytesread;
4076 * mp4_i32 readD263(MP4HandleImp handle,
4077 * h263SpecificAtom *d263)
4081 * This function parses one D263 atom.
4085 * handle MP4 library handle
4090 * Negative integer Error
4091 * >= 0 Success. Value tells how many bytes were read.
4094 mp4_i32 readD263(MP4HandleImp handle, h263SpecificAtom *d263)
4097 mp4_i32 totalbytesread = 0;
4100 if ((d263->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
4103 bytesread = readAtomHeader(handle, d263->atomhdr);
4106 totalbytesread += bytesread;
4108 if (d263->atomhdr->type != ATOMTYPE_D263)
4112 bytesread = readData(handle, handle->buf, 4);
4115 d263->vendor = u32endian(*((mp4_u32 *)handle->buf));
4116 totalbytesread += bytesread;
4118 bytesread = readData(handle, handle->buf, 1);
4121 d263->decoderVersion = handle->buf[0];
4122 totalbytesread += bytesread;
4124 bytesread = readData(handle, handle->buf, 1);
4127 d263->h263Level = handle->buf[0];
4128 totalbytesread += bytesread;
4130 bytesread = readData(handle, handle->buf, 1);
4133 d263->h263Profile = handle->buf[0];
4134 totalbytesread += bytesread;
4136 /* Check for the bitrate atom */
4138 while ((mp4_u32)totalbytesread < d263->atomhdr->size)
4143 if (peekData(handle, handle->buf, 8) < 0)
4146 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
4152 if (d263->bitr) /* BITR has already been read, more than one is not allowed */
4155 if ((d263->bitr = (bitrateAtom *)mp4malloc(sizeof(bitrateAtom))) == NULL)
4158 bytesread = readBITR(handle, d263->bitr);
4161 totalbytesread += bytesread;
4165 default: /* Other atoms are not needed */
4167 bytesread = readUnknown(handle);
4170 totalbytesread += bytesread;
4176 return totalbytesread;
4183 * mp4_i32 readBITR(MP4HandleImp handle,
4184 * bitrateAtom *d263)
4188 * This function parses one BITR atom.
4192 * handle MP4 library handle
4197 * Negative integer Error
4198 * >= 0 Success. Value tells how many bytes were read.
4201 mp4_i32 readBITR(MP4HandleImp handle, bitrateAtom *bitr)
4204 mp4_i32 totalbytesread = 0;
4207 if ((bitr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
4210 bytesread = readAtomHeader(handle, bitr->atomhdr);
4213 totalbytesread += bytesread;
4215 if (bitr->atomhdr->type != ATOMTYPE_BITR)
4219 bytesread = readData(handle, handle->buf, 4);
4222 bitr->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
4223 totalbytesread += bytesread;
4225 bytesread = readData(handle, handle->buf, 4);
4228 bitr->maxBitrate = u32endian(*((mp4_u32 *)handle->buf));
4229 totalbytesread += bytesread;
4231 return totalbytesread;
4238 * mp4_i32 readDAMR(MP4HandleImp handle,
4239 * amrDecSpecStruc *damr)
4243 * This function parses one DAMR atom.
4247 * handle MP4 library handle
4252 * Negative integer Error
4253 * >= 0 Success. Value tells how many bytes were read.
4256 mp4_i32 readDAMR(MP4HandleImp handle, amrDecSpecStruc *damr)
4259 mp4_i32 totalbytesread = 0;
4262 if ((damr->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
4265 bytesread = readAtomHeader(handle, damr->atomhdr);
4268 totalbytesread += bytesread;
4270 if (damr->atomhdr->type != ATOMTYPE_DAMR)
4274 bytesread = readData(handle, handle->buf, 4);
4277 damr->vendor = u32endian(*((mp4_u32 *)handle->buf));
4278 totalbytesread += bytesread;
4280 bytesread = readData(handle, handle->buf, 1);
4283 damr->decoderVersion = handle->buf[0];
4284 totalbytesread += bytesread;
4286 bytesread = readData(handle, handle->buf, 2);
4289 damr->modeSet = u16endian(*((mp4_u16 *)handle->buf));
4290 totalbytesread += bytesread;
4292 bytesread = readData(handle, handle->buf, 1);
4295 damr->modeChangePeriod = handle->buf[0];
4296 totalbytesread += bytesread;
4298 bytesread = readData(handle, handle->buf, 1);
4301 damr->framesPerSample = handle->buf[0];
4302 totalbytesread += bytesread;
4304 return totalbytesread;
4311 * mp4_i32 freeFTYP(MP4HandleImp handle)
4315 * This function frees memory for FTYP atom.
4319 * ftyp FTYP atom pointer
4327 mp4_i32 freeFTYP(fileTypeAtom *ftyp)
4331 if (freeAtomHeader(ftyp->atomhdr) < 0)
4333 if (ftyp->compatibleBrands)
4334 mp4free(ftyp->compatibleBrands);
4346 * mp4_i32 freeMOOV(movieAtom *moov)
4350 * This function frees memory for MOOV atom.
4354 * moov MOOV atom pointer
4362 mp4_i32 freeMOOV(movieAtom *moov)
4366 if (freeAtomHeader(moov->atomhdr) < 0)
4368 if (freeMVHD(moov->mvhd) < 0)
4370 if (freeTRAK(moov->trakAudio) < 0)
4372 if (freeTRAK(moov->trakVideo) < 0)
4374 if (freeIODS(moov->iods) < 0)
4376 if (freeUDTA(moov->udta) < 0)
4378 if (freeMETA(moov->meta) < 0)
4391 * mp4_i32 freeAtomHeader(atomHeader *atomhdr)
4395 * This function frees memory for atom header.
4399 * atomhdr atom header pointer
4407 mp4_i32 freeAtomHeader(atomHeader *atomhdr)
4419 * mp4_i32 freeMVHD(movieHeaderAtom *mvhd)
4423 * This function frees memory for MVHD atom.
4427 * mvhd MVHD atom pointer
4435 mp4_i32 freeMVHD(movieHeaderAtom *mvhd)
4439 if (freeAtomHeader(mvhd->atomhdr) < 0)
4452 * mp4_i32 freeTRAK(trackAtom *trak)
4456 * This function frees memory for TRAK atom.
4460 * trak TRAK atom pointer
4468 mp4_i32 freeTRAK(trackAtom *trak)
4472 if (freeAtomHeader(trak->atomhdr) < 0)
4474 if (freeTKHD(trak->tkhd) < 0)
4476 if (freeTREF(trak->tref) < 0)
4478 if (freeEDTS(trak->edts) < 0)
4480 if (freeMDIA(trak->mdia) < 0)
4482 if (freeUDTA(trak->udta) < 0)
4495 * mp4_i32 freeTKHD(trackHeaderAtom *tkhd)
4499 * This function frees memory for TKHD atom.
4503 * tkhd TKHD atom pointer
4511 mp4_i32 freeTKHD(trackHeaderAtom *tkhd)
4515 if (freeAtomHeader(tkhd->atomhdr) < 0)
4528 * mp4_i32 freeTREF(trackReferenceAtom *tref)
4532 * This function frees memory for TREF atom.
4536 * tref TREF atom pointer
4544 mp4_i32 freeTREF(trackReferenceAtom *tref)
4548 if (freeAtomHeader(tref->atomhdr) < 0)
4561 * mp4_i32 freeEDTS(editListContainerAtom *edts)
4565 * This function frees memory for EDTS atom.
4569 * edts EDTS atom pointer
4577 mp4_i32 freeEDTS(editListContainerAtom *edts)
4581 if (freeAtomHeader(edts->atomhdr) < 0)
4594 * mp4_i32 freeMDIA(mediaAtom *mdia)
4598 * This function frees memory for MDIA atom.
4602 * mdia MDIA atom pointer
4610 mp4_i32 freeMDIA(mediaAtom *mdia)
4614 if (freeAtomHeader(mdia->atomhdr) < 0)
4616 if (freeMDHD(mdia->mdhd) < 0)
4618 if (freeHDLR(mdia->hdlr) < 0)
4620 if (freeMINF(mdia->minf) < 0)
4633 * mp4_i32 freeMDHD(mediaHeaderAtom *mdhd)
4637 * This function frees memory for MDHD atom.
4641 * mdhd MDHD atom pointer
4649 mp4_i32 freeMDHD(mediaHeaderAtom *mdhd)
4653 if (freeAtomHeader(mdhd->atomhdr) < 0)
4666 * mp4_i32 freeHDLR(handlerAtom *hdlr)
4670 * This function frees memory for HDLR atom.
4674 * hdlr HDLR atom pointer
4682 mp4_i32 freeHDLR(handlerAtom *hdlr)
4686 if (freeAtomHeader(hdlr->atomhdr) < 0)
4689 mp4free(hdlr->name);
4701 * mp4_i32 freeMINF(mediaInformationAtom *minf)
4705 * This function frees memory for MINF atom.
4709 * minf MINF atom pointer
4717 mp4_i32 freeMINF(mediaInformationAtom *minf)
4721 if (freeAtomHeader(minf->atomhdr) < 0)
4723 if (freeVMHD(minf->vmhd) < 0)
4725 if (freeSMHD(minf->smhd) < 0)
4727 if (freeDINF(minf->dinf) < 0)
4729 if (freeSTBL(minf->stbl) < 0)
4742 * mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd)
4746 * This function frees memory for VMHD atom.
4750 * vmhd VMHD atom pointer
4758 mp4_i32 freeVMHD(videoMediaHeaderAtom *vmhd)
4762 if (freeAtomHeader(vmhd->atomhdr) < 0)
4775 * mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd)
4779 * This function frees memory for SMHD atom.
4783 * smhd SMHD atom pointer
4791 mp4_i32 freeSMHD(soundMediaHeaderAtom *smhd)
4795 if (freeAtomHeader(smhd->atomhdr) < 0)
4808 * mp4_i32 freeDINF(dataInformationAtom *dinf)
4812 * This function frees memory for DINF atom.
4816 * dinf DINF atom pointer
4824 mp4_i32 freeDINF(dataInformationAtom *dinf)
4828 if (freeAtomHeader(dinf->atomhdr) < 0)
4830 if (freeDREF(dinf->dref) < 0)
4843 * mp4_i32 freeDREF(dataReferenceAtom *dref)
4847 * This function frees memory for DREF atom.
4851 * dref DREF atom pointer
4859 mp4_i32 freeDREF(dataReferenceAtom *dref)
4863 if (freeAtomHeader(dref->atomhdr) < 0)
4865 if (freeURL(dref->url) < 0)
4867 if (freeURN(dref->urn) < 0)
4880 * mp4_i32 freeURL(dataEntryURLAtom *url)
4884 * This function frees memory for URL atom.
4888 * url URL atom pointer
4896 mp4_i32 freeURL(dataEntryURLAtom *url)
4900 if (freeAtomHeader(url->atomhdr) < 0)
4913 * mp4_i32 freeURN(dataEntryURNAtom *urn)
4917 * This function frees memory for URN atom.
4921 * urn URN atom pointer
4929 mp4_i32 freeURN(dataEntryURNAtom *urn)
4933 if (freeAtomHeader(urn->atomhdr) < 0)
4946 * mp4_i32 freeSTBL(sampleTableAtom *stbl)
4950 * This function frees memory for STBL atom.
4954 * stbl STBL atom pointer
4962 mp4_i32 freeSTBL(sampleTableAtom *stbl)
4966 if (freeAtomHeader(stbl->atomhdr) < 0)
4968 if (freeSTTS(stbl->stts) < 0)
4970 if (freeCTTS(stbl->ctts) < 0)
4972 if (freeSTSD(stbl->stsd) < 0)
4974 if (freeSTSZ(stbl->stsz) < 0)
4976 if (freeSTSC(stbl->stsc) < 0)
4978 if (stbl->is32BitOffsets)
4981 if (freeSTCO(stbl->stco) < 0)
4987 if (freeSTCO64(stbl->stco64) < 0)
4990 if (freeSTSS(stbl->stss) < 0)
4992 if (freeSTSH(stbl->stsh) < 0)
4994 if (freeSDTP(stbl->sdtp) < 0)
5007 * mp4_i32 freeSTTS(timeToSampleAtom *stts)
5011 * This function frees memory for STTS atom.
5015 * stts STTS atom pointer
5023 mp4_i32 freeSTTS(timeToSampleAtom *stts)
5027 if (freeAtomHeader(stts->atomhdr) < 0)
5029 if (stts->sampleCount)
5030 mp4free(stts->sampleCount);
5031 if (stts->sampleDelta)
5032 mp4free(stts->sampleDelta);
5044 * mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts)
5048 * This function frees memory for CTTS atom.
5052 * ctts CTTS atom pointer
5060 mp4_i32 freeCTTS(compositionTimeToSampleAtom *ctts)
5064 if (freeAtomHeader(ctts->atomhdr) < 0)
5066 if (ctts->sampleCount)
5067 mp4free(ctts->sampleCount);
5068 if (ctts->sampleOffset)
5069 mp4free(ctts->sampleOffset);
5081 * mp4_i32 freeSTSD(sampleDescriptionAtom *stsd)
5085 * This function frees memory for STSD atom.
5089 * stsd STSD atom pointer
5097 mp4_i32 freeSTSD(sampleDescriptionAtom *stsd)
5099 mp4_u32 sampleentrycount = 0;
5104 sampleentrycount = stsd->entryCount;
5106 if (freeAtomHeader(stsd->atomhdr) < 0)
5108 for (entryindex = 0; entryindex < sampleentrycount; entryindex++)
5110 if (freeMP4V(stsd->mp4v[entryindex]) < 0)
5112 if (freeMP4A(stsd->mp4a[entryindex]) < 0)
5114 if (freeMP4S(stsd->mp4s[entryindex]) < 0)
5116 if (freeS263(stsd->s263[entryindex]) < 0)
5118 if (freeSAMR(stsd->samr[entryindex]) < 0)
5120 if (freeSAWB(stsd->sawb[entryindex]) < 0)
5122 if (freeAVC1(stsd->avc1[entryindex]) < 0)
5124 if (freeSQCP(stsd->sqcp[entryindex]) < 0)
5137 * mp4_i32 freeMP4V(visualSampleEntry *mp4v)
5141 * This function frees memory for MP4V atom.
5145 * mp4v MP4V atom pointer
5153 mp4_i32 freeMP4V(visualSampleEntry *mp4v)
5157 if (freeAtomHeader(mp4v->atomhdr) < 0)
5159 if (freeESD(mp4v->esd) < 0)
5172 * mp4_i32 freeESD(ESDAtom *esd)
5176 * This function frees memory for ESD atom.
5180 * esd ESD atom pointer
5188 mp4_i32 freeESD(ESDAtom *esd)
5192 if (freeAtomHeader(esd->atomhdr) < 0)
5195 mp4free(esd->URLString);
5196 if (esd->decSpecificInfo)
5197 mp4free(esd->decSpecificInfo);
5209 * mp4_i32 freeMP4A(audioSampleEntry *mp4a)
5213 * This function frees memory for MP4A atom.
5217 * mp4a MP4A atom pointer
5225 mp4_i32 freeMP4A(audioSampleEntry *mp4a)
5229 if (freeAtomHeader(mp4a->atomhdr) < 0)
5231 if (freeESD(mp4a->esd) < 0)
5244 * mp4_i32 freeMP4S(mpegSampleEntry *mp4s)
5248 * This function frees memory for MP4S atom.
5252 * mp4s MP4S atom pointer
5260 mp4_i32 freeMP4S(mpegSampleEntry *mp4s)
5264 if (freeAtomHeader(mp4s->atomhdr) < 0)
5266 if (freeESD(mp4s->esd) < 0)
5279 * mp4_i32 freeS263(h263SampleEntry *s263)
5283 * This function frees memory for S263 atom.
5287 * s263 S263 atom pointer
5295 mp4_i32 freeS263(h263SampleEntry *s263)
5299 if (freeAtomHeader(s263->atomhdr) < 0)
5301 if (freeD263(s263->d263) < 0)
5314 * mp4_i32 freeD263(h263SpecificAtom *d263)
5318 * This function frees memory for D263 atom.
5322 * d263 D263 atom pointer
5330 mp4_i32 freeD263(h263SpecificAtom *d263)
5334 if (freeAtomHeader(d263->atomhdr) < 0)
5336 if (freeBITR(d263->bitr) < 0)
5349 * mp4_i32 freeBITR(BitrateAtom *bitr)
5353 * This function frees memory for BITR atom.
5357 * bitr BITR atom pointer
5365 mp4_i32 freeBITR(bitrateAtom *bitr)
5369 if (freeAtomHeader(bitr->atomhdr) < 0)
5382 * mp4_i32 freeSAMR(amrSampleEntry *samr)
5386 * This function frees memory for SAMR atom.
5390 * samr SAMR atom pointer
5398 mp4_i32 freeSAMR(amrSampleEntry *samr)
5402 if (freeAtomHeader(samr->atomhdr) < 0)
5404 if (freeDAMR(samr->damr) < 0)
5417 * mp4_i32 freeSAWB(amrSampleEntry *sawb)
5421 * This function frees memory for SAWB atom.
5425 * sawb SAWB atom pointer
5433 mp4_i32 freeSAWB(amrSampleEntry *sawb)
5437 if (freeAtomHeader(sawb->atomhdr) < 0)
5439 if (freeDAMR(sawb->damr) < 0)
5452 * mp4_i32 freeDAMR(amrDecSpecStruc *damr)
5456 * This function frees memory for DAMR atom.
5460 * damr DAMR atom pointer
5468 mp4_i32 freeDAMR(amrDecSpecStruc *damr)
5472 if (freeAtomHeader(damr->atomhdr) < 0)
5485 * mp4_i32 freeSTSZ(sampleSizeAtom *stsz)
5489 * This function frees memory for STSZ atom.
5493 * stsz STSZ atom pointer
5501 mp4_i32 freeSTSZ(sampleSizeAtom *stsz)
5505 if (freeAtomHeader(stsz->atomhdr) < 0)
5507 if (stsz->entrySize)
5508 mp4free(stsz->entrySize);
5520 * mp4_i32 freeSTSC(sampleToChunkAtom *stsc)
5524 * This function frees memory for STSC atom.
5528 * stsc STSC atom pointer
5536 mp4_i32 freeSTSC(sampleToChunkAtom *stsc)
5540 if (freeAtomHeader(stsc->atomhdr) < 0)
5542 if (stsc->firstChunk)
5543 mp4free(stsc->firstChunk);
5544 if (stsc->samplesPerChunk)
5545 mp4free(stsc->samplesPerChunk);
5546 if (stsc->sampleDescriptionIndex)
5547 mp4free(stsc->sampleDescriptionIndex);
5559 * mp4_i32 freeSTCO(chunkOffsetAtom *stco)
5563 * This function frees memory for STCO atom.
5567 * stco STCO atom pointer
5575 mp4_i32 freeSTCO(chunkOffsetAtom *stco)
5579 if (freeAtomHeader(stco->atomhdr) < 0)
5581 if (stco->chunkOffset)
5582 mp4free(stco->chunkOffset);
5593 * mp4_i32 freeSTCO64(chunkOffset64Atom *stco64)
5597 * This function frees memory for STCO64 atom.
5601 * stco64 STCO64 atom pointer
5609 mp4_i32 freeSTCO64(chunkOffset64Atom *stco64)
5613 if (freeAtomHeader(stco64->atomhdr) < 0)
5615 if (stco64->chunkOffset)
5616 mp4free(stco64->chunkOffset);
5628 * mp4_i32 freeSTSS(syncSampleAtom *stss)
5632 * This function frees memory for STSS atom.
5636 * stss STSS atom pointer
5644 mp4_i32 freeSTSS(syncSampleAtom *stss)
5648 if (freeAtomHeader(stss->atomhdr) < 0)
5650 if (stss->sampleNumber)
5651 mp4free(stss->sampleNumber);
5663 * mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh)
5667 * This function frees memory for STSH atom.
5671 * stsh STSH atom pointer
5679 mp4_i32 freeSTSH(shadowSyncSampleAtom *stsh)
5683 if (freeAtomHeader(stsh->atomhdr) < 0)
5696 * mp4_i32 freeSDTP(sampleDependencyAtom *sdtp)
5700 * This function frees memory for SDTP atom.
5704 * sdtp SDTP atom pointer
5712 mp4_i32 freeSDTP(sampleDependencyAtom *sdtp)
5716 if (freeAtomHeader(sdtp->atomhdr) < 0)
5735 * mp4_i32 freeIODS(objectDescriptorAtom *iods)
5739 * This function frees memory for IODS atom.
5743 * iods IODS atom pointer
5751 mp4_i32 freeIODS(objectDescriptorAtom *iods)
5755 if (freeAtomHeader(iods->atomhdr) < 0)
5768 * mp4_i32 readUDTA(MP4HandleImp handle,
5769 * userDataAtom *udta)
5773 * This function parses one UDTA atom.
5777 * handle MP4 library handle
5782 * Negative integer Error
5783 * >= 0 Success. Value tells how many bytes were read.
5786 mp4_i32 readUDTA(MP4HandleImp handle, userDataAtom *udta)
5789 mp4_i32 totalbytesread = 0;
5791 if ((udta->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
5794 bytesread = readAtomHeader(handle, udta->atomhdr);
5797 totalbytesread += bytesread;
5799 if (udta->atomhdr->type != ATOMTYPE_UDTA)
5804 udta->atomcontentloc = handle->diskReadBufStart + handle->diskReadBufPos;
5808 udta->atomcontentloc = handle->absPosition;
5811 if ( udta->atomhdr->size == 1 )
5813 udta->atomcontentsize = I64INT(udta->atomhdr->largeSize) - (TInt)totalbytesread;
5817 udta->atomcontentsize = (TInt)(udta->atomhdr->size - totalbytesread);
5822 if ( seekFile(handle, udta->atomhdr->size - totalbytesread) < 0 )
5828 return udta->atomhdr->size;
5833 bytesread = discardData(handle, udta->atomhdr->size - totalbytesread);
5836 totalbytesread += bytesread;
5838 return totalbytesread;
5844 * mp4_i32 freeUDTA(userDataAtom *udta)
5848 * This function frees memory for UDTA atom.
5852 * udta UDTA atom pointer
5860 mp4_i32 freeUDTA(userDataAtom *udta)
5864 if (freeAtomHeader(udta->atomhdr) < 0)
5876 * mp4_i32 determineVideoLength(MP4HandleImp handle,
5877 * mp4_u32 *videolength)
5881 * This function determines the length of video in milliseconds.
5885 * handle MP4 library handle
5886 * videolength Video length is returned here
5894 mp4_i32 determineVideoLength(MP4HandleImp handle, mp4_u32 *videolength)
5899 if (!handle->moov->mvhd)
5902 if (!handle->moov->trakVideo)
5905 if (!handle->moov->trakVideo->tkhd)
5908 /* Is timescale set? */
5909 if (handle->moov->mvhd->timeScale == 0)
5912 *videolength = (mp4_u32)(((mp4_double)handle->moov->trakVideo->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000);
5921 * mp4_i32 determineFrameRate(MP4HandleImp handle,
5922 * mp4_double *framerate)
5926 * This function determines the frame rate of video.
5928 * Frame rate is calculated as the average frame rate of the entire video.
5932 * handle MP4 library handle
5933 * framerate Frame rate is returned here
5941 mp4_i32 determineFrameRate(MP4HandleImp handle, mp4_double *framerate)
5943 mp4_double numberofframes;
5951 if (!handle->moov->trakVideo)
5953 if (!handle->moov->trakVideo->mdia)
5955 if (!handle->moov->trakVideo->mdia->minf)
5957 if (!handle->moov->trakVideo->mdia->minf->stbl)
5959 if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
5961 if (!handle->moov->trakVideo->mdia->mdhd)
5965 if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
5968 if (handle->moov->trakVideo->mdia->mdhd->duration == 0)
5974 numberofframes = (mp4_double)handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount;
5975 length = (mp4_double)handle->moov->trakVideo->mdia->mdhd->duration /
5976 (mp4_double)handle->moov->trakVideo->mdia->mdhd->timeScale;
5978 *framerate = numberofframes / length;
5988 * mp4_i32 determineVideoType(MP4HandleImp handle,
5989 * mp4_u32 *videotype)
5993 * This function determines the video type of the MP4.
5997 * handle MP4 library handle
5998 * videotype Video type is returned here
6004 * -2 Unknown video type
6007 mp4_i32 determineVideoType(MP4HandleImp handle, mp4_u32 *videotype)
6009 *videotype = MP4_TYPE_NONE;
6014 if (!handle->moov->trakVideo)
6017 if (!handle->moov->trakVideo->mdia)
6020 if (!handle->moov->trakVideo->mdia->minf)
6023 if (!handle->moov->trakVideo->mdia->minf->stbl)
6026 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
6029 if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0)
6032 /* Assume that the video type is the same for all sample entries. Just get the video type from the first one */
6034 if (handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0])
6036 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd)
6039 if ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->objectTypeIndication == 0x20) &&
6040 ((handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->esd->stream >> 2) == 0x04))
6041 *videotype = MP4_TYPE_MPEG4_VIDEO;
6044 if (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
6046 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263)
6049 switch (handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->d263->h263Profile)
6052 *videotype = MP4_TYPE_H263_PROFILE_0;
6055 *videotype = MP4_TYPE_H263_PROFILE_3;
6062 if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0])
6064 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc)
6067 if (handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize == 0)
6070 /* AVC profile is in the second byte of the avcconfigrecord */
6071 switch((mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[1])
6074 *videotype = MP4_TYPE_AVC_PROFILE_BASELINE;
6077 *videotype = MP4_TYPE_AVC_PROFILE_MAIN;
6080 *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED;
6083 *videotype = MP4_TYPE_AVC_PROFILE_HIGH;
6087 mp4_u8 constraintByte = (mp4_u8)handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig[2];
6088 if ( (constraintByte & 0x80) || (constraintByte & 0x10) )
6090 *videotype = MP4_TYPE_AVC_PROFILE_BASELINE;
6092 else if (constraintByte & 0x40)
6094 *videotype = MP4_TYPE_AVC_PROFILE_MAIN;
6096 else if (constraintByte & 0x20)
6098 *videotype = MP4_TYPE_AVC_PROFILE_EXTENDED;
6100 // NOTE: Cannot reliably determine higher profiles from
6101 // the constraint flags.
6108 /* Note: Read the AVC level and recreate the actual AVC profile and level in the future! */
6109 if (*videotype == MP4_TYPE_NONE)
6119 * mp4_i32 determineVideoResolution(MP4HandleImp handle,
6120 * mp4_u32 *videowidth,
6121 * mp4_u32 *videoheight)
6125 * This function finds out the video width and height from the atom
6130 * handle MP4 library handle
6131 * videowidth Video width is returned here
6132 * videoheight Video height is returned here
6140 mp4_i32 determineVideoResolution(MP4HandleImp handle, mp4_u32 *videowidth, mp4_u32 *videoheight)
6142 mp4_u32 videotype = MP4_TYPE_NONE;
6145 if (determineVideoType(handle, &videotype) < 0)
6148 if (videotype == MP4_TYPE_NONE)
6154 if (!handle->moov->trakVideo)
6157 if (!handle->moov->trakVideo->mdia)
6160 if (!handle->moov->trakVideo->mdia->minf)
6163 if (!handle->moov->trakVideo->mdia->minf->stbl)
6166 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd)
6169 if (handle->moov->trakVideo->mdia->minf->stbl->stsd->entryCount == 0)
6172 /* Assume that the video characteristics for all the video sample entries are the same. Just get them from the first one */
6174 if (videotype == MP4_TYPE_H263_PROFILE_0 ||
6175 videotype == MP4_TYPE_H263_PROFILE_3)
6177 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0])
6180 *videowidth = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->width;
6181 *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->s263[0]->height;
6183 else if (videotype == MP4_TYPE_MPEG4_VIDEO)
6185 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0])
6188 *videowidth = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->width;
6189 *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->mp4v[0]->height;
6191 else if ( isAvcVideo(videotype) )
6193 if (!handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0])
6196 *videowidth = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->width;
6197 *videoheight = handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->height;
6210 * mp4_i32 determineVideoTimeScale(MP4HandleImp handle,
6211 * mp4_u32 *timescale)
6215 * This function determines the timescale of video track.
6219 * handle MP4 library handle
6220 * timescale Timescale of video track is returned here
6228 mp4_i32 determineVideoTimeScale(MP4HandleImp handle, mp4_u32 *timescale)
6230 if (timescale == NULL)
6237 if (!handle->moov->trakVideo)
6239 if (!handle->moov->trakVideo->mdia)
6241 if (!handle->moov->trakVideo->mdia->mdhd)
6243 if (handle->moov->trakVideo->mdia->mdhd->timeScale == 0)
6246 *timescale = handle->moov->trakVideo->mdia->mdhd->timeScale;
6255 * mp4_i32 determineAudioLength(MP4HandleImp handle,
6256 * mp4_u32 *audiolength)
6260 * This function determines the length of audio in milliseconds.
6264 * handle MP4 library handle
6265 * audiolength Audio length is returned here
6273 mp4_i32 determineAudioLength(MP4HandleImp handle, mp4_u32 *audiolength)
6278 if (!handle->moov->mvhd)
6281 if (!handle->moov->trakAudio)
6284 if (!handle->moov->trakAudio->tkhd)
6287 /* Is timescale set? */
6288 if (handle->moov->mvhd->timeScale == 0)
6291 *audiolength = (mp4_u32)(((mp4_double)handle->moov->trakAudio->tkhd->duration / (mp4_double)handle->moov->mvhd->timeScale) * (mp4_double)1000);
6300 * mp4_i32 determineAudioType(MP4HandleImp handle,
6301 * mp4_u32 *audiotype)
6305 * This function determines the audio type of the MP4.
6309 * handle MP4 library handle
6310 * audiotype Audio type is returned here
6316 * -2 Unknown audiotrack
6319 mp4_i32 determineAudioType(MP4HandleImp handle, mp4_u32 *audiotype)
6321 *audiotype = MP4_TYPE_NONE;
6327 if (!handle->moov->trakAudio)
6330 if (!handle->moov->trakAudio->mdia)
6333 if (!handle->moov->trakAudio->mdia->minf)
6336 if (!handle->moov->trakAudio->mdia->minf->stbl)
6339 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
6342 if (handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount == 0)
6345 /* Assume that the audio type is the same for all sample entries. Just get the audio type from the first one */
6346 if (handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0])
6348 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd)
6351 if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0x40) &&
6352 ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05))
6353 *audiotype = MP4_TYPE_MPEG4_AUDIO;
6355 if ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->objectTypeIndication == 0xE1) &&
6356 ((handle->moov->trakAudio->mdia->minf->stbl->stsd->mp4a[0]->esd->stream >> 2) == 0x05))
6358 *audiotype = MP4_TYPE_QCELP_13K;
6359 handle->qcelpStoredAsMPEGAudio = MP4TRUE;
6362 else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[0])
6363 *audiotype = MP4_TYPE_AMR_NB;
6364 else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[0])
6365 *audiotype = MP4_TYPE_AMR_WB;
6366 else if (handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[0])
6368 *audiotype = MP4_TYPE_QCELP_13K;
6369 handle->qcelpStoredAsMPEGAudio = MP4FALSE;
6375 if (*audiotype == MP4_TYPE_NONE)
6385 * mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle,
6386 * mp4_u8 *framespersample)
6390 * This function determines the number of audio frames in each sample.
6391 * The function works with AMR audio type only.
6395 * handle MP4 library handle
6396 * framespersample Number of frames in each sample
6404 mp4_i32 determineAudioFramesPerSample(MP4HandleImp handle, mp4_u8 *framespersample)
6406 mp4_i8 sampleentryindex;
6408 *framespersample = 0;
6411 if (!((handle->type & MP4_TYPE_AMR_NB) ||
6412 (handle->type & MP4_TYPE_AMR_WB) ||
6413 ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))))
6415 *framespersample = 1;
6424 if (!handle->moov->trakAudio)
6427 if (!handle->moov->trakAudio->mdia)
6430 if (!handle->moov->trakAudio->mdia->minf)
6433 if (!handle->moov->trakAudio->mdia->minf->stbl)
6436 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd)
6439 if (handle->type & MP4_TYPE_AMR_NB)
6441 /* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/
6442 for (sampleentryindex = 0; (mp4_u8) sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
6444 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex])
6447 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr)
6450 if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample)
6451 *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->samr[sampleentryindex]->damr->framesPerSample;
6454 else if (handle->type & MP4_TYPE_AMR_WB)
6456 /* Now, framespersample returns the maximum frames_per_sample listed in the AMR sample entries*/
6457 for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
6459 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex])
6462 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr)
6465 if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample)
6466 *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sawb[sampleentryindex]->damr->framesPerSample;
6469 else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))
6471 /* Now, framespersample returns the maximum frames_per_sample listed in the QCELP-13K sample entries*/
6472 for (sampleentryindex = 0; (mp4_u8)sampleentryindex < handle->moov->trakAudio->mdia->minf->stbl->stsd->entryCount; sampleentryindex++)
6474 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex])
6477 if (!handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp)
6480 if (*framespersample < handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample)
6481 *framespersample = handle->moov->trakAudio->mdia->minf->stbl->stsd->sqcp[sampleentryindex]->dqcp->framesPerSample;
6495 * mp4_i32 determineAudioTimeScale(MP4HandleImp handle,
6496 * mp4_u32 *timescale)
6500 * This function determines the timescale of audio track.
6504 * handle MP4 library handle
6505 * timescale Timescale of audio track is returned here
6513 mp4_i32 determineAudioTimeScale(MP4HandleImp handle, mp4_u32 *timescale)
6515 if (timescale == NULL)
6522 if (!handle->moov->trakAudio)
6524 if (!handle->moov->trakAudio->mdia)
6526 if (!handle->moov->trakAudio->mdia->mdhd)
6530 if (handle->moov->trakAudio->mdia->mdhd->timeScale == 0)
6533 *timescale = handle->moov->trakAudio->mdia->mdhd->timeScale;
6542 * mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle,
6543 * mp4_u32 *averagebitrate)
6547 * This function determines the average bitrate of the audio in bits per
6550 * The average is calculated so that the audio data length is divided by
6551 * the length of the audio track.
6555 * handle MP4 library handle
6556 * averagebitrate Result is returned here
6564 mp4_i32 determineAudioAverageBitRate(MP4HandleImp handle, mp4_u32 *averagebitrate)
6566 mp4_u32 audiosize = 0;
6573 if (handle->moov->trakAudio)
6575 if (!handle->moov->trakAudio->mdia)
6580 if (!handle->moov->trakAudio->mdia->minf)
6585 if (!handle->moov->trakAudio->mdia->minf->stbl)
6590 if (!handle->moov->trakAudio->mdia->minf->stbl->stsz)
6595 if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0)
6597 audiosize += (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount *
6598 handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize);
6603 for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++)
6605 audiosize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i];
6614 if (!handle->moov->trakAudio->mdia->mdhd)
6619 if (!handle->moov->trakAudio->mdia->mdhd->timeScale)
6624 if (handle->moov->trakAudio->mdia->mdhd->duration == 0)
6626 *averagebitrate = 0;
6630 *averagebitrate = (mp4_u32)((mp4_double)8 *
6631 (mp4_double)audiosize /
6632 ((mp4_double)handle->moov->trakAudio->mdia->mdhd->duration /
6633 (mp4_double)handle->moov->trakAudio->mdia->mdhd->timeScale));
6643 * mp4_i32 determineStreamSize(MP4HandleImp handle,
6644 * mp4_u32 *streamsize)
6648 * This function determines the size of media data in MP4 file/stream.
6652 * handle MP4 library handle
6653 * streamsize Size of data
6661 mp4_i32 determineStreamSize(MP4HandleImp handle, mp4_u32 *streamsize)
6668 if ((!handle->moov->trakAudio) && (!handle->moov->trakVideo))
6671 if (handle->moov->trakAudio)
6673 if (!handle->moov->trakAudio->mdia)
6676 if (!handle->moov->trakAudio->mdia->minf)
6679 if (!handle->moov->trakAudio->mdia->minf->stbl)
6682 if (!handle->moov->trakAudio->mdia->minf->stbl->stsz)
6685 if (handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize != 0)
6686 *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount *
6687 handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleSize;
6692 for (i = 0; i < handle->moov->trakAudio->mdia->minf->stbl->stsz->sampleCount; i++)
6693 *streamsize += handle->moov->trakAudio->mdia->minf->stbl->stsz->entrySize[i];
6697 if (handle->moov->trakVideo)
6699 if (!handle->moov->trakVideo->mdia)
6702 if (!handle->moov->trakVideo->mdia->minf)
6705 if (!handle->moov->trakVideo->mdia->minf->stbl)
6708 if (!handle->moov->trakVideo->mdia->minf->stbl->stsz)
6711 if (handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize != 0)
6712 *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount *
6713 handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleSize;
6718 for (i = 0; i < handle->moov->trakVideo->mdia->minf->stbl->stsz->sampleCount; i++)
6719 *streamsize += handle->moov->trakVideo->mdia->minf->stbl->stsz->entrySize[i];
6730 * mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle,
6731 * mp4_u32 *streamaveragebitrate,
6732 * mp4_u32 streamsize)
6736 * This function determines the average bitrate of the stream in bits per
6739 * The average is calculated so that the media data length is divided by
6740 * the length of the presentation.
6744 * handle MP4 library handle
6745 * streamaveragebitrate Result is returned here
6746 * streamsize Size of media data in bytes
6754 mp4_i32 determineStreamAverageBitRate(MP4HandleImp handle, mp4_u32 *streamaveragebitrate, mp4_u32 streamsize)
6759 if (!handle->moov->mvhd)
6762 if (!handle->moov->mvhd->timeScale)
6765 if (handle->moov->mvhd->atomhdr->version == 1) /* 64 bit */
6767 if (!handle->moov->mvhd->duration64)
6770 *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize /
6771 ((mp4_double)handle->moov->mvhd->duration64 / handle->moov->mvhd->timeScale));
6775 if (!handle->moov->mvhd->duration)
6778 *streamaveragebitrate = (mp4_u32)((mp4_double)8 * (mp4_double)streamsize /
6779 ((mp4_double)handle->moov->mvhd->duration / handle->moov->mvhd->timeScale));
6789 * mp4_i32 advanceVideoFrame(MP4HandleImp handle,
6794 * This function Advances one video frame and finds the frame offset
6799 * handle MP4 library handle
6800 * trak TRAK atom pointer
6808 mp4_i32 advanceVideoFrame(MP4HandleImp handle, trackAtom *trak)
6812 if (!trak->mdia->minf)
6814 if (!trak->mdia->minf->stbl)
6816 if (!trak->mdia->minf->stbl->stsz)
6819 /* Are there frames (samples) left? */
6821 if (trak->mdia->minf->stbl->stsz->sampleCount > handle->videoSampleNum)
6822 handle->videoSampleNum++;
6826 /* Find the size of the frame (sample) */
6828 if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
6831 /* Find the offset of the frame (sample) */
6833 if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0)
6844 * mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle,
6845 * sampleTableAtom *stbl)
6849 * This function finds the offset of the current video sample.
6850 * The result is stored in handle->videoFrameOffset.
6854 * handle MP4 library handle
6855 * stbl STBL atom pointer
6863 mp4_i32 resolveVideoSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl)
6865 mp4_u32 chunk; /* Current chunk number */
6866 mp4_u32 sample; /* Number of samples before this run of chunks */
6867 mp4_u32 entry; /* Current entry in sample to chunk */
6868 mp4_u32 chunksInThisRun; /* Number of chunks in this run */
6869 mp4_u32 sampleNrInChunk = 0; /* Sample number in the chunk */
6871 if (!stbl->stsc || stbl->stsc->entryCount == 0)
6876 if (!stbl->stco || stbl->stco->entryCount == 0)
6887 /* Find how many chunks there are in this run */
6889 if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */
6891 chunksInThisRun = stbl->stsc->firstChunk[entry + 1] - stbl->stsc->firstChunk[entry];
6895 chunksInThisRun = stbl->stco->entryCount - chunk + 1;
6898 if (handle->videoSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample)
6900 chunk += (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry];
6901 sampleNrInChunk = (handle->videoSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry];
6903 /* The following functions are needed for multiple sample entry support */
6904 handle->videoSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry];
6906 break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/
6910 chunk += chunksInThisRun;
6911 sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry];
6917 if (chunk > stbl->stco->entryCount)
6922 handle->videoFrameOffset = getChunkOffset(stbl, chunk - 1);
6924 if (sampleNrInChunk)
6926 if (stbl->stsz->sampleSize)
6928 handle->videoFrameOffset += stbl->stsz->sampleSize * sampleNrInChunk;
6932 if (stbl->stsz->sampleCount == 0)
6936 while (sampleNrInChunk)
6938 handle->videoFrameOffset += stbl->stsz->entrySize[handle->videoSampleNum - sampleNrInChunk - 1];
6945 //PRINT((_L("videoFrameOffset %Lu"), handle->videoFrameOffset));
6953 * mp4_i32 resolveVideoSampleSize(MP4HandleImp handle,
6954 * sampleSizeAtom *stsz)
6958 * This function finds the size of the current video sample.
6959 * The result is stored in handle->videoFrameSize.
6963 * handle MP4 library handle
6964 * stsz STSZ atom pointer
6972 mp4_i32 resolveVideoSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz)
6974 if (stsz->sampleSize)
6976 handle->videoFrameSize = stsz->sampleSize;
6980 if (stsz->sampleCount == 0)
6984 handle->videoFrameSize = stsz->entrySize[handle->videoSampleNum - 1];
6993 * mp4_i32 fetchVideoFrame(MP4HandleImp handle,
6996 * mp4_u32 buffersize,
6997 * mp4_u32 *framesize,
6998 * mp4_u32 *timestamp,
6999 * mp4_bool *keyframe,
7000 * mp4_u32 *timestamp2)
7004 * This function fetches one video frame from a file.
7008 * handle MP4 library handle
7009 * trak TRAK atom pointer
7010 * buffer Video frame is retuned here
7011 * buffersize Size of buffer
7012 * framesize Size of returned frame in bytes
7013 * timestamp Frame time in milliseconds (from the beginning of the
7015 * keyframe True if intra frame, false otherwise
7016 * timestamp2 Frame time in timescale (from the beginning of the
7025 mp4_i32 fetchVideoFrame(MP4HandleImp handle,
7032 mp4_u32 *timestamp2)
7040 if (handle->file) /* Input is in a file */
7042 if (seekFileAbs(handle, handle->videoFrameOffset) != 0)
7045 else /* Input is a stream */
7047 if (handle->videoFrameOffset + handle->videoFrameSize <= getCumulativeBufferedBytes(handle))
7049 handle->absPosition = handle->videoFrameOffset;
7055 if (handle->videoFrameSize > buffersize)
7057 *framesize = handle->videoFrameSize;
7061 bytesread = readData(handle, buffer, handle->videoFrameSize);
7075 if (handle->videoFrameOffset + handle->videoFrameSize - 1 > handle->lastAccessedPosInFile)
7076 handle->lastAccessedPosInFile = handle->videoFrameOffset + handle->videoFrameSize - 1;
7078 *framesize = handle->videoFrameSize;
7080 if (convertVideoSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0)
7083 if (isVideoFrameKeyFrame(handle, trak, keyframe) < 0)
7092 * mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle,
7095 * mp4_u32 buffersize,
7099 * This function fetches one video frame from a file asyncronously.
7103 * handle MP4 library handle
7104 * trak TRAK atom pointer
7105 * buffer Video frame is retuned here
7106 * buffersize Size of buffer
7114 mp4_i32 fetchVideoFrameAsync(MP4HandleImp handle,
7117 mp4_u32 *buffersize)
7129 if (handle->videoFrameSize > *buffersize)
7131 *buffersize = handle->videoFrameSize;
7135 if ( handle->asyncReader == NULL )
7137 TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile ));
7138 if ( error != KErrNone )
7140 if (error == KErrNoMemory )
7142 return MP4_OUT_OF_MEMORY;
7151 return handle->asyncReader->ReadVideoFrame( buffer, handle->videoFrameOffset, handle->videoFrameSize);
7157 * mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle,
7159 * mp4_bool *keyframe)
7163 * This function determines if the current frame is a keyframe (intra)
7168 * handle MP4 library handle
7169 * trak TRAK atom pointer
7170 * keyframe Has a value of MP4TRUE if current frame is a keyframe
7171 * (intra) or MP4FALSE otherwise
7179 mp4_i32 isVideoFrameKeyFrame(MP4HandleImp handle, trackAtom *trak, mp4_bool *keyframe)
7184 *keyframe = MP4FALSE;
7189 if (!trak->mdia->minf)
7192 if (!trak->mdia->minf->stbl)
7195 if (!trak->mdia->minf->stbl->stss)
7197 *keyframe = MP4TRUE;
7202 for (i = 0; i < trak->mdia->minf->stbl->stss->entryCount; i++)
7204 if (trak->mdia->minf->stbl->stss->sampleNumber[i] == handle->videoSampleNum)
7206 *keyframe = MP4TRUE;
7218 * mp4_i32 convertVideoSampleToTime(MP4HandleImp handle,
7220 * mp4_u32 *timestamp,
7221 * mp4_u32 *timestamp2)
7225 * This function converts a video sample to corresponding time.
7229 * handle MP4 library handle
7230 * mdia MDIA atom pointer
7231 * timestamp Time in milliseconds is returned here
7232 * timestamp2 Time in timescale is returned here
7240 mp4_i32 convertVideoSampleToTime(MP4HandleImp handle,
7243 mp4_u32 *timestamp2)
7246 mp4_double tmptime2;
7258 if (!mdia->minf->stbl)
7262 if (!mdia->minf->stbl->stts)
7266 if (mdia->minf->stbl->stts->entryCount == 0)
7277 if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->videoSampleNum)
7279 sample += mdia->minf->stbl->stts->sampleCount[entry];
7280 tmptime += (mdia->minf->stbl->stts->sampleCount[entry] * mdia->minf->stbl->stts->sampleDelta[entry]);
7282 if (entry == mdia->minf->stbl->stts->entryCount)
7289 tmptime += ((handle->videoSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry]);
7294 if (mdia->mdhd->timeScale == 0)
7301 *timestamp2 = tmptime;
7304 tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5;
7306 *timestamp = (mp4_u32)tmptime2;
7315 * mp4_i32 advanceAudioSample(MP4HandleImp handle,
7320 * This function advances one audio sample and finds the sample
7321 * offset and sample size.
7325 * handle MP4 library handle
7326 * trak TRAK atom pointer
7334 mp4_i32 advanceAudioSample(MP4HandleImp handle,
7339 if (!trak->mdia->minf)
7341 if (!trak->mdia->minf->stbl)
7343 if (!trak->mdia->minf->stbl->stsz)
7347 /* Are there samples left? */
7349 if (trak->mdia->minf->stbl->stsz->sampleCount > handle->audioSampleNum)
7350 handle->audioSampleNum++;
7354 /* Find the size of the sample */
7356 if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
7359 /* Find the offset of the sample */
7361 if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0)
7372 * mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle,
7373 * sampleTableAtom *stbl)
7377 * This function finds the offset of the current audio sample.
7378 * The result is stored in handle->audioSampleOffset.
7382 * handle MP4 library handle
7383 * stbl STBL atom pointer
7391 mp4_i32 resolveAudioSampleOffset(MP4HandleImp handle, sampleTableAtom *stbl)
7393 mp4_u32 chunk; /* Current chunk number */
7394 mp4_u32 sample; /* Number of samples before this run of chunks */
7395 mp4_u32 entry; /* Current entry in sample to chunk */
7396 mp4_u32 chunksInThisRun; /* Number of chunks in this run */
7397 mp4_u32 sampleNrInChunk; /* Sample number in the chunk */
7400 if (!stbl->stsc || stbl->stsc->entryCount == 0)
7402 if (!stbl->stco || stbl->stco->entryCount == 0)
7411 /* Find how many chunks there are in this run */
7413 if (stbl->stsc->entryCount > entry + 1) /* Not last chunk run */
7415 chunksInThisRun = stbl->stsc->firstChunk[entry + 1] -
7416 stbl->stsc->firstChunk[entry];
7419 chunksInThisRun = stbl->stco->entryCount - chunk + 1;
7422 if (handle->audioSampleNum <= chunksInThisRun * stbl->stsc->samplesPerChunk[entry] + sample)
7424 chunk += (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) / stbl->stsc->samplesPerChunk[entry];
7425 sampleNrInChunk = (handle->audioSampleNum - sample + stbl->stsc->samplesPerChunk[entry] - 1) % stbl->stsc->samplesPerChunk[entry];
7427 /* The following functions are needed for multiple sample entry support */
7428 handle->audioSampleEntryIndex = stbl->stsc->sampleDescriptionIndex[entry];
7430 break; /* We know the chunk number and sample number in chunk AND the sample entry index of the current sample*/
7434 chunk += chunksInThisRun;
7435 sample += chunksInThisRun * stbl->stsc->samplesPerChunk[entry];
7441 if (chunk > stbl->stco->entryCount)
7444 handle->audioSampleOffset = getChunkOffset(stbl, chunk - 1);
7446 if (sampleNrInChunk)
7448 if (stbl->stsz->sampleSize)
7450 handle->audioSampleOffset += stbl->stsz->sampleSize * sampleNrInChunk;
7454 if (stbl->stsz->sampleCount == 0)
7456 // ensure there are entries in the entrySize array
7460 while (sampleNrInChunk)
7462 handle->audioSampleOffset += stbl->stsz->entrySize[handle->audioSampleNum - sampleNrInChunk - 1];
7468 //PRINT((_L("audioSampleOffset %Lu"), handle->audioSampleOffset));
7476 * mp4_i32 resolveAudioSampleSize(MP4HandleImp handle,
7477 * sampleSizeAtom *stsz)
7481 * This function finds the size of the current audio sample.
7482 * The result is stored in handle->audioSampleSize.
7486 * handle MP4 library handle
7487 * stsz STSZ atom pointer
7495 mp4_i32 resolveAudioSampleSize(MP4HandleImp handle, sampleSizeAtom *stsz)
7497 if (stsz->sampleSize)
7499 handle->audioSampleSize = stsz->sampleSize;
7503 if (stsz->sampleCount == 0)
7507 handle->audioSampleSize = stsz->entrySize[handle->audioSampleNum - 1];
7516 * mp4_i32 fetchAudioSample(MP4HandleImp handle,
7519 * mp4_u32 buffersize,
7520 * mp4_u32 *framesize,
7521 * mp4_u32 *timestamp,
7522 * mp4_u32 *returnedframes,
7523 * mp4_u32 *timestamp2)
7527 * This function fetches one audio sample from a file.
7529 * Note: returnedframes may differ from the correct value when accessing
7530 * the last audio sample.
7534 * handle MP4 library handle
7535 * trak TRAK atom pointer
7536 * buffer Audio frame is retuned here
7537 * buffersize Size of buffer
7538 * framesize Size of returned frame in bytes
7539 * timestamp Frame time in milliseconds (from the beginning of the
7541 * returnedframes Number of frames returned, of 0 if not known
7542 * timestamp2 Frame time in timescale (from the beginning of the
7551 mp4_i32 fetchAudioSample(MP4HandleImp handle,
7557 mp4_u32 *returnedframes,
7558 mp4_u32 *timestamp2)
7561 mp4_i32 frameLength;
7562 mp4_u32 numOfFrames;
7563 mp4_u8 *framepointer;
7564 mp4_u32 rawAmrFrameLength[16] = {13,14,16,18,20,21,27,32,6,0,0,0,0,0,0,1};
7569 if (handle->file) /* Input is in a file */
7571 if (seekFileAbs(handle, handle->audioSampleOffset) != 0)
7574 else /* Input is a stream */
7576 if (handle->audioSampleOffset + handle->audioSampleSize <= getCumulativeBufferedBytes(handle))
7578 handle->absPosition = handle->audioSampleOffset;
7584 if (handle->audioSampleSize > buffersize)
7586 *framesize = handle->audioSampleSize;
7590 bytesread = readData(handle, buffer, handle->audioSampleSize);
7604 if (handle->audioSampleOffset + handle->audioSampleSize - 1 > handle->lastAccessedPosInFile)
7605 handle->lastAccessedPosInFile = handle->audioSampleOffset + handle->audioSampleSize - 1;
7607 *framesize = handle->audioSampleSize;
7608 if (convertAudioSampleToTime(handle, trak->mdia, timestamp, timestamp2) < 0)
7611 *returnedframes = 0;
7614 if (trak->mdia->minf)
7615 if (trak->mdia->minf->stbl)
7616 if (trak->mdia->minf->stbl->stsd)
7617 if (handle->type & MP4_TYPE_AMR_NB)
7619 framepointer = buffer;
7621 while ( bytesread > 0 )
7623 frameLength = rawAmrFrameLength[(TInt)(((*framepointer) & 0x78) >> 3)];
7624 if ( frameLength == 0)
7628 bytesread -= frameLength;
7629 framepointer += frameLength;
7632 *returnedframes = numOfFrames;
7634 /* Return the number of sample entries listed for this particular sample entry index
7635 if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1])
7636 if (trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr)
7637 *returnedframes = trak->mdia->minf->stbl->stsd->samr[handle->audioSampleEntryIndex - 1]->damr->framesPerSample;*/
7639 else if (handle->type & MP4_TYPE_AMR_WB)
7641 /* Return the number of sample entries listed for this particular sample entry index */
7642 if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1])
7643 if (trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr)
7644 *returnedframes = trak->mdia->minf->stbl->stsd->sawb[handle->audioSampleEntryIndex - 1]->damr->framesPerSample;
7651 if (trak->mdia->minf)
7652 if (trak->mdia->minf->stbl)
7653 if (trak->mdia->minf->stbl->stsd)
7654 if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1])
7655 *returnedframes = 1;
7657 /* QCELP 13K as QCELPSampleEntry*/
7658 if (trak->mdia->minf)
7659 if (trak->mdia->minf->stbl)
7660 if (trak->mdia->minf->stbl->stsd)
7661 if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))
7663 /* Return the number of sample entries listed for this particular sample entry index */
7664 if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1])
7665 if (trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp)
7666 *returnedframes = trak->mdia->minf->stbl->stsd->sqcp[handle->audioSampleEntryIndex - 1]->dqcp->framesPerSample;
7669 /* QCELP 13K as MPEG-4 audio */
7670 if (trak->mdia->minf)
7671 if (trak->mdia->minf->stbl)
7672 if (trak->mdia->minf->stbl->stsd)
7673 if (trak->mdia->minf->stbl->stsd->mp4a[handle->audioSampleEntryIndex - 1])
7674 *returnedframes = 1;
7682 * mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle,
7685 * mp4_u32 buffersize,
7689 * This function fetches one audio sample from a file asyncronously.
7693 * handle MP4 library handle
7694 * trak TRAK atom pointer
7695 * buffer Audio frame is retuned here
7696 * buffersize Size of buffer
7704 mp4_i32 fetchAudioSampleAsync(MP4HandleImp handle,
7707 mp4_u32 *buffersize)
7719 if (handle->audioSampleSize > *buffersize)
7721 *buffersize = handle->audioSampleSize;
7725 if (!handle->file) // Other input than file is not supported
7730 if ( handle->asyncReader == NULL )
7732 TRAPD(error, handle->asyncReader = CFileAsyncParser::NewL( handle, (RFile64&)handle->rfile ));
7733 if ( error != KErrNone )
7735 if (error == KErrNoMemory )
7737 return MP4_OUT_OF_MEMORY;
7746 return handle->asyncReader->ReadAudioFrames( buffer, handle->audioSampleOffset, handle->audioSampleSize);
7752 * mp4_i32 convertAudioSampleToTime(MP4HandleImp handle,
7754 * mp4_u32 *timestamp,
7755 * mp4_u32 *timestamp2)
7759 * This function converts an audio sample to corresponding time.
7763 * handle MP4 library handle
7764 * mdia MDIA atom pointer
7765 * timestamp Time in milliseconds is returned here
7766 * timestamp2 Time in timescale is returned here
7774 mp4_i32 convertAudioSampleToTime(MP4HandleImp handle,
7777 mp4_u32 *timestamp2)
7780 mp4_double tmptime2;
7792 if (!mdia->minf->stbl)
7796 if (!mdia->minf->stbl->stts)
7800 if (mdia->minf->stbl->stts->entryCount == 0)
7811 if (sample + mdia->minf->stbl->stts->sampleCount[entry] < handle->audioSampleNum)
7813 sample += mdia->minf->stbl->stts->sampleCount[entry];
7814 tmptime += mdia->minf->stbl->stts->sampleCount[entry] *
7815 mdia->minf->stbl->stts->sampleDelta[entry];
7818 if (entry == mdia->minf->stbl->stts->entryCount)
7823 tmptime += (handle->audioSampleNum - sample - 1) * mdia->minf->stbl->stts->sampleDelta[entry];
7828 if (mdia->mdhd->timeScale == 0)
7835 *timestamp2 = tmptime;
7838 tmptime2 = (mp4_double)tmptime * (mp4_double)1000 / (mp4_double)mdia->mdhd->timeScale + (mp4_double)0.5;
7840 *timestamp = (mp4_u32)tmptime2;
7849 * mp4_i32 convertTimeToSample(MP4HandleImp handle,
7856 * This function converts time to corresponding sample number.
7860 * handle MP4 library handle
7861 * trak trackAtom pointer
7862 * position Time in milliseconds
7863 * sample Sample number is returned here
7871 mp4_i32 convertTimeToSample(MP4HandleImp handle,
7876 mp4_u32 pos; /* Target position in media timescale */
7877 mp4_u32 tmppos; /* Temporary position counter */
7887 if (!trak->mdia->mdhd)
7889 if (!trak->mdia->minf)
7891 if (!trak->mdia->minf->stbl)
7893 if (!trak->mdia->minf->stbl->stts)
7895 if (trak->mdia->minf->stbl->stts->entryCount == 0)
7901 pos = (mp4_u32)((mp4_double)position / (mp4_double)1000 * (mp4_double)trak->mdia->mdhd->timeScale + (mp4_double)0.5);
7903 for (i = 0; i < trak->mdia->minf->stbl->stts->entryCount; i++)
7905 if (pos >= (tmppos + trak->mdia->minf->stbl->stts->sampleCount[i] *
7906 trak->mdia->minf->stbl->stts->sampleDelta[i]))
7908 *sample += trak->mdia->minf->stbl->stts->sampleCount[i];
7909 tmppos += (trak->mdia->minf->stbl->stts->sampleCount[i] *
7910 trak->mdia->minf->stbl->stts->sampleDelta[i]);
7912 if (i == trak->mdia->minf->stbl->stts->entryCount - 1) /* Last entry */
7913 *sample = *sample - 1;
7917 if (trak->mdia->minf->stbl->stts->sampleDelta[i] == 0)
7920 *sample += ((pos - tmppos) / trak->mdia->minf->stbl->stts->sampleDelta[i]);
7933 * mp4_i32 goToVideoSample(MP4HandleImp handle,
7939 * This function moves to video sample indicated by sample and finds the
7940 * sample offset and sample size.
7944 * handle MP4 library handle
7945 * trak TRAK atom pointer
7946 * sample Sample to go to
7954 mp4_i32 goToVideoSample(MP4HandleImp handle,
7960 if (!trak->mdia->minf)
7962 if (!trak->mdia->minf->stbl)
7964 if (!trak->mdia->minf->stbl->stsz)
7968 /* Is the sample valid? */
7970 if (sample <= trak->mdia->minf->stbl->stsz->sampleCount)
7971 handle->videoSampleNum = sample;
7975 /* Find the size of the sample */
7977 if (resolveVideoSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
7980 /* Find the offset of the sample */
7982 if (resolveVideoSampleOffset(handle, trak->mdia->minf->stbl) < 0)
7993 * mp4_i32 goToAudioSample(MP4HandleImp handle,
7999 * This function moves to audio sample indicated by sample and finds the
8000 * sample offset and sample size.
8004 * handle MP4 library handle
8005 * trak TRAK atom pointer
8006 * sample Sample to go to
8014 mp4_i32 goToAudioSample(MP4HandleImp handle,
8020 if (!trak->mdia->minf)
8022 if (!trak->mdia->minf->stbl)
8024 if (!trak->mdia->minf->stbl->stsz)
8028 /* Is the sample valid? */
8030 if (sample <= trak->mdia->minf->stbl->stsz->sampleCount)
8031 handle->audioSampleNum = sample;
8035 /* Find the size of the sample */
8037 if (resolveAudioSampleSize(handle, trak->mdia->minf->stbl->stsz) < 0)
8040 /* Find the offset of the sample */
8042 if (resolveAudioSampleOffset(handle, trak->mdia->minf->stbl) < 0)
8053 * mp4_i32 findVideoKeyFrame(MP4HandleImp handle,
8056 * mp4_u32 *newsample)
8060 * This function finds the video keyframe that is identical to or precedes
8061 * the sample indicated by sample.
8065 * handle MP4 library handle
8066 * trak TRAK atom pointer
8067 * sample Sample number
8068 * newsample Sample number of found keyframe
8076 mp4_i32 findVideoKeyFrame(MP4HandleImp handle,
8088 if (!trak->mdia->minf)
8090 if (!trak->mdia->minf->stbl)
8093 if (!trak->mdia->minf->stbl->stss) /* No sync sample atom => all samples are
8094 random access points */
8096 *newsample = sample;
8102 for (i = trak->mdia->minf->stbl->stss->entryCount - 1; i >= 0; i--)
8104 if (sample >= trak->mdia->minf->stbl->stss->sampleNumber[i])
8106 *newsample = trak->mdia->minf->stbl->stss->sampleNumber[i];
8111 if (*newsample == 0)
8121 * mp4_i32 readAVCC(MP4HandleImp handle,
8122 * avcConfigurationAtom *avcc)
8126 * This function parses one avcc atom.
8130 * handle MP4 library handle
8135 * Negative integer Error
8136 * >= 0 Success. Value tells how many bytes were read.
8139 mp4_i32 readAVCC(MP4HandleImp handle, avcConfigurationAtom *avcc)
8142 mp4_i32 totalbytesread = 0;
8144 avcc->avcConfigSize = 0;
8146 if ((avcc->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8149 bytesread = readAtomHeader(handle, avcc->atomhdr);
8152 totalbytesread +=bytesread;
8154 if (avcc->atomhdr->type != ATOMTYPE_AVCC)
8157 /* read the avcDecoderConfigurationRecord */
8158 if (avcc->atomhdr->size != 1)
8159 avcc->avcConfigSize = avcc->atomhdr->size - 8;
8161 avcc->avcConfigSize = (mp4_u32)(I64INT(avcc->atomhdr->largeSize) - 16);
8163 avcc->avcConfig = (mp4_u8 *)mp4malloc(avcc->avcConfigSize);
8164 if (avcc->avcConfig == 0)
8167 bytesread = readData(handle, avcc->avcConfig, avcc->avcConfigSize );
8171 totalbytesread +=bytesread;
8172 return totalbytesread;
8179 * mp4_i32 readBTRT(MP4HandleImp handle,
8180 * mpeg4BitrateAtom *btrt)
8184 * This function parses one btrt atom.
8188 * handle MP4 library handle
8193 * Negative integer Error
8194 * >= 0 Success. Value tells how many bytes were read.
8197 mp4_i32 readBTRT(MP4HandleImp handle, mpeg4BitrateAtom *btrt)
8200 mp4_i32 totalbytesread = 0;
8203 if ((btrt->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8206 bytesread = readAtomHeader(handle, btrt->atomhdr);
8209 totalbytesread +=bytesread;
8211 if (btrt->atomhdr->type != ATOMTYPE_BTRT)
8214 /* read the mpeg4BitrateAtom */
8215 bytesread = readData(handle, handle->buf, 4);
8218 btrt->bufferSizeDB = u32endian(*((mp4_u32 *)handle->buf));
8219 totalbytesread +=bytesread;
8221 bytesread = readData(handle, handle->buf, 4);
8224 btrt->maxBitRate = u32endian(*((mp4_u32 *)handle->buf));
8225 totalbytesread +=bytesread;
8227 bytesread = readData(handle, handle->buf, 4);
8230 btrt->avgBitrate = u32endian(*((mp4_u32 *)handle->buf));
8231 totalbytesread +=bytesread;
8233 return totalbytesread;
8239 * mp4_i32 readM4DS(MP4HandleImp handle,
8240 * mpeg4ExtensionDescriptorsAtom *m4ds)
8244 * This function parses one m4ds atom.
8248 * handle MP4 library handle
8253 * Negative integer Error
8254 * >= 0 Success. Value tells how many bytes were read.
8257 mp4_i32 readM4DS(MP4HandleImp handle, mpeg4ExtensionDescriptorsAtom *m4ds)
8260 mp4_i32 totalbytesread = 0;
8263 m4ds->descrSize = 0;
8265 if ((m4ds->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8268 bytesread = readAtomHeader(handle, m4ds->atomhdr);
8271 totalbytesread +=bytesread;
8273 if (m4ds->atomhdr->type != ATOMTYPE_M4DS)
8276 /* read the avcDecoderConfigurationRecord */
8277 if (m4ds->atomhdr->size != 1)
8278 bytesread = readData(handle, handle->buf, m4ds->atomhdr->size - 8);
8280 bytesread = readData(handle, handle->buf, (mp4_u32)(I64INT(m4ds->atomhdr->largeSize) - 16) );
8284 m4ds->descrSize = bytesread;
8285 m4ds->descr = (mp4_u8 *)mp4malloc(m4ds->descrSize * sizeof(mp4_u8));
8287 /* copy the mpeg4ExtensionDescriptors from the temp. buffer */
8288 for(i = 0; i < m4ds->descrSize; i++)
8289 m4ds->descr[i] = handle->buf[i];
8291 totalbytesread +=bytesread;
8293 return totalbytesread;
8299 * mp4_i32 readAVC1(MP4HandleImp handle,
8300 * avcSampleEntry *avc1)
8304 * This function parses one avc1 atom.
8308 * handle MP4 library handle
8313 * Negative integer Error
8314 * >= 0 Success. Value tells how many bytes were read.
8317 mp4_i32 readAVC1(MP4HandleImp handle, avcSampleEntry *avc1)
8320 mp4_i32 totalbytesread = 0;
8322 if ((avc1->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8325 bytesread = readAtomHeader(handle, avc1->atomhdr);
8329 totalbytesread += bytesread;
8331 if (avc1->atomhdr->type != ATOMTYPE_AVC1)
8334 bytesread = discardData(handle, 6);
8337 totalbytesread += bytesread;
8339 bytesread = readData(handle, handle->buf, 2);
8342 avc1->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
8343 totalbytesread += bytesread;
8345 bytesread = discardData(handle, 16);
8348 totalbytesread += bytesread;
8350 bytesread = readData(handle, handle->buf, 2);
8353 avc1->width = u16endian(*((mp4_u16 *)handle->buf));
8354 totalbytesread += bytesread;
8356 bytesread = readData(handle, handle->buf, 2);
8359 avc1->height = u16endian(*((mp4_u16 *)handle->buf));
8360 totalbytesread += bytesread;
8362 bytesread = discardData(handle, 50);
8365 totalbytesread += bytesread;
8367 /* Check for the present atoms */
8368 while ((mp4_u32)totalbytesread < avc1->atomhdr->size)
8372 if (peekData(handle, handle->buf, 8) < 0)
8375 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
8381 if (avc1->avcc) /* avcC has already been read, more than one is not allowed. */
8384 if ((avc1->avcc = (avcConfigurationAtom *)mp4malloc(sizeof(avcConfigurationAtom))) == NULL)
8387 bytesread = readAVCC(handle, avc1->avcc);
8390 totalbytesread +=bytesread;
8395 if (avc1->btrt) /* btrt has already been read, more than one is not allowed. */
8398 if ((avc1->btrt = (mpeg4BitrateAtom *)mp4malloc(sizeof(mpeg4BitrateAtom))) == NULL)
8401 bytesread = readBTRT(handle, avc1->btrt);
8404 totalbytesread +=bytesread;
8409 if (avc1->m4ds) /* m4ds has already been read, more than one is not allowed. */
8412 if ((avc1->m4ds = (mpeg4ExtensionDescriptorsAtom *)mp4malloc(sizeof(mpeg4ExtensionDescriptorsAtom))) == NULL)
8415 bytesread = readM4DS(handle, avc1->m4ds);
8418 totalbytesread +=bytesread;
8423 bytesread = readUnknown(handle);
8426 totalbytesread += bytesread;
8433 return totalbytesread;
8439 * mp4_i32 freeAVCC(avcConfigurationAtom *avcc)
8443 * This function frees memory for avcc atom.
8447 * avcc avcc atom pointer
8455 mp4_i32 freeAVCC(avcConfigurationAtom *avcc)
8459 if (freeAtomHeader(avcc->atomhdr) < 0)
8462 mp4free(avcc->avcConfig);
8473 * mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt)
8477 * This function frees memory for btrt atom.
8481 * btrt btrt atom pointer
8489 mp4_i32 freeBTRT(mpeg4BitrateAtom *btrt)
8493 if (freeAtomHeader(btrt->atomhdr) < 0)
8505 * mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds)
8509 * This function frees memory for m4ds atom.
8513 * m4ds m4ds atom pointer
8521 mp4_i32 freeM4DS(mpeg4ExtensionDescriptorsAtom *m4ds)
8525 if (freeAtomHeader(m4ds->atomhdr) < 0)
8528 mp4free(m4ds->descr);
8539 * mp4_i32 freeAVC1(avcSampleEntry *avc1)
8543 * This function frees memory for avc1 atom.
8547 * avc1 avc1 atom pointer
8555 mp4_i32 freeAVC1(avcSampleEntry *avc1)
8559 if (freeAtomHeader(avc1->atomhdr) < 0)
8561 if (freeAVCC(avc1->avcc) < 0)
8563 if (freeBTRT(avc1->btrt) < 0)
8565 if (freeM4DS(avc1->m4ds) < 0)
8577 * mp4_i32 readSQCP(MP4HandleImp handle,
8578 * qcelpSampleEntry *sqcp)
8582 * This function parses one SQCP atom.
8586 * handle MP4 library handle
8591 * Negative integer Error
8592 * >= 0 Success. Value tells how many bytes were read.
8595 mp4_i32 readSQCP(MP4HandleImp handle, qcelpSampleEntry *sqcp)
8598 mp4_i32 totalbytesread = 0;
8601 if ((sqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8604 bytesread = readAtomHeader(handle, sqcp->atomhdr);
8607 totalbytesread += bytesread;
8609 if (sqcp->atomhdr->type != ATOMTYPE_SQCP)
8613 bytesread = discardData(handle, 6);
8616 totalbytesread += bytesread;
8618 bytesread = readData(handle, handle->buf, 2);
8621 sqcp->dataReferenceIndex = u16endian(*((mp4_u16 *)handle->buf));
8622 totalbytesread += bytesread;
8624 bytesread = discardData(handle, 16);
8627 totalbytesread += bytesread;
8629 bytesread = readData(handle, handle->buf, 2);
8632 sqcp->timeScale = u16endian(*((mp4_u16 *)handle->buf));
8633 totalbytesread += bytesread;
8635 bytesread = discardData(handle, 2);
8638 totalbytesread += bytesread;
8640 if ((sqcp->dqcp = (qcelpDecSpecStruc *)mp4malloc(sizeof(qcelpDecSpecStruc))) == NULL)
8643 bytesread = readDQCP(handle, sqcp->dqcp);
8646 totalbytesread += bytesread;
8648 if ( totalbytesread < sqcp->atomhdr->size )
8650 bytesread = discardData(handle, sqcp->atomhdr->size - totalbytesread );
8655 totalbytesread += bytesread;
8658 return totalbytesread;
8664 * mp4_i32 freeSQCP(qcelpSampleEntry *sqcp)
8668 * This function frees memory for SQCP atom.
8672 * sqcp SQCP atom pointer
8680 mp4_i32 freeSQCP(qcelpSampleEntry *sqcp)
8684 if (freeAtomHeader(sqcp->atomhdr) < 0)
8686 if (freeDQCP(sqcp->dqcp) < 0)
8698 * mp4_i32 readDQCP(MP4HandleImp handle,
8699 * qcelpDecSpecStruc *dqcp)
8703 * This function parses one DQCP atom.
8707 * handle MP4 library handle
8712 * Negative integer Error
8713 * >= 0 Success. Value tells how many bytes were read.
8716 mp4_i32 readDQCP(MP4HandleImp handle, qcelpDecSpecStruc *dqcp)
8719 mp4_i32 totalbytesread = 0;
8722 if ((dqcp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8725 bytesread = readAtomHeader(handle, dqcp->atomhdr);
8728 totalbytesread += bytesread;
8730 if (dqcp->atomhdr->type != ATOMTYPE_DQCP)
8734 bytesread = readData(handle, handle->buf, 4);
8737 dqcp->vendor = u32endian(*((mp4_u32 *)handle->buf));
8738 totalbytesread += bytesread;
8740 bytesread = readData(handle, handle->buf, 1);
8743 dqcp->decoderVersion = handle->buf[0];
8744 totalbytesread += bytesread;
8746 bytesread = readData(handle, handle->buf, 1);
8749 dqcp->framesPerSample = handle->buf[0];
8750 totalbytesread += bytesread;
8752 return totalbytesread;
8758 * mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp)
8762 * This function frees memory for DQCP atom.
8766 * damr DQCP atom pointer
8774 mp4_i32 freeDQCP(qcelpDecSpecStruc *dqcp)
8778 if (freeAtomHeader(dqcp->atomhdr) < 0)
8790 * mp4_i32 readSDTP(MP4HandleImp handle, sampleDependencyAtom *sdtp,
8791 * mp4_i32 sample_count)
8795 * This function parses one SDTP atom.
8799 * handle MP4 library handle
8800 * sdtp SDTP atom pointer
8804 * Negative integer Error
8805 * >= 0 Success. Value tells how many bytes were read.
8809 mp4_i32 readSDTP(MP4HandleImp handle,
8810 sampleDependencyAtom *sdtp,
8811 mp4_i32 sample_count)
8813 mp4_i32 bytesread = 0;
8814 mp4_i32 totalbytesread = 0;
8817 if ((sdtp->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8820 bytesread = readAtomHeader(handle, sdtp->atomhdr);
8823 totalbytesread += bytesread;
8825 if (sdtp->atomhdr->type != ATOMTYPE_SDTP)
8828 bytesread = readData(handle, handle->buf, 1); //Version must be 0
8829 if (bytesread < 0 || handle->buf[0] != 0)
8831 totalbytesread += bytesread;
8832 bytesread = readData(handle, handle->buf, 3); // Flags must be 0
8833 if (bytesread < 0 || handle->buf[0] != 0 || handle->buf[1] != 0 || handle->buf[2] != 0)
8835 totalbytesread += bytesread;
8837 // sample_count == (size_of_atom - 12) ??? 12 = size + 'sdtp' + ver + flags = 4 + 4 + 1 + 3 ???
8839 // sample_count is taken from the sample_count in the Sample Size Box ('stsz') or
8840 // Compact Sample Size Box (‘stz2’).
8841 if (sample_count != sdtp->atomhdr->size-12 || sample_count < 0)
8843 // as each byte consititue one entry in the table, the number of remaining bytes in this
8844 // atom should match the sample count. If not, the file is corrupted.
8848 if ((sdtp->dep = (sampleDependency *)mp4malloc(sample_count * sizeof(sampleDependency))) == NULL)
8851 for(i=0;i<sample_count;i++)
8853 bytesread = readData(handle, handle->buf, 1);
8857 sdtp->dep[i].sDependsOn = (handle->buf[0] >> 4) & 0x03; // value from 0 to 3
8858 sdtp->dep[i].sIsDependentOn = (handle->buf[0] >> 2) & 0x03; // value from 0 to 3
8859 sdtp->dep[i].sHasRedundancy = handle->buf[0] & 0x03; // value from 0 to 3
8860 totalbytesread += bytesread;
8863 sdtp->sampleCount = sample_count;
8864 return totalbytesread;
8870 * mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type)
8875 * This function parses the size and type information for a box.
8876 * Taking into account largesize if needed.
8880 * handle MP4 library handle
8881 * size Size of box is returned here
8882 * type Type of the box is returned here
8885 * Negative integer Error
8889 mp4_i32 readBoxHeader(MP4HandleImp handle, mp4_i64* size, mp4_u32* type)
8891 if (peekData(handle, handle->buf, 8) < 0)
8894 *size = u32endian(*((mp4_u32 *)handle->buf));
8895 *type = u32endian(*((mp4_u32 *)(handle->buf+4)));
8899 if (peekData(handle, handle->buf, 16) < 0)
8902 *size = u64endian(*((mp4_u64 *)(handle->buf+8)));
8911 mp4_i64 getChunkOffset(sampleTableAtom *stbl, mp4_u32 index)
8913 if (stbl->is32BitOffsets)
8914 return (mp4_i64)stbl->stco->chunkOffset[index];
8916 return stbl->stco64->chunkOffset[index];
8922 * mp4_i32 readMeta(MP4HandleImp handle,
8927 * This function parses one META atom.
8931 * handle MP4 library handle
8936 * Negative integer Error
8937 * >= 0 Success. Value tells how many bytes were read.
8940 mp4_i32 readMeta(MP4HandleImp handle, metaAtom *meta)
8943 mp4_i32 totalbytesread = 0;
8946 if ((meta->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
8949 bytesread = readFullAtomHeader(handle, meta->atomhdr);
8952 totalbytesread += bytesread;
8954 if (meta->atomhdr->type != ATOMTYPE_META)
8958 while ((mp4_u32)totalbytesread < meta->atomhdr->size)
8963 if (peekData(handle, handle->buf, 8) < 0)
8966 type = u32endian(*((mp4_u32 *)(handle->buf+4)));
8972 if (meta->hdlr) /* HDLR has already been read, more than one is not allowed */
8975 if ((meta->hdlr = (handlerAtom *)mp4malloc(sizeof(handlerAtom))) == NULL)
8978 bytesread = readHDLR(handle, meta->hdlr);
8981 totalbytesread += bytesread;
8987 if (meta->ID32) /* ID32 has already been read, more than one is not allowed */
8990 if ((meta->ID32 = (ID32Atom *)mp4malloc(sizeof(ID32Atom))) == NULL)
8993 bytesread = readID32(handle, meta->ID32);
8996 totalbytesread += bytesread;
9002 bytesread = readUnknown(handle);
9005 totalbytesread += bytesread;
9011 return totalbytesread;
9017 * mp4_i32 readID32(MP4HandleImp handle,
9022 * This function parses one ID32 atom.
9026 * handle MP4 library handle
9031 * Negative integer Error
9032 * >= 0 Success. Value tells how many bytes were read.
9035 mp4_i32 readID32(MP4HandleImp handle, ID32Atom *ID32)
9038 mp4_i32 totalbytesread = 0;
9041 if ((ID32->atomhdr = (atomHeader *)mp4malloc(sizeof(atomHeader))) == NULL)
9044 bytesread = readFullAtomHeader(handle, ID32->atomhdr);
9047 totalbytesread += bytesread;
9049 if (ID32->atomhdr->type != ATOMTYPE_ID32)
9052 // next 2 bytes: top bit is padding, remaining 15 bits is Packed ISO-639-2/T language code
9053 bytesread = readData(handle, handle->buf, 2);
9056 ID32->language = u16endian(*((mp4_u16 *)handle->buf));
9057 totalbytesread += bytesread;
9061 ID32->atomcontentloc = handle->diskReadBufStart + handle->diskReadBufPos;
9065 ID32->atomcontentloc = handle->absPosition;
9068 bytesread = discardData(handle, ID32->atomhdr->size - totalbytesread );
9071 totalbytesread += bytesread;
9073 return totalbytesread;
9079 * mp4_i32 freeMETA(metaAtom *meta)
9083 * This function frees memory for META atom.
9087 * meta META atom pointer
9095 mp4_i32 freeMETA(metaAtom *meta)
9099 if (freeAtomHeader(meta->atomhdr) < 0)
9101 if (freeHDLR(meta->hdlr) < 0)
9103 if (freeID32(meta->ID32) < 0)
9115 * mp4_i32 freeID32(ID32Atom *ID32)
9119 * This function frees memory for ID32 atom.
9123 * ID32 ID32 atom pointer
9131 mp4_i32 freeID32(ID32Atom *ID32)
9135 if (freeAtomHeader(ID32->atomhdr) < 0)