# HG changeset patch # User nenolod # Date 1130193212 25200 # Node ID 6a86fdd4dea4eb87b9ace9d0978e6e3b4c523c45 # Parent 9780c2671a6215f49b5bc912f1c2c26450b2893d [svn] Replacement libmp4v2. diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/3gp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/3gp.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,126 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +#define _3GP_MAJOR_BRAND "3gp5" +#define _3GP_MINOR_VERSION 0x0001 + +void MP4File::Make3GPCompliant(const char* fileName, char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount, bool deleteIodsAtom) +{ + char brand[5] = "3gp5"; + char* _3gpSupportedBrands[1] = { (char*)&brand }; + + if (majorBrand) { + if (!supportedBrands || !supportedBrandsCount) { + throw new MP4Error("Invalid parameters", "MP4File::Make3GPCompliant"); + } + } + + MakeFtypAtom( + majorBrand ? majorBrand : (char*)brand, + majorBrand ? minorVersion : _3GP_MINOR_VERSION, + majorBrand ? supportedBrands : (char**)_3gpSupportedBrands, + majorBrand ? supportedBrandsCount : 1); + + if (deleteIodsAtom) { + // Delete the iods atom, if it exists.... + MP4Atom* iodsAtom = m_pRootAtom->FindAtom("moov.iods"); + if (iodsAtom) { + MP4Atom* moovAtom = m_pRootAtom->FindAtom("moov"); + ASSERT(moovAtom); + + moovAtom->DeleteChildAtom(iodsAtom); + } + } + +} + +void MP4File::MakeFtypAtom(char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount) +{ + bool rewriteNeeded = false; + u_int32_t currentSupportedBrandsCount; + u_int32_t i; + + + MP4Atom* ftypAtom = m_pRootAtom->FindAtom("ftyp"); + if (ftypAtom == NULL) { + ftypAtom = InsertChildAtom(m_pRootAtom, "ftyp", 0); + } + if (majorBrand == NULL) + return; + MP4StringProperty* pMajorBrandProperty; + ftypAtom->FindProperty( + "ftyp.majorBrand", + (MP4Property**)&pMajorBrandProperty); + + pMajorBrandProperty->SetValue(majorBrand); + + + MP4Integer32Property* pMinorVersionProperty; + ftypAtom->FindProperty( + "ftype.minorVersion", + (MP4Property**)&pMinorVersionProperty); + + pMinorVersionProperty->SetValue(minorVersion); + + MP4Integer32Property* pCompatibleBrandsCountProperty; + ftypAtom->FindProperty( + "ftyp.compatibleBrandsCount", + (MP4Property**)&pCompatibleBrandsCountProperty); + + currentSupportedBrandsCount = pCompatibleBrandsCountProperty->GetValue(); + + MP4TableProperty* pCompatibleBrandsProperty; + ftypAtom->FindProperty( + "ftyp.compatibleBrands", + (MP4Property**)&pCompatibleBrandsProperty); + + MP4StringProperty* pBrandProperty = (MP4StringProperty*) + pCompatibleBrandsProperty->GetProperty(0); + ASSERT(pBrandProperty); + + for (i = 0 ; i < ((currentSupportedBrandsCount > supportedBrandsCount) ? supportedBrandsCount : currentSupportedBrandsCount) ; i++) { + pBrandProperty->SetValue(supportedBrands[i], i); + + } + + if (i < supportedBrandsCount) { + for ( ; i < supportedBrandsCount ; i++) { + pBrandProperty->AddValue(supportedBrands[i]); + } + } + + if (currentSupportedBrandsCount != supportedBrandsCount) { + rewriteNeeded = true; + pBrandProperty->SetCount(supportedBrandsCount); + pCompatibleBrandsCountProperty->SetReadOnly(false); + pCompatibleBrandsCountProperty->SetValue(supportedBrandsCount); + pCompatibleBrandsCountProperty->SetReadOnly(true); + } + +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/API_CHANGES --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/API_CHANGES Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,124 @@ +Changes in xxxx +--------------- +Change to MP4Create and MP4Modify to allow flags to be set for 64 bit +to allow Quicktime compatibility +Change to MP4CloneTrack and MP4CopyTrack for when you copy a hint +track - you must now specify the track ID in the new file for the +reference track. + +Changes in 0.9.9 +--------------------------- +Added support for ISMA's Ismacrypt specification: + MP4GetTrackEsdsObjectTypeId replaces MP4GetTrackAudioType + and MP4GetTrackVideoType. + MP4EncAndCloneTrack is used instead of MP4CloneTrack to encrypt a track + while cloning it. + MP4EncAndCopyTrack is used instead of MP4CopyTrack to encrypt a track + while copying it. + MP4AddEncAudioTrack adds an encrypted audio track. + MP4AddEncVideoTrack adds an encrypted video track. + + +Changes in 0.9.8 +--------------------------- + MP4WriteSample - changed "uint8_t * data" to "const uint8_t *data" + +Changes from 0.9.6 +--------------------------- +Modified + MP4SetHintTrackRtpPayload + payload parameter to get a dynamic payload is MP4_SET_DYNAMIC_PAYLOAD + (value 0xff) instead of 0. + +Changes from 0.9.5 to 0.9.6 +--------------------------- +Modified + MP4GetHintTrackRtpPayload + MP4SetHintTrackRtpPayload + get/set the encoding params (a=rtpmap /[/]) + +Changes from 0.9.4 to 0.9.5 +--------------------------- +Added + MP4GetTrackAudioMpeg4Type() + Returns MPEG-4 Audio type (e.g. AAC, CELP, HXVC, MIDI, etc.) + MP4ReadSampleFromTime() + Variant of MP4ReadSample() that uses time instead of sample id + (basically MP4GetSampleIdFromTime() + MP4ReadSample()) + MP4Info() + MP4FileInfo() + Returns summary info on tracks in file (from util/mp4info.cpp) + + The following functions add support for mp4 authoring/editting: + + MP4CloneTrack() + Make a copy of a specified track, without media samples + MP4CopyTrack() + Make a copy of a specified track, with or without media samples + MP4CopySample() + Make a copy of a specified media sample + + MP4AddTrackEdit() + Add a track edit list element + MP4DeleteTrackEdit() + Delete a track edit list element + MP4GetTrackNumberOfEdits() + Return the number of track edit list elements + MP4GetTrackEditTotalDuration() + Return the total duration of the track edit list + MP4GetTrackEditStart() + Return the edit start time for the edit list element + MP4GetTrackEditMediaStart() + Return the media start time for the edit list element + MP4SetTrackEditMediaStart() + Set the media start time for the edit list element + MP4GetTrackEditDuration() + Return the edit list element duration + MP4SetTrackEditDuration() + Set the edit list element duration + MP4GetTrackEditDwell() + Return the edit list element dwell parameter, see man page + MP4SetTrackEditDwell() + Set the edit list element dwell parameter, see man page + MP4ReadSampleFromEditTime() + Apply the edit list timeline to reading a sample + MP4GetSampleIdFromEditTime() + Return the sample id for a specified time on the edit list timeline + +Modified + MP4GetSampleIdFromTime() + Semantic change - now returns sample id corresponding + to specified time, not the sample id with the smallest positive + start time difference from the specified time. + + +Changes from 0.9.3 to 0.9.4 +--------------------------- +Added + MP4GetTrackVideoFrameRate() + Returns video frame rate (average rate if video is variable rate). + + MP4GetTrackBitRate() + Returns track average bit rate in bits-per-second. + +Changes from 0.9.2 to 0.9.3 +--------------------------- +Modified + MP4Optimize() + Second argument, newFileName, can now be NULL in which case + a temporary file is created for the results of the optimization. + Upon success, the existing file specified with the first argument + is overwritten with the optimized file. + + MP4GetNumberOfTracks() + MP4FindTrackId() + Both have a new optional argument, subType, with default value 0. + The subType can be specified for audio and video tracks to + match only a specific encoding type. See man page for more details. + +Added + MP4GetTrackVideoWidth() + Returns video width in pixels. See man page for caveat. + + MP4GetTrackVideoHeight() + Returns video height in pixels. See man page for caveat. diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/INTERNALS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/INTERNALS Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,223 @@ +January 7, 2002 + +MP4V2 LIBRARY INTERNALS +======================= + +This document provides an overview of the internals of the mp4v2 library +to aid those who wish to modify and extend it. Before reading this document, +I recommend familiarizing yourself with the MP4 (or Quicktime) file format +standard and the mp4v2 library API. The API is described in a set of man pages +in mpeg4ip/doc/mp4v2, or if you prefer by looking at mp4.h. + +All the library code is written in C++, however the library API follows uses +C calling conventions hence is linkable by both C and C++ programs. The +library has been compiled and used on Linux, BSD, Windows, and Mac OS X. +Other than libc, the library has no external dependencies, and hence can +be used independently of the mpeg4ip package if desired. The library is +used for both real-time recording and playback in mpeg4ip, and its runtime +performance is up to those tasks. On the IA32 architecture compiled with gcc, +the stripped library is approximately 600 KB code and initialized data. + +It is useful to think of the mp4v2 library as consisting of four layers: +infrastructure, file format, generic tracks, and type specific track helpers. +A description of each layer follows, from the fundamental to the optional. + + +Infrastructure +============== + +The infrastructure layer provides basic file I/O, memory allocation, +error handling, string utilities, and protected arrays. The source files +for this layer are mp4file_io, mp4util, and mp4array. + +Note that the array classes uses preprocessor macros instead of C++ +templates. The rationale for this is to increase portability given the +sometimes incomplete support by some compilers for templates. + + +File Format +=========== + +The file format layer provides the translation from the on-disk MP4 file +format to in-memory C++ structures and back to disk. It is intended +to exactly match the MP4 specification in syntax and semantics. It +represents the majority of the code. + +There are three key structures at the file format layer: atoms, properties, +and descriptors. + +Atoms are the primary containers within an mp4 file. They can contain +any combination of properties, other atoms, or descriptors. + +The mp4atom files contain the base class for all the atoms, and provide +generic functions that cover most cases. Most atoms are covered in +atom_standard.cpp. Atoms that have a special read, generation or +write needs are contained in their subclass contained in file atom_.cpp, + where is the four letter name of the atom defined in the MP4 +specification. + +Atoms that only specifies the properties of the atom or the possible child +atoms in the case of a container atom are located in atom_standard.cpp. + +In more specialized cases the atom specific file provides routines to +initialize, read, or write the atom. + +Properties are the atomic pieces of information. The basic types of +properties are integers, floats, strings, and byte arrays. For integers +and floats there are subclasses that represent the different storage sizes, +e.g. 8, 16, 24, 32, and 64 bit integers. For strings, there is 1 property +class with a number of options regarding exact storage details, e.g. null +terminated, fixed length, counted. + +For implementation reasons, there are also two special properties, table +and descriptor, that are actually containers for groups of properties. +I.e by making these containers provide a property interface much code can +be written in a generic fashion. + +The mp4property files contain all the property related classes. + +Descriptors are containers that derive from the MPEG conventions and use +different encoding rules than the atoms derived from the QuickTime file +format. This means more use of bitfields and conditional existence with +an emphasis on bit efficiency at the cost of encoding/decoding complexity. +Descriptors can contain other descriptors and/or properties. + +The mp4descriptor files contain the generic base class for descriptors. +Also the mp4property files have a descriptor wrapper class that allows a +descriptor to behave as if it were a property. The specific descriptors +are implemented as subclasses of the base class descriptor in manner similar +to that of atoms. The descriptors, ocidescriptors, and qosqualifiers files +contain these implementations. + +Each atom/property/descriptor has a name closely related to that in the +MP4 specification. The difference being that the mp4v2 library doesn't +use '-' or '_' in property names and capitalizes the first letter of each +word, e.g. "thisIsAPropertyName". A complete name specifies the complete +container path. The names follow the C/C++ syntax for elements and array +indices. + +Examples are: + "moov.mvhd.duration" + "moov.trak[2].tkhd.duration" + "moov.trak[3].minf.mdia.stbl.stsz[101].sampleSize" + +Note "*" can be used as a wildcard for an atom name (only). This is most +useful when dealing with the stsd atom which contains child atoms with +various names, but shared property names. + +Note that internally when performance matters the code looks up a property +by name once, and then stores the returned pointer to the property class. + +To add an atom, first you should see if an existing atom exists that +can be used. If not, you need to decide if special read/write or +generate properties need to be established; for example a property in the atom +changes other properties (adds, or subtracts). If there are no +special cases, add the atom properties to atom_standard.cpp. If there +are special properties, add a new file, add a new class to atoms.h, and +add the class to MP4Atom::CreateAtom in mp4atom.cpp. + + + +Generic Tracks +============== + +The two entities at this level are the mp4 file as a whole and the tracks +which are contained with it. The mp4file and mp4track files contain the +implementation. + +The critical work done by this layer is to map the collection of atoms, +properties, and descriptors that represent a media track into a useful, +and consistent set of operations. For example, reading or writing a media +sample of a track is a relatively simple operation from the library API +perspective. However there are numerous pieces of information in the mp4 +file that need to be properly used and updated to do this. This layer +handles all those details. + +Given familiarity with the mp4 spec, the code should be straight-forward. +What may not be immediately obvious are the functions to handle chunks of +media samples. These exist to allow optimization of the mp4 file layout by +reordering the chunks on disk to interleave the media sample chunks of +multiple tracks in time order. (See MP4Optimize API doc). + + +Type Specific Track Helpers +=========================== + +This specialized code goes beyond the meta-information about tracks in +the mp4 file to understanding and manipulating the information in the +track samples. There are currently two helpers in the library: +the MPEG-4 Systems Helper, and the RTP Hint Track Helper. + +The MPEG-4 Systems Helper is currently limited to creating the OD, BIFS, +and SDP information about a minimal audio/video scene consistent with +the Internet Streaming Media Alliance (ISMA) specifications. We will be +evaluating how best to generalize the library's helper functions for +MPEG-4 Systems without overburdening the implementation. The code for +this helper is found in the isma and odcommands files. + +The RTP Hint Track Helper is more extensive in its support. The hint +tracks contain the track packetization information needed to build +RTP packets for streaming. The library can construct RTP packets based +on the hint track making RTP based servers significantly easier to write. + +All code related to rtp hint tracks is in the rtphint files. It would also +be useful to look at test/mp4broadcaster and mpeg4ip/server/mp4creator for +examples of how this part of the library API can be used. + + +Library API +=========== + +The library API is defined and implemented in the mp4 files. The API uses +C linkage conventions, and the mp4.h file adapts itself according to whether +C or C++ is the compilation mode. + +All API calls are implemented in mp4.cpp and basically pass thru's to the +MP4File member functions. This ensures that the library has internal access +to the same functions as available via the API. All the calls in mp4.cpp use +C++ try/catch blocks to protect against any runtime errors in the library. +Upon error the library will print a diagnostic message if the verbostiy level +has MP4_DETAILS_ERROR set, and return a distinguished error value, typically +0 or -1. + +The test and util subdirectories contain useful examples of how to +use the library. Also the mp4creator and mp4live programs within +mpeg4ip demonstrate more complete usage of the library API. + + +Debugging +========= + +Since mp4 files are fairly complicated, extensive debugging support is +built into the library. Multi-level diagnostic messages are available +under the control of a verbosity bitmask described in the API. + +Also the library provides the MP4Dump() call which provides an ASCII +version of the mp4 file meta-information. The mp4dump utilitity is a +wrapper executable around this function. + +The mp4extract program is also provided in the utilities directory +which is useful for extracting a track from an mp4file and putting the +media data back into it's own file. It can also extract each sample of +a track into its own file it that is desired. + +When all else fails, mp4 files are amenable to debugging by direct +examination. Since the atom names are four letter ASCII codes finding +reference points in a hex dump is feasible. On UNIX, the od command +is your friend: "od -t x1z -A x [-j 0xXXXXXX] foo.mp4" will print +a hex and ASCII dump, with hex addresses, starting optionally from +a specified offset. The library diagnostic messages can provide +information on where the library is reading or writing. + + +General caveats +=============== + +The coding convention is to use the C++ throw operator whenever an +unrecoverable error occurs. This throw is caught at the API layer +in mp4.cpp and translated into an error value. + +Be careful about indices. Internally, we follow the C/C++ convention +to use zero-based indices. However the MP4 spec uses one-based indices +for things like samples and hence the library API uses this convention. + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/Makefile.am Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,89 @@ +INCLUDES = -I../include -I. + +lib_LTLIBRARIES = libmp4v2.la + +include_HEADERS = mp4.h + +libmp4v2_la_SOURCES = \ + 3gp.cpp \ + atom_amr.cpp \ + atom_avc1.cpp \ + atom_avcC.cpp \ + atom_d263.cpp \ + atom_damr.cpp \ + atom_dref.cpp \ + atom_elst.cpp \ + atom_enca.cpp \ + atom_encv.cpp \ + atom_free.cpp \ + atom_ftyp.cpp \ + atom_hdlr.cpp \ + atom_hinf.cpp \ + atom_hnti.cpp \ + atom_href.cpp \ + atom_mdat.cpp \ + atom_mdhd.cpp \ + atom_meta.cpp \ + atom_mp4a.cpp \ + atom_mp4s.cpp \ + atom_mp4v.cpp \ + atom_mvhd.cpp \ + atom_root.cpp \ + atom_rtp.cpp \ + atom_s263.cpp \ + atom_sdp.cpp \ + atoms.h \ + atom_smi.cpp \ + atom_sound.cpp \ + atom_standard.cpp \ + atom_stbl.cpp \ + atom_stdp.cpp \ + atom_stsc.cpp \ + atom_stsd.cpp \ + atom_stsz.cpp \ + atom_tfhd.cpp \ + atom_tkhd.cpp \ + atom_treftype.cpp \ + atom_trun.cpp \ + atom_udta.cpp \ + atom_url.cpp \ + atom_urn.cpp \ + atom_video.cpp \ + atom_vmhd.cpp \ + descriptors.cpp \ + descriptors.h \ + isma.cpp \ + mp4array.h \ + mp4atom.cpp \ + mp4atom.h \ + mp4common.h \ + mp4container.cpp \ + mp4container.h \ + mp4.cpp \ + mp4descriptor.cpp \ + mp4descriptor.h \ + mp4file.cpp \ + mp4file.h \ + mp4file_io.cpp \ + mp4info.cpp \ + mp4meta.cpp \ + mp4property.cpp \ + mp4property.h \ + mp4track.cpp \ + mp4track.h \ + mp4util.cpp \ + mp4util.h \ + ocidescriptors.cpp \ + ocidescriptors.h \ + odcommands.cpp \ + odcommands.h \ + qosqualifiers.cpp \ + qosqualifiers.h \ + rtphint.cpp \ + rtphint.h + +EXTRA_DIST = API_CHANGES \ + INTERNALS \ + libmp4v260.dsp \ + libmp4v2_st60.dsp \ + TODO diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/Makefile.in Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,748 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = Input/aac/libmp4v2 +DIST_COMMON = README $(include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in TODO +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 $(top_srcdir)/m4/inttypes.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/ulonglong.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libmp4v2_la_LIBADD = +am_libmp4v2_la_OBJECTS = 3gp.lo atom_amr.lo atom_avc1.lo atom_avcC.lo \ + atom_d263.lo atom_damr.lo atom_dref.lo atom_elst.lo \ + atom_enca.lo atom_encv.lo atom_free.lo atom_ftyp.lo \ + atom_hdlr.lo atom_hinf.lo atom_hnti.lo atom_href.lo \ + atom_mdat.lo atom_mdhd.lo atom_meta.lo atom_mp4a.lo \ + atom_mp4s.lo atom_mp4v.lo atom_mvhd.lo atom_root.lo \ + atom_rtp.lo atom_s263.lo atom_sdp.lo atom_smi.lo atom_sound.lo \ + atom_standard.lo atom_stbl.lo atom_stdp.lo atom_stsc.lo \ + atom_stsd.lo atom_stsz.lo atom_tfhd.lo atom_tkhd.lo \ + atom_treftype.lo atom_trun.lo atom_udta.lo atom_url.lo \ + atom_urn.lo atom_video.lo atom_vmhd.lo descriptors.lo isma.lo \ + mp4atom.lo mp4container.lo mp4.lo mp4descriptor.lo mp4file.lo \ + mp4file_io.lo mp4info.lo mp4meta.lo mp4property.lo mp4track.lo \ + mp4util.lo ocidescriptors.lo odcommands.lo qosqualifiers.lo \ + rtphint.lo +libmp4v2_la_OBJECTS = $(am_libmp4v2_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libmp4v2_la_SOURCES) +DIST_SOURCES = $(libmp4v2_la_SOURCES) +includeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +ARCH_DEFINES = @ARCH_DEFINES@ +ARCH_X86_FALSE = @ARCH_X86_FALSE@ +ARCH_X86_TRUE = @ARCH_X86_TRUE@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BEEP_DEFINES = @BEEP_DEFINES@ +BEEP_PATH = @BEEP_PATH@ +BMP_RCPATH = @BMP_RCPATH@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EFFECT_PLUGINS = @EFFECT_PLUGINS@ +EFFECT_PLUGIN_DIR = @EFFECT_PLUGIN_DIR@ +EGREP = @EGREP@ +ENABLE_AAC_FALSE = @ENABLE_AAC_FALSE@ +ENABLE_AAC_TRUE = @ENABLE_AAC_TRUE@ +ENABLE_MPG123_FALSE = @ENABLE_MPG123_FALSE@ +ENABLE_MPG123_TRUE = @ENABLE_MPG123_TRUE@ +ESD_CFLAGS = @ESD_CFLAGS@ +ESD_LIBS = @ESD_LIBS@ +EXEEXT = @EXEEXT@ +GCONF_CFLAGS = @GCONF_CFLAGS@ +GCONF_LIBS = @GCONF_LIBS@ +GENCAT = @GENCAT@ +GENERAL_PLUGINS = @GENERAL_PLUGINS@ +GENERAL_PLUGIN_DIR = @GENERAL_PLUGIN_DIR@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +GNOMEVFS_CFLAGS = @GNOMEVFS_CFLAGS@ +GNOMEVFS_LIBS = @GNOMEVFS_LIBS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_ALSA_FALSE = @HAVE_ALSA_FALSE@ +HAVE_ALSA_TRUE = @HAVE_ALSA_TRUE@ +HAVE_CDROM_FALSE = @HAVE_CDROM_FALSE@ +HAVE_CDROM_TRUE = @HAVE_CDROM_TRUE@ +HAVE_ESD_FALSE = @HAVE_ESD_FALSE@ +HAVE_ESD_TRUE = @HAVE_ESD_TRUE@ +HAVE_GCONF_FALSE = @HAVE_GCONF_FALSE@ +HAVE_GCONF_TRUE = @HAVE_GCONF_TRUE@ +HAVE_GNOME_VFS_FALSE = @HAVE_GNOME_VFS_FALSE@ +HAVE_GNOME_VFS_TRUE = @HAVE_GNOME_VFS_TRUE@ +HAVE_LINUX_JOYSTICK_FALSE = @HAVE_LINUX_JOYSTICK_FALSE@ +HAVE_LINUX_JOYSTICK_TRUE = @HAVE_LINUX_JOYSTICK_TRUE@ +HAVE_OGGVORBIS_FALSE = @HAVE_OGGVORBIS_FALSE@ +HAVE_OGGVORBIS_TRUE = @HAVE_OGGVORBIS_TRUE@ +HAVE_OSS_FALSE = @HAVE_OSS_FALSE@ +HAVE_OSS_TRUE = @HAVE_OSS_TRUE@ +HAVE_SOLARIS_FALSE = @HAVE_SOLARIS_FALSE@ +HAVE_SOLARIS_TRUE = @HAVE_SOLARIS_TRUE@ +HAVE_SUN_FALSE = @HAVE_SUN_FALSE@ +HAVE_SUN_TRUE = @HAVE_SUN_TRUE@ +ID3LIBS = @ID3LIBS@ +INPUT_PLUGINS = @INPUT_PLUGINS@ +INPUT_PLUGIN_DIR = @INPUT_PLUGIN_DIR@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +LDFLAGS = @LDFLAGS@ +LIBBEEP_MAJOR_VERSION = @LIBBEEP_MAJOR_VERSION@ +LIBBEEP_MICRO_VERSION = @LIBBEEP_MICRO_VERSION@ +LIBBEEP_MINOR_VERSION = @LIBBEEP_MINOR_VERSION@ +LIBGLADE_CFLAGS = @LIBGLADE_CFLAGS@ +LIBGLADE_LIBS = @LIBGLADE_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +OGG_VORBIS_CFLAGS = @OGG_VORBIS_CFLAGS@ +OGG_VORBIS_LIBS = @OGG_VORBIS_LIBS@ +OUTPUT_PLUGINS = @OUTPUT_PLUGINS@ +OUTPUT_PLUGIN_DIR = @OUTPUT_PLUGIN_DIR@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PC_REQUIRES = @PC_REQUIRES@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGIN_LDFLAGS = @PLUGIN_LDFLAGS@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +USE_SIMD_FALSE = @USE_SIMD_FALSE@ +USE_SIMD_TRUE = @USE_SIMD_TRUE@ +USE_X86ASM_FALSE = @USE_X86ASM_FALSE@ +USE_X86ASM_TRUE = @USE_X86ASM_TRUE@ +VERSION = @VERSION@ +VISUALIZATION_PLUGINS = @VISUALIZATION_PLUGINS@ +VISUALIZATION_PLUGIN_DIR = @VISUALIZATION_PLUGIN_DIR@ +XGETTEXT = @XGETTEXT@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +beepdir = @beepdir@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +plugindir = @plugindir@ +pluginsubs = @pluginsubs@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +INCLUDES = -I../include -I. +lib_LTLIBRARIES = libmp4v2.la +include_HEADERS = mp4.h +libmp4v2_la_SOURCES = \ + 3gp.cpp \ + atom_amr.cpp \ + atom_avc1.cpp \ + atom_avcC.cpp \ + atom_d263.cpp \ + atom_damr.cpp \ + atom_dref.cpp \ + atom_elst.cpp \ + atom_enca.cpp \ + atom_encv.cpp \ + atom_free.cpp \ + atom_ftyp.cpp \ + atom_hdlr.cpp \ + atom_hinf.cpp \ + atom_hnti.cpp \ + atom_href.cpp \ + atom_mdat.cpp \ + atom_mdhd.cpp \ + atom_meta.cpp \ + atom_mp4a.cpp \ + atom_mp4s.cpp \ + atom_mp4v.cpp \ + atom_mvhd.cpp \ + atom_root.cpp \ + atom_rtp.cpp \ + atom_s263.cpp \ + atom_sdp.cpp \ + atoms.h \ + atom_smi.cpp \ + atom_sound.cpp \ + atom_standard.cpp \ + atom_stbl.cpp \ + atom_stdp.cpp \ + atom_stsc.cpp \ + atom_stsd.cpp \ + atom_stsz.cpp \ + atom_tfhd.cpp \ + atom_tkhd.cpp \ + atom_treftype.cpp \ + atom_trun.cpp \ + atom_udta.cpp \ + atom_url.cpp \ + atom_urn.cpp \ + atom_video.cpp \ + atom_vmhd.cpp \ + descriptors.cpp \ + descriptors.h \ + isma.cpp \ + mp4array.h \ + mp4atom.cpp \ + mp4atom.h \ + mp4common.h \ + mp4container.cpp \ + mp4container.h \ + mp4.cpp \ + mp4descriptor.cpp \ + mp4descriptor.h \ + mp4file.cpp \ + mp4file.h \ + mp4file_io.cpp \ + mp4info.cpp \ + mp4meta.cpp \ + mp4property.cpp \ + mp4property.h \ + mp4track.cpp \ + mp4track.h \ + mp4util.cpp \ + mp4util.h \ + ocidescriptors.cpp \ + ocidescriptors.h \ + odcommands.cpp \ + odcommands.h \ + qosqualifiers.cpp \ + qosqualifiers.h \ + rtphint.cpp \ + rtphint.h + +EXTRA_DIST = API_CHANGES \ + INTERNALS \ + libmp4v260.dsp \ + libmp4v2_st60.dsp \ + TODO + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Input/aac/libmp4v2/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu Input/aac/libmp4v2/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libmp4v2.la: $(libmp4v2_la_OBJECTS) $(libmp4v2_la_DEPENDENCIES) + $(CXXLINK) -rpath $(libdir) $(libmp4v2_la_LDFLAGS) $(libmp4v2_la_OBJECTS) $(libmp4v2_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/3gp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_amr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_avc1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_avcC.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_d263.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_damr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_dref.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_elst.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_enca.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_encv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_free.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_ftyp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_hdlr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_hinf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_hnti.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_href.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mdat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mdhd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_meta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mp4a.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mp4s.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mp4v.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_mvhd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_root.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_rtp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_s263.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_sdp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_smi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_sound.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_standard.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_stbl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_stdp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_stsc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_stsd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_stsz.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_tfhd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_tkhd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_treftype.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_trun.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_udta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_url.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_urn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_video.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atom_vmhd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/descriptors.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isma.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4atom.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4container.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4descriptor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4file_io.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4info.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4meta.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4property.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4track.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocidescriptors.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/odcommands.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qosqualifiers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtphint.Plo@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \ + $(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(includedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS + +install-exec-am: install-libLTLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS uninstall-info-am \ + uninstall-libLTLIBRARIES + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-includeHEADERS install-info \ + install-info-am install-libLTLIBRARIES install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-includeHEADERS uninstall-info-am \ + uninstall-libLTLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/README Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,28 @@ +July 18, 2002 + +MP4V2 Library +============= + +This library provides functions to read, create, and modify mp4 files. + +The detailed documentation of the library is available as a set of man pages +in mpeg4ip/doc/mp4v2. The MP4.3 man page gives an overview of the library. + +Alternately mp4.h in this directory specifies the complete API. + +The file INTERNALS provides an overview of what is happening behind the API. +Note that although we using C++ object oriented features internally, that's +all hidden behind a flat C style API (with C linkage conventions). + +The test and util subdirectories contain some simple programs that use +this library. + +Once make install is run, to use this library, you should: +To use this library in your application, it should be sufficient to: + +1) add the installed library to your final link: + e.g. gcc ... -o foo foo.cpp -lmp4v2 + +2) include mp4.h into your code, + e.g. #include + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/TODO --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/TODO Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,9 @@ + +Add ability to create samples referenced in multiple tracks + +Add ability to create atoms/properties via set or add operations + +Exploit extended format (ISO v2) + +List all possible atoms/properties with types + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_amr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_amr.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,65 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +MP4AmrAtom::MP4AmrAtom(const char *type) + : MP4Atom(type) +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("timeScale")); + + AddReserved("reserved3", 2); /* 4 */ + + ExpectChildAtom("damr", Required, OnlyOne); +} + +void MP4AmrAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved2 has non-zero fixed values + static u_int8_t reserved2[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, + }; + m_pProperties[2]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[2])-> + SetValue(reserved2, sizeof(reserved2)); + m_pProperties[2]->SetReadOnly(true); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_avc1.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_avc1.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,81 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + */ + +#include "mp4common.h" + +MP4Avc1Atom::MP4Avc1Atom() + : MP4Atom("avc1") +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("width")); + AddProperty( /* 4 */ + new MP4Integer16Property("height")); + + AddReserved("reserved3", 14); /* 5 */ + + MP4StringProperty* pProp = + new MP4StringProperty("compressorName"); + pProp->SetFixedLength(32); + pProp->SetValue("AVC Coding"); + AddProperty(pProp); /* 6 */ + + AddReserved("reserved4", 4); /* 7 */ + + ExpectChildAtom("avcC", Required, OnlyOne); + ExpectChildAtom("btrt", Optional, OnlyOne); + // for now ExpectChildAtom("m4ds", Optional, OnlyOne); +} + +void MP4Avc1Atom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved3 has non-zero fixed values + static u_int8_t reserved3[14] = { + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + }; + m_pProperties[5]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[5])-> + SetValue(reserved3, sizeof(reserved3)); + m_pProperties[5]->SetReadOnly(true); + + // property reserved4 has non-zero fixed values + static u_int8_t reserved4[4] = { + 0x00, 0x18, 0xFF, 0xFF, + }; + m_pProperties[7]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[7])-> + SetValue(reserved4, sizeof(reserved4)); + m_pProperties[7]->SetReadOnly(true); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_avcC.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_avcC.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,106 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + */ + +#include "mp4common.h" + +/* + * SizeTableProperty is a special version of the MP4TableProperty - + * the BytesProperty will need to set the value before it can read + * from the file + */ +class SizeTableProperty : public MP4TableProperty +{ + public: + SizeTableProperty(char *name, MP4IntegerProperty *pCountProperty) : + MP4TableProperty(name, pCountProperty) {}; + protected: + void ReadEntry(MP4File *pFile, u_int32_t index) { + // Each table has a size, followed by the length field + // first, read the length + m_pProperties[0]->Read(pFile, index); + MP4IntegerProperty *pIntProp = (MP4IntegerProperty *)m_pProperties[0]; + // set the size in the bytes property + MP4BytesProperty *pBytesProp = (MP4BytesProperty *)m_pProperties[1]; + pBytesProp->SetValueSize(pIntProp->GetValue(index), index); + // And read the bytes + m_pProperties[1]->Read(pFile, index); + }; +}; + +MP4AvcCAtom::MP4AvcCAtom() + : MP4Atom("avcC") +{ + MP4BitfieldProperty *pCount; + MP4TableProperty *pTable; + + AddProperty( new MP4Integer8Property("configurationVersion")); /* 0 */ + + AddProperty( new MP4Integer8Property("AVCProfileIndication")); /* 1 */ + + AddProperty( new MP4Integer8Property("profile_compatibility")); /* 2 */ + + AddProperty( new MP4Integer8Property("AVCLevelIndication")); /* 3 */ + + AddProperty( new MP4BitfieldProperty("reserved", 6)); /* 4 */ + AddProperty( new MP4BitfieldProperty("lengthSizeMinusOne", 2)); /* 5 */ + AddProperty( new MP4BitfieldProperty("reserved1", 3)); /* 6 */ + pCount = new MP4BitfieldProperty("numOfSequenceParameterSets", 5); + AddProperty(pCount); /* 7 */ + + pTable = new SizeTableProperty("sequenceEntries", pCount); + AddProperty(pTable); /* 8 */ + pTable->AddProperty(new MP4Integer16Property("sequenceParameterSetLength")); + pTable->AddProperty(new MP4BytesProperty("sequenceParameterSetNALUnit")); + + MP4Integer8Property *pCount2 = new MP4Integer8Property("numOfPictureParameterSets"); + AddProperty(pCount2); /* 9 */ + + pTable = new SizeTableProperty("pictureEntries", pCount2); + AddProperty(pTable); /* 10 */ + pTable->AddProperty(new MP4Integer16Property("pictureParameterSetLength")); + pTable->AddProperty(new MP4BytesProperty("pictureParameterSetNALUnit")); +} + +void MP4AvcCAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer8Property*)m_pProperties[0])->SetValue(1); + + m_pProperties[4]->SetReadOnly(false); + ((MP4BitfieldProperty*)m_pProperties[4])->SetValue(0x3f); + m_pProperties[4]->SetReadOnly(true); + + m_pProperties[6]->SetReadOnly(false); + ((MP4BitfieldProperty*)m_pProperties[6])->SetValue(0x7); + m_pProperties[6]->SetReadOnly(true); +#if 0 + // property reserved4 has non-zero fixed values + static u_int8_t reserved4[4] = { + 0x00, 0x18, 0xFF, 0xFF, + }; + m_pProperties[7]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[7])-> + SetValue(reserved4, sizeof(reserved4)); + m_pProperties[7]->SetReadOnly(true); +#endif +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_d263.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_d263.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,88 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +#define H263_VENDOR 0x6d346970 + +MP4D263Atom::MP4D263Atom() + : MP4Atom("d263") +{ + AddProperty( /* 0 */ + new MP4Integer32Property("vendor")); + + AddProperty( /* 1 */ + new MP4Integer8Property("decoderVersion")); + + AddProperty( /* 2 */ + new MP4Integer8Property("h263Level")); + + AddProperty( /* 3 */ + new MP4Integer8Property("h263Profile")); + + ExpectChildAtom("bitr", Optional, OnlyOne); + +} + +void MP4D263Atom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer32Property*)m_pProperties[0])->SetValue(H263_VENDOR); + ((MP4Integer8Property*)m_pProperties[1])->SetValue(1); + +} + +void MP4D263Atom::Write() +{ + // Check whether we have valid values in the bitr atom + // (if it exists, of course) + MP4Atom* bitrAtom = FindAtom("d263.bitr"); + if (bitrAtom) { + u_int32_t avgBitrate; + u_int32_t maxBitrate; + + MP4Integer32Property* pProp; + bitrAtom->FindProperty("bitr.avgBitrate", + (MP4Property**)&pProp, + NULL); + ASSERT(pProp); + avgBitrate = pProp->GetValue(); + + bitrAtom->FindProperty("bitr.maxBitrate", + (MP4Property**)&pProp, + NULL); + ASSERT(pProp); + maxBitrate = pProp->GetValue(); + + if(!maxBitrate && !avgBitrate) { + DeleteChildAtom(bitrAtom); + } + } + + MP4Atom::Write(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_damr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_damr.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,59 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +#define AMR_VENDOR 0x6d346970 + +MP4DamrAtom::MP4DamrAtom() + : MP4Atom("damr") +{ + AddProperty( /* 0 */ + new MP4Integer32Property("vendor")); + + AddProperty( /* 1 */ + new MP4Integer8Property("decoderVersion")); + + AddProperty( /* 2 */ + new MP4Integer16Property("modeSet")); + + AddProperty( /* 3 */ + new MP4Integer8Property("modeChangePeriod")); + + AddProperty( /* 4 */ + new MP4Integer8Property("framesPerSample")); + +} + +void MP4DamrAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer32Property*)m_pProperties[0])->SetValue(AMR_VENDOR); + ((MP4Integer8Property*)m_pProperties[1])->SetValue(1); + +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_dref.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_dref.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,57 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4DrefAtom::MP4DrefAtom() + : MP4Atom("dref") +{ + AddVersionAndFlags(); + + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + pCount->SetReadOnly(); + AddProperty(pCount); + + ExpectChildAtom("url ", Optional, Many); + ExpectChildAtom("urn ", Optional, Many); + ExpectChildAtom("alis", Optional, Many); +} + +void MP4DrefAtom::Read() +{ + /* do the usual read */ + MP4Atom::Read(); + + // check that number of children == entryCount + MP4Integer32Property* pCount = + (MP4Integer32Property*)m_pProperties[2]; + + if (m_pChildAtoms.Size() != pCount->GetValue()) { + VERBOSE_READ(GetVerbosity(), + MP4Printf("Warning: dref inconsistency with number of entries")); + + /* fix it */ + pCount->SetReadOnly(false); + pCount->SetValue(m_pChildAtoms.Size()); + pCount->SetReadOnly(true); + } +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_elst.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_elst.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,80 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4ElstAtom::MP4ElstAtom() + : MP4Atom("elst") +{ + AddVersionAndFlags(); + + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); +} + +void MP4ElstAtom::AddProperties(u_int8_t version) +{ + MP4TableProperty* pTable = (MP4TableProperty*)m_pProperties[3]; + + if (version == 1) { + pTable->AddProperty( + new MP4Integer64Property("segmentDuration")); + pTable->AddProperty( + new MP4Integer64Property("mediaTime")); + } else { + pTable->AddProperty( + new MP4Integer32Property("segmentDuration")); + pTable->AddProperty( + new MP4Integer32Property("mediaTime")); + } + + pTable->AddProperty( + new MP4Integer16Property("mediaRate")); + pTable->AddProperty( + new MP4Integer16Property("reserved")); +} + +void MP4ElstAtom::Generate() +{ + SetVersion(0); + AddProperties(GetVersion()); + + MP4Atom::Generate(); +} + +void MP4ElstAtom::Read() +{ + /* read atom version */ + ReadProperties(0, 1); + + /* need to create the properties based on the atom version */ + AddProperties(GetVersion()); + + /* now we can read the remaining properties */ + ReadProperties(1); + + Skip(); // to end of atom +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_enca.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_enca.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,61 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + */ + +#include "mp4common.h" + +MP4EncaAtom::MP4EncaAtom() + : MP4Atom("enca") +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("timeScale")); + + AddReserved("reserved3", 2); /* 4 */ + + ExpectChildAtom("esds", Required, OnlyOne); + ExpectChildAtom("sinf", Required, OnlyOne); +} + +void MP4EncaAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved2 has non-zero fixed values + static u_int8_t reserved2[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, + }; + m_pProperties[2]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[2])-> + SetValue(reserved2, sizeof(reserved2)); + m_pProperties[2]->SetReadOnly(true); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_encv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_encv.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,80 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + */ + +#include "mp4common.h" + +MP4EncvAtom::MP4EncvAtom() + : MP4Atom("encv") +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("width")); + AddProperty( /* 4 */ + new MP4Integer16Property("height")); + + AddReserved("reserved3", 14); /* 5 */ + + MP4StringProperty* pProp = + new MP4StringProperty("compressorName"); + pProp->SetFixedLength(32); + pProp->SetValue(""); + AddProperty(pProp); /* 6 */ + AddReserved("reserved4", 4); /* 7 */ + + ExpectChildAtom("esds", Required, OnlyOne); + ExpectChildAtom("sinf", Required, OnlyOne); +} + +void MP4EncvAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved3 has non-zero fixed values + static u_int8_t reserved3[14] = { + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + }; + m_pProperties[5]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[5])-> + SetValue(reserved3, sizeof(reserved3)); + m_pProperties[5]->SetReadOnly(true); + + // property reserved4 has non-zero fixed values + static u_int8_t reserved4[4] = { + 0x00, 0x18, 0xFF, 0xFF, + }; + m_pProperties[7]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[7])-> + SetValue(reserved4, sizeof(reserved4)); + m_pProperties[7]->SetReadOnly(true); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_free.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_free.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,49 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4FreeAtom::MP4FreeAtom() + : MP4Atom("free") +{ +} + +void MP4FreeAtom::Read() +{ + Skip(); +} + +void MP4FreeAtom::Write() +{ + ASSERT(m_pFile); + + bool use64 = (GetSize() > (0xFFFFFFFF - 8)); + BeginWrite(use64); +#if 1 + for (uint64_t ix = 0; ix < GetSize(); ix++) { + m_pFile->WriteUInt8(0); + } +#else + m_pFile->SetPosition(m_pFile->GetPosition() + GetSize()); +#endif + FinishWrite(use64); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_ftyp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_ftyp.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,71 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4FtypAtom::MP4FtypAtom() + : MP4Atom("ftyp") +{ + MP4StringProperty* pProp = new MP4StringProperty("majorBrand"); + pProp->SetFixedLength(4); + AddProperty(pProp); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer32Property("minorVersion")); + + MP4Integer32Property* pCount = + new MP4Integer32Property("compatibleBrandsCount"); + pCount->SetImplicit(); + AddProperty(pCount); /* 2 */ + + MP4TableProperty* pTable = + new MP4TableProperty("compatibleBrands", pCount); + AddProperty(pTable); /* 3 */ + + pProp = new MP4StringProperty("brand"); + pProp->SetFixedLength(4); + pTable->AddProperty(pProp); +} + +void MP4FtypAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4StringProperty*)m_pProperties[0])->SetValue("mp42"); + + MP4StringProperty* pBrandProperty = (MP4StringProperty*) + ((MP4TableProperty*)m_pProperties[3])->GetProperty(0); + ASSERT(pBrandProperty); + pBrandProperty->AddValue("mp42"); + pBrandProperty->AddValue("isom"); + ((MP4Integer32Property*)m_pProperties[2])->IncrementValue(); + ((MP4Integer32Property*)m_pProperties[2])->IncrementValue(); +} + +void MP4FtypAtom::Read() +{ + // table entry count computed from atom size + ((MP4Integer32Property*)m_pProperties[2])->SetReadOnly(false); + ((MP4Integer32Property*)m_pProperties[2])->SetValue((m_size - 8) / 4); + ((MP4Integer32Property*)m_pProperties[2])->SetReadOnly(true); + + MP4Atom::Read(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_hdlr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_hdlr.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,64 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4HdlrAtom::MP4HdlrAtom() + : MP4Atom("hdlr") +{ + AddVersionAndFlags(); /* 0, 1 */ + AddReserved("reserved1", 4); /* 2 */ + MP4StringProperty* pProp = new MP4StringProperty("handlerType"); + pProp->SetFixedLength(4); + AddProperty(pProp); /* 3 */ + AddReserved("reserved2", 12); /* 4 */ + AddProperty( /* 5 */ + new MP4StringProperty("name")); +} + +// There is a spec incompatiblity between QT and MP4 +// QT says name field is a counted string +// MP4 says name field is a null terminated string +// Here we attempt to make all things work +void MP4HdlrAtom::Read() +{ + // read all the properties but the "name" field + ReadProperties(0, 5); + + // take a peek at the next byte + u_int8_t strLength; + m_pFile->PeekBytes(&strLength, 1); + + // if the value matches the remaining atom length + if (m_pFile->GetPosition() + strLength + 1 == GetEnd()) { + // read a counted string + MP4StringProperty* pNameProp = + (MP4StringProperty*)m_pProperties[5]; + pNameProp->SetCountedFormat(true); + ReadProperties(5); + pNameProp->SetCountedFormat(false); + } else { + // read a null terminated string + ReadProperties(5); + } + + Skip(); // to end of atom +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_hinf.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_hinf.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,57 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4HinfAtom::MP4HinfAtom() + : MP4Atom("hinf") +{ + ExpectChildAtom("trpy", Optional, OnlyOne); + ExpectChildAtom("nump", Optional, OnlyOne); + ExpectChildAtom("tpyl", Optional, OnlyOne); + ExpectChildAtom("maxr", Optional, Many); + ExpectChildAtom("dmed", Optional, OnlyOne); + ExpectChildAtom("dimm", Optional, OnlyOne); + ExpectChildAtom("drep", Optional, OnlyOne); + ExpectChildAtom("tmin", Optional, OnlyOne); + ExpectChildAtom("tmax", Optional, OnlyOne); + ExpectChildAtom("pmax", Optional, OnlyOne); + ExpectChildAtom("dmax", Optional, OnlyOne); + ExpectChildAtom("payt", Optional, OnlyOne); +} + +void MP4HinfAtom::Generate() +{ + // hinf is special in that although all it's child atoms + // are optional (on read), if we generate it for writing + // we really want all the children + + for (u_int32_t i = 0; i < m_pChildAtomInfos.Size(); i++) { + MP4Atom* pChildAtom = + CreateAtom(m_pChildAtomInfos[i]->m_name); + + AddChildAtom(pChildAtom); + + // and ask it to self generate + pChildAtom->Generate(); + } +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_hnti.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_hnti.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,40 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4HntiAtom::MP4HntiAtom() + : MP4Atom("hnti") +{ +} + +void MP4HntiAtom::Read() +{ + MP4Atom* grandParent = m_pParentAtom->GetParentAtom(); + ASSERT(grandParent); + if (ATOMID(grandParent->GetType()) == ATOMID("trak")) { + ExpectChildAtom("sdp ", Optional, OnlyOne); + } else { + ExpectChildAtom("rtp ", Optional, OnlyOne); + } + + MP4Atom::Read(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_href.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_href.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2005. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + */ + +#include "mp4common.h" + +MP4HrefAtom::MP4HrefAtom() + : MP4Atom("href") +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); +} + +void MP4HrefAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_mdat.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_mdat.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,38 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4MdatAtom::MP4MdatAtom() + : MP4Atom("mdat") +{ +} + +void MP4MdatAtom::Read() +{ + Skip(); +} + +void MP4MdatAtom::Write() +{ + // should never get here + ASSERT(false); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_mdhd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_mdhd.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,91 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4MdhdAtom::MP4MdhdAtom() + : MP4Atom("mdhd") +{ + AddVersionAndFlags(); +} + +void MP4MdhdAtom::AddProperties(u_int8_t version) +{ + if (version == 1) { + AddProperty( + new MP4Integer64Property("creationTime")); + AddProperty( + new MP4Integer64Property("modificationTime")); + } else { + AddProperty( + new MP4Integer32Property("creationTime")); + AddProperty( + new MP4Integer32Property("modificationTime")); + } + + AddProperty( + new MP4Integer32Property("timeScale")); + + if (version == 1) { + AddProperty( + new MP4Integer64Property("duration")); + } else { + AddProperty( + new MP4Integer32Property("duration")); + } + + AddProperty( + new MP4Integer16Property("language")); + AddReserved("reserved", 2); +} + +void MP4MdhdAtom::Generate() +{ + u_int8_t version = m_pFile->Use64Bits(GetType()) ? 1 : 0; + SetVersion(version); + AddProperties(version); + + MP4Atom::Generate(); + + // set creation and modification times + MP4Timestamp now = MP4GetAbsTimestamp(); + if (version == 1) { + ((MP4Integer64Property*)m_pProperties[2])->SetValue(now); + ((MP4Integer64Property*)m_pProperties[3])->SetValue(now); + } else { + ((MP4Integer32Property*)m_pProperties[2])->SetValue(now); + ((MP4Integer32Property*)m_pProperties[3])->SetValue(now); + } +} + +void MP4MdhdAtom::Read() +{ + /* read atom version */ + ReadProperties(0, 1); + + /* need to create the properties based on the atom version */ + AddProperties(GetVersion()); + + /* now we can read the remaining properties */ + ReadProperties(1); + + Skip(); // to end of atom +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_meta.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_meta.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,77 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * M. Bakker mbakker at nero.com + * + * Apple iTunes META data + */ + +#include "mp4common.h" + +MP4MeanAtom::MP4MeanAtom() + : MP4Atom("mean") +{ + AddVersionAndFlags(); /* 0, 1 */ + + AddProperty( + new MP4BytesProperty("metadata")); /* 2 */ +} + +void MP4MeanAtom::Read() +{ + // calculate size of the metadata from the atom size + ((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 4); + + MP4Atom::Read(); +} + +MP4NameAtom::MP4NameAtom() + : MP4Atom("name") +{ + AddVersionAndFlags(); /* 0, 1 */ + + AddProperty( + new MP4BytesProperty("metadata")); /* 2 */ +} + +void MP4NameAtom::Read() +{ + // calculate size of the metadata from the atom size + ((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 4); + + MP4Atom::Read(); +} + +MP4DataAtom::MP4DataAtom() + : MP4Atom("data") +{ + AddVersionAndFlags(); /* 0, 1 */ + AddReserved("reserved2", 4); /* 2 */ + + AddProperty( + new MP4BytesProperty("metadata")); /* 3 */ +} + +void MP4DataAtom::Read() +{ + // calculate size of the metadata from the atom size + ((MP4BytesProperty*)m_pProperties[3])->SetValueSize(m_size - 8); + + MP4Atom::Read(); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_mp4a.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_mp4a.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,59 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4Mp4aAtom::MP4Mp4aAtom() + : MP4Atom("mp4a") +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("timeScale")); + + AddReserved("reserved3", 2); /* 4 */ + + ExpectChildAtom("esds", Required, OnlyOne); +} + +void MP4Mp4aAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved2 has non-zero fixed values + static u_int8_t reserved2[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, + }; + m_pProperties[2]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[2])-> + SetValue(reserved2, sizeof(reserved2)); + m_pProperties[2]->SetReadOnly(true); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_mp4s.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_mp4s.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,40 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4Mp4sAtom::MP4Mp4sAtom() + : MP4Atom("mp4s") +{ + AddReserved("reserved1", 6); + AddProperty( + new MP4Integer16Property("dataReferenceIndex")); + + ExpectChildAtom("esds", Required, OnlyOne); +} + +void MP4Mp4sAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_mp4v.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_mp4v.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,79 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4Mp4vAtom::MP4Mp4vAtom() + : MP4Atom("mp4v") +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("width")); + AddProperty( /* 4 */ + new MP4Integer16Property("height")); + + AddReserved("reserved3", 14); /* 5 */ + + MP4StringProperty* pProp = + new MP4StringProperty("compressorName"); + pProp->SetFixedLength(32); + pProp->SetValue(""); + AddProperty(pProp); /* 6 */ + + AddReserved("reserved4", 4); /* 7 */ + + ExpectChildAtom("esds", Required, OnlyOne); +} + +void MP4Mp4vAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved3 has non-zero fixed values + static u_int8_t reserved3[14] = { + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + }; + m_pProperties[5]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[5])-> + SetValue(reserved3, sizeof(reserved3)); + m_pProperties[5]->SetReadOnly(true); + + // property reserved4 has non-zero fixed values + static u_int8_t reserved4[4] = { + 0x00, 0x18, 0xFF, 0xFF, + }; + m_pProperties[7]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[7])-> + SetValue(reserved4, sizeof(reserved4)); + m_pProperties[7]->SetReadOnly(true); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_mvhd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_mvhd.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,136 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4MvhdAtom::MP4MvhdAtom() + : MP4Atom("mvhd") +{ + AddVersionAndFlags(); +} + +void MP4MvhdAtom::AddProperties(u_int8_t version) +{ + if (version == 1) { + AddProperty( /* 2 */ + new MP4Integer64Property("creationTime")); + AddProperty( /* 3 */ + new MP4Integer64Property("modificationTime")); + } else { + AddProperty( /* 2 */ + new MP4Integer32Property("creationTime")); + AddProperty( /* 3 */ + new MP4Integer32Property("modificationTime")); + } + + AddProperty( /* 4 */ + new MP4Integer32Property("timeScale")); + + if (version == 1) { + AddProperty( /* 5 */ + new MP4Integer64Property("duration")); + } else { + AddProperty( /* 5 */ + new MP4Integer32Property("duration")); + } + + MP4Float32Property* pProp; + + pProp = new MP4Float32Property("rate"); + pProp->SetFixed32Format(); + AddProperty(pProp); /* 6 */ + + pProp = new MP4Float32Property("volume"); + pProp->SetFixed16Format(); + AddProperty(pProp); /* 7 */ + + AddReserved("reserved1", 70); /* 8 */ + + AddProperty( /* 9 */ + new MP4Integer32Property("nextTrackId")); +} + +void MP4MvhdAtom::Generate() +{ + u_int8_t version = m_pFile->Use64Bits(GetType()) ? 1 : 0; + SetVersion(version); + AddProperties(version); + + MP4Atom::Generate(); + + // set creation and modification times + MP4Timestamp now = MP4GetAbsTimestamp(); + if (version == 1) { + ((MP4Integer64Property*)m_pProperties[2])->SetValue(now); + ((MP4Integer64Property*)m_pProperties[3])->SetValue(now); + } else { + ((MP4Integer32Property*)m_pProperties[2])->SetValue(now); + ((MP4Integer32Property*)m_pProperties[3])->SetValue(now); + } + + ((MP4Integer32Property*)m_pProperties[4])->SetValue(1000); + + ((MP4Float32Property*)m_pProperties[6])->SetValue(1.0); + ((MP4Float32Property*)m_pProperties[7])->SetValue(1.0); + + // property reserved has non-zero fixed values + static u_int8_t reserved[70] = { + 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + m_pProperties[8]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[8])-> + SetValue(reserved, sizeof(reserved)); + m_pProperties[8]->SetReadOnly(true); + + // set next track id + ((MP4Integer32Property*)m_pProperties[9])->SetValue(1); +} + +void MP4MvhdAtom::Read() +{ + /* read atom version */ + ReadProperties(0, 1); + + /* need to create the properties based on the atom version */ + AddProperties(GetVersion()); + + /* now we can read the remaining properties */ + ReadProperties(1); + + Skip(); // to end of atom +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_root.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_root.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,123 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4RootAtom::MP4RootAtom() + : MP4Atom(NULL) +{ + ExpectChildAtom("moov", Required, OnlyOne); + ExpectChildAtom("ftyp", Optional, OnlyOne); + ExpectChildAtom("mdat", Optional, Many); + ExpectChildAtom("free", Optional, Many); + ExpectChildAtom("skip", Optional, Many); + ExpectChildAtom("udta", Optional, Many); + ExpectChildAtom("moof", Optional, Many); +} + +void MP4RootAtom::BeginWrite(bool use64) +{ + // only call under MP4Create() control + WriteAtomType("ftyp", OnlyOne); + + m_pChildAtoms[GetLastMdatIndex()]->BeginWrite(m_pFile->Use64Bits("mdat")); +} + +void MP4RootAtom::Write() +{ + // no-op +} + +void MP4RootAtom::FinishWrite(bool use64) +{ + // finish writing last mdat atom + u_int32_t mdatIndex = GetLastMdatIndex(); + m_pChildAtoms[mdatIndex]->FinishWrite(m_pFile->Use64Bits("mdat")); + + // write all atoms after last mdat + u_int32_t size = m_pChildAtoms.Size(); + for (u_int32_t i = mdatIndex + 1; i < size; i++) { + m_pChildAtoms[i]->Write(); + } +} + +void MP4RootAtom::BeginOptimalWrite() +{ + WriteAtomType("ftyp", OnlyOne); + WriteAtomType("moov", OnlyOne); + WriteAtomType("udta", Many); + + m_pChildAtoms[GetLastMdatIndex()]->BeginWrite(m_pFile->Use64Bits("mdat")); +} + +void MP4RootAtom::FinishOptimalWrite() +{ + // finish writing mdat + m_pChildAtoms[GetLastMdatIndex()]->FinishWrite(m_pFile->Use64Bits("mdat")); + + // find moov atom + u_int32_t size = m_pChildAtoms.Size(); + MP4Atom* pMoovAtom = NULL; + + u_int32_t i; + for (i = 0; i < size; i++) { + if (!strcmp("moov", m_pChildAtoms[i]->GetType())) { + pMoovAtom = m_pChildAtoms[i]; + break; + } + } + ASSERT(i < size); + + // rewrite moov so that updated chunkOffsets are written to disk + m_pFile->SetPosition(pMoovAtom->GetStart()); + u_int64_t oldSize = pMoovAtom->GetSize(); + + pMoovAtom->Write(); + + // sanity check + u_int64_t newSize = pMoovAtom->GetSize(); + ASSERT(oldSize == newSize); +} + +u_int32_t MP4RootAtom::GetLastMdatIndex() +{ + for (int32_t i = m_pChildAtoms.Size() - 1; i >= 0; i--) { + if (!strcmp("mdat", m_pChildAtoms[i]->GetType())) { + return i; + } + } + ASSERT(false); + return (u_int32_t)-1; +} + +void MP4RootAtom::WriteAtomType(const char* type, bool onlyOne) +{ + u_int32_t size = m_pChildAtoms.Size(); + + for (u_int32_t i = 0; i < size; i++) { + if (!strcmp(type, m_pChildAtoms[i]->GetType())) { + m_pChildAtoms[i]->Write(); + if (onlyOne) { + break; + } + } + } +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_rtp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_rtp.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,147 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4RtpAtom::MP4RtpAtom() + : MP4Atom("rtp ") +{ + // The atom type "rtp " is used in two complete unrelated ways + // i.e. it's real two atoms with the same name + // To handle that we need to postpone property creation until + // we know who our parent atom is (stsd or hnti) which gives us + // the context info we need to know who we are +} + +void MP4RtpAtom::AddPropertiesStsdType() +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddProperty( /* 2 */ + new MP4Integer16Property("hintTrackVersion")); + AddProperty( /* 3 */ + new MP4Integer16Property("highestCompatibleVersion")); + AddProperty( /* 4 */ + new MP4Integer32Property("maxPacketSize")); + + ExpectChildAtom("tims", Required, OnlyOne); + ExpectChildAtom("tsro", Optional, OnlyOne); + ExpectChildAtom("snro", Optional, OnlyOne); +} + +void MP4RtpAtom::AddPropertiesHntiType() +{ + MP4StringProperty* pProp = + new MP4StringProperty("descriptionFormat"); + pProp->SetFixedLength(4); + AddProperty(pProp); /* 0 */ + + AddProperty( /* 1 */ + new MP4StringProperty("sdpText")); +} + +void MP4RtpAtom::Generate() +{ + if (!strcmp(m_pParentAtom->GetType(), "stsd")) { + AddPropertiesStsdType(); + GenerateStsdType(); + } else if (!strcmp(m_pParentAtom->GetType(), "hnti")) { + AddPropertiesHntiType(); + GenerateHntiType(); + } else { + VERBOSE_WARNING(m_pFile->GetVerbosity(), + printf("Warning: rtp atom in unexpected context, can not generate")); + } +} + +void MP4RtpAtom::GenerateStsdType() +{ + // generate children + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + ((MP4Integer16Property*)m_pProperties[2])->SetValue(1); + ((MP4Integer16Property*)m_pProperties[3])->SetValue(1); +} + +void MP4RtpAtom::GenerateHntiType() +{ + MP4Atom::Generate(); + + ((MP4StringProperty*)m_pProperties[0])->SetValue("sdp "); +} + +void MP4RtpAtom::Read() +{ + if (!strcmp(m_pParentAtom->GetType(), "stsd")) { + AddPropertiesStsdType(); + ReadStsdType(); + } else if (!strcmp(m_pParentAtom->GetType(), "hnti")) { + AddPropertiesHntiType(); + ReadHntiType(); + } else { + VERBOSE_READ(m_pFile->GetVerbosity(), + printf("rtp atom in unexpected context, can not read")); + } + + Skip(); // to end of atom +} + +void MP4RtpAtom::ReadStsdType() +{ + MP4Atom::Read(); +} + +void MP4RtpAtom::ReadHntiType() +{ + ReadProperties(0, 1); + + // read sdp string, length is implicit in size of atom + u_int64_t size = GetEnd() - m_pFile->GetPosition(); + char* data = (char*)MP4Malloc(size + 1); + m_pFile->ReadBytes((u_int8_t*)data, size); + data[size] = '\0'; + ((MP4StringProperty*)m_pProperties[1])->SetValue(data); + MP4Free(data); +} + +void MP4RtpAtom::Write() +{ + if (!strcmp(m_pParentAtom->GetType(), "hnti")) { + WriteHntiType(); + } else { + MP4Atom::Write(); + } +} + +void MP4RtpAtom::WriteHntiType() +{ + // since length of string is implicit in size of atom + // we need to handle this specially, and not write the terminating \0 + MP4StringProperty* pSdp = (MP4StringProperty*)m_pProperties[1]; + pSdp->SetFixedLength(strlen(pSdp->GetValue())); + MP4Atom::Write(); + pSdp->SetFixedLength(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_s263.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_s263.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,78 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +MP4S263Atom::MP4S263Atom() + : MP4Atom("s263") +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("width")); + + AddProperty( /* 4 */ + new MP4Integer16Property("height")); + + AddReserved("reserved3", 50); /* 5 */ + + + ExpectChildAtom("d263", Required, OnlyOne); +} + +void MP4S263Atom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved2 has non-zero fixed values + static u_int8_t reserved3[50] = { + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, + 0xFF, 0xFF + }; + m_pProperties[5]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[5])-> + SetValue(reserved3, sizeof(reserved3)); + m_pProperties[5]->SetReadOnly(true); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_sdp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_sdp.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,53 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4SdpAtom::MP4SdpAtom() : MP4Atom("sdp ") +{ + AddProperty( + new MP4StringProperty("sdpText")); +} + +void MP4SdpAtom::Read() +{ + // read sdp string, length is implicit in size of atom + u_int64_t size = GetEnd() - m_pFile->GetPosition(); + char* data = (char*)MP4Malloc(size + 1); + m_pFile->ReadBytes((u_int8_t*)data, size); + data[size] = '\0'; + ((MP4StringProperty*)m_pProperties[0])->SetValue(data); + MP4Free(data); +} + +void MP4SdpAtom::Write() +{ + // since length of string is implicit in size of atom + // we need to handle this specially, and not write the terminating \0 + MP4StringProperty* pSdp = (MP4StringProperty*)m_pProperties[0]; + const char* sdpText = pSdp->GetValue(); + if (sdpText) { + pSdp->SetFixedLength(strlen(sdpText)); + } + MP4Atom::Write(); + pSdp->SetFixedLength(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_smi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_smi.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,41 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + * + * Apple iTunes META data + */ + +#include "mp4common.h" + +MP4SmiAtom::MP4SmiAtom() + : MP4Atom("meta") +{ + + AddProperty( new MP4BytesProperty("metadata")); + +} + +void MP4SmiAtom::Read() +{ + // calculate size of the metadata from the atom size + ((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size); + + MP4Atom::Read(); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_sound.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_sound.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,82 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + */ + +#include "mp4common.h" + +MP4SoundAtom::MP4SoundAtom(const char *atomid) + : MP4Atom(atomid) +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + AddProperty( /* 2 */ + new MP4Integer16Property("soundVersion")); + AddReserved( "reserved2", 6); /* 3 */ + + AddProperty( /* 4 */ + new MP4Integer16Property("channels")); + AddProperty( /* 5 */ + new MP4Integer16Property("sampleSize")); + AddProperty( /* 6 */ + new MP4Integer16Property("packetSize")); + AddProperty( /* 7 */ + new MP4Integer32Property("timeScale")); +} + +void MP4SoundAtom::AddProperties (uint8_t version) +{ + if (version > 0) { + AddProperty( /* 8 */ + new MP4Integer32Property("samplesPerPacket")); + AddProperty( /* 9 */ + new MP4Integer32Property("bytesPerPacket")); + AddProperty( /* 10 */ + new MP4Integer32Property("bytesPerFrame")); + AddProperty( /* 11 */ + new MP4Integer32Property("bytesPerSample")); + } +} +void MP4SoundAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved2 has non-zero fixed values + static u_int8_t reserved2[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, + }; + m_pProperties[2]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[2])-> + SetValue(reserved2, sizeof(reserved2)); + m_pProperties[2]->SetReadOnly(true); +} + +void MP4SoundAtom::Read() +{ + ReadProperties(0, 3); // read first 3 properties + AddProperties(((MP4IntegerProperty *)m_pProperties[2])->GetValue()); + ReadProperties(3); // continue +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_standard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_standard.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,422 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. + * + * Contributor(s): + * Bill May (from others work). + */ + +#include "mp4common.h" +#include "atoms.h" + +static const char name[5]={0251,'n', 'a', 'm', '\0'}; +static const char art[5]={0251,'A', 'R', 'T', '\0'}; +static const char wrt[5]={0251,'w', 'r', 't', '\0'}; +static const char alb[5]={0251,'a', 'l', 'b', '\0'}; +static const char day[5]={0251,'d', 'a', 'y', '\0'}; +static const char too[5]={0251,'t', 'o', 'o', '\0'}; +static const char cmt[5]={0251,'c', 'm', 't', '\0'}; +static const char gen[5]={0251,'g', 'e', 'n', '\0'}; +static const char grp[5]={0251,'g', 'r', 'p', '\0'}; + +MP4StandardAtom::MP4StandardAtom (const char *type) : MP4Atom(type) +{ + /* + * This is a big if else loop. Make sure that you don't break it + * when adding new atoms, or you will set the unknown type flag + * + * Try to keep it in alphabetical order - it should only be called + * 1 time per atom, so it's not that urgent. + */ + /* + * b??? + */ + if (ATOMID(type) == ATOMID("bitr")) { + AddProperty( /* 0 */ + new MP4Integer32Property("avgBitrate")); + + AddProperty( /* 1 */ + new MP4Integer32Property("maxBitrate")); + + } else if (ATOMID(type) == ATOMID("btrt")) { + AddProperty( new MP4Integer32Property("bufferSizeDB")); /* 0 */ + AddProperty( new MP4Integer32Property("avgBitrate")); /* 1 */ + AddProperty( new MP4Integer32Property("maxBitrate")); /* 2 */ + /* + * c??? + */ + } else if (ATOMID(type) == ATOMID("co64")) { + AddVersionAndFlags(); + + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty( + new MP4Integer64Property("chunkOffset")); + + } else if (ATOMID(type) == ATOMID("cpil") || + ATOMID(type) == ATOMID("covr")) { /* Apple iTunes */ + ExpectChildAtom("data", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("cprt")) { + AddVersionAndFlags(); + AddProperty( + new MP4Integer16Property("language")); + AddProperty( + new MP4StringProperty("notice")); + + } else if (ATOMID(type) == ATOMID("ctts")) { + AddVersionAndFlags(); + + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty(new MP4Integer32Property("sampleCount")); + pTable->AddProperty(new MP4Integer32Property("sampleOffset")); + /* + * d??? + */ + } else if (ATOMID(type) == ATOMID("dinf")) { + ExpectChildAtom("dref", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("dimm")) { + AddProperty( // bytes of immediate data + new MP4Integer64Property("bytes")); + + } else if (ATOMID(type) == ATOMID("disk")) { /* Apple iTunes */ + ExpectChildAtom("data", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("dmax")) { + AddProperty( // max packet duration + new MP4Integer32Property("milliSecs")); + + } else if (ATOMID(type) == ATOMID("dmed")) { + AddProperty( // bytes sent from media data + new MP4Integer64Property("bytes")); + + } else if (ATOMID(type) == ATOMID("drep")) { + AddProperty( // bytes of repeated data + new MP4Integer64Property("bytes")); + /* + * e??? + */ + } else if (ATOMID(type) == ATOMID("edts")) { + ExpectChildAtom("elst", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("esds")) { + AddVersionAndFlags(); + AddProperty( + new MP4DescriptorProperty(NULL, MP4ESDescrTag, 0, + Required, OnlyOne)); + /* + * f??? + */ + } else if (ATOMID(type) == ATOMID("frma")) { + AddProperty( /* 0 */ + new MP4Integer32Property("data-format")); + /* + * g??? + */ + } else if (ATOMID(type) == ATOMID("gnre")) { // Apple iTunes + ExpectChildAtom("data", Optional, OnlyOne); + + /* + * h??? + */ + } else if (ATOMID(type) == ATOMID("hmhd")) { + AddVersionAndFlags(); + + AddProperty(new MP4Integer16Property("maxPduSize")); + AddProperty(new MP4Integer16Property("avgPduSize")); + AddProperty(new MP4Integer32Property("maxBitRate")); + AddProperty(new MP4Integer32Property("avgBitRate")); + AddProperty(new MP4Integer32Property("slidingAvgBitRate")); + /* + * i??? + */ + } else if (ATOMID(type) == ATOMID("iKMS")) { + AddVersionAndFlags(); /* 0, 1 */ + MP4StringProperty* pProp = new MP4StringProperty("kms_URI"); + AddProperty(pProp); /* 2 */ + + } else if (ATOMID(type) == ATOMID("iSFM")) { + AddVersionAndFlags(); /* 0, 1 */ + AddProperty( /* 2 */ + new MP4BitfieldProperty("selective-encryption", 1)); + AddProperty( /* 3 */ + new MP4BitfieldProperty("reserved", 7)); + AddProperty( /* 4 */ + new MP4Integer8Property("key-indicator-length")); + AddProperty( /* 5 */ + new MP4Integer8Property("IV-length")); + + } else if (ATOMID(type) == ATOMID("ilst")) { + ExpectChildAtom("\251nam", Optional, OnlyOne); /* name */ + ExpectChildAtom("\251ART", Optional, OnlyOne); /* artist */ + ExpectChildAtom("\251wrt", Optional, OnlyOne); /* writer */ + ExpectChildAtom("\251alb", Optional, OnlyOne); /* album */ + ExpectChildAtom("\251day", Optional, OnlyOne); /* date */ + ExpectChildAtom("\251too", Optional, OnlyOne); /* tool */ + ExpectChildAtom("\251cmt", Optional, OnlyOne); /* comment */ + ExpectChildAtom("\251gen", Optional, OnlyOne); /* custom genre */ + ExpectChildAtom("trkn", Optional, OnlyOne); /* tracknumber */ + ExpectChildAtom("disk", Optional, OnlyOne); /* disknumber */ + ExpectChildAtom("gnre", Optional, OnlyOne); /* genre (ID3v1 index + 1) */ + ExpectChildAtom("cpil", Optional, OnlyOne); /* compilation */ + ExpectChildAtom("tmpo", Optional, OnlyOne); /* BPM */ + ExpectChildAtom("covr", Optional, OnlyOne); /* cover art */ + ExpectChildAtom("----", Optional, Many); /* ---- free form */ + + } else if (ATOMID(type) == ATOMID("iods")) { + AddVersionAndFlags(); + AddProperty( + new MP4DescriptorProperty(NULL, MP4FileIODescrTag, + MP4FileODescrTag, + Required, OnlyOne)); + /* + * m??? + */ + } else if (ATOMID(type) == ATOMID("maxr")) { + AddProperty(new MP4Integer32Property("granularity")); + AddProperty(new MP4Integer32Property("bytes")); + + } else if (ATOMID(type) == ATOMID("mdia")) { + ExpectChildAtom("mdhd", Required, OnlyOne); + ExpectChildAtom("hdlr", Required, OnlyOne); + ExpectChildAtom("minf", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("meta")) { // iTunes + AddVersionAndFlags(); /* 0, 1 */ + ExpectChildAtom("hdlr", Required, OnlyOne); + ExpectChildAtom("ilst", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("mfhd")) { + AddVersionAndFlags(); /* 0, 1 */ + AddProperty( /* 2 */ + new MP4Integer32Property("sequenceNumber")); + + } else if (ATOMID(type) == ATOMID("minf")) { + ExpectChildAtom("vmhd", Optional, OnlyOne); + ExpectChildAtom("smhd", Optional, OnlyOne); + ExpectChildAtom("hmhd", Optional, OnlyOne); + ExpectChildAtom("nmhd", Optional, OnlyOne); + ExpectChildAtom("dinf", Required, OnlyOne); + ExpectChildAtom("stbl", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("moof")) { + ExpectChildAtom("mfhd", Required, OnlyOne); + ExpectChildAtom("traf", Optional, Many); + + } else if (ATOMID(type) == ATOMID("moov")) { + ExpectChildAtom("mvhd", Required, OnlyOne); + ExpectChildAtom("iods", Required, OnlyOne); + ExpectChildAtom("trak", Required, Many); + ExpectChildAtom("udta", Optional, Many); + ExpectChildAtom("mvex", Optional, OnlyOne); + + } else if (ATOMID(type) == ATOMID("mvex")) { + ExpectChildAtom("trex", Required, Many); + + /* + * n??? + */ + } else if (ATOMID(type) == ATOMID("nmhd")) { + AddVersionAndFlags(); + + } else if (ATOMID(type) == ATOMID("nump")) { + AddProperty( // packets sent + new MP4Integer64Property("packets")); + /* + * p??? + */ + } else if (ATOMID(type) == ATOMID("payt")) { + AddProperty(new MP4Integer32Property("payloadNumber")); + AddProperty(new MP4StringProperty("rtpMap", Counted)); + + } else if (ATOMID(type) == ATOMID("pmax")) { + AddProperty( // max packet size + new MP4Integer32Property("bytes")); + /* + * s??? + */ + } else if (ATOMID(type) == ATOMID("schi")) { + // not sure if this is child atoms or table of boxes + // get clarification on spec 9.1.2.5 + ExpectChildAtom("iKMS", Required, OnlyOne); + ExpectChildAtom("iSFM", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("schm")) { + AddVersionAndFlags(); /* 0, 1 */ + AddProperty( /* 2 */ + new MP4Integer32Property("scheme_type")); + AddProperty( /* 3 */ + new MP4Integer32Property("scheme_version")); + // browser URI if flags set, TODO + + } else if (ATOMID(type) == ATOMID("sinf")) { + ExpectChildAtom("frma", Required, OnlyOne); + ExpectChildAtom("schm", Required, OnlyOne); + ExpectChildAtom("schi", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("smhd")) { + AddVersionAndFlags(); + AddReserved("reserved", 4); + + } else if (ATOMID(type) == ATOMID("snro")) { + AddProperty(new MP4Integer32Property("offset")); + + } else if (ATOMID(type) == ATOMID("stco")) { + AddVersionAndFlags(); + + MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty(new MP4Integer32Property("chunkOffset")); + + } else if (ATOMID(type) == ATOMID("stsh")) { + AddVersionAndFlags(); + + MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty(new MP4Integer32Property("shadowedSampleNumber")); + pTable->AddProperty(new MP4Integer32Property("syncSampleNumber")); + + } else if (ATOMID(type) == ATOMID("stss")) { + AddVersionAndFlags(); + + MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty(new MP4Integer32Property("sampleNumber")); + + } else if (ATOMID(type) == ATOMID("stts")) { + AddVersionAndFlags(); + MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty(new MP4Integer32Property("sampleCount")); + pTable->AddProperty(new MP4Integer32Property("sampleDelta")); + + /* + * t??? + */ + } else if (ATOMID(type) == ATOMID("tims")) { + AddProperty( + new MP4Integer32Property("timeScale")); + + } else if (ATOMID(type) == ATOMID("tmin")) { + AddProperty( // min relative xmit time + new MP4Integer32Property("milliSecs")); + + } else if (ATOMID(type) == ATOMID("tmax")) { + AddProperty( // max relative xmit time + new MP4Integer32Property("milliSecs")); + + } else if (ATOMID(type) == ATOMID("tmpo")) { // iTunes + ExpectChildAtom("data", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("traf")) { + ExpectChildAtom("tfhd", Required, OnlyOne); + ExpectChildAtom("trun", Optional, Many); + + } else if (ATOMID(type) == ATOMID("trak")) { + ExpectChildAtom("tkhd", Required, OnlyOne); + ExpectChildAtom("tref", Optional, OnlyOne); + ExpectChildAtom("edts", Optional, OnlyOne); + ExpectChildAtom("mdia", Required, OnlyOne); + ExpectChildAtom("udta", Optional, Many); + + } else if (ATOMID(type) == ATOMID("tref")) { + ExpectChildAtom("dpnd", Optional, OnlyOne); + ExpectChildAtom("hint", Optional, OnlyOne); + ExpectChildAtom("ipir", Optional, OnlyOne); + ExpectChildAtom("mpod", Optional, OnlyOne); + ExpectChildAtom("sync", Optional, OnlyOne); + + } else if (ATOMID(type) == ATOMID("trex")) { + AddVersionAndFlags(); /* 0, 1 */ + AddProperty( /* 2 */ + new MP4Integer32Property("trackId")); + AddProperty( /* 3 */ + new MP4Integer32Property("defaultSampleDesriptionIndex")); + AddProperty( /* 4 */ + new MP4Integer32Property("defaultSampleDuration")); + AddProperty( /* 5 */ + new MP4Integer32Property("defaultSampleSize")); + AddProperty( /* 6 */ + new MP4Integer32Property("defaultSampleFlags")); + + } else if (ATOMID(type) == ATOMID("trkn")) { // iTunes + ExpectChildAtom("data", Required, OnlyOne); + + } else if (ATOMID(type) == ATOMID("trpy") || + ATOMID(type) == ATOMID("tpyl")) { + AddProperty( // bytes sent including RTP headers + new MP4Integer64Property("bytes")); + + } else if (ATOMID(type) == ATOMID("tsro")) { + AddProperty( + new MP4Integer32Property("offset")); + + /* + * copyright??? + */ + } else if (ATOMID(type) == ATOMID(name) || + ATOMID(type) == ATOMID(art) || + ATOMID(type) == ATOMID(wrt) || + ATOMID(type) == ATOMID(alb) || + ATOMID(type) == ATOMID(day) || + ATOMID(type) == ATOMID(too) || + ATOMID(type) == ATOMID(cmt) || + ATOMID(type) == ATOMID(gen) || + ATOMID(type) == ATOMID(grp)) { /* Apple iTunes */ + ExpectChildAtom("data", Required, OnlyOne); + /* + * ---- + */ + } else if (ATOMID(type) == ATOMID("----")) { /* Apple iTunes */ + ExpectChildAtom("mean", Required, OnlyOne); + ExpectChildAtom("name", Required, OnlyOne); + ExpectChildAtom("data", Required, OnlyOne); + } else { + /* + * default - unknown type + */ + SetUnknownType(true); + } + +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_stbl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_stbl.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,57 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4StblAtom::MP4StblAtom() + : MP4Atom("stbl") +{ + ExpectChildAtom("stsd", Required, OnlyOne); + ExpectChildAtom("stts", Required, OnlyOne); + ExpectChildAtom("ctts", Optional, OnlyOne); + ExpectChildAtom("stsz", Required, OnlyOne); + ExpectChildAtom("stsc", Required, OnlyOne); + ExpectChildAtom("stco", Optional, OnlyOne); + ExpectChildAtom("co64", Optional, OnlyOne); + ExpectChildAtom("stss", Optional, OnlyOne); + ExpectChildAtom("stsh", Optional, OnlyOne); + ExpectChildAtom("stdp", Optional, OnlyOne); +} + +void MP4StblAtom::Generate() +{ + // as usual + MP4Atom::Generate(); + + // but we also need one of the chunk offset atoms + MP4Atom* pChunkOffsetAtom; + if (m_pFile->Use64Bits(GetType())) { + pChunkOffsetAtom = CreateAtom("co64"); + } else { + pChunkOffsetAtom = CreateAtom("stco"); + } + + AddChildAtom(pChunkOffsetAtom); + + // and ask it to self generate + pChunkOffsetAtom->Generate(); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_stdp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_stdp.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,49 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4StdpAtom::MP4StdpAtom() + : MP4Atom("stdp") +{ + AddVersionAndFlags(); + + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + pCount->SetImplicit(); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty( + new MP4Integer16Property("priority")); +} + +void MP4StdpAtom::Read() +{ + // table entry count computed from atom size + ((MP4Integer32Property*)m_pProperties[2])->SetReadOnly(false); + ((MP4Integer32Property*)m_pProperties[2])->SetValue((m_size - 4) / 2); + ((MP4Integer32Property*)m_pProperties[2])->SetReadOnly(true); + + MP4Atom::Read(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_stsc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_stsc.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,78 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4StscAtom::MP4StscAtom() + : MP4Atom("stsc") +{ + AddVersionAndFlags(); + + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); + + pTable->AddProperty( + new MP4Integer32Property("firstChunk")); + pTable->AddProperty( + new MP4Integer32Property("samplesPerChunk")); + pTable->AddProperty( + new MP4Integer32Property("sampleDescriptionIndex")); + + // As an optimization we add an implicit property to this table, + // "firstSample" that corresponds to the first sample of the firstChunk + MP4Integer32Property* pSample = + new MP4Integer32Property("firstSample"); + pSample->SetImplicit(); + pTable->AddProperty(pSample); +} + +void MP4StscAtom::Read() +{ + // Read as usual + MP4Atom::Read(); + + // Compute the firstSample values for later use + u_int32_t count = + ((MP4Integer32Property*)m_pProperties[2])->GetValue(); + + MP4Integer32Property* pFirstChunk = (MP4Integer32Property*) + ((MP4TableProperty*)m_pProperties[3])->GetProperty(0); + MP4Integer32Property* pSamplesPerChunk = (MP4Integer32Property*) + ((MP4TableProperty*)m_pProperties[3])->GetProperty(1); + MP4Integer32Property* pFirstSample = (MP4Integer32Property*) + ((MP4TableProperty*)m_pProperties[3])->GetProperty(3); + + MP4SampleId sampleId = 1; + + for (u_int32_t i = 0; i < count; i++) { + pFirstSample->SetValue(sampleId, i); + + if (i < count - 1) { + sampleId += + (pFirstChunk->GetValue(i+1) - pFirstChunk->GetValue(i)) + * pSamplesPerChunk->GetValue(i); + } + } +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_stsd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_stsd.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,72 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2004. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +MP4StsdAtom::MP4StsdAtom() + : MP4Atom("stsd") +{ + AddVersionAndFlags(); + + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + pCount->SetReadOnly(); + AddProperty(pCount); + + ExpectChildAtom("mp4a", Optional, Many); + ExpectChildAtom("enca", Optional, Many); + ExpectChildAtom("mp4s", Optional, Many); + ExpectChildAtom("mp4v", Optional, Many); + ExpectChildAtom("encv", Optional, Many); + ExpectChildAtom("rtp ", Optional, Many); + ExpectChildAtom("samr", Optional, Many); // For AMR-NB + ExpectChildAtom("sawb", Optional, Many); // For AMR-WB + ExpectChildAtom("s263", Optional, Many); // For H.263 + ExpectChildAtom("avc1", Optional, Many); +} + +void MP4StsdAtom::Read() +{ + /* do the usual read */ + MP4Atom::Read(); + + // check that number of children == entryCount + MP4Integer32Property* pCount = + (MP4Integer32Property*)m_pProperties[2]; + + if (m_pChildAtoms.Size() != pCount->GetValue()) { + VERBOSE_READ(GetVerbosity(), + printf("Warning: stsd inconsistency with number of entries")); + + /* fix it */ + pCount->SetReadOnly(false); + pCount->SetValue(m_pChildAtoms.Size()); + pCount->SetReadOnly(true); + } +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_stsz.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_stsz.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,69 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4StszAtom::MP4StszAtom() + : MP4Atom("stsz") +{ + AddVersionAndFlags(); /* 0, 1 */ + + AddProperty( /* 2 */ + new MP4Integer32Property("sampleSize")); + + MP4Integer32Property* pCount = + new MP4Integer32Property("sampleCount"); + AddProperty(pCount); /* 3 */ + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); /* 4 */ + + pTable->AddProperty( /* 4/0 */ + new MP4Integer32Property("sampleSize")); +} + +void MP4StszAtom::Read() +{ + ReadProperties(0, 4); + + u_int32_t sampleSize = + ((MP4Integer32Property*)m_pProperties[2])->GetValue(); + + // only attempt to read entries table if sampleSize is zero + // i.e sample size is not constant + m_pProperties[4]->SetImplicit(sampleSize != 0); + + ReadProperties(4); + + Skip(); // to end of atom +} + +void MP4StszAtom::Write() +{ + u_int32_t sampleSize = + ((MP4Integer32Property*)m_pProperties[2])->GetValue(); + + // only attempt to write entries table if sampleSize is zero + // i.e sample size is not constant + m_pProperties[4]->SetImplicit(sampleSize != 0); + + MP4Atom::Write(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_tfhd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_tfhd.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,69 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4TfhdAtom::MP4TfhdAtom() + : MP4Atom("tfhd") +{ + AddVersionAndFlags(); /* 0, 1 */ + AddProperty( /* 2 */ + new MP4Integer32Property("trackId")); +} + +void MP4TfhdAtom::AddProperties(u_int32_t flags) +{ + if (flags & 0x01) { + // note this property is signed 64! + AddProperty( + new MP4Integer64Property("baseDataOffset")); + } + if (flags & 0x02) { + AddProperty( + new MP4Integer32Property("sampleDescriptionIndex")); + } + if (flags & 0x08) { + AddProperty( + new MP4Integer32Property("defaultSampleDuration")); + } + if (flags & 0x10) { + AddProperty( + new MP4Integer32Property("defaultSampleSize")); + } + if (flags & 0x20) { + AddProperty( + new MP4Integer32Property("defaultSampleFlags")); + } +} + +void MP4TfhdAtom::Read() +{ + /* read atom version, flags, and trackId */ + ReadProperties(0, 3); + + /* need to create the properties based on the atom flags */ + AddProperties(GetFlags()); + + /* now we can read the remaining properties */ + ReadProperties(3); + + Skip(); // to end of atom +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_tkhd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_tkhd.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,124 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4TkhdAtom::MP4TkhdAtom() + : MP4Atom("tkhd") +{ + AddVersionAndFlags(); +} + +void MP4TkhdAtom::AddProperties(u_int8_t version) +{ + if (version == 1) { + AddProperty( /* 2 */ + new MP4Integer64Property("creationTime")); + AddProperty( /* 3 */ + new MP4Integer64Property("modificationTime")); + } else { // version == 0 + AddProperty( /* 2 */ + new MP4Integer32Property("creationTime")); + AddProperty( /* 3 */ + new MP4Integer32Property("modificationTime")); + } + + AddProperty( /* 4 */ + new MP4Integer32Property("trackId")); + AddReserved("reserved1", 4); /* 5 */ + + if (version == 1) { + AddProperty( /* 6 */ + new MP4Integer64Property("duration")); + } else { + AddProperty( /* 6 */ + new MP4Integer32Property("duration")); + } + + AddReserved("reserved2", 12); /* 7 */ + + MP4Float32Property* pProp; + + pProp = new MP4Float32Property("volume"); + pProp->SetFixed16Format(); + AddProperty(pProp); /* 8 */ + + AddReserved("reserved3", 38); /* 9 */ + + pProp = new MP4Float32Property("width"); + pProp->SetFixed32Format(); + AddProperty(pProp); /* 10 */ + + pProp = new MP4Float32Property("height"); + pProp->SetFixed32Format(); + AddProperty(pProp); /* 11 */ +} + +void MP4TkhdAtom::Generate() +{ + u_int8_t version = m_pFile->Use64Bits(GetType()) ? 1 : 0; + SetVersion(version); + AddProperties(version); + + MP4Atom::Generate(); + + // set creation and modification times + MP4Timestamp now = MP4GetAbsTimestamp(); + if (version == 1) { + ((MP4Integer64Property*)m_pProperties[2])->SetValue(now); + ((MP4Integer64Property*)m_pProperties[3])->SetValue(now); + } else { + ((MP4Integer32Property*)m_pProperties[2])->SetValue(now); + ((MP4Integer32Property*)m_pProperties[3])->SetValue(now); + } + + // property reserved3 has non-zero fixed values + static u_int8_t reserved3[38] = { + 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, + }; + m_pProperties[9]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[9])-> + SetValue(reserved3, sizeof(reserved3)); + m_pProperties[9]->SetReadOnly(true); +} + +void MP4TkhdAtom::Read() +{ + /* read atom version */ + ReadProperties(0, 1); + + /* need to create the properties based on the atom version */ + AddProperties(GetVersion()); + + /* now we can read the remaining properties */ + ReadProperties(1); + + Skip(); // to end of atom +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_treftype.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_treftype.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,47 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4TrefTypeAtom::MP4TrefTypeAtom(const char* type) + : MP4Atom(type) +{ + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + pCount->SetImplicit(); + AddProperty(pCount); /* 0 */ + + MP4TableProperty* pTable = new MP4TableProperty("entries", pCount); + AddProperty(pTable); /* 1 */ + + pTable->AddProperty( /* 1, 0 */ + new MP4Integer32Property("trackId")); +} + +void MP4TrefTypeAtom::Read() +{ + // table entry count computed from atom size + ((MP4Integer32Property*)m_pProperties[0])->SetReadOnly(false); + ((MP4Integer32Property*)m_pProperties[0])->SetValue(m_size / 4); + ((MP4Integer32Property*)m_pProperties[0])->SetReadOnly(true); + + MP4Atom::Read(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_trun.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_trun.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,79 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4TrunAtom::MP4TrunAtom() + : MP4Atom("trun") +{ + AddVersionAndFlags(); /* 0, 1 */ + AddProperty( /* 2 */ + new MP4Integer32Property("sampleCount")); +} + +void MP4TrunAtom::AddProperties(u_int32_t flags) +{ + if (flags & 0x01) { + // Note this is a signed 32 value + AddProperty( + new MP4Integer32Property("dataOffset")); + } + if (flags & 0x04) { + AddProperty( + new MP4Integer32Property("firstSampleFlags")); + } + + MP4TableProperty* pTable = + new MP4TableProperty("samples", + (MP4Integer32Property *)m_pProperties[2]); + AddProperty(pTable); + + if (flags & 0x100) { + pTable->AddProperty( + new MP4Integer32Property("sampleDuration")); + } + if (flags & 0x200) { + pTable->AddProperty( + new MP4Integer32Property("sampleSize")); + } + if (flags & 0x400) { + pTable->AddProperty( + new MP4Integer32Property("sampleFlags")); + } + if (flags & 0x800) { + pTable->AddProperty( + new MP4Integer32Property("sampleCompositionTimeOffset")); + } +} + +void MP4TrunAtom::Read() +{ + /* read atom version, flags, and sampleCount */ + ReadProperties(0, 3); + + /* need to create the properties based on the atom flags */ + AddProperties(GetFlags()); + + /* now we can read the remaining properties */ + ReadProperties(3); + + Skip(); // to end of atom +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_udta.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_udta.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,39 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4UdtaAtom::MP4UdtaAtom() + : MP4Atom("udta") +{ + ExpectChildAtom("cprt", Optional, Many); + ExpectChildAtom("hnti", Optional, OnlyOne); + ExpectChildAtom("meta", Optional, OnlyOne); +} + +void MP4UdtaAtom::Read() +{ + if (ATOMID(m_pParentAtom->GetType()) == ATOMID("trak")) { + ExpectChildAtom("hinf", Optional, OnlyOne); + } + + MP4Atom::Read(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_url.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_url.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,63 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4UrlAtom::MP4UrlAtom(const char *type) + : MP4Atom(type) +{ + AddVersionAndFlags(); + AddProperty(new MP4StringProperty("location")); +} + +void MP4UrlAtom::Read() +{ + // read the version and flags properties + ReadProperties(0, 2); + + // check if self-contained flag is set + if (!(GetFlags() & 1)) { + // if not then read url location + ReadProperties(2); + } + + Skip(); // to end of atom +} + +void MP4UrlAtom::Write() +{ + MP4StringProperty* pLocationProp = + (MP4StringProperty*)m_pProperties[2]; + + // if no url location has been set + // then set self-contained flag + // and don't attempt to write anything + if (pLocationProp->GetValue() == NULL) { + SetFlags(GetFlags() | 1); + pLocationProp->SetImplicit(true); + } else { + SetFlags(GetFlags() & 0xFFFFFE); + pLocationProp->SetImplicit(false); + } + + // write atom as usual + MP4Atom::Write(); +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_urn.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_urn.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,44 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4UrnAtom::MP4UrnAtom() + : MP4Atom("urn ") +{ + AddVersionAndFlags(); + AddProperty(new MP4StringProperty("name")); + AddProperty(new MP4StringProperty("location")); +} + +void MP4UrnAtom::Read() +{ + // read the version, flags, and name properties + ReadProperties(0, 3); + + // check if location is present + if (m_pFile->GetPosition() < GetEnd()) { + // read it + ReadProperties(3); + } + + Skip(); // to end of atom +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_video.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_video.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,78 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com + */ + +#include "mp4common.h" + +MP4VideoAtom::MP4VideoAtom (const char *type) + : MP4Atom(type) +{ + AddReserved("reserved1", 6); /* 0 */ + + AddProperty( /* 1 */ + new MP4Integer16Property("dataReferenceIndex")); + + AddReserved("reserved2", 16); /* 2 */ + + AddProperty( /* 3 */ + new MP4Integer16Property("width")); + AddProperty( /* 4 */ + new MP4Integer16Property("height")); + + AddReserved("reserved3", 14); /* 5 */ + + MP4StringProperty* pProp = + new MP4StringProperty("compressorName"); + pProp->SetFixedLength(32); + pProp->SetValue(""); + AddProperty(pProp); /* 6 */ + + AddProperty(/* 7 */ + new MP4Integer16Property("depth")); + AddProperty(/* 8 */ + new MP4Integer16Property("colorTableId")); + ExpectChildAtom("smi ", Optional, OnlyOne); +} + +void MP4VideoAtom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved3 has non-zero fixed values + static u_int8_t reserved3[14] = { + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + }; + m_pProperties[5]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[5])-> + SetValue(reserved3, sizeof(reserved3)); + m_pProperties[5]->SetReadOnly(true); + + // depth and color table id values - should be set later + // as far as depth - color table is most likely 0xff + ((MP4IntegerProperty *)m_pProperties[7])->SetValue(0x18); + ((MP4IntegerProperty *)m_pProperties[8])->SetValue(0xffff); + +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atom_vmhd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atom_vmhd.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,37 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4VmhdAtom::MP4VmhdAtom() + : MP4Atom("vmhd") +{ + AddVersionAndFlags(); + AddReserved("reserved", 8); +} + +void MP4VmhdAtom::Generate() +{ + MP4Atom::Generate(); + + SetFlags(1); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/atoms.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/atoms.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,377 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + * Bill May wmay@cisco.com + */ + +#ifndef __MP4_ATOMS_INCLUDED__ +#define __MP4_ATOMS_INCLUDED__ + +// declare all the atom subclasses +// i.e. spare us atom_xxxx.h for all the atoms +// +// The majority of atoms just need their own constructor declared +// Some atoms have a few special needs +// A small minority of atoms need lots of special handling + +class MP4RootAtom : public MP4Atom { +public: + MP4RootAtom(); + void BeginWrite(bool use64 = false); + void Write(); + void FinishWrite(bool use64 = false); + + void BeginOptimalWrite(); + void FinishOptimalWrite(); + +protected: + u_int32_t GetLastMdatIndex(); + void WriteAtomType(const char* type, bool onlyOne); +}; + +/*********************************************************************** + * Common atom classes - standard for anything that just contains atoms + * and non-maleable properties, treftype and url + ***********************************************************************/ +class MP4StandardAtom : public MP4Atom { + public: + MP4StandardAtom(const char *name); +}; + +class MP4TrefTypeAtom : public MP4Atom { +public: + MP4TrefTypeAtom(const char* type); + void Read(); +}; + +class MP4UrlAtom : public MP4Atom { +public: + MP4UrlAtom(const char *type="url "); + void Read(); + void Write(); +}; + +/*********************************************************************** + * Sound and Video atoms - use the generic atoms when possible + * (MP4SoundAtom and MP4VideoAtom) + ***********************************************************************/ +class MP4SoundAtom : public MP4Atom { + public: + MP4SoundAtom(const char *atomid); + void Generate(); + void Read(); +protected: + void AddProperties(u_int8_t version); +}; + +class MP4VideoAtom : public MP4Atom { + public: + MP4VideoAtom(const char *atomid); + void Generate(); +}; + +class MP4AmrAtom : public MP4Atom { + public: + MP4AmrAtom(const char *type); + void Generate(); +}; + +// H.264 atoms + +class MP4Avc1Atom : public MP4Atom { + public: + MP4Avc1Atom(); + void Generate(); +}; + +class MP4AvcCAtom : public MP4Atom { + public: + MP4AvcCAtom(); + void Generate(); +}; + + + +class MP4D263Atom : public MP4Atom { + public: + MP4D263Atom(); + void Generate(); + void Write(); +}; + +class MP4DamrAtom : public MP4Atom { + public: + MP4DamrAtom(); + void Generate(); +}; + +class MP4EncaAtom : public MP4Atom { +public: + MP4EncaAtom(); + void Generate(); +}; + +class MP4EncvAtom : public MP4Atom { +public: + MP4EncvAtom(); + void Generate(); +}; + +class MP4Mp4aAtom : public MP4Atom { +public: + MP4Mp4aAtom(); + void Generate(); +}; + +class MP4Mp4sAtom : public MP4Atom { +public: + MP4Mp4sAtom(); + void Generate(); +}; + +class MP4Mp4vAtom : public MP4Atom { +public: + MP4Mp4vAtom(); + void Generate(); +}; + + +class MP4S263Atom : public MP4Atom { + public: + MP4S263Atom(); + void Generate(); +}; + + + +/************************************************************************ + * Specialized Atoms + ************************************************************************/ + +class MP4DataAtom : public MP4Atom { +public: + MP4DataAtom(); + void Read(); +}; + +class MP4DrefAtom : public MP4Atom { +public: + MP4DrefAtom(); + void Read(); +}; + +class MP4ElstAtom : public MP4Atom { +public: + MP4ElstAtom(); + void Generate(); + void Read(); +protected: + void AddProperties(u_int8_t version); +}; + +class MP4FreeAtom : public MP4Atom { +public: + MP4FreeAtom(); + void Read(); + void Write(); +}; + +class MP4FtypAtom : public MP4Atom { +public: + MP4FtypAtom(); + void Generate(); + void Read(); +}; + +class MP4HdlrAtom : public MP4Atom { +public: + MP4HdlrAtom(); + void Read(); +}; + +class MP4HinfAtom : public MP4Atom { +public: + MP4HinfAtom(); + void Generate(); +}; + +class MP4HntiAtom : public MP4Atom { +public: + MP4HntiAtom(); + void Read(); +}; + + +class MP4MdatAtom : public MP4Atom { +public: + MP4MdatAtom(); + void Read(); + void Write(); +}; + +class MP4MdhdAtom : public MP4Atom { +public: + MP4MdhdAtom(); + void Generate(); + void Read(); +protected: + void AddProperties(u_int8_t version); +}; + +class MP4MeanAtom : public MP4Atom { +public: + MP4MeanAtom(); + void Read(); +}; + + +class MP4MvhdAtom : public MP4Atom { +public: + MP4MvhdAtom(); + void Generate(); + void Read(); +protected: + void AddProperties(u_int8_t version); +}; + +class MP4NameAtom : public MP4Atom { +public: + MP4NameAtom(); + void Read(); +}; + +class MP4RtpAtom : public MP4Atom { +public: + MP4RtpAtom(); + void Generate(); + void Read(); + void Write(); + +protected: + void AddPropertiesStsdType(); + void AddPropertiesHntiType(); + + void GenerateStsdType(); + void GenerateHntiType(); + + void ReadStsdType(); + void ReadHntiType(); + + void WriteHntiType(); +}; + +class MP4SdpAtom : public MP4Atom { +public: + MP4SdpAtom(); + void Read(); + void Write(); +}; + +class MP4SmiAtom : public MP4Atom { + public: + MP4SmiAtom(void); + void Read(); +}; + +class MP4StblAtom : public MP4Atom { +public: + MP4StblAtom(); + void Generate(); +}; + +class MP4StdpAtom : public MP4Atom { +public: + MP4StdpAtom(); + void Read(); +}; + +class MP4StscAtom : public MP4Atom { +public: + MP4StscAtom(); + void Read(); +}; + +class MP4StsdAtom : public MP4Atom { +public: + MP4StsdAtom(); + void Read(); +}; + +class MP4StszAtom : public MP4Atom { +public: + MP4StszAtom(); + void Read(); + void Write(); +}; + +class MP4TfhdAtom : public MP4Atom { +public: + MP4TfhdAtom(); + void Read(); +protected: + void AddProperties(u_int32_t flags); +}; + +class MP4TkhdAtom : public MP4Atom { +public: + MP4TkhdAtom(); + void Generate(); + void Read(); +protected: + void AddProperties(u_int8_t version); +}; +class MP4TrunAtom : public MP4Atom { +public: + MP4TrunAtom(); + void Read(); +protected: + void AddProperties(u_int32_t flags); +}; + +class MP4UdtaAtom : public MP4Atom { +public: + MP4UdtaAtom(); + void Read(); +}; + +class MP4UrnAtom : public MP4Atom { +public: + MP4UrnAtom(); + void Read(); +}; +class MP4VmhdAtom : public MP4Atom { +public: + MP4VmhdAtom(); + void Generate(); +}; + +class MP4HrefAtom : public MP4Atom { + public: + MP4HrefAtom(); + void Generate(void); +}; + +#endif /* __MP4_ATOMS_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/descriptors.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/descriptors.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,634 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4IODescriptor::MP4IODescriptor() + : MP4Descriptor(MP4FileIODescrTag) +{ + /* N.B. other member functions depend on the property indicies */ + AddProperty( /* 0 */ + new MP4BitfieldProperty("objectDescriptorId", 10)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("URLFlag", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("includeInlineProfileLevelFlag", 1)); + AddProperty( /* 3 */ + new MP4BitfieldProperty("reserved", 4)); + AddProperty( /* 4 */ + new MP4StringProperty("URL", Counted)); + AddProperty( /* 5 */ + new MP4Integer8Property("ODProfileLevelId")); + AddProperty( /* 6 */ + new MP4Integer8Property("sceneProfileLevelId")); + AddProperty( /* 7 */ + new MP4Integer8Property("audioProfileLevelId")); + AddProperty( /* 8 */ + new MP4Integer8Property("visualProfileLevelId")); + AddProperty( /* 9 */ + new MP4Integer8Property("graphicsProfileLevelId")); + AddProperty( /* 10 */ + new MP4DescriptorProperty("esIds", + MP4ESIDIncDescrTag, 0, Required, Many)); + AddProperty( /* 11 */ + new MP4DescriptorProperty("ociDescr", + MP4OCIDescrTagsStart, MP4OCIDescrTagsEnd, Optional, Many)); + AddProperty( /* 12 */ + new MP4DescriptorProperty("ipmpDescrPtr", + MP4IPMPPtrDescrTag, 0, Optional, Many)); + AddProperty( /* 13 */ + new MP4DescriptorProperty("extDescr", + MP4ExtDescrTagsStart, MP4ExtDescrTagsEnd, Optional, Many)); + + SetReadMutate(2); +} + +void MP4IODescriptor::Generate() +{ + ((MP4BitfieldProperty*)m_pProperties[0])->SetValue(1); + ((MP4BitfieldProperty*)m_pProperties[3])->SetValue(0xF); + for (u_int32_t i = 5; i <= 9; i++) { + ((MP4Integer8Property*)m_pProperties[i])->SetValue(0xFF); + } +} + +void MP4IODescriptor::Mutate() +{ + bool urlFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(); + + m_pProperties[4]->SetImplicit(!urlFlag); + for (u_int32_t i = 5; i <= 12; i++) { + m_pProperties[i]->SetImplicit(urlFlag); + } +} + +MP4ODescriptor::MP4ODescriptor() + : MP4Descriptor(MP4FileODescrTag) +{ + /* N.B. other member functions depend on the property indicies */ + AddProperty( /* 0 */ + new MP4BitfieldProperty("objectDescriptorId", 10)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("URLFlag", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("reserved", 5)); + AddProperty( /* 3 */ + new MP4StringProperty("URL", Counted)); + AddProperty( /* 4 */ + new MP4DescriptorProperty("esIds", + MP4ESIDRefDescrTag, 0, Required, Many)); + AddProperty( /* 5 */ + new MP4DescriptorProperty("ociDescr", + MP4OCIDescrTagsStart, MP4OCIDescrTagsEnd, Optional, Many)); + AddProperty( /* 6 */ + new MP4DescriptorProperty("ipmpDescrPtr", + MP4IPMPPtrDescrTag, 0, Optional, Many)); + AddProperty( /* 7 */ + new MP4DescriptorProperty("extDescr", + MP4ExtDescrTagsStart, MP4ExtDescrTagsEnd, Optional, Many)); + + SetReadMutate(2); +} + +void MP4ODescriptor::Generate() +{ + ((MP4BitfieldProperty*)m_pProperties[2])->SetValue(0x1F); +} + +void MP4ODescriptor::Mutate() +{ + bool urlFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(); + + m_pProperties[3]->SetImplicit(!urlFlag); + for (u_int32_t i = 4; i <= 6; i++) { + m_pProperties[i]->SetImplicit(urlFlag); + } +} + +MP4ESIDIncDescriptor::MP4ESIDIncDescriptor() + : MP4Descriptor(MP4ESIDIncDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("id")); +} + +MP4ESIDRefDescriptor::MP4ESIDRefDescriptor() + : MP4Descriptor(MP4ESIDRefDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer16Property("refIndex")); +} + +MP4ESDescriptor::MP4ESDescriptor() + : MP4Descriptor(MP4ESDescrTag) +{ + /* N.B. other class functions depend on the property indicies */ + AddProperty( /* 0 */ + new MP4Integer16Property("ESID")); + AddProperty( /* 1 */ + new MP4BitfieldProperty("streamDependenceFlag", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("URLFlag", 1)); + AddProperty( /* 3 */ + new MP4BitfieldProperty("OCRstreamFlag", 1)); + AddProperty( /* 4 */ + new MP4BitfieldProperty("streamPriority", 5)); + AddProperty( /* 5 */ + new MP4Integer16Property("dependsOnESID")); + AddProperty( /* 6 */ + new MP4StringProperty("URL", Counted)); + AddProperty( /* 7 */ + new MP4Integer16Property("OCRESID")); + AddProperty( /* 8 */ + new MP4DescriptorProperty("decConfigDescr", + MP4DecConfigDescrTag, 0, Required, OnlyOne)); + AddProperty( /* 9 */ + new MP4DescriptorProperty("slConfigDescr", + MP4SLConfigDescrTag, 0, Required, OnlyOne)); + AddProperty( /* 10 */ + new MP4DescriptorProperty("ipiPtr", + MP4IPIPtrDescrTag, 0, Optional, OnlyOne)); + AddProperty( /* 11 */ + new MP4DescriptorProperty("ipIds", + MP4ContentIdDescrTag, MP4SupplContentIdDescrTag, Optional, Many)); + AddProperty( /* 12 */ + new MP4DescriptorProperty("ipmpDescrPtr", + MP4IPMPPtrDescrTag, 0, Optional, Many)); + AddProperty( /* 13 */ + new MP4DescriptorProperty("langDescr", + MP4LanguageDescrTag, 0, Optional, Many)); + AddProperty( /* 14 */ + new MP4DescriptorProperty("qosDescr", + MP4QosDescrTag, 0, Optional, OnlyOne)); + AddProperty( /* 15 */ + new MP4DescriptorProperty("regDescr", + MP4RegistrationDescrTag, 0, Optional, OnlyOne)); + AddProperty( /* 16 */ + new MP4DescriptorProperty("extDescr", + MP4ExtDescrTagsStart, MP4ExtDescrTagsEnd, Optional, Many)); + + SetReadMutate(5); +} + +void MP4ESDescriptor::Mutate() +{ + bool streamDependFlag = + ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(); + m_pProperties[5]->SetImplicit(!streamDependFlag); + + bool urlFlag = + ((MP4BitfieldProperty*)m_pProperties[2])->GetValue(); + m_pProperties[6]->SetImplicit(!urlFlag); + + bool ocrFlag = + ((MP4BitfieldProperty*)m_pProperties[3])->GetValue(); + m_pProperties[7]->SetImplicit(!ocrFlag); +} + +MP4DecConfigDescriptor::MP4DecConfigDescriptor() + : MP4Descriptor(MP4DecConfigDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer8Property("objectTypeId")); + AddProperty( /* 1 */ + new MP4BitfieldProperty("streamType", 6)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("upStream", 1)); + AddProperty( /* 3 */ + new MP4BitfieldProperty("reserved", 1)); + AddProperty( /* 4 */ + new MP4BitfieldProperty("bufferSizeDB", 24)); + AddProperty( /* 5 */ + new MP4Integer32Property("maxBitrate")); + AddProperty( /* 6 */ + new MP4Integer32Property("avgBitrate")); + AddProperty( /* 7 */ + new MP4DescriptorProperty("decSpecificInfo", + MP4DecSpecificDescrTag, 0, Optional, OnlyOne)); + AddProperty( /* 8 */ + new MP4DescriptorProperty("profileLevelIndicationIndexDescr", + MP4ExtProfileLevelDescrTag, 0, Optional, Many)); +} + +void MP4DecConfigDescriptor::Generate() +{ + ((MP4BitfieldProperty*)m_pProperties[3])->SetValue(1); +} + +MP4DecSpecificDescriptor::MP4DecSpecificDescriptor() + : MP4Descriptor(MP4DecSpecificDescrTag) +{ + AddProperty( /* 0 */ + new MP4BytesProperty("info")); +} + +void MP4DecSpecificDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size); + + ReadProperties(pFile); +} + +MP4SLConfigDescriptor::MP4SLConfigDescriptor() + : MP4Descriptor(MP4SLConfigDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer8Property("predefined")); + AddProperty( /* 1 */ + new MP4BitfieldProperty("useAccessUnitStartFlag", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("useAccessUnitEndFlag", 1)); + AddProperty( /* 3 */ + new MP4BitfieldProperty("useRandomAccessPointFlag", 1)); + AddProperty( /* 4 */ + new MP4BitfieldProperty("hasRandomAccessUnitsOnlyFlag", 1)); + AddProperty( /* 5 */ + new MP4BitfieldProperty("usePaddingFlag", 1)); + AddProperty( /* 6 */ + new MP4BitfieldProperty("useTimeStampsFlag", 1)); + AddProperty( /* 7 */ + new MP4BitfieldProperty("useIdleFlag", 1)); + AddProperty( /* 8 */ + new MP4BitfieldProperty("durationFlag", 1)); + AddProperty( /* 9 */ + new MP4Integer32Property("timeStampResolution")); + AddProperty( /* 10 */ + new MP4Integer32Property("OCRResolution")); + AddProperty( /* 11 */ + new MP4Integer8Property("timeStampLength")); + AddProperty( /* 12 */ + new MP4Integer8Property("OCRLength")); + AddProperty( /* 13 */ + new MP4Integer8Property("AULength")); + AddProperty( /* 14 */ + new MP4Integer8Property("instantBitrateLength")); + AddProperty( /* 15 */ + new MP4BitfieldProperty("degradationPriortyLength", 4)); + AddProperty( /* 16 */ + new MP4BitfieldProperty("AUSeqNumLength", 5)); + AddProperty( /* 17 */ + new MP4BitfieldProperty("packetSeqNumLength", 5)); + AddProperty( /* 18 */ + new MP4BitfieldProperty("reserved", 2)); + + // if durationFlag + AddProperty( /* 19 */ + new MP4Integer32Property("timeScale")); + AddProperty( /* 20 */ + new MP4Integer16Property("accessUnitDuration")); + AddProperty( /* 21 */ + new MP4Integer16Property("compositionUnitDuration")); + + // if !useTimeStampsFlag + AddProperty( /* 22 */ + new MP4BitfieldProperty("startDecodingTimeStamp", 64)); + AddProperty( /* 23 */ + new MP4BitfieldProperty("startCompositionTimeStamp", 64)); +} + +void MP4SLConfigDescriptor::Generate() +{ + // by default all tracks in an mp4 file + // use predefined SLConfig descriptor == 2 + ((MP4Integer8Property*)m_pProperties[0])->SetValue(2); + + // which implies UseTimestampsFlag = 1 + ((MP4BitfieldProperty*)m_pProperties[6])->SetValue(1); + + // reserved = 3 + ((MP4BitfieldProperty*)m_pProperties[18])->SetValue(3); +} + +void MP4SLConfigDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + // read the first property, 'predefined' + ReadProperties(pFile, 0, 1); + + // if predefined == 0 + if (((MP4Integer8Property*)m_pProperties[0])->GetValue() == 0) { + + /* read the next 18 properties */ + ReadProperties(pFile, 1, 18); + } + + // now mutate + Mutate(); + + // and read the remaining properties + ReadProperties(pFile, 19); +} + +void MP4SLConfigDescriptor::Mutate() +{ + u_int32_t i; + u_int8_t predefined = + ((MP4Integer8Property*)m_pProperties[0])->GetValue(); + + if (predefined) { + // properties 1-18 are implicit + for (i = 1; i < m_pProperties.Size(); i++) { + m_pProperties[i]->SetImplicit(true); + } + + if (predefined == 1) { + // UseTimestampsFlag = 0 + ((MP4BitfieldProperty*)m_pProperties[6])->SetValue(0); + + // TimestampResolution = 1000 + ((MP4Integer32Property*)m_pProperties[9])->SetValue(1000); + + // TimeStampLength = 32 + ((MP4Integer8Property*)m_pProperties[11])->SetValue(32); + + } else if (predefined == 2) { + // UseTimestampsFlag = 1 + ((MP4BitfieldProperty*)m_pProperties[6])->SetValue(1); + } + } else { +#if 1 + for (i = 1; i <= 18; i++) { + m_pProperties[i]->SetImplicit(false); + } + ((MP4BitfieldProperty*)m_pProperties[18])->SetValue(3); +#endif + } + + bool durationFlag = + ((MP4BitfieldProperty*)m_pProperties[8])->GetValue(); + + for (i = 19; i <= 21; i++) { + m_pProperties[i]->SetImplicit(!durationFlag); + } + + bool useTimeStampsFlag = + ((MP4BitfieldProperty*)m_pProperties[6])->GetValue(); + + for (i = 22; i <= 23; i++) { + m_pProperties[i]->SetImplicit(useTimeStampsFlag); + + u_int8_t timeStampLength = MIN(64, + ((MP4Integer8Property*)m_pProperties[11])->GetValue()); + + ((MP4BitfieldProperty*)m_pProperties[i])->SetNumBits(timeStampLength); + + // handle a nonsensical situation gracefully + if (timeStampLength == 0) { + m_pProperties[i]->SetImplicit(true); + } + } +} + +MP4IPIPtrDescriptor::MP4IPIPtrDescriptor() + : MP4Descriptor(MP4IPIPtrDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer16Property("IPIESId")); +} + +MP4ContentIdDescriptor::MP4ContentIdDescriptor() + : MP4Descriptor(MP4ContentIdDescrTag) +{ + AddProperty( /* 0 */ + new MP4BitfieldProperty("compatibility", 2)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("contentTypeFlag", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("contentIdFlag", 1)); + AddProperty( /* 3 */ + new MP4BitfieldProperty("protectedContent", 1)); + AddProperty( /* 4 */ + new MP4BitfieldProperty("reserved", 3)); + AddProperty( /* 5 */ + new MP4Integer8Property("contentType")); + AddProperty( /* 6 */ + new MP4Integer8Property("contentIdType")); + AddProperty( /* 7 */ + new MP4BytesProperty("contentId")); +} + +void MP4ContentIdDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* read the first property, 'compatiblity' */ + ReadProperties(pFile, 0, 1); + + /* if compatiblity != 0 */ + if (((MP4Integer8Property*)m_pProperties[0])->GetValue() != 0) { + /* we don't understand it */ + VERBOSE_READ(pFile->GetVerbosity(), + printf("incompatible content id descriptor\n")); + return; + } + + /* read the next four properties */ + ReadProperties(pFile, 1, 4); + + /* which allows us to reconfigure ourselves */ + Mutate(); + + /* read the remaining properties */ + ReadProperties(pFile, 5); +} + +void MP4ContentIdDescriptor::Mutate() +{ + bool contentTypeFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(); + m_pProperties[5]->SetImplicit(!contentTypeFlag); + + bool contentIdFlag = ((MP4BitfieldProperty*)m_pProperties[2])->GetValue(); + m_pProperties[6]->SetImplicit(!contentIdFlag); + m_pProperties[7]->SetImplicit(!contentIdFlag); +} + +MP4SupplContentIdDescriptor::MP4SupplContentIdDescriptor() + : MP4Descriptor(MP4SupplContentIdDescrTag) +{ + AddProperty( /* 0 */ + new MP4BytesProperty("languageCode", 3)); + AddProperty( /* 1 */ + new MP4StringProperty("title", Counted)); + AddProperty( /* 2 */ + new MP4StringProperty("value", Counted)); +} + +MP4IPMPPtrDescriptor::MP4IPMPPtrDescriptor() + : MP4Descriptor(MP4IPMPPtrDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer8Property("IPMPDescriptorId")); +} + +MP4IPMPDescriptor::MP4IPMPDescriptor() + : MP4Descriptor(MP4IPMPDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer8Property("IPMPDescriptorId")); + AddProperty( /* 1 */ + new MP4Integer16Property("IPMPSType")); + AddProperty( /* 2 */ + new MP4BytesProperty("IPMPData")); + /* note: if IPMPSType == 0, IPMPData is an URL */ +} + +void MP4IPMPDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 3); + + ReadProperties(pFile); +} + +MP4RegistrationDescriptor::MP4RegistrationDescriptor() + : MP4Descriptor(MP4RegistrationDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("formatIdentifier")); + AddProperty( /* 1 */ + new MP4BytesProperty("additionalIdentificationInfo")); +} + +void MP4RegistrationDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[1])->SetValueSize(m_size - 4); + + ReadProperties(pFile); +} + +MP4ExtProfileLevelDescriptor::MP4ExtProfileLevelDescriptor() + : MP4Descriptor(MP4ExtProfileLevelDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer8Property("profileLevelIndicationIndex")); + AddProperty( /* 1 */ + new MP4Integer8Property("ODProfileLevelIndication")); + AddProperty( /* 2 */ + new MP4Integer8Property("sceneProfileLevelIndication")); + AddProperty( /* 3 */ + new MP4Integer8Property("audioProfileLevelIndication")); + AddProperty( /* 4 */ + new MP4Integer8Property("visualProfileLevelIndication")); + AddProperty( /* 5 */ + new MP4Integer8Property("graphicsProfileLevelIndication")); + AddProperty( /* 6 */ + new MP4Integer8Property("MPEGJProfileLevelIndication")); +} + +MP4ExtensionDescriptor::MP4ExtensionDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4BytesProperty("data")); +} + +void MP4ExtensionDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size); + + ReadProperties(pFile); +} + +MP4Descriptor* MP4DescriptorProperty::CreateDescriptor(u_int8_t tag) +{ + MP4Descriptor* pDescriptor = NULL; + + switch (tag) { + case MP4ESDescrTag: + pDescriptor = new MP4ESDescriptor(); + break; + case MP4DecConfigDescrTag: + pDescriptor = new MP4DecConfigDescriptor(); + break; + case MP4DecSpecificDescrTag: + pDescriptor = new MP4DecSpecificDescriptor(); + break; + case MP4SLConfigDescrTag: + pDescriptor = new MP4SLConfigDescriptor(); + break; + case MP4ContentIdDescrTag: + pDescriptor = new MP4ContentIdDescriptor(); + break; + case MP4SupplContentIdDescrTag: + pDescriptor = new MP4SupplContentIdDescriptor(); + break; + case MP4IPIPtrDescrTag: + pDescriptor = new MP4IPIPtrDescriptor(); + break; + case MP4IPMPPtrDescrTag: + pDescriptor = new MP4IPMPPtrDescriptor(); + break; + case MP4IPMPDescrTag: + pDescriptor = new MP4IPMPDescriptor(); + break; + case MP4QosDescrTag: + pDescriptor = new MP4QosDescriptor(); + break; + case MP4RegistrationDescrTag: + pDescriptor = new MP4RegistrationDescriptor(); + break; + case MP4ESIDIncDescrTag: + pDescriptor = new MP4ESIDIncDescriptor(); + break; + case MP4ESIDRefDescrTag: + pDescriptor = new MP4ESIDRefDescriptor(); + break; + case MP4IODescrTag: + case MP4FileIODescrTag: + pDescriptor = new MP4IODescriptor(); + pDescriptor->SetTag(tag); + break; + case MP4ODescrTag: + case MP4FileODescrTag: + pDescriptor = new MP4ODescriptor(); + pDescriptor->SetTag(tag); + break; + case MP4ExtProfileLevelDescrTag: + pDescriptor = new MP4ExtProfileLevelDescriptor(); + break; + } + + if (pDescriptor == NULL) { + if (tag >= MP4OCIDescrTagsStart && tag <= MP4OCIDescrTagsEnd) { + pDescriptor = CreateOCIDescriptor(tag); + } + + if (tag >= MP4ExtDescrTagsStart && tag <= MP4ExtDescrTagsEnd) { + pDescriptor = new MP4ExtensionDescriptor(); + pDescriptor->SetTag(tag); + } + } + + return pDescriptor; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/descriptors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/descriptors.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,164 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __DESCRIPTORS_INCLUDED__ +#define __DESCRIPTORS_INCLUDED__ + +const u_int8_t MP4ODescrTag = 0x01; +const u_int8_t MP4IODescrTag = 0x02; +const u_int8_t MP4ESDescrTag = 0x03; +const u_int8_t MP4DecConfigDescrTag = 0x04; +const u_int8_t MP4DecSpecificDescrTag = 0x05; +const u_int8_t MP4SLConfigDescrTag = 0x06; +const u_int8_t MP4ContentIdDescrTag = 0x07; +const u_int8_t MP4SupplContentIdDescrTag = 0x08; +const u_int8_t MP4IPIPtrDescrTag = 0x09; +const u_int8_t MP4IPMPPtrDescrTag = 0x0A; +const u_int8_t MP4IPMPDescrTag = 0x0B; +const u_int8_t MP4RegistrationDescrTag = 0x0D; +const u_int8_t MP4ESIDIncDescrTag = 0x0E; +const u_int8_t MP4ESIDRefDescrTag = 0x0F; +const u_int8_t MP4FileIODescrTag = 0x10; +const u_int8_t MP4FileODescrTag = 0x11; +const u_int8_t MP4ExtProfileLevelDescrTag = 0x13; +const u_int8_t MP4ExtDescrTagsStart = 0x80; +const u_int8_t MP4ExtDescrTagsEnd = 0xFE; + +class MP4IODescriptor : public MP4Descriptor { +public: + MP4IODescriptor(); + void Generate(); +protected: + void Mutate(); +}; + +class MP4ODescriptor : public MP4Descriptor { +public: + MP4ODescriptor(); + void Generate(); +protected: + void Mutate(); +}; + +class MP4ESIDIncDescriptor : public MP4Descriptor { +public: + MP4ESIDIncDescriptor(); +}; + +class MP4ESIDRefDescriptor : public MP4Descriptor { +public: + MP4ESIDRefDescriptor(); +}; + +class MP4ESDescriptor : public MP4Descriptor { +public: + MP4ESDescriptor(); +protected: + void Mutate(); +}; + +class MP4DecConfigDescriptor : public MP4Descriptor { +public: + MP4DecConfigDescriptor(); + void Generate(); +}; + +class MP4DecSpecificDescriptor : public MP4Descriptor { +public: + MP4DecSpecificDescriptor(); + void Read(MP4File* pFile); +}; + +class MP4SLConfigDescriptor : public MP4Descriptor { +public: + MP4SLConfigDescriptor(); + void Generate(); + void Read(MP4File* pFile); + protected: + void Mutate(); +}; + +class MP4IPIPtrDescriptor : public MP4Descriptor { +public: + MP4IPIPtrDescriptor(); +}; + +class MP4ContentIdDescriptor : public MP4Descriptor { +public: + MP4ContentIdDescriptor(); + void Read(MP4File* pFile); +protected: + void Mutate(); +}; + +class MP4SupplContentIdDescriptor : public MP4Descriptor { +public: + MP4SupplContentIdDescriptor(); +}; + +class MP4IPMPPtrDescriptor : public MP4Descriptor { +public: + MP4IPMPPtrDescriptor(); +}; + +class MP4IPMPDescriptor : public MP4Descriptor { +public: + MP4IPMPDescriptor(); + void Read(MP4File* pFile); +}; + +class MP4RegistrationDescriptor : public MP4Descriptor { +public: + MP4RegistrationDescriptor(); + void Read(MP4File* pFile); +}; + +class MP4ExtProfileLevelDescriptor : public MP4Descriptor { +public: + MP4ExtProfileLevelDescriptor(); +}; + +class MP4ExtensionDescriptor : public MP4Descriptor { +public: + MP4ExtensionDescriptor(); + void Read(MP4File* pFile); +}; + +// associated values in descriptors + +// ES objectTypeId +const u_int8_t MP4SystemsV1ObjectType = 0x01; +const u_int8_t MP4SystemsV2ObjectType = 0x02; + +// ES streamType +const u_int8_t MP4ObjectDescriptionStreamType = 0x01; +const u_int8_t MP4ClockReferenceStreamType = 0x02; +const u_int8_t MP4SceneDescriptionStreamType = 0x03; +const u_int8_t MP4VisualStreamType = 0x04; +const u_int8_t MP4AudioStreamType = 0x05; +const u_int8_t MP4Mpeg7StreamType = 0x06; +const u_int8_t MP4IPMPStreamType = 0x07; +const u_int8_t MP4OCIStreamType = 0x08; +const u_int8_t MP4MPEGJStreamType = 0x09; +const u_int8_t MP4UserPrivateStreamType = 0x20; + +#endif /* __DESCRIPTORS_INCLUDED__ */ + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/isma.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/isma.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,920 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2004. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +static const u_int8_t BifsV2Config[3] = { + 0x00, 0x00, 0x60 // IsCommandStream = 1, PixelMetric = 1 +}; + +void MP4File::MakeIsmaCompliant(bool addIsmaComplianceSdp) +{ + ProtectWriteOperation("MP4MakeIsmaCompliant"); + + if (m_useIsma) { + // already done + return; + } + + // find first audio and/or video tracks + + MP4TrackId audioTrackId = MP4_INVALID_TRACK_ID; + try { + audioTrackId = FindTrackId(0, MP4_AUDIO_TRACK_TYPE); + } + catch (MP4Error* e) { + delete e; + } + + MP4TrackId videoTrackId = MP4_INVALID_TRACK_ID; + try { + videoTrackId = FindTrackId(0, MP4_VIDEO_TRACK_TYPE); + } + catch (MP4Error* e) { + delete e; + } + if (audioTrackId == MP4_INVALID_TRACK_ID && + videoTrackId == MP4_INVALID_TRACK_ID) return; + + const char *audio_media_data_name, *video_media_data_name; + if (audioTrackId != MP4_INVALID_TRACK_ID) { + audio_media_data_name = MP4GetTrackMediaDataName(this, audioTrackId); + if (!(ATOMID(audio_media_data_name) == ATOMID("mp4a") || + ATOMID(audio_media_data_name) == ATOMID("enca"))) { + VERBOSE_ERROR(m_verbosity, + printf("MakeIsmaCompliant:can't make ISMA compliant when file contains an %s track\n", audio_media_data_name); + ); + return; + } + } + // + // Note - might have to check for avc1 here... + if (videoTrackId != MP4_INVALID_TRACK_ID) { + video_media_data_name = MP4GetTrackMediaDataName(this, videoTrackId); + if (!(ATOMID(video_media_data_name) == ATOMID("mp4v") || + ATOMID(video_media_data_name) == ATOMID("encv"))) { + VERBOSE_ERROR(m_verbosity, + printf("MakeIsmaCompliant:can't make ISMA compliant when file contains an %s track\n", video_media_data_name); + ); + return; + } + } + + m_useIsma = true; + + u_int64_t fileMsDuration = + ConvertFromMovieDuration(GetDuration(), MP4_MSECS_TIME_SCALE); + + // delete any existing OD track + if (m_odTrackId != MP4_INVALID_TRACK_ID) { + DeleteTrack(m_odTrackId); + } + + AddODTrack(); + SetODProfileLevel(0xFF); + + if (audioTrackId != MP4_INVALID_TRACK_ID) { + AddTrackToOd(audioTrackId); + } + + if (videoTrackId != MP4_INVALID_TRACK_ID) { + AddTrackToOd(videoTrackId); + } + + // delete any existing scene track + MP4TrackId sceneTrackId = MP4_INVALID_TRACK_ID; + try { + sceneTrackId = FindTrackId(0, MP4_SCENE_TRACK_TYPE); + } + catch (MP4Error *e) { + delete e; + } + if (sceneTrackId != MP4_INVALID_TRACK_ID) { + DeleteTrack(sceneTrackId); + } + + // add scene track + sceneTrackId = AddSceneTrack(); + SetSceneProfileLevel(0xFF); + SetGraphicsProfileLevel(0xFF); + SetTrackIntegerProperty(sceneTrackId, + "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId", + MP4SystemsV2ObjectType); + + SetTrackESConfiguration(sceneTrackId, + BifsV2Config, sizeof(BifsV2Config)); + + u_int8_t* pBytes = NULL; + u_int64_t numBytes = 0; + + // write OD Update Command + CreateIsmaODUpdateCommandFromFileForFile( + m_odTrackId, + audioTrackId, + videoTrackId, + &pBytes, + &numBytes); + + WriteSample(m_odTrackId, pBytes, numBytes, fileMsDuration); + + MP4Free(pBytes); + pBytes = NULL; + + // write BIFS Scene Replace Command + CreateIsmaSceneCommand( + MP4_IS_VALID_TRACK_ID(audioTrackId), + MP4_IS_VALID_TRACK_ID(videoTrackId), + &pBytes, + &numBytes); + + WriteSample(sceneTrackId, pBytes, numBytes, fileMsDuration); + + MP4Free(pBytes); + pBytes = NULL; + + // add session level sdp + CreateIsmaIodFromFile( + m_odTrackId, + sceneTrackId, + audioTrackId, + videoTrackId, + &pBytes, + &numBytes); + + char* iodBase64 = MP4ToBase64(pBytes, numBytes); + + char* sdpBuf = (char*)MP4Calloc(strlen(iodBase64) + 256); + + if (addIsmaComplianceSdp) { + strcpy(sdpBuf, "a=isma-compliance:1,1.0,1\015\012"); + } + + sprintf(&sdpBuf[strlen(sdpBuf)], + "a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042\015\012", + iodBase64); + + SetSessionSdp(sdpBuf); + + VERBOSE_ISMA(GetVerbosity(), + printf("IOD SDP = %s\n", sdpBuf)); + + MP4Free(iodBase64); + iodBase64 = NULL; + MP4Free(pBytes); + pBytes = NULL; + MP4Free(sdpBuf); + sdpBuf = NULL; +} + +static void CloneIntegerProperty( + MP4Descriptor* pDest, + MP4DescriptorProperty* pSrc, + const char* name) +{ + MP4IntegerProperty* pGetProperty; + MP4IntegerProperty* pSetProperty; + + pSrc->FindProperty(name, (MP4Property**)&pGetProperty); + pDest->FindProperty(name, (MP4Property**)&pSetProperty); + + pSetProperty->SetValue(pGetProperty->GetValue()); +} + +void MP4File::CreateIsmaIodFromFile( + MP4TrackId odTrackId, + MP4TrackId sceneTrackId, + MP4TrackId audioTrackId, + MP4TrackId videoTrackId, + u_int8_t** ppBytes, + u_int64_t* pNumBytes) +{ + MP4Descriptor* pIod = new MP4IODescriptor(); + pIod->SetTag(MP4IODescrTag); + pIod->Generate(); + + MP4Atom* pIodsAtom = FindAtom("moov.iods"); + ASSERT(pIodsAtom); + MP4DescriptorProperty* pSrcIod = + (MP4DescriptorProperty*)pIodsAtom->GetProperty(2); + + CloneIntegerProperty(pIod, pSrcIod, "objectDescriptorId"); + CloneIntegerProperty(pIod, pSrcIod, "ODProfileLevelId"); + CloneIntegerProperty(pIod, pSrcIod, "sceneProfileLevelId"); + CloneIntegerProperty(pIod, pSrcIod, "audioProfileLevelId"); + CloneIntegerProperty(pIod, pSrcIod, "visualProfileLevelId"); + CloneIntegerProperty(pIod, pSrcIod, "graphicsProfileLevelId"); + + // mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag + MP4DescriptorProperty* pEsProperty; + pIod->FindProperty("esIds", (MP4Property**)&pEsProperty); + pEsProperty->SetTags(MP4ESDescrTag); + + MP4IntegerProperty* pSetProperty; + MP4IntegerProperty* pSceneESID; + MP4IntegerProperty* pOdESID; + + // OD + MP4Descriptor* pOdEsd = + pEsProperty->AddDescriptor(MP4ESDescrTag); + pOdEsd->Generate(); + + pOdEsd->FindProperty("ESID", + (MP4Property**)&pOdESID); + + // we set the OD ESID to a non-zero unique value + pOdESID->SetValue(m_odTrackId); + + pOdEsd->FindProperty("URLFlag", + (MP4Property**)&pSetProperty); + pSetProperty->SetValue(1); + + u_int8_t* pBytes; + u_int64_t numBytes; + + CreateIsmaODUpdateCommandFromFileForStream( + audioTrackId, + videoTrackId, + &pBytes, + &numBytes); + + VERBOSE_ISMA(GetVerbosity(), + printf("OD data =\n"); MP4HexDump(pBytes, numBytes)); + + char* odCmdBase64 = MP4ToBase64(pBytes, numBytes); + + char* urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64); + + sprintf(urlBuf, + "data:application/mpeg4-od-au;base64,%s", + odCmdBase64); + + MP4StringProperty* pUrlProperty; + pOdEsd->FindProperty("URL", + (MP4Property**)&pUrlProperty); + pUrlProperty->SetValue(urlBuf); + + VERBOSE_ISMA(GetVerbosity(), + printf("OD data URL = \042%s\042\n", urlBuf)); + + MP4Free(odCmdBase64); + odCmdBase64 = NULL; + MP4Free(pBytes); + pBytes = NULL; + MP4Free(urlBuf); + urlBuf = NULL; + + MP4DescriptorProperty* pSrcDcd = NULL; + + // HACK temporarily point to scene decoder config + FindProperty(MakeTrackName(odTrackId, + "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"), + (MP4Property**)&pSrcDcd); + ASSERT(pSrcDcd); + MP4Property* pOrgOdEsdProperty = + pOdEsd->GetProperty(8); + pOdEsd->SetProperty(8, pSrcDcd); + + // bufferSizeDB needs to be set appropriately + MP4BitfieldProperty* pBufferSizeProperty = NULL; + pOdEsd->FindProperty("decConfigDescr.bufferSizeDB", + (MP4Property**)&pBufferSizeProperty); + ASSERT(pBufferSizeProperty); + pBufferSizeProperty->SetValue(numBytes); + + // SL config needs to change from 2 (file) to 1 (null) + pOdEsd->FindProperty("slConfigDescr.predefined", + (MP4Property**)&pSetProperty); + pSetProperty->SetValue(1); + + + // Scene + MP4Descriptor* pSceneEsd = + pEsProperty->AddDescriptor(MP4ESDescrTag); + pSceneEsd->Generate(); + + pSceneEsd->FindProperty("ESID", + (MP4Property**)&pSceneESID); + // we set the Scene ESID to a non-zero unique value + pSceneESID->SetValue(sceneTrackId); + + pSceneEsd->FindProperty("URLFlag", + (MP4Property**)&pSetProperty); + pSetProperty->SetValue(1); + + CreateIsmaSceneCommand( + MP4_IS_VALID_TRACK_ID(audioTrackId), + MP4_IS_VALID_TRACK_ID(videoTrackId), + &pBytes, + &numBytes); + + VERBOSE_ISMA(GetVerbosity(), + printf("Scene data =\n"); MP4HexDump(pBytes, numBytes)); + + char *sceneCmdBase64 = MP4ToBase64(pBytes, numBytes); + + urlBuf = (char*)MP4Malloc(strlen(sceneCmdBase64) + 64); + sprintf(urlBuf, + "data:application/mpeg4-bifs-au;base64,%s", + sceneCmdBase64); + + pSceneEsd->FindProperty("URL", + (MP4Property**)&pUrlProperty); + pUrlProperty->SetValue(urlBuf); + + VERBOSE_ISMA(GetVerbosity(), + printf("Scene data URL = \042%s\042\n", urlBuf)); + + MP4Free(sceneCmdBase64); + sceneCmdBase64 = NULL; + MP4Free(urlBuf); + urlBuf = NULL; + MP4Free(pBytes); + pBytes = NULL; + + // HACK temporarily point to scene decoder config + FindProperty(MakeTrackName(sceneTrackId, + "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"), + (MP4Property**)&pSrcDcd); + ASSERT(pSrcDcd); + MP4Property* pOrgSceneEsdProperty = + pSceneEsd->GetProperty(8); + pSceneEsd->SetProperty(8, pSrcDcd); + + // bufferSizeDB needs to be set + pBufferSizeProperty = NULL; + pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB", + (MP4Property**)&pBufferSizeProperty); + ASSERT(pBufferSizeProperty); + pBufferSizeProperty->SetValue(numBytes); + + // SL config needs to change from 2 (file) to 1 (null) + pSceneEsd->FindProperty("slConfigDescr.predefined", + (MP4Property**)&pSetProperty); + pSetProperty->SetValue(1); + + + // finally get the whole thing written to a memory + pIod->WriteToMemory(this, ppBytes, pNumBytes); + + + // now carefully replace esd properties before destroying + pOdEsd->SetProperty(8, pOrgOdEsdProperty); + pSceneEsd->SetProperty(8, pOrgSceneEsdProperty); + pSceneESID->SetValue(0); // restore 0 value + pOdESID->SetValue(0); + + delete pIod; + + VERBOSE_ISMA(GetVerbosity(), + printf("IOD data =\n"); MP4HexDump(*ppBytes, *pNumBytes)); +} + +void MP4File::CreateIsmaIodFromParams( + u_int8_t videoProfile, + u_int32_t videoBitrate, + u_int8_t* videoConfig, + u_int32_t videoConfigLength, + u_int8_t audioProfile, + u_int32_t audioBitrate, + u_int8_t* audioConfig, + u_int32_t audioConfigLength, + u_int8_t** ppIodBytes, + u_int64_t* pIodNumBytes) +{ + MP4IntegerProperty* pInt; + u_int8_t* pBytes = NULL; + u_int64_t numBytes; + + // Create the IOD + MP4Descriptor* pIod = new MP4IODescriptor(); + pIod->SetTag(MP4IODescrTag); + pIod->Generate(); + + // Set audio and video profileLevels + pIod->FindProperty("audioProfileLevelId", + (MP4Property**)&pInt); + pInt->SetValue(audioProfile); + + pIod->FindProperty("visualProfileLevelId", + (MP4Property**)&pInt); + pInt->SetValue(videoProfile); + + // Mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag + MP4DescriptorProperty* pEsProperty; + pIod->FindProperty("esIds", (MP4Property**)&pEsProperty); + pEsProperty->SetTags(MP4ESDescrTag); + + // Add ES Descriptors + + // Scene + CreateIsmaSceneCommand( + (audioProfile != 0xFF), + (videoProfile != 0xFF), + &pBytes, + &numBytes); + + VERBOSE_ISMA(GetVerbosity(), + printf("Scene data =\n"); MP4HexDump(pBytes, numBytes)); + + char* sceneCmdBase64 = MP4ToBase64(pBytes, numBytes); + + char* urlBuf = + (char*)MP4Malloc(strlen(sceneCmdBase64) + 64); + sprintf(urlBuf, + "data:application/mpeg4-bifs-au;base64,%s", + sceneCmdBase64); + + VERBOSE_ISMA(GetVerbosity(), + printf("Scene data URL = \042%s\042\n", urlBuf)); + + /* MP4Descriptor* pSceneEsd = */ + CreateESD( + pEsProperty, + 201, // esid + MP4SystemsV2ObjectType, + MP4SceneDescriptionStreamType, + numBytes, // bufferSize + numBytes * 8, // bitrate + BifsV2Config, + sizeof(BifsV2Config), + urlBuf); + + MP4Free(sceneCmdBase64); + sceneCmdBase64 = NULL; + MP4Free(urlBuf); + urlBuf = NULL; + MP4Free(pBytes); + pBytes = NULL; + + // OD + + // Video + MP4DescriptorProperty* pVideoEsdProperty = + new MP4DescriptorProperty(); + pVideoEsdProperty->SetTags(MP4ESDescrTag); + + /* MP4Descriptor* pVideoEsd = */ + CreateESD( + pVideoEsdProperty, + 20, // esid + MP4_MPEG4_VIDEO_TYPE, + MP4VisualStreamType, + videoBitrate / 8, // bufferSize + videoBitrate, + videoConfig, + videoConfigLength, + NULL); + + // Audio + MP4DescriptorProperty* pAudioEsdProperty = + new MP4DescriptorProperty(); + pAudioEsdProperty->SetTags(MP4ESDescrTag); + + /* MP4Descriptor* pAudioEsd = */ + CreateESD( + pAudioEsdProperty, + 10, // esid + MP4_MPEG4_AUDIO_TYPE, + MP4AudioStreamType, + audioBitrate / 8, // bufferSize + audioBitrate, + audioConfig, + audioConfigLength, + NULL); + + CreateIsmaODUpdateCommandForStream( + pAudioEsdProperty, + pVideoEsdProperty, + &pBytes, + &numBytes); + + // cleanup temporary descriptor properties + delete pAudioEsdProperty; + delete pVideoEsdProperty; + + VERBOSE_ISMA(GetVerbosity(), + printf("OD data = %llu bytes\n", numBytes); MP4HexDump(pBytes, numBytes)); + + char* odCmdBase64 = MP4ToBase64(pBytes, numBytes); + + urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64); + + sprintf(urlBuf, + "data:application/mpeg4-od-au;base64,%s", + odCmdBase64); + + VERBOSE_ISMA(GetVerbosity(), + printf("OD data URL = \042%s\042\n", urlBuf)); + + /* MP4Descriptor* pOdEsd = */ + CreateESD( + pEsProperty, + 101, + MP4SystemsV1ObjectType, + MP4ObjectDescriptionStreamType, + numBytes, // bufferSize + numBytes * 8, // bitrate + NULL, // config + 0, // configLength + urlBuf); + + MP4Free(odCmdBase64); + odCmdBase64 = NULL; + MP4Free(pBytes); + pBytes = NULL; + MP4Free(urlBuf); + urlBuf = NULL; + + // finally get the whole thing written to a memory + pIod->WriteToMemory(this, ppIodBytes, pIodNumBytes); + + delete pIod; + + VERBOSE_ISMA(GetVerbosity(), + printf("IOD data =\n"); MP4HexDump(*ppIodBytes, *pIodNumBytes)); +} + +MP4Descriptor* MP4File::CreateESD( + MP4DescriptorProperty* pEsProperty, + u_int32_t esid, + u_int8_t objectType, + u_int8_t streamType, + u_int32_t bufferSize, + u_int32_t bitrate, + const u_int8_t* pConfig, + u_int32_t configLength, + char* url) +{ + MP4IntegerProperty* pInt; + MP4StringProperty* pString; + MP4BytesProperty* pBytes; + MP4BitfieldProperty* pBits; + + MP4Descriptor* pEsd = + pEsProperty->AddDescriptor(MP4ESDescrTag); + pEsd->Generate(); + + pEsd->FindProperty("ESID", + (MP4Property**)&pInt); + pInt->SetValue(esid); + + pEsd->FindProperty("decConfigDescr.objectTypeId", + (MP4Property**)&pInt); + pInt->SetValue(objectType); + + pEsd->FindProperty("decConfigDescr.streamType", + (MP4Property**)&pInt); + pInt->SetValue(streamType); + + pEsd->FindProperty("decConfigDescr.bufferSizeDB", + (MP4Property**)&pInt); + pInt->SetValue(bufferSize); + + pEsd->FindProperty("decConfigDescr.maxBitrate", + (MP4Property**)&pInt); + pInt->SetValue(bitrate); + + pEsd->FindProperty("decConfigDescr.avgBitrate", + (MP4Property**)&pInt); + pInt->SetValue(bitrate); + + MP4DescriptorProperty* pConfigDescrProperty; + pEsd->FindProperty("decConfigDescr.decSpecificInfo", + (MP4Property**)&pConfigDescrProperty); + + MP4Descriptor* pConfigDescr = + pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag); + pConfigDescr->Generate(); + + pConfigDescrProperty->FindProperty("decSpecificInfo[0].info", + (MP4Property**)&pBytes); + pBytes->SetValue(pConfig, configLength); + + pEsd->FindProperty("slConfigDescr.predefined", + (MP4Property**)&pInt); + // changed 12/5/02 from plugfest to value 0 + pInt->SetValue(0); + + pEsd->FindProperty("slConfig.useAccessUnitEndFlag", + (MP4Property **)&pBits); + pBits->SetValue(1); + + if (url) { + pEsd->FindProperty("URLFlag", + (MP4Property**)&pInt); + pInt->SetValue(1); + + pEsd->FindProperty("URL", + (MP4Property**)&pString); + pString->SetValue(url); + } + + return pEsd; +} + +void MP4File::CreateIsmaODUpdateCommandFromFileForFile( + MP4TrackId odTrackId, + MP4TrackId audioTrackId, + MP4TrackId videoTrackId, + u_int8_t** ppBytes, + u_int64_t* pNumBytes) +{ + MP4Descriptor* pCommand = CreateODCommand(MP4ODUpdateODCommandTag); + pCommand->Generate(); + + for (u_int8_t i = 0; i < 2; i++) { + MP4TrackId trackId; + u_int16_t odId; + + if (i == 0) { + trackId = audioTrackId; + odId = 10; + } else { + trackId = videoTrackId; + odId = 20; + } + + if (trackId == MP4_INVALID_TRACK_ID) { + continue; + } + + MP4DescriptorProperty* pOdDescrProperty = + (MP4DescriptorProperty*)(pCommand->GetProperty(0)); + + pOdDescrProperty->SetTags(MP4FileODescrTag); + + MP4Descriptor* pOd = + pOdDescrProperty->AddDescriptor(MP4FileODescrTag); + + pOd->Generate(); + + MP4BitfieldProperty* pOdIdProperty = NULL; + pOd->FindProperty("objectDescriptorId", + (MP4Property**)&pOdIdProperty); + pOdIdProperty->SetValue(odId); + + MP4DescriptorProperty* pEsIdsDescriptorProperty = NULL; + pOd->FindProperty("esIds", + (MP4Property**)&pEsIdsDescriptorProperty); + ASSERT(pEsIdsDescriptorProperty); + + pEsIdsDescriptorProperty->SetTags(MP4ESIDRefDescrTag); + + MP4Descriptor *pRefDescriptor = + pEsIdsDescriptorProperty->AddDescriptor(MP4ESIDRefDescrTag); + pRefDescriptor->Generate(); + + MP4Integer16Property* pRefIndexProperty = NULL; + pRefDescriptor->FindProperty("refIndex", + (MP4Property**)&pRefIndexProperty); + ASSERT(pRefIndexProperty); + + u_int32_t mpodIndex = FindTrackReference( + MakeTrackName(odTrackId, "tref.mpod"), trackId); + ASSERT(mpodIndex != 0); + + pRefIndexProperty->SetValue(mpodIndex); + } + + pCommand->WriteToMemory(this, ppBytes, pNumBytes); + + delete pCommand; +} + +void MP4File::CreateIsmaODUpdateCommandFromFileForStream( + MP4TrackId audioTrackId, + MP4TrackId videoTrackId, + u_int8_t** ppBytes, + u_int64_t* pNumBytes) +{ + MP4DescriptorProperty* pAudioEsd = NULL; + MP4Integer8Property* pAudioSLConfigPredef = NULL; + MP4BitfieldProperty* pAudioAccessUnitEndFlag = NULL; + int oldAudioUnitEndFlagValue = 0; + MP4DescriptorProperty* pVideoEsd = NULL; + MP4Integer8Property* pVideoSLConfigPredef = NULL; + MP4BitfieldProperty* pVideoAccessUnitEndFlag = NULL; + int oldVideoUnitEndFlagValue = 0; + MP4IntegerProperty* pAudioEsdId = NULL; + MP4IntegerProperty* pVideoEsdId = NULL; + + if (audioTrackId != MP4_INVALID_TRACK_ID) { + // changed mp4a to * to handle enca case + MP4Atom* pEsdsAtom = + FindAtom(MakeTrackName(audioTrackId, + "mdia.minf.stbl.stsd.*.esds")); + ASSERT(pEsdsAtom); + + pAudioEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2)); + // ESID is 0 for file, stream needs to be non-ze + pAudioEsd->FindProperty("ESID", + (MP4Property**)&pAudioEsdId); + + ASSERT(pAudioEsdId); + pAudioEsdId->SetValue(audioTrackId); + + // SL config needs to change from 2 (file) to 1 (null) + pAudioEsd->FindProperty("slConfigDescr.predefined", + (MP4Property**)&pAudioSLConfigPredef); + ASSERT(pAudioSLConfigPredef); + pAudioSLConfigPredef->SetValue(0); + + pAudioEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag", + (MP4Property **)&pAudioAccessUnitEndFlag); + oldAudioUnitEndFlagValue = + pAudioAccessUnitEndFlag->GetValue(); + pAudioAccessUnitEndFlag->SetValue(1); + } + + if (videoTrackId != MP4_INVALID_TRACK_ID) { + // changed mp4v to * to handle encv case + MP4Atom* pEsdsAtom = + FindAtom(MakeTrackName(videoTrackId, + "mdia.minf.stbl.stsd.*.esds")); + ASSERT(pEsdsAtom); + + pVideoEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2)); + pVideoEsd->FindProperty("ESID", + (MP4Property**)&pVideoEsdId); + + ASSERT(pVideoEsdId); + pVideoEsdId->SetValue(videoTrackId); + + // SL config needs to change from 2 (file) to 1 (null) + pVideoEsd->FindProperty("slConfigDescr.predefined", + (MP4Property**)&pVideoSLConfigPredef); + ASSERT(pVideoSLConfigPredef); + pVideoSLConfigPredef->SetValue(0); + + pVideoEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag", + (MP4Property **)&pVideoAccessUnitEndFlag); + oldVideoUnitEndFlagValue = + pVideoAccessUnitEndFlag->GetValue(); + pVideoAccessUnitEndFlag->SetValue(1); + } + + CreateIsmaODUpdateCommandForStream( + pAudioEsd, pVideoEsd, ppBytes, pNumBytes); + VERBOSE_ISMA(GetVerbosity(), + printf("After CreateImsaODUpdateCommandForStream len %llu =\n", *pNumBytes); MP4HexDump(*ppBytes, *pNumBytes)); + // return SL config values to 2 (file) + // return ESID values to 0 + if (pAudioSLConfigPredef) { + pAudioSLConfigPredef->SetValue(2); + } + if (pAudioEsdId) { + pAudioEsdId->SetValue(0); + } + if (pAudioAccessUnitEndFlag) { + pAudioAccessUnitEndFlag->SetValue(oldAudioUnitEndFlagValue ); + } + if (pVideoEsdId) { + pVideoEsdId->SetValue(0); + } + if (pVideoSLConfigPredef) { + pVideoSLConfigPredef->SetValue(2); + } + if (pVideoAccessUnitEndFlag) { + pVideoAccessUnitEndFlag->SetValue(oldVideoUnitEndFlagValue ); + } +} + +void MP4File::CreateIsmaODUpdateCommandForStream( + MP4DescriptorProperty* pAudioEsdProperty, + MP4DescriptorProperty* pVideoEsdProperty, + u_int8_t** ppBytes, + u_int64_t* pNumBytes) +{ + MP4Descriptor* pAudioOd = NULL; + MP4Descriptor* pVideoOd = NULL; + + MP4Descriptor* pCommand = + CreateODCommand(MP4ODUpdateODCommandTag); + pCommand->Generate(); + + for (u_int8_t i = 0; i < 2; i++) { + u_int16_t odId; + MP4DescriptorProperty* pEsdProperty = NULL; + + if (i == 0) { + odId = 10; + pEsdProperty = pAudioEsdProperty; + } else { + odId = 20; + pEsdProperty = pVideoEsdProperty; + } + + if (pEsdProperty == NULL) { + continue; + } + + MP4DescriptorProperty* pOdDescrProperty = + (MP4DescriptorProperty*)(pCommand->GetProperty(0)); + + pOdDescrProperty->SetTags(MP4ODescrTag); + + MP4Descriptor* pOd = + pOdDescrProperty->AddDescriptor(MP4ODescrTag); + pOd->Generate(); + + if (i == 0) { + pAudioOd = pOd; + } else { + pVideoOd = pOd; + } + + MP4BitfieldProperty* pOdIdProperty = NULL; + pOd->FindProperty("objectDescriptorId", + (MP4Property**)&pOdIdProperty); + pOdIdProperty->SetValue(odId); + + delete (MP4DescriptorProperty*)pOd->GetProperty(4); + pOd->SetProperty(4, pEsdProperty); + } + + // serialize OD command + pCommand->WriteToMemory(this, ppBytes, pNumBytes); + + // detach from esd descriptor params + if (pAudioOd) { + pAudioOd->SetProperty(4, NULL); + } + if (pVideoOd) { + pVideoOd->SetProperty(4, NULL); + } + + // then destroy + delete pCommand; +} + +void MP4File::CreateIsmaSceneCommand( + bool hasAudio, + bool hasVideo, + u_int8_t** ppBytes, + u_int64_t* pNumBytes) +{ + // from ISMA 1.0 Tech Spec Appendix E + static const u_int8_t bifsAudioOnly[] = { + 0xC0, 0x10, 0x12, + 0x81, 0x30, 0x2A, 0x05, 0x6D, 0xC0 + }; + static const u_int8_t bifsVideoOnly[] = { + 0xC0, 0x10, 0x12, + 0x61, 0x04, + 0x1F, 0xC0, 0x00, 0x00, + 0x1F, 0xC0, 0x00, 0x00, + 0x44, 0x28, 0x22, 0x82, 0x9F, 0x80 + }; + static const u_int8_t bifsAudioVideo[] = { + 0xC0, 0x10, 0x12, + 0x81, 0x30, 0x2A, 0x05, 0x6D, 0x26, + 0x10, 0x41, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, + 0x04, 0x42, 0x82, 0x28, 0x29, 0xF8 + }; + + if (hasAudio && hasVideo) { + *pNumBytes = sizeof(bifsAudioVideo); + *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes); + memcpy(*ppBytes, bifsAudioVideo, sizeof(bifsAudioVideo)); + + } else if (hasAudio) { + *pNumBytes = sizeof(bifsAudioOnly); + *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes); + memcpy(*ppBytes, bifsAudioOnly, sizeof(bifsAudioOnly)); + + } else if (hasVideo) { + *pNumBytes = sizeof(bifsVideoOnly); + *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes); + memcpy(*ppBytes, bifsVideoOnly, sizeof(bifsVideoOnly)); + } else { + *pNumBytes = 0; + *ppBytes = NULL; + } +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/libmp4v260.dsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/libmp4v260.dsp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,401 @@ +# Microsoft Developer Studio Project File - Name="libmp4v2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libmp4v2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libmp4v260.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libmp4v260.mak" CFG="libmp4v2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libmp4v2 - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libmp4v2 - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libmp4v2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libmp4v2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libmp4v2 - Win32 Release" +# Name "libmp4v2 - Win32 Debug" +# Begin Group "source" + +# PROP Default_Filter ".c, .cpp" +# Begin Source File + +SOURCE=.\3gp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_amr.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_avc1.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_avcC.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_d263.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_damr.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_dref.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_elst.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_enca.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_encv.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_free.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_ftyp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_hdlr.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_hinf.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_hnti.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_href.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mdat.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mdhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_meta.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mp4a.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mp4s.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mp4v.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mvhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_root.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_rtp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_s263.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_sdp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_smi.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_sound.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_standard.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stbl.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stdp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stsc.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stsd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stsz.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_tfhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_tkhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_treftype.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_trun.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_udta.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_url.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_urn.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_video.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_vmhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\descriptors.cpp +# End Source File +# Begin Source File + +SOURCE=.\isma.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4atom.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4container.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4descriptor.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4file.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4file_io.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4info.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4meta.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4property.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4track.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4util.cpp +# End Source File +# Begin Source File + +SOURCE=.\ocidescriptors.cpp +# End Source File +# Begin Source File + +SOURCE=.\odcommands.cpp +# End Source File +# Begin Source File + +SOURCE=.\qosqualifiers.cpp +# End Source File +# Begin Source File + +SOURCE=.\rtphint.cpp +# End Source File +# End Group +# Begin Group "include" + +# PROP Default_Filter ".h" +# Begin Source File + +SOURCE=.\atoms.h +# End Source File +# Begin Source File + +SOURCE=.\descriptors.h +# End Source File +# Begin Source File + +SOURCE=.\mp4.h +# End Source File +# Begin Source File + +SOURCE=.\mp4array.h +# End Source File +# Begin Source File + +SOURCE=.\mp4atom.h +# End Source File +# Begin Source File + +SOURCE=.\mp4common.h +# End Source File +# Begin Source File + +SOURCE=.\mp4container.h +# End Source File +# Begin Source File + +SOURCE=.\mp4descriptor.h +# End Source File +# Begin Source File + +SOURCE=.\mp4file.h +# End Source File +# Begin Source File + +SOURCE=.\mp4property.h +# End Source File +# Begin Source File + +SOURCE=.\mp4track.h +# End Source File +# Begin Source File + +SOURCE=.\mp4util.h +# End Source File +# Begin Source File + +SOURCE=.\ocidescriptors.h +# End Source File +# Begin Source File + +SOURCE=.\odcommands.h +# End Source File +# Begin Source File + +SOURCE=.\qosqualifiers.h +# End Source File +# Begin Source File + +SOURCE=.\rtphint.h +# End Source File +# End Group +# End Target +# End Project diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/libmp4v2_st60.dsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/libmp4v2_st60.dsp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,400 @@ +# Microsoft Developer Studio Project File - Name="libmp4v2_st" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libmp4v2_st - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libmp4v2_st60.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libmp4v2_st60.mak" CFG="libmp4v2_st - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libmp4v2_st - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libmp4v2_st - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libmp4v2_st - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ST_Release" +# PROP Intermediate_Dir "ST_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libmp4v2_st - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "ST_Debug" +# PROP Intermediate_Dir "ST_Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libmp4v2_st - Win32 Release" +# Name "libmp4v2_st - Win32 Debug" +# Begin Group "source" + +# PROP Default_Filter ".c, .cpp" +# Begin Source File + +SOURCE=.\3gp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_amr.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_avc1.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_avcC.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_d263.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_damr.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_dref.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_elst.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_enca.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_encv.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_free.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_ftyp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_hdlr.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_hinf.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_hnti.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_href.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mdat.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mdhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_meta.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mp4a.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mp4s.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mp4v.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_mvhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_root.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_rtp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_s263.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_sdp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_smi.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_sound.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_standard.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stbl.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stdp.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stsc.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stsd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_stsz.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_tfhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_tkhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_treftype.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_trun.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_udta.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_url.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_urn.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_video.cpp +# End Source File +# Begin Source File + +SOURCE=.\atom_vmhd.cpp +# End Source File +# Begin Source File + +SOURCE=.\descriptors.cpp +# End Source File +# Begin Source File + +SOURCE=.\isma.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4atom.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4container.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4descriptor.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4file.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4file_io.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4info.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4meta.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4property.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4track.cpp +# End Source File +# Begin Source File + +SOURCE=.\mp4util.cpp +# End Source File +# Begin Source File + +SOURCE=.\ocidescriptors.cpp +# End Source File +# Begin Source File + +SOURCE=.\odcommands.cpp +# End Source File +# Begin Source File + +SOURCE=.\qosqualifiers.cpp +# End Source File +# Begin Source File + +SOURCE=.\rtphint.cpp +# End Source File +# End Group +# Begin Group "include" + +# PROP Default_Filter ".h" +# Begin Source File + +SOURCE=.\atoms.h +# End Source File +# Begin Source File + +SOURCE=.\descriptors.h +# End Source File +# Begin Source File + +SOURCE=.\mp4.h +# End Source File +# Begin Source File + +SOURCE=.\mp4array.h +# End Source File +# Begin Source File + +SOURCE=.\mp4atom.h +# End Source File +# Begin Source File + +SOURCE=.\mp4common.h +# End Source File +# Begin Source File + +SOURCE=.\mp4container.h +# End Source File +# Begin Source File + +SOURCE=.\mp4descriptor.h +# End Source File +# Begin Source File + +SOURCE=.\mp4file.h +# End Source File +# Begin Source File + +SOURCE=.\mp4property.h +# End Source File +# Begin Source File + +SOURCE=.\mp4track.h +# End Source File +# Begin Source File + +SOURCE=.\mp4util.h +# End Source File +# Begin Source File + +SOURCE=.\ocidescriptors.h +# End Source File +# Begin Source File + +SOURCE=.\odcommands.h +# End Source File +# Begin Source File + +SOURCE=.\qosqualifiers.h +# End Source File +# Begin Source File + +SOURCE=.\rtphint.h +# End Source File +# End Group +# End Target +# End Project diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,3963 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + * Bill May wmay@cisco.com + */ + +/* + * MP4 library API functions + * + * These are wrapper functions that provide C linkage conventions + * to the library, and catch any internal errors, ensuring that + * a proper return value is given. + */ + +#include "mp4common.h" + +#define PRINT_ERROR(e) \ + VERBOSE_ERROR(((MP4File*)hFile)->GetVerbosity(), e->Print()); + +/* file operations */ + +extern "C" MP4FileHandle MP4Read(const char* fileName, u_int32_t verbosity) +{ + MP4File* pFile = NULL; + try { + pFile = new MP4File(verbosity); + pFile->Read(fileName); + return (MP4FileHandle)pFile; + } + catch (MP4Error* e) { + VERBOSE_ERROR(verbosity, e->Print()); + delete e; + delete pFile; + return MP4_INVALID_FILE_HANDLE; + } +} + +extern "C" MP4FileHandle MP4Create (const char* fileName, + u_int32_t verbosity, + u_int32_t flags) +{ + return MP4CreateEx(fileName, verbosity, flags); +} + +extern "C" MP4FileHandle MP4CreateEx (const char* fileName, + u_int32_t verbosity, + u_int32_t flags, + int add_ftyp, + int add_iods, + char* majorBrand, + u_int32_t minorVersion, + char** supportedBrands, + u_int32_t supportedBrandsCount) +{ + MP4File* pFile = NULL; + try { + pFile = new MP4File(verbosity); + // LATER useExtensibleFormat, moov first, then mvex's + pFile->Create(fileName, flags, add_ftyp, add_iods, + majorBrand, minorVersion, + supportedBrands, supportedBrandsCount); + return (MP4FileHandle)pFile; + } + catch (MP4Error* e) { + VERBOSE_ERROR(verbosity, e->Print()); + delete e; + delete pFile; + return MP4_INVALID_FILE_HANDLE; + } +} + +extern "C" MP4FileHandle MP4Modify(const char* fileName, + u_int32_t verbosity, u_int32_t flags) +{ + MP4File* pFile = NULL; + try { + pFile = new MP4File(verbosity); + // LATER useExtensibleFormat, moov first, then mvex's + pFile->Modify(fileName); + return (MP4FileHandle)pFile; + } + catch (MP4Error* e) { + VERBOSE_ERROR(verbosity, e->Print()); + delete e; + delete pFile; + return MP4_INVALID_FILE_HANDLE; + } +} + +extern "C" bool MP4Optimize(const char* existingFileName, + const char* newFileName, + u_int32_t verbosity) +{ + try { + MP4File* pFile = new MP4File(verbosity); + pFile->Optimize(existingFileName, newFileName); + delete pFile; + return true; + } + catch (MP4Error* e) { + VERBOSE_ERROR(verbosity, e->Print()); + delete e; + } + return false; +} + +extern "C" bool MP4Close(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->Close(); + delete (MP4File*)hFile; + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4Dump( + MP4FileHandle hFile, + FILE* pDumpFile, + bool dumpImplicits) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->Dump(pDumpFile, dumpImplicits); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + + +/* specific file properties */ + +extern "C" u_int32_t MP4GetVerbosity(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetVerbosity(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetVerbosity(verbosity); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" MP4Duration MP4GetDuration(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetDuration(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" u_int32_t MP4GetTimeScale(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTimeScale(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetTimeScale(MP4FileHandle hFile, u_int32_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTimeScale(value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int8_t MP4GetODProfileLevel(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetODProfileLevel(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetODProfileLevel(MP4FileHandle hFile, u_int8_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetODProfileLevel(value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int8_t MP4GetSceneProfileLevel(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSceneProfileLevel(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetSceneProfileLevel(MP4FileHandle hFile, u_int8_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetSceneProfileLevel(value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetVideoProfileLevel(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetVideoProfileLevel(value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetAudioProfileLevel(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetAudioProfileLevel(value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetGraphicsProfileLevel(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, u_int8_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetGraphicsProfileLevel(value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +/* generic file properties */ + +extern "C" u_int64_t MP4GetIntegerProperty( + MP4FileHandle hFile, const char* propName) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetIntegerProperty(propName); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return (u_int64_t)-1; +} + +extern "C" float MP4GetFloatProperty( + MP4FileHandle hFile, const char* propName) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetFloatProperty(propName); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NAN; +} + +extern "C" const char* MP4GetStringProperty( + MP4FileHandle hFile, const char* propName) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetStringProperty(propName); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NULL; +} + +extern "C" void MP4GetBytesProperty( + MP4FileHandle hFile, const char* propName, + u_int8_t** ppValue, u_int32_t* pValueSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetBytesProperty(propName, ppValue, pValueSize); + return; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + *ppValue = NULL; + *pValueSize = 0; + return; +} + +extern "C" bool MP4SetIntegerProperty( + MP4FileHandle hFile, const char* propName, int64_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetIntegerProperty(propName, value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetFloatProperty( + MP4FileHandle hFile, const char* propName, float value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetFloatProperty(propName, value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetStringProperty( + MP4FileHandle hFile, const char* propName, const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetStringProperty(propName, value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetBytesProperty( + MP4FileHandle hFile, const char* propName, + const u_int8_t* pValue, u_int32_t valueSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetBytesProperty(propName, pValue, valueSize); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +/* track operations */ + +extern "C" MP4TrackId MP4AddTrack( + MP4FileHandle hFile, const char* type) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->AddSystemsTrack(type); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddSystemsTrack( + MP4FileHandle hFile, const char* type) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->AddSystemsTrack(type); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddODTrack(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->AddODTrack(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddSceneTrack(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->AddSceneTrack(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int8_t audioType) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + AddAudioTrack(timeScale, sampleDuration, audioType); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddEncAudioTrack(MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + mp4v2_ismacrypParams *icPp, + u_int8_t audioType + ) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + AddEncAudioTrack(timeScale, sampleDuration, audioType, + icPp->scheme_type, icPp->scheme_version, + icPp->key_ind_len, icPp->iv_len, + icPp->selective_enc, icPp->kms_uri); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} +extern "C" MP4TrackId MP4AddAmrAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + u_int16_t modeSet, + u_int8_t modeChangePeriod, + u_int8_t framesPerSample, + bool isAmrWB) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + AddAmrAudioTrack(timeScale, modeSet, modeChangePeriod, framesPerSample, isAmrWB); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" void MP4SetAmrVendor( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t vendor) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)-> + SetAmrVendor(trackId, vendor); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } +} + +extern "C" void MP4SetAmrDecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t decoderVersion) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)-> + SetAmrDecoderVersion(trackId, decoderVersion); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } +} + +extern "C" void MP4SetAmrModeSet( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int16_t modeSet) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)-> + SetAmrModeSet(trackId, modeSet); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } +} + +extern "C" uint16_t MP4GetAmrModeSet( + MP4FileHandle hFile, + MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + GetAmrModeSet(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" MP4TrackId MP4AddHrefTrack (MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + MP4File *pFile = (MP4File *)hFile; + + return pFile->AddHrefTrack(timeScale, + sampleDuration); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddVideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t videoType) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + MP4File *pFile = (MP4File *)hFile; + + return pFile->AddMP4VideoTrack(timeScale, + sampleDuration, + width, + height, + videoType); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddEncVideoTrack(MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + mp4v2_ismacrypParams *icPp, + u_int8_t videoType ) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->AddEncVideoTrack(timeScale, sampleDuration, + width, height, videoType, + icPp->scheme_type, icPp->scheme_version, + icPp->key_ind_len, icPp->iv_len, + icPp->selective_enc, icPp->kms_uri); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4AddH264VideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + uint8_t AVCProfileIndication, + uint8_t profile_compat, + uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + MP4File *pFile = (MP4File *)hFile; + + return pFile->AddH264VideoTrack(timeScale, + sampleDuration, + width, + height, + AVCProfileIndication, + profile_compat, + AVCLevelIndication, + sampleLenFieldSizeMinusOne); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" bool MP4AddH264SequenceParameterSet (MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + MP4File *pFile = (MP4File *)hFile; + + return pFile->AddH264SequenceParameterSet(trackId, + pSequence, + sequenceLen); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} +extern "C" bool MP4AddH264PictureParameterSet (MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pPict, + uint16_t pictLen) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + MP4File *pFile = (MP4File *)hFile; + + return pFile->AddH264PictureParameterSet(trackId, + pPict, + pictLen); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" MP4TrackId MP4AddH263VideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t h263Level, + u_int8_t h263Profile, + u_int32_t avgBitrate, + u_int32_t maxBitrate) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + AddH263VideoTrack(timeScale, sampleDuration, width, height, h263Level, h263Profile, avgBitrate, maxBitrate); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + + return MP4_INVALID_TRACK_ID; +} + +extern "C" void MP4SetH263Vendor( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t vendor) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)-> + SetH263Vendor(trackId, vendor); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } +} + +extern "C" void MP4SetH263DecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t decoderVersion) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + + try { + ((MP4File*)hFile)-> + SetH263DecoderVersion(trackId, decoderVersion); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } +} + +extern "C" void MP4SetH263Bitrates( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t avgBitrate, + u_int32_t maxBitrate) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + + try { + ((MP4File*)hFile)-> + SetH263Bitrates(trackId, avgBitrate, maxBitrate); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } +} + +extern "C" MP4TrackId MP4AddHintTrack( + MP4FileHandle hFile, MP4TrackId refTrackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->AddHintTrack(refTrackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" MP4TrackId MP4CloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile, + MP4TrackId dstHintTrackReferenceTrack) +{ + MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID; + + if (dstFile == NULL) { + dstFile = srcFile; + } + + const char* trackType = + MP4GetTrackType(srcFile, srcTrackId); + + if (!trackType) { + return dstTrackId; + } + + if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) { + MP4SetVideoProfileLevel(dstFile, + MP4GetVideoProfileLevel(srcFile)); + dstTrackId = MP4AddVideoTrack( + dstFile, + MP4GetTrackTimeScale(srcFile, srcTrackId), + MP4GetTrackFixedSampleDuration(srcFile, srcTrackId), + MP4GetTrackVideoWidth(srcFile, srcTrackId), + MP4GetTrackVideoHeight(srcFile, srcTrackId), + MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId)); + + } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) { + MP4SetAudioProfileLevel(dstFile, + MP4GetAudioProfileLevel(srcFile)); + dstTrackId = MP4AddAudioTrack( + dstFile, + MP4GetTrackTimeScale(srcFile, srcTrackId), + MP4GetTrackFixedSampleDuration(srcFile, srcTrackId), + MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId)); + + } else if (MP4_IS_OD_TRACK_TYPE(trackType)) { + dstTrackId = MP4AddODTrack(dstFile); + + } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) { + dstTrackId = MP4AddSceneTrack(dstFile); + + } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) { + if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) { + dstTrackId = MP4_INVALID_TRACK_ID; + } else { + dstTrackId = MP4AddHintTrack( + dstFile, + dstHintTrackReferenceTrack); + } + + } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) { + dstTrackId = MP4AddSystemsTrack(dstFile, trackType); + + } else { + dstTrackId = MP4AddTrack(dstFile, trackType); + } + + if (dstTrackId == MP4_INVALID_TRACK_ID) { + return dstTrackId; + } + + MP4SetTrackTimeScale( + dstFile, + dstTrackId, + MP4GetTrackTimeScale(srcFile, srcTrackId)); + + if (MP4_IS_AUDIO_TRACK_TYPE(trackType) + || MP4_IS_VIDEO_TRACK_TYPE(trackType)) { + // copy track ES configuration + u_int8_t* pConfig = NULL; + u_int32_t configSize = 0; + + MP4GetTrackESConfiguration( + srcFile, + srcTrackId, + &pConfig, + &configSize); + + MP4SetTrackESConfiguration( + dstFile, + dstTrackId, + pConfig, + configSize); + + free(pConfig); + } + + if (MP4_IS_HINT_TRACK_TYPE(trackType)) { + // probably not exactly what is wanted + // but caller can adjust later to fit their desires + + char* payloadName = NULL; + char *encodingParms = NULL; + u_int8_t payloadNumber; + u_int16_t maxPayloadSize; + + MP4GetHintTrackRtpPayload( + srcFile, + srcTrackId, + &payloadName, + &payloadNumber, + &maxPayloadSize, + &encodingParms); + + MP4SetHintTrackRtpPayload( + dstFile, + dstTrackId, + payloadName, + &payloadNumber, + maxPayloadSize, + encodingParms); +#if 0 + MP4SetHintTrackSdp( + dstFile, + dstTrackId, + MP4GetHintTrackSdp(srcFile, srcTrackId)); +#endif + } + + return dstTrackId; +} + +// Given a track, make an encrypted clone of it in the dest. file +extern "C" MP4TrackId MP4EncAndCloneTrack(MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams *icPp, + MP4FileHandle dstFile, + MP4TrackId dstHintTrackReferenceTrack + ) +{ + MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID; + + if (dstFile == NULL) { + dstFile = srcFile; + } + + const char* trackType = + MP4GetTrackType(srcFile, srcTrackId); + + if (!trackType) { + return dstTrackId; + } + + if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) { + MP4SetVideoProfileLevel(dstFile, MP4GetVideoProfileLevel(srcFile)); + dstTrackId = MP4AddEncVideoTrack(dstFile, + MP4GetTrackTimeScale(srcFile, srcTrackId), + MP4GetTrackFixedSampleDuration(srcFile, + srcTrackId), + MP4GetTrackVideoWidth(srcFile, srcTrackId), + MP4GetTrackVideoHeight(srcFile, srcTrackId), + icPp, + MP4GetTrackEsdsObjectTypeId(srcFile, + srcTrackId) + ); + + } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) { + MP4SetAudioProfileLevel(dstFile, MP4GetAudioProfileLevel(srcFile)); + dstTrackId = MP4AddEncAudioTrack(dstFile, + MP4GetTrackTimeScale(srcFile, srcTrackId), + MP4GetTrackFixedSampleDuration(srcFile, + srcTrackId), + icPp, + MP4GetTrackEsdsObjectTypeId(srcFile, + srcTrackId) + ); + + } else if (MP4_IS_OD_TRACK_TYPE(trackType)) { + dstTrackId = MP4AddODTrack(dstFile); + + } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) { + dstTrackId = MP4AddSceneTrack(dstFile); + + } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) { + if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) { + dstTrackId = MP4_INVALID_TRACK_ID; + } else { + dstTrackId = MP4AddHintTrack(dstFile, + MP4GetHintTrackReferenceTrackId(srcFile, + srcTrackId)); + } + } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) { + dstTrackId = MP4AddSystemsTrack(dstFile, trackType); + + } else { + dstTrackId = MP4AddTrack(dstFile, trackType); + } + + if (dstTrackId == MP4_INVALID_TRACK_ID) { + return dstTrackId; + } + + MP4SetTrackTimeScale(dstFile, + dstTrackId, + MP4GetTrackTimeScale(srcFile, srcTrackId)); + + if (MP4_IS_AUDIO_TRACK_TYPE(trackType) + || MP4_IS_VIDEO_TRACK_TYPE(trackType)) { + // copy track ES configuration + u_int8_t* pConfig = NULL; + u_int32_t configSize = 0; + if (MP4GetTrackESConfiguration(srcFile, srcTrackId, + &pConfig, &configSize)) { + + if (pConfig != NULL) { + MP4SetTrackESConfiguration(dstFile, dstTrackId, + pConfig, configSize); + } + } + if (pConfig != NULL) + free(pConfig); + } + + // Bill's change to MP4CloneTrack + if (MP4_IS_HINT_TRACK_TYPE(trackType)) { + // probably not exactly what is wanted + // but caller can adjust later to fit their desires + + char* payloadName = NULL; + char *encodingParms = NULL; + u_int8_t payloadNumber; + u_int16_t maxPayloadSize; + + MP4GetHintTrackRtpPayload( + srcFile, + srcTrackId, + &payloadName, + &payloadNumber, + &maxPayloadSize, + &encodingParms); + + MP4SetHintTrackRtpPayload( + dstFile, + dstTrackId, + payloadName, + &payloadNumber, + maxPayloadSize, + encodingParms); +#if 0 + MP4SetHintTrackSdp( + dstFile, + dstTrackId, + MP4GetHintTrackSdp(srcFile, srcTrackId)); +#endif + } + + return dstTrackId; +} +extern "C" MP4TrackId MP4CopyTrack(MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile, + bool applyEdits, + MP4TrackId dstHintTrackReferenceTrack) +{ + bool copySamples = true; // LATER allow false => reference samples + + MP4TrackId dstTrackId = + MP4CloneTrack(srcFile, srcTrackId, dstFile, dstHintTrackReferenceTrack); + + if (dstTrackId == MP4_INVALID_TRACK_ID) { + return dstTrackId; + } + + bool viaEdits = + applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId); + + MP4SampleId sampleId = 0; + MP4SampleId numSamples = + MP4GetTrackNumberOfSamples(srcFile, srcTrackId); + + MP4Timestamp when = 0; + MP4Duration editsDuration = + MP4GetTrackEditTotalDuration(srcFile, srcTrackId); + + while (true) { + MP4Duration sampleDuration = MP4_INVALID_DURATION; + + if (viaEdits) { + sampleId = MP4GetSampleIdFromEditTime( + srcFile, + srcTrackId, + when, + NULL, + &sampleDuration); + + // in theory, this shouldn't happen + if (sampleId == MP4_INVALID_SAMPLE_ID) { + MP4DeleteTrack(dstFile, dstTrackId); + return MP4_INVALID_TRACK_ID; + } + + when += sampleDuration; + + if (when >= editsDuration) { + break; + } + } else { + sampleId++; + if (sampleId > numSamples) { + break; + } + } + + bool rc = false; + + if (copySamples) { + rc = MP4CopySample( + srcFile, + srcTrackId, + sampleId, + dstFile, + dstTrackId, + sampleDuration); + + } else { + rc = MP4ReferenceSample( + srcFile, + srcTrackId, + sampleId, + dstFile, + dstTrackId, + sampleDuration); + } + + if (!rc) { + MP4DeleteTrack(dstFile, dstTrackId); + return MP4_INVALID_TRACK_ID; + } + } + + return dstTrackId; +} + +// Given a source track in a source file, make an encrypted copy of +// the track in the destination file, including sample encryption +extern "C" MP4TrackId MP4EncAndCopyTrack(MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams *icPp, + encryptFunc_t encfcnp, + u_int32_t encfcnparam1, + MP4FileHandle dstFile, + bool applyEdits, + MP4TrackId dstHintTrackReferenceTrack + ) +{ + bool copySamples = true; // LATER allow false => reference samples + + MP4TrackId dstTrackId = + MP4EncAndCloneTrack(srcFile, srcTrackId, + icPp, + dstFile, dstHintTrackReferenceTrack); + + if (dstTrackId == MP4_INVALID_TRACK_ID) { + return dstTrackId; + } + + bool viaEdits = + applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId); + + MP4SampleId sampleId = 0; + MP4SampleId numSamples = + MP4GetTrackNumberOfSamples(srcFile, srcTrackId); + + MP4Timestamp when = 0; + MP4Duration editsDuration = + MP4GetTrackEditTotalDuration(srcFile, srcTrackId); + + while (true) { + MP4Duration sampleDuration = MP4_INVALID_DURATION; + + if (viaEdits) { + sampleId = MP4GetSampleIdFromEditTime(srcFile, + srcTrackId, + when, + NULL, + &sampleDuration); + + // in theory, this shouldn't happen + if (sampleId == MP4_INVALID_SAMPLE_ID) { + MP4DeleteTrack(dstFile, dstTrackId); + return MP4_INVALID_TRACK_ID; + } + + when += sampleDuration; + + if (when >= editsDuration) { + break; + } + } else { + sampleId++; + if (sampleId > numSamples) { + break; + } + } + + bool rc = false; + + if (copySamples) { + // encrypt and copy + rc = MP4EncAndCopySample(srcFile, + srcTrackId, + sampleId, + encfcnp, + encfcnparam1, + dstFile, + dstTrackId, + sampleDuration); + + } else { + // not sure what these are - encrypt? + rc = MP4ReferenceSample(srcFile, + srcTrackId, + sampleId, + dstFile, + dstTrackId, + sampleDuration); + } + + if (!rc) { + MP4DeleteTrack(dstFile, dstTrackId); + return MP4_INVALID_TRACK_ID; + } + } + + return dstTrackId; +} + +extern "C" bool MP4DeleteTrack( + MP4FileHandle hFile, + MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->DeleteTrack(trackId); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int32_t MP4GetNumberOfTracks( + MP4FileHandle hFile, + const char* type, + u_int8_t subType) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetNumberOfTracks(type, subType); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" MP4TrackId MP4FindTrackId( + MP4FileHandle hFile, + u_int16_t index, + const char* type, + u_int8_t subType) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->FindTrackId(index, type, subType); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" u_int16_t MP4FindTrackIndex( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->FindTrackIndex(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return (u_int16_t)-1; +} + +/* specific track properties */ + +extern "C" const char* MP4GetTrackType( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackType(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NULL; +} +extern "C" const char* MP4GetTrackMediaDataName( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackMediaDataName(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NULL; +} + + +extern "C" MP4Duration MP4GetTrackDuration( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackDuration(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" u_int32_t MP4GetTrackTimeScale( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackTimeScale(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4SetTrackTimeScale( + MP4FileHandle hFile, MP4TrackId trackId, u_int32_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackTimeScale(trackId, value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int8_t MP4GetTrackAudioMpeg4Type( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackAudioMpeg4Type(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_MPEG4_INVALID_AUDIO_TYPE; +} + + + +// Replacement to MP4GetTrackVideoType and MP4GetTrackAudioType +// Basically does the same thing but with a more self-explanatory name +extern "C" u_int8_t MP4GetTrackEsdsObjectTypeId( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + + return ((MP4File*)hFile)->GetTrackEsdsObjectTypeId(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_AUDIO_TYPE; +} + +extern "C" MP4Duration MP4GetTrackFixedSampleDuration( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackFixedSampleDuration(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" u_int32_t MP4GetTrackBitRate( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + MP4File *pFile = (MP4File *)hFile; + try { + return pFile->GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate"); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + // if we're here, we can't get the bitrate from above - + // lets calculate it + try { + MP4Duration trackDur; + trackDur = MP4GetTrackDuration(hFile, trackId); + uint64_t msDuration = + pFile->ConvertFromTrackDuration(trackId, trackDur, + MP4_MSECS_TIME_SCALE); + MP4Track *pTrack = pFile->GetTrack(trackId); + uint64_t bytes = pTrack->GetTotalOfSampleSizes(); + bytes *= (u_int64_t) (8 * 1000); + bytes /= msDuration; + return (uint32_t)bytes; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + + } + return 0; +} + +extern "C" bool MP4GetTrackESConfiguration( + MP4FileHandle hFile, MP4TrackId trackId, + u_int8_t** ppConfig, u_int32_t* pConfigSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetTrackESConfiguration( + trackId, ppConfig, pConfigSize); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + *ppConfig = NULL; + *pConfigSize = 0; + return false; +} +extern "C" bool MP4GetTrackVideoMetadata( + MP4FileHandle hFile, MP4TrackId trackId, + u_int8_t** ppConfig, u_int32_t* pConfigSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetTrackVideoMetadata( + trackId, ppConfig, pConfigSize); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + *ppConfig = NULL; + *pConfigSize = 0; + return false; +} + +extern "C" bool MP4SetTrackESConfiguration( + MP4FileHandle hFile, MP4TrackId trackId, + const u_int8_t* pConfig, u_int32_t configSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackESConfiguration( + trackId, pConfig, configSize); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetTrackH264ProfileLevel (MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t *pProfile, + uint8_t *pLevel) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetTrackH264ProfileLevel(trackId, pProfile, pLevel); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} +extern "C" bool MP4GetTrackH264SeqPictHeaders (MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t ***pSeqHeader, + uint32_t **pSeqHeaderSize, + uint8_t ***pPictHeader, + uint32_t **pPictHeaderSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetTrackH264SeqPictHeaders(trackId, + pSeqHeader, + pSeqHeaderSize, + pPictHeader, + pPictHeaderSize); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} +extern "C" bool MP4GetTrackH264LengthSize (MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t *pLength) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetTrackH264LengthSize(trackId, + pLength); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" MP4SampleId MP4GetTrackNumberOfSamples( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackNumberOfSamples(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" u_int16_t MP4GetTrackVideoWidth( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.width"); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" u_int16_t MP4GetTrackVideoHeight( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.height"); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" double MP4GetTrackVideoFrameRate( + MP4FileHandle hFile, MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackVideoFrameRate(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0.0; +} + +extern "C" int MP4GetTrackAudioChannels (MP4FileHandle hFile, + MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackAudioChannels(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return -1; +} + +// returns true if the track is a media track encrypted according to ismacryp +extern "C" bool MP4IsIsmaCrypMediaTrack( + MP4FileHandle hFile, MP4TrackId trackId) +{ + bool retval = false; + uint32_t verb = MP4GetVerbosity(hFile); + MP4SetVerbosity(hFile, verb & ~(MP4_DETAILS_ERROR)); + + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + retval = ((MP4File*)hFile)->IsIsmaCrypMediaTrack(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + MP4SetVerbosity(hFile, verb); + return retval; +} + + +/* generic track properties */ + +extern "C" u_int64_t MP4GetTrackIntegerProperty ( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, + propName); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return (u_int64_t)-1; +} +extern "C" bool MP4HaveTrackIntegerProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName) +{ + // The same as MP4GetTrackIntegerProperty but with no error reporting + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, + propName) != (u_int64_t)-1; + } + catch (MP4Error* e) { + // No error reporting + delete e; + } + } + return false; +} + +extern "C" float MP4GetTrackFloatProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackFloatProperty(trackId, propName); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NAN; +} + +extern "C" const char* MP4GetTrackStringProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackStringProperty(trackId, propName); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NULL; +} + +extern "C" void MP4GetTrackBytesProperty( + MP4FileHandle hFile, MP4TrackId trackId, const char* propName, + u_int8_t** ppValue, u_int32_t* pValueSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetTrackBytesProperty( + trackId, propName, ppValue, pValueSize); + return; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + *ppValue = NULL; + *pValueSize = 0; + return; +} + +extern "C" bool MP4SetTrackIntegerProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName, int64_t value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackIntegerProperty(trackId, + propName, value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetTrackFloatProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName, float value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackFloatProperty(trackId, propName, value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetTrackStringProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName, const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackStringProperty(trackId, propName, value); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetTrackBytesProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName, const u_int8_t* pValue, u_int32_t valueSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackBytesProperty( + trackId, propName, pValue, valueSize); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +/* sample operations */ + +extern "C" bool MP4ReadSample( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + /* output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + MP4Timestamp* pStartTime, + MP4Duration* pDuration, + MP4Duration* pRenderingOffset, + bool* pIsSyncSample) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->ReadSample( + trackId, + sampleId, + ppBytes, + pNumBytes, + pStartTime, + pDuration, + pRenderingOffset, + pIsSyncSample); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + *pNumBytes = 0; + return false; +} + +extern "C" bool MP4ReadSampleFromTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + MP4Timestamp* pStartTime, + MP4Duration* pDuration, + MP4Duration* pRenderingOffset, + bool* pIsSyncSample) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + MP4SampleId sampleId = + ((MP4File*)hFile)->GetSampleIdFromTime( + trackId, when, false); + + ((MP4File*)hFile)->ReadSample( + trackId, + sampleId, + ppBytes, + pNumBytes, + pStartTime, + pDuration, + pRenderingOffset, + pIsSyncSample); + + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + *pNumBytes = 0; + return false; +} + +extern "C" bool MP4WriteSample( + MP4FileHandle hFile, + MP4TrackId trackId, + const u_int8_t* pBytes, + u_int32_t numBytes, + MP4Duration duration, + MP4Duration renderingOffset, + bool isSyncSample) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->WriteSample( + trackId, + pBytes, + numBytes, + duration, + renderingOffset, + isSyncSample); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4CopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile, + MP4TrackId dstTrackId, + MP4Duration dstSampleDuration) +{ + bool rc; + u_int8_t* pBytes = NULL; + u_int32_t numBytes = 0; + MP4Duration sampleDuration; + MP4Duration renderingOffset; + bool isSyncSample; + + // Note: we leave it up to the caller to ensure that the + // source and destination tracks are compatible. + // i.e. copying audio samples into a video track + // is unlikely to do anything useful + + rc = MP4ReadSample( + srcFile, + srcTrackId, + srcSampleId, + &pBytes, + &numBytes, + NULL, + &sampleDuration, + &renderingOffset, + &isSyncSample); + + if (!rc) { + return false; + } + + if (dstFile == MP4_INVALID_FILE_HANDLE) { + dstFile = srcFile; + } + if (dstTrackId == MP4_INVALID_TRACK_ID) { + dstTrackId = srcTrackId; + } + if (dstSampleDuration != MP4_INVALID_DURATION) { + sampleDuration = dstSampleDuration; + } + + rc = MP4WriteSample( + dstFile, + dstTrackId, + pBytes, + numBytes, + sampleDuration, + renderingOffset, + isSyncSample); + + free(pBytes); + + return rc; +} + +extern "C" bool MP4EncAndCopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + encryptFunc_t encfcnp, + u_int32_t encfcnparam1, + MP4FileHandle dstFile, + MP4TrackId dstTrackId, + MP4Duration dstSampleDuration) +{ + bool rc; + u_int8_t* pBytes = NULL; + u_int32_t numBytes = 0; + u_int8_t* encSampleData = NULL; + u_int32_t encSampleLength = 0; + MP4Duration sampleDuration; + MP4Duration renderingOffset; + bool isSyncSample; + + // Note: we leave it up to the caller to ensure that the + // source and destination tracks are compatible. + // i.e. copying audio samples into a video track + // is unlikely to do anything useful + + rc = MP4ReadSample( + srcFile, + srcTrackId, + srcSampleId, + &pBytes, + &numBytes, + NULL, + &sampleDuration, + &renderingOffset, + &isSyncSample); + + if (!rc) { + return false; + } + + if (dstFile == MP4_INVALID_FILE_HANDLE) { + dstFile = srcFile; + } + if (dstTrackId == MP4_INVALID_TRACK_ID) { + dstTrackId = srcTrackId; + } + if (dstSampleDuration != MP4_INVALID_DURATION) { + sampleDuration = dstSampleDuration; + } + + //if (ismacrypEncryptSampleAddHeader(ismaCryptSId, numBytes, pBytes, + // &encSampleLength, &encSampleData) != 0) { + if (encfcnp(encfcnparam1, numBytes, pBytes, + &encSampleLength, &encSampleData) != 0) { + fprintf(stderr, + "Can't encrypt the sample and add its header %u\n", + srcSampleId); + } + + rc = MP4WriteSample( + dstFile, + dstTrackId, + encSampleData, + encSampleLength, + sampleDuration, + renderingOffset, + isSyncSample); + + free(pBytes); + + if (encSampleData != NULL) { + free(encSampleData); + } + + return rc; +} + +extern "C" bool MP4ReferenceSample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile, + MP4TrackId dstTrackId, + MP4Duration dstSampleDuration) +{ + // LATER Not yet implemented + return false; +} + +extern "C" u_int32_t MP4GetSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSampleSize( + trackId, sampleId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" u_int32_t MP4GetTrackMaxSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackMaxSampleSize(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" MP4SampleId MP4GetSampleIdFromTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + bool wantSyncSample) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSampleIdFromTime( + trackId, when, wantSyncSample); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_SAMPLE_ID; +} + +extern "C" MP4Timestamp MP4GetSampleTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSampleTime( + trackId, sampleId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TIMESTAMP; +} + +extern "C" MP4Duration MP4GetSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSampleDuration( + trackId, sampleId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" MP4Duration MP4GetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSampleRenderingOffset( + trackId, sampleId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" bool MP4SetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + MP4Duration renderingOffset) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetSampleRenderingOffset( + trackId, sampleId, renderingOffset); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" int8_t MP4GetSampleSync( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSampleSync( + trackId, sampleId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return -1; +} + + +extern "C" u_int64_t MP4ConvertFromMovieDuration( + MP4FileHandle hFile, + MP4Duration duration, + u_int32_t timeScale) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->ConvertFromMovieDuration( + duration, timeScale); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return (u_int64_t)MP4_INVALID_DURATION; +} + +extern "C" u_int64_t MP4ConvertFromTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp timeStamp, + u_int32_t timeScale) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->ConvertFromTrackTimestamp( + trackId, timeStamp, timeScale); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return (u_int64_t)MP4_INVALID_TIMESTAMP; +} + +extern "C" MP4Timestamp MP4ConvertToTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int64_t timeStamp, + u_int32_t timeScale) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->ConvertToTrackTimestamp( + trackId, timeStamp, timeScale); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TIMESTAMP; +} + +extern "C" u_int64_t MP4ConvertFromTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration duration, + u_int32_t timeScale) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->ConvertFromTrackDuration( + trackId, duration, timeScale); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return (u_int64_t)MP4_INVALID_DURATION; +} + +extern "C" MP4Duration MP4ConvertToTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int64_t duration, + u_int32_t timeScale) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->ConvertToTrackDuration( + trackId, duration, timeScale); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" bool MP4GetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + char** ppPayloadName, + u_int8_t* pPayloadNumber, + u_int16_t* pMaxPayloadSize, + char **ppEncodingParams) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->GetHintTrackRtpPayload( + hintTrackId, ppPayloadName, pPayloadNumber, pMaxPayloadSize, + ppEncodingParams); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* pPayloadName, + u_int8_t* pPayloadNumber, + u_int16_t maxPayloadSize, + const char *encode_params, + bool include_rtp_map, + bool include_mpeg4_esid) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetHintTrackRtpPayload( + hintTrackId, pPayloadName, pPayloadNumber, maxPayloadSize, encode_params, + include_rtp_map, include_mpeg4_esid); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" const char* MP4GetSessionSdp( + MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSessionSdp(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NULL; +} + +extern "C" bool MP4SetSessionSdp( + MP4FileHandle hFile, + const char* sdpString) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetSessionSdp(sdpString); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4AppendSessionSdp( + MP4FileHandle hFile, + const char* sdpString) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->AppendSessionSdp(sdpString); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" const char* MP4GetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetHintTrackSdp(hintTrackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return NULL; +} + +extern "C" bool MP4SetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetHintTrackSdp(hintTrackId, sdpString); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4AppendHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->AppendHintTrackSdp(hintTrackId, sdpString); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" MP4TrackId MP4GetHintTrackReferenceTrackId( + MP4FileHandle hFile, + MP4TrackId hintTrackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + GetHintTrackReferenceTrackId(hintTrackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TRACK_ID; +} + +extern "C" bool MP4ReadRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId hintSampleId, + u_int16_t* pNumPackets) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->ReadRtpHint( + hintTrackId, hintSampleId, pNumPackets); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int16_t MP4GetRtpHintNumberOfPackets( + MP4FileHandle hFile, + MP4TrackId hintTrackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetRtpHintNumberOfPackets(hintTrackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" int8_t MP4GetRtpPacketBFrame( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + GetRtpPacketBFrame(hintTrackId, packetIndex); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return -1; +} + +extern "C" int32_t MP4GetRtpPacketTransmitOffset( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)-> + GetRtpPacketTransmitOffset(hintTrackId, packetIndex); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" bool MP4ReadRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + u_int32_t ssrc, + bool includeHeader, + bool includePayload) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->ReadRtpPacket( + hintTrackId, packetIndex, + ppBytes, pNumBytes, + ssrc, includeHeader, includePayload); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" MP4Timestamp MP4GetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetRtpTimestampStart(hintTrackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TIMESTAMP; +} + +extern "C" bool MP4SetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Timestamp rtpStart) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetRtpTimestampStart( + hintTrackId, rtpStart); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4AddRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId) +{ + return MP4AddRtpVideoHint(hFile, hintTrackId, false, 0); +} + +extern "C" bool MP4AddRtpVideoHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool isBframe, + u_int32_t timestampOffset) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->AddRtpHint(hintTrackId, + isBframe, timestampOffset); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4AddRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool setMbit, + int32_t transmitOffset) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->AddRtpPacket( + hintTrackId, setMbit, transmitOffset); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4AddRtpImmediateData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const u_int8_t* pBytes, + u_int32_t numBytes) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->AddRtpImmediateData(hintTrackId, + pBytes, numBytes); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4AddRtpSampleData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId sampleId, + u_int32_t dataOffset, + u_int32_t dataLength) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->AddRtpSampleData( + hintTrackId, sampleId, dataOffset, dataLength); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4AddRtpESConfigurationPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->AddRtpESConfigurationPacket(hintTrackId); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4WriteRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Duration duration, + bool isSyncSample) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->WriteRtpHint( + hintTrackId, duration, isSyncSample); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} +/* 3GPP specific operations */ + +extern "C" bool MP4Make3GPCompliant( + const char* fileName, + u_int32_t verbosity, + char* majorBrand, + u_int32_t minorVersion, + char** supportedBrands, + u_int32_t supportedBrandsCount, + bool deleteIodsAtom) +{ + MP4File* pFile = NULL; + + try { + pFile = new MP4File(verbosity); + pFile->Modify(fileName); + pFile->Make3GPCompliant(fileName, majorBrand, minorVersion, supportedBrands, supportedBrandsCount, deleteIodsAtom); + pFile->Close(); + delete pFile; + return true; + } + catch (MP4Error* e) { + VERBOSE_ERROR(verbosity, e->Print()); + delete e; + } + delete pFile; + return false; +} + +/* ISMA specific operations */ + +extern "C" bool MP4MakeIsmaCompliant( + const char* fileName, + u_int32_t verbosity, + bool addIsmaComplianceSdp) +{ + MP4File* pFile = NULL; + + try { + pFile = new MP4File(verbosity); + pFile->Modify(fileName); + pFile->MakeIsmaCompliant(addIsmaComplianceSdp); + pFile->Close(); + delete pFile; + return true; + } + catch (MP4Error* e) { + VERBOSE_ERROR(verbosity, e->Print()); + delete e; + } + delete pFile; + return false; +} + +extern "C" char* MP4MakeIsmaSdpIod( + u_int8_t videoProfile, + u_int32_t videoBitrate, + u_int8_t* videoConfig, + u_int32_t videoConfigLength, + u_int8_t audioProfile, + u_int32_t audioBitrate, + u_int8_t* audioConfig, + u_int32_t audioConfigLength, + u_int32_t verbosity) +{ + MP4File* pFile = NULL; + + try { + pFile = new MP4File(verbosity); + + u_int8_t* pBytes = NULL; + u_int64_t numBytes = 0; + + pFile->CreateIsmaIodFromParams( + videoProfile, + videoBitrate, + videoConfig, + videoConfigLength, + audioProfile, + audioBitrate, + audioConfig, + audioConfigLength, + &pBytes, + &numBytes); + + char* iodBase64 = + MP4ToBase64(pBytes, numBytes); + MP4Free(pBytes); + + char* sdpIod = + (char*)MP4Malloc(strlen(iodBase64) + 64); + sprintf(sdpIod, + "a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042", + iodBase64); + MP4Free(iodBase64); + + delete pFile; + + return sdpIod; + } + catch (MP4Error* e) { + VERBOSE_ERROR(verbosity, e->Print()); + delete e; + } + delete pFile; + return NULL; +} + +/* Edit list */ + +extern "C" MP4EditId MP4AddTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Timestamp startTime, + MP4Duration duration, + bool dwell) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + MP4EditId newEditId = + ((MP4File*)hFile)->AddTrackEdit(trackId, editId); + + if (newEditId != MP4_INVALID_EDIT_ID) { + ((MP4File*)hFile)->SetTrackEditMediaStart( + trackId, newEditId, startTime); + ((MP4File*)hFile)->SetTrackEditDuration( + trackId, newEditId, duration); + ((MP4File*)hFile)->SetTrackEditDwell( + trackId, newEditId, dwell); + } + + return newEditId; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_EDIT_ID; +} + +extern "C" bool MP4DeleteTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->DeleteTrackEdit(trackId, editId); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" u_int32_t MP4GetTrackNumberOfEdits( + MP4FileHandle hFile, + MP4TrackId trackId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackNumberOfEdits(trackId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return 0; +} + +extern "C" MP4Timestamp MP4GetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackEditMediaStart( + trackId, editId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_TIMESTAMP; +} + +extern "C" MP4Duration MP4GetTrackEditTotalDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackEditTotalDuration( + trackId, editId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" bool MP4SetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Timestamp startTime) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackEditMediaStart( + trackId, editId, startTime); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" MP4Duration MP4GetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackEditDuration(trackId, editId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_DURATION; +} + +extern "C" bool MP4SetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Duration duration) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackEditDuration(trackId, editId, duration); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" int8_t MP4GetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackEditDwell(trackId, editId); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return -1; +} + +extern "C" bool MP4SetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + bool dwell) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + ((MP4File*)hFile)->SetTrackEditDwell(trackId, editId, dwell); + return true; + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4ReadSampleFromEditTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + MP4Timestamp* pStartTime, + MP4Duration* pDuration, + MP4Duration* pRenderingOffset, + bool* pIsSyncSample) +{ + MP4SampleId sampleId = + MP4GetSampleIdFromEditTime( + hFile, + trackId, + when, + pStartTime, + pDuration); + + return MP4ReadSample( + hFile, + trackId, + sampleId, + ppBytes, + pNumBytes, + NULL, + NULL, + pRenderingOffset, + pIsSyncSample); +} + +extern "C" MP4SampleId MP4GetSampleIdFromEditTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + MP4Timestamp* pStartTime, + MP4Duration* pDuration) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetSampleIdFromEditTime( + trackId, when, pStartTime, pDuration); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return MP4_INVALID_SAMPLE_ID; +} + +/* Utlities */ + +extern "C" char* MP4BinaryToBase16( + const u_int8_t* pData, + u_int32_t dataSize) +{ + if (pData || dataSize == 0) { + try { + return MP4ToBase16(pData, dataSize); + } + catch (MP4Error* e) { + delete e; + } + } + return NULL; +} + +extern "C" char* MP4BinaryToBase64( + const u_int8_t* pData, + u_int32_t dataSize) +{ + if (pData || dataSize == 0) { + try { + return MP4ToBase64(pData, dataSize); + } + catch (MP4Error* e) { + delete e; + } + } + return NULL; +} + +/* iTunes meta data handling */ +extern "C" bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index, + const char** ppName, + u_int8_t** ppValue, u_int32_t* pValueSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataByIndex( + index, ppName, ppValue, pValueSize); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4MetadataDelete(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->MetadataDelete(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataName(MP4FileHandle hFile, + const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataName(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataName(MP4FileHandle hFile, + char** value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataName(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataName(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataName(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataWriter(MP4FileHandle hFile, + const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataWriter(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataWriter(MP4FileHandle hFile, + char** value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataWriter(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataWriter(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataWriter(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataAlbum(MP4FileHandle hFile, + const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataAlbum(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataAlbum(MP4FileHandle hFile, + char** value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataAlbum(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataAlbum(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataAlbum(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataArtist(MP4FileHandle hFile, + const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataArtist(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataArtist(MP4FileHandle hFile, + char** value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataArtist(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataArtist(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataArtist(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataTool(MP4FileHandle hFile, + const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataTool(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataTool(MP4FileHandle hFile, + char** value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataTool(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataTool(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataTool(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataComment(MP4FileHandle hFile, + const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataComment(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataComment(MP4FileHandle hFile, + char** value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataComment(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataComment(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataComment(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataYear(MP4FileHandle hFile, + const char* value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataYear(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataYear(MP4FileHandle hFile, + char** value) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataYear(value); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataYear(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataYear(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataTrack(MP4FileHandle hFile, + u_int16_t track, u_int16_t totalTracks) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataTrack(track, totalTracks); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataTrack(MP4FileHandle hFile, + u_int16_t* track, u_int16_t* totalTracks) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataTrack(track, totalTracks); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataTrack(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataTrack(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataDisk(MP4FileHandle hFile, + u_int16_t disk, u_int16_t totalDisks) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataDisk(disk, totalDisks); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataDisk(MP4FileHandle hFile, + u_int16_t* disk, u_int16_t* totalDisks) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataDisk(disk, totalDisks); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataDisk(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataDisk(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataGenre(genre); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataGenre(MP4FileHandle hFile, char **genre) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataGenre(genre); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataGenre(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataGenre(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataGrouping(MP4FileHandle hFile, const char *grouping) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataGrouping(grouping); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataGrouping(MP4FileHandle hFile, char **grouping) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataGrouping(grouping); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataGrouping(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataGrouping(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataTempo(tempo); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataTempo(tempo); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataTempo(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataTempo(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataCompilation(cpl); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataCompilation(cpl); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataCompilation(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataCompilation(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataCoverArt(MP4FileHandle hFile, + u_int8_t *coverArt, u_int32_t size) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataCoverArt(coverArt, size); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataCoverArt(MP4FileHandle hFile, + u_int8_t **coverArt, u_int32_t* size) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataCoverArt(coverArt, size); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataCoverArt(MP4FileHandle hFile) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataCoverArt(); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name, + u_int8_t* pValue, u_int32_t valueSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->SetMetadataFreeForm(name, pValue, valueSize); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name, + u_int8_t** pValue, u_int32_t* valueSize) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetMetadataFreeForm(name, pValue, valueSize); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + +extern "C" bool MP4DeleteMetadataFreeForm(MP4FileHandle hFile, char *name) +{ + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->DeleteMetadataFreeForm(name); + } + catch (MP4Error* e) { + PRINT_ERROR(e); + delete e; + } + } + return false; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,1212 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + * Bill May wmay@cisco.com + */ + +#ifndef __MP4_INCLUDED__ +#define __MP4_INCLUDED__ + +/* include system and project specific headers */ +#include "mpeg4ip.h" + +#include /* to define float HUGE_VAL and/or NAN */ +#ifndef NAN +#define NAN HUGE_VAL +#endif + +#define X64 "%llx" +#define U64 "%llu" +#define D64 "%lld" +#define UINT64_TO_DOUBLE (double) + +#ifdef __cplusplus +/* exploit C++ ability of default values for function parameters */ +#define DEFAULT(x) =x +#else +#define DEFAULT(x) +#endif + +/* MP4 API types */ +typedef void* MP4FileHandle; +typedef u_int32_t MP4TrackId; +typedef u_int32_t MP4SampleId; +typedef u_int64_t MP4Timestamp; +typedef u_int64_t MP4Duration; +typedef u_int32_t MP4EditId; + +/* Invalid values for API types */ +#define MP4_INVALID_FILE_HANDLE ((MP4FileHandle)NULL) +#define MP4_INVALID_TRACK_ID ((MP4TrackId)0) +#define MP4_INVALID_SAMPLE_ID ((MP4SampleId)0) +#define MP4_INVALID_TIMESTAMP ((MP4Timestamp)-1) +#define MP4_INVALID_DURATION ((MP4Duration)-1) +#define MP4_INVALID_EDIT_ID ((MP4EditId)0) + +/* Macros to test for API type validity */ +#define MP4_IS_VALID_FILE_HANDLE(x) ((x) != MP4_INVALID_FILE_HANDLE) +#define MP4_IS_VALID_TRACK_ID(x) ((x) != MP4_INVALID_TRACK_ID) +#define MP4_IS_VALID_SAMPLE_ID(x) ((x) != MP4_INVALID_SAMPLE_ID) +#define MP4_IS_VALID_TIMESTAMP(x) ((x) != MP4_INVALID_TIMESTAMP) +#define MP4_IS_VALID_DURATION(x) ((x) != MP4_INVALID_DURATION) +#define MP4_IS_VALID_EDIT_ID(x) ((x) != MP4_INVALID_EDIT_ID) + +/* MP4 verbosity levels - e.g. MP4SetVerbosity() */ +#define MP4_DETAILS_ALL 0xFFFFFFFF +#define MP4_DETAILS_ERROR 0x00000001 +#define MP4_DETAILS_WARNING 0x00000002 +#define MP4_DETAILS_READ 0x00000004 +#define MP4_DETAILS_WRITE 0x00000008 +#define MP4_DETAILS_FIND 0x00000010 +#define MP4_DETAILS_TABLE 0x00000020 +#define MP4_DETAILS_SAMPLE 0x00000040 +#define MP4_DETAILS_HINT 0x00000080 +#define MP4_DETAILS_ISMA 0x00000100 +#define MP4_DETAILS_EDIT 0x00000200 + +#define MP4_DETAILS_READ_ALL \ + (MP4_DETAILS_READ | MP4_DETAILS_TABLE | MP4_DETAILS_SAMPLE) +#define MP4_DETAILS_WRITE_ALL \ + (MP4_DETAILS_WRITE | MP4_DETAILS_TABLE | MP4_DETAILS_SAMPLE) + +/* + * MP4 Known track type names - e.g. MP4GetNumberOfTracks(type) + * + * Note this first group of track types should be created + * via the MP4AddTrack() functions, and not MP4AddTrack(type) + */ +#define MP4_OD_TRACK_TYPE "odsm" +#define MP4_SCENE_TRACK_TYPE "sdsm" +#define MP4_AUDIO_TRACK_TYPE "soun" +#define MP4_VIDEO_TRACK_TYPE "vide" +#define MP4_HINT_TRACK_TYPE "hint" +#define MP4_CNTL_TRACK_TYPE "cntl" +/* + * This second set of track types should be created + * via MP4AddSystemsTrack(type) + */ +#define MP4_CLOCK_TRACK_TYPE "crsm" +#define MP4_MPEG7_TRACK_TYPE "m7sm" +#define MP4_OCI_TRACK_TYPE "ocsm" +#define MP4_IPMP_TRACK_TYPE "ipsm" +#define MP4_MPEGJ_TRACK_TYPE "mjsm" + +#define MP4_IS_VIDEO_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_VIDEO_TRACK_TYPE)) + +#define MP4_IS_AUDIO_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_AUDIO_TRACK_TYPE)) + +#define MP4_IS_CNTL_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_CNTL_TRACK_TYPE)) + +#define MP4_IS_OD_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_OD_TRACK_TYPE)) + +#define MP4_IS_SCENE_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_SCENE_TRACK_TYPE)) + +#define MP4_IS_HINT_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_HINT_TRACK_TYPE)) + +#define MP4_IS_SYSTEMS_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_CLOCK_TRACK_TYPE) \ + || !strcasecmp(type, MP4_MPEG7_TRACK_TYPE) \ + || !strcasecmp(type, MP4_OCI_TRACK_TYPE) \ + || !strcasecmp(type, MP4_IPMP_TRACK_TYPE) \ + || !strcasecmp(type, MP4_MPEGJ_TRACK_TYPE)) + +/* MP4 Audio track types - see MP4AddAudioTrack()*/ +#define MP4_INVALID_AUDIO_TYPE 0x00 +#define MP4_MPEG1_AUDIO_TYPE 0x6B +#define MP4_MPEG2_AUDIO_TYPE 0x69 +#define MP4_MP3_AUDIO_TYPE MP4_MPEG2_AUDIO_TYPE +#define MP4_MPEG2_AAC_MAIN_AUDIO_TYPE 0x66 +#define MP4_MPEG2_AAC_LC_AUDIO_TYPE 0x67 +#define MP4_MPEG2_AAC_SSR_AUDIO_TYPE 0x68 +#define MP4_MPEG2_AAC_AUDIO_TYPE MP4_MPEG2_AAC_MAIN_AUDIO_TYPE +#define MP4_MPEG4_AUDIO_TYPE 0x40 +#define MP4_PRIVATE_AUDIO_TYPE 0xC0 +#define MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE 0xE0 /* a private definition */ +#define MP4_VORBIS_AUDIO_TYPE 0xE1 /* a private definition */ +#define MP4_AC3_AUDIO_TYPE 0xE2 /* a private definition */ +#define MP4_ALAW_AUDIO_TYPE 0xE3 /* a private definition */ +#define MP4_ULAW_AUDIO_TYPE 0xE4 /* a private definition */ +#define MP4_G723_AUDIO_TYPE 0xE5 /* a private definition */ +#define MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE 0xE6 /* a private definition */ + +/* MP4 MPEG-4 Audio types from 14496-3 Table 1.5.1 */ +#define MP4_MPEG4_INVALID_AUDIO_TYPE 0 +#define MP4_MPEG4_AAC_MAIN_AUDIO_TYPE 1 +#define MP4_MPEG4_AAC_LC_AUDIO_TYPE 2 +#define MP4_MPEG4_AAC_SSR_AUDIO_TYPE 3 +#define MP4_MPEG4_AAC_LTP_AUDIO_TYPE 4 +#define MP4_MPEG4_AAC_HE_AUDIO_TYPE 5 +#define MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE 6 +#define MP4_MPEG4_CELP_AUDIO_TYPE 8 +#define MP4_MPEG4_HVXC_AUDIO_TYPE 9 +#define MP4_MPEG4_TTSI_AUDIO_TYPE 12 +#define MP4_MPEG4_MAIN_SYNTHETIC_AUDIO_TYPE 13 +#define MP4_MPEG4_WAVETABLE_AUDIO_TYPE 14 +#define MP4_MPEG4_MIDI_AUDIO_TYPE 15 +#define MP4_MPEG4_ALGORITHMIC_FX_AUDIO_TYPE 16 + +/* MP4 Audio type utilities following common usage */ +#define MP4_IS_MP3_AUDIO_TYPE(type) \ + ((type) == MP4_MPEG1_AUDIO_TYPE || (type) == MP4_MPEG2_AUDIO_TYPE) + +#define MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \ + (((type) >= MP4_MPEG2_AAC_MAIN_AUDIO_TYPE \ + && (type) <= MP4_MPEG2_AAC_SSR_AUDIO_TYPE)) + +#define MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4Type) \ + (((mpeg4Type) >= MP4_MPEG4_AAC_MAIN_AUDIO_TYPE \ + && (mpeg4Type) <= MP4_MPEG4_AAC_HE_AUDIO_TYPE) \ + || (mpeg4Type) == MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE \ + || (mpeg4Type) == 17) + +#define MP4_IS_AAC_AUDIO_TYPE(type) \ + (MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \ + || (type) == MP4_MPEG4_AUDIO_TYPE) + +/* MP4 Video track types - see MP4AddVideoTrack() */ +#define MP4_INVALID_VIDEO_TYPE 0x00 +#define MP4_MPEG1_VIDEO_TYPE 0x6A +#define MP4_MPEG2_SIMPLE_VIDEO_TYPE 0x60 +#define MP4_MPEG2_MAIN_VIDEO_TYPE 0x61 +#define MP4_MPEG2_SNR_VIDEO_TYPE 0x62 +#define MP4_MPEG2_SPATIAL_VIDEO_TYPE 0x63 +#define MP4_MPEG2_HIGH_VIDEO_TYPE 0x64 +#define MP4_MPEG2_442_VIDEO_TYPE 0x65 +#define MP4_MPEG2_VIDEO_TYPE MP4_MPEG2_MAIN_VIDEO_TYPE +#define MP4_MPEG4_VIDEO_TYPE 0x20 +#define MP4_JPEG_VIDEO_TYPE 0x6C +#define MP4_PRIVATE_VIDEO_TYPE 0xD0 +#define MP4_YUV12_VIDEO_TYPE 0xF0 /* a private definition */ +#define MP4_H263_VIDEO_TYPE 0xF2 /* a private definition */ +#define MP4_H261_VIDEO_TYPE 0xF3 /* a private definition */ + +/* MP4 Video type utilities */ +#define MP4_IS_MPEG1_VIDEO_TYPE(type) \ + ((type) == MP4_MPEG1_VIDEO_TYPE) + +#define MP4_IS_MPEG2_VIDEO_TYPE(type) \ + (((type) >= MP4_MPEG2_SIMPLE_VIDEO_TYPE \ + && (type) <= MP4_MPEG2_442_VIDEO_TYPE) \ + || MP4_IS_MPEG1_VIDEO_TYPE(type)) + +#define MP4_IS_MPEG4_VIDEO_TYPE(type) \ + ((type) == MP4_MPEG4_VIDEO_TYPE) + +/* Mpeg4 Visual Profile Defines - ISO/IEC 14496-2:2001/Amd.2:2002(E) */ +#define MPEG4_SP_L1 (0x1) +#define MPEG4_SP_L2 (0x2) +#define MPEG4_SP_L3 (0x3) +#define MPEG4_SP_L0 (0x8) +#define MPEG4_SSP_L1 (0x11) +#define MPEG4_SSP_L2 (0x12) +#define MPEG4_CP_L1 (0x21) +#define MPEG4_CP_L2 (0x22) +#define MPEG4_MP_L2 (0x32) +#define MPEG4_MP_L3 (0x33) +#define MPEG4_MP_L4 (0x34) +#define MPEG4_NBP_L2 (0x42) +#define MPEG4_STP_L1 (0x51) +#define MPEG4_SFAP_L1 (0x61) +#define MPEG4_SFAP_L2 (0x62) +#define MPEG4_SFBAP_L1 (0x63) +#define MPEG4_SFBAP_L2 (0x64) +#define MPEG4_BATP_L1 (0x71) +#define MPEG4_BATP_L2 (0x72) +#define MPEG4_HP_L1 (0x81) +#define MPEG4_HP_L2 (0x82) +#define MPEG4_ARTSP_L1 (0x91) +#define MPEG4_ARTSP_L2 (0x92) +#define MPEG4_ARTSP_L3 (0x93) +#define MPEG4_ARTSP_L4 (0x94) +#define MPEG4_CSP_L1 (0xa1) +#define MPEG4_CSP_L2 (0xa2) +#define MPEG4_CSP_L3 (0xa3) +#define MPEG4_ACEP_L1 (0xb1) +#define MPEG4_ACEP_L2 (0xb2) +#define MPEG4_ACEP_L3 (0xb3) +#define MPEG4_ACEP_L4 (0xb4) +#define MPEG4_ACP_L1 (0xc1) +#define MPEG4_ACP_L2 (0xc2) +#define MPEG4_AST_L1 (0xd1) +#define MPEG4_AST_L2 (0xd2) +#define MPEG4_AST_L3 (0xd3) +#define MPEG4_S_STUDIO_P_L1 (0xe1) +#define MPEG4_S_STUDIO_P_L2 (0xe2) +#define MPEG4_S_STUDIO_P_L3 (0xe3) +#define MPEG4_S_STUDIO_P_L4 (0xe4) +#define MPEG4_C_STUDIO_P_L1 (0xe5) +#define MPEG4_C_STUDIO_P_L2 (0xe6) +#define MPEG4_C_STUDIO_P_L3 (0xe7) +#define MPEG4_C_STUDIO_P_L4 (0xe8) +#define MPEG4_ASP_L0 (0xF0) +#define MPEG4_ASP_L1 (0xF1) +#define MPEG4_ASP_L2 (0xF2) +#define MPEG4_ASP_L3 (0xF3) +#define MPEG4_ASP_L4 (0xF4) +#define MPEG4_ASP_L5 (0xF5) +#define MPEG4_ASP_L3B (0xF7) +#define MPEG4_FGSP_L0 (0xf8) +#define MPEG4_FGSP_L1 (0xf9) +#define MPEG4_FGSP_L2 (0xfa) +#define MPEG4_FGSP_L3 (0xfb) +#define MPEG4_FGSP_L4 (0xfc) +#define MPEG4_FGSP_L5 (0xfd) + +/* MP4 API declarations */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* file operations */ +#define MP4_CREATE_64BIT_DATA (0x01) +#define MP4_CREATE_64BIT_TIME (0x02) // Quicktime is not compatible with this +#define MP4_CREATE_64BIT (MP4_CREATE_64BIT_DATA | MP4_CREATE_64BIT_TIME) +#define MP4_CREATE_EXTENSIBLE_FORMAT (0x04) + +MP4FileHandle MP4Create( + const char* fileName, + u_int32_t verbosity DEFAULT(0), + u_int32_t flags DEFAULT(0)); +MP4FileHandle MP4CreateEx( + const char *fileName, + u_int32_t verbosity DEFAULT(0), + u_int32_t flags DEFAULT(0), + int add_ftyp DEFAULT(1), + int add_iods DEFAULT(1), + char* majorBrand DEFAULT(0), + u_int32_t minorVersion DEFAULT(0), + char** supportedBrands DEFAULT(0), + u_int32_t supportedBrandsCount DEFAULT(0)); + +MP4FileHandle MP4Modify( + const char* fileName, + u_int32_t verbosity DEFAULT(0), + u_int32_t flags DEFAULT(0)); + +MP4FileHandle MP4Read( + const char* fileName, + u_int32_t verbosity DEFAULT(0)); + +bool MP4Close( + MP4FileHandle hFile); + +bool MP4Optimize( + const char* existingFileName, + const char* newFileName DEFAULT(NULL), + u_int32_t verbosity DEFAULT(0)); + +bool MP4Dump( + MP4FileHandle hFile, + FILE* pDumpFile DEFAULT(NULL), + bool dumpImplicits DEFAULT(0)); + +char* MP4Info( + MP4FileHandle hFile, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID)); + +char* MP4FileInfo( + const char* fileName, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID)); + +/* file properties */ + +/* specific file properties */ + +u_int32_t MP4GetVerbosity(MP4FileHandle hFile); + +bool MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity); + +MP4Duration MP4GetDuration(MP4FileHandle hFile); + +u_int32_t MP4GetTimeScale(MP4FileHandle hFile); + +bool MP4SetTimeScale(MP4FileHandle hFile, u_int32_t value); + +u_int8_t MP4GetODProfileLevel(MP4FileHandle hFile); + +bool MP4SetODProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetSceneProfileLevel(MP4FileHandle hFile); + +bool MP4SetSceneProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile); + +bool MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile); + +bool MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile); + +bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, u_int8_t value); + +/* generic file properties */ + +u_int64_t MP4GetIntegerProperty( + MP4FileHandle hFile, + const char* propName); + +bool MP4HaveTrackIntegerProperty( + MP4FileHandle hFile, MP4TrackId trackId, + const char* propName); + +float MP4GetFloatProperty( + MP4FileHandle hFile, + const char* propName); + +const char* MP4GetStringProperty( + MP4FileHandle hFile, + const char* propName); + +void MP4GetBytesProperty( + MP4FileHandle hFile, + const char* propName, + u_int8_t** ppValue, + u_int32_t* pValueSize); + +bool MP4SetIntegerProperty( + MP4FileHandle hFile, + const char* propName, + int64_t value); + +bool MP4SetFloatProperty( + MP4FileHandle hFile, + const char* propName, + float value); + +bool MP4SetStringProperty( + MP4FileHandle hFile, const char* propName, const char* value); + +bool MP4SetBytesProperty( + MP4FileHandle hFile, const char* propName, + const u_int8_t* pValue, u_int32_t valueSize); + +/* track operations */ + +MP4TrackId MP4AddTrack( + MP4FileHandle hFile, + const char* type); + +MP4TrackId MP4AddSystemsTrack( + MP4FileHandle hFile, + const char* type); + +MP4TrackId MP4AddODTrack( + MP4FileHandle hFile); + +MP4TrackId MP4AddSceneTrack( + MP4FileHandle hFile); + +MP4TrackId MP4AddAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE)); + +typedef struct mp4v2_ismacryp_session_params { + u_int32_t scheme_type; + u_int16_t scheme_version; + u_int8_t key_ind_len; + u_int8_t iv_len; + u_int8_t selective_enc; + char *kms_uri; +} mp4v2_ismacrypParams; + + +MP4TrackId MP4AddEncAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + mp4v2_ismacrypParams *icPp, + u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE)); +MP4TrackId MP4AddAmrAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + u_int16_t modeSet, + u_int8_t modeChangePeriod, + u_int8_t framesPerSample, + bool isAmrWB); + +void MP4SetAmrVendor( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t vendor); + +void MP4SetAmrDecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t decoderVersion); + +void MP4SetAmrModeSet(MP4FileHandle hFile, MP4TrackId trakId, uint16_t modeSet); +uint16_t MP4GetAmrModeSet(MP4FileHandle hFile, MP4TrackId trackId); + +MP4TrackId MP4AddHrefTrack(MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration); + +MP4TrackId MP4AddVideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE)); + +MP4TrackId MP4AddEncVideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + mp4v2_ismacrypParams *icPp, + u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE)); + +MP4TrackId MP4AddH264VideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + uint8_t AVCProfileIndication, + uint8_t profile_compat, + uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne); +bool MP4AddH264SequenceParameterSet(MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen); +bool MP4AddH264PictureParameterSet(MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pPict, + uint16_t pictLen); +void MP4SetH263Vendor( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t vendor); + +void MP4SetH263DecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t decoderVersion); + +void MP4SetH263Bitrates( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t avgBitrate, + u_int32_t maxBitrate); + +MP4TrackId MP4AddH263VideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t h263Level, + u_int8_t h263Profile, + u_int32_t avgBitrate, + u_int32_t maxBitrate); + +MP4TrackId MP4AddHintTrack( + MP4FileHandle hFile, + MP4TrackId refTrackId); + +MP4TrackId MP4CloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +MP4TrackId MP4EncAndCloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams *icPp, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +MP4TrackId MP4CopyTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + bool applyEdits DEFAULT(false), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +typedef u_int32_t (*encryptFunc_t)(u_int32_t, u_int32_t, u_int8_t*, u_int32_t*, u_int8_t **); + +MP4TrackId MP4EncAndCopyTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams *icPp, + encryptFunc_t encfcnp, + u_int32_t encfcnparam1, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + bool applyEdits DEFAULT(false), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +bool MP4DeleteTrack( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int32_t MP4GetNumberOfTracks( + MP4FileHandle hFile, + const char* type DEFAULT(NULL), + u_int8_t subType DEFAULT(0)); + +MP4TrackId MP4FindTrackId( + MP4FileHandle hFile, + u_int16_t index, + const char* type DEFAULT(NULL), + u_int8_t subType DEFAULT(0)); + +u_int16_t MP4FindTrackIndex( + MP4FileHandle hFile, + MP4TrackId trackId); + +/* track properties */ + +/* specific track properties */ + +const char* MP4GetTrackType( + MP4FileHandle hFile, + MP4TrackId trackId); + +const char *MP4GetTrackMediaDataName(MP4FileHandle hFile, + MP4TrackId trackId); +MP4Duration MP4GetTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int32_t MP4GetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId); + +bool MP4SetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t value); + +u_int8_t MP4GetTrackAudioMpeg4Type( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int8_t MP4GetTrackEsdsObjectTypeId( + MP4FileHandle hFile, + MP4TrackId trackId); + +/* returns MP4_INVALID_DURATION if track samples do not have a fixed duration */ +MP4Duration MP4GetTrackFixedSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int32_t MP4GetTrackBitRate( + MP4FileHandle hFile, + MP4TrackId trackId); + +bool MP4GetTrackVideoMetadata(MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t **ppConfig, + uint32_t *pConfigSize); + +bool MP4GetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t** ppConfig, + u_int32_t* pConfigSize); + +bool MP4SetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + const u_int8_t* pConfig, + u_int32_t configSize); + +/* h264 information routines */ +bool MP4GetTrackH264ProfileLevel(MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t *pProfile, + uint8_t *pLevel); +bool MP4GetTrackH264SeqPictHeaders(MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t ***pSeqHeaders, + uint32_t **pSeqHeaderSize, + uint8_t ***pPictHeader, + uint32_t **pPictHeaderSize); +bool MP4GetTrackH264LengthSize(MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t *pLength); +MP4SampleId MP4GetTrackNumberOfSamples( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int16_t MP4GetTrackVideoWidth( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int16_t MP4GetTrackVideoHeight( + MP4FileHandle hFile, + MP4TrackId trackId); + +double MP4GetTrackVideoFrameRate( + MP4FileHandle hFile, + MP4TrackId trackId); + +int MP4GetTrackAudioChannels(MP4FileHandle hFile, + MP4TrackId trackId); + +bool MP4IsIsmaCrypMediaTrack( + MP4FileHandle hFile, + MP4TrackId trackId); + +/* generic track properties */ + +u_int64_t MP4GetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName); + +float MP4GetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName); + +const char* MP4GetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName); + +void MP4GetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + u_int8_t** ppValue, + u_int32_t* pValueSize); + +bool MP4SetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + int64_t value); + +bool MP4SetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + float value); + +bool MP4SetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const char* value); + +bool MP4SetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const u_int8_t* pValue, + u_int32_t valueSize); + +/* sample operations */ + +bool MP4ReadSample( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + /* input/output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL)); + +/* uses (unedited) time to specify sample instead of sample id */ +bool MP4ReadSampleFromTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* input/output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL)); + +bool MP4WriteSample( + MP4FileHandle hFile, + MP4TrackId trackId, + const u_int8_t* pBytes, + u_int32_t numBytes, + MP4Duration duration DEFAULT(MP4_INVALID_DURATION), + MP4Duration renderingOffset DEFAULT(0), + bool isSyncSample DEFAULT(true)); + +bool MP4CopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID), + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION)); + +bool MP4EncAndCopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + encryptFunc_t encfcnp, + u_int32_t encfcnparam1, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID), + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION)); + +/* Note this function is not yet implemented */ +bool MP4ReferenceSample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile, + MP4TrackId dstTrackId, + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION)); + +u_int32_t MP4GetSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +u_int32_t MP4GetTrackMaxSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId); + +MP4SampleId MP4GetSampleIdFromTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + bool wantSyncSample DEFAULT(false)); + +MP4Timestamp MP4GetSampleTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +MP4Duration MP4GetSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +MP4Duration MP4GetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +bool MP4SetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + MP4Duration renderingOffset); + +int8_t MP4GetSampleSync( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +/* rtp hint track operations */ + +bool MP4GetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + char** ppPayloadName DEFAULT(NULL), + u_int8_t* pPayloadNumber DEFAULT(NULL), + u_int16_t* pMaxPayloadSize DEFAULT(NULL), + char **ppEncodingParams DEFAULT(NULL)); + +#define MP4_SET_DYNAMIC_PAYLOAD 0xff + +bool MP4SetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* pPayloadName, + u_int8_t* pPayloadNumber, + u_int16_t maxPayloadSize DEFAULT(0), + const char *encode_params DEFAULT(NULL), + bool include_rtp_map DEFAULT(true), + bool include_mpeg4_esid DEFAULT(true)); + +const char* MP4GetSessionSdp( + MP4FileHandle hFile); + +bool MP4SetSessionSdp( + MP4FileHandle hFile, + const char* sdpString); + +bool MP4AppendSessionSdp( + MP4FileHandle hFile, + const char* sdpString); + +const char* MP4GetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4SetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString); + +bool MP4AppendHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString); + +MP4TrackId MP4GetHintTrackReferenceTrackId( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4ReadRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId hintSampleId, + u_int16_t* pNumPackets DEFAULT(NULL)); + +u_int16_t MP4GetRtpHintNumberOfPackets( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +int8_t MP4GetRtpPacketBFrame( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex); + +int32_t MP4GetRtpPacketTransmitOffset( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex); + +bool MP4ReadRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + u_int32_t ssrc DEFAULT(0), + bool includeHeader DEFAULT(true), + bool includePayload DEFAULT(true)); + +MP4Timestamp MP4GetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4SetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Timestamp rtpStart); + +bool MP4AddRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4AddRtpVideoHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool isBframe DEFAULT(false), + u_int32_t timestampOffset DEFAULT(0)); + +bool MP4AddRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool setMbit DEFAULT(false), + int32_t transmitOffset DEFAULT(0)); + +bool MP4AddRtpImmediateData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const u_int8_t* pBytes, + u_int32_t numBytes); + +bool MP4AddRtpSampleData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId sampleId, + u_int32_t dataOffset, + u_int32_t dataLength); + +bool MP4AddRtpESConfigurationPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4WriteRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Duration duration, + bool isSyncSample DEFAULT(true)); + +/* 3GP specific utilities */ + +bool MP4Make3GPCompliant( + const char* fileName, + u_int32_t verbosity DEFAULT(0), + char* majorBrand DEFAULT(0), + u_int32_t minorVersion DEFAULT(0), + char** supportedBrands DEFAULT(NULL), + u_int32_t supportedBrandsCount DEFAULT(0), + bool deleteIodsAtom DEFAULT(true)); + +/* ISMA specific utilities */ + +bool MP4MakeIsmaCompliant(const char* fileName, + u_int32_t verbosity DEFAULT(0), + bool addIsmaComplianceSdp DEFAULT(true)); + +char* MP4MakeIsmaSdpIod( + u_int8_t videoProfile, + u_int32_t videoBitrate, + u_int8_t* videoConfig, + u_int32_t videoConfigLength, + u_int8_t audioProfile, + u_int32_t audioBitrate, + u_int8_t* audioConfig, + u_int32_t audioConfigLength, + u_int32_t verbosity DEFAULT(0)); + +/* edit list */ + +/* NOTE this section of functionality + * has not yet been fully tested + */ + +MP4EditId MP4AddTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID), + MP4Timestamp startTime DEFAULT(0), + MP4Duration duration DEFAULT(0), + bool dwell DEFAULT(false)); + +bool MP4DeleteTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +u_int32_t MP4GetTrackNumberOfEdits( + MP4FileHandle hFile, + MP4TrackId trackId); + +MP4Timestamp MP4GetTrackEditStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +MP4Duration MP4GetTrackEditTotalDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID)); + +MP4Timestamp MP4GetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +bool MP4SetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Timestamp startTime); + +MP4Duration MP4GetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +bool MP4SetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Duration duration); + +int8_t MP4GetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +bool MP4SetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + bool dwell); + +bool MP4ReadSampleFromEditTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* input/output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL)); + +MP4SampleId MP4GetSampleIdFromEditTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL)); +/* iTunes metadata handling */ +bool MP4MetadataDelete(MP4FileHandle hFile); +bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index, + const char** ppName, + u_int8_t** ppValue, u_int32_t* pValueSize); +bool MP4SetMetadataName(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataName(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataName(MP4FileHandle hFile); +bool MP4SetMetadataArtist(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataArtist(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataArtist(MP4FileHandle hFile); +bool MP4SetMetadataWriter(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataWriter(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataWriter(MP4FileHandle hFile); +bool MP4SetMetadataComment(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataComment(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataComment(MP4FileHandle hFile); +bool MP4SetMetadataTool(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataTool(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataTool(MP4FileHandle hFile); +bool MP4SetMetadataYear(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataYear(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataYear(MP4FileHandle hFile); +bool MP4SetMetadataAlbum(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataAlbum(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataAlbum(MP4FileHandle hFile); +bool MP4SetMetadataTrack(MP4FileHandle hFile, + u_int16_t track, u_int16_t totalTracks); +bool MP4GetMetadataTrack(MP4FileHandle hFile, + u_int16_t* track, u_int16_t* totalTracks); +bool MP4DeleteMetadataTrack(MP4FileHandle hFile); +bool MP4SetMetadataDisk(MP4FileHandle hFile, + u_int16_t disk, u_int16_t totalDisks); +bool MP4GetMetadataDisk(MP4FileHandle hFile, + u_int16_t* disk, u_int16_t* totalDisks); +bool MP4DeleteMetadataDisk(MP4FileHandle hFile); +bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre); +bool MP4GetMetadataGenre(MP4FileHandle hFile, char **genre); +bool MP4DeleteMetadataGenre(MP4FileHandle hFile); +bool MP4SetMetadataGrouping(MP4FileHandle hFile, const char *grouping); +bool MP4GetMetadataGrouping(MP4FileHandle hFile, char **grouping); +bool MP4DeleteMetadataGrouping(MP4FileHandle hFile); +bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo); +bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo); +bool MP4DeleteMetadataTempo(MP4FileHandle hFile); +bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl); +bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl); +bool MP4DeleteMetadataCompilation(MP4FileHandle hFile); +bool MP4SetMetadataCoverArt(MP4FileHandle hFile, + u_int8_t *coverArt, u_int32_t size); +bool MP4GetMetadataCoverArt(MP4FileHandle hFile, + u_int8_t **coverArt, u_int32_t* size); +bool MP4DeleteMetadataCoverArt(MP4FileHandle hFile); +bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name, + u_int8_t* pValue, u_int32_t valueSize); +bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name, + u_int8_t** pValue, u_int32_t* valueSize); +bool MP4DeleteMetadataFreeForm(MP4FileHandle hFile, char *name); + + +/* time conversion utilties */ + +/* predefined values for timeScale parameter below */ +#define MP4_SECONDS_TIME_SCALE 1 +#define MP4_MILLISECONDS_TIME_SCALE 1000 +#define MP4_MICROSECONDS_TIME_SCALE 1000000 +#define MP4_NANOSECONDS_TIME_SCALE 1000000000 + +#define MP4_SECS_TIME_SCALE MP4_SECONDS_TIME_SCALE +#define MP4_MSECS_TIME_SCALE MP4_MILLISECONDS_TIME_SCALE +#define MP4_USECS_TIME_SCALE MP4_MICROSECONDS_TIME_SCALE +#define MP4_NSECS_TIME_SCALE MP4_NANOSECONDS_TIME_SCALE + +u_int64_t MP4ConvertFromMovieDuration( + MP4FileHandle hFile, + MP4Duration duration, + u_int32_t timeScale); + +u_int64_t MP4ConvertFromTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp timeStamp, + u_int32_t timeScale); + +MP4Timestamp MP4ConvertToTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int64_t timeStamp, + u_int32_t timeScale); + +u_int64_t MP4ConvertFromTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration duration, + u_int32_t timeScale); + +MP4Duration MP4ConvertToTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int64_t duration, + u_int32_t timeScale); + +char* MP4BinaryToBase16( + const u_int8_t* pData, + u_int32_t dataSize); + +char* MP4BinaryToBase64( + const u_int8_t* pData, + u_int32_t dataSize); + +uint8_t *Base64ToBinary(const char *pData, + uint32_t decodeSize, + uint32_t *pDataSize); + +#ifdef __cplusplus +} +#endif + +/* undefined our utlity macro to avoid conflicts */ +#undef DEFAULT + +#endif /* __MP4_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4array.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4array.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,130 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __MP4_ARRAY_INCLUDED__ +#define __MP4_ARRAY_INCLUDED__ + +typedef u_int32_t MP4ArrayIndex; + +class MP4Array { +public: + MP4Array() { + m_numElements = 0; + m_maxNumElements = 0; + } + + inline bool ValidIndex(MP4ArrayIndex index) { + if (m_numElements == 0 || index > m_numElements - 1) { + return false; + } + return true; + } + + inline MP4ArrayIndex Size(void) { + return m_numElements; + } + + inline MP4ArrayIndex MaxSize(void) { + return m_maxNumElements; + } + +protected: + MP4ArrayIndex m_numElements; + MP4ArrayIndex m_maxNumElements; +}; + +// macro to generate subclasses +// we use this as an alternative to templates +// due to the excessive compile time price of extensive template usage + +#define MP4ARRAY_DECL(name, type) \ + class name##Array : public MP4Array { \ + public: \ + name##Array() { \ + m_elements = NULL; \ + } \ + \ + ~name##Array() { \ + MP4Free(m_elements); \ + } \ + \ + inline void Add(type newElement) { \ + Insert(newElement, m_numElements); \ + } \ + \ + void Insert(type newElement, MP4ArrayIndex newIndex) { \ + if (newIndex > m_numElements) { \ + throw new MP4Error(ERANGE, "MP4Array::Insert"); \ + } \ + if (m_numElements == m_maxNumElements) { \ + m_maxNumElements = MAX(m_maxNumElements, 1) * 2; \ + m_elements = (type*)MP4Realloc(m_elements, \ + m_maxNumElements * sizeof(type)); \ + } \ + memmove(&m_elements[newIndex + 1], &m_elements[newIndex], \ + (m_numElements - newIndex) * sizeof(type)); \ + m_elements[newIndex] = newElement; \ + m_numElements++; \ + } \ + \ + void Delete(MP4ArrayIndex index) { \ + if (!ValidIndex(index)) { \ + throw new MP4Error(ERANGE, "MP4Array::Delete"); \ + } \ + memmove(&m_elements[index], &m_elements[index + 1], \ + (m_numElements - index) * sizeof(type)); \ + m_numElements--; \ + } \ + void Resize(MP4ArrayIndex newSize) { \ + m_numElements = newSize; \ + m_maxNumElements = newSize; \ + m_elements = (type*)MP4Realloc(m_elements, \ + m_maxNumElements * sizeof(type)); \ + } \ + \ + type& operator[](MP4ArrayIndex index) { \ + if (!ValidIndex(index)) { \ + throw new MP4Error(ERANGE, "index %u of %u", "MP4Array::[]", index, m_numElements); \ + } \ + return m_elements[index]; \ + } \ + \ + protected: \ + type* m_elements; \ + }; + +MP4ARRAY_DECL(MP4Integer8, u_int8_t) + +MP4ARRAY_DECL(MP4Integer16, u_int16_t) + +MP4ARRAY_DECL(MP4Integer32, u_int32_t) + +MP4ARRAY_DECL(MP4Integer64, u_int64_t) + +MP4ARRAY_DECL(MP4Float32, float) + +MP4ARRAY_DECL(MP4Float64, double) + +MP4ARRAY_DECL(MP4String, char*) + +MP4ARRAY_DECL(MP4Bytes, u_int8_t*) + +#endif /* __MP4_ARRAY_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4atom.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4atom.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,867 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2004. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" +#include "atoms.h" + +MP4AtomInfo::MP4AtomInfo(const char* name, bool mandatory, bool onlyOne) +{ + m_name = name; + m_mandatory = mandatory; + m_onlyOne = onlyOne; + m_count = 0; +} + +MP4Atom::MP4Atom(const char* type) +{ + SetType(type); + m_unknownType = FALSE; + m_pFile = NULL; + m_start = 0; + m_end = 0; + m_size = 0; + m_pParentAtom = NULL; + m_depth = 0xFF; +} + +MP4Atom::~MP4Atom() +{ + u_int32_t i; + + for (i = 0; i < m_pProperties.Size(); i++) { + delete m_pProperties[i]; + } + for (i = 0; i < m_pChildAtomInfos.Size(); i++) { + delete m_pChildAtomInfos[i]; + } + for (i = 0; i < m_pChildAtoms.Size(); i++) { + delete m_pChildAtoms[i]; + } +} + +MP4Atom* MP4Atom::CreateAtom(const char* type) +{ + MP4Atom* pAtom = NULL; + + if (type == NULL) { + pAtom = new MP4RootAtom(); + } else { + switch((uint8_t)type[0]) { + case 'a': + if (ATOMID(type) == ATOMID("avc1")) { + pAtom = new MP4Avc1Atom(); + } else if (ATOMID(type) == ATOMID("avcC")) { + pAtom = new MP4AvcCAtom(); + } else if (ATOMID(type) == ATOMID("alis")) { + pAtom = new MP4UrlAtom("alis"); + } else if (ATOMID(type) == ATOMID("alaw")) { + pAtom = new MP4SoundAtom("alaw"); + } + break; + case 'd': + if (ATOMID(type) == ATOMID("d263")) { + pAtom = new MP4D263Atom(); + } else if (ATOMID(type) == ATOMID("damr")) { + pAtom = new MP4DamrAtom(); + } else if (ATOMID(type) == ATOMID("dref")) { + pAtom = new MP4DrefAtom(); + } else if (ATOMID(type) == ATOMID("dpnd")) { + pAtom = new MP4TrefTypeAtom(type); + } else if (ATOMID(type) == ATOMID("data")) { /* Apple iTunes */ + pAtom = new MP4DataAtom(); + } + break; + case 'e': + if (ATOMID(type) == ATOMID("elst")) { + pAtom = new MP4ElstAtom(); + } else if (ATOMID(type) == ATOMID("enca")) { + pAtom = new MP4EncaAtom(); + } else if (ATOMID(type) == ATOMID("encv")) { + pAtom = new MP4EncvAtom(); + } + break; + case 'f': + if (ATOMID(type) == ATOMID("free")) { + pAtom = new MP4FreeAtom(); + } else if (ATOMID(type) == ATOMID("ftyp")) { + pAtom = new MP4FtypAtom(); + } + break; + case 'h': + if (ATOMID(type) == ATOMID("hdlr")) { + pAtom = new MP4HdlrAtom(); + } else if (ATOMID(type) == ATOMID("hint")) { + pAtom = new MP4TrefTypeAtom(type); + } else if (ATOMID(type) == ATOMID("hnti")) { + pAtom = new MP4HntiAtom(); + } else if (ATOMID(type) == ATOMID("hinf")) { + pAtom = new MP4HinfAtom(); + } else if (ATOMID(type) == ATOMID("h263")) { + pAtom = new MP4VideoAtom("h263"); + } else if (ATOMID(type) == ATOMID("href")) { + pAtom = new MP4HrefAtom(); + } + break; + case 'i': + if (ATOMID(type) == ATOMID("ipir")) { + pAtom = new MP4TrefTypeAtom(type); + } else if (ATOMID(type) == ATOMID("ima4")) { + pAtom = new MP4SoundAtom("ima4"); + } + break; + case 'j': + if (ATOMID(type) == ATOMID("jpeg")) { + pAtom = new MP4VideoAtom("jpeg"); + } + break; + case 'm': + if (ATOMID(type) == ATOMID("mdhd")) { + pAtom = new MP4MdhdAtom(); + } else if (ATOMID(type) == ATOMID("mvhd")) { + pAtom = new MP4MvhdAtom(); + } else if (ATOMID(type) == ATOMID("mdat")) { + pAtom = new MP4MdatAtom(); + } else if (ATOMID(type) == ATOMID("mpod")) { + pAtom = new MP4TrefTypeAtom(type); + } else if (ATOMID(type) == ATOMID("mp4a")) { + pAtom = new MP4Mp4aAtom(); + } else if (ATOMID(type) == ATOMID("mp4s")) { + pAtom = new MP4Mp4sAtom(); + } else if (ATOMID(type) == ATOMID("mp4v")) { + pAtom = new MP4Mp4vAtom(); + } else if (ATOMID(type) == ATOMID("mean")) { // iTunes + pAtom = new MP4MeanAtom(); + } + break; + case 'n': + if (ATOMID(type) == ATOMID("name")) { // iTunes + pAtom = new MP4NameAtom(); + } + break; + case 'r': + if (ATOMID(type) == ATOMID("rtp ")) { + pAtom = new MP4RtpAtom(); + } else if (ATOMID(type) == ATOMID("raw ")) { + pAtom = new MP4VideoAtom("raw "); + } + break; + case 's': + if (ATOMID(type) == ATOMID("s263")) { + pAtom = new MP4S263Atom(); + } else if (ATOMID(type) == ATOMID("samr")) { + pAtom = new MP4AmrAtom("samr"); + } else if (ATOMID(type) == ATOMID("sawb")) { + pAtom = new MP4AmrAtom("sawb"); + } else if (ATOMID(type) == ATOMID("stbl")) { + pAtom = new MP4StblAtom(); + } else if (ATOMID(type) == ATOMID("stsd")) { + pAtom = new MP4StsdAtom(); + } else if (ATOMID(type) == ATOMID("stsz")) { + pAtom = new MP4StszAtom(); + } else if (ATOMID(type) == ATOMID("stsc")) { + pAtom = new MP4StscAtom(); + } else if (ATOMID(type) == ATOMID("stdp")) { + pAtom = new MP4StdpAtom(); + } else if (ATOMID(type) == ATOMID("sdp ")) { + pAtom = new MP4SdpAtom(); + } else if (ATOMID(type) == ATOMID("sync")) { + pAtom = new MP4TrefTypeAtom(type); + } else if (ATOMID(type) == ATOMID("skip")) { + pAtom = new MP4FreeAtom(); + pAtom->SetType("skip"); + } else if (ATOMID(type) == ATOMID("sowt")) { + pAtom = new MP4SoundAtom("sowt"); + } + break; + case 't': + if (ATOMID(type) == ATOMID("tkhd")) { + pAtom = new MP4TkhdAtom(); + } else if (ATOMID(type) == ATOMID("tfhd")) { + pAtom = new MP4TfhdAtom(); + } else if (ATOMID(type) == ATOMID("trun")) { + pAtom = new MP4TrunAtom(); + } else if (ATOMID(type) == ATOMID("twos")) { + pAtom = new MP4SoundAtom("twos"); + } + break; + case 'u': + if (ATOMID(type) == ATOMID("udta")) { + pAtom = new MP4UdtaAtom(); + } else if (ATOMID(type) == ATOMID("url ")) { + pAtom = new MP4UrlAtom(); + } else if (ATOMID(type) == ATOMID("urn ")) { + pAtom = new MP4UrnAtom(); + } else if (ATOMID(type) == ATOMID("ulaw")) { + pAtom = new MP4SoundAtom("ulaw"); + } + break; + case 'v': + if (ATOMID(type) == ATOMID("vmhd")) { + pAtom = new MP4VmhdAtom(); + } + break; + case 'y': + if (ATOMID(type) == ATOMID("yuv2")) { + pAtom = new MP4VideoAtom("yuv2"); + } + break; + case 'S': + if (ATOMID(type) == ATOMID("SVQ3")) { + pAtom = new MP4VideoAtom("SVQ3"); + } else if (ATOMID(type) == ATOMID("SMI ")) { + pAtom = new MP4SmiAtom(); + } + break; + } + } + + if (pAtom == NULL) { + pAtom = new MP4StandardAtom(type); + // unknown type is set by StandardAtom type + } + + ASSERT(pAtom); + return pAtom; +} + +// generate a skeletal self + +void MP4Atom::Generate() +{ + u_int32_t i; + + // for all properties + for (i = 0; i < m_pProperties.Size(); i++) { + // ask it to self generate + m_pProperties[i]->Generate(); + } + + // for all mandatory, single child atom types + for (i = 0; i < m_pChildAtomInfos.Size(); i++) { + if (m_pChildAtomInfos[i]->m_mandatory + && m_pChildAtomInfos[i]->m_onlyOne) { + + // create the mandatory, single child atom + MP4Atom* pChildAtom = + CreateAtom(m_pChildAtomInfos[i]->m_name); + + AddChildAtom(pChildAtom); + + // and ask it to self generate + pChildAtom->Generate(); + } + } +} + +MP4Atom* MP4Atom::ReadAtom(MP4File* pFile, MP4Atom* pParentAtom) +{ + u_int8_t hdrSize = 8; + u_int8_t extendedType[16]; + + u_int64_t pos = pFile->GetPosition(); + + VERBOSE_READ(pFile->GetVerbosity(), + printf("ReadAtom: pos = 0x%llx\n", pos)); + + u_int64_t dataSize = pFile->ReadUInt32(); + + char type[5]; + pFile->ReadBytes((u_int8_t*)&type[0], 4); + type[4] = '\0'; + + // extended size + if (dataSize == 1) { + dataSize = pFile->ReadUInt64(); + hdrSize += 8; + } + + // extended type + if (ATOMID(type) == ATOMID("uuid")) { + pFile->ReadBytes(extendedType, sizeof(extendedType)); + hdrSize += sizeof(extendedType); + } + + if (dataSize == 0) { + // extends to EOF + dataSize = pFile->GetSize() - pos; + } + + dataSize -= hdrSize; + + VERBOSE_READ(pFile->GetVerbosity(), + printf("ReadAtom: type = \"%s\" data-size = %llu (0x%llx) hdr %u\n", + type, dataSize, dataSize, hdrSize)); + + if (pos + hdrSize + dataSize > pParentAtom->GetEnd()) { + VERBOSE_ERROR(pFile->GetVerbosity(), + printf("ReadAtom: invalid atom size, extends outside parent atom - skipping to end of \"%s\" \"%s\" %llu vs %llu\n", + pParentAtom->GetType(), type, + pos + hdrSize + dataSize, + pParentAtom->GetEnd())); + VERBOSE_READ(pFile->GetVerbosity(), + printf("parent %s (%llu) pos %llu hdr %d data %llu sum %llu\n", + pParentAtom->GetType(), + pParentAtom->GetEnd(), + pos, + hdrSize, + dataSize, + pos + hdrSize + dataSize)); +#if 0 + throw new MP4Error("invalid atom size", "ReadAtom"); +#else + // skip to end of atom + dataSize = pParentAtom->GetEnd() - pos - hdrSize; +#endif + } + + + MP4Atom* pAtom = CreateAtom(type); + pAtom->SetFile(pFile); + pAtom->SetStart(pos); + pAtom->SetEnd(pos + hdrSize + dataSize); + pAtom->SetSize(dataSize); + if (ATOMID(type) == ATOMID("uuid")) { + pAtom->SetExtendedType(extendedType); + } + if (pAtom->IsUnknownType()) { + if (!IsReasonableType(pAtom->GetType())) { + VERBOSE_READ(pFile->GetVerbosity(), + printf("Warning: atom type %s is suspect\n", pAtom->GetType())); + } else { + VERBOSE_READ(pFile->GetVerbosity(), + printf("Info: atom type %s is unknown\n", pAtom->GetType())); + } + + if (dataSize > 0) { + pAtom->AddProperty( + new MP4BytesProperty("data", dataSize)); + } + } + + pAtom->SetParentAtom(pParentAtom); + + pAtom->Read(); + + return pAtom; +} + +bool MP4Atom::IsReasonableType(const char* type) +{ + for (u_int8_t i = 0; i < 4; i++) { + if (isalnum(type[i])) { + continue; + } + if (i == 3 && type[i] == ' ') { + continue; + } + return false; + } + return true; +} + +// generic read +void MP4Atom::Read() +{ + ASSERT(m_pFile); + + if (ATOMID(m_type) != 0 && m_size > 1000000) { + VERBOSE_READ(GetVerbosity(), + printf("Warning: %s atom size %llu is suspect\n", + m_type, m_size)); + } + + ReadProperties(); + + // read child atoms, if we expect there to be some + if (m_pChildAtomInfos.Size() > 0) { + ReadChildAtoms(); + } + + Skip(); // to end of atom +} + +void MP4Atom::Skip() +{ + if (m_pFile->GetPosition() != m_end) { + VERBOSE_READ(m_pFile->GetVerbosity(), + printf("Skip: %llu bytes\n", m_end - m_pFile->GetPosition())); + } + m_pFile->SetPosition(m_end); +} + +MP4Atom* MP4Atom::FindAtom(const char* name) +{ + if (!IsMe(name)) { + return NULL; + } + + if (!IsRootAtom()) { + VERBOSE_FIND(m_pFile->GetVerbosity(), + printf("FindAtom: matched %s\n", name)); + + name = MP4NameAfterFirst(name); + + // I'm the sought after atom + if (name == NULL) { + return this; + } + } + + // else it's one of my children + return FindChildAtom(name); +} + +bool MP4Atom::FindProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!IsMe(name)) { + return false; + } + + if (!IsRootAtom()) { + VERBOSE_FIND(m_pFile->GetVerbosity(), + printf("FindProperty: matched %s\n", name)); + + name = MP4NameAfterFirst(name); + + // no property name given + if (name == NULL) { + return false; + } + } + + return FindContainedProperty(name, ppProperty, pIndex); +} + +bool MP4Atom::IsMe(const char* name) +{ + if (name == NULL) { + return false; + } + + // root atom always matches + if (!strcmp(m_type, "")) { + return true; + } + + // check if our atom name is specified as the first component + if (!MP4NameFirstMatches(m_type, name)) { + return false; + } + + return true; +} + +MP4Atom* MP4Atom::FindChildAtom(const char* name) +{ + u_int32_t atomIndex = 0; + + // get the index if we have one, e.g. moov.trak[2].mdia... + MP4NameFirstIndex(name, &atomIndex); + + // need to get to the index'th child atom of the right type + for (u_int32_t i = 0; i < m_pChildAtoms.Size(); i++) { + if (MP4NameFirstMatches(m_pChildAtoms[i]->GetType(), name)) { + if (atomIndex == 0) { + // this is the one, ask it to match + return m_pChildAtoms[i]->FindAtom(name); + } + atomIndex--; + } + } + + return NULL; +} + +bool MP4Atom::FindContainedProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + u_int32_t numProperties = m_pProperties.Size(); + u_int32_t i; + // check all of our properties + for (i = 0; i < numProperties; i++) { + if (m_pProperties[i]->FindProperty(name, ppProperty, pIndex)) { + return true; + } + } + + // not one of our properties, + // presumably one of our children's properties + // check child atoms... + + // check if we have an index, e.g. trak[2].mdia... + u_int32_t atomIndex = 0; + MP4NameFirstIndex(name, &atomIndex); + + // need to get to the index'th child atom of the right type + for (i = 0; i < m_pChildAtoms.Size(); i++) { + if (MP4NameFirstMatches(m_pChildAtoms[i]->GetType(), name)) { + if (atomIndex == 0) { + // this is the one, ask it to match + return m_pChildAtoms[i]->FindProperty(name, ppProperty, pIndex); + } + atomIndex--; + } + } + + VERBOSE_FIND(m_pFile->GetVerbosity(), + printf("FindProperty: no match for %s\n", name)); + return false; +} + +void MP4Atom::ReadProperties(u_int32_t startIndex, u_int32_t count) +{ + u_int32_t numProperties = MIN(count, m_pProperties.Size() - startIndex); + + // read any properties of the atom + for (u_int32_t i = startIndex; i < startIndex + numProperties; i++) { + + m_pProperties[i]->Read(m_pFile); + + if (m_pFile->GetPosition() > m_end) { + VERBOSE_READ(GetVerbosity(), + printf("ReadProperties: insufficient data for property: %s pos 0x%llx atom end 0x%llx\n", + m_pProperties[i]->GetName(), + m_pFile->GetPosition(), m_end)); + + throw new MP4Error("atom is too small", "Atom ReadProperties"); + } + + if (m_pProperties[i]->GetType() == TableProperty) { + VERBOSE_READ_TABLE(GetVerbosity(), + printf("Read: "); m_pProperties[i]->Dump(stdout, 0, true)); + } else if (m_pProperties[i]->GetType() != DescriptorProperty) { + VERBOSE_READ(GetVerbosity(), + printf("Read: "); m_pProperties[i]->Dump(stdout, 0, true)); + } + } +} + +void MP4Atom::ReadChildAtoms() +{ + bool this_is_udta = ATOMID(m_type) == ATOMID("udta"); + + VERBOSE_READ(GetVerbosity(), + printf("ReadChildAtoms: of %s\n", m_type[0] ? m_type : "root")); + for (u_int64_t position = m_pFile->GetPosition(); + position < m_end; + position = m_pFile->GetPosition()) { + // make sure that we have enough to read at least 8 bytes + // size and type. + if (m_end - position < 2 * sizeof(uint32_t)) { + // if we're reading udta, it's okay to have 4 bytes of 0 + if (this_is_udta && + m_end - position == sizeof(uint32_t)) { + u_int32_t mbz = m_pFile->ReadUInt32(); + if (mbz != 0) { + VERBOSE_WARNING(GetVerbosity(), + printf("Error: In udta atom, end value is not zero %x\n", + mbz)); + } + continue; + } + // otherwise, output a warning, but don't care + VERBOSE_WARNING(GetVerbosity(), + printf("Error: In %s atom, extra %lld bytes at end of atom\n", + m_type, (m_end - position))); + for (uint64_t ix = 0; ix < m_end - position; ix++) { + m_pFile->ReadUInt8(); + } + continue; + } + MP4Atom* pChildAtom = MP4Atom::ReadAtom(m_pFile, this); + + AddChildAtom(pChildAtom); + + MP4AtomInfo* pChildAtomInfo = FindAtomInfo(pChildAtom->GetType()); + + // if child atom is of known type + // but not expected here print warning + if (pChildAtomInfo == NULL && !pChildAtom->IsUnknownType()) { + VERBOSE_READ(GetVerbosity(), + printf("Warning: In atom %s unexpected child atom %s\n", + GetType(), pChildAtom->GetType())); + } + + // if child atoms should have just one instance + // and this is more than one, print warning + if (pChildAtomInfo) { + pChildAtomInfo->m_count++; + + if (pChildAtomInfo->m_onlyOne && pChildAtomInfo->m_count > 1) { + VERBOSE_READ(GetVerbosity(), + printf("Warning: In atom %s multiple child atoms %s\n", + GetType(), pChildAtom->GetType())); + } + } + + } + + // if mandatory child atom doesn't exist, print warning + u_int32_t numAtomInfo = m_pChildAtomInfos.Size(); + for (u_int32_t i = 0; i < numAtomInfo; i++) { + if (m_pChildAtomInfos[i]->m_mandatory + && m_pChildAtomInfos[i]->m_count == 0) { + VERBOSE_READ(GetVerbosity(), + printf("Warning: In atom %s missing child atom %s\n", + GetType(), m_pChildAtomInfos[i]->m_name)); + } + } + + VERBOSE_READ(GetVerbosity(), + printf("ReadChildAtoms: finished %s\n", m_type)); +} + +MP4AtomInfo* MP4Atom::FindAtomInfo(const char* name) +{ + u_int32_t numAtomInfo = m_pChildAtomInfos.Size(); + for (u_int32_t i = 0; i < numAtomInfo; i++) { + if (ATOMID(m_pChildAtomInfos[i]->m_name) == ATOMID(name)) { + return m_pChildAtomInfos[i]; + } + } + return NULL; +} + +// generic write +void MP4Atom::Write() +{ + ASSERT(m_pFile); + + BeginWrite(); + + WriteProperties(); + + WriteChildAtoms(); + + FinishWrite(); +} + +void MP4Atom::Rewrite() +{ + ASSERT(m_pFile); + + if (!m_end) { + // This atom hasn't been written yet... + return; + } + + u_int64_t fPos = m_pFile->GetPosition(); + m_pFile->SetPosition(GetStart()); + Write(); + m_pFile->SetPosition(fPos); +} + +void MP4Atom::BeginWrite(bool use64) +{ + m_start = m_pFile->GetPosition(); + //use64 = m_pFile->Use64Bits(); + if (use64) { + m_pFile->WriteUInt32(1); + } else { + m_pFile->WriteUInt32(0); + } + m_pFile->WriteBytes((u_int8_t*)&m_type[0], 4); + if (use64) { + m_pFile->WriteUInt64(0); + } + if (ATOMID(m_type) == ATOMID("uuid")) { + m_pFile->WriteBytes(m_extendedType, sizeof(m_extendedType)); + } +} + +void MP4Atom::FinishWrite(bool use64) +{ + m_end = m_pFile->GetPosition(); + m_size = (m_end - m_start); + VERBOSE_WRITE(GetVerbosity(), + printf("end: type %s %llu %llu size %llu\n", m_type, + m_start, m_end, + m_size)); + //use64 = m_pFile->Use64Bits(); + if (use64) { + m_pFile->SetPosition(m_start + 8); + m_pFile->WriteUInt64(m_size); + } else { + ASSERT(m_size <= (u_int64_t)0xFFFFFFFF); + m_pFile->SetPosition(m_start); + m_pFile->WriteUInt32(m_size); + } + m_pFile->SetPosition(m_end); + + // adjust size to just reflect data portion of atom + m_size -= (use64 ? 16 : 8); + if (ATOMID(m_type) == ATOMID("uuid")) { + m_size -= sizeof(m_extendedType); + } +} + +void MP4Atom::WriteProperties(u_int32_t startIndex, u_int32_t count) +{ + u_int32_t numProperties = MIN(count, m_pProperties.Size() - startIndex); + + VERBOSE_WRITE(GetVerbosity(), + printf("Write: type %s\n", m_type)); + + for (u_int32_t i = startIndex; i < startIndex + numProperties; i++) { + m_pProperties[i]->Write(m_pFile); + + if (m_pProperties[i]->GetType() == TableProperty) { + VERBOSE_WRITE_TABLE(GetVerbosity(), + printf("Write: "); m_pProperties[i]->Dump(stdout, 0, false)); + } else { + VERBOSE_WRITE(GetVerbosity(), + printf("Write: "); m_pProperties[i]->Dump(stdout, 0, false)); + } + } +} + +void MP4Atom::WriteChildAtoms() +{ + u_int32_t size = m_pChildAtoms.Size(); + for (u_int32_t i = 0; i < size; i++) { + m_pChildAtoms[i]->Write(); + } + + VERBOSE_WRITE(GetVerbosity(), + printf("Write: finished %s\n", m_type)); +} + +void MP4Atom::AddProperty(MP4Property* pProperty) +{ + ASSERT(pProperty); + m_pProperties.Add(pProperty); + pProperty->SetParentAtom(this); +} + +void MP4Atom::AddVersionAndFlags() +{ + AddProperty(new MP4Integer8Property("version")); + AddProperty(new MP4Integer24Property("flags")); +} + +void MP4Atom::AddReserved(char* name, u_int32_t size) +{ + MP4BytesProperty* pReserved = new MP4BytesProperty(name, size); + pReserved->SetReadOnly(); + AddProperty(pReserved); +} + +void MP4Atom::ExpectChildAtom(const char* name, bool mandatory, bool onlyOne) +{ + m_pChildAtomInfos.Add(new MP4AtomInfo(name, mandatory, onlyOne)); +} + +u_int8_t MP4Atom::GetVersion() +{ + if (strcmp("version", m_pProperties[0]->GetName())) { + return 0; + } + return ((MP4Integer8Property*)m_pProperties[0])->GetValue(); +} + +void MP4Atom::SetVersion(u_int8_t version) +{ + if (strcmp("version", m_pProperties[0]->GetName())) { + return; + } + ((MP4Integer8Property*)m_pProperties[0])->SetValue(version); +} + +u_int32_t MP4Atom::GetFlags() +{ + if (strcmp("flags", m_pProperties[1]->GetName())) { + return 0; + } + return ((MP4Integer24Property*)m_pProperties[1])->GetValue(); +} + +void MP4Atom::SetFlags(u_int32_t flags) +{ + if (strcmp("flags", m_pProperties[1]->GetName())) { + return; + } + ((MP4Integer24Property*)m_pProperties[1])->SetValue(flags); +} + +void MP4Atom::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits) +{ + if (m_type[0] != '\0') { + Indent(pFile, indent); + fprintf(pFile, "type %s\n", m_type); + fflush(pFile); + } + + u_int32_t i; + u_int32_t size; + + // dump our properties + size = m_pProperties.Size(); + for (i = 0; i < size; i++) { + + /* skip details of tables unless we're told to be verbose */ + if (m_pProperties[i]->GetType() == TableProperty + && !(GetVerbosity() & MP4_DETAILS_TABLE)) { + Indent(pFile, indent + 1); + fprintf(pFile, "\n"); + continue; + } + + m_pProperties[i]->Dump(pFile, indent + 1, dumpImplicits); + } + + // dump our children + size = m_pChildAtoms.Size(); + for (i = 0; i < size; i++) { + m_pChildAtoms[i]->Dump(pFile, indent + 1, dumpImplicits); + } +} + +u_int32_t MP4Atom::GetVerbosity() +{ + ASSERT(m_pFile); + return m_pFile->GetVerbosity(); +} + +u_int8_t MP4Atom::GetDepth() +{ + if (m_depth < 0xFF) { + return m_depth; + } + + MP4Atom *pAtom = this; + m_depth = 0; + + while ((pAtom = pAtom->GetParentAtom()) != NULL) { + m_depth++; + ASSERT(m_depth < 255); + } + return m_depth; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4atom.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4atom.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,239 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2004. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#ifndef __MP4_ATOM_INCLUDED__ +#define __MP4_ATOM_INCLUDED__ + +class MP4Atom; +MP4ARRAY_DECL(MP4Atom, MP4Atom*); + +#define Required true +#define Optional false +#define OnlyOne true +#define Many false +#define Counted true + +/* helper class */ +class MP4AtomInfo { +public: + MP4AtomInfo() { + m_name = NULL; + } + MP4AtomInfo(const char* name, bool mandatory, bool onlyOne); + + const char* m_name; + bool m_mandatory; + bool m_onlyOne; + u_int32_t m_count; +}; + +MP4ARRAY_DECL(MP4AtomInfo, MP4AtomInfo*); + +class MP4Atom { +public: + MP4Atom(const char* type = NULL); + virtual ~MP4Atom(); + + static MP4Atom* ReadAtom(MP4File* pFile, MP4Atom* pParentAtom); + static MP4Atom* CreateAtom(const char* type); + static bool IsReasonableType(const char* type); + + MP4File* GetFile() { + return m_pFile; + }; + void SetFile(MP4File* pFile) { + m_pFile = pFile; + }; + + u_int64_t GetStart() { + return m_start; + }; + void SetStart(u_int64_t pos) { + m_start = pos; + }; + + u_int64_t GetEnd() { + return m_end; + }; + void SetEnd(u_int64_t pos) { + m_end = pos; + }; + + u_int64_t GetSize() { + return m_size; + } + void SetSize(u_int64_t size) { + m_size = size; + } + + const char* GetType() { + return m_type; + }; + void SetType(const char* type) { + if (type && *type != '\0') { + // not needed ASSERT(strlen(type) == 4); + memcpy(m_type, type, 4); + m_type[4] = '\0'; + } else { + memset(m_type, 0, 5); + } + } + + void GetExtendedType(u_int8_t* pExtendedType) { + memcpy(pExtendedType, m_extendedType, sizeof(m_extendedType)); + }; + void SetExtendedType(u_int8_t* pExtendedType) { + memcpy(m_extendedType, pExtendedType, sizeof(m_extendedType)); + }; + + bool IsUnknownType() { + return m_unknownType; + } + void SetUnknownType(bool unknownType = true) { + m_unknownType = unknownType; + } + + bool IsRootAtom() { + return m_type[0] == '\0'; + } + + MP4Atom* GetParentAtom() { + return m_pParentAtom; + } + void SetParentAtom(MP4Atom* pParentAtom) { + m_pParentAtom = pParentAtom; + } + + void AddChildAtom(MP4Atom* pChildAtom) { + pChildAtom->SetFile(m_pFile); + pChildAtom->SetParentAtom(this); + m_pChildAtoms.Add(pChildAtom); + } + + void InsertChildAtom(MP4Atom* pChildAtom, u_int32_t index) { + pChildAtom->SetFile(m_pFile); + pChildAtom->SetParentAtom(this); + m_pChildAtoms.Insert(pChildAtom, index); + } + + void DeleteChildAtom(MP4Atom* pChildAtom) { + for (MP4ArrayIndex i = 0; i < m_pChildAtoms.Size(); i++) { + if (m_pChildAtoms[i] == pChildAtom) { + m_pChildAtoms.Delete(i); + return; + } + } + } + + u_int32_t GetNumberOfChildAtoms() { + return m_pChildAtoms.Size(); + } + + MP4Atom* GetChildAtom(u_int32_t index) { + return m_pChildAtoms[index]; + } + + MP4Property* GetProperty(u_int32_t index) { + return m_pProperties[index]; + } + + MP4Atom* FindAtom(const char* name); + + MP4Atom* FindChildAtom(const char* name); + + bool FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + u_int32_t GetFlags(); + void SetFlags(u_int32_t flags); + + u_int8_t GetDepth(); + + void Skip(); + + virtual void Generate(); + virtual void Read(); + virtual void BeginWrite(bool use64 = false); + virtual void Write(); + virtual void Rewrite(); + virtual void FinishWrite(bool use64 = false); + virtual void Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits); + +protected: + void AddProperty(MP4Property* pProperty); + + void AddVersionAndFlags(); + + void AddReserved(char* name, u_int32_t size); + + void ExpectChildAtom(const char* name, + bool mandatory, bool onlyOne = true); + + MP4AtomInfo* FindAtomInfo(const char* name); + + bool IsMe(const char* name); + + bool FindContainedProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex); + + void ReadProperties( + u_int32_t startIndex = 0, u_int32_t count = 0xFFFFFFFF); + void ReadChildAtoms(); + + void WriteProperties( + u_int32_t startIndex = 0, u_int32_t count = 0xFFFFFFFF); + void WriteChildAtoms(); + + u_int8_t GetVersion(); + void SetVersion(u_int8_t version); + + /* debugging aid */ + u_int32_t GetVerbosity(); + +protected: + MP4File* m_pFile; + u_int64_t m_start; + u_int64_t m_end; + u_int64_t m_size; + char m_type[5]; + bool m_unknownType; + u_int8_t m_extendedType[16]; + + MP4Atom* m_pParentAtom; + u_int8_t m_depth; + + MP4PropertyArray m_pProperties; + MP4AtomInfoArray m_pChildAtomInfos; + MP4AtomArray m_pChildAtoms; +}; + +inline u_int32_t ATOMID(const char* type) { + return STRTOINT32(type); +} + +#endif /* __MP4_ATOM_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4common.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,50 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __MP4_COMMON_INCLUDED__ +#define __MP4_COMMON_INCLUDED__ + +// common includes for everything +// with an internal view of the library +// i.e. all the .cpp's just #include "mp4common.h" + +#include "mpeg4ip.h" + +#include "mp4.h" +#include "mp4util.h" +#include "mp4array.h" +#include "mp4track.h" +#include "mp4file.h" +#include "mp4property.h" +#include "mp4container.h" +#include "mp4descriptor.h" +#include "mp4atom.h" + +#include "atoms.h" +#include "descriptors.h" +#include "ocidescriptors.h" +#include "qosqualifiers.h" + +#include "odcommands.h" + +#include "rtphint.h" + +#endif /* __MP4_COMMON_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4container.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4container.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,227 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4Container::~MP4Container() +{ + for (u_int32_t i = 0; i < m_pProperties.Size(); i++) { + delete m_pProperties[i]; + } +} + +void MP4Container::AddProperty(MP4Property* pProperty) +{ + ASSERT(pProperty); + m_pProperties.Add(pProperty); +} + +bool MP4Container::FindProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (pIndex) { + *pIndex = 0; // set the default answer for index + } + + u_int32_t numProperties = m_pProperties.Size(); + + for (u_int32_t i = 0; i < numProperties; i++) { + if (m_pProperties[i]->FindProperty(name, ppProperty, pIndex)) { + return true; + } + } + return false; +} + +void MP4Container::FindIntegerProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property", + "MP4Container::FindIntegerProperty"); + } + + switch ((*ppProperty)->GetType()) { + case Integer8Property: + case Integer16Property: + case Integer24Property: + case Integer32Property: + case Integer64Property: + break; + default: + throw new MP4Error("type mismatch", + "MP4Container::FindIntegerProperty"); + } +} + +u_int64_t MP4Container::GetIntegerProperty(const char* name) +{ + MP4Property* pProperty; + u_int32_t index; + + FindIntegerProperty(name, &pProperty, &index); + + return ((MP4IntegerProperty*)pProperty)->GetValue(index); +} + +void MP4Container::SetIntegerProperty(const char* name, u_int64_t value) +{ + MP4Property* pProperty = NULL; + u_int32_t index = 0; + + FindIntegerProperty(name, &pProperty, &index); + + ((MP4IntegerProperty*)pProperty)->SetValue(value, index); +} + +void MP4Container::FindFloatProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property", + "MP4Container::FindFloatProperty"); + } + if ((*ppProperty)->GetType() != Float32Property) { + throw new MP4Error("type mismatch", + "MP4Container::FindFloatProperty"); + } +} + +float MP4Container::GetFloatProperty(const char* name) +{ + MP4Property* pProperty; + u_int32_t index; + + FindFloatProperty(name, &pProperty, &index); + + return ((MP4Float32Property*)pProperty)->GetValue(index); +} + +void MP4Container::SetFloatProperty(const char* name, float value) +{ + MP4Property* pProperty; + u_int32_t index; + + FindFloatProperty(name, &pProperty, &index); + + ((MP4Float32Property*)pProperty)->SetValue(value, index); +} + +void MP4Container::FindStringProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property", + "MP4Container::FindStringProperty"); + } + if ((*ppProperty)->GetType() != StringProperty) { + throw new MP4Error("type mismatch", + "MP4Container::FindStringProperty"); + } +} + +const char* MP4Container::GetStringProperty(const char* name) +{ + MP4Property* pProperty; + u_int32_t index; + + FindStringProperty(name, &pProperty, &index); + + return ((MP4StringProperty*)pProperty)->GetValue(index); +} + +void MP4Container::SetStringProperty(const char* name, const char* value) +{ + MP4Property* pProperty; + u_int32_t index; + + FindStringProperty(name, &pProperty, &index); + + ((MP4StringProperty*)pProperty)->SetValue(value, index); +} + +void MP4Container::FindBytesProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property", + "MP4Container::FindBytesProperty"); + } + if ((*ppProperty)->GetType() != BytesProperty) { + throw new MP4Error("type mismatch", + "MP4Container::FindBytesProperty"); + } +} + +void MP4Container::GetBytesProperty(const char* name, + u_int8_t** ppValue, u_int32_t* pValueSize) +{ + MP4Property* pProperty; + u_int32_t index; + + FindBytesProperty(name, &pProperty, &index); + + ((MP4BytesProperty*)pProperty)->GetValue(ppValue, pValueSize, index); +} + +void MP4Container::SetBytesProperty(const char* name, + const u_int8_t* pValue, u_int32_t valueSize) +{ + MP4Property* pProperty; + u_int32_t index; + + FindBytesProperty(name, &pProperty, &index); + + ((MP4BytesProperty*)pProperty)->SetValue(pValue, valueSize, index); +} + +void MP4Container::Read(MP4File* pFile) +{ + u_int32_t numProperties = m_pProperties.Size(); + + for (u_int32_t i = 0; i < numProperties; i++) { + m_pProperties[i]->Read(pFile); + } +} + +void MP4Container::Write(MP4File* pFile) +{ + u_int32_t numProperties = m_pProperties.Size(); + + if (numProperties == 0) { + WARNING(numProperties == 0); + return; + } + + for (u_int32_t i = 0; i < numProperties; i++) { + m_pProperties[i]->Write(pFile); + } +} + +void MP4Container::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits) +{ + u_int32_t numProperties = m_pProperties.Size(); + + for (u_int32_t i = 0; i < numProperties; i++) { + m_pProperties[i]->Dump(pFile, indent, dumpImplicits); + } +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4container.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4container.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,84 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __MP4_CONTAINER_INCLUDED__ +#define __MP4_CONTAINER_INCLUDED__ + +// base class - container of mp4 properties +class MP4Container { +public: + MP4Container() { } + + virtual ~MP4Container(); + + void AddProperty(MP4Property* pProperty); + + virtual void Read(MP4File* pFile); + + virtual void Write(MP4File* pFile); + + virtual void Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits); + + MP4Property* GetProperty(u_int32_t index) { + return m_pProperties[index]; + } + + // LATER MP4Property* GetProperty(const char* name); throw on error + // LATER MP4Property* FindProperty(const char* name, u_int32_t* pIndex = NULL); returns NULL on error + + bool FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + void FindIntegerProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + u_int64_t GetIntegerProperty(const char* name); + + void SetIntegerProperty(const char* name, u_int64_t value); + + void FindFloatProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + float GetFloatProperty(const char* name); + + void SetFloatProperty(const char* name, float value); + + void FindStringProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + const char* GetStringProperty(const char* name); + + void SetStringProperty(const char* name, const char* value); + + void FindBytesProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + void GetBytesProperty(const char* name, + u_int8_t** ppValue, u_int32_t* pValueSize); + + void SetBytesProperty(const char* name, + const u_int8_t* pValue, u_int32_t valueSize); + +protected: + MP4PropertyArray m_pProperties; +}; + +#endif /* __MP4_CONTAINER_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4descriptor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4descriptor.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,211 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4Descriptor::MP4Descriptor(u_int8_t tag) { + m_tag = tag; + m_pParentAtom = NULL; + m_start = 0; + m_size = 0; + m_readMutatePoint = 0; +} + +MP4Descriptor::~MP4Descriptor() +{ + for (u_int32_t i = 0; i < m_pProperties.Size(); i++) { + delete m_pProperties[i]; + } +} + +void MP4Descriptor::AddProperty(MP4Property* pProperty) +{ + ASSERT(pProperty); + m_pProperties.Add(pProperty); + pProperty->SetParentAtom(m_pParentAtom); +} + +bool MP4Descriptor::FindContainedProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + u_int32_t numProperties = m_pProperties.Size(); + + for (u_int32_t i = 0; i < numProperties; i++) { + if (m_pProperties[i]->FindProperty(name, ppProperty, pIndex)) { + return true; + } + } + return false; +} + +void MP4Descriptor::Generate() +{ + // generate properties + for (u_int32_t i = 0; i < m_pProperties.Size(); i++) { + m_pProperties[i]->Generate(); + } +} + +void MP4Descriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + ReadProperties(pFile, 0, m_readMutatePoint); + + Mutate(); + + ReadProperties(pFile, m_readMutatePoint); + + // flush any leftover read bits + pFile->FlushReadBits(); +} + +void MP4Descriptor::ReadHeader(MP4File* pFile) +{ + VERBOSE_READ(pFile->GetVerbosity(), + printf("ReadDescriptor: pos = 0x%llx\n", + pFile->GetPosition())); + + // read tag and length + u_int8_t tag = pFile->ReadUInt8(); + if (m_tag) { + ASSERT(tag == m_tag); + } else { + m_tag = tag; + } + m_size = pFile->ReadMpegLength(); + m_start = pFile->GetPosition(); + + VERBOSE_READ(pFile->GetVerbosity(), + printf("ReadDescriptor: tag 0x%02x data size %u (0x%x)\n", + m_tag, m_size, m_size)); +} + +void MP4Descriptor::ReadProperties(MP4File* pFile, + u_int32_t propStartIndex, u_int32_t propCount) +{ + u_int32_t numProperties = MIN(propCount, + m_pProperties.Size() - propStartIndex); + + for (u_int32_t i = propStartIndex; + i < propStartIndex + numProperties; i++) { + + MP4Property* pProperty = m_pProperties[i]; + + int32_t remaining = m_size - (pFile->GetPosition() - m_start); + + if (pProperty->GetType() == DescriptorProperty) { + if (remaining > 0) { + // place a limit on how far this sub-descriptor looks + ((MP4DescriptorProperty*)pProperty)->SetSizeLimit(remaining); + pProperty->Read(pFile); + } // else do nothing, empty descriptor + } else { + // non-descriptor property + if (remaining >= 0) { + pProperty->Read(pFile); + + if (pProperty->GetType() == TableProperty) { + VERBOSE_READ_TABLE(pFile->GetVerbosity(), + printf("Read: "); pProperty->Dump(stdout, 0, true)); + } else { + VERBOSE_READ(pFile->GetVerbosity(), + printf("Read: "); pProperty->Dump(stdout, 0, true)); + } + } else { + VERBOSE_ERROR(pFile->GetVerbosity(), + printf("Overran descriptor, tag %u data size %u property %u\n", + m_tag, m_size, i)); + throw new MP4Error("overran descriptor", + "MP4Descriptor::ReadProperties"); + } + } + } +} + +void MP4Descriptor::Write(MP4File* pFile) +{ + // call virtual function to adapt properties before writing + Mutate(); + + u_int32_t numProperties = m_pProperties.Size(); + + if (numProperties == 0) { + WARNING(numProperties == 0); + return; + } + + // write tag and length placeholder + pFile->WriteUInt8(m_tag); + u_int64_t lengthPos = pFile->GetPosition(); + pFile->WriteMpegLength(0); + u_int64_t startPos = pFile->GetPosition(); + + for (u_int32_t i = 0; i < numProperties; i++) { + m_pProperties[i]->Write(pFile); + } + + // align with byte boundary (rarely necessary) + pFile->PadWriteBits(); + + // go back and write correct length + u_int64_t endPos = pFile->GetPosition(); + pFile->SetPosition(lengthPos); + pFile->WriteMpegLength(endPos - startPos); + pFile->SetPosition(endPos); +} + +void MP4Descriptor::WriteToMemory(MP4File* pFile, + u_int8_t** ppBytes, u_int64_t* pNumBytes) +{ + // use memory buffer to save descriptor in memory + // instead of going directly to disk + + pFile->EnableMemoryBuffer(); + + Write(pFile); + + pFile->DisableMemoryBuffer(ppBytes, pNumBytes); +} + +void MP4Descriptor::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits) +{ + // call virtual function to adapt properties before dumping + Mutate(); + + u_int32_t numProperties = m_pProperties.Size(); + + if (numProperties == 0) { + WARNING(numProperties == 0); + return; + } + for (u_int32_t i = 0; i < numProperties; i++) { + m_pProperties[i]->Dump(pFile, indent, dumpImplicits); + } +} + +u_int8_t MP4Descriptor::GetDepth() +{ + if (m_pParentAtom) { + return m_pParentAtom->GetDepth(); + } + return 0; +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4descriptor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4descriptor.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,96 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __MP4_DESCRIPTOR_INCLUDED__ +#define __MP4_DESCRIPTOR_INCLUDED__ + +class MP4Descriptor { +public: + MP4Descriptor(u_int8_t tag = 0); + + virtual ~MP4Descriptor(); + + u_int8_t GetTag() { + return m_tag; + } + void SetTag(u_int8_t tag) { + m_tag = tag; + } + + void SetParentAtom(MP4Atom* pParentAtom) { + m_pParentAtom = pParentAtom; + for (u_int32_t i = 0; i < m_pProperties.Size(); i++) { + m_pProperties[i]->SetParentAtom(pParentAtom); + } + } + + void AddProperty(MP4Property* pProperty); + + virtual void Generate(); + virtual void Read(MP4File* pFile); + virtual void Write(MP4File* pFile); + virtual void Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits); + + MP4Property* GetProperty(u_int32_t index) { + return m_pProperties[index]; + } + + // use with extreme caution + void SetProperty(u_int32_t index, MP4Property* pProperty) { + m_pProperties[index] = pProperty; + } + + bool FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL) { + return FindContainedProperty(name, ppProperty, pIndex); + } + + void WriteToMemory(MP4File* pFile, + u_int8_t** ppBytes, u_int64_t* pNumBytes); + +protected: + void SetReadMutate(u_int32_t propIndex) { + m_readMutatePoint = propIndex; + } + + void ReadHeader(MP4File* pFile); + void ReadProperties(MP4File* pFile, + u_int32_t startIndex = 0, u_int32_t count = 0xFFFFFFFF); + + virtual void Mutate() { + // default is a no-op + }; + + bool FindContainedProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex); + + u_int8_t GetDepth(); + +protected: + MP4Atom* m_pParentAtom; + u_int8_t m_tag; + u_int64_t m_start; + u_int32_t m_size; + MP4PropertyArray m_pProperties; + u_int32_t m_readMutatePoint; +}; + +#endif /* __MP4_DESCRIPTOR_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4file.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4file.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,3047 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + * Bill May wmay@cisco.com + */ + +#include "mp4common.h" + +MP4File::MP4File(u_int32_t verbosity) +{ + m_fileName = NULL; + m_pFile = NULL; + m_orgFileSize = 0; + m_fileSize = 0; + m_pRootAtom = NULL; + m_odTrackId = MP4_INVALID_TRACK_ID; + + m_verbosity = verbosity; + m_mode = 0; + m_createFlags = 0; + m_useIsma = false; + + m_pModificationProperty = NULL; + m_pTimeScaleProperty = NULL; + m_pDurationProperty = NULL; + + m_memoryBuffer = NULL; + m_memoryBufferSize = 0; + m_memoryBufferPosition = 0; + + m_numReadBits = 0; + m_bufReadBits = 0; + m_numWriteBits = 0; + m_bufWriteBits = 0; + m_editName = NULL; +} + +MP4File::~MP4File() +{ + MP4Free(m_fileName); + if (m_pFile != NULL) { + // not closed ? + fclose(m_pFile); + m_pFile = NULL; + } + delete m_pRootAtom; + for (u_int32_t i = 0; i < m_pTracks.Size(); i++) { + delete m_pTracks[i]; + } + MP4Free(m_memoryBuffer); // just in case + CHECK_AND_FREE(m_editName); + +} + +void MP4File::Read(const char* fileName) +{ + m_fileName = MP4Stralloc(fileName); + m_mode = 'r'; + + Open("rb"); + + ReadFromFile(); + + CacheProperties(); +} + +void MP4File::Create(const char* fileName, u_int32_t flags, + int add_ftyp, int add_iods, + char* majorBrand, u_int32_t minorVersion, + char** supportedBrands, u_int32_t supportedBrandsCount) +{ + m_fileName = MP4Stralloc(fileName); + m_mode = 'w'; + m_createFlags = flags; + + Open("wb+"); + + // generate a skeletal atom tree + m_pRootAtom = MP4Atom::CreateAtom(NULL); + m_pRootAtom->SetFile(this); + m_pRootAtom->Generate(); + + if (add_ftyp != 0) { + MakeFtypAtom(majorBrand, minorVersion, + supportedBrands, supportedBrandsCount); + } + + CacheProperties(); + + // create mdat, and insert it after ftyp, and before moov + InsertChildAtom(m_pRootAtom, "mdat", + add_ftyp != 0 ? 1 : 0); + + // start writing + m_pRootAtom->BeginWrite(); +} + +bool MP4File::Use64Bits (const char *atomName) +{ + if (!strcmp(atomName, "mdat") || !strcmp(atomName, "stbl")) { + return (m_createFlags & MP4_CREATE_64BIT_DATA) == MP4_CREATE_64BIT_DATA; + } + + if (!strcmp(atomName, "mvhd") || + !strcmp(atomName, "tkhd") || + !strcmp(atomName, "mdhd")) { + return (m_createFlags & MP4_CREATE_64BIT_TIME) == MP4_CREATE_64BIT_TIME; + } + return false; +} + + +void MP4File::Modify(const char* fileName) +{ + m_fileName = MP4Stralloc(fileName); + m_mode = 'r'; + + Open("rb+"); + ReadFromFile(); + + m_mode = 'w'; + + // find the moov atom + MP4Atom* pMoovAtom = m_pRootAtom->FindAtom("moov"); + u_int32_t numAtoms; + + if (pMoovAtom == NULL) { + // there isn't one, odd but we can still proceed + pMoovAtom = AddChildAtom(m_pRootAtom, "moov"); + } else { + numAtoms = m_pRootAtom->GetNumberOfChildAtoms(); + + // work backwards thru the top level atoms + int32_t i; + bool lastAtomIsMoov = true; + MP4Atom* pLastAtom = NULL; + + for (i = numAtoms - 1; i >= 0; i--) { + MP4Atom* pAtom = m_pRootAtom->GetChildAtom(i); + const char* type = pAtom->GetType(); + + // get rid of any trailing free or skips + if (!strcmp(type, "free") || !strcmp(type, "skip")) { + m_pRootAtom->DeleteChildAtom(pAtom); + continue; + } + + if (strcmp(type, "moov")) { + if (pLastAtom == NULL) { + pLastAtom = pAtom; + lastAtomIsMoov = false; + } + continue; + } + + // now at moov atom + + // multiple moov atoms?!? + if (pAtom != pMoovAtom) { + throw new MP4Error( + "Badly formed mp4 file, multiple moov atoms", + "MP4Modify"); + } + + if (lastAtomIsMoov) { + // position to start of moov atom, + // effectively truncating file + // prior to adding new mdat + SetPosition(pMoovAtom->GetStart()); + + } else { // last atom isn't moov + // need to place a free atom + MP4Atom* pFreeAtom = MP4Atom::CreateAtom("free"); + + // in existing position of the moov atom + m_pRootAtom->InsertChildAtom(pFreeAtom, i); + m_pRootAtom->DeleteChildAtom(pMoovAtom); + m_pRootAtom->AddChildAtom(pMoovAtom); + + // write free atom to disk + SetPosition(pMoovAtom->GetStart()); + pFreeAtom->SetSize(pMoovAtom->GetSize()); + pFreeAtom->Write(); + + // finally set our file position to the end of the last atom + SetPosition(pLastAtom->GetEnd()); + } + + break; + } + ASSERT(i != -1); + } + + CacheProperties(); // of moov atom + + numAtoms = m_pRootAtom->GetNumberOfChildAtoms(); + + // insert another mdat prior to moov atom (the last atom) + MP4Atom* pMdatAtom = InsertChildAtom(m_pRootAtom, "mdat", numAtoms - 1); + + // start writing new mdat + pMdatAtom->BeginWrite(); +} + +void MP4File::Optimize(const char* orgFileName, const char* newFileName) +{ + m_fileName = MP4Stralloc(orgFileName); + m_mode = 'r'; + + // first load meta-info into memory + Open("rb"); + ReadFromFile(); + + CacheProperties(); // of moov atom + + // now switch over to writing the new file + MP4Free(m_fileName); + + // create a temporary file if necessary + if (newFileName == NULL) { + m_fileName = MP4Stralloc(TempFileName()); + } else { + m_fileName = MP4Stralloc(newFileName); + } + + FILE* pReadFile = m_pFile; + m_pFile = NULL; + m_mode = 'w'; + + Open("wb"); + + SetIntegerProperty("moov.mvhd.modificationTime", + MP4GetAbsTimestamp()); + + // writing meta info in the optimal order + ((MP4RootAtom*)m_pRootAtom)->BeginOptimalWrite(); + + // write data in optimal order + RewriteMdat(pReadFile, m_pFile); + + // finish writing + ((MP4RootAtom*)m_pRootAtom)->FinishOptimalWrite(); + + // cleanup + fclose(m_pFile); + m_pFile = NULL; + fclose(pReadFile); + + // move temporary file into place + if (newFileName == NULL) { + Rename(m_fileName, orgFileName); + } +} + +void MP4File::RewriteMdat(FILE* pReadFile, FILE* pWriteFile) +{ + u_int32_t numTracks = m_pTracks.Size(); + + MP4ChunkId* chunkIds = new MP4ChunkId[numTracks]; + MP4ChunkId* maxChunkIds = new MP4ChunkId[numTracks]; + MP4Timestamp* nextChunkTimes = new MP4Timestamp[numTracks]; + + for (u_int32_t i = 0; i < numTracks; i++) { + chunkIds[i] = 1; + maxChunkIds[i] = m_pTracks[i]->GetNumberOfChunks(); + nextChunkTimes[i] = MP4_INVALID_TIMESTAMP; + } + + while (true) { + u_int32_t nextTrackIndex = (u_int32_t)-1; + MP4Timestamp nextTime = MP4_INVALID_TIMESTAMP; + + for (u_int32_t i = 0; i < numTracks; i++) { + if (chunkIds[i] > maxChunkIds[i]) { + continue; + } + + if (nextChunkTimes[i] == MP4_INVALID_TIMESTAMP) { + MP4Timestamp chunkTime = + m_pTracks[i]->GetChunkTime(chunkIds[i]); + + nextChunkTimes[i] = MP4ConvertTime(chunkTime, + m_pTracks[i]->GetTimeScale(), GetTimeScale()); + } + + // time is not earliest so far + if (nextChunkTimes[i] > nextTime) { + continue; + } + + // prefer hint tracks to media tracks if times are equal + if (nextChunkTimes[i] == nextTime + && strcmp(m_pTracks[i]->GetType(), MP4_HINT_TRACK_TYPE)) { + continue; + } + + // this is our current choice of tracks + nextTime = nextChunkTimes[i]; + nextTrackIndex = i; + } + + if (nextTrackIndex == (u_int32_t)-1) { + break; + } + + // point into original mp4 file for read chunk call + m_pFile = pReadFile; + m_mode = 'r'; + + u_int8_t* pChunk; + u_int32_t chunkSize; + + m_pTracks[nextTrackIndex]-> + ReadChunk(chunkIds[nextTrackIndex], &pChunk, &chunkSize); + + // point back at the new mp4 file for write chunk + m_pFile = pWriteFile; + m_mode = 'w'; + + m_pTracks[nextTrackIndex]-> + RewriteChunk(chunkIds[nextTrackIndex], pChunk, chunkSize); + + MP4Free(pChunk); + + chunkIds[nextTrackIndex]++; + nextChunkTimes[nextTrackIndex] = MP4_INVALID_TIMESTAMP; + } + + delete [] chunkIds; + delete [] maxChunkIds; + delete [] nextChunkTimes; +} + +void MP4File::Open(const char* fmode) +{ + ASSERT(m_pFile == NULL); + +#ifdef O_LARGEFILE + // UGH! fopen doesn't open a file in 64-bit mode, period. + // So we need to use open() and then fdopen() + int fd; + int flags = O_LARGEFILE; + + if (strchr(fmode, '+')) { + flags |= O_CREAT | O_RDWR; + if (fmode[0] == 'w') { + flags |= O_TRUNC; + } + } else { + if (fmode[0] == 'w') { + flags |= O_CREAT | O_TRUNC | O_WRONLY; + } else { + flags |= O_RDONLY; + } + } + fd = open(m_fileName, flags, 0666); + + if (fd >= 0) { + m_pFile = fdopen(fd, fmode); + } +#else + m_pFile = fopen(m_fileName, fmode); +#endif + if (m_pFile == NULL) { + throw new MP4Error(errno, "failed", "MP4Open"); + } + + if (m_mode == 'r') { + struct stat s; + if (fstat(fileno(m_pFile), &s) < 0) { + throw new MP4Error(errno, "stat failed", "MP4Open"); + } + m_orgFileSize = m_fileSize = s.st_size; + } else { + m_orgFileSize = m_fileSize = 0; + } +} + +void MP4File::ReadFromFile() +{ + // ensure we start at beginning of file + SetPosition(0); + + // create a new root atom + ASSERT(m_pRootAtom == NULL); + m_pRootAtom = MP4Atom::CreateAtom(NULL); + + u_int64_t fileSize = GetSize(); + + m_pRootAtom->SetFile(this); + m_pRootAtom->SetStart(0); + m_pRootAtom->SetSize(fileSize); + m_pRootAtom->SetEnd(fileSize); + + m_pRootAtom->Read(); + + // create MP4Track's for any tracks in the file + GenerateTracks(); +} + +void MP4File::GenerateTracks() +{ + u_int32_t trackIndex = 0; + + while (true) { + char trackName[32]; + snprintf(trackName, sizeof(trackName), "moov.trak[%u]", trackIndex); + + // find next trak atom + MP4Atom* pTrakAtom = m_pRootAtom->FindAtom(trackName); + + // done, no more trak atoms + if (pTrakAtom == NULL) { + break; + } + + // find track id property + MP4Integer32Property* pTrackIdProperty = NULL; + pTrakAtom->FindProperty( + "trak.tkhd.trackId", + (MP4Property**)&pTrackIdProperty); + + // find track type property + MP4StringProperty* pTypeProperty = NULL; + pTrakAtom->FindProperty( + "trak.mdia.hdlr.handlerType", + (MP4Property**)&pTypeProperty); + + // ensure we have the basics properties + if (pTrackIdProperty && pTypeProperty) { + + m_trakIds.Add(pTrackIdProperty->GetValue()); + + MP4Track* pTrack = NULL; + try { + if (!strcmp(pTypeProperty->GetValue(), MP4_HINT_TRACK_TYPE)) { + pTrack = new MP4RtpHintTrack(this, pTrakAtom); + } else { + pTrack = new MP4Track(this, pTrakAtom); + } + m_pTracks.Add(pTrack); + } + catch (MP4Error* e) { + VERBOSE_ERROR(m_verbosity, e->Print()); + delete e; + } + + // remember when we encounter the OD track + if (pTrack && !strcmp(pTrack->GetType(), MP4_OD_TRACK_TYPE)) { + if (m_odTrackId == MP4_INVALID_TRACK_ID) { + m_odTrackId = pTrackIdProperty->GetValue(); + } else { + VERBOSE_READ(GetVerbosity(), + printf("Warning: multiple OD tracks present\n")); + } + } + } else { + m_trakIds.Add(0); + } + + trackIndex++; + } +} + +void MP4File::CacheProperties() +{ + FindIntegerProperty("moov.mvhd.modificationTime", + (MP4Property**)&m_pModificationProperty); + + FindIntegerProperty("moov.mvhd.timeScale", + (MP4Property**)&m_pTimeScaleProperty); + + FindIntegerProperty("moov.mvhd.duration", + (MP4Property**)&m_pDurationProperty); +} + +void MP4File::BeginWrite() +{ + m_pRootAtom->BeginWrite(); +} + +void MP4File::FinishWrite() +{ + // for all tracks, flush chunking buffers + for (u_int32_t i = 0; i < m_pTracks.Size(); i++) { + ASSERT(m_pTracks[i]); + m_pTracks[i]->FinishWrite(); + } + + // ask root atom to write + m_pRootAtom->FinishWrite(); + + // check if file shrunk, e.g. we deleted a track + if (GetSize() < m_orgFileSize) { + // just use a free atom to mark unused space + // MP4Optimize() should be used to clean up this space + MP4Atom* pFreeAtom = MP4Atom::CreateAtom("free"); + ASSERT(pFreeAtom); + pFreeAtom->SetFile(this); + int64_t size = m_orgFileSize - (m_fileSize + 8); + if (size < 0) size = 0; + pFreeAtom->SetSize(size); + pFreeAtom->Write(); + delete pFreeAtom; + } +} + +MP4Duration MP4File::UpdateDuration(MP4Duration duration) +{ + MP4Duration currentDuration = GetDuration(); + if (duration > currentDuration) { + SetDuration(duration); + return duration; + } + return currentDuration; +} + +void MP4File::Dump(FILE* pDumpFile, bool dumpImplicits) +{ + if (pDumpFile == NULL) { + pDumpFile = stdout; + } + + fprintf(pDumpFile, "Dumping %s meta-information...\n", m_fileName); + m_pRootAtom->Dump(pDumpFile, 0, dumpImplicits); +} + +void MP4File::Close() +{ + if (m_mode == 'w') { + SetIntegerProperty("moov.mvhd.modificationTime", + MP4GetAbsTimestamp()); + + FinishWrite(); + } + + fclose(m_pFile); + m_pFile = NULL; +} + +const char* MP4File::TempFileName() +{ + // there are so many attempts in libc to get this right + // that for portablity reasons, it's best just to roll our own +#ifndef _WIN32 + u_int32_t i; + for (i = getpid(); i < 0xFFFFFFFF; i++) { + sprintf(m_tempFileName, "./tmp%u.mp4", i); + if (access(m_tempFileName, F_OK) != 0) { + break; + } + } + if (i == 0xFFFFFFFF) { + throw new MP4Error("can't create temporary file", "TempFileName"); + } +#else + GetTempFileName(".", // dir. for temp. files + "mp4", // temp. filename prefix + 0, // create unique name + m_tempFileName); // buffer for name +#endif + + return m_tempFileName; +} + +void MP4File::Rename(const char* oldFileName, const char* newFileName) +{ + int rc; + +#ifdef _WIN32 + rc = remove(newFileName); + if (rc == 0) { + rc = rename(oldFileName, newFileName); + } +#else + rc = rename(oldFileName, newFileName); +#endif + if (rc != 0) { + throw new MP4Error(errno, "can't overwrite existing file", "Rename"); + } +} + +void MP4File::ProtectWriteOperation(char* where) +{ + if (m_mode == 'r') { + throw new MP4Error("operation not permitted in read mode", where); + } +} + +MP4Track* MP4File::GetTrack(MP4TrackId trackId) +{ + return m_pTracks[FindTrackIndex(trackId)]; +} + +MP4Atom* MP4File::FindAtom(const char* name) +{ + MP4Atom* pAtom = NULL; + if (!name || !strcmp(name, "")) { + pAtom = m_pRootAtom; + } else { + pAtom = m_pRootAtom->FindAtom(name); + } + return pAtom; +} + +MP4Atom* MP4File::AddChildAtom( + const char* parentName, + const char* childName) +{ + return AddChildAtom(FindAtom(parentName), childName); +} + +MP4Atom* MP4File::AddChildAtom( + MP4Atom* pParentAtom, + const char* childName) +{ + return InsertChildAtom(pParentAtom, childName, + pParentAtom->GetNumberOfChildAtoms()); +} + +MP4Atom* MP4File::InsertChildAtom( + const char* parentName, + const char* childName, + u_int32_t index) +{ + return InsertChildAtom(FindAtom(parentName), childName, index); +} + +MP4Atom* MP4File::InsertChildAtom( + MP4Atom* pParentAtom, + const char* childName, + u_int32_t index) +{ + MP4Atom* pChildAtom = MP4Atom::CreateAtom(childName); + + ASSERT(pParentAtom); + pParentAtom->InsertChildAtom(pChildAtom, index); + + pChildAtom->Generate(); + + return pChildAtom; +} + +MP4Atom* MP4File::AddDescendantAtoms( + const char* ancestorName, + const char* descendantNames) +{ + return AddDescendantAtoms(FindAtom(ancestorName), descendantNames); +} + +MP4Atom* MP4File::AddDescendantAtoms( + MP4Atom* pAncestorAtom, const char* descendantNames) +{ + ASSERT(pAncestorAtom); + + MP4Atom* pParentAtom = pAncestorAtom; + MP4Atom* pChildAtom = NULL; + + while (true) { + char* childName = MP4NameFirst(descendantNames); + + if (childName == NULL) { + break; + } + + descendantNames = MP4NameAfterFirst(descendantNames); + + pChildAtom = pParentAtom->FindChildAtom(childName); + + if (pChildAtom == NULL) { + pChildAtom = AddChildAtom(pParentAtom, childName); + } + + pParentAtom = pChildAtom; + + MP4Free(childName); + } + + return pChildAtom; +} + +bool MP4File::FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (pIndex) { + *pIndex = 0; // set the default answer for index + } + + return m_pRootAtom->FindProperty(name, ppProperty, pIndex); +} + +void MP4File::FindIntegerProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property - %s", "MP4File::FindIntegerProperty", name); + } + + switch ((*ppProperty)->GetType()) { + case Integer8Property: + case Integer16Property: + case Integer24Property: + case Integer32Property: + case Integer64Property: + break; + default: + throw new MP4Error("type mismatch - property %s type %d", "MP4File::FindIntegerProperty", name, (*ppProperty)->GetType()); + } +} + +u_int64_t MP4File::GetIntegerProperty(const char* name) +{ + MP4Property* pProperty; + u_int32_t index; + + FindIntegerProperty(name, &pProperty, &index); + + return ((MP4IntegerProperty*)pProperty)->GetValue(index); +} + +void MP4File::SetIntegerProperty(const char* name, u_int64_t value) +{ + ProtectWriteOperation("SetIntegerProperty"); + + MP4Property* pProperty = NULL; + u_int32_t index = 0; + + FindIntegerProperty(name, &pProperty, &index); + + ((MP4IntegerProperty*)pProperty)->SetValue(value, index); +} + +void MP4File::FindFloatProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property - %s", "MP4File::FindFloatProperty", name); + } + if ((*ppProperty)->GetType() != Float32Property) { + throw new MP4Error("type mismatch - property %s type %d", + "MP4File::FindFloatProperty", + name, + (*ppProperty)->GetType()); + } +} + +float MP4File::GetFloatProperty(const char* name) +{ + MP4Property* pProperty; + u_int32_t index; + + FindFloatProperty(name, &pProperty, &index); + + return ((MP4Float32Property*)pProperty)->GetValue(index); +} + +void MP4File::SetFloatProperty(const char* name, float value) +{ + ProtectWriteOperation("SetFloatProperty"); + + MP4Property* pProperty; + u_int32_t index; + + FindFloatProperty(name, &pProperty, &index); + + ((MP4Float32Property*)pProperty)->SetValue(value, index); +} + +void MP4File::FindStringProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property - %s", "MP4File::FindStringProperty", name); + } + if ((*ppProperty)->GetType() != StringProperty) { + throw new MP4Error("type mismatch - property %s type %d", "MP4File::FindStringProperty", + name, (*ppProperty)->GetType()); + } +} + +const char* MP4File::GetStringProperty(const char* name) +{ + MP4Property* pProperty; + u_int32_t index; + + FindStringProperty(name, &pProperty, &index); + + return ((MP4StringProperty*)pProperty)->GetValue(index); +} + +void MP4File::SetStringProperty(const char* name, const char* value) +{ + ProtectWriteOperation("SetStringProperty"); + + MP4Property* pProperty; + u_int32_t index; + + FindStringProperty(name, &pProperty, &index); + + ((MP4StringProperty*)pProperty)->SetValue(value, index); +} + +void MP4File::FindBytesProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (!FindProperty(name, ppProperty, pIndex)) { + throw new MP4Error("no such property %s", "MP4File::FindBytesProperty", name); + } + if ((*ppProperty)->GetType() != BytesProperty) { + throw new MP4Error("type mismatch - property %s - type %d", "MP4File::FindBytesProperty", name, (*ppProperty)->GetType()); + } +} + +void MP4File::GetBytesProperty(const char* name, + u_int8_t** ppValue, u_int32_t* pValueSize) +{ + MP4Property* pProperty; + u_int32_t index; + + FindBytesProperty(name, &pProperty, &index); + + ((MP4BytesProperty*)pProperty)->GetValue(ppValue, pValueSize, index); +} + +void MP4File::SetBytesProperty(const char* name, + const u_int8_t* pValue, u_int32_t valueSize) +{ + ProtectWriteOperation("SetBytesProperty"); + + MP4Property* pProperty; + u_int32_t index; + + FindBytesProperty(name, &pProperty, &index); + + ((MP4BytesProperty*)pProperty)->SetValue(pValue, valueSize, index); +} + + +// track functions + +MP4TrackId MP4File::AddTrack(const char* type, u_int32_t timeScale) +{ + ProtectWriteOperation("AddTrack"); + + // create and add new trak atom + MP4Atom* pTrakAtom = AddChildAtom("moov", "trak"); + + // allocate a new track id + MP4TrackId trackId = AllocTrackId(); + + m_trakIds.Add(trackId); + + // set track id + MP4Integer32Property* pInteger32Property = NULL; + pTrakAtom->FindProperty( + "trak.tkhd.trackId", (MP4Property**)&pInteger32Property); + ASSERT(pInteger32Property); + pInteger32Property->SetValue(trackId); + + // set track type + const char* normType = MP4NormalizeTrackType(type, m_verbosity); + + // sanity check for user defined types + if (strlen(normType) > 4) { + VERBOSE_WARNING(m_verbosity, + printf("AddTrack: type truncated to four characters\n")); + // StringProperty::SetValue() will do the actual truncation + } + + MP4StringProperty* pStringProperty = NULL; + pTrakAtom->FindProperty( + "trak.mdia.hdlr.handlerType", (MP4Property**)&pStringProperty); + ASSERT(pStringProperty); + pStringProperty->SetValue(normType); + + // set track time scale + pInteger32Property = NULL; + pTrakAtom->FindProperty( + "trak.mdia.mdhd.timeScale", (MP4Property**)&pInteger32Property); + ASSERT(pInteger32Property); + pInteger32Property->SetValue(timeScale ? timeScale : 1000); + + // now have enough to create MP4Track object + MP4Track* pTrack = NULL; + if (!strcmp(normType, MP4_HINT_TRACK_TYPE)) { + pTrack = new MP4RtpHintTrack(this, pTrakAtom); + } else { + pTrack = new MP4Track(this, pTrakAtom); + } + m_pTracks.Add(pTrack); + + // mark non-hint tracks as enabled + if (strcmp(normType, MP4_HINT_TRACK_TYPE)) { + SetTrackIntegerProperty(trackId, "tkhd.flags", 1); + } + + // mark track as contained in this file + // LATER will provide option for external data references + AddDataReference(trackId, NULL); + + return trackId; +} + +void MP4File::AddTrackToIod(MP4TrackId trackId) +{ + MP4DescriptorProperty* pDescriptorProperty = NULL; + m_pRootAtom->FindProperty("moov.iods.esIds", + (MP4Property**)&pDescriptorProperty); + ASSERT(pDescriptorProperty); + + MP4Descriptor* pDescriptor = + pDescriptorProperty->AddDescriptor(MP4ESIDIncDescrTag); + ASSERT(pDescriptor); + + MP4Integer32Property* pIdProperty = NULL; + pDescriptor->FindProperty("id", + (MP4Property**)&pIdProperty); + ASSERT(pIdProperty); + + pIdProperty->SetValue(trackId); +} + + void MP4File::RemoveTrackFromIod(MP4TrackId trackId, bool shallHaveIods) +{ + MP4DescriptorProperty* pDescriptorProperty = NULL; + m_pRootAtom->FindProperty("moov.iods.esIds", + (MP4Property**)&pDescriptorProperty); + + if (shallHaveIods) { + ASSERT(pDescriptorProperty); + } else { + if (!pDescriptorProperty) { + return; + } + } + + for (u_int32_t i = 0; i < pDescriptorProperty->GetCount(); i++) { + /* static */char name[32]; + snprintf(name, sizeof(name), "esIds[%u].id", i); + + MP4Integer32Property* pIdProperty = NULL; + pDescriptorProperty->FindProperty(name, + (MP4Property**)&pIdProperty); + ASSERT(pIdProperty); + + if (pIdProperty->GetValue() == trackId) { + pDescriptorProperty->DeleteDescriptor(i); + break; + } + } +} + +void MP4File::AddTrackToOd(MP4TrackId trackId) +{ + if (!m_odTrackId) { + return; + } + + AddTrackReference(MakeTrackName(m_odTrackId, "tref.mpod"), trackId); +} + +void MP4File::RemoveTrackFromOd(MP4TrackId trackId) +{ + if (!m_odTrackId) { + return; + } + + RemoveTrackReference(MakeTrackName(m_odTrackId, "tref.mpod"), trackId); +} + +void MP4File::GetTrackReferenceProperties(const char* trefName, + MP4Property** ppCountProperty, MP4Property** ppTrackIdProperty) +{ + char propName[1024]; + + snprintf(propName, sizeof(propName), "%s.%s", trefName, "entryCount"); + m_pRootAtom->FindProperty(propName, ppCountProperty); + ASSERT(*ppCountProperty); + + snprintf(propName, sizeof(propName), "%s.%s", trefName, "entries.trackId"); + m_pRootAtom->FindProperty(propName, ppTrackIdProperty); + ASSERT(*ppTrackIdProperty); +} + +void MP4File::AddTrackReference(const char* trefName, MP4TrackId refTrackId) +{ + MP4Integer32Property* pCountProperty = NULL; + MP4Integer32Property* pTrackIdProperty = NULL; + + GetTrackReferenceProperties(trefName, + (MP4Property**)&pCountProperty, + (MP4Property**)&pTrackIdProperty); + + pTrackIdProperty->AddValue(refTrackId); + pCountProperty->IncrementValue(); +} + +u_int32_t MP4File::FindTrackReference(const char* trefName, + MP4TrackId refTrackId) +{ + MP4Integer32Property* pCountProperty = NULL; + MP4Integer32Property* pTrackIdProperty = NULL; + + GetTrackReferenceProperties(trefName, + (MP4Property**)&pCountProperty, + (MP4Property**)&pTrackIdProperty); + + for (u_int32_t i = 0; i < pCountProperty->GetValue(); i++) { + if (refTrackId == pTrackIdProperty->GetValue(i)) { + return i + 1; // N.B. 1 not 0 based index + } + } + return 0; +} + +void MP4File::RemoveTrackReference(const char* trefName, MP4TrackId refTrackId) +{ + MP4Integer32Property* pCountProperty = NULL; + MP4Integer32Property* pTrackIdProperty = NULL; + + GetTrackReferenceProperties(trefName, + (MP4Property**)&pCountProperty, + (MP4Property**)&pTrackIdProperty); + + for (u_int32_t i = 0; i < pCountProperty->GetValue(); i++) { + if (refTrackId == pTrackIdProperty->GetValue(i)) { + pTrackIdProperty->DeleteValue(i); + pCountProperty->IncrementValue(-1); + } + } +} + +void MP4File::AddDataReference(MP4TrackId trackId, const char* url) +{ + MP4Atom* pDrefAtom = + FindAtom(MakeTrackName(trackId, "mdia.minf.dinf.dref")); + ASSERT(pDrefAtom); + + MP4Integer32Property* pCountProperty = NULL; + pDrefAtom->FindProperty("dref.entryCount", + (MP4Property**)&pCountProperty); + ASSERT(pCountProperty); + pCountProperty->IncrementValue(); + + MP4Atom* pUrlAtom = AddChildAtom(pDrefAtom, "url "); + + if (url && url[0] != '\0') { + pUrlAtom->SetFlags(pUrlAtom->GetFlags() & 0xFFFFFE); + + MP4StringProperty* pUrlProperty = NULL; + pUrlAtom->FindProperty("url .location", + (MP4Property**)&pUrlProperty); + ASSERT(pUrlProperty); + pUrlProperty->SetValue(url); + } else { + pUrlAtom->SetFlags(pUrlAtom->GetFlags() | 1); + } +} + +MP4TrackId MP4File::AddSystemsTrack(const char* type) +{ + const char* normType = MP4NormalizeTrackType(type, m_verbosity); + + // TBD if user type, fix name to four chars, and warn + + MP4TrackId trackId = AddTrack(type, MP4_MSECS_TIME_SCALE); + + InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0); + + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4s"); + + // stsd is a unique beast in that it has a count of the number + // of child atoms that needs to be incremented after we add the mp4s atom + MP4Integer32Property* pStsdCountProperty; + FindIntegerProperty( + MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), + (MP4Property**)&pStsdCountProperty); + pStsdCountProperty->IncrementValue(); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4s.esds.ESID", +#if 0 + // note - for a file, these values need to + // be 0 - wmay - 04/16/2003 + trackId +#else + 0 +#endif + ); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId", + MP4SystemsV1ObjectType); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.streamType", + ConvertTrackTypeToStreamType(normType)); + + return trackId; +} + +MP4TrackId MP4File::AddODTrack() +{ + // until a demonstrated need emerges + // we limit ourselves to one object description track + if (m_odTrackId != MP4_INVALID_TRACK_ID) { + throw new MP4Error("object description track already exists", + "AddObjectDescriptionTrack"); + } + + m_odTrackId = AddSystemsTrack(MP4_OD_TRACK_TYPE); + + AddTrackToIod(m_odTrackId); + + AddDescendantAtoms(MakeTrackName(m_odTrackId, NULL), "tref.mpod"); + + return m_odTrackId; +} + +MP4TrackId MP4File::AddSceneTrack() +{ + MP4TrackId trackId = AddSystemsTrack(MP4_SCENE_TRACK_TYPE); + + AddTrackToIod(trackId); + AddTrackToOd(trackId); + + return trackId; +} + +// NULL terminated list of brands which require the IODS atom +char *brandsWithIods[] = { "mp42", + "isom", + NULL}; + +bool MP4File::ShallHaveIods() +{ + u_int32_t compatibleBrandsCount; + MP4StringProperty *pMajorBrandProperty; + + MP4Atom* ftypAtom = m_pRootAtom->FindAtom("ftyp"); + if (ftypAtom == NULL) return false; + + // Check the major brand + ftypAtom->FindProperty( + "ftyp.majorBrand", + (MP4Property**)&pMajorBrandProperty); + ASSERT(pMajorBrandProperty); + for(u_int32_t j = 0 ; brandsWithIods[j] != NULL ; j++) { + if (!strcasecmp( ((MP4StringProperty*)pMajorBrandProperty)->GetValue(), + brandsWithIods[j])) + return true; + } + + // Check the compatible brands + MP4Integer32Property* pCompatibleBrandsCountProperty; + ftypAtom->FindProperty( + "ftyp.compatibleBrandsCount", + (MP4Property**)&pCompatibleBrandsCountProperty); + ASSERT(pCompatibleBrandsCountProperty); + + compatibleBrandsCount = pCompatibleBrandsCountProperty->GetValue(); + + MP4TableProperty* pCompatibleBrandsProperty; + ftypAtom->FindProperty( + "ftyp.compatibleBrands", + (MP4Property**)&pCompatibleBrandsProperty); + + MP4StringProperty* pBrandProperty = (MP4StringProperty*)pCompatibleBrandsProperty->GetProperty(0); + ASSERT(pBrandProperty); + + for(u_int32_t i = 0 ; i < compatibleBrandsCount ; i++) { + for(u_int32_t j = 0 ; brandsWithIods[j] != NULL ; j++) { + if (!strcasecmp(pBrandProperty->GetValue(i), brandsWithIods[j])) + return true; + } + } + + return false; +} + +void MP4File::SetAmrVendor( + MP4TrackId trackId, + u_int32_t vendor) +{ + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.damr.vendor", + vendor); +} + +void MP4File::SetAmrDecoderVersion( + MP4TrackId trackId, + u_int8_t decoderVersion) +{ + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.damr.decoderVersion", + decoderVersion); +} + +void MP4File::SetAmrModeSet( + MP4TrackId trackId, + u_int16_t modeSet) +{ + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.damr.modeSet", + modeSet); +} +uint16_t MP4File::GetAmrModeSet(MP4TrackId trackId) +{ + return GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.damr.modeSet"); +} + +MP4TrackId MP4File::AddAmrAudioTrack( + u_int32_t timeScale, + u_int16_t modeSet, + u_int8_t modeChangePeriod, + u_int8_t framesPerSample, + bool isAmrWB) +{ + + u_int32_t fixedSampleDuration = (timeScale * 20)/1000; // 20mSec/Sample + + MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale); + + AddTrackToOd(trackId); + + SetTrackFloatProperty(trackId, "tkhd.volume", 1.0); + + InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0); + + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), isAmrWB ? "sawb" : "samr"); + + // stsd is a unique beast in that it has a count of the number + // of child atoms that needs to be incremented after we add the mp4a atom + MP4Integer32Property* pStsdCountProperty; + FindIntegerProperty( + MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), + (MP4Property**)&pStsdCountProperty); + pStsdCountProperty->IncrementValue(); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.timeScale", + timeScale); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.damr.modeSet", + modeSet); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.damr.modeChangePeriod", + modeChangePeriod); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.damr.framesPerSample", + framesPerSample); + + + m_pTracks[FindTrackIndex(trackId)]-> + SetFixedSampleDuration(fixedSampleDuration); + + return trackId; +} + +MP4TrackId MP4File::AddAudioTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int8_t audioType) +{ + MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale); + + AddTrackToOd(trackId); + + SetTrackFloatProperty(trackId, "tkhd.volume", 1.0); + + InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0); + + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4a"); + + // stsd is a unique beast in that it has a count of the number + // of child atoms that needs to be incremented after we add the mp4a atom + MP4Integer32Property* pStsdCountProperty; + FindIntegerProperty( + MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), + (MP4Property**)&pStsdCountProperty); + pStsdCountProperty->IncrementValue(); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4a.timeScale", timeScale); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4a.esds.ESID", +#if 0 + // note - for a file, these values need to + // be 0 - wmay - 04/16/2003 + trackId +#else + 0 +#endif + ); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId", + audioType); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.streamType", + MP4AudioStreamType); + + m_pTracks[FindTrackIndex(trackId)]-> + SetFixedSampleDuration(sampleDuration); + + return trackId; +} + +MP4TrackId MP4File::AddEncAudioTrack(u_int32_t timeScale, + MP4Duration sampleDuration, + u_int8_t audioType, + u_int32_t scheme_type, + u_int16_t scheme_version, + u_int8_t key_ind_len, + u_int8_t iv_len, + bool selective_enc, + char *kms_uri + ) +{ + u_int32_t original_fmt = 0; + + MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale); + + AddTrackToOd(trackId); + + SetTrackFloatProperty(trackId, "tkhd.volume", 1.0); + + InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0); + + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "enca"); + + // stsd is a unique beast in that it has a count of the number + // of child atoms that needs to be incremented after we add the enca atom + MP4Integer32Property* pStsdCountProperty; + FindIntegerProperty(MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), + (MP4Property**)&pStsdCountProperty); + pStsdCountProperty->IncrementValue(); + + + /* set all the ismacryp-specific values */ + // original format is mp4a + original_fmt = ('m'<<24 | 'p'<<16 | '4'<<8 | 'a'); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.sinf.frma.data-format", + original_fmt); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.sinf.schm.scheme_type", + scheme_type); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.sinf.schm.scheme_version", + scheme_version); + + SetTrackStringProperty(trackId, + "mdia.minf.stbl.stsd.enca.sinf.schi.iKMS.kms_URI", + kms_uri); + if (kms_uri != NULL) { + free(kms_uri); + } + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.selective-encryption", + selective_enc); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.key-indicator-length", + key_ind_len); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.IV-length", + iv_len); + /* end ismacryp */ + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.timeScale", timeScale); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.esds.ESID", +#if 0 + // note - for a file, these values need to + // be 0 - wmay - 04/16/2003 + trackId +#else + 0 +#endif + ); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.esds.decConfigDescr.objectTypeId", + audioType); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.enca.esds.decConfigDescr.streamType", + MP4AudioStreamType); + + m_pTracks[FindTrackIndex(trackId)]-> + SetFixedSampleDuration(sampleDuration); + + return trackId; +} + +MP4TrackId MP4File::AddCntlTrackDefault (uint32_t timeScale, + MP4Duration sampleDuration, + const char *type) +{ + MP4TrackId trackId = AddTrack(MP4_CNTL_TRACK_TYPE, timeScale); + + InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0); + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), type); + + // stsd is a unique beast in that it has a count of the number + // of child atoms that needs to be incremented after we add the mp4v atom + MP4Integer32Property* pStsdCountProperty; + FindIntegerProperty( + MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), + (MP4Property**)&pStsdCountProperty); + pStsdCountProperty->IncrementValue(); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsz.sampleSize", sampleDuration); + + m_pTracks[FindTrackIndex(trackId)]-> + SetFixedSampleDuration(sampleDuration); + + return trackId; +} + +MP4TrackId MP4File::AddHrefTrack (uint32_t timeScale, + MP4Duration sampleDuration) +{ + MP4TrackId trackId = AddCntlTrackDefault(timeScale, sampleDuration, "href"); + + return trackId; +} + +MP4TrackId MP4File::AddVideoTrackDefault( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + const char *videoType) +{ + MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale); + + AddTrackToOd(trackId); + + SetTrackFloatProperty(trackId, "tkhd.width", width); + SetTrackFloatProperty(trackId, "tkhd.height", height); + + InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0); + + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), videoType); + + // stsd is a unique beast in that it has a count of the number + // of child atoms that needs to be incremented after we add the mp4v atom + MP4Integer32Property* pStsdCountProperty; + FindIntegerProperty( + MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), + (MP4Property**)&pStsdCountProperty); + pStsdCountProperty->IncrementValue(); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsz.sampleSize", sampleDuration); + + m_pTracks[FindTrackIndex(trackId)]-> + SetFixedSampleDuration(sampleDuration); + + return trackId; +} +MP4TrackId MP4File::AddMP4VideoTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t videoType) +{ + MP4TrackId trackId = AddVideoTrackDefault(timeScale, + sampleDuration, + width, + height, + "mp4v"); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4v.width", width); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4v.height", height); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4v.esds.ESID", +#if 0 + // note - for a file, these values need to + // be 0 - wmay - 04/16/2003 + trackId +#else + 0 +#endif + ); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId", + videoType); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.streamType", + MP4VisualStreamType); + + return trackId; +} + +MP4TrackId MP4File::AddEncVideoTrack(u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t videoType, + u_int32_t scheme_type, + u_int16_t scheme_version, + u_int8_t key_ind_len, + u_int8_t iv_len, + bool selective_enc, + char *kms_uri + ) +{ + u_int32_t original_fmt = 0; + + MP4TrackId trackId = AddVideoTrackDefault(timeScale, + sampleDuration, + width, + height, + "encv"); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.width", width); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.height", height); + + /* set all the ismacryp-specific values */ + // original format is mp4v + original_fmt = ATOMID("mp4v"); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.sinf.frma.data-format", + original_fmt); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_type", + scheme_type); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_version", + scheme_version); + + SetTrackStringProperty(trackId, + "mdia.minf.stbl.stsd.encv.sinf.schi.iKMS.kms_URI", + kms_uri); + if (kms_uri != NULL) { + free(kms_uri); + } + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.selective-encryption", + selective_enc); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.key-indicator-length", + key_ind_len); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.IV-length", + iv_len); + /* end ismacryp */ + + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.esds.ESID", +#if 0 + // note - for a file, these values need to + // be 0 - wmay - 04/16/2003 + trackId +#else + 0 +#endif + ); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.esds.decConfigDescr.objectTypeId", + videoType); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.encv.esds.decConfigDescr.streamType", + MP4VisualStreamType); + + return trackId; +} + +MP4TrackId MP4File::AddH264VideoTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + uint8_t AVCProfileIndication, + uint8_t profile_compat, + uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne) +{ + MP4TrackId trackId = AddVideoTrackDefault(timeScale, + sampleDuration, + width, + height, + "avc1"); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.avc1.width", width); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.avc1.height", height); + + /* shouldn't need this + AddChildAtom(MakeTrackName(trackId, + "mdia.minf.stbl.stsd.avc1"), + "avcC"); + */ + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.avc1.avcC.AVCProfileIndication", + AVCProfileIndication); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.avc1.avcC.profile_compatibility", + profile_compat); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.avc1.avcC.AVCLevelIndication", + AVCLevelIndication); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.avc1.avcC.lengthSizeMinusOne", + sampleLenFieldSizeMinusOne); + + + return trackId; +} + +bool MP4File::AddH264SequenceParameterSet (MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen) +{ + MP4Atom *avcCAtom = + FindAtom(MakeTrackName(trackId, + "mdia.minf.stbl.stsd.avc1.avcC")); + MP4BitfieldProperty *pCount; + MP4Integer16Property *pLength; + MP4BytesProperty *pUnit; + if ((avcCAtom->FindProperty("avcC.numOfSequenceParameterSets", + (MP4Property **)&pCount) == false) || + (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetLength", + (MP4Property **)&pLength) == false) || + (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetNALUnit", + (MP4Property **)&pUnit) == false)) { + VERBOSE_ERROR(m_verbosity, WARNING("Could not find avcC properties")); + return false; + } + uint32_t count = pCount->GetValue(); + + if (count > 0) { + // see if we already exist + for (uint32_t index = 0; index < count; index++) { + if (pLength->GetValue(index) == sequenceLen) { + uint8_t *seq; + uint32_t seqlen; + pUnit->GetValue(&seq, &seqlen, index); + if (memcmp(seq, pSequence, sequenceLen) == 0) { + free(seq); + return true; + } + free(seq); + } + } + } + pLength->AddValue(sequenceLen); + pUnit->AddValue(pSequence, sequenceLen); + pCount->IncrementValue(); + + return true; +} +bool MP4File::AddH264PictureParameterSet (MP4TrackId trackId, + const uint8_t *pPict, + uint16_t pictLen) +{ + MP4Atom *avcCAtom = + FindAtom(MakeTrackName(trackId, + "mdia.minf.stbl.stsd.avc1.avcC")); + MP4Integer8Property *pCount; + MP4Integer16Property *pLength; + MP4BytesProperty *pUnit; + if ((avcCAtom->FindProperty("avcC.numOfPictureParameterSets", + (MP4Property **)&pCount) == false) || + (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetLength", + (MP4Property **)&pLength) == false) || + (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetNALUnit", + (MP4Property **)&pUnit) == false)) { + VERBOSE_ERROR(m_verbosity, + WARNING("Could not find avcC picture table properties")); + return false; + } + uint32_t count = pCount->GetValue(); + + if (count > 0) { + // see if we already exist + for (uint32_t index = 0; index < count; index++) { + if (pLength->GetValue(index) == pictLen) { + uint8_t *seq; + uint32_t seqlen; + pUnit->GetValue(&seq, &seqlen, index); + if (memcmp(seq, pPict, pictLen) == 0) { + VERBOSE_WRITE(m_verbosity, + fprintf(stderr, "picture matches %d\n", index)); + free(seq); + return true; + } + free(seq); + } + } + } + pLength->AddValue(pictLen); + pUnit->AddValue(pPict, pictLen); + pCount->IncrementValue(); + VERBOSE_WRITE(m_verbosity, + fprintf(stderr, "new picture added %d\n", pCount->GetValue())); + + return true; +} +void MP4File::SetH263Vendor( + MP4TrackId trackId, + u_int32_t vendor) +{ + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.vendor", + vendor); +} + +void MP4File::SetH263DecoderVersion( + MP4TrackId trackId, + u_int8_t decoderVersion) +{ + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.decoderVersion", + decoderVersion); +} + +void MP4File::SetH263Bitrates( + MP4TrackId trackId, + u_int32_t avgBitrate, + u_int32_t maxBitrate) +{ + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.bitr.avgBitrate", + avgBitrate); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.bitr.maxBitrate", + maxBitrate); + +} + +MP4TrackId MP4File::AddH263VideoTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t h263Level, + u_int8_t h263Profile, + u_int32_t avgBitrate, + u_int32_t maxBitrate) + +{ + MP4TrackId trackId = AddVideoTrackDefault(timeScale, + sampleDuration, + width, + height, + "s263"); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.width", width); + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.height", height); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.h263Level", h263Level); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.h263Profile", h263Profile); + + // Add the bitr atom + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"), + "bitr"); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.bitr.avgBitrate", avgBitrate); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.s263.d263.bitr.maxBitrate", maxBitrate); + + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsz.sampleSize", sampleDuration); + + return trackId; + +} + +MP4TrackId MP4File::AddHintTrack(MP4TrackId refTrackId) +{ + // validate reference track id + FindTrackIndex(refTrackId); + + MP4TrackId trackId = + AddTrack(MP4_HINT_TRACK_TYPE, GetTrackTimeScale(refTrackId)); + + InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "hmhd", 0); + + AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "rtp "); + + // stsd is a unique beast in that it has a count of the number + // of child atoms that needs to be incremented after we add the rtp atom + MP4Integer32Property* pStsdCountProperty; + FindIntegerProperty( + MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"), + (MP4Property**)&pStsdCountProperty); + pStsdCountProperty->IncrementValue(); + + SetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.rtp .tims.timeScale", + GetTrackTimeScale(trackId)); + + AddDescendantAtoms(MakeTrackName(trackId, NULL), "tref.hint"); + + AddTrackReference(MakeTrackName(trackId, "tref.hint"), refTrackId); + + AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hnti.sdp "); + + AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hinf"); + + return trackId; +} + +void MP4File::DeleteTrack(MP4TrackId trackId) +{ + ProtectWriteOperation("MP4DeleteTrack"); + + u_int32_t trakIndex = FindTrakAtomIndex(trackId); + u_int16_t trackIndex = FindTrackIndex(trackId); + MP4Track* pTrack = m_pTracks[trackIndex]; + + MP4Atom* pTrakAtom = pTrack->GetTrakAtom(); + ASSERT(pTrakAtom); + + MP4Atom* pMoovAtom = FindAtom("moov"); + ASSERT(pMoovAtom); + + RemoveTrackFromIod(trackId, ShallHaveIods()); + RemoveTrackFromOd(trackId); + + if (trackId == m_odTrackId) { + m_odTrackId = 0; + } + + pMoovAtom->DeleteChildAtom(pTrakAtom); + + m_trakIds.Delete(trakIndex); + + m_pTracks.Delete(trackIndex); + + delete pTrack; + delete pTrakAtom; +} + +u_int32_t MP4File::GetNumberOfTracks(const char* type, u_int8_t subType) +{ + if (type == NULL) { + return m_pTracks.Size(); + } + + u_int32_t typeSeen = 0; + const char* normType = MP4NormalizeTrackType(type, m_verbosity); + + for (u_int32_t i = 0; i < m_pTracks.Size(); i++) { + if (!strcmp(normType, m_pTracks[i]->GetType())) { + if (subType) { + if (normType == MP4_AUDIO_TRACK_TYPE) { + if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) { + continue; + } + } else if (normType == MP4_VIDEO_TRACK_TYPE) { + if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) { + continue; + } + } + // else unknown subtype, ignore it + } + typeSeen++; + } + } + return typeSeen; +} + +MP4TrackId MP4File::AllocTrackId() +{ + MP4TrackId trackId = + GetIntegerProperty("moov.mvhd.nextTrackId"); + + if (trackId <= 0xFFFF) { + // check that nextTrackid is correct + try { + FindTrackIndex(trackId); + // ERROR, this trackId is in use + } + catch (MP4Error* e) { + // OK, this trackId is not in use, proceed + delete e; + SetIntegerProperty("moov.mvhd.nextTrackId", trackId + 1); + return trackId; + } + } + + // we need to search for a track id + for (trackId = 1; trackId <= 0xFFFF; trackId++) { + try { + FindTrackIndex(trackId); + // KEEP LOOKING, this trackId is in use + } + catch (MP4Error* e) { + // OK, this trackId is not in use, proceed + delete e; + return trackId; + } + } + + // extreme case where mp4 file has 2^16 tracks in it + throw new MP4Error("too many existing tracks", "AddTrack"); + return MP4_INVALID_TRACK_ID; // to keep MSVC happy +} + +MP4TrackId MP4File::FindTrackId(u_int16_t trackIndex, + const char* type, u_int8_t subType) +{ + if (type == NULL) { + return m_pTracks[trackIndex]->GetId(); + } + + u_int32_t typeSeen = 0; + const char* normType = MP4NormalizeTrackType(type, m_verbosity); + + for (u_int32_t i = 0; i < m_pTracks.Size(); i++) { + if (!strcmp(normType, m_pTracks[i]->GetType())) { + if (subType) { + if (normType == MP4_AUDIO_TRACK_TYPE) { + if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) { + continue; + } + } else if (normType == MP4_VIDEO_TRACK_TYPE) { + if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) { + continue; + } + } + // else unknown subtype, ignore it + } + + if (trackIndex == typeSeen) { + return m_pTracks[i]->GetId(); + } + + typeSeen++; + } + } + + throw new MP4Error("Track index doesn't exist - track %d type %s", + "FindTrackId", + trackIndex, type); + return MP4_INVALID_TRACK_ID; // satisfy MS compiler +} + +u_int16_t MP4File::FindTrackIndex(MP4TrackId trackId) +{ + for (u_int32_t i = 0; i < m_pTracks.Size() && i <= 0xFFFF; i++) { + if (m_pTracks[i]->GetId() == trackId) { + return (u_int16_t)i; + } + } + + throw new MP4Error("Track id %d doesn't exist", "FindTrackIndex", trackId); + return (u_int16_t)-1; // satisfy MS compiler +} + +u_int16_t MP4File::FindTrakAtomIndex(MP4TrackId trackId) +{ + if (trackId) { + for (u_int32_t i = 0; i < m_trakIds.Size(); i++) { + if (m_trakIds[i] == trackId) { + return i; + } + } + } + + throw new MP4Error("Track id %d doesn't exist", "FindTrakAtomIndex", + trackId); + return (u_int16_t)-1; // satisfy MS compiler +} + +u_int32_t MP4File::GetSampleSize(MP4TrackId trackId, MP4SampleId sampleId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetSampleSize(sampleId); +} + +u_int32_t MP4File::GetTrackMaxSampleSize(MP4TrackId trackId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetMaxSampleSize(); +} + +MP4SampleId MP4File::GetSampleIdFromTime(MP4TrackId trackId, + MP4Timestamp when, bool wantSyncSample) +{ + return m_pTracks[FindTrackIndex(trackId)]-> + GetSampleIdFromTime(when, wantSyncSample); +} + +MP4Timestamp MP4File::GetSampleTime( + MP4TrackId trackId, MP4SampleId sampleId) +{ + MP4Timestamp timestamp; + m_pTracks[FindTrackIndex(trackId)]-> + GetSampleTimes(sampleId, ×tamp, NULL); + return timestamp; +} + +MP4Duration MP4File::GetSampleDuration( + MP4TrackId trackId, MP4SampleId sampleId) +{ + MP4Duration duration; + m_pTracks[FindTrackIndex(trackId)]-> + GetSampleTimes(sampleId, NULL, &duration); + return duration; +} + +MP4Duration MP4File::GetSampleRenderingOffset( + MP4TrackId trackId, MP4SampleId sampleId) +{ + return m_pTracks[FindTrackIndex(trackId)]-> + GetSampleRenderingOffset(sampleId); +} + +bool MP4File::GetSampleSync(MP4TrackId trackId, MP4SampleId sampleId) +{ + return m_pTracks[FindTrackIndex(trackId)]->IsSyncSample(sampleId); +} + +void MP4File::ReadSample(MP4TrackId trackId, MP4SampleId sampleId, + u_int8_t** ppBytes, u_int32_t* pNumBytes, + MP4Timestamp* pStartTime, MP4Duration* pDuration, + MP4Duration* pRenderingOffset, bool* pIsSyncSample) +{ + m_pTracks[FindTrackIndex(trackId)]-> + ReadSample(sampleId, ppBytes, pNumBytes, + pStartTime, pDuration, pRenderingOffset, pIsSyncSample); +} + +void MP4File::WriteSample(MP4TrackId trackId, + const u_int8_t* pBytes, u_int32_t numBytes, + MP4Duration duration, MP4Duration renderingOffset, bool isSyncSample) +{ + ProtectWriteOperation("MP4WriteSample"); + + m_pTracks[FindTrackIndex(trackId)]-> + WriteSample(pBytes, numBytes, duration, renderingOffset, isSyncSample); + + m_pModificationProperty->SetValue(MP4GetAbsTimestamp()); +} + +void MP4File::SetSampleRenderingOffset(MP4TrackId trackId, + MP4SampleId sampleId, MP4Duration renderingOffset) +{ + ProtectWriteOperation("MP4SetSampleRenderingOffset"); + + m_pTracks[FindTrackIndex(trackId)]-> + SetSampleRenderingOffset(sampleId, renderingOffset); + + m_pModificationProperty->SetValue(MP4GetAbsTimestamp()); +} + +char* MP4File::MakeTrackName(MP4TrackId trackId, const char* name) +{ + u_int16_t trakIndex = FindTrakAtomIndex(trackId); + + if (name == NULL || name[0] == '\0') { + snprintf(m_trakName, sizeof(m_trakName), + "moov.trak[%u]", trakIndex); + } else { + snprintf(m_trakName, sizeof(m_trakName), + "moov.trak[%u].%s", trakIndex, name); + } + return m_trakName; +} + +u_int64_t MP4File::GetTrackIntegerProperty(MP4TrackId trackId, const char* name) +{ + return GetIntegerProperty(MakeTrackName(trackId, name)); +} + +void MP4File::SetTrackIntegerProperty(MP4TrackId trackId, const char* name, + int64_t value) +{ + SetIntegerProperty(MakeTrackName(trackId, name), value); +} + +float MP4File::GetTrackFloatProperty(MP4TrackId trackId, const char* name) +{ + return GetFloatProperty(MakeTrackName(trackId, name)); +} + +void MP4File::SetTrackFloatProperty(MP4TrackId trackId, const char* name, + float value) +{ + SetFloatProperty(MakeTrackName(trackId, name), value); +} + +const char* MP4File::GetTrackStringProperty(MP4TrackId trackId, const char* name) +{ + return GetStringProperty(MakeTrackName(trackId, name)); +} + +void MP4File::SetTrackStringProperty(MP4TrackId trackId, const char* name, + const char* value) +{ + SetStringProperty(MakeTrackName(trackId, name), value); +} + +void MP4File::GetTrackBytesProperty(MP4TrackId trackId, const char* name, + u_int8_t** ppValue, u_int32_t* pValueSize) +{ + GetBytesProperty(MakeTrackName(trackId, name), ppValue, pValueSize); +} + +void MP4File::SetTrackBytesProperty(MP4TrackId trackId, const char* name, + const u_int8_t* pValue, u_int32_t valueSize) +{ + SetBytesProperty(MakeTrackName(trackId, name), pValue, valueSize); +} + + +// file level convenience functions + +MP4Duration MP4File::GetDuration() +{ + return m_pDurationProperty->GetValue(); +} + +void MP4File::SetDuration(MP4Duration value) +{ + m_pDurationProperty->SetValue(value); +} + +u_int32_t MP4File::GetTimeScale() +{ + return m_pTimeScaleProperty->GetValue(); +} + +void MP4File::SetTimeScale(u_int32_t value) +{ + if (value == 0) { + throw new MP4Error("invalid value", "SetTimeScale"); + } + m_pTimeScaleProperty->SetValue(value); +} + +u_int8_t MP4File::GetODProfileLevel() +{ + return GetIntegerProperty("moov.iods.ODProfileLevelId"); +} + +void MP4File::SetODProfileLevel(u_int8_t value) +{ + SetIntegerProperty("moov.iods.ODProfileLevelId", value); +} + +u_int8_t MP4File::GetSceneProfileLevel() +{ + return GetIntegerProperty("moov.iods.sceneProfileLevelId"); +} + +void MP4File::SetSceneProfileLevel(u_int8_t value) +{ + SetIntegerProperty("moov.iods.sceneProfileLevelId", value); +} + +u_int8_t MP4File::GetVideoProfileLevel() +{ + return GetIntegerProperty("moov.iods.visualProfileLevelId"); +} + +void MP4File::SetVideoProfileLevel(u_int8_t value) +{ + SetIntegerProperty("moov.iods.visualProfileLevelId", value); +} + +u_int8_t MP4File::GetAudioProfileLevel() +{ + return GetIntegerProperty("moov.iods.audioProfileLevelId"); +} + +void MP4File::SetAudioProfileLevel(u_int8_t value) +{ + SetIntegerProperty("moov.iods.audioProfileLevelId", value); +} + +u_int8_t MP4File::GetGraphicsProfileLevel() +{ + return GetIntegerProperty("moov.iods.graphicsProfileLevelId"); +} + +void MP4File::SetGraphicsProfileLevel(u_int8_t value) +{ + SetIntegerProperty("moov.iods.graphicsProfileLevelId", value); +} + +const char* MP4File::GetSessionSdp() +{ + return GetStringProperty("moov.udta.hnti.rtp .sdpText"); +} + +void MP4File::SetSessionSdp(const char* sdpString) +{ + AddDescendantAtoms("moov", "udta.hnti.rtp "); + + SetStringProperty("moov.udta.hnti.rtp .sdpText", sdpString); +} + +void MP4File::AppendSessionSdp(const char* sdpFragment) +{ + const char* oldSdpString = NULL; + try { + oldSdpString = GetSessionSdp(); + } + catch (MP4Error* e) { + delete e; + SetSessionSdp(sdpFragment); + return; + } + + char* newSdpString = + (char*)MP4Malloc(strlen(oldSdpString) + strlen(sdpFragment) + 1); + strcpy(newSdpString, oldSdpString); + strcat(newSdpString, sdpFragment); + SetSessionSdp(newSdpString); + MP4Free(newSdpString); +} + + +// track level convenience functions + +MP4SampleId MP4File::GetTrackNumberOfSamples(MP4TrackId trackId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetNumberOfSamples(); +} + +const char* MP4File::GetTrackType(MP4TrackId trackId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetType(); +} + +const char *MP4File::GetTrackMediaDataName (MP4TrackId trackId) +{ + MP4Atom *pChild; + MP4Atom *pAtom = + FindAtom(MakeTrackName(trackId, + "mdia.minf.stbl.stsd")); + if (pAtom->GetNumberOfChildAtoms() != 1) { + VERBOSE_ERROR(m_verbosity, + fprintf(stderr, "track %d has more than 1 child atoms in stsd\n", trackId)); + return NULL; + } + pChild = pAtom->GetChildAtom(0); + return pChild->GetType(); +} + + +u_int32_t MP4File::GetTrackTimeScale(MP4TrackId trackId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetTimeScale(); +} + +void MP4File::SetTrackTimeScale(MP4TrackId trackId, u_int32_t value) +{ + if (value == 0) { + throw new MP4Error("invalid value", "SetTrackTimeScale"); + } + SetTrackIntegerProperty(trackId, "mdia.mdhd.timeScale", value); +} + +MP4Duration MP4File::GetTrackDuration(MP4TrackId trackId) +{ + return GetTrackIntegerProperty(trackId, "mdia.mdhd.duration"); +} + +u_int8_t MP4File::GetTrackEsdsObjectTypeId(MP4TrackId trackId) +{ + // changed mp4a to * to handle enca case + return GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.esds.decConfigDescr.objectTypeId"); +} + +u_int8_t MP4File::GetTrackAudioMpeg4Type(MP4TrackId trackId) +{ + // verify that track is an MPEG-4 audio track + if (GetTrackEsdsObjectTypeId(trackId) != MP4_MPEG4_AUDIO_TYPE) { + return MP4_MPEG4_INVALID_AUDIO_TYPE; + } + + u_int8_t* pEsConfig = NULL; + u_int32_t esConfigSize; + + // The Mpeg4 audio type (AAC, CELP, HXVC, ...) + // is the first 5 bits of the ES configuration + + GetTrackESConfiguration(trackId, &pEsConfig, &esConfigSize); + + if (esConfigSize < 1) { + return MP4_MPEG4_INVALID_AUDIO_TYPE; + } + + u_int8_t mpeg4Type = (pEsConfig[0] >> 3); + + free(pEsConfig); + + return mpeg4Type; +} + + +MP4Duration MP4File::GetTrackFixedSampleDuration(MP4TrackId trackId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetFixedSampleDuration(); +} + +double MP4File::GetTrackVideoFrameRate(MP4TrackId trackId) +{ + MP4SampleId numSamples = + GetTrackNumberOfSamples(trackId); + u_int64_t + msDuration = + ConvertFromTrackDuration(trackId, + GetTrackDuration(trackId), MP4_MSECS_TIME_SCALE); + + if (msDuration == 0) { + return 0.0; + } + + return ((double)numSamples / (double) msDuration) * MP4_MSECS_TIME_SCALE; +} + +int MP4File::GetTrackAudioChannels (MP4TrackId trackId) +{ + return GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*[0].channels"); +} + +// true if media track encrypted according to ismacryp +bool MP4File::IsIsmaCrypMediaTrack(MP4TrackId trackId) +{ + if (GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*.sinf.frma.data-format") + != (u_int64_t)-1) { + return true; + } + return false; +} + + +void MP4File::GetTrackESConfiguration(MP4TrackId trackId, + u_int8_t** ppConfig, u_int32_t* pConfigSize) +{ + GetTrackBytesProperty(trackId, + "mdia.minf.stbl.stsd.*[0].esds.decConfigDescr.decSpecificInfo[0].info", + ppConfig, pConfigSize); +} + +void MP4File::GetTrackVideoMetadata(MP4TrackId trackId, + u_int8_t** ppConfig, u_int32_t* pConfigSize) +{ + GetTrackBytesProperty(trackId, + "mdia.minf.stbl.stsd.*[0].*.metadata", + ppConfig, pConfigSize); +} + +void MP4File::SetTrackESConfiguration(MP4TrackId trackId, + const u_int8_t* pConfig, u_int32_t configSize) +{ + // get a handle on the track decoder config descriptor + MP4DescriptorProperty* pConfigDescrProperty = NULL; + FindProperty(MakeTrackName(trackId, + "mdia.minf.stbl.stsd.*[0].esds.decConfigDescr.decSpecificInfo"), + (MP4Property**)&pConfigDescrProperty); + + if (pConfigDescrProperty == NULL) { + // probably trackId refers to a hint track + throw new MP4Error("no such property", "MP4SetTrackESConfiguration"); + } + + // lookup the property to store the configuration + MP4BytesProperty* pInfoProperty = NULL; + pConfigDescrProperty->FindProperty("decSpecificInfo[0].info", + (MP4Property**)&pInfoProperty); + + // configuration being set for the first time + if (pInfoProperty == NULL) { + // need to create a new descriptor to hold it + MP4Descriptor* pConfigDescr = + pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag); + pConfigDescr->Generate(); + + pConfigDescrProperty->FindProperty( + "decSpecificInfo[0].info", + (MP4Property**)&pInfoProperty); + ASSERT(pInfoProperty); + } + + // set the value + pInfoProperty->SetValue(pConfig, configSize); +} + +void MP4File::GetTrackH264ProfileLevel (MP4TrackId trackId, + uint8_t *pProfile, + uint8_t *pLevel) +{ + *pProfile = + GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*[0].avcC.AVCProfileIndication"); + *pLevel = + GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*[0].avcC.AVCLevelIndication"); +} +void MP4File::GetTrackH264LengthSize (MP4TrackId trackId, + uint32_t *pLength) +{ + *pLength = 1 + + GetTrackIntegerProperty(trackId, + "mdia.minf.stbl.stsd.*[0].avcC.lengthSizeMinusOne"); +} + +bool MP4File::GetTrackH264SeqPictHeaders (MP4TrackId trackId, + uint8_t ***pppSeqHeader, + uint32_t **ppSeqHeaderSize, + uint8_t ***pppPictHeader, + uint32_t **ppPictHeaderSize) +{ + uint32_t count; + + MP4Atom *avcCAtom = + FindAtom(MakeTrackName(trackId, + "mdia.minf.stbl.stsd.avc1.avcC")); + MP4BitfieldProperty *pSeqCount; + MP4IntegerProperty *pSeqLen, *pPictCount, *pPictLen; + MP4BytesProperty *pSeqVal, *pPictVal; + if ((avcCAtom->FindProperty("avcC.numOfSequenceParameterSets", + (MP4Property **)&pSeqCount) == false) || + (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetLength", + (MP4Property **)&pSeqLen) == false) || + (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetNALUnit", + (MP4Property **)&pSeqVal) == false)) { + VERBOSE_ERROR(m_verbosity, WARNING("Could not find avcC properties")); + return false; + } + uint8_t **ppSeqHeader = + (uint8_t **)malloc((pSeqCount->GetValue() + 1) * sizeof(uint8_t *)); + *pppSeqHeader = ppSeqHeader; + + uint32_t *pSeqHeaderSize = + (uint32_t *)malloc((pSeqCount->GetValue() + 1) * sizeof(uint32_t *)); + + *ppSeqHeaderSize = pSeqHeaderSize; + for (count = 0; count < pSeqCount->GetValue(); count++) { + pSeqVal->GetValue(&(ppSeqHeader[count]), &(pSeqHeaderSize[count])); + } + ppSeqHeader[count] = NULL; + pSeqHeaderSize[count] = 0; + + if ((avcCAtom->FindProperty("avcC.numOfPictureParameterSets", + (MP4Property **)&pPictCount) == false) || + (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetLength", + (MP4Property **)&pPictLen) == false) || + (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetNALUnit", + (MP4Property **)&pPictVal) == false)) { + VERBOSE_ERROR(m_verbosity, + WARNING("Could not find avcC picture table properties")); + return false; + } + uint8_t + **ppPictHeader = + (uint8_t **)malloc((pPictCount->GetValue() + 1) * sizeof(uint8_t *)); + uint32_t *pPictHeaderSize = + (uint32_t *)malloc((pPictCount->GetValue() + 1)* sizeof(uint32_t *)); + *pppPictHeader = ppPictHeader; + *ppPictHeaderSize = pPictHeaderSize; + + for (count = 0; count < pPictCount->GetValue(); count++) { + pPictVal->GetValue(&(ppPictHeader[count]), &(pPictHeaderSize[count])); + } + ppPictHeader[count] = NULL; + pPictHeaderSize[count] = 0; + return true; +} + + + +const char* MP4File::GetHintTrackSdp(MP4TrackId hintTrackId) +{ + return GetTrackStringProperty(hintTrackId, "udta.hnti.sdp .sdpText"); +} + +void MP4File::SetHintTrackSdp(MP4TrackId hintTrackId, const char* sdpString) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4SetHintTrackSdp"); + } + + AddDescendantAtoms( + MakeTrackName(hintTrackId, NULL), "udta.hnti.sdp "); + + SetTrackStringProperty(hintTrackId, "udta.hnti.sdp .sdpText", sdpString); +} + +void MP4File::AppendHintTrackSdp(MP4TrackId hintTrackId, + const char* sdpFragment) +{ + const char* oldSdpString = NULL; + try { + oldSdpString = GetHintTrackSdp(hintTrackId); + } + catch (MP4Error* e) { + delete e; + SetHintTrackSdp(hintTrackId, sdpFragment); + return; + } + + char* newSdpString = + (char*)MP4Malloc(strlen(oldSdpString) + strlen(sdpFragment) + 1); + strcpy(newSdpString, oldSdpString); + strcat(newSdpString, sdpFragment); + SetHintTrackSdp(hintTrackId, newSdpString); + MP4Free(newSdpString); +} + +void MP4File::GetHintTrackRtpPayload( + MP4TrackId hintTrackId, + char** ppPayloadName, + u_int8_t* pPayloadNumber, + u_int16_t* pMaxPayloadSize, + char **ppEncodingParams) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4GetHintTrackRtpPayload"); + } + + ((MP4RtpHintTrack*)pTrack)->GetPayload( + ppPayloadName, pPayloadNumber, pMaxPayloadSize, ppEncodingParams); +} + +void MP4File::SetHintTrackRtpPayload(MP4TrackId hintTrackId, + const char* payloadName, u_int8_t* pPayloadNumber, u_int16_t maxPayloadSize, + const char *encoding_params, + bool include_rtp_map, + bool include_mpeg4_esid) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4SetHintTrackRtpPayload"); + } + + u_int8_t payloadNumber; + if (pPayloadNumber && *pPayloadNumber != MP4_SET_DYNAMIC_PAYLOAD) { + payloadNumber = *pPayloadNumber; + } else { + payloadNumber = AllocRtpPayloadNumber(); + if (pPayloadNumber) { + *pPayloadNumber = payloadNumber; + } + } + + ((MP4RtpHintTrack*)pTrack)->SetPayload( + payloadName, payloadNumber, maxPayloadSize, encoding_params, + include_rtp_map, include_mpeg4_esid); +} + +u_int8_t MP4File::AllocRtpPayloadNumber() +{ + MP4Integer32Array usedPayloads; + u_int32_t i; + + // collect rtp payload numbers in use by existing tracks + for (i = 0; i < m_pTracks.Size(); i++) { + MP4Atom* pTrakAtom = m_pTracks[i]->GetTrakAtom(); + + MP4Integer32Property* pPayloadProperty = NULL; + pTrakAtom->FindProperty("trak.udta.hinf.payt.payloadNumber", + (MP4Property**)&pPayloadProperty); + + if (pPayloadProperty) { + usedPayloads.Add(pPayloadProperty->GetValue()); + } + } + + // search dynamic payload range for an available slot + u_int8_t payload; + for (payload = 96; payload < 128; payload++) { + for (i = 0; i < usedPayloads.Size(); i++) { + if (payload == usedPayloads[i]) { + break; + } + } + if (i == usedPayloads.Size()) { + break; + } + } + + if (payload >= 128) { + throw new MP4Error("no more available rtp payload numbers", + "AllocRtpPayloadNumber"); + } + + return payload; +} + +MP4TrackId MP4File::GetHintTrackReferenceTrackId( + MP4TrackId hintTrackId) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4GetHintTrackReferenceTrackId"); + } + + MP4Track* pRefTrack = ((MP4RtpHintTrack*)pTrack)->GetRefTrack(); + + if (pRefTrack == NULL) { + return MP4_INVALID_TRACK_ID; + } + return pRefTrack->GetId(); +} + +void MP4File::ReadRtpHint( + MP4TrackId hintTrackId, + MP4SampleId hintSampleId, + u_int16_t* pNumPackets) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", "MP4ReadRtpHint"); + } + ((MP4RtpHintTrack*)pTrack)-> + ReadHint(hintSampleId, pNumPackets); +} + +u_int16_t MP4File::GetRtpHintNumberOfPackets( + MP4TrackId hintTrackId) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4GetRtpHintNumberOfPackets"); + } + return ((MP4RtpHintTrack*)pTrack)->GetHintNumberOfPackets(); +} + +int8_t MP4File::GetRtpPacketBFrame( + MP4TrackId hintTrackId, + u_int16_t packetIndex) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4GetRtpHintBFrame"); + } + return ((MP4RtpHintTrack*)pTrack)->GetPacketBFrame(packetIndex); +} + +int32_t MP4File::GetRtpPacketTransmitOffset( + MP4TrackId hintTrackId, + u_int16_t packetIndex) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4GetRtpPacketTransmitOffset"); + } + return ((MP4RtpHintTrack*)pTrack)->GetPacketTransmitOffset(packetIndex); +} + +void MP4File::ReadRtpPacket( + MP4TrackId hintTrackId, + u_int16_t packetIndex, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + u_int32_t ssrc, + bool includeHeader, + bool includePayload) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", "MP4ReadPacket"); + } + ((MP4RtpHintTrack*)pTrack)->ReadPacket( + packetIndex, ppBytes, pNumBytes, + ssrc, includeHeader, includePayload); +} + +MP4Timestamp MP4File::GetRtpTimestampStart( + MP4TrackId hintTrackId) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4GetRtpTimestampStart"); + } + return ((MP4RtpHintTrack*)pTrack)->GetRtpTimestampStart(); +} + +void MP4File::SetRtpTimestampStart( + MP4TrackId hintTrackId, + MP4Timestamp rtpStart) +{ + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4SetRtpTimestampStart"); + } + ((MP4RtpHintTrack*)pTrack)->SetRtpTimestampStart(rtpStart); +} + +void MP4File::AddRtpHint(MP4TrackId hintTrackId, + bool isBframe, u_int32_t timestampOffset) +{ + ProtectWriteOperation("MP4AddRtpHint"); + + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", "MP4AddRtpHint"); + } + ((MP4RtpHintTrack*)pTrack)->AddHint(isBframe, timestampOffset); +} + +void MP4File::AddRtpPacket( + MP4TrackId hintTrackId, bool setMbit, int32_t transmitOffset) +{ + ProtectWriteOperation("MP4AddRtpPacket"); + + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", "MP4AddRtpPacket"); + } + ((MP4RtpHintTrack*)pTrack)->AddPacket(setMbit, transmitOffset); +} + +void MP4File::AddRtpImmediateData(MP4TrackId hintTrackId, + const u_int8_t* pBytes, u_int32_t numBytes) +{ + ProtectWriteOperation("MP4AddRtpImmediateData"); + + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4AddRtpImmediateData"); + } + ((MP4RtpHintTrack*)pTrack)->AddImmediateData(pBytes, numBytes); +} + +void MP4File::AddRtpSampleData(MP4TrackId hintTrackId, + MP4SampleId sampleId, u_int32_t dataOffset, u_int32_t dataLength) +{ + ProtectWriteOperation("MP4AddRtpSampleData"); + + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4AddRtpSampleData"); + } + ((MP4RtpHintTrack*)pTrack)->AddSampleData( + sampleId, dataOffset, dataLength); +} + +void MP4File::AddRtpESConfigurationPacket(MP4TrackId hintTrackId) +{ + ProtectWriteOperation("MP4AddRtpESConfigurationPacket"); + + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4AddRtpESConfigurationPacket"); + } + ((MP4RtpHintTrack*)pTrack)->AddESConfigurationPacket(); +} + +void MP4File::WriteRtpHint(MP4TrackId hintTrackId, + MP4Duration duration, bool isSyncSample) +{ + ProtectWriteOperation("MP4WriteRtpHint"); + + MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)]; + + if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) { + throw new MP4Error("track is not a hint track", + "MP4WriteRtpHint"); + } + ((MP4RtpHintTrack*)pTrack)->WriteHint(duration, isSyncSample); +} + +u_int64_t MP4File::ConvertFromMovieDuration( + MP4Duration duration, + u_int32_t timeScale) +{ + return MP4ConvertTime((u_int64_t)duration, + GetTimeScale(), timeScale); +} + +u_int64_t MP4File::ConvertFromTrackTimestamp( + MP4TrackId trackId, + MP4Timestamp timeStamp, + u_int32_t timeScale) +{ + return MP4ConvertTime(timeStamp, + GetTrackTimeScale(trackId), timeScale); +} + +MP4Timestamp MP4File::ConvertToTrackTimestamp( + MP4TrackId trackId, + u_int64_t timeStamp, + u_int32_t timeScale) +{ + return (MP4Timestamp)MP4ConvertTime(timeStamp, + timeScale, GetTrackTimeScale(trackId)); +} + +u_int64_t MP4File::ConvertFromTrackDuration( + MP4TrackId trackId, + MP4Duration duration, + u_int32_t timeScale) +{ + return MP4ConvertTime((u_int64_t)duration, + GetTrackTimeScale(trackId), timeScale); +} + +MP4Duration MP4File::ConvertToTrackDuration( + MP4TrackId trackId, + u_int64_t duration, + u_int32_t timeScale) +{ + return (MP4Duration)MP4ConvertTime(duration, + timeScale, GetTrackTimeScale(trackId)); +} + +u_int8_t MP4File::ConvertTrackTypeToStreamType(const char* trackType) +{ + u_int8_t streamType; + + if (!strcmp(trackType, MP4_OD_TRACK_TYPE)) { + streamType = MP4ObjectDescriptionStreamType; + } else if (!strcmp(trackType, MP4_SCENE_TRACK_TYPE)) { + streamType = MP4SceneDescriptionStreamType; + } else if (!strcmp(trackType, MP4_CLOCK_TRACK_TYPE)) { + streamType = MP4ClockReferenceStreamType; + } else if (!strcmp(trackType, MP4_MPEG7_TRACK_TYPE)) { + streamType = MP4Mpeg7StreamType; + } else if (!strcmp(trackType, MP4_OCI_TRACK_TYPE)) { + streamType = MP4OCIStreamType; + } else if (!strcmp(trackType, MP4_IPMP_TRACK_TYPE)) { + streamType = MP4IPMPStreamType; + } else if (!strcmp(trackType, MP4_MPEGJ_TRACK_TYPE)) { + streamType = MP4MPEGJStreamType; + } else { + streamType = MP4UserPrivateStreamType; + } + + return streamType; +} + +// edit list + +char* MP4File::MakeTrackEditName( + MP4TrackId trackId, + MP4EditId editId, + const char* name) +{ + char* trakName = MakeTrackName(trackId, NULL); + + if (m_editName == NULL) { + m_editName = (char *)malloc(1024); + if (m_editName == NULL) return NULL; + } + snprintf(m_editName, 1024, + "%s.edts.elst.entries[%u].%s", + trakName, editId - 1, name); + return m_editName; +} + +MP4EditId MP4File::AddTrackEdit( + MP4TrackId trackId, + MP4EditId editId) +{ + ProtectWriteOperation("AddTrackEdit"); + return m_pTracks[FindTrackIndex(trackId)]->AddEdit(editId); +} + +void MP4File::DeleteTrackEdit( + MP4TrackId trackId, + MP4EditId editId) +{ + ProtectWriteOperation("DeleteTrackEdit"); + m_pTracks[FindTrackIndex(trackId)]->DeleteEdit(editId); +} + +u_int32_t MP4File::GetTrackNumberOfEdits( + MP4TrackId trackId) +{ + return GetTrackIntegerProperty(trackId, "edts.elst.entryCount"); +} + +MP4Duration MP4File::GetTrackEditTotalDuration( + MP4TrackId trackId, + MP4EditId editId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetEditTotalDuration(editId); +} + +MP4Timestamp MP4File::GetTrackEditStart( + MP4TrackId trackId, + MP4EditId editId) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetEditStart(editId); +} + +MP4Timestamp MP4File::GetTrackEditMediaStart( + MP4TrackId trackId, + MP4EditId editId) +{ + return GetIntegerProperty( + MakeTrackEditName(trackId, editId, "mediaTime")); +} + +void MP4File::SetTrackEditMediaStart( + MP4TrackId trackId, + MP4EditId editId, + MP4Timestamp startTime) +{ + SetIntegerProperty( + MakeTrackEditName(trackId, editId, "mediaTime"), + startTime); +} + +MP4Duration MP4File::GetTrackEditDuration( + MP4TrackId trackId, + MP4EditId editId) +{ + return GetIntegerProperty( + MakeTrackEditName(trackId, editId, "segmentDuration")); +} + +void MP4File::SetTrackEditDuration( + MP4TrackId trackId, + MP4EditId editId, + MP4Duration duration) +{ + SetIntegerProperty( + MakeTrackEditName(trackId, editId, "segmentDuration"), + duration); +} + +bool MP4File::GetTrackEditDwell( + MP4TrackId trackId, + MP4EditId editId) +{ + return (GetIntegerProperty( + MakeTrackEditName(trackId, editId, "mediaRate")) == 0); +} + +void MP4File::SetTrackEditDwell( + MP4TrackId trackId, + MP4EditId editId, + bool dwell) +{ + SetIntegerProperty( + MakeTrackEditName(trackId, editId, "mediaRate"), + (dwell ? 0 : 1)); +} + +MP4SampleId MP4File::GetSampleIdFromEditTime( + MP4TrackId trackId, + MP4Timestamp when, + MP4Timestamp* pStartTime, + MP4Duration* pDuration) +{ + return m_pTracks[FindTrackIndex(trackId)]->GetSampleIdFromEditTime( + when, pStartTime, pDuration); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4file.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4file.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,841 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#ifndef __MP4_FILE_INCLUDED__ +#define __MP4_FILE_INCLUDED__ + +// forward declarations +class MP4Atom; +class MP4Property; +class MP4Float32Property; +class MP4StringProperty; +class MP4BytesProperty; +class MP4Descriptor; +class MP4DescriptorProperty; + +class MP4File { +public: /* equivalent to MP4 library API */ + MP4File(u_int32_t verbosity = 0); + ~MP4File(); + + /* file operations */ + void Read(const char* fileName); + void Create(const char* fileName, u_int32_t flags, + int add_ftyp = 1, int add_iods = 1, + char* majorBrand = NULL, + u_int32_t minorVersion = 0, char** supportedBrands = NULL, + u_int32_t supportedBrandsCount = 0); + void Modify(const char* fileName); + void Optimize(const char* orgFileName, + const char* newFileName = NULL); + void Dump(FILE* pDumpFile = NULL, bool dumpImplicits = false); + void Close(); + + /* library property per file */ + + u_int32_t GetVerbosity() { + return m_verbosity; + } + void SetVerbosity(u_int32_t verbosity) { + m_verbosity = verbosity; + } + + bool Use64Bits(const char *atomName); + + /* file properties */ + + u_int64_t GetIntegerProperty(const char* name); + float GetFloatProperty(const char* name); + const char* GetStringProperty(const char* name); + void GetBytesProperty(const char* name, + u_int8_t** ppValue, u_int32_t* pValueSize); + + void SetIntegerProperty(const char* name, u_int64_t value); + void SetFloatProperty(const char* name, float value); + void SetStringProperty(const char* name, const char* value); + void SetBytesProperty(const char* name, + const u_int8_t* pValue, u_int32_t valueSize); + + // file level convenience functions + + MP4Duration GetDuration(); + void SetDuration(MP4Duration value); + + u_int32_t GetTimeScale(); + void SetTimeScale(u_int32_t value); + + u_int8_t GetODProfileLevel(); + void SetODProfileLevel(u_int8_t value); + + u_int8_t GetSceneProfileLevel(); + void SetSceneProfileLevel(u_int8_t value); + + u_int8_t GetVideoProfileLevel(); + void SetVideoProfileLevel(u_int8_t value); + + u_int8_t GetAudioProfileLevel(); + void SetAudioProfileLevel(u_int8_t value); + + u_int8_t GetGraphicsProfileLevel(); + void SetGraphicsProfileLevel(u_int8_t value); + + const char* GetSessionSdp(); + void SetSessionSdp(const char* sdpString); + void AppendSessionSdp(const char* sdpString); + + /* track operations */ + + MP4TrackId AddTrack(const char* type, u_int32_t timeScale = 1000); + void DeleteTrack(MP4TrackId trackId); + + u_int32_t GetNumberOfTracks(const char* type = NULL, u_int8_t subType = 0); + + MP4TrackId AllocTrackId(); + MP4TrackId FindTrackId(u_int16_t trackIndex, + const char* type = NULL, u_int8_t subType = 0); + u_int16_t FindTrackIndex(MP4TrackId trackId); + u_int16_t FindTrakAtomIndex(MP4TrackId trackId); + + /* track properties */ + + u_int64_t GetTrackIntegerProperty( + MP4TrackId trackId, const char* name); + float GetTrackFloatProperty( + MP4TrackId trackId, const char* name); + const char* GetTrackStringProperty( + MP4TrackId trackId, const char* name); + void GetTrackBytesProperty( + MP4TrackId trackId, const char* name, + u_int8_t** ppValue, u_int32_t* pValueSize); + + void SetTrackIntegerProperty( + MP4TrackId trackId, const char* name, int64_t value); + void SetTrackFloatProperty( + MP4TrackId trackId, const char* name, float value); + void SetTrackStringProperty( + MP4TrackId trackId, const char* name, const char* value); + void SetTrackBytesProperty( + MP4TrackId trackId, const char* name, + const u_int8_t* pValue, u_int32_t valueSize); + + /* sample operations */ + + u_int32_t GetSampleSize(MP4TrackId trackId, MP4SampleId sampleId); + + u_int32_t GetTrackMaxSampleSize(MP4TrackId trackId); + + MP4SampleId GetSampleIdFromTime(MP4TrackId trackId, + MP4Timestamp when, bool wantSyncSample = false); + + MP4Timestamp GetSampleTime( + MP4TrackId trackId, MP4SampleId sampleId); + + MP4Duration GetSampleDuration( + MP4TrackId trackId, MP4SampleId sampleId); + + MP4Duration GetSampleRenderingOffset( + MP4TrackId trackId, MP4SampleId sampleId); + + bool GetSampleSync( + MP4TrackId trackId, MP4SampleId sampleId); + + void ReadSample( + // input parameters + MP4TrackId trackId, + MP4SampleId sampleId, + // output parameters + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + MP4Timestamp* pStartTime = NULL, + MP4Duration* pDuration = NULL, + MP4Duration* pRenderingOffset = NULL, + bool* pIsSyncSample = NULL); + + void WriteSample( + MP4TrackId trackId, + const u_int8_t* pBytes, + u_int32_t numBytes, + MP4Duration duration = 0, + MP4Duration renderingOffset = 0, + bool isSyncSample = true); + + void SetSampleRenderingOffset( + MP4TrackId trackId, + MP4SampleId sampleId, + MP4Duration renderingOffset); + + /* track level convenience functions */ + + MP4TrackId AddSystemsTrack(const char* type); + + MP4TrackId AddODTrack(); + + MP4TrackId AddSceneTrack(); + + MP4TrackId AddAudioTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int8_t audioType); + + MP4TrackId AddEncAudioTrack( // ismacryp + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int8_t audioType, + u_int32_t scheme_type, + u_int16_t scheme_version, + u_int8_t key_ind_len, + u_int8_t iv_len, + bool selective_enc, + char *kms_uri); + + void SetAmrVendor( + MP4TrackId trackId, + u_int32_t vendor); + + void SetAmrDecoderVersion( + MP4TrackId trackId, + u_int8_t decoderVersion); + + void SetAmrModeSet( + MP4TrackId trackId, + u_int16_t modeSet); + uint16_t GetAmrModeSet(MP4TrackId trackId); + + MP4TrackId AddAmrAudioTrack( + u_int32_t timeScale, + u_int16_t modeSet, + u_int8_t modeChangePeriod, + u_int8_t framesPerSample, + bool isAmrWB); + + MP4TrackId AddHrefTrack(uint32_t timeScale, + MP4Duration sampleDuration); + + MP4TrackId AddMP4VideoTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t videoType); + + MP4TrackId AddEncVideoTrack( // ismacryp + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t videoType, + u_int32_t scheme_type, + u_int16_t scheme_version, + u_int8_t key_ind_len, + u_int8_t iv_len, + bool selective_enc, + char *kms_uri); + + + void SetH263Vendor( + MP4TrackId trackId, + u_int32_t vendor); + + void SetH263DecoderVersion( + MP4TrackId trackId, + u_int8_t decoderVersion); + + void SetH263Bitrates( + MP4TrackId, + u_int32_t avgBitrate, + u_int32_t maxBitrate); + + MP4TrackId AddH263VideoTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t h263Level, + u_int8_t h263Profile, + u_int32_t avgBitrate, + u_int32_t maxBitrate); + MP4TrackId AddH264VideoTrack( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + uint8_t AVCProfileIndication, + uint8_t profile_compat, + uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne); + bool AddH264SequenceParameterSet(MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen); + bool AddH264PictureParameterSet(MP4TrackId trackId, + const uint8_t *pPicture, + uint16_t pictureLen); + MP4TrackId AddHintTrack(MP4TrackId refTrackId); + + MP4SampleId GetTrackNumberOfSamples(MP4TrackId trackId); + + const char* GetTrackType(MP4TrackId trackId); + + const char *GetTrackMediaDataName(MP4TrackId trackId); + MP4Duration GetTrackDuration(MP4TrackId trackId); + + u_int32_t GetTrackTimeScale(MP4TrackId trackId); + void SetTrackTimeScale(MP4TrackId trackId, u_int32_t value); + + // replacement to GetTrackAudioType and GetTrackVideoType + u_int8_t GetTrackEsdsObjectTypeId(MP4TrackId trackId); + + u_int8_t GetTrackAudioMpeg4Type(MP4TrackId trackId); + + MP4Duration GetTrackFixedSampleDuration(MP4TrackId trackId); + + double GetTrackVideoFrameRate(MP4TrackId trackId); + + int GetTrackAudioChannels(MP4TrackId trackId); + void GetTrackESConfiguration(MP4TrackId trackId, + u_int8_t** ppConfig, u_int32_t* pConfigSize); + void SetTrackESConfiguration(MP4TrackId trackId, + const u_int8_t* pConfig, u_int32_t configSize); + + void GetTrackVideoMetadata(MP4TrackId trackId, + u_int8_t** ppConfig, u_int32_t* pConfigSize); + void GetTrackH264ProfileLevel(MP4TrackId trackId, + uint8_t *pProfile, + uint8_t *pLevel); + bool GetTrackH264SeqPictHeaders(MP4TrackId trackId, + uint8_t ***pSeqHeader, + uint32_t **pSeqHeaderSize, + uint8_t ***pPictHeader, + uint32_t **pPictHeaderSize); + void GetTrackH264LengthSize(MP4TrackId, + uint32_t *pLength); + const char* GetHintTrackSdp(MP4TrackId hintTrackId); + void SetHintTrackSdp(MP4TrackId hintTrackId, const char* sdpString); + void AppendHintTrackSdp(MP4TrackId hintTrackId, const char* sdpString); + + // 3GPP specific functions + void MakeFtypAtom(char* majorBrand, + u_int32_t minorVersion, + char** supportedBrands, + u_int32_t supportedBrandsCount); + void Make3GPCompliant(const char* fileName, + char* majorBrand, + u_int32_t minorVersion, + char** supportedBrands, + u_int32_t supportedBrandsCount, + bool deleteIodsAtom); + + // ISMA specific functions + + // true if media track encrypted according to ismacryp + bool IsIsmaCrypMediaTrack(MP4TrackId trackId); + + void MakeIsmaCompliant(bool addIsmaComplianceSdp = true); + + void CreateIsmaIodFromParams( + u_int8_t videoProfile, + u_int32_t videoBitrate, + u_int8_t* videoConfig, + u_int32_t videoConfigLength, + u_int8_t audioProfile, + u_int32_t audioBitrate, + u_int8_t* audioConfig, + u_int32_t audioConfigLength, + u_int8_t** ppBytes, + u_int64_t* pNumBytes); + + // time convenience functions + + u_int64_t ConvertFromMovieDuration( + MP4Duration duration, + u_int32_t timeScale); + + u_int64_t ConvertFromTrackTimestamp( + MP4TrackId trackId, + MP4Timestamp timeStamp, + u_int32_t timeScale); + + MP4Timestamp ConvertToTrackTimestamp( + MP4TrackId trackId, + u_int64_t timeStamp, + u_int32_t timeScale); + + u_int64_t ConvertFromTrackDuration( + MP4TrackId trackId, + MP4Duration duration, + u_int32_t timeScale); + + MP4Duration ConvertToTrackDuration( + MP4TrackId trackId, + u_int64_t duration, + u_int32_t timeScale); + + // specialized operations + + void GetHintTrackRtpPayload( + MP4TrackId hintTrackId, + char** ppPayloadName = NULL, + u_int8_t* pPayloadNumber = NULL, + u_int16_t* pMaxPayloadSize = NULL, + char **ppEncodingParams = NULL); + + void SetHintTrackRtpPayload( + MP4TrackId hintTrackId, + const char* payloadName, + u_int8_t* pPayloadNumber, + u_int16_t maxPayloadSize, + const char *encoding_params, + bool include_rtp_map, + bool include_mpeg4_esid); + + MP4TrackId GetHintTrackReferenceTrackId( + MP4TrackId hintTrackId); + + void ReadRtpHint( + MP4TrackId hintTrackId, + MP4SampleId hintSampleId, + u_int16_t* pNumPackets = NULL); + + u_int16_t GetRtpHintNumberOfPackets( + MP4TrackId hintTrackId); + + int8_t GetRtpPacketBFrame( + MP4TrackId hintTrackId, + u_int16_t packetIndex); + + int32_t GetRtpPacketTransmitOffset( + MP4TrackId hintTrackId, + u_int16_t packetIndex); + + void ReadRtpPacket( + MP4TrackId hintTrackId, + u_int16_t packetIndex, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + u_int32_t ssrc = 0, + bool includeHeader = true, + bool includePayload = true); + + MP4Timestamp GetRtpTimestampStart( + MP4TrackId hintTrackId); + + void SetRtpTimestampStart( + MP4TrackId hintTrackId, + MP4Timestamp rtpStart); + + void AddRtpHint( + MP4TrackId hintTrackId, + bool isBframe, + u_int32_t timestampOffset); + + void AddRtpPacket( + MP4TrackId hintTrackId, + bool setMbit, + int32_t transmitOffset); + + void AddRtpImmediateData( + MP4TrackId hintTrackId, + const u_int8_t* pBytes, + u_int32_t numBytes); + + void AddRtpSampleData( + MP4TrackId hintTrackId, + MP4SampleId sampleId, + u_int32_t dataOffset, + u_int32_t dataLength); + + void AddRtpESConfigurationPacket( + MP4TrackId hintTrackId); + + void WriteRtpHint( + MP4TrackId hintTrackId, + MP4Duration duration, + bool isSyncSample); + + u_int8_t AllocRtpPayloadNumber(); + + // edit list related + + char* MakeTrackEditName( + MP4TrackId trackId, + MP4EditId editId, + const char* name); + + MP4EditId AddTrackEdit( + MP4TrackId trackId, + MP4EditId editId = MP4_INVALID_EDIT_ID); + + void DeleteTrackEdit( + MP4TrackId trackId, + MP4EditId editId); + + u_int32_t GetTrackNumberOfEdits( + MP4TrackId trackId); + + MP4Timestamp GetTrackEditStart( + MP4TrackId trackId, + MP4EditId editId); + + MP4Duration GetTrackEditTotalDuration( + MP4TrackId trackId, + MP4EditId editId); + + MP4Timestamp GetTrackEditMediaStart( + MP4TrackId trackId, + MP4EditId editId); + + void SetTrackEditMediaStart( + MP4TrackId trackId, + MP4EditId editId, + MP4Timestamp startTime); + + MP4Duration GetTrackEditDuration( + MP4TrackId trackId, + MP4EditId editId); + + void SetTrackEditDuration( + MP4TrackId trackId, + MP4EditId editId, + MP4Duration duration); + + bool GetTrackEditDwell( + MP4TrackId trackId, + MP4EditId editId); + + void SetTrackEditDwell( + MP4TrackId trackId, + MP4EditId editId, + bool dwell); + + MP4SampleId GetSampleIdFromEditTime( + MP4TrackId trackId, + MP4Timestamp when, + MP4Timestamp* pStartTime = NULL, + MP4Duration* pDuration = NULL); + + /* iTunes metadata handling */ + protected: + bool CreateMetadataAtom(const char* name); + bool DeleteMetadataAtom(const char* name); + bool GetMetadataString(const char *atom, char **value); + bool SetMetadataString(const char *atom, const char *value); + public: + bool MetadataDelete(void); + + /* set metadata */ + bool SetMetadataName(const char* value); + bool SetMetadataWriter(const char* value); + bool SetMetadataAlbum(const char* value); + bool SetMetadataArtist(const char* value); + bool SetMetadataTool(const char* value); + bool SetMetadataComment(const char* value); + bool SetMetadataYear(const char* value); + bool SetMetadataTrack(u_int16_t track, u_int16_t totalTracks); + bool SetMetadataDisk(u_int16_t disk, u_int16_t totalDisks); + bool SetMetadataGenre(const char *value); + bool SetMetadataGrouping(const char *value); + bool SetMetadataTempo(u_int16_t tempo); + bool SetMetadataCompilation(u_int8_t compilation); + bool SetMetadataCoverArt(u_int8_t *coverArt, u_int32_t size); + bool SetMetadataFreeForm(char *name, + u_int8_t* pValue, + u_int32_t valueSize); + + /* get metadata */ + bool GetMetadataByIndex(u_int32_t index, + const char** ppName, + u_int8_t** ppValue, + u_int32_t* pValueSize); + bool GetMetadataName(char** value); + bool GetMetadataWriter(char** value); + bool GetMetadataAlbum(char** value); + bool GetMetadataArtist(char** value); + bool GetMetadataTool(char** value); + bool GetMetadataComment(char** value); + bool GetMetadataYear(char** value); + bool GetMetadataTrack(u_int16_t* track, u_int16_t* totalTracks); + bool GetMetadataDisk(u_int16_t* disk, u_int16_t* totalDisks); + bool GetMetadataGenre(char **value); + bool GetMetadataGrouping(char **value); + bool GetMetadataTempo(u_int16_t* tempo); + bool GetMetadataCompilation(u_int8_t* compilation); + bool GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t* size); + bool GetMetadataFreeForm(char *name, + u_int8_t** pValue, + u_int32_t* valueSize); + + /* delete metadata */ + bool DeleteMetadataName(); + bool DeleteMetadataWriter(); + bool DeleteMetadataAlbum(); + bool DeleteMetadataArtist(); + bool DeleteMetadataTool(); + bool DeleteMetadataComment(); + bool DeleteMetadataYear(); + bool DeleteMetadataTrack(); + bool DeleteMetadataDisk(); + bool DeleteMetadataGenre(); + bool DeleteMetadataGrouping(); + bool DeleteMetadataTempo(); + bool DeleteMetadataCompilation(); + bool DeleteMetadataCoverArt(); + bool DeleteMetadataFreeForm(char *name); + + /* end of MP4 API */ + + /* "protected" interface to be used only by friends in library */ + + u_int64_t GetPosition(FILE* pFile = NULL); + void SetPosition(u_int64_t pos, FILE* pFile = NULL); + + u_int64_t GetSize(); + + u_int32_t ReadBytes( + u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile = NULL); + u_int64_t ReadUInt(u_int8_t size); + u_int8_t ReadUInt8(); + u_int16_t ReadUInt16(); + u_int32_t ReadUInt24(); + u_int32_t ReadUInt32(); + u_int64_t ReadUInt64(); + float ReadFixed16(); + float ReadFixed32(); + float ReadFloat(); + char* ReadString(); + char* ReadCountedString( + u_int8_t charSize = 1, bool allowExpandedCount = false); + u_int64_t ReadBits(u_int8_t numBits); + void FlushReadBits(); + u_int32_t ReadMpegLength(); + + u_int32_t PeekBytes( + u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile = NULL); + + void WriteBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile = NULL); + void WriteUInt(u_int64_t value, u_int8_t size); + void WriteUInt8(u_int8_t value); + void WriteUInt16(u_int16_t value); + void WriteUInt24(u_int32_t value); + void WriteUInt32(u_int32_t value); + void WriteUInt64(u_int64_t value); + void WriteFixed16(float value); + void WriteFixed32(float value); + void WriteFloat(float value); + void WriteString(char* string); + void WriteCountedString(char* string, + u_int8_t charSize = 1, bool allowExpandedCount = false); + void WriteBits(u_int64_t bits, u_int8_t numBits); + void PadWriteBits(u_int8_t pad = 0); + void FlushWriteBits(); + void WriteMpegLength(u_int32_t value, bool compact = false); + + void EnableMemoryBuffer( + u_int8_t* pBytes = NULL, u_int64_t numBytes = 0); + void DisableMemoryBuffer( + u_int8_t** ppBytes = NULL, u_int64_t* pNumBytes = NULL); + + char GetMode() { + return m_mode; + } + + MP4Track* GetTrack(MP4TrackId trackId); + + MP4Duration UpdateDuration(MP4Duration duration); + + MP4Atom* FindAtom(const char* name); + + MP4Atom* AddChildAtom( + const char* parentName, + const char* childName); + + MP4Atom* AddChildAtom( + MP4Atom* pParentAtom, + const char* childName); + + MP4Atom* InsertChildAtom( + const char* parentName, + const char* childName, + u_int32_t index); + + MP4Atom* InsertChildAtom( + MP4Atom* pParentAtom, + const char* childName, + u_int32_t index); + + MP4Atom* AddDescendantAtoms( + const char* ancestorName, + const char* childName); + + MP4Atom* AddDescendantAtoms( + MP4Atom* pAncestorAtom, + const char* childName); + +protected: + void Open(const char* fmode); + void ReadFromFile(); + void GenerateTracks(); + void BeginWrite(); + void FinishWrite(); + void CacheProperties(); + void RewriteMdat(FILE* pReadFile, FILE* pWriteFile); + bool ShallHaveIods(); + + const char* TempFileName(); + void Rename(const char* existingFileName, const char* newFileName); + + void ProtectWriteOperation(char* where); + + void FindIntegerProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + void FindFloatProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + void FindStringProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + void FindBytesProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + bool FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + + MP4TrackId AddVideoTrackDefault( + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + const char *videoType); + MP4TrackId AddCntlTrackDefault( + u_int32_t timeScale, + MP4Duration sampleDuration, + const char *videoType); + void AddTrackToIod(MP4TrackId trackId); + + void RemoveTrackFromIod(MP4TrackId trackId, bool shallHaveIods = true); + + void AddTrackToOd(MP4TrackId trackId); + + void RemoveTrackFromOd(MP4TrackId trackId); + + void GetTrackReferenceProperties(const char* trefName, + MP4Property** ppCountProperty, MP4Property** ppTrackIdProperty); + + void AddTrackReference(const char* trefName, MP4TrackId refTrackId); + + u_int32_t FindTrackReference(const char* trefName, MP4TrackId refTrackId); + + void RemoveTrackReference(const char* trefName, MP4TrackId refTrackId); + + void AddDataReference(MP4TrackId trackId, const char* url); + + char* MakeTrackName(MP4TrackId trackId, const char* name); + + u_int8_t ConvertTrackTypeToStreamType(const char* trackType); + + void CreateIsmaIodFromFile( + MP4TrackId odTrackId, + MP4TrackId sceneTrackId, + MP4TrackId audioTrackId, + MP4TrackId videoTrackId, + u_int8_t** ppBytes, + u_int64_t* pNumBytes); + + MP4Descriptor* CreateESD( + MP4DescriptorProperty* pEsProperty, + u_int32_t esid, + u_int8_t objectType, + u_int8_t streamType, + u_int32_t bufferSize, + u_int32_t bitrate, + const u_int8_t* pConfig, + u_int32_t configLength, + char* url); + + void CreateIsmaODUpdateCommandFromFileForFile( + MP4TrackId odTrackId, + MP4TrackId audioTrackId, + MP4TrackId videoTrackId, + u_int8_t** ppBytes, + u_int64_t* pNumBytes); + + void CreateIsmaODUpdateCommandFromFileForStream( + MP4TrackId audioTrackId, + MP4TrackId videoTrackId, + u_int8_t** ppBytes, + u_int64_t* pNumBytes); + + void CreateIsmaODUpdateCommandForStream( + MP4DescriptorProperty* pAudioEsdProperty, + MP4DescriptorProperty* pVideoEsdProperty, + u_int8_t** ppBytes, + u_int64_t* pNumBytes); + + void CreateIsmaSceneCommand( + bool hasAudio, + bool hasVideo, + u_int8_t** ppBytes, + u_int64_t* pNumBytes); + +protected: + char* m_fileName; + FILE* m_pFile; + u_int64_t m_orgFileSize; + u_int64_t m_fileSize; + MP4Atom* m_pRootAtom; + MP4Integer32Array m_trakIds; + MP4TrackArray m_pTracks; + MP4TrackId m_odTrackId; + u_int32_t m_verbosity; + char m_mode; + u_int32_t m_createFlags; + bool m_useIsma; + + // cached properties + MP4IntegerProperty* m_pModificationProperty; + MP4Integer32Property* m_pTimeScaleProperty; + MP4IntegerProperty* m_pDurationProperty; + + // read/write in memory + u_int8_t* m_memoryBuffer; + u_int64_t m_memoryBufferPosition; + u_int64_t m_memoryBufferSize; + + // bit read/write buffering + u_int8_t m_numReadBits; + u_int8_t m_bufReadBits; + u_int8_t m_numWriteBits; + u_int8_t m_bufWriteBits; + +#ifndef _WIN32 + char m_tempFileName[64]; +#else + char m_tempFileName[MAX_PATH + 3]; +#endif + char m_trakName[1024]; + char *m_editName; +}; + +#endif /* __MP4_FILE_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4file_io.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4file_io.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,557 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +// MP4File low level IO support + +u_int64_t MP4File::GetPosition(FILE* pFile) +{ + if (m_memoryBuffer == NULL) { + if (pFile == NULL) { + ASSERT(m_pFile); + pFile = m_pFile; + } + + fpos_t fpos; + if (fgetpos(pFile, &fpos) < 0) { + throw new MP4Error(errno, "MP4GetPosition"); + } + uint64_t ret; + FPOS_TO_VAR(fpos, uint64_t, ret); + return ret; + } else { + return m_memoryBufferPosition; + } +} + +void MP4File::SetPosition(u_int64_t pos, FILE* pFile) +{ + if (m_memoryBuffer == NULL) { + if (pFile == NULL) { + ASSERT(m_pFile); + pFile = m_pFile; + } + + fpos_t fpos; + VAR_TO_FPOS(fpos, pos); + if (fsetpos(pFile, &fpos) < 0) { + throw new MP4Error(errno, "MP4SetPosition"); + } + } else { + if (pos >= m_memoryBufferSize) { + // abort(); + throw new MP4Error("position out of range", "MP4SetPosition"); + } + m_memoryBufferPosition = pos; + } +} + +u_int64_t MP4File::GetSize() +{ + if (m_mode == 'w') { + // we're always positioned at the end of file in write mode + // except for short intervals in ReadSample and FinishWrite routines + // so we rely on the faster approach of GetPosition() + // instead of flushing to disk, and then stat'ing the file + m_fileSize = GetPosition(); + } // else read mode, fileSize was determined at Open() + + return m_fileSize; +} + +u_int32_t MP4File::ReadBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile) +{ + // handle degenerate cases + if (numBytes == 0) { + return 0; + } + + ASSERT(pBytes); + WARNING(m_numReadBits > 0); + + if (pFile == NULL) { + pFile = m_pFile; + } + ASSERT(pFile); + + if (m_memoryBuffer == NULL) { + if (fread(pBytes, 1, numBytes, pFile) != numBytes) { + if (feof(pFile)) { + throw new MP4Error( + "not enough bytes, reached end-of-file", + "MP4ReadBytes"); + } else { + throw new MP4Error(errno, "MP4ReadBytes"); + } + } + } else { + if (m_memoryBufferPosition + numBytes > m_memoryBufferSize) { + throw new MP4Error( + "not enough bytes, reached end-of-memory", + "MP4ReadBytes"); + } + memcpy(pBytes, &m_memoryBuffer[m_memoryBufferPosition], numBytes); + m_memoryBufferPosition += numBytes; + } + return numBytes; +} + +u_int32_t MP4File::PeekBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile) +{ + u_int64_t pos = GetPosition(pFile); + ReadBytes(pBytes, numBytes, pFile); + SetPosition(pos, pFile); + return numBytes; +} + +void MP4File::EnableMemoryBuffer(u_int8_t* pBytes, u_int64_t numBytes) +{ + ASSERT(m_memoryBuffer == NULL); + + if (pBytes) { + m_memoryBuffer = pBytes; + m_memoryBufferSize = numBytes; + } else { + if (numBytes) { + m_memoryBufferSize = numBytes; + } else { + m_memoryBufferSize = 4096; + } + m_memoryBuffer = (u_int8_t*)MP4Malloc(m_memoryBufferSize); + } + m_memoryBufferPosition = 0; +} + +void MP4File::DisableMemoryBuffer(u_int8_t** ppBytes, u_int64_t* pNumBytes) +{ + ASSERT(m_memoryBuffer != NULL); + + if (ppBytes) { + *ppBytes = m_memoryBuffer; + } + if (pNumBytes) { + *pNumBytes = m_memoryBufferPosition; + } + + m_memoryBuffer = NULL; + m_memoryBufferSize = 0; + m_memoryBufferPosition = 0; +} + +void MP4File::WriteBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile) +{ + ASSERT(m_numWriteBits == 0 || m_numWriteBits >= 8); + + if (pBytes == NULL || numBytes == 0) { + return; + } + + if (m_memoryBuffer == NULL) { + if (pFile == NULL) { + ASSERT(m_pFile); + pFile = m_pFile; + } + + u_int32_t rc = fwrite(pBytes, 1, numBytes, pFile); + if (rc != numBytes) { + throw new MP4Error(errno, "MP4WriteBytes"); + } + } else { + if (m_memoryBufferPosition + numBytes > m_memoryBufferSize) { + m_memoryBufferSize = 2 * (m_memoryBufferSize + numBytes); + m_memoryBuffer = (u_int8_t*) + MP4Realloc(m_memoryBuffer, m_memoryBufferSize); + } + memcpy(&m_memoryBuffer[m_memoryBufferPosition], pBytes, numBytes); + m_memoryBufferPosition += numBytes; + } +} + +u_int64_t MP4File::ReadUInt(u_int8_t size) +{ + switch (size) { + case 1: + return ReadUInt8(); + case 2: + return ReadUInt16(); + case 3: + return ReadUInt24(); + case 4: + return ReadUInt32(); + case 8: + return ReadUInt64(); + default: + ASSERT(false); + return 0; + } +} + +void MP4File::WriteUInt(u_int64_t value, u_int8_t size) +{ + switch (size) { + case 1: + WriteUInt8(value); + case 2: + WriteUInt16(value); + case 3: + WriteUInt24(value); + case 4: + WriteUInt32(value); + case 8: + WriteUInt64(value); + default: + ASSERT(false); + } +} + +u_int8_t MP4File::ReadUInt8() +{ + u_int8_t data; + ReadBytes(&data, 1); + return data; +} + +void MP4File::WriteUInt8(u_int8_t value) +{ + WriteBytes(&value, 1); +} + +u_int16_t MP4File::ReadUInt16() +{ + u_int8_t data[2]; + ReadBytes(&data[0], 2); + return ((data[0] << 8) | data[1]); +} + +void MP4File::WriteUInt16(u_int16_t value) +{ + u_int8_t data[2]; + data[0] = (value >> 8) & 0xFF; + data[1] = value & 0xFF; + WriteBytes(data, 2); +} + +u_int32_t MP4File::ReadUInt24() +{ + u_int8_t data[3]; + ReadBytes(&data[0], 3); + return ((data[0] << 16) | (data[1] << 8) | data[2]); +} + +void MP4File::WriteUInt24(u_int32_t value) +{ + u_int8_t data[3]; + data[0] = (value >> 16) & 0xFF; + data[1] = (value >> 8) & 0xFF; + data[2] = value & 0xFF; + WriteBytes(data, 3); +} + +u_int32_t MP4File::ReadUInt32() +{ + u_int8_t data[4]; + ReadBytes(&data[0], 4); + return ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]); +} + +void MP4File::WriteUInt32(u_int32_t value) +{ + u_int8_t data[4]; + data[0] = (value >> 24) & 0xFF; + data[1] = (value >> 16) & 0xFF; + data[2] = (value >> 8) & 0xFF; + data[3] = value & 0xFF; + WriteBytes(data, 4); +} + +u_int64_t MP4File::ReadUInt64() +{ + u_int8_t data[8]; + u_int64_t result = 0; + u_int64_t temp; + + ReadBytes(&data[0], 8); + + for (int i = 0; i < 8; i++) { + temp = data[i]; + result |= temp << ((7 - i) * 8); + } + return result; +} + +void MP4File::WriteUInt64(u_int64_t value) +{ + u_int8_t data[8]; + + for (int i = 7; i >= 0; i--) { + data[i] = value & 0xFF; + value >>= 8; + } + WriteBytes(data, 8); +} + +float MP4File::ReadFixed16() +{ + u_int8_t iPart = ReadUInt8(); + u_int8_t fPart = ReadUInt8(); + + return iPart + (((float)fPart) / 0x100); +} + +void MP4File::WriteFixed16(float value) +{ + if (value >= 0x100) { + throw new MP4Error(ERANGE, "MP4WriteFixed16"); + } + + u_int8_t iPart = (u_int8_t)value; + u_int8_t fPart = (u_int8_t)((value - iPart) * 0x100); + + WriteUInt8(iPart); + WriteUInt8(fPart); +} + +float MP4File::ReadFixed32() +{ + u_int16_t iPart = ReadUInt16(); + u_int16_t fPart = ReadUInt16(); + + return iPart + (((float)fPart) / 0x10000); +} + +void MP4File::WriteFixed32(float value) +{ + if (value >= 0x10000) { + throw new MP4Error(ERANGE, "MP4WriteFixed32"); + } + + u_int16_t iPart = (u_int16_t)value; + u_int16_t fPart = (u_int16_t)((value - iPart) * 0x10000); + + WriteUInt16(iPart); + WriteUInt16(fPart); +} + +float MP4File::ReadFloat() +{ + union { + float f; + u_int32_t i; + } u; + + u.i = ReadUInt32(); + return u.f; +} + +void MP4File::WriteFloat(float value) +{ + union { + float f; + u_int32_t i; + } u; + + u.f = value; + WriteUInt32(u.i); +} + +char* MP4File::ReadString() +{ + u_int32_t length = 0; + u_int32_t alloced = 64; + char* data = (char*)MP4Malloc(alloced); + + do { + if (length == alloced) { + data = (char*)MP4Realloc(data, alloced * 2); + } + ReadBytes((u_int8_t*)&data[length], 1); + length++; + } while (data[length - 1] != 0); + + data = (char*)MP4Realloc(data, length); + return data; +} + +void MP4File::WriteString(char* string) +{ + if (string == NULL) { + u_int8_t zero = 0; + WriteBytes(&zero, 1); + } else { + WriteBytes((u_int8_t*)string, strlen(string) + 1); + } +} + +char* MP4File::ReadCountedString(u_int8_t charSize, bool allowExpandedCount) +{ + u_int32_t charLength; + if (allowExpandedCount) { + u_int8_t b; + charLength = 0; + do { + b = ReadUInt8(); + charLength += b; + } while (b == 255); + } else { + charLength = ReadUInt8(); + } + + u_int32_t byteLength = charLength * charSize; + char* data = (char*)MP4Malloc(byteLength + 1); + if (byteLength > 0) { + ReadBytes((u_int8_t*)data, byteLength); + } + data[byteLength] = '\0'; + return data; +} + +void MP4File::WriteCountedString(char* string, + u_int8_t charSize, bool allowExpandedCount) +{ + u_int32_t byteLength; + if (string) { + byteLength = strlen(string); + } else { + byteLength = 0; + } + u_int32_t charLength = byteLength / charSize; + + if (allowExpandedCount) { + while (charLength >= 0xFF) { + WriteUInt8(0xFF); + charLength -= 0xFF; + } + WriteUInt8(charLength); + } else { + if (charLength > 255) { + throw new MP4Error(ERANGE, "Length is %d", "MP4WriteCountedString", charLength); + } + WriteUInt8(charLength); + } + + if (byteLength > 0) { + WriteBytes((u_int8_t*)string, byteLength); + } +} + +u_int64_t MP4File::ReadBits(u_int8_t numBits) +{ + ASSERT(numBits > 0); + ASSERT(numBits <= 64); + + u_int64_t bits = 0; + + for (u_int8_t i = numBits; i > 0; i--) { + if (m_numReadBits == 0) { + ReadBytes(&m_bufReadBits, 1); + m_numReadBits = 8; + } + bits = (bits << 1) | ((m_bufReadBits >> (--m_numReadBits)) & 1); + } + + return bits; +} + +void MP4File::FlushReadBits() +{ + // eat any remaining bits in the read buffer + m_numReadBits = 0; +} + +void MP4File::WriteBits(u_int64_t bits, u_int8_t numBits) +{ + ASSERT(numBits <= 64); + + for (u_int8_t i = numBits; i > 0; i--) { + m_bufWriteBits |= + (((bits >> (i - 1)) & 1) << (8 - ++m_numWriteBits)); + + if (m_numWriteBits == 8) { + FlushWriteBits(); + } + } +} + +void MP4File::PadWriteBits(u_int8_t pad) +{ + if (m_numWriteBits) { + WriteBits(pad ? 0xFF : 0x00, 8 - m_numWriteBits); + } +} + +void MP4File::FlushWriteBits() +{ + if (m_numWriteBits > 0) { + WriteBytes(&m_bufWriteBits, 1); + m_numWriteBits = 0; + m_bufWriteBits = 0; + } +} + +u_int32_t MP4File::ReadMpegLength() +{ + u_int32_t length = 0; + u_int8_t numBytes = 0; + u_int8_t b; + + do { + b = ReadUInt8(); + length = (length << 7) | (b & 0x7F); + numBytes++; + } while ((b & 0x80) && numBytes < 4); + + return length; +} + +void MP4File::WriteMpegLength(u_int32_t value, bool compact) +{ + if (value > 0x0FFFFFFF) { + throw new MP4Error(ERANGE, "MP4WriteMpegLength"); + } + + int8_t numBytes; + + if (compact) { + if (value <= 0x7F) { + numBytes = 1; + } else if (value <= 0x3FFF) { + numBytes = 2; + } else if (value <= 0x1FFFFF) { + numBytes = 3; + } else { + numBytes = 4; + } + } else { + numBytes = 4; + } + + int8_t i = numBytes; + do { + i--; + u_int8_t b = (value >> (i * 7)) & 0x7F; + if (i > 0) { + b |= 0x80; + } + WriteUInt8(b); + } while (i > 0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4info.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4info.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,567 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001-2002. All Rights Reserved. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Bill May wmay@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +static char* PrintAudioInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + static const char* mpeg4AudioNames[] = { + "MPEG-4 AAC main", + "MPEG-4 AAC LC", + "MPEG-4 AAC SSR", + "MPEG-4 AAC LTP", + "MPEG-4 AAC HE", + "MPEG-4 AAC Scalable", + "MPEG-4 TwinVQ", + "MPEG-4 CELP", + "MPEG-4 HVXC", + NULL, NULL, + "MPEG-4 TTSI", + "MPEG-4 Main Synthetic", + "MPEG-4 Wavetable Syn", + "MPEG-4 General MIDI", + "MPEG-4 Algo Syn and Audio FX", + "MPEG-4 ER AAC LC", + NULL, + "MPEG-4 ER AAC LTP", + "MPEG-4 ER AAC Scalable", + "MPEG-4 ER TwinVQ", + "MPEG-4 ER BSAC", + "MPEG-4 ER ACC LD", + "MPEG-4 ER CELP", + "MPEG-4 ER HVXC", + "MPEG-4 ER HILN", + "MPEG-4 ER Parametric", + }; + + static const u_int8_t mpegAudioTypes[] = { + MP4_MPEG2_AAC_MAIN_AUDIO_TYPE, // 0x66 + MP4_MPEG2_AAC_LC_AUDIO_TYPE, // 0x67 + MP4_MPEG2_AAC_SSR_AUDIO_TYPE, // 0x68 + MP4_MPEG2_AUDIO_TYPE, // 0x69 + MP4_MPEG1_AUDIO_TYPE, // 0x6B + // private types + MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE, + MP4_VORBIS_AUDIO_TYPE, + MP4_ALAW_AUDIO_TYPE, + MP4_ULAW_AUDIO_TYPE, + MP4_G723_AUDIO_TYPE, + MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE, + }; + static const char* mpegAudioNames[] = { + "MPEG-2 AAC Main", + "MPEG-2 AAC LC", + "MPEG-2 AAC SSR", + "MPEG-2 Audio (13818-3)", + "MPEG-1 Audio (11172-3)", + // private types + "PCM16 (little endian)", + "Vorbis", + "G.711 aLaw", + "G.711 uLaw", + "G.723.1", + "PCM16 (big endian)", + }; + u_int8_t numMpegAudioTypes = + sizeof(mpegAudioTypes) / sizeof(u_int8_t); + + const char* typeName = "Unknown"; + bool foundType = false; + u_int8_t type = 0; + const char *media_data_name; + + media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); + + if (media_data_name == NULL) { + typeName = "Unknown - no media data name"; + } else if (strcasecmp(media_data_name, "samr") == 0) { + typeName = "AMR"; + foundType = true; + } else if (strcasecmp(media_data_name, "sawb") == 0) { + typeName = "AMR-WB"; + foundType = true; + } else if (strcasecmp(media_data_name, "mp4a") == 0) { + + type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId); + + switch (type) { + case MP4_MPEG4_AUDIO_TYPE: { + u_int8_t* pAacConfig = NULL; + u_int32_t aacConfigLength; + + MP4GetTrackESConfiguration(mp4File, + trackId, + &pAacConfig, + &aacConfigLength); + + if (pAacConfig != NULL && aacConfigLength >= 2) { + type = (pAacConfig[0] >> 3) & 0x1f; + if (type == 0 || /* type == 5 || */ type == 10 || type == 11 || + type == 18 || type >= 28) { + typeName = "MPEG-4 Unknown Profile"; + } else { + typeName = mpeg4AudioNames[type - 1]; + foundType = true; + } + free(pAacConfig); + } else { + typeName = "MPEG-4 (no GAConfig)"; + foundType = true; + } + break; + } + // fall through + default: + for (u_int8_t i = 0; i < numMpegAudioTypes; i++) { + if (type == mpegAudioTypes[i]) { + typeName = mpegAudioNames[i]; + foundType = true; + break; + } + } + } + } else { + typeName = media_data_name; + foundType = true; + } + + u_int32_t timeScale = + MP4GetTrackTimeScale(mp4File, trackId); + + MP4Duration trackDuration = + MP4GetTrackDuration(mp4File, trackId); + + double msDuration = + (double) (MP4ConvertFromTrackDuration(mp4File, trackId, + trackDuration, MP4_MSECS_TIME_SCALE)); + + u_int32_t avgBitRate = + MP4GetTrackBitRate(mp4File, trackId); + + char *sInfo = (char*)MP4Malloc(256); + + // type duration avgBitrate samplingFrequency + if (foundType) + sprintf(sInfo, + "%u\taudio\t%s%s, %.3f secs, %u kbps, %u Hz\n", + trackId, + MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "", + typeName, + msDuration / 1000.0, + (avgBitRate + 500) / 1000, + timeScale); + else + sprintf(sInfo, + "%u\taudio\t%s%s(%u), %.3f secs, %u kbps, %u Hz\n", + trackId, + MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "", + typeName, + type, + msDuration / 1000.0, + (avgBitRate + 500) / 1000, + timeScale); + + return sInfo; +} +static const struct { + uint8_t profile; + const char *name; +} VisualProfileToName[] = { + { MPEG4_SP_L1, "MPEG-4 Simple @ L1"}, + { MPEG4_SP_L2, "MPEG-4 Simple @ L2" }, + { MPEG4_SP_L3, "MPEG-4 Simple @ L3" }, + { MPEG4_SP_L0, "MPEG-4 Simple @ L0" }, + { MPEG4_SSP_L1, "MPEG-4 Simple Scalable @ L1"}, + { MPEG4_SSP_L2, "MPEG-4 Simple Scalable @ L2" }, + { MPEG4_CP_L1, "MPEG-4 Core @ L1"}, + { MPEG4_CP_L2, "MPEG-4 Core @ L2"}, + { MPEG4_MP_L2, "MPEG-4 Main @ L2"}, + { MPEG4_MP_L3, "MPEG-4 Main @ L3"}, + { MPEG4_MP_L4, "MPEG-4 Main @ L4"}, + { MPEG4_NBP_L2, "MPEG-4 N-bit @ L2"}, + { MPEG4_STP_L1, "MPEG-4 Scalable Texture @ L1"}, + { MPEG4_SFAP_L1, "MPEG-4 Simple Face Anim @ L1"}, + { MPEG4_SFAP_L2, "MPEG-4 Simple Face Anim @ L2"}, + { MPEG4_SFBAP_L1, "MPEG-4 Simple FBA @ L1"}, + { MPEG4_SFBAP_L2, "MPEG-4 Simple FBA @ L2"}, + { MPEG4_BATP_L1, "MPEG-4 Basic Anim Text @ L1"}, + { MPEG4_BATP_L2, "MPEG-4 Basic Anim Text @ L2"}, + { MPEG4_HP_L1, "MPEG-4 Hybrid @ L1"}, + { MPEG4_HP_L2, "MPEG-4 Hybrid @ L2"}, + { MPEG4_ARTSP_L1, "MPEG-4 Adv RT Simple @ L1"}, + { MPEG4_ARTSP_L2, "MPEG-4 Adv RT Simple @ L2"}, + { MPEG4_ARTSP_L3, "MPEG-4 Adv RT Simple @ L3"}, + { MPEG4_ARTSP_L4, "MPEG-4 Adv RT Simple @ L4"}, + { MPEG4_CSP_L1, "MPEG-4 Core Scalable @ L1"}, + { MPEG4_CSP_L2, "MPEG-4 Core Scalable @ L2"}, + { MPEG4_CSP_L3, "MPEG-4 Core Scalable @ L3"}, + { MPEG4_ACEP_L1, "MPEG-4 Adv Coding Efficieny @ L1"}, + { MPEG4_ACEP_L2, "MPEG-4 Adv Coding Efficieny @ L2"}, + { MPEG4_ACEP_L3, "MPEG-4 Adv Coding Efficieny @ L3"}, + { MPEG4_ACEP_L4, "MPEG-4 Adv Coding Efficieny @ L4"}, + { MPEG4_ACP_L1, "MPEG-4 Adv Core Profile @ L1"}, + { MPEG4_ACP_L2, "MPEG-4 Adv Core Profile @ L2"}, + { MPEG4_AST_L1, "MPEG-4 Adv Scalable Texture @ L1"}, + { MPEG4_AST_L2, "MPEG-4 Adv Scalable Texture @ L2"}, + { MPEG4_AST_L3, "MPEG-4 Adv Scalable Texture @ L3"}, + { MPEG4_S_STUDIO_P_L1, "MPEG-4 Simple Studio @ L1"}, + { MPEG4_S_STUDIO_P_L2, "MPEG-4 Simple Studio @ L2"}, + { MPEG4_S_STUDIO_P_L3, "MPEG-4 Simple Studio @ L3"}, + { MPEG4_S_STUDIO_P_L4, "MPEG-4 Simple Studio @ L4"}, + { MPEG4_C_STUDIO_P_L1, "MPEG-4 Core Studio @ L1"}, + { MPEG4_C_STUDIO_P_L2, "MPEG-4 Core Studio @ L2"}, + { MPEG4_C_STUDIO_P_L3, "MPEG-4 Core Studio @ L3"}, + { MPEG4_C_STUDIO_P_L4, "MPEG-4 Core Studio @ L4"}, + { MPEG4_ASP_L0, "MPEG-4 Adv Simple@L0"}, + { MPEG4_ASP_L1, "MPEG-4 Adv Simple@L1"}, + { MPEG4_ASP_L2, "MPEG-4 Adv Simple@L2"}, + { MPEG4_ASP_L3, "MPEG-4 Adv Simple@L3"}, + { MPEG4_ASP_L4, "MPEG-4 Adv Simple@L4"}, + { MPEG4_ASP_L5, "MPEG-4 Adv Simple@L5"}, + { MPEG4_ASP_L3B, "MPEG-4 Adv Simple@L3b"}, + { MPEG4_FGSP_L0, "MPEG-4 FGS @ L0" }, + { MPEG4_FGSP_L1, "MPEG-4 FGS @ L1" }, + { MPEG4_FGSP_L2, "MPEG-4 FGS @ L2" }, + { MPEG4_FGSP_L3, "MPEG-4 FGS @ L3" }, + { MPEG4_FGSP_L4, "MPEG-4 FGS @ L4" }, + { MPEG4_FGSP_L5, "MPEG-4 FGS @ L5" } +}; + +static const char *Mpeg4VisualProfileName (uint8_t visual_profile) +{ + size_t size = sizeof(VisualProfileToName) / sizeof(*VisualProfileToName); + + for (size_t ix = 0; ix < size; ix++) { + if (visual_profile == VisualProfileToName[ix].profile) { + return (VisualProfileToName[ix].name); + } + } + return (NULL); +} +static char* PrintVideoInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + + static const u_int8_t mpegVideoTypes[] = { + MP4_MPEG2_SIMPLE_VIDEO_TYPE, // 0x60 + MP4_MPEG2_MAIN_VIDEO_TYPE, // 0x61 + MP4_MPEG2_SNR_VIDEO_TYPE, // 0x62 + MP4_MPEG2_SPATIAL_VIDEO_TYPE, // 0x63 + MP4_MPEG2_HIGH_VIDEO_TYPE, // 0x64 + MP4_MPEG2_442_VIDEO_TYPE, // 0x65 + MP4_MPEG1_VIDEO_TYPE, // 0x6A + MP4_JPEG_VIDEO_TYPE, // 0x6C + MP4_YUV12_VIDEO_TYPE, + MP4_H263_VIDEO_TYPE, + MP4_H261_VIDEO_TYPE, + }; + static const char* mpegVideoNames[] = { + "MPEG-2 Simple", + "MPEG-2 Main", + "MPEG-2 SNR", + "MPEG-2 Spatial", + "MPEG-2 High", + "MPEG-2 4:2:2", + "MPEG-1", + "JPEG", + "YUV12", + "H.263", + "H.261", + }; + u_int8_t numMpegVideoTypes = + sizeof(mpegVideoTypes) / sizeof(u_int8_t); + bool foundTypeName = false; + const char* typeName = "Unknown"; + + const char *media_data_name; + uint8_t type = 0; + + media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); + char typebuffer[80]; + if (media_data_name == NULL) { + typeName = "Unknown - no media data name"; + foundTypeName = true; + } else if (strcasecmp(media_data_name, "avc1") == 0) { + // avc + uint8_t profile, level; + char profileb[20], levelb[20]; + if (MP4GetTrackH264ProfileLevel(mp4File, trackId, &profile, &level)) { + if (profile == 66) { + strcpy(profileb, "Baseline"); + } else if (profile == 77) { + strcpy(profileb, "Main"); + } else if (profile == 88) { + strcpy(profileb, "Extended"); + } else { + sprintf(profileb, "Unknown Profile %x", profile); + } + switch (level) { + case 10: case 20: case 30: case 40: case 50: + sprintf(levelb, "%u", level / 10); + break; + case 11: case 12: case 13: + case 21: case 22: + case 31: case 32: + case 41: case 42: + case 51: + sprintf(levelb, "%u.%u", level / 10, level % 10); + break; + default: + sprintf(levelb, "unknown level %x", level); + break; + } + sprintf(typebuffer, "H264 %s@%s", profileb, levelb); + typeName = typebuffer; + } else { + typeName = "H.264 - profile/level error"; + } + foundTypeName = true; + } else if (strcasecmp(media_data_name, "s263") == 0) { + // 3gp h.263 + typeName = "H.263"; + foundTypeName = true; + } else if ((strcasecmp(media_data_name, "mp4v") == 0) || + (strcasecmp(media_data_name, "encv") == 0)) { + // note encv might needs it's own field eventually. + type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId); + if (type == MP4_MPEG4_VIDEO_TYPE) { + type = MP4GetVideoProfileLevel(mp4File); + typeName = Mpeg4VisualProfileName(type); + if (typeName == NULL) { + typeName = "MPEG-4 Unknown Profile"; + } else { + foundTypeName = true; + } + } else { + for (u_int8_t i = 0; i < numMpegVideoTypes; i++) { + if (type == mpegVideoTypes[i]) { + typeName = mpegVideoNames[i]; + foundTypeName = true; + break; + } + } + } + } else { + typeName = media_data_name; + foundTypeName = true; // we don't have a type value to display + } + + MP4Duration trackDuration = + MP4GetTrackDuration(mp4File, trackId); + + double msDuration = + (double) (MP4ConvertFromTrackDuration(mp4File, trackId, + trackDuration, MP4_MSECS_TIME_SCALE)); + + u_int32_t avgBitRate = + MP4GetTrackBitRate(mp4File, trackId); + + // Note not all mp4 implementations set width and height correctly + // The real answer can be buried inside the ES configuration info + u_int16_t width = MP4GetTrackVideoWidth(mp4File, trackId); + + u_int16_t height = MP4GetTrackVideoHeight(mp4File, trackId); + + double fps = MP4GetTrackVideoFrameRate(mp4File, trackId); + + char *sInfo = (char*)MP4Malloc(256); + + // type duration avgBitrate frameSize frameRate + if (foundTypeName) { + sprintf(sInfo, + "%u\tvideo\t%s%s, %.3f secs, %u kbps, %ux%u @ %f fps\n", + trackId, + MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "encv - " : "", + typeName, + msDuration / 1000.0, + (avgBitRate + 500) / 1000, + width, + height, + fps + ); + } else { + sprintf(sInfo, + "%u\tvideo\t%s(%u), %.3f secs, %u kbps, %ux%u @ %f fps\n", + trackId, + typeName, + type, + msDuration / 1000.0, + (avgBitRate + 500) / 1000, + width, + height, + fps + ); + } + + return sInfo; +} +static char* PrintCntlInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + const char *media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); + const char *typeName = "Unknown"; + + if (media_data_name == NULL) { + typeName = "Unknown - no media data name"; + } else if (strcasecmp(media_data_name, "href") == 0) { + typeName = "ISMA Href"; + } else { + typeName = media_data_name; + } + + MP4Duration trackDuration = + MP4GetTrackDuration(mp4File, trackId); + + double msDuration = + (double) (MP4ConvertFromTrackDuration(mp4File, trackId, + trackDuration, MP4_MSECS_TIME_SCALE)); + char *sInfo = (char *)MP4Malloc(256); + + snprintf(sInfo, 256, + "%u\tcontrol\t%s, %.3f secs\n", + trackId, + typeName, + msDuration / 1000.0); + return sInfo; +} + + +static char* PrintHintInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + MP4TrackId referenceTrackId = + MP4GetHintTrackReferenceTrackId(mp4File, trackId); + + char* payloadName = NULL; + MP4GetHintTrackRtpPayload(mp4File, trackId, &payloadName); + + char *sInfo = (char*)MP4Malloc(256); + + sprintf(sInfo, + "%u\thint\tPayload %s for track %u\n", + trackId, + payloadName, + referenceTrackId); + + free(payloadName); + + return sInfo; +} + +static char* PrintTrackInfo( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + char* trackInfo = NULL; + + const char* trackType = + MP4GetTrackType(mp4File, trackId); + + if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) { + trackInfo = PrintAudioInfo(mp4File, trackId); + } else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) { + trackInfo = PrintVideoInfo(mp4File, trackId); + } else if (!strcmp(trackType, MP4_HINT_TRACK_TYPE)) { + trackInfo = PrintHintInfo(mp4File, trackId); + } else if (strcmp(trackType, MP4_CNTL_TRACK_TYPE) == 0) { + trackInfo = PrintCntlInfo(mp4File, trackId); + } else { + trackInfo = (char*)MP4Malloc(256); + if (!strcmp(trackType, MP4_OD_TRACK_TYPE)) { + sprintf(trackInfo, + "%u\tod\tObject Descriptors\n", + trackId); + } else if (!strcmp(trackType, MP4_SCENE_TRACK_TYPE)) { + sprintf(trackInfo, + "%u\tscene\tBIFS\n", + trackId); + } else { + sprintf(trackInfo, + "%u\t%s\n", + trackId, trackType); + } + } + + return trackInfo; +} + +extern "C" char* MP4Info( + MP4FileHandle mp4File, + MP4TrackId trackId) +{ + char* info = NULL; + + if (MP4_IS_VALID_FILE_HANDLE(mp4File)) { + try { + if (trackId == MP4_INVALID_TRACK_ID) { + info = (char*)MP4Calloc(4*1024); + + sprintf(info, "Track\tType\tInfo\n"); + + u_int32_t numTracks = MP4GetNumberOfTracks(mp4File); + + for (u_int32_t i = 0; i < numTracks; i++) { + trackId = MP4FindTrackId(mp4File, i); + char* trackInfo = PrintTrackInfo(mp4File, trackId); + strcat(info, trackInfo); + MP4Free(trackInfo); + } + } else { + info = PrintTrackInfo(mp4File, trackId); + } + } + catch (MP4Error* e) { + delete e; + } + } + + return info; +} + +extern "C" char* MP4FileInfo( + const char* fileName, + MP4TrackId trackId) +{ + MP4FileHandle mp4File = + MP4Read(fileName); + + if (!mp4File) { + return NULL; + } + + char* info = MP4Info(mp4File, trackId); + + MP4Close(mp4File); + + return info; // caller should free this +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4meta.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4meta.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,979 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * M. Bakker mbakker at nero.com + * + * Apple iTunes Metadata handling + */ + +/** + + The iTunes tagging seems to support any tag field name + but there are some predefined fields, also known from the QuickTime format + + predefined fields (the ones I know of until now): + - ©nam : Name of the song/movie (string) + - ©ART : Name of the artist/performer (string) + - ©wrt : Name of the writer (string) + - ©alb : Name of the album (string) + - ©day : Year (4 bytes, e.g. "2003") (string) + - ©too : Tool(s) used to create the file (string) + - ©cmt : Comment (string) + - ©gen : Custom genre (string) + - ©grp : Grouping (string) + - trkn : Tracknumber (8 byte string) + 16 bit: empty + 16 bit: tracknumber + 16 bit: total tracks on album + 16 bit: empty + - disk : Disknumber (8 byte string) + 16 bit: empty + 16 bit: disknumber + 16 bit: total number of disks + 16 bit: empty + - gnre : Genre (16 bit genre) (ID3v1 index + 1) + - cpil : Part of a compilation (1 byte, 1 or 0) + - tmpo : Tempo in BPM (16 bit) + - covr : Cover art (xx bytes binary data) + - ---- : Free form metadata, can have any name and any data + +**/ + +#include "mp4common.h" + +bool MP4File::GetMetadataByIndex(u_int32_t index, + const char** ppName, + u_int8_t** ppValue, u_int32_t* pValueSize) +{ + char s[256]; + + sprintf(s, "moov.udta.meta.ilst.*[%u].data.metadata", index); + GetBytesProperty(s, ppValue, pValueSize); + + sprintf(s, "moov.udta.meta.ilst.*[%u]", index); + MP4Atom* pParent = m_pRootAtom->FindAtom(s); + *ppName = pParent->GetType(); + + /* check for free form tagfield */ + if (memcmp(*ppName, "----", 4) == 0) + { + u_int8_t* pV; + u_int32_t VSize = 0; + char *pN; + + sprintf(s, "moov.udta.meta.ilst.*[%u].name.metadata", index); + GetBytesProperty(s, &pV, &VSize); + + pN = (char*)malloc((VSize+1)*sizeof(char)); + memset(pN, 0, (VSize+1)*sizeof(char)); + memcpy(pN, pV, VSize*sizeof(char)); + + *ppName = pN; + } + + return true; +} + +bool MP4File::CreateMetadataAtom(const char* name) +{ + char s[256]; + char t[256]; + + sprintf(t, "udta.meta.ilst.%s.data", name); + sprintf(s, "moov.udta.meta.ilst.%s.data", name); + AddDescendantAtoms("moov", t); + MP4Atom *pMetaAtom = m_pRootAtom->FindAtom(s); + + if (!pMetaAtom) + return false; + + /* some fields need special flags set */ + if ((uint8_t)name[0] == 0251) + { + pMetaAtom->SetFlags(0x1); + } else if ((memcmp(name, "cpil", 4) == 0) || (memcmp(name, "tmpo", 4) == 0)) { + pMetaAtom->SetFlags(0x15); + } + + MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr"); + MP4StringProperty *pStringProperty = NULL; + MP4BytesProperty *pBytesProperty = NULL; + ASSERT(pHdlrAtom); + + pHdlrAtom->FindProperty( + "hdlr.handlerType", (MP4Property**)&pStringProperty); + ASSERT(pStringProperty); + pStringProperty->SetValue("mdir"); + + u_int8_t val[12]; + memset(val, 0, 12*sizeof(u_int8_t)); + val[0] = 0x61; + val[1] = 0x70; + val[2] = 0x70; + val[3] = 0x6c; + pHdlrAtom->FindProperty( + "hdlr.reserved2", (MP4Property**)&pBytesProperty); + ASSERT(pBytesProperty); + pBytesProperty->SetReadOnly(false); + pBytesProperty->SetValue(val, 12); + pBytesProperty->SetReadOnly(true); + + return true; +} + +bool MP4File::DeleteMetadataAtom(const char* name) +{ + MP4Atom *pMetaAtom = NULL; + char s[256]; + + sprintf(s, "moov.udta.meta.ilst.%s", name); + pMetaAtom = m_pRootAtom->FindAtom(s); + + /* if it exists, delete it */ + if (pMetaAtom) + { + MP4Atom *pParent = pMetaAtom->GetParentAtom(); + + pParent->DeleteChildAtom(pMetaAtom); + + delete pMetaAtom; + + return true; + } + + return false; +} + +bool MP4File::SetMetadataString (const char *atom, const char *value) +{ + char atomstring[40]; + MP4Atom *pMetaAtom; + MP4BytesProperty *pMetadataProperty = NULL; + sprintf(atomstring, "moov.udta.meta.ilst.%s.data", atom); + + pMetaAtom = m_pRootAtom->FindAtom(atomstring); + + if (!pMetaAtom) + { + if (!CreateMetadataAtom(atom)) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(atomstring); + } + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + pMetadataProperty->SetValue((u_int8_t*)value, strlen(value)); + + return true; +} + +bool MP4File::GetMetadataString (const char *atom, char **value) +{ + unsigned char *val = NULL; + u_int32_t valSize = 0; + char atomstring[60]; + sprintf(atomstring, "moov.udta.meta.ilst.%s.data.metadata", atom); + + *value = NULL; + + GetBytesProperty(atomstring, (u_int8_t**)&val, &valSize); + + if (valSize > 0) + { + *value = (char*)malloc((valSize+1)*sizeof(unsigned char)); + memset(*value, 0, (valSize+1)*sizeof(unsigned char)); + memcpy(*value, val, valSize*sizeof(unsigned char)); + return true; + } + return false; +} + +bool MP4File::SetMetadataName(const char* value) +{ + return SetMetadataString("\251nam", value); +} + +bool MP4File::GetMetadataName(char** value) +{ + return GetMetadataString("\251nam", value); +} + +bool MP4File::DeleteMetadataName() +{ + return DeleteMetadataAtom("\251nam"); +} + +bool MP4File::SetMetadataWriter(const char* value) +{ + return SetMetadataString("\251wrt", value); +} + +bool MP4File::GetMetadataWriter(char** value) +{ + return GetMetadataString("\251wrt", value); +} + +bool MP4File::DeleteMetadataWriter() +{ + return DeleteMetadataAtom("\251wrt"); +} + +bool MP4File::SetMetadataAlbum(const char* value) +{ + return SetMetadataString("\251alb", value); +} + +bool MP4File::GetMetadataAlbum(char** value) +{ + return GetMetadataString("\251alb", value); +} + +bool MP4File::DeleteMetadataAlbum() +{ + return DeleteMetadataAtom("\251alb"); +} + +bool MP4File::SetMetadataArtist(const char* value) +{ + return SetMetadataString("\251ART", value); +} + +bool MP4File::GetMetadataArtist(char** value) +{ + return GetMetadataString("\251ART", value); +} + +bool MP4File::DeleteMetadataArtist() +{ + return DeleteMetadataAtom("\251ART"); +} + +bool MP4File::SetMetadataTool(const char* value) +{ + return SetMetadataString("\251too", value); +} + +bool MP4File::GetMetadataTool(char** value) +{ + return GetMetadataString("\251too", value); +} + +bool MP4File::DeleteMetadataTool() +{ + return DeleteMetadataAtom("\251too"); +} + +bool MP4File::SetMetadataComment(const char* value) +{ + return SetMetadataString("\251cmt", value); +} + +bool MP4File::GetMetadataComment(char** value) +{ + return GetMetadataString("\251cmt", value); +} + +bool MP4File::DeleteMetadataComment() +{ + return DeleteMetadataAtom("\251cmt"); +} + +bool MP4File::SetMetadataYear(const char* value) +{ + if (strlen(value) != 4) return false; + + return SetMetadataString("\251day", value); +} + +bool MP4File::GetMetadataYear(char** value) +{ + return GetMetadataString("\251day", value); +} + +bool MP4File::DeleteMetadataYear() +{ + return DeleteMetadataAtom("\251day"); +} + +bool MP4File::SetMetadataTrack(u_int16_t track, u_int16_t totalTracks) +{ + unsigned char t[9]; + const char *s = "moov.udta.meta.ilst.trkn.data"; + MP4BytesProperty *pMetadataProperty = NULL; + MP4Atom *pMetaAtom = NULL; + + pMetaAtom = m_pRootAtom->FindAtom(s); + + if (!pMetaAtom) + { + if (!CreateMetadataAtom("trkn")) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(s); + } + + memset(t, 0, 9*sizeof(unsigned char)); + t[2] = (unsigned char)(track>>8)&0xFF; + t[3] = (unsigned char)(track)&0xFF; + t[4] = (unsigned char)(totalTracks>>8)&0xFF; + t[5] = (unsigned char)(totalTracks)&0xFF; + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + pMetadataProperty->SetValue((u_int8_t*)t, 8); + + return true; +} + +bool MP4File::GetMetadataTrack(u_int16_t* track, u_int16_t* totalTracks) +{ + unsigned char *val = NULL; + u_int32_t valSize = 0; + const char *s = "moov.udta.meta.ilst.trkn.data.metadata"; + + *track = 0; + *totalTracks = 0; + + GetBytesProperty(s, (u_int8_t**)&val, &valSize); + + if (valSize != 8) + return false; + + *track = (u_int16_t)(val[3]); + *track += (u_int16_t)(val[2]<<8); + *totalTracks = (u_int16_t)(val[5]); + *totalTracks += (u_int16_t)(val[4]<<8); + + return true; +} + +bool MP4File::DeleteMetadataTrack() +{ + return DeleteMetadataAtom("trkn"); +} + +bool MP4File::SetMetadataDisk(u_int16_t disk, u_int16_t totalDisks) +{ + unsigned char t[9]; + const char *s = "moov.udta.meta.ilst.disk.data"; + MP4BytesProperty *pMetadataProperty = NULL; + MP4Atom *pMetaAtom = NULL; + + pMetaAtom = m_pRootAtom->FindAtom(s); + + if (!pMetaAtom) + { + if (!CreateMetadataAtom("disk")) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(s); + } + + memset(t, 0, 9*sizeof(unsigned char)); + t[2] = (unsigned char)(disk>>8)&0xFF; + t[3] = (unsigned char)(disk)&0xFF; + t[4] = (unsigned char)(totalDisks>>8)&0xFF; + t[5] = (unsigned char)(totalDisks)&0xFF; + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + pMetadataProperty->SetValue((u_int8_t*)t, 8); + + return true; +} + +bool MP4File::GetMetadataDisk(u_int16_t* disk, u_int16_t* totalDisks) +{ + unsigned char *val = NULL; + u_int32_t valSize = 0; + const char *s = "moov.udta.meta.ilst.disk.data.metadata"; + + *disk = 0; + *totalDisks = 0; + + GetBytesProperty(s, (u_int8_t**)&val, &valSize); + + if (valSize != 8) + return false; + + *disk = (u_int16_t)(val[3]); + *disk += (u_int16_t)(val[2]<<8); + *totalDisks = (u_int16_t)(val[5]); + *totalDisks += (u_int16_t)(val[4]<<8); + + return true; +} + +bool MP4File::DeleteMetadataDisk() +{ + return DeleteMetadataAtom("disk"); +} + +static const char* ID3v1GenreList[] = { + "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", + "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", + "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", + "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", + "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", + "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House", + "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", + "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", + "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", + "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", + "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret", + "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", + "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", + "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", + "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", + "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band", + "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", + "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", + "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", + "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", + "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall", + "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror", + "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat", + "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C", + "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", + "SynthPop", +}; + +int GenreToString(char** GenreStr, const int genre) +{ + if (genre > 0 && + genre <= (int)(sizeof(ID3v1GenreList)/sizeof(*ID3v1GenreList))) + { + *GenreStr = (char*)malloc((strlen(ID3v1GenreList[genre-1])+1)*sizeof(char)); + memset(*GenreStr, 0, (strlen(ID3v1GenreList[genre-1])+1)*sizeof(char)); + strcpy(*GenreStr, ID3v1GenreList[genre-1]); + return 0; + } else { + *GenreStr = (char*)malloc(2*sizeof(char)); + memset(*GenreStr, 0, 2*sizeof(char)); + return 1; + } +} + +int StringToGenre(const char* GenreStr) +{ + unsigned int i; + + for (i = 0; i < sizeof(ID3v1GenreList)/sizeof(*ID3v1GenreList); i++) + { + if (strcasecmp(GenreStr, ID3v1GenreList[i]) == 0) + return i+1; + } + return 0; +} + +bool MP4File::SetMetadataGenre(const char* value) +{ + u_int16_t genreIndex = 0; + unsigned char t[3]; + MP4BytesProperty *pMetadataProperty = NULL; + MP4Atom *pMetaAtom = NULL; + + genreIndex = StringToGenre(value); + + const char *s = "moov.udta.meta.ilst.gnre.data"; + const char *sroot = "moov.udta.meta.ilst.gnre"; + const char *s2 = "moov.udta.meta.ilst.\251gen.data"; + const char *s2root = "moov.udta.meta.ilst.\251gen"; + if (genreIndex != 0) + { + pMetaAtom = m_pRootAtom->FindAtom(s); + if (!pMetaAtom) + { + if (!CreateMetadataAtom("gnre")) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(s); + } + + memset(t, 0, 3*sizeof(unsigned char)); + t[0] = (unsigned char)(genreIndex>>8)&0xFF; + t[1] = (unsigned char)(genreIndex)&0xFF; + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + pMetadataProperty->SetValue((u_int8_t*)t, 2); + + // remove other style of genre atom, if this one is added + pMetaAtom = m_pRootAtom->FindAtom(s2root); + if (pMetaAtom != NULL) { + MP4Atom *pParent = pMetaAtom->GetParentAtom(); + pParent->DeleteChildAtom(pMetaAtom); + delete pMetaAtom; + } + + + (void)DeleteMetadataAtom( "\251gen" ); + + return true; + } else { + pMetaAtom = m_pRootAtom->FindAtom(s2); + + if (!pMetaAtom) + { + if (!CreateMetadataAtom("\251gen")) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(s2); + } + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + pMetadataProperty->SetValue((u_int8_t*)value, strlen(value)); + + // remove other gnre atom if this one is entered + pMetaAtom = m_pRootAtom->FindAtom(sroot); + if (pMetaAtom != NULL) { + MP4Atom *pParent = pMetaAtom->GetParentAtom(); + pParent->DeleteChildAtom(pMetaAtom); + delete pMetaAtom; + } + return true; + } + + return false; +} + +bool MP4File::GetMetadataGenre(char** value) +{ + u_int16_t genreIndex = 0; + unsigned char *val = NULL; + u_int32_t valSize = 0; + const char *t = "moov.udta.meta.ilst.gnre"; + const char *s = "moov.udta.meta.ilst.gnre.data.metadata"; + + *value = NULL; + + MP4Atom *gnre = FindAtom(t); + + if (gnre) + { + GetBytesProperty(s, (u_int8_t**)&val, &valSize); + + if (valSize != 2) + return false; + + genreIndex = (u_int16_t)(val[1]); + genreIndex += (u_int16_t)(val[0]<<8); + + GenreToString(value, genreIndex); + + (void)DeleteMetadataAtom( "gnre" ); + + return true; + } else { + const char *s2 = "moov.udta.meta.ilst.\251gen.data.metadata"; + + val = NULL; + valSize = 0; + + GetBytesProperty(s2, (u_int8_t**)&val, &valSize); + + if (valSize > 0) + { + *value = (char*)malloc((valSize+1)*sizeof(unsigned char)); + memset(*value, 0, (valSize+1)*sizeof(unsigned char)); + memcpy(*value, val, valSize*sizeof(unsigned char)); + return true; + } else { + return false; + } + } + + return false; +} + +bool MP4File::DeleteMetadataGenre() +{ + bool val1 = DeleteMetadataAtom("\251gen"); + bool val2 = DeleteMetadataAtom("gnre"); + return val1 || val2; +} + +bool MP4File::SetMetadataGrouping(const char* value) +{ + return SetMetadataString("\251grp", value); +} + +bool MP4File::GetMetadataGrouping(char** value) +{ + return GetMetadataString("\251grp", value); +} + +bool MP4File::DeleteMetadataGrouping() +{ + return DeleteMetadataAtom("\251grp"); +} + +bool MP4File::SetMetadataTempo(u_int16_t tempo) +{ + unsigned char t[3]; + const char *s = "moov.udta.meta.ilst.tmpo.data"; + MP4BytesProperty *pMetadataProperty = NULL; + MP4Atom *pMetaAtom = NULL; + + pMetaAtom = m_pRootAtom->FindAtom(s); + + if (!pMetaAtom) + { + if (!CreateMetadataAtom("tmpo")) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(s); + } + + memset(t, 0, 3*sizeof(unsigned char)); + t[0] = (unsigned char)(tempo>>8)&0xFF; + t[1] = (unsigned char)(tempo)&0xFF; + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + pMetadataProperty->SetValue((u_int8_t*)t, 2); + + return true; +} + +bool MP4File::GetMetadataTempo(u_int16_t* tempo) +{ + unsigned char *val = NULL; + u_int32_t valSize = 0; + const char *s = "moov.udta.meta.ilst.tmpo.data.metadata"; + + *tempo = 0; + + GetBytesProperty(s, (u_int8_t**)&val, &valSize); + + if (valSize != 2) + return false; + + *tempo = (u_int16_t)(val[1]); + *tempo += (u_int16_t)(val[0]<<8); + + return true; +} + +bool MP4File::DeleteMetadataTempo() +{ + return DeleteMetadataAtom("tmpo"); +} + +bool MP4File::SetMetadataCompilation(u_int8_t compilation) +{ + const char *s = "moov.udta.meta.ilst.cpil.data"; + MP4BytesProperty *pMetadataProperty = NULL; + MP4Atom *pMetaAtom = NULL; + + pMetaAtom = m_pRootAtom->FindAtom(s); + + if (!pMetaAtom) + { + if (!CreateMetadataAtom("cpil")) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(s); + } + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + compilation &= 0x1; + pMetadataProperty->SetValue((u_int8_t*)&compilation, 1); + + return true; +} + +bool MP4File::GetMetadataCompilation(u_int8_t* compilation) +{ + unsigned char *val = NULL; + u_int32_t valSize = 0; + const char *s = "moov.udta.meta.ilst.cpil.data.metadata"; + + *compilation = 0; + + GetBytesProperty(s, (u_int8_t**)&val, &valSize); + + if (valSize != 1) + return false; + + *compilation = (u_int16_t)(val[0]); + + return true; +} + +bool MP4File::DeleteMetadataCompilation() +{ + return DeleteMetadataAtom("cpil"); +} + +bool MP4File::SetMetadataCoverArt(u_int8_t *coverArt, u_int32_t size) +{ + const char *s = "moov.udta.meta.ilst.covr.data"; + MP4BytesProperty *pMetadataProperty = NULL; + MP4Atom *pMetaAtom = NULL; + + pMetaAtom = m_pRootAtom->FindAtom(s); + + if (!pMetaAtom) + { + if (!CreateMetadataAtom("covr")) + return false; + + pMetaAtom = m_pRootAtom->FindAtom(s); + } + + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + + pMetadataProperty->SetValue(coverArt, size); + + return true; +} + +bool MP4File::GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t *size) +{ + const char *s = "moov.udta.meta.ilst.covr.data.metadata"; + + *coverArt = NULL; + *size = 0; + + GetBytesProperty(s, coverArt, size); + + if (size == 0) + return false; + + return true; +} + +bool MP4File::DeleteMetadataCoverArt() +{ + return DeleteMetadataAtom("covr"); +} + +bool MP4File::SetMetadataFreeForm(char *name, u_int8_t* pValue, u_int32_t valueSize) +{ + MP4Atom *pMetaAtom = NULL; + MP4BytesProperty *pMetadataProperty = NULL; + char s[256]; + int i = 0; + + while (1) + { + MP4BytesProperty *pMetadataProperty; + + sprintf(s, "moov.udta.meta.ilst.----[%u].name", i); + + MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s); + + if (!pTagAtom) + break; + + pTagAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty); + if (pMetadataProperty) + { + u_int8_t* pV; + u_int32_t VSize = 0; + + pMetadataProperty->GetValue(&pV, &VSize); + + if (VSize != 0) + { + if (memcmp(pV, name, VSize) == 0) + { + sprintf(s, "moov.udta.meta.ilst.----[%u].data.metadata", i); + SetBytesProperty(s, pValue, valueSize); + + return true; + } + } + } + + i++; + } + + /* doesn't exist yet, create it */ + char t[256]; + + sprintf(t, "udta.meta.ilst.----[%u]", i); + sprintf(s, "moov.udta.meta.ilst.----[%u].data", i); + AddDescendantAtoms("moov", t); + + pMetaAtom = m_pRootAtom->FindAtom(s); + + if (!pMetaAtom) + return false; + + pMetaAtom->SetFlags(0x1); + + MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr"); + MP4StringProperty *pStringProperty = NULL; + MP4BytesProperty *pBytesProperty = NULL; + ASSERT(pHdlrAtom); + + pHdlrAtom->FindProperty( + "hdlr.handlerType", (MP4Property**)&pStringProperty); + ASSERT(pStringProperty); + pStringProperty->SetValue("mdir"); + + u_int8_t val[12]; + memset(val, 0, 12*sizeof(u_int8_t)); + val[0] = 0x61; + val[1] = 0x70; + val[2] = 0x70; + val[3] = 0x6c; + pHdlrAtom->FindProperty( + "hdlr.reserved2", (MP4Property**)&pBytesProperty); + ASSERT(pBytesProperty); + pBytesProperty->SetReadOnly(false); + pBytesProperty->SetValue(val, 12); + pBytesProperty->SetReadOnly(true); + + pMetaAtom = m_pRootAtom->FindAtom(s); + pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + pMetadataProperty->SetValue(pValue, valueSize); + + sprintf(s, "moov.udta.meta.ilst.----[%u].name", i); + pMetaAtom = m_pRootAtom->FindAtom(s); + pMetaAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + pMetadataProperty->SetValue((u_int8_t*)name, strlen(name)); + + sprintf(s, "moov.udta.meta.ilst.----[%u].mean", i); + pMetaAtom = m_pRootAtom->FindAtom(s); + pMetaAtom->FindProperty("mean.metadata", (MP4Property**)&pMetadataProperty); + ASSERT(pMetadataProperty); + pMetadataProperty->SetValue((u_int8_t*)"com.apple.iTunes", 16); /* ?? */ + + return true; +} + +bool MP4File::GetMetadataFreeForm(char *name, u_int8_t** ppValue, u_int32_t *pValueSize) +{ + char s[256]; + int i = 0; + + *ppValue = NULL; + *pValueSize = 0; + + while (1) + { + MP4BytesProperty *pMetadataProperty; + + sprintf(s, "moov.udta.meta.ilst.----[%u].name", i); + + MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s); + + if (!pTagAtom) + return false; + + pTagAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty); + if (pMetadataProperty) + { + u_int8_t* pV; + u_int32_t VSize = 0; + + pMetadataProperty->GetValue(&pV, &VSize); + + if (VSize != 0) + { + if (memcmp(pV, name, VSize) == 0) + { + sprintf(s, "moov.udta.meta.ilst.----[%u].data.metadata", i); + GetBytesProperty(s, ppValue, pValueSize); + + return true; + } + } + } + + i++; + } +} + +bool MP4File::DeleteMetadataFreeForm(char *name) +{ + char s[256]; + int i = 0; + + while (1) + { + MP4BytesProperty *pMetadataProperty; + + sprintf(s, "moov.udta.meta.ilst.----[%u].name", i); + + MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s); + + if (!pTagAtom) + return false; + + pTagAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty); + if (pMetadataProperty) + { + u_int8_t* pV; + u_int32_t VSize = 0; + + pMetadataProperty->GetValue(&pV, &VSize); + + if (VSize != 0) + { + if (memcmp(pV, name, VSize) == 0) + { + sprintf(s, "----[%u]", i); + + return DeleteMetadataAtom(s); + } + } + } + + i++; + } +} + +bool MP4File::MetadataDelete() +{ + MP4Atom *pMetaAtom = NULL; + char s[256]; + + sprintf(s, "moov.udta.meta"); + pMetaAtom = m_pRootAtom->FindAtom(s); + + /* if it exists, delete it */ + if (pMetaAtom) + { + MP4Atom *pParent = pMetaAtom->GetParentAtom(); + + pParent->DeleteChildAtom(pMetaAtom); + + delete pMetaAtom; + + return true; + } + + return false; +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4property.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4property.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,925 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4Property::MP4Property(const char* name) +{ + m_name = name; + m_pParentAtom = NULL; + m_readOnly = false; + m_implicit = false; +} + +bool MP4Property::FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + if (name == NULL) { + return false; + } + + if (!strcasecmp(m_name, name)) { + if (m_pParentAtom) { + VERBOSE_FIND(m_pParentAtom->GetFile()->GetVerbosity(), + printf("FindProperty: matched %s\n", name)); + } + + *ppProperty = this; + return true; + } + return false; +} + +// Integer Property + +u_int64_t MP4IntegerProperty::GetValue(u_int32_t index) +{ + switch (this->GetType()) { + case Integer8Property: + return ((MP4Integer8Property*)this)->GetValue(index); + case Integer16Property: + return ((MP4Integer16Property*)this)->GetValue(index); + case Integer24Property: + return ((MP4Integer24Property*)this)->GetValue(index); + case Integer32Property: + return ((MP4Integer32Property*)this)->GetValue(index); + case Integer64Property: + return ((MP4Integer64Property*)this)->GetValue(index); + default: + ASSERT(FALSE); + } + return (0); +} + +void MP4IntegerProperty::SetValue(u_int64_t value, u_int32_t index) +{ + switch (this->GetType()) { + case Integer8Property: + ((MP4Integer8Property*)this)->SetValue(value, index); + break; + case Integer16Property: + ((MP4Integer16Property*)this)->SetValue(value, index); + break; + case Integer24Property: + ((MP4Integer24Property*)this)->SetValue(value, index); + break; + case Integer32Property: + ((MP4Integer32Property*)this)->SetValue(value, index); + break; + case Integer64Property: + ((MP4Integer64Property*)this)->SetValue(value, index); + break; + default: + ASSERT(FALSE); + } +} + +void MP4IntegerProperty::InsertValue(u_int64_t value, u_int32_t index) +{ + switch (this->GetType()) { + case Integer8Property: + ((MP4Integer8Property*)this)->InsertValue(value, index); + break; + case Integer16Property: + ((MP4Integer16Property*)this)->InsertValue(value, index); + break; + case Integer24Property: + ((MP4Integer24Property*)this)->InsertValue(value, index); + break; + case Integer32Property: + ((MP4Integer32Property*)this)->InsertValue(value, index); + break; + case Integer64Property: + ((MP4Integer64Property*)this)->InsertValue(value, index); + break; + default: + ASSERT(FALSE); + } +} + +void MP4IntegerProperty::DeleteValue(u_int32_t index) +{ + switch (this->GetType()) { + case Integer8Property: + ((MP4Integer8Property*)this)->DeleteValue(index); + break; + case Integer16Property: + ((MP4Integer16Property*)this)->DeleteValue(index); + break; + case Integer24Property: + ((MP4Integer24Property*)this)->DeleteValue(index); + break; + case Integer32Property: + ((MP4Integer32Property*)this)->DeleteValue(index); + break; + case Integer64Property: + ((MP4Integer64Property*)this)->DeleteValue(index); + break; + default: + ASSERT(FALSE); + } +} + +void MP4IntegerProperty::IncrementValue(int32_t increment, u_int32_t index) +{ + SetValue(GetValue() + increment); +} + +void MP4Integer8Property::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + if (index != 0) + fprintf(pFile, "%s[%u] = %u (0x%02x)\n", + m_name, index, m_values[index], m_values[index]); + else + fprintf(pFile, "%s = %u (0x%02x)\n", + m_name, m_values[index], m_values[index]); + fflush(pFile); +} + +void MP4Integer16Property::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + if (index != 0) + fprintf(pFile, "%s[%u] = %u (0x%04x)\n", + m_name, index, m_values[index], m_values[index]); + else + fprintf(pFile, "%s = %u (0x%04x)\n", + m_name, m_values[index], m_values[index]); + fflush(pFile); +} + +void MP4Integer24Property::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + if (index != 0) + fprintf(pFile, "%s[%u] = %u (0x%06x)\n", + m_name, index, m_values[index], m_values[index]); + else + fprintf(pFile, "%s = %u (0x%06x)\n", + m_name, m_values[index], m_values[index]); + fflush(pFile); +} + +void MP4Integer32Property::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + if (index != 0) + fprintf(pFile, "%s[%u] = %u (0x%08x)\n", + m_name, index, m_values[index], m_values[index]); + else + fprintf(pFile, "%s = %u (0x%08x)\n", + m_name, m_values[index], m_values[index]); + fflush(pFile); +} + +void MP4Integer64Property::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + if (index != 0) + fprintf(pFile, "%s[%u] = %llu (0x%016llxf)\n", + m_name, index, m_values[index], m_values[index]); + else + fprintf(pFile, + "%s = %llu (0x%016llxf)\n", + m_name, m_values[index], m_values[index]); + fflush(pFile); +} + +// MP4BitfieldProperty + +void MP4BitfieldProperty::Read(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + m_values[index] = pFile->ReadBits(m_numBits); +} + +void MP4BitfieldProperty::Write(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + pFile->WriteBits(m_values[index], m_numBits); +} + +void MP4BitfieldProperty::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + + u_int8_t hexWidth = m_numBits / 4; + if (hexWidth == 0 || (m_numBits % 4)) { + hexWidth++; + } + if (index != 0) + fprintf(pFile, + "%s[%u] = %llu (0x%0*llxf) <%u bits>\n", + m_name, index, m_values[index], (int)hexWidth, m_values[index], m_numBits); + else + fprintf(pFile, + "%s = %llu (0x%0*llxf) <%u bits>\n", + m_name, m_values[index], (int)hexWidth, m_values[index], m_numBits); + fflush(pFile); +} + +// MP4Float32Property + +void MP4Float32Property::Read(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + if (m_useFixed16Format) { + m_values[index] = pFile->ReadFixed16(); + } else if (m_useFixed32Format) { + m_values[index] = pFile->ReadFixed32(); + } else { + m_values[index] = pFile->ReadFloat(); + } +} + +void MP4Float32Property::Write(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + if (m_useFixed16Format) { + pFile->WriteFixed16(m_values[index]); + } else if (m_useFixed32Format) { + pFile->WriteFixed32(m_values[index]); + } else { + pFile->WriteFloat(m_values[index]); + } +} + +void MP4Float32Property::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + if (index != 0) + fprintf(pFile, "%s[%u] = %f\n", + m_name, index, m_values[index]); + else + fprintf(pFile, "%s = %f\n", + m_name, m_values[index]); + fflush(pFile); +} + +// MP4StringProperty + +MP4StringProperty::MP4StringProperty(char* name, + bool useCountedFormat, bool useUnicode) + : MP4Property(name) +{ + SetCount(1); + m_values[0] = NULL; + m_useCountedFormat = useCountedFormat; + m_useExpandedCount = false; + m_useUnicode = useUnicode; + m_fixedLength = 0; // length not fixed +} + +MP4StringProperty::~MP4StringProperty() +{ + u_int32_t count = GetCount(); + for (u_int32_t i = 0; i < count; i++) { + MP4Free(m_values[i]); + } +} + +void MP4StringProperty::SetCount(u_int32_t count) +{ + u_int32_t oldCount = m_values.Size(); + + m_values.Resize(count); + + for (u_int32_t i = oldCount; i < count; i++) { + m_values[i] = NULL; + } +} + +void MP4StringProperty::SetValue(const char* value, u_int32_t index) +{ + if (m_readOnly) { + throw new MP4Error(EACCES, "property is read-only", m_name); + } + + MP4Free(m_values[index]); + + if (m_fixedLength) { + m_values[index] = (char*)MP4Calloc(m_fixedLength + 1); + if (value) { + strncpy(m_values[index], value, m_fixedLength); + } + } else { + if (value) { + m_values[index] = MP4Stralloc(value); + } else { + m_values[index] = NULL; + } + } +} + +void MP4StringProperty::Read(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + if (m_useCountedFormat) { + m_values[index] = pFile->ReadCountedString( + (m_useUnicode ? 2 : 1), m_useExpandedCount); + } else if (m_fixedLength) { + MP4Free(m_values[index]); + m_values[index] = (char*)MP4Calloc(m_fixedLength + 1); + pFile->ReadBytes((u_int8_t*)m_values[index], m_fixedLength); + } else { + m_values[index] = pFile->ReadString(); + } +} + +void MP4StringProperty::Write(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + if (m_useCountedFormat) { + pFile->WriteCountedString(m_values[index], + (m_useUnicode ? 2 : 1), m_useExpandedCount); + } else if (m_fixedLength) { + pFile->WriteBytes((u_int8_t*)m_values[index], m_fixedLength); + } else { + pFile->WriteString(m_values[index]); + } +} + +void MP4StringProperty::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + char indexd[32]; + if (index != 0) { + sprintf(indexd, "[%u]", index); + } else indexd[0] = '\0'; + + if (m_useUnicode) { + fprintf(pFile, "%s%s = %ls\n", m_name, indexd, (wchar_t*)m_values[index]); + } else { + fprintf(pFile, "%s%s = %s\n", m_name, indexd, m_values[index]); + } + fflush(pFile); +} + +// MP4BytesProperty + +MP4BytesProperty::MP4BytesProperty(char* name, u_int32_t valueSize, + u_int32_t defaultValueSize) + : MP4Property(name) +{ + SetCount(1); + m_values[0] = (u_int8_t*)MP4Calloc(valueSize); + m_valueSizes[0] = valueSize; + m_fixedValueSize = 0; + m_defaultValueSize = defaultValueSize; +} + +MP4BytesProperty::~MP4BytesProperty() +{ + u_int32_t count = GetCount(); + for (u_int32_t i = 0; i < count; i++) { + MP4Free(m_values[i]); + } +} + +void MP4BytesProperty::SetCount(u_int32_t count) +{ + u_int32_t oldCount = m_values.Size(); + + m_values.Resize(count); + m_valueSizes.Resize(count); + + for (u_int32_t i = oldCount; i < count; i++) { + m_values[i] = NULL; + m_valueSizes[i] = m_defaultValueSize; + } +} + +void MP4BytesProperty::SetValue(const u_int8_t* pValue, u_int32_t valueSize, + u_int32_t index) +{ + if (m_readOnly) { + throw new MP4Error(EACCES, "property is read-only", m_name); + } + if (m_fixedValueSize) { + if (valueSize > m_fixedValueSize) { + throw new MP4Error("%s.%s value size %d exceeds fixed value size %d", + "MP4BytesProperty::SetValue", + GetParentAtom()->GetType(), + GetName(), + valueSize, + m_fixedValueSize); + } + if (m_values[index] == NULL) { + m_values[index] = (u_int8_t*)MP4Calloc(m_fixedValueSize); + m_valueSizes[index] = m_fixedValueSize; + } + if (pValue) { + memcpy(m_values[index], pValue, valueSize); + } + } else { + MP4Free(m_values[index]); + if (pValue) { + m_values[index] = (u_int8_t*)MP4Malloc(valueSize); + memcpy(m_values[index], pValue, valueSize); + m_valueSizes[index] = valueSize; + } else { + m_values[index] = NULL; + m_valueSizes[index] = 0; + } + } +} + +void MP4BytesProperty::SetValueSize(u_int32_t valueSize, u_int32_t index) +{ + if (m_fixedValueSize) { + throw new MP4Error("can't change size of fixed sized property", + "MP4BytesProperty::SetValueSize"); + } + if (m_values[index] != NULL) { + m_values[index] = (u_int8_t*)MP4Realloc(m_values[index], valueSize); + } + m_valueSizes[index] = valueSize; +} + +void MP4BytesProperty::SetFixedSize(u_int32_t fixedSize) +{ + m_fixedValueSize = 0; + for (u_int32_t i = 0; i < GetCount(); i++) { + SetValueSize(fixedSize, i); + } + m_fixedValueSize = fixedSize; +} + +void MP4BytesProperty::Read(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + MP4Free(m_values[index]); + m_values[index] = (u_int8_t*)MP4Malloc(m_valueSizes[index]); + pFile->ReadBytes(m_values[index], m_valueSizes[index]); +} + +void MP4BytesProperty::Write(MP4File* pFile, u_int32_t index) +{ + if (m_implicit) { + return; + } + pFile->WriteBytes(m_values[index], m_valueSizes[index]); +} + +void MP4BytesProperty::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + if (m_implicit && !dumpImplicits) { + return; + } + Indent(pFile, indent); + fputs(m_name, pFile); + if (index != 0) fprintf(pFile, "[%u]", index); + fprintf(pFile, " = <%u bytes> ", m_valueSizes[index]); + for (u_int32_t i = 0; i < m_valueSizes[index]; i++) { + if ((i % 16) == 0 && m_valueSizes[index] > 16) { + fprintf(pFile, "\n"); + Indent(pFile, indent); + } + fprintf(pFile, "%02x ", m_values[index][i]); + } + fprintf(pFile, "\n"); + fflush(pFile); +} + +// MP4TableProperty + +MP4TableProperty::MP4TableProperty(char* name, MP4IntegerProperty* pCountProperty) + : MP4Property(name) +{ + m_pCountProperty = pCountProperty; + m_pCountProperty->SetReadOnly(); +} + +MP4TableProperty::~MP4TableProperty() +{ + for (u_int32_t i = 0; i < m_pProperties.Size(); i++) { + delete m_pProperties[i]; + } +} + +void MP4TableProperty::AddProperty(MP4Property* pProperty) +{ + ASSERT(pProperty); + ASSERT(pProperty->GetType() != TableProperty); + ASSERT(pProperty->GetType() != DescriptorProperty); + m_pProperties.Add(pProperty); + pProperty->SetParentAtom(m_pParentAtom); + pProperty->SetCount(0); +} + +bool MP4TableProperty::FindProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + ASSERT(m_name); + + // check if first component of name matches ourselves + if (!MP4NameFirstMatches(m_name, name)) { + return false; + } + + // check if the specified table entry exists + u_int32_t index; + bool haveIndex = MP4NameFirstIndex(name, &index); + if (haveIndex) { + if (index >= GetCount()) { + return false; + } + if (pIndex) { + *pIndex = index; + } + } + + VERBOSE_FIND(m_pParentAtom->GetFile()->GetVerbosity(), + printf("FindProperty: matched %s\n", name)); + + // get name of table property + const char *tablePropName = MP4NameAfterFirst(name); + if (tablePropName == NULL) { + if (!haveIndex) { + *ppProperty = this; + return true; + } + return false; + } + + // check if this table property exists + return FindContainedProperty(tablePropName, ppProperty, pIndex); +} + +bool MP4TableProperty::FindContainedProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + u_int32_t numProperties = m_pProperties.Size(); + + for (u_int32_t i = 0; i < numProperties; i++) { + if (m_pProperties[i]->FindProperty(name, ppProperty, pIndex)) { + return true; + } + } + return false; +} + +void MP4TableProperty::Read(MP4File* pFile, u_int32_t index) +{ + ASSERT(index == 0); + + if (m_implicit) { + return; + } + + u_int32_t numProperties = m_pProperties.Size(); + + if (numProperties == 0) { + WARNING(numProperties == 0); + return; + } + + u_int32_t numEntries = GetCount(); + + /* for each property set size */ + for (u_int32_t j = 0; j < numProperties; j++) { + m_pProperties[j]->SetCount(numEntries); + } + + for (u_int32_t i = 0; i < numEntries; i++) { + ReadEntry(pFile, i); + } +} + +void MP4TableProperty::ReadEntry(MP4File* pFile, u_int32_t index) +{ + for (u_int32_t j = 0; j < m_pProperties.Size(); j++) { + m_pProperties[j]->Read(pFile, index); + } +} + +void MP4TableProperty::Write(MP4File* pFile, u_int32_t index) +{ + ASSERT(index == 0); + + if (m_implicit) { + return; + } + + u_int32_t numProperties = m_pProperties.Size(); + + if (numProperties == 0) { + WARNING(numProperties == 0); + return; + } + + u_int32_t numEntries = GetCount(); + + if (m_pProperties[0]->GetCount() != numEntries) { + fprintf(stderr, "%s \"%s\"table entries %u doesn't match count %u\n", + GetName(), m_pProperties[0]->GetName(), + m_pProperties[0]->GetCount(), numEntries); + + ASSERT(m_pProperties[0]->GetCount() == numEntries); + } + + for (u_int32_t i = 0; i < numEntries; i++) { + WriteEntry(pFile, i); + } +} + +void MP4TableProperty::WriteEntry(MP4File* pFile, u_int32_t index) +{ + for (u_int32_t j = 0; j < m_pProperties.Size(); j++) { + m_pProperties[j]->Write(pFile, index); + } +} + +void MP4TableProperty::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + ASSERT(index == 0); + + // implicit tables just can't be dumped + if (m_implicit) { + return; + } + + u_int32_t numProperties = m_pProperties.Size(); + + if (numProperties == 0) { + WARNING(numProperties == 0); + return; + } + + u_int32_t numEntries = GetCount(); + + for (u_int32_t i = 0; i < numEntries; i++) { + for (u_int32_t j = 0; j < numProperties; j++) { + m_pProperties[j]->Dump(pFile, indent + 1, dumpImplicits, i); + } + } +} + +// MP4DescriptorProperty + +MP4DescriptorProperty::MP4DescriptorProperty(char* name, + u_int8_t tagsStart, u_int8_t tagsEnd, bool mandatory, bool onlyOne) + : MP4Property(name) +{ + SetTags(tagsStart, tagsEnd); + m_sizeLimit = 0; + m_mandatory = mandatory; + m_onlyOne = onlyOne; +} + +MP4DescriptorProperty::~MP4DescriptorProperty() +{ + for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) { + delete m_pDescriptors[i]; + } +} + +void MP4DescriptorProperty::SetParentAtom(MP4Atom* pParentAtom) { + m_pParentAtom = pParentAtom; + for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) { + m_pDescriptors[i]->SetParentAtom(pParentAtom); + } +} + +MP4Descriptor* MP4DescriptorProperty::AddDescriptor(u_int8_t tag) +{ + // check that tag is in expected range + ASSERT(tag >= m_tagsStart && tag <= m_tagsEnd); + + MP4Descriptor* pDescriptor = CreateDescriptor(tag); + ASSERT(pDescriptor); + + m_pDescriptors.Add(pDescriptor); + pDescriptor->SetParentAtom(m_pParentAtom); + + return pDescriptor; +} + +void MP4DescriptorProperty::DeleteDescriptor(u_int32_t index) +{ + delete m_pDescriptors[index]; + m_pDescriptors.Delete(index); +} + +void MP4DescriptorProperty::Generate() +{ + // generate a default descriptor + // if it is mandatory, and single + if (m_mandatory && m_onlyOne) { + MP4Descriptor* pDescriptor = + AddDescriptor(m_tagsStart); + pDescriptor->Generate(); + } +} + +bool MP4DescriptorProperty::FindProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + // we're unnamed, so just check contained properties + if (m_name == NULL || !strcmp(m_name, "")) { + return FindContainedProperty(name, ppProperty, pIndex); + } + + // check if first component of name matches ourselves + if (!MP4NameFirstMatches(m_name, name)) { + return false; + } + + // check if the specific descriptor entry exists + u_int32_t descrIndex; + bool haveDescrIndex = MP4NameFirstIndex(name, &descrIndex); + + if (haveDescrIndex && descrIndex >= GetCount()) { + return false; + } + + if (m_pParentAtom) { + VERBOSE_FIND(m_pParentAtom->GetFile()->GetVerbosity(), + printf("FindProperty: matched %s\n", name)); + } + + // get name of descriptor property + name = MP4NameAfterFirst(name); + if (name == NULL) { + if (!haveDescrIndex) { + *ppProperty = this; + return true; + } + return false; + } + + /* check rest of name */ + if (haveDescrIndex) { + return m_pDescriptors[descrIndex]->FindProperty(name, + ppProperty, pIndex); + } else { + return FindContainedProperty(name, ppProperty, pIndex); + } +} + +bool MP4DescriptorProperty::FindContainedProperty(const char *name, + MP4Property** ppProperty, u_int32_t* pIndex) +{ + for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) { + if (m_pDescriptors[i]->FindProperty(name, ppProperty, pIndex)) { + return true; + } + } + return false; +} + +void MP4DescriptorProperty::Read(MP4File* pFile, u_int32_t index) +{ + ASSERT(index == 0); + + if (m_implicit) { + return; + } + + u_int64_t start = pFile->GetPosition(); + + while (true) { + // enforce size limitation + if (m_sizeLimit && pFile->GetPosition() >= start + m_sizeLimit) { + break; + } + + u_int8_t tag; + try { + pFile->PeekBytes(&tag, 1); + } + catch (MP4Error* e) { + if (pFile->GetPosition() >= pFile->GetSize()) { + // EOF + delete e; + break; + } + throw e; + } + + // check if tag is in desired range + if (tag < m_tagsStart || tag > m_tagsEnd) { + break; + } + + MP4Descriptor* pDescriptor = + AddDescriptor(tag); + + pDescriptor->Read(pFile); + } + + // warnings + if (m_mandatory && m_pDescriptors.Size() == 0) { + VERBOSE_READ(pFile->GetVerbosity(), + printf("Warning: Mandatory descriptor 0x%02x missing\n", + m_tagsStart)); + } else if (m_onlyOne && m_pDescriptors.Size() > 1) { + VERBOSE_READ(pFile->GetVerbosity(), + printf("Warning: Descriptor 0x%02x has more than one instance\n", + m_tagsStart)); + } +} + +void MP4DescriptorProperty::Write(MP4File* pFile, u_int32_t index) +{ + ASSERT(index == 0); + + if (m_implicit) { + return; + } + + for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) { + m_pDescriptors[i]->Write(pFile); + } +} + +void MP4DescriptorProperty::Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index) +{ + ASSERT(index == 0); + + if (m_implicit && !dumpImplicits) { + return; + } + + if (m_name) { + Indent(pFile, indent); + if (index != 0) + fprintf(pFile, "%s[%u]\n", m_name, index); + else + fprintf(pFile, "%s\n", m_name); + indent++; + } + + for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) { + m_pDescriptors[i]->Dump(pFile, indent, dumpImplicits); + } +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4property.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4property.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,543 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __MP4_PROPERTY_INCLUDED__ +#define __MP4_PROPERTY_INCLUDED__ + +// forward declarations +class MP4Atom; + +class MP4Descriptor; +MP4ARRAY_DECL(MP4Descriptor, MP4Descriptor*); + +enum MP4PropertyType { + Integer8Property, + Integer16Property, + Integer24Property, + Integer32Property, + Integer64Property, + Float32Property, + StringProperty, + BytesProperty, + TableProperty, + DescriptorProperty, +}; + +class MP4Property { +public: + MP4Property(const char *name = NULL); + + virtual ~MP4Property() { } + + MP4Atom* GetParentAtom() { + return m_pParentAtom; + } + virtual void SetParentAtom(MP4Atom* pParentAtom) { + m_pParentAtom = pParentAtom; + } + + const char *GetName() { + return m_name; + } + + virtual MP4PropertyType GetType() = 0; + + bool IsReadOnly() { + return m_readOnly; + } + void SetReadOnly(bool value = true) { + m_readOnly = value; + } + + bool IsImplicit() { + return m_implicit; + } + void SetImplicit(bool value = true) { + m_implicit = value; + } + + virtual u_int32_t GetCount() = 0; + virtual void SetCount(u_int32_t count) = 0; + + virtual void Generate() { /* default is a no-op */ }; + + virtual void Read(MP4File* pFile, u_int32_t index = 0) = 0; + + virtual void Write(MP4File* pFile, u_int32_t index = 0) = 0; + + virtual void Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index = 0) = 0; + + virtual bool FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + +protected: + MP4Atom* m_pParentAtom; + const char* m_name; + bool m_readOnly; + bool m_implicit; +}; + +MP4ARRAY_DECL(MP4Property, MP4Property*); + +class MP4IntegerProperty : public MP4Property { +protected: + MP4IntegerProperty(char* name) + : MP4Property(name) { }; + +public: + u_int64_t GetValue(u_int32_t index = 0); + + void SetValue(u_int64_t value, u_int32_t index = 0); + + void InsertValue(u_int64_t value, u_int32_t index = 0); + + void DeleteValue(u_int32_t index = 0); + + void IncrementValue(int32_t increment = 1, u_int32_t index = 0); +}; + +#define MP4INTEGER_PROPERTY_DECL2(isize, xsize) \ + class MP4Integer##xsize##Property : public MP4IntegerProperty { \ + public: \ + MP4Integer##xsize##Property(char* name) \ + : MP4IntegerProperty(name) { \ + SetCount(1); \ + m_values[0] = 0; \ + } \ + \ + MP4PropertyType GetType() { \ + return Integer##xsize##Property; \ + } \ + \ + u_int32_t GetCount() { \ + return m_values.Size(); \ + } \ + void SetCount(u_int32_t count) { \ + m_values.Resize(count); \ + } \ + \ + u_int##isize##_t GetValue(u_int32_t index = 0) { \ + return m_values[index]; \ + } \ + \ + void SetValue(u_int##isize##_t value, u_int32_t index = 0) { \ + if (m_readOnly) { \ + throw new MP4Error(EACCES, "property is read-only", m_name); \ + } \ + m_values[index] = value; \ + } \ + void AddValue(u_int##isize##_t value) { \ + m_values.Add(value); \ + } \ + void InsertValue(u_int##isize##_t value, u_int32_t index) { \ + m_values.Insert(value, index); \ + } \ + void DeleteValue(u_int32_t index) { \ + m_values.Delete(index); \ + } \ + void IncrementValue(int32_t increment = 1, u_int32_t index = 0) { \ + m_values[index] += increment; \ + } \ + void Read(MP4File* pFile, u_int32_t index = 0) { \ + if (m_implicit) { \ + return; \ + } \ + m_values[index] = pFile->ReadUInt##xsize(); \ + } \ + \ + void Write(MP4File* pFile, u_int32_t index = 0) { \ + if (m_implicit) { \ + return; \ + } \ + pFile->WriteUInt##xsize(m_values[index]); \ + } \ + void Dump(FILE* pFile, u_int8_t indent, \ + bool dumpImplicits, u_int32_t index = 0); \ + \ + protected: \ + MP4Integer##isize##Array m_values; \ + }; + +#define MP4INTEGER_PROPERTY_DECL(size) \ + MP4INTEGER_PROPERTY_DECL2(size, size) + +MP4INTEGER_PROPERTY_DECL(8); +MP4INTEGER_PROPERTY_DECL(16); +MP4INTEGER_PROPERTY_DECL2(32, 24); +MP4INTEGER_PROPERTY_DECL(32); +MP4INTEGER_PROPERTY_DECL(64); + +class MP4BitfieldProperty : public MP4Integer64Property { +public: + MP4BitfieldProperty(char* name, u_int8_t numBits) + : MP4Integer64Property(name) { + ASSERT(numBits != 0); + ASSERT(numBits <= 64); + m_numBits = numBits; + } + + u_int8_t GetNumBits() { + return m_numBits; + } + void SetNumBits(u_int8_t numBits) { + m_numBits = numBits; + } + + void Read(MP4File* pFile, u_int32_t index = 0); + void Write(MP4File* pFile, u_int32_t index = 0); + void Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index = 0); + +protected: + u_int8_t m_numBits; +}; + +class MP4Float32Property : public MP4Property { +public: + MP4Float32Property(char* name) + : MP4Property(name) { + m_useFixed16Format = false; + m_useFixed32Format = false; + SetCount(1); + m_values[0] = 0.0; + } + + MP4PropertyType GetType() { + return Float32Property; + } + + u_int32_t GetCount() { + return m_values.Size(); + } + void SetCount(u_int32_t count) { + m_values.Resize(count); + } + + float GetValue(u_int32_t index = 0) { + return m_values[index]; + } + + void SetValue(float value, u_int32_t index = 0) { + if (m_readOnly) { + throw new MP4Error(EACCES, "property is read-only", m_name); + } + m_values[index] = value; + } + + void AddValue(float value) { + m_values.Add(value); + } + + void InsertValue(float value, u_int32_t index) { + m_values.Insert(value, index); + } + + bool IsFixed16Format() { + return m_useFixed16Format; + } + + void SetFixed16Format(bool useFixed16Format = true) { + m_useFixed16Format = useFixed16Format; + } + + bool IsFixed32Format() { + return m_useFixed32Format; + } + + void SetFixed32Format(bool useFixed32Format = true) { + m_useFixed32Format = useFixed32Format; + } + + void Read(MP4File* pFile, u_int32_t index = 0); + void Write(MP4File* pFile, u_int32_t index = 0); + void Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index = 0); + +protected: + bool m_useFixed16Format; + bool m_useFixed32Format; + MP4Float32Array m_values; +}; + +class MP4StringProperty : public MP4Property { +public: + MP4StringProperty(char* name, + bool useCountedFormat = false, bool useUnicode = false); + + ~MP4StringProperty(); + + MP4PropertyType GetType() { + return StringProperty; + } + + u_int32_t GetCount() { + return m_values.Size(); + } + + void SetCount(u_int32_t count); + + const char* GetValue(u_int32_t index = 0) { + return m_values[index]; + } + + void SetValue(const char* value, u_int32_t index = 0); + + void AddValue(const char* value) { + u_int32_t count = GetCount(); + SetCount(count + 1); + SetValue(value, count); + } + + bool IsCountedFormat() { + return m_useCountedFormat; + } + + void SetCountedFormat(bool useCountedFormat) { + m_useCountedFormat = useCountedFormat; + } + + bool IsExpandedCountedFormat() { + return m_useExpandedCount; + } + + void SetExpandedCountedFormat(bool useExpandedCount) { + m_useExpandedCount = useExpandedCount; + } + + bool IsUnicode() { + return m_useUnicode; + } + + void SetUnicode(bool useUnicode) { + m_useUnicode = useUnicode; + } + + u_int32_t GetFixedLength() { + return m_fixedLength; + } + + void SetFixedLength(u_int32_t fixedLength) { + m_fixedLength = fixedLength; + } + + void Read(MP4File* pFile, u_int32_t index = 0); + void Write(MP4File* pFile, u_int32_t index = 0); + void Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index = 0); + +protected: + bool m_useCountedFormat; + bool m_useExpandedCount; + bool m_useUnicode; + u_int32_t m_fixedLength; + + MP4StringArray m_values; +}; + +class MP4BytesProperty : public MP4Property { +public: + MP4BytesProperty(char* name, u_int32_t valueSize = 0, + u_int32_t defaultValueSize = 0); + + ~MP4BytesProperty(); + + MP4PropertyType GetType() { + return BytesProperty; + } + + u_int32_t GetCount() { + return m_values.Size(); + } + + void SetCount(u_int32_t count); + + void GetValue(u_int8_t** ppValue, u_int32_t* pValueSize, + u_int32_t index = 0) { + // N.B. caller must free memory + *ppValue = (u_int8_t*)MP4Malloc(m_valueSizes[index]); + memcpy(*ppValue, m_values[index], m_valueSizes[index]); + *pValueSize = m_valueSizes[index]; + } + + void CopyValue(u_int8_t* pValue, u_int32_t index = 0) { + // N.B. caller takes responsbility for valid pointer + // and sufficient memory at the destination + memcpy(pValue, m_values[index], m_valueSizes[index]); + } + + void SetValue(const u_int8_t* pValue, u_int32_t valueSize, + u_int32_t index = 0); + + void AddValue(const u_int8_t* pValue, u_int32_t valueSize) { + u_int32_t count = GetCount(); + SetCount(count + 1); + SetValue(pValue, valueSize, count); + } + + u_int32_t GetValueSize(u_int32_t valueSize, u_int32_t index = 0) { + return m_valueSizes[index]; + } + + void SetValueSize(u_int32_t valueSize, u_int32_t index = 0); + + u_int32_t GetFixedSize() { + return m_fixedValueSize; + } + + void SetFixedSize(u_int32_t fixedSize); + + void Read(MP4File* pFile, u_int32_t index = 0); + void Write(MP4File* pFile, u_int32_t index = 0); + void Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index = 0); + +protected: + u_int32_t m_fixedValueSize; + u_int32_t m_defaultValueSize; + MP4Integer32Array m_valueSizes; + MP4BytesArray m_values; +}; + +class MP4TableProperty : public MP4Property { +public: + MP4TableProperty(char* name, MP4IntegerProperty* pCountProperty); + + ~MP4TableProperty(); + + MP4PropertyType GetType() { + return TableProperty; + } + + void SetParentAtom(MP4Atom* pParentAtom) { + m_pParentAtom = pParentAtom; + for (u_int32_t i = 0; i < m_pProperties.Size(); i++) { + m_pProperties[i]->SetParentAtom(pParentAtom); + } + } + + void AddProperty(MP4Property* pProperty); + + MP4Property* GetProperty(u_int32_t index) { + return m_pProperties[index]; + } + + u_int32_t GetCount() { + return m_pCountProperty->GetValue(); + } + void SetCount(u_int32_t count) { + m_pCountProperty->SetValue(count); + } + + void Read(MP4File* pFile, u_int32_t index = 0); + void Write(MP4File* pFile, u_int32_t index = 0); + void Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index = 0); + + bool FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + +protected: + virtual void ReadEntry(MP4File* pFile, u_int32_t index); + virtual void WriteEntry(MP4File* pFile, u_int32_t index); + + bool FindContainedProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex); + +protected: + MP4IntegerProperty* m_pCountProperty; + MP4PropertyArray m_pProperties; +}; + +class MP4DescriptorProperty : public MP4Property { +public: + MP4DescriptorProperty(char* name = NULL, + u_int8_t tagsStart = 0, u_int8_t tagsEnd = 0, + bool mandatory = false, bool onlyOne = false); + + ~MP4DescriptorProperty(); + + MP4PropertyType GetType() { + return DescriptorProperty; + } + + void SetParentAtom(MP4Atom* pParentAtom); + + void SetSizeLimit(u_int64_t sizeLimit) { + m_sizeLimit = sizeLimit; + } + + u_int32_t GetCount() { + return m_pDescriptors.Size(); + } + void SetCount(u_int32_t count) { + m_pDescriptors.Resize(count); + } + + void SetTags(u_int8_t tagsStart, u_int8_t tagsEnd = 0) { + m_tagsStart = tagsStart; + m_tagsEnd = tagsEnd ? tagsEnd : tagsStart; + } + + MP4Descriptor* AddDescriptor(u_int8_t tag); + + void AppendDescriptor(MP4Descriptor* pDescriptor) { + m_pDescriptors.Add(pDescriptor); + } + + void DeleteDescriptor(u_int32_t index); + + void Generate(); + void Read(MP4File* pFile, u_int32_t index = 0); + void Write(MP4File* pFile, u_int32_t index = 0); + void Dump(FILE* pFile, u_int8_t indent, + bool dumpImplicits, u_int32_t index = 0); + + bool FindProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex = NULL); + +protected: + virtual MP4Descriptor* CreateDescriptor(u_int8_t tag); + + bool FindContainedProperty(const char* name, + MP4Property** ppProperty, u_int32_t* pIndex); + +protected: + u_int8_t m_tagsStart; + u_int8_t m_tagsEnd; + u_int64_t m_sizeLimit; + bool m_mandatory; + bool m_onlyOne; + MP4DescriptorArray m_pDescriptors; +}; + +class MP4QosQualifierProperty : public MP4DescriptorProperty { +public: + MP4QosQualifierProperty(char* name = NULL, + u_int8_t tagsStart = 0, u_int8_t tagsEnd = 0, + bool mandatory = false, bool onlyOne = false) : + MP4DescriptorProperty(name, tagsStart, tagsEnd, mandatory, onlyOne) { } + +protected: + MP4Descriptor* CreateDescriptor(u_int8_t tag); +}; + +#endif /* __MP4_PROPERTY_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4track.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4track.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,1697 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2004. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Alix Marchandise-Franquet alix@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#include "mp4common.h" + +#define AMR_UNINITIALIZED -1 +#define AMR_TRUE 0 +#define AMR_FALSE 1 + +MP4Track::MP4Track(MP4File* pFile, MP4Atom* pTrakAtom) +{ + m_pFile = pFile; + m_pTrakAtom = pTrakAtom; + + m_lastStsdIndex = 0; + m_lastSampleFile = NULL; + + m_cachedReadSampleId = MP4_INVALID_SAMPLE_ID; + m_pCachedReadSample = NULL; + m_cachedReadSampleSize = 0; + + m_writeSampleId = 1; + m_fixedSampleDuration = 0; + m_pChunkBuffer = NULL; + m_chunkBufferSize = 0; + m_chunkSamples = 0; + m_chunkDuration = 0; + + // m_bytesPerSample should be set to 1, except for the + // quicktime audio constant bit rate samples, which have non-1 values + m_bytesPerSample = 1; + m_samplesPerChunk = 0; + m_durationPerChunk = 0; + m_isAmr = AMR_UNINITIALIZED; + m_curMode = 0; + + bool success = true; + + MP4Integer32Property* pTrackIdProperty; + success &= m_pTrakAtom->FindProperty( + "trak.tkhd.trackId", + (MP4Property**)&pTrackIdProperty); + if (success) { + m_trackId = pTrackIdProperty->GetValue(); + } + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.mdhd.timeScale", + (MP4Property**)&m_pTimeScaleProperty); + if (success) { + // default chunking is 1 second of samples + m_durationPerChunk = m_pTimeScaleProperty->GetValue(); + } + + success &= m_pTrakAtom->FindProperty( + "trak.tkhd.duration", + (MP4Property**)&m_pTrackDurationProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.mdhd.duration", + (MP4Property**)&m_pMediaDurationProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.tkhd.modificationTime", + (MP4Property**)&m_pTrackModificationProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.mdhd.modificationTime", + (MP4Property**)&m_pMediaModificationProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.hdlr.handlerType", + (MP4Property**)&m_pTypeProperty); + + // get handles on sample size information + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsz.sampleSize", + (MP4Property**)&m_pStszFixedSampleSizeProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsz.sampleCount", + (MP4Property**)&m_pStszSampleCountProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsz.entries.sampleSize", + (MP4Property**)&m_pStszSampleSizeProperty); + + // get handles on information needed to map sample id's to file offsets + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsc.entryCount", + (MP4Property**)&m_pStscCountProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsc.entries.firstChunk", + (MP4Property**)&m_pStscFirstChunkProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsc.entries.samplesPerChunk", + (MP4Property**)&m_pStscSamplesPerChunkProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsc.entries.sampleDescriptionIndex", + (MP4Property**)&m_pStscSampleDescrIndexProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsc.entries.firstSample", + (MP4Property**)&m_pStscFirstSampleProperty); + + bool haveStco = m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stco.entryCount", + (MP4Property**)&m_pChunkCountProperty); + + if (haveStco) { + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stco.entries.chunkOffset", + (MP4Property**)&m_pChunkOffsetProperty); + } else { + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.co64.entryCount", + (MP4Property**)&m_pChunkCountProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.co64.entries.chunkOffset", + (MP4Property**)&m_pChunkOffsetProperty); + } + + // get handles on sample timing info + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stts.entryCount", + (MP4Property**)&m_pSttsCountProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stts.entries.sampleCount", + (MP4Property**)&m_pSttsSampleCountProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stts.entries.sampleDelta", + (MP4Property**)&m_pSttsSampleDeltaProperty); + + // get handles on rendering offset info if it exists + + m_pCttsCountProperty = NULL; + m_pCttsSampleCountProperty = NULL; + m_pCttsSampleOffsetProperty = NULL; + + bool haveCtts = m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.ctts.entryCount", + (MP4Property**)&m_pCttsCountProperty); + + if (haveCtts) { + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.ctts.entries.sampleCount", + (MP4Property**)&m_pCttsSampleCountProperty); + + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.ctts.entries.sampleOffset", + (MP4Property**)&m_pCttsSampleOffsetProperty); + } + + // get handles on sync sample info if it exists + + m_pStssCountProperty = NULL; + m_pStssSampleProperty = NULL; + + bool haveStss = m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stss.entryCount", + (MP4Property**)&m_pStssCountProperty); + + if (haveStss) { + success &= m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stss.entries.sampleNumber", + (MP4Property**)&m_pStssSampleProperty); + } + + // edit list + InitEditListProperties(); + + // was everything found? + if (!success) { + throw new MP4Error("invalid track", "MP4Track::MP4Track"); + } + CalculateBytesPerSample(); +} + +MP4Track::~MP4Track() +{ + MP4Free(m_pCachedReadSample); + MP4Free(m_pChunkBuffer); +} + +const char* MP4Track::GetType() +{ + return m_pTypeProperty->GetValue(); +} + +void MP4Track::SetType(const char* type) +{ + m_pTypeProperty->SetValue(MP4NormalizeTrackType(type, + m_pFile->GetVerbosity())); +} + +void MP4Track::ReadSample( + MP4SampleId sampleId, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + MP4Timestamp* pStartTime, + MP4Duration* pDuration, + MP4Duration* pRenderingOffset, + bool* pIsSyncSample) +{ + if (sampleId == MP4_INVALID_SAMPLE_ID) { + throw new MP4Error("sample id can't be zero", + "MP4Track::ReadSample"); + } + + // handle unusual case of wanting to read a sample + // that is still sitting in the write chunk buffer + if (m_pChunkBuffer && sampleId >= m_writeSampleId - m_chunkSamples) { + WriteChunkBuffer(); + } + + FILE* pFile = GetSampleFile(sampleId); + + if (pFile == (FILE*)-1) { + throw new MP4Error("sample is located in an inaccessible file", + "MP4Track::ReadSample"); + } + + u_int64_t fileOffset = GetSampleFileOffset(sampleId); + + u_int32_t sampleSize = GetSampleSize(sampleId); + if (*ppBytes != NULL && *pNumBytes < sampleSize) { + throw new MP4Error("sample buffer is too small", + "MP4Track::ReadSample"); + } + *pNumBytes = sampleSize; + + VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(), + printf("ReadSample: track %u id %u offset 0x"X64" size %u (0x%x)\n", + m_trackId, sampleId, fileOffset, *pNumBytes, *pNumBytes)); + + bool bufferMalloc = false; + if (*ppBytes == NULL) { + *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes); + bufferMalloc = true; + } + + u_int64_t oldPos = m_pFile->GetPosition(pFile); // only used in mode == 'w' + try { + m_pFile->SetPosition(fileOffset, pFile); + m_pFile->ReadBytes(*ppBytes, *pNumBytes, pFile); + + if (pStartTime || pDuration) { + GetSampleTimes(sampleId, pStartTime, pDuration); + + VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(), + printf("ReadSample: start "U64" duration "D64"\n", + (pStartTime ? *pStartTime : 0), + (pDuration ? *pDuration : 0))); + } + if (pRenderingOffset) { + *pRenderingOffset = GetSampleRenderingOffset(sampleId); + + VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(), + printf("ReadSample: renderingOffset "D64"\n", + *pRenderingOffset)); + } + if (pIsSyncSample) { + *pIsSyncSample = IsSyncSample(sampleId); + + VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(), + printf("ReadSample: isSyncSample %u\n", + *pIsSyncSample)); + } + } + + catch (MP4Error* e) { + if (bufferMalloc) { + // let's not leak memory + MP4Free(*ppBytes); + *ppBytes = NULL; + } + if (m_pFile->GetMode() == 'w') { + m_pFile->SetPosition(oldPos, pFile); + } + throw e; + } + + if (m_pFile->GetMode() == 'w') { + m_pFile->SetPosition(oldPos, pFile); + } +} + +void MP4Track::ReadSampleFragment( + MP4SampleId sampleId, + u_int32_t sampleOffset, + u_int16_t sampleLength, + u_int8_t* pDest) +{ + if (sampleId == MP4_INVALID_SAMPLE_ID) { + throw new MP4Error("invalid sample id", + "MP4Track::ReadSampleFragment"); + } + + if (sampleId != m_cachedReadSampleId) { + MP4Free(m_pCachedReadSample); + m_pCachedReadSample = NULL; + m_cachedReadSampleSize = 0; + m_cachedReadSampleId = MP4_INVALID_SAMPLE_ID; + + ReadSample( + sampleId, + &m_pCachedReadSample, + &m_cachedReadSampleSize); + + m_cachedReadSampleId = sampleId; + } + + if (sampleOffset + sampleLength > m_cachedReadSampleSize) { + throw new MP4Error("offset and/or length are too large", + "MP4Track::ReadSampleFragment"); + } + + memcpy(pDest, &m_pCachedReadSample[sampleOffset], sampleLength); +} + +void MP4Track::WriteSample( + const u_int8_t* pBytes, + u_int32_t numBytes, + MP4Duration duration, + MP4Duration renderingOffset, + bool isSyncSample) +{ + u_int8_t curMode = 0; + + VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(), + printf("WriteSample: track %u id %u size %u (0x%x) ", + m_trackId, m_writeSampleId, numBytes, numBytes)); + + if (pBytes == NULL && numBytes > 0) { + throw new MP4Error("no sample data", "MP4WriteSample"); + } + + if (m_isAmr == AMR_UNINITIALIZED ) { + // figure out if this is an AMR audio track + if (m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.samr") || + m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.sawb")) { + m_isAmr = AMR_TRUE; + m_curMode = (pBytes[0] >> 3) & 0x000F; + } else { + m_isAmr = AMR_FALSE; + } + } + + if (m_isAmr == AMR_TRUE) { + curMode = (pBytes[0] >> 3) &0x000F; // The mode is in the first byte + } + + if (duration == MP4_INVALID_DURATION) { + duration = GetFixedSampleDuration(); + } + + VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(), + printf("duration "U64"\n", duration)); + + if ((m_isAmr == AMR_TRUE) && + (m_curMode != curMode)) { + WriteChunkBuffer(); + m_curMode = curMode; + } + + // append sample bytes to chunk buffer + m_pChunkBuffer = (u_int8_t*)MP4Realloc(m_pChunkBuffer, + m_chunkBufferSize + numBytes); + memcpy(&m_pChunkBuffer[m_chunkBufferSize], pBytes, numBytes); + m_chunkBufferSize += numBytes; + m_chunkSamples++; + m_chunkDuration += duration; + + UpdateSampleSizes(m_writeSampleId, numBytes); + + UpdateSampleTimes(duration); + + UpdateRenderingOffsets(m_writeSampleId, renderingOffset); + + UpdateSyncSamples(m_writeSampleId, isSyncSample); + + if (IsChunkFull(m_writeSampleId)) { + WriteChunkBuffer(); + m_curMode = curMode; + } + + UpdateDurations(duration); + + UpdateModificationTimes(); + + m_writeSampleId++; +} + +void MP4Track::WriteChunkBuffer() +{ + if (m_chunkBufferSize == 0) { + return; + } + + u_int64_t chunkOffset = m_pFile->GetPosition(); + + // write chunk buffer + m_pFile->WriteBytes(m_pChunkBuffer, m_chunkBufferSize); + + VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(), + printf("WriteChunk: track %u offset 0x"X64" size %u (0x%x) numSamples %u\n", + m_trackId, chunkOffset, m_chunkBufferSize, + m_chunkBufferSize, m_chunkSamples)); + + UpdateSampleToChunk(m_writeSampleId, + m_pChunkCountProperty->GetValue() + 1, + m_chunkSamples); + + UpdateChunkOffsets(chunkOffset); + + // clean up chunk buffer + MP4Free(m_pChunkBuffer); + m_pChunkBuffer = NULL; + m_chunkBufferSize = 0; + m_chunkSamples = 0; + m_chunkDuration = 0; +} + +void MP4Track::FinishWrite() +{ + // write out any remaining samples in chunk buffer + WriteChunkBuffer(); + + // record buffer size and bitrates + MP4BitfieldProperty* pBufferSizeProperty; + + if (m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsd.*.esds.decConfigDescr.bufferSizeDB", + (MP4Property**)&pBufferSizeProperty)) { + pBufferSizeProperty->SetValue(GetMaxSampleSize()); + } + + MP4Integer32Property* pBitrateProperty; + + if (m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsd.*.esds.decConfigDescr.maxBitrate", + (MP4Property**)&pBitrateProperty)) { + pBitrateProperty->SetValue(GetMaxBitrate()); + } + + if (m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate", + (MP4Property**)&pBitrateProperty)) { + pBitrateProperty->SetValue(GetAvgBitrate()); + } +} + +bool MP4Track::IsChunkFull(MP4SampleId sampleId) +{ + if (m_samplesPerChunk) { + return m_chunkSamples >= m_samplesPerChunk; + } + + ASSERT(m_durationPerChunk); + return m_chunkDuration >= m_durationPerChunk; +} + +u_int32_t MP4Track::GetNumberOfSamples() +{ + return m_pStszSampleCountProperty->GetValue(); +} + +u_int32_t MP4Track::GetSampleSize(MP4SampleId sampleId) +{ + u_int32_t fixedSampleSize = + m_pStszFixedSampleSizeProperty->GetValue(); + + if (fixedSampleSize != 0) { + return fixedSampleSize * m_bytesPerSample; + } + return m_bytesPerSample * + m_pStszSampleSizeProperty->GetValue(sampleId - 1); +} + +u_int32_t MP4Track::GetMaxSampleSize() +{ + u_int32_t fixedSampleSize = + m_pStszFixedSampleSizeProperty->GetValue(); + + if (fixedSampleSize != 0) { + return fixedSampleSize * m_bytesPerSample; + } + + u_int32_t maxSampleSize = 0; + u_int32_t numSamples = m_pStszSampleSizeProperty->GetCount(); + for (MP4SampleId sid = 1; sid <= numSamples; sid++) { + u_int32_t sampleSize = + m_pStszSampleSizeProperty->GetValue(sid - 1); + if (sampleSize > maxSampleSize) { + maxSampleSize = sampleSize; + } + } + return maxSampleSize * m_bytesPerSample; +} + +u_int64_t MP4Track::GetTotalOfSampleSizes() +{ + uint64_t retval; + u_int32_t fixedSampleSize = + m_pStszFixedSampleSizeProperty->GetValue(); + + // if fixed sample size, just need to multiply by number of samples + if (fixedSampleSize != 0) { + retval = m_bytesPerSample; + retval *= fixedSampleSize; + retval *= GetNumberOfSamples(); + return retval; + } + + // else non-fixed sample size, sum them + u_int64_t totalSampleSizes = 0; + u_int32_t numSamples = m_pStszSampleSizeProperty->GetCount(); + for (MP4SampleId sid = 1; sid <= numSamples; sid++) { + u_int32_t sampleSize = + m_pStszSampleSizeProperty->GetValue(sid - 1); + totalSampleSizes += sampleSize; + } + return totalSampleSizes * m_bytesPerSample; +} + +void MP4Track::UpdateSampleSizes(MP4SampleId sampleId, u_int32_t numBytes) +{ + if (m_bytesPerSample > 1) { + if ((numBytes % m_bytesPerSample) != 0) { + // error + VERBOSE_ERROR(m_pFile->GetVerbosity(), + printf("UpdateSampleSize: numBytes %u not divisible by bytesPerSample %u sampleId %u\n", + numBytes, m_bytesPerSample, sampleId); + ); + } + numBytes /= m_bytesPerSample; + } + // for first sample + if (sampleId == 1) { + if (numBytes > 0) { + // presume sample size is fixed + m_pStszFixedSampleSizeProperty->SetValue(numBytes); + } else { + // special case of first sample is zero bytes in length + // leave m_pStszFixedSampleSizeProperty at 0 + // start recording variable sample sizes + m_pStszSampleSizeProperty->AddValue(0); + } + + } else { // sampleId > 1 + u_int32_t fixedSampleSize = + m_pStszFixedSampleSizeProperty->GetValue(); + + if (fixedSampleSize == 0 || numBytes != fixedSampleSize) { + // sample size is not fixed + + if (fixedSampleSize) { + // need to clear fixed sample size + m_pStszFixedSampleSizeProperty->SetValue(0); + + // and create sizes for all previous samples + for (MP4SampleId sid = 1; sid < sampleId; sid++) { + m_pStszSampleSizeProperty->AddValue(fixedSampleSize); + } + } + + // add size value for this sample + m_pStszSampleSizeProperty->AddValue(numBytes); + } + } + + m_pStszSampleCountProperty->IncrementValue(); +} + +u_int32_t MP4Track::GetAvgBitrate() +{ + if (GetDuration() == 0) { + return 0; + } + + double calc = (double) (GetTotalOfSampleSizes()); + // this is a bit better - we use the whole duration + calc *= 8.0; + calc *= GetTimeScale(); + calc /= (double) (GetDuration()); + // we might want to think about rounding to the next 100 or 1000 + return (uint32_t) ceil(calc); +} + +u_int32_t MP4Track::GetMaxBitrate() +{ + u_int32_t timeScale = GetTimeScale(); + MP4SampleId numSamples = GetNumberOfSamples(); + u_int32_t maxBytesPerSec = 0; + u_int32_t bytesThisSec = 0; + MP4Timestamp thisSecStart = 0; + MP4Timestamp lastSampleTime = 0; + uint32_t lastSampleSize = 0; + + MP4SampleId thisSecStartSid = 1; + for (MP4SampleId sid = 1; sid <= numSamples; sid++) { + uint32_t sampleSize; + MP4Timestamp sampleTime; + + sampleSize = GetSampleSize(sid); + GetSampleTimes(sid, &sampleTime, NULL); + + if (sampleTime < thisSecStart + timeScale) { + bytesThisSec += sampleSize; + lastSampleSize = sampleSize; + lastSampleTime = sampleTime; + } else { + // we've already written the last sample and sampleSize. + // this means that we've probably overflowed the last second + // calculate the time we've overflowed + MP4Duration overflow_dur = + (thisSecStart + timeScale) - lastSampleTime; + // calculate the duration of the last sample + MP4Duration lastSampleDur = sampleTime - lastSampleTime; + uint32_t overflow_bytes; + // now, calculate the number of bytes we overflowed. Round up. + overflow_bytes = + ((lastSampleSize * overflow_dur) + (lastSampleDur - 1)) / lastSampleDur; + + if (bytesThisSec - overflow_bytes > maxBytesPerSec) { + maxBytesPerSec = bytesThisSec - overflow_bytes; + } + + // now adjust the values for this sample. Remove the bytes + // from the first sample in this time frame + lastSampleTime = sampleTime; + lastSampleSize = sampleSize; + bytesThisSec += sampleSize; + bytesThisSec -= GetSampleSize(thisSecStartSid); + thisSecStartSid++; + GetSampleTimes(thisSecStartSid, &thisSecStart, NULL); + } + } + + return maxBytesPerSec * 8; +} + +u_int32_t MP4Track::GetSampleStscIndex(MP4SampleId sampleId) +{ + u_int32_t stscIndex; + u_int32_t numStscs = m_pStscCountProperty->GetValue(); + + if (numStscs == 0) { + throw new MP4Error("No data chunks exist", "GetSampleStscIndex"); + } + + for (stscIndex = 0; stscIndex < numStscs; stscIndex++) { + if (sampleId < m_pStscFirstSampleProperty->GetValue(stscIndex)) { + ASSERT(stscIndex != 0); + stscIndex -= 1; + break; + } + } + if (stscIndex == numStscs) { + ASSERT(stscIndex != 0); + stscIndex -= 1; + } + + return stscIndex; +} + +FILE* MP4Track::GetSampleFile(MP4SampleId sampleId) +{ + u_int32_t stscIndex = + GetSampleStscIndex(sampleId); + + u_int32_t stsdIndex = + m_pStscSampleDescrIndexProperty->GetValue(stscIndex); + + // check if the answer will be the same as last time + if (m_lastStsdIndex && stsdIndex == m_lastStsdIndex) { + return m_lastSampleFile; + } + + MP4Atom* pStsdAtom = + m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd"); + ASSERT(pStsdAtom); + + MP4Atom* pStsdEntryAtom = + pStsdAtom->GetChildAtom(stsdIndex - 1); + ASSERT(pStsdEntryAtom); + + MP4Integer16Property* pDrefIndexProperty = NULL; + pStsdEntryAtom->FindProperty( + "*.dataReferenceIndex", + (MP4Property**)&pDrefIndexProperty); + + if (pDrefIndexProperty == NULL) { + throw new MP4Error("invalid stsd entry", "GetSampleFile"); + } + + u_int32_t drefIndex = + pDrefIndexProperty->GetValue(); + + MP4Atom* pDrefAtom = + m_pTrakAtom->FindAtom("trak.mdia.minf.dinf.dref"); + ASSERT(pDrefAtom); + + MP4Atom* pUrlAtom = + pDrefAtom->GetChildAtom(drefIndex - 1); + ASSERT(pUrlAtom); + + FILE* pFile; + + if (pUrlAtom->GetFlags() & 1) { + pFile = NULL; // self-contained + } else { + MP4StringProperty* pLocationProperty = NULL; + pUrlAtom->FindProperty( + "*.location", + (MP4Property**)&pLocationProperty); + ASSERT(pLocationProperty); + + const char* url = pLocationProperty->GetValue(); + + VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(), + printf("dref url = %s\n", url)); + + pFile = (FILE*)-1; + + // attempt to open url if it's a file url + // currently this is the only thing we understand + if (!strncmp(url, "file:", 5)) { + const char* fileName = url + 5; + if (!strncmp(fileName, "//", 2)) { + fileName = strchr(fileName + 2, '/'); + } + if (fileName) { + pFile = fopen(fileName, "rb"); + if (!pFile) { + pFile = (FILE*)-1; + } + } + } + } + + if (m_lastSampleFile) { + fclose(m_lastSampleFile); + } + + // cache the answer + m_lastStsdIndex = stsdIndex; + m_lastSampleFile = pFile; + + return pFile; +} + +u_int64_t MP4Track::GetSampleFileOffset(MP4SampleId sampleId) +{ + u_int32_t stscIndex = + GetSampleStscIndex(sampleId); + + // firstChunk is the chunk index of the first chunk with + // samplesPerChunk samples in the chunk. There may be multiples - + // ie: several chunks with the same number of samples per chunk. + u_int32_t firstChunk = + m_pStscFirstChunkProperty->GetValue(stscIndex); + + MP4SampleId firstSample = + m_pStscFirstSampleProperty->GetValue(stscIndex); + + u_int32_t samplesPerChunk = + m_pStscSamplesPerChunkProperty->GetValue(stscIndex); + + // chunkId tells which is the absolute chunk number that this sample + // is stored in. + MP4ChunkId chunkId = firstChunk + + ((sampleId - firstSample) / samplesPerChunk); + + // chunkOffset is the file offset (absolute) for the start of the chunk + u_int64_t chunkOffset = m_pChunkOffsetProperty->GetValue(chunkId - 1); + + MP4SampleId firstSampleInChunk = + sampleId - ((sampleId - firstSample) % samplesPerChunk); + + // need cumulative samples sizes from firstSample to sampleId - 1 + u_int32_t sampleOffset = 0; + for (MP4SampleId i = firstSampleInChunk; i < sampleId; i++) { + sampleOffset += GetSampleSize(i); + } + + return chunkOffset + sampleOffset; +} + +void MP4Track::UpdateSampleToChunk(MP4SampleId sampleId, + MP4ChunkId chunkId, u_int32_t samplesPerChunk) +{ + u_int32_t numStsc = m_pStscCountProperty->GetValue(); + + // if samplesPerChunk == samplesPerChunk of last entry + if (numStsc && samplesPerChunk == + m_pStscSamplesPerChunkProperty->GetValue(numStsc-1)) { + + // nothing to do + + } else { + // add stsc entry + m_pStscFirstChunkProperty->AddValue(chunkId); + m_pStscSamplesPerChunkProperty->AddValue(samplesPerChunk); + m_pStscSampleDescrIndexProperty->AddValue(1); + m_pStscFirstSampleProperty->AddValue(sampleId - samplesPerChunk + 1); + + m_pStscCountProperty->IncrementValue(); + } +} + +void MP4Track::UpdateChunkOffsets(u_int64_t chunkOffset) +{ + if (m_pChunkOffsetProperty->GetType() == Integer32Property) { + ((MP4Integer32Property*)m_pChunkOffsetProperty)->AddValue(chunkOffset); + } else { + ((MP4Integer64Property*)m_pChunkOffsetProperty)->AddValue(chunkOffset); + } + m_pChunkCountProperty->IncrementValue(); +} + +MP4Duration MP4Track::GetFixedSampleDuration() +{ + u_int32_t numStts = m_pSttsCountProperty->GetValue(); + + if (numStts == 0) { + return m_fixedSampleDuration; + } + if (numStts != 1) { + return MP4_INVALID_DURATION; // sample duration is not fixed + } + return m_pSttsSampleDeltaProperty->GetValue(0); +} + +bool MP4Track::SetFixedSampleDuration(MP4Duration duration) +{ + u_int32_t numStts = m_pSttsCountProperty->GetValue(); + + // setting this is only allowed before samples have been written + if (numStts != 0) { + return false; + } + m_fixedSampleDuration = duration; + return true; +} + +void MP4Track::GetSampleTimes(MP4SampleId sampleId, + MP4Timestamp* pStartTime, MP4Duration* pDuration) +{ + u_int32_t numStts = m_pSttsCountProperty->GetValue(); + MP4SampleId sid = 1; + MP4Duration elapsed = 0; + + for (u_int32_t sttsIndex = 0; sttsIndex < numStts; sttsIndex++) { + u_int32_t sampleCount = + m_pSttsSampleCountProperty->GetValue(sttsIndex); + u_int32_t sampleDelta = + m_pSttsSampleDeltaProperty->GetValue(sttsIndex); + + if (sampleId <= sid + sampleCount - 1) { + if (pStartTime) { + *pStartTime = (sampleId - sid); + *pStartTime *= sampleDelta; + *pStartTime += elapsed; + } + if (pDuration) { + *pDuration = sampleDelta; + } + return; + } + sid += sampleCount; + elapsed += sampleCount * sampleDelta; + } + + throw new MP4Error("sample id out of range", + "MP4Track::GetSampleTimes"); +} + +MP4SampleId MP4Track::GetSampleIdFromTime( + MP4Timestamp when, + bool wantSyncSample) +{ + u_int32_t numStts = m_pSttsCountProperty->GetValue(); + MP4SampleId sid = 1; + MP4Duration elapsed = 0; + + for (u_int32_t sttsIndex = 0; sttsIndex < numStts; sttsIndex++) { + u_int32_t sampleCount = + m_pSttsSampleCountProperty->GetValue(sttsIndex); + u_int32_t sampleDelta = + m_pSttsSampleDeltaProperty->GetValue(sttsIndex); + + if (sampleDelta == 0 && sttsIndex < numStts - 1) { + VERBOSE_READ(m_pFile->GetVerbosity(), + printf("Warning: Zero sample duration, stts entry %u\n", + sttsIndex)); + } + + MP4Duration d = when - elapsed; + + if (d <= sampleCount * sampleDelta) { + MP4SampleId sampleId = sid; + if (sampleDelta) { + sampleId += (d / sampleDelta); + } + + if (wantSyncSample) { + return GetNextSyncSample(sampleId); + } + return sampleId; + } + + sid += sampleCount; + elapsed += sampleCount * sampleDelta; + } + + throw new MP4Error("time out of range", + "MP4Track::GetSampleIdFromTime"); + + return 0; // satisfy MS compiler +} + +void MP4Track::UpdateSampleTimes(MP4Duration duration) +{ + u_int32_t numStts = m_pSttsCountProperty->GetValue(); + + // if duration == duration of last entry + if (numStts + && duration == m_pSttsSampleDeltaProperty->GetValue(numStts-1)) { + // increment last entry sampleCount + m_pSttsSampleCountProperty->IncrementValue(1, numStts-1); + + } else { + // add stts entry, sampleCount = 1, sampleDuration = duration + m_pSttsSampleCountProperty->AddValue(1); + m_pSttsSampleDeltaProperty->AddValue(duration); + m_pSttsCountProperty->IncrementValue();; + } +} + +u_int32_t MP4Track::GetSampleCttsIndex(MP4SampleId sampleId, + MP4SampleId* pFirstSampleId) +{ + u_int32_t numCtts = m_pCttsCountProperty->GetValue(); + + MP4SampleId sid = 1; + + for (u_int32_t cttsIndex = 0; cttsIndex < numCtts; cttsIndex++) { + u_int32_t sampleCount = + m_pCttsSampleCountProperty->GetValue(cttsIndex); + + if (sampleId <= sid + sampleCount - 1) { + if (pFirstSampleId) { + *pFirstSampleId = sid; + } + return cttsIndex; + } + sid += sampleCount; + } + + throw new MP4Error("sample id out of range", + "MP4Track::GetSampleCttsIndex"); + return 0; // satisfy MS compiler +} + +MP4Duration MP4Track::GetSampleRenderingOffset(MP4SampleId sampleId) +{ + if (m_pCttsCountProperty == NULL) { + return 0; + } + if (m_pCttsCountProperty->GetValue() == 0) { + return 0; + } + + u_int32_t cttsIndex = GetSampleCttsIndex(sampleId); + + return m_pCttsSampleOffsetProperty->GetValue(cttsIndex); +} + +void MP4Track::UpdateRenderingOffsets(MP4SampleId sampleId, + MP4Duration renderingOffset) +{ + // if ctts atom doesn't exist + if (m_pCttsCountProperty == NULL) { + + // no rendering offset, so nothing to do + if (renderingOffset == 0) { + return; + } + + // else create a ctts atom + MP4Atom* pCttsAtom = AddAtom("trak.mdia.minf.stbl", "ctts"); + + // and get handles on the properties + pCttsAtom->FindProperty( + "ctts.entryCount", + (MP4Property**)&m_pCttsCountProperty); + + pCttsAtom->FindProperty( + "ctts.entries.sampleCount", + (MP4Property**)&m_pCttsSampleCountProperty); + + pCttsAtom->FindProperty( + "ctts.entries.sampleOffset", + (MP4Property**)&m_pCttsSampleOffsetProperty); + + // if this is not the first sample + if (sampleId > 1) { + // add a ctts entry for all previous samples + // with rendering offset equal to zero + m_pCttsSampleCountProperty->AddValue(sampleId - 1); + m_pCttsSampleOffsetProperty->AddValue(0); + m_pCttsCountProperty->IncrementValue();; + } + } + + // ctts atom exists (now) + + u_int32_t numCtts = m_pCttsCountProperty->GetValue(); + + // if renderingOffset == renderingOffset of last entry + if (numCtts && renderingOffset + == m_pCttsSampleOffsetProperty->GetValue(numCtts-1)) { + + // increment last entry sampleCount + m_pCttsSampleCountProperty->IncrementValue(1, numCtts-1); + + } else { + // add ctts entry, sampleCount = 1, sampleOffset = renderingOffset + m_pCttsSampleCountProperty->AddValue(1); + m_pCttsSampleOffsetProperty->AddValue(renderingOffset); + m_pCttsCountProperty->IncrementValue(); + } +} + +void MP4Track::SetSampleRenderingOffset(MP4SampleId sampleId, + MP4Duration renderingOffset) +{ + // check if any ctts entries exist + if (m_pCttsCountProperty == NULL + || m_pCttsCountProperty->GetValue() == 0) { + // if not then Update routine can be used + // to create a ctts entry for samples before this one + // and a ctts entry for this sample + UpdateRenderingOffsets(sampleId, renderingOffset); + + // but we also need a ctts entry + // for all samples after this one + u_int32_t afterSamples = GetNumberOfSamples() - sampleId; + + if (afterSamples) { + m_pCttsSampleCountProperty->AddValue(afterSamples); + m_pCttsSampleOffsetProperty->AddValue(0); + m_pCttsCountProperty->IncrementValue();; + } + + return; + } + + MP4SampleId firstSampleId; + u_int32_t cttsIndex = GetSampleCttsIndex(sampleId, &firstSampleId); + + // do nothing in the degenerate case + if (renderingOffset == + m_pCttsSampleOffsetProperty->GetValue(cttsIndex)) { + return; + } + + u_int32_t sampleCount = + m_pCttsSampleCountProperty->GetValue(cttsIndex); + + // if this sample has it's own ctts entry + if (sampleCount == 1) { + // then just set the value, + // note we don't attempt to collapse entries + m_pCttsSampleOffsetProperty->SetValue(renderingOffset, cttsIndex); + return; + } + + MP4SampleId lastSampleId = firstSampleId + sampleCount - 1; + + // else we share this entry with other samples + // we need to insert our own entry + if (sampleId == firstSampleId) { + // our sample is the first one + m_pCttsSampleCountProperty-> + InsertValue(1, cttsIndex); + m_pCttsSampleOffsetProperty-> + InsertValue(renderingOffset, cttsIndex); + + m_pCttsSampleCountProperty-> + SetValue(sampleCount - 1, cttsIndex + 1); + + m_pCttsCountProperty->IncrementValue(); + + } else if (sampleId == lastSampleId) { + // our sample is the last one + m_pCttsSampleCountProperty-> + InsertValue(1, cttsIndex + 1); + m_pCttsSampleOffsetProperty-> + InsertValue(renderingOffset, cttsIndex + 1); + + m_pCttsSampleCountProperty-> + SetValue(sampleCount - 1, cttsIndex); + + m_pCttsCountProperty->IncrementValue(); + + } else { + // our sample is in the middle, UGH! + + // insert our new entry + m_pCttsSampleCountProperty-> + InsertValue(1, cttsIndex + 1); + m_pCttsSampleOffsetProperty-> + InsertValue(renderingOffset, cttsIndex + 1); + + // adjust count of previous entry + m_pCttsSampleCountProperty-> + SetValue(sampleId - firstSampleId, cttsIndex); + + // insert new entry for those samples beyond our sample + m_pCttsSampleCountProperty-> + InsertValue(lastSampleId - sampleId, cttsIndex + 2); + u_int32_t oldRenderingOffset = + m_pCttsSampleOffsetProperty->GetValue(cttsIndex); + m_pCttsSampleOffsetProperty-> + InsertValue(oldRenderingOffset, cttsIndex + 2); + + m_pCttsCountProperty->IncrementValue(2); + } +} + +bool MP4Track::IsSyncSample(MP4SampleId sampleId) +{ + if (m_pStssCountProperty == NULL) { + return true; + } + + u_int32_t numStss = m_pStssCountProperty->GetValue(); + + for (u_int32_t stssIndex = 0; stssIndex < numStss; stssIndex++) { + MP4SampleId syncSampleId = + m_pStssSampleProperty->GetValue(stssIndex); + + if (sampleId == syncSampleId) { + return true; + } + if (sampleId < syncSampleId) { + break; + } + } + + return false; +} + +// N.B. "next" is inclusive of this sample id +MP4SampleId MP4Track::GetNextSyncSample(MP4SampleId sampleId) +{ + if (m_pStssCountProperty == NULL) { + return sampleId; + } + + u_int32_t numStss = m_pStssCountProperty->GetValue(); + + for (u_int32_t stssIndex = 0; stssIndex < numStss; stssIndex++) { + MP4SampleId syncSampleId = + m_pStssSampleProperty->GetValue(stssIndex); + + if (sampleId > syncSampleId) { + continue; + } + return syncSampleId; + } + + // LATER check stsh for alternate sample + + return MP4_INVALID_SAMPLE_ID; +} + +void MP4Track::UpdateSyncSamples(MP4SampleId sampleId, bool isSyncSample) +{ + if (isSyncSample) { + // if stss atom exists, add entry + if (m_pStssCountProperty) { + m_pStssSampleProperty->AddValue(sampleId); + m_pStssCountProperty->IncrementValue(); + } // else nothing to do (yet) + + } else { // !isSyncSample + // if stss atom doesn't exist, create one + if (m_pStssCountProperty == NULL) { + + MP4Atom* pStssAtom = AddAtom("trak.mdia.minf.stbl", "stss"); + + pStssAtom->FindProperty( + "stss.entryCount", + (MP4Property**)&m_pStssCountProperty); + + pStssAtom->FindProperty( + "stss.entries.sampleNumber", + (MP4Property**)&m_pStssSampleProperty); + + // set values for all samples that came before this one + for (MP4SampleId sid = 1; sid < sampleId; sid++) { + m_pStssSampleProperty->AddValue(sid); + m_pStssCountProperty->IncrementValue(); + } + } // else nothing to do + } +} + +MP4Atom* MP4Track::AddAtom(char* parentName, char* childName) +{ + MP4Atom* pChildAtom = MP4Atom::CreateAtom(childName); + + MP4Atom* pParentAtom = m_pTrakAtom->FindAtom(parentName); + ASSERT(pParentAtom); + + pParentAtom->AddChildAtom(pChildAtom); + + pChildAtom->Generate(); + + return pChildAtom; +} + +u_int64_t MP4Track::GetDuration() +{ + return m_pMediaDurationProperty->GetValue(); +} + +u_int32_t MP4Track::GetTimeScale() +{ + return m_pTimeScaleProperty->GetValue(); +} + +void MP4Track::UpdateDurations(MP4Duration duration) +{ + // update media, track, and movie durations + m_pMediaDurationProperty->SetValue( + m_pMediaDurationProperty->GetValue() + duration); + + MP4Duration movieDuration = ToMovieDuration(duration); + m_pTrackDurationProperty->SetValue( + m_pTrackDurationProperty->GetValue() + movieDuration); + + m_pFile->UpdateDuration(m_pTrackDurationProperty->GetValue()); +} + +MP4Duration MP4Track::ToMovieDuration(MP4Duration trackDuration) +{ + return (trackDuration * m_pFile->GetTimeScale()) + / m_pTimeScaleProperty->GetValue(); +} + +void MP4Track::UpdateModificationTimes() +{ + // update media and track modification times + MP4Timestamp now = MP4GetAbsTimestamp(); + m_pMediaModificationProperty->SetValue(now); + m_pTrackModificationProperty->SetValue(now); +} + +u_int32_t MP4Track::GetNumberOfChunks() +{ + return m_pChunkOffsetProperty->GetCount(); +} + +u_int32_t MP4Track::GetChunkStscIndex(MP4ChunkId chunkId) +{ + u_int32_t stscIndex; + u_int32_t numStscs = m_pStscCountProperty->GetValue(); + + ASSERT(chunkId); + ASSERT(numStscs > 0); + + for (stscIndex = 0; stscIndex < numStscs; stscIndex++) { + if (chunkId < m_pStscFirstChunkProperty->GetValue(stscIndex)) { + ASSERT(stscIndex != 0); + break; + } + } + return stscIndex - 1; +} + +MP4Timestamp MP4Track::GetChunkTime(MP4ChunkId chunkId) +{ + u_int32_t stscIndex = GetChunkStscIndex(chunkId); + + MP4ChunkId firstChunkId = + m_pStscFirstChunkProperty->GetValue(stscIndex); + + MP4SampleId firstSample = + m_pStscFirstSampleProperty->GetValue(stscIndex); + + u_int32_t samplesPerChunk = + m_pStscSamplesPerChunkProperty->GetValue(stscIndex); + + MP4SampleId firstSampleInChunk = + firstSample + ((chunkId - firstChunkId) * samplesPerChunk); + + MP4Timestamp chunkTime; + + GetSampleTimes(firstSampleInChunk, &chunkTime, NULL); + + return chunkTime; +} + +u_int32_t MP4Track::GetChunkSize(MP4ChunkId chunkId) +{ + u_int32_t stscIndex = GetChunkStscIndex(chunkId); + + MP4ChunkId firstChunkId = + m_pStscFirstChunkProperty->GetValue(stscIndex); + + MP4SampleId firstSample = + m_pStscFirstSampleProperty->GetValue(stscIndex); + + u_int32_t samplesPerChunk = + m_pStscSamplesPerChunkProperty->GetValue(stscIndex); + + MP4SampleId firstSampleInChunk = + firstSample + ((chunkId - firstChunkId) * samplesPerChunk); + + // need cumulative sizes of samples in chunk + u_int32_t chunkSize = 0; + for (u_int32_t i = 0; i < samplesPerChunk; i++) { + chunkSize += GetSampleSize(firstSampleInChunk + i); + } + + return chunkSize; +} + +void MP4Track::ReadChunk(MP4ChunkId chunkId, + u_int8_t** ppChunk, u_int32_t* pChunkSize) +{ + ASSERT(chunkId); + ASSERT(ppChunk); + ASSERT(pChunkSize); + + u_int64_t chunkOffset = + m_pChunkOffsetProperty->GetValue(chunkId - 1); + + *pChunkSize = GetChunkSize(chunkId); + *ppChunk = (u_int8_t*)MP4Malloc(*pChunkSize); + + VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(), + printf("ReadChunk: track %u id %u offset 0x"X64" size %u (0x%x)\n", + m_trackId, chunkId, chunkOffset, *pChunkSize, *pChunkSize)); + + u_int64_t oldPos = m_pFile->GetPosition(); // only used in mode == 'w' + try { + m_pFile->SetPosition(chunkOffset); + m_pFile->ReadBytes(*ppChunk, *pChunkSize); + } + catch (MP4Error* e) { + // let's not leak memory + MP4Free(*ppChunk); + *ppChunk = NULL; + + if (m_pFile->GetMode() == 'w') { + m_pFile->SetPosition(oldPos); + } + throw e; + } + + if (m_pFile->GetMode() == 'w') { + m_pFile->SetPosition(oldPos); + } +} + +void MP4Track::RewriteChunk(MP4ChunkId chunkId, + u_int8_t* pChunk, u_int32_t chunkSize) +{ + u_int64_t chunkOffset = m_pFile->GetPosition(); + + m_pFile->WriteBytes(pChunk, chunkSize); + + m_pChunkOffsetProperty->SetValue(chunkOffset, chunkId - 1); + + VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(), + printf("RewriteChunk: track %u id %u offset 0x"X64" size %u (0x%x)\n", + m_trackId, chunkId, chunkOffset, chunkSize, chunkSize)); +} + +// map track type name aliases to official names + + +bool MP4Track::InitEditListProperties() +{ + m_pElstCountProperty = NULL; + m_pElstMediaTimeProperty = NULL; + m_pElstDurationProperty = NULL; + m_pElstRateProperty = NULL; + m_pElstReservedProperty = NULL; + + MP4Atom* pElstAtom = + m_pTrakAtom->FindAtom("trak.edts.elst"); + + if (!pElstAtom) { + return false; + } + + pElstAtom->FindProperty( + "elst.entryCount", + (MP4Property**)&m_pElstCountProperty); + + pElstAtom->FindProperty( + "elst.entries.mediaTime", + (MP4Property**)&m_pElstMediaTimeProperty); + + pElstAtom->FindProperty( + "elst.entries.segmentDuration", + (MP4Property**)&m_pElstDurationProperty); + + pElstAtom->FindProperty( + "elst.entries.mediaRate", + (MP4Property**)&m_pElstRateProperty); + + pElstAtom->FindProperty( + "elst.entries.reserved", + (MP4Property**)&m_pElstReservedProperty); + + return m_pElstCountProperty + && m_pElstMediaTimeProperty + && m_pElstDurationProperty + && m_pElstRateProperty + && m_pElstReservedProperty; +} + +MP4EditId MP4Track::AddEdit(MP4EditId editId) +{ + if (!m_pElstCountProperty) { + m_pFile->AddDescendantAtoms(m_pTrakAtom, "edts.elst"); + InitEditListProperties(); + } + + if (editId == MP4_INVALID_EDIT_ID) { + editId = m_pElstCountProperty->GetValue() + 1; + } + + m_pElstMediaTimeProperty->InsertValue(0, editId - 1); + m_pElstDurationProperty->InsertValue(0, editId - 1); + m_pElstRateProperty->InsertValue(1, editId - 1); + m_pElstReservedProperty->InsertValue(0, editId - 1); + + m_pElstCountProperty->IncrementValue(); + + return editId; +} + +void MP4Track::DeleteEdit(MP4EditId editId) +{ + if (editId == MP4_INVALID_EDIT_ID) { + throw new MP4Error("edit id can't be zero", + "MP4Track::DeleteEdit"); + } + + if (!m_pElstCountProperty + || m_pElstCountProperty->GetValue() == 0) { + throw new MP4Error("no edits exist", + "MP4Track::DeleteEdit"); + } + + m_pElstMediaTimeProperty->DeleteValue(editId - 1); + m_pElstDurationProperty->DeleteValue(editId - 1); + m_pElstRateProperty->DeleteValue(editId - 1); + m_pElstReservedProperty->DeleteValue(editId - 1); + + m_pElstCountProperty->IncrementValue(-1); + + // clean up if last edit is deleted + if (m_pElstCountProperty->GetValue() == 0) { + m_pElstCountProperty = NULL; + m_pElstMediaTimeProperty = NULL; + m_pElstDurationProperty = NULL; + m_pElstRateProperty = NULL; + m_pElstReservedProperty = NULL; + + m_pTrakAtom->DeleteChildAtom( + m_pTrakAtom->FindAtom("trak.edts")); + } +} + +MP4Timestamp MP4Track::GetEditStart( + MP4EditId editId) +{ + if (editId == MP4_INVALID_EDIT_ID) { + return MP4_INVALID_TIMESTAMP; + } else if (editId == 1) { + return 0; + } + return (MP4Timestamp)GetEditTotalDuration(editId - 1); +} + +MP4Duration MP4Track::GetEditTotalDuration( + MP4EditId editId) +{ + u_int32_t numEdits = 0; + + if (m_pElstCountProperty) { + numEdits = m_pElstCountProperty->GetValue(); + } + + if (editId == MP4_INVALID_EDIT_ID) { + editId = numEdits; + } + + if (numEdits == 0 || editId > numEdits) { + return MP4_INVALID_DURATION; + } + + MP4Duration totalDuration = 0; + + for (MP4EditId eid = 1; eid <= editId; eid++) { + totalDuration += + m_pElstDurationProperty->GetValue(eid - 1); + } + + return totalDuration; +} + +MP4SampleId MP4Track::GetSampleIdFromEditTime( + MP4Timestamp editWhen, + MP4Timestamp* pStartTime, + MP4Duration* pDuration) +{ + MP4SampleId sampleId = MP4_INVALID_SAMPLE_ID; + u_int32_t numEdits = 0; + + if (m_pElstCountProperty) { + numEdits = m_pElstCountProperty->GetValue(); + } + + if (numEdits) { + MP4Duration editElapsedDuration = 0; + + for (MP4EditId editId = 1; editId <= numEdits; editId++) { + // remember edit segment's start time (in edit timeline) + MP4Timestamp editStartTime = + (MP4Timestamp)editElapsedDuration; + + // accumulate edit segment's duration + editElapsedDuration += + m_pElstDurationProperty->GetValue(editId - 1); + + // calculate difference between the specified edit time + // and the end of this edit segment + if (editElapsedDuration - editWhen <= 0) { + // the specified time has not yet been reached + continue; + } + + // 'editWhen' is within this edit segment + + // calculate the specified edit time + // relative to just this edit segment + MP4Duration editOffset = + editWhen - editStartTime; + + // calculate the media (track) time that corresponds + // to the specified edit time based on the edit list + MP4Timestamp mediaWhen = + m_pElstMediaTimeProperty->GetValue(editId - 1) + + editOffset; + + // lookup the sample id for the media time + sampleId = GetSampleIdFromTime(mediaWhen, false); + + // lookup the sample's media start time and duration + MP4Timestamp sampleStartTime; + MP4Duration sampleDuration; + + GetSampleTimes(sampleId, &sampleStartTime, &sampleDuration); + + // calculate the difference if any between when the sample + // would naturally start and when it starts in the edit timeline + MP4Duration sampleStartOffset = + mediaWhen - sampleStartTime; + + // calculate the start time for the sample in the edit time line + MP4Timestamp editSampleStartTime = + editWhen - MIN(editOffset, sampleStartOffset); + + MP4Duration editSampleDuration = 0; + + // calculate how long this sample lasts in the edit list timeline + if (m_pElstRateProperty->GetValue(editId - 1) == 0) { + // edit segment is a "dwell" + // so sample duration is that of the edit segment + editSampleDuration = + m_pElstDurationProperty->GetValue(editId - 1); + + } else { + // begin with the natural sample duration + editSampleDuration = sampleDuration; + + // now shorten that if the edit segment starts + // after the sample would naturally start + if (editOffset < sampleStartOffset) { + editSampleDuration -= sampleStartOffset - editOffset; + } + + // now shorten that if the edit segment ends + // before the sample would naturally end + if (editElapsedDuration + < editSampleStartTime + sampleDuration) { + editSampleDuration -= (editSampleStartTime + sampleDuration) + - editElapsedDuration; + } + } + + if (pStartTime) { + *pStartTime = editSampleStartTime; + } + + if (pDuration) { + *pDuration = editSampleDuration; + } + + VERBOSE_EDIT(m_pFile->GetVerbosity(), + printf("GetSampleIdFromEditTime: when "U64" " + "sampleId %u start "U64" duration "D64"\n", + editWhen, sampleId, + editSampleStartTime, editSampleDuration)); + + return sampleId; + } + + throw new MP4Error("time out of range", + "MP4Track::GetSampleIdFromEditTime"); + + } else { // no edit list + sampleId = GetSampleIdFromTime(editWhen, false); + + if (pStartTime || pDuration) { + GetSampleTimes(sampleId, pStartTime, pDuration); + } + } + + return sampleId; +} + +void MP4Track::CalculateBytesPerSample () +{ + MP4Atom *pMedia = m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd"); + MP4Atom *pMediaData; + const char *media_data_name; + if (pMedia == NULL) return; + + if (pMedia->GetNumberOfChildAtoms() != 1) return; + + pMediaData = pMedia->GetChildAtom(0); + media_data_name = pMediaData->GetType(); + if ((ATOMID(media_data_name) == ATOMID("twos")) || + (ATOMID(media_data_name) == ATOMID("sowt"))) { + MP4IntegerProperty *chan, *sampleSize; + chan = (MP4IntegerProperty *)pMediaData->GetProperty(4); + sampleSize = (MP4IntegerProperty *)pMediaData->GetProperty(5); + m_bytesPerSample = chan->GetValue() * (sampleSize->GetValue() / 8); + } +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4track.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4track.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,252 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2004. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Ximpo Group Ltd. mp4v2@ximpo.com + */ + +#ifndef __MP4_TRACK_INCLUDED__ +#define __MP4_TRACK_INCLUDED__ + +typedef u_int32_t MP4ChunkId; + +// forward declarations +class MP4File; +class MP4Atom; +class MP4Property; +class MP4IntegerProperty; +class MP4Integer16Property; +class MP4Integer32Property; +class MP4Integer64Property; +class MP4StringProperty; + +class MP4Track { +public: + MP4Track(MP4File* pFile, MP4Atom* pTrakAtom); + + virtual ~MP4Track(); + + MP4TrackId GetId() { + return m_trackId; + } + + const char* GetType(); + + void SetType(const char* type); + + MP4File* GetFile() { + return m_pFile; + } + + MP4Atom* GetTrakAtom() { + return m_pTrakAtom; + } + + void ReadSample( + // input parameters + MP4SampleId sampleId, + // output parameters + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + MP4Timestamp* pStartTime = NULL, + MP4Duration* pDuration = NULL, + MP4Duration* pRenderingOffset = NULL, + bool* pIsSyncSample = NULL); + + void WriteSample( + const u_int8_t* pBytes, + u_int32_t numBytes, + MP4Duration duration = 0, + MP4Duration renderingOffset = 0, + bool isSyncSample = true); + + virtual void FinishWrite(); + + u_int64_t GetDuration(); // in track timeScale units + u_int32_t GetTimeScale(); + u_int32_t GetNumberOfSamples(); + u_int32_t GetSampleSize(MP4SampleId sampleId); + u_int32_t GetMaxSampleSize(); + u_int64_t GetTotalOfSampleSizes(); + u_int32_t GetAvgBitrate(); // in bps + u_int32_t GetMaxBitrate(); // in bps + + MP4Duration GetFixedSampleDuration(); + bool SetFixedSampleDuration(MP4Duration duration); + + void GetSampleTimes(MP4SampleId sampleId, + MP4Timestamp* pStartTime, MP4Duration* pDuration); + + bool IsSyncSample(MP4SampleId sampleId); + + MP4SampleId GetSampleIdFromTime( + MP4Timestamp when, + bool wantSyncSample = false); + + MP4Duration GetSampleRenderingOffset(MP4SampleId sampleId); + void SetSampleRenderingOffset(MP4SampleId sampleId, + MP4Duration renderingOffset); + + MP4EditId AddEdit( + MP4EditId editId = MP4_INVALID_EDIT_ID); + + void DeleteEdit( + MP4EditId editId); + + MP4Timestamp GetEditStart( + MP4EditId editId); + + MP4Timestamp GetEditTotalDuration( + MP4EditId editId); + + MP4SampleId GetSampleIdFromEditTime( + MP4Timestamp editWhen, + MP4Timestamp* pStartTime = NULL, + MP4Duration* pDuration = NULL); + + // special operation for use during hint track packet assembly + void ReadSampleFragment( + MP4SampleId sampleId, + u_int32_t sampleOffset, + u_int16_t sampleLength, + u_int8_t* pDest); + + // special operations for use during optimization + + u_int32_t GetNumberOfChunks(); + + MP4Timestamp GetChunkTime(MP4ChunkId chunkId); + + void ReadChunk(MP4ChunkId chunkId, + u_int8_t** ppChunk, u_int32_t* pChunkSize); + + void RewriteChunk(MP4ChunkId chunkId, + u_int8_t* pChunk, u_int32_t chunkSize); + +protected: + bool InitEditListProperties(); + + FILE* GetSampleFile(MP4SampleId sampleId); + u_int64_t GetSampleFileOffset(MP4SampleId sampleId); + u_int32_t GetSampleStscIndex(MP4SampleId sampleId); + u_int32_t GetChunkStscIndex(MP4ChunkId chunkId); + u_int32_t GetChunkSize(MP4ChunkId chunkId); + u_int32_t GetSampleCttsIndex(MP4SampleId sampleId, + MP4SampleId* pFirstSampleId = NULL); + MP4SampleId GetNextSyncSample(MP4SampleId sampleId); + + void UpdateSampleSizes(MP4SampleId sampleId, + u_int32_t numBytes); + bool IsChunkFull(MP4SampleId sampleId); + void UpdateSampleToChunk(MP4SampleId sampleId, + MP4ChunkId chunkId, u_int32_t samplesPerChunk); + void UpdateChunkOffsets(u_int64_t chunkOffset); + void UpdateSampleTimes(MP4Duration duration); + void UpdateRenderingOffsets(MP4SampleId sampleId, + MP4Duration renderingOffset); + void UpdateSyncSamples(MP4SampleId sampleId, + bool isSyncSample); + + MP4Atom* AddAtom(char* parentName, char* childName); + + void UpdateDurations(MP4Duration duration); + MP4Duration ToMovieDuration(MP4Duration trackDuration); + + void UpdateModificationTimes(); + + void WriteChunkBuffer(); + + void CalculateBytesPerSample(); +protected: + MP4File* m_pFile; + MP4Atom* m_pTrakAtom; // moov.trak[] + MP4TrackId m_trackId; // moov.trak[].tkhd.trackId + MP4StringProperty* m_pTypeProperty; // moov.trak[].mdia.hdlr.handlerType + + u_int32_t m_lastStsdIndex; + FILE* m_lastSampleFile; + + // for efficient construction of hint track packets + MP4SampleId m_cachedReadSampleId; + u_int8_t* m_pCachedReadSample; + u_int32_t m_cachedReadSampleSize; + + // for writing + MP4SampleId m_writeSampleId; + MP4Duration m_fixedSampleDuration; + u_int8_t* m_pChunkBuffer; + u_int32_t m_chunkBufferSize; + u_int32_t m_chunkSamples; + MP4Duration m_chunkDuration; + + // controls for chunking + u_int32_t m_samplesPerChunk; + MP4Duration m_durationPerChunk; + + u_int32_t m_bytesPerSample; + + // controls for AMR chunking + int m_isAmr; + u_int8_t m_curMode; + + MP4Integer32Property* m_pTimeScaleProperty; + MP4IntegerProperty* m_pTrackDurationProperty; // 32 or 64 bits + MP4IntegerProperty* m_pMediaDurationProperty; // 32 or 64 bits + MP4IntegerProperty* m_pTrackModificationProperty; // 32 or 64 bits + MP4IntegerProperty* m_pMediaModificationProperty; // 32 or 64 bits + + MP4Integer32Property* m_pStszFixedSampleSizeProperty; + MP4Integer32Property* m_pStszSampleCountProperty; + MP4Integer32Property* m_pStszSampleSizeProperty; + + MP4Integer32Property* m_pStscCountProperty; + MP4Integer32Property* m_pStscFirstChunkProperty; + MP4Integer32Property* m_pStscSamplesPerChunkProperty; + MP4Integer32Property* m_pStscSampleDescrIndexProperty; + MP4Integer32Property* m_pStscFirstSampleProperty; + + MP4Integer32Property* m_pChunkCountProperty; + MP4IntegerProperty* m_pChunkOffsetProperty; // 32 or 64 bits + + MP4Integer32Property* m_pSttsCountProperty; + MP4Integer32Property* m_pSttsSampleCountProperty; + MP4Integer32Property* m_pSttsSampleDeltaProperty; + + MP4Integer32Property* m_pCttsCountProperty; + MP4Integer32Property* m_pCttsSampleCountProperty; + MP4Integer32Property* m_pCttsSampleOffsetProperty; + + MP4Integer32Property* m_pStssCountProperty; + MP4Integer32Property* m_pStssSampleProperty; + + MP4Integer32Property* m_pElstCountProperty; + MP4IntegerProperty* m_pElstMediaTimeProperty; // 32 or 64 bits + MP4IntegerProperty* m_pElstDurationProperty; // 32 or 64 bits + MP4Integer16Property* m_pElstRateProperty; + MP4Integer16Property* m_pElstReservedProperty; +}; + +MP4ARRAY_DECL(MP4Track, MP4Track*); + +#endif /* __MP4_TRACK_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4util.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4util.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,345 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001-2005. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + * Bill May wmay@cisco.com + */ + +#include "mp4common.h" + +void MP4Error::Print(FILE* pFile) +{ + fprintf(pFile, "MP4ERROR: "); + if (m_where) { + fprintf(pFile, "%s", m_where); + } + if (m_errstring) { + if (m_where) { + fprintf(pFile, ": "); + } + fprintf(pFile, "%s", m_errstring); + } + if (m_errno) { + if (m_where || m_errstring) { + fprintf(pFile, ": "); + } + fprintf(pFile, "%s", strerror(m_errno)); + } + fprintf(pFile, "\n"); +} + +void MP4HexDump( + u_int8_t* pBytes, u_int32_t numBytes, + FILE* pFile, u_int8_t indent) +{ + if (pFile == NULL) { + pFile = stdout; + } + Indent(pFile, indent); + fprintf(pFile, "<%u bytes> ", numBytes); + for (u_int32_t i = 0; i < numBytes; i++) { + if ((i % 16) == 0 && numBytes > 16) { + fprintf(pFile, "\n"); + Indent(pFile, indent); + } + fprintf(pFile, "%02x ", pBytes[i]); + } + fprintf(pFile, "\n"); +} + +bool MP4NameFirstMatches(const char* s1, const char* s2) +{ + if (s1 == NULL || *s1 == '\0' || s2 == NULL || *s2 == '\0') { + return false; + } + + if (*s2 == '*') { + return true; + } + + while (*s1 != '\0') { + if (*s2 == '\0' || strchr("[.", *s2)) { + break; + } + if (tolower(*s1) != tolower(*s2)) { + return false; + } + s1++; + s2++; + } + return true; +} + +bool MP4NameFirstIndex(const char* s, u_int32_t* pIndex) +{ + if (s == NULL) { + return false; + } + + while (*s != '\0' && *s != '.') { + if (*s == '[') { + s++; + ASSERT(pIndex); + if (sscanf(s, "%u", pIndex) != 1) { + return false; + } + return true; + } + s++; + } + return false; +} + +char* MP4NameFirst(const char *s) +{ + if (s == NULL) { + return NULL; + } + + const char* end = s; + + while (*end != '\0' && *end != '.') { + end++; + } + + char* first = (char*)MP4Calloc((end - s) + 1); + + if (first) { + strncpy(first, s, end - s); + } + + return first; +} + +const char* MP4NameAfterFirst(const char *s) +{ + if (s == NULL) { + return NULL; + } + + while (*s != '\0') { + if (*s == '.') { + s++; + if (*s == '\0') { + return NULL; + } + return s; + } + s++; + } + return NULL; +} + +char* MP4ToBase16(const u_int8_t* pData, u_int32_t dataSize) +{ + if (dataSize) { + ASSERT(pData); + } + + char* s = (char*)MP4Calloc((2 * dataSize) + 1); + + u_int32_t i, j; + for (i = 0, j = 0; i < dataSize; i++) { + sprintf(&s[j], "%02x", pData[i]); + j += 2; + } + + return s; /* N.B. caller is responsible for free'ing s */ +} + +char* MP4ToBase64(const u_int8_t* pData, u_int32_t dataSize) +{ + if (dataSize) { + ASSERT(pData); + } + + static const char encoding[64] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' + }; + + char* s = (char*)MP4Calloc((((dataSize + 2) * 4) / 3) + 1); + + const u_int8_t* src = pData; + char* dest = s; + u_int32_t numGroups = dataSize / 3; + + for (u_int32_t i = 0; i < numGroups; i++) { + *dest++ = encoding[src[0] >> 2]; + *dest++ = encoding[((src[0] & 0x03) << 4) | (src[1] >> 4)]; + *dest++ = encoding[((src[1] & 0x0F) << 2) | (src[2] >> 6)]; + *dest++ = encoding[src[2] & 0x3F]; + src += 3; + } + + if (dataSize % 3 == 1) { + *dest++ = encoding[src[0] >> 2]; + *dest++ = encoding[((src[0] & 0x03) << 4)]; + *dest++ = '='; + *dest++ = '='; + } else if (dataSize % 3 == 2) { + *dest++ = encoding[src[0] >> 2]; + *dest++ = encoding[((src[0] & 0x03) << 4) | (src[1] >> 4)]; + *dest++ = encoding[((src[1] & 0x0F) << 2)]; + *dest++ = '='; + } + *dest = '\0'; + return s; /* N.B. caller is responsible for free'ing s */ +} + +static bool convertBase64 (const char data, uint8_t *value) +{ + static const uint8_t decodingarr64[128] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, + }; + uint8_t index = (uint8_t)data; + if ((index & 0x80) != 0) return false; + + if (decodingarr64[index] == 0xff) return false; + *value = decodingarr64[index]; + return true; +} + +uint8_t *Base64ToBinary (const char *pData, uint32_t decodeSize, uint32_t *pDataSize) +{ + uint8_t *ret; + uint32_t size, ix, groups; + if (pData == NULL || decodeSize == 0 || pDataSize == NULL) + return NULL; + + if ((decodeSize % 4) != 0) { + // must be multiples of 4 characters + return NULL; + } + size = (decodeSize * 3) / 4; + groups = decodeSize / 4; + ret = (uint8_t *)MP4Calloc(size); + for (ix = 0; ix < groups; ix++) { + uint8_t value[4]; + for (uint8_t jx = 0; jx < 4; jx++) { + if (pData[jx] == '=') { + if (ix != (groups - 1)) { + free(ret); + return NULL; + } + size--; + value[jx] = 0; + } else if (convertBase64(pData[jx], &value[jx]) == false) { + free(ret); + return NULL; + } + } + ret[(ix * 3)] = value[0] << 2 | ((value[1] >> 4) & 0x3); + ret[(ix * 3) + 1] = (value[1] << 4) | (value[2] >> 2 & 0xf); + ret[(ix * 3) + 2] = ((value[2] & 0x3) << 6) | value[3]; + pData += 4; + } + *pDataSize = size; + return ret; +} + +// log2 of value, rounded up +static u_int8_t ilog2(u_int64_t value) +{ + u_int64_t powerOf2 = 1; + for (u_int8_t i = 0; i < 64; i++) { + if (value <= powerOf2) { + return i; + } + powerOf2 <<= 1; + } + return 64; +} + +u_int64_t MP4ConvertTime(u_int64_t t, + u_int32_t oldTimeScale, u_int32_t newTimeScale) +{ + // avoid float point exception + if (oldTimeScale == 0) { + throw new MP4Error("division by zero", "MP4ConvertTime"); + } + + // check if we can safely use integer operations + if (ilog2(t) + ilog2(newTimeScale) <= 64) { + return (t * newTimeScale) / oldTimeScale; + } + + // final resort is to use floating point + double d = ((double)newTimeScale / (double)oldTimeScale) + 0.5; + d *= UINT64_TO_DOUBLE(t); + + return (u_int64_t)d; +} + +const char* MP4NormalizeTrackType (const char* type, + uint32_t verbosity) +{ + if (!strcasecmp(type, "vide") + || !strcasecmp(type, "video") + || !strcasecmp(type, "mp4v") + || !strcasecmp(type, "avc1") + || !strcasecmp(type, "s263") // 3GPP H.263 + || !strcasecmp(type, "encv")) { + return MP4_VIDEO_TRACK_TYPE; + } + + if (!strcasecmp(type, "soun") + || !strcasecmp(type, "sound") + || !strcasecmp(type, "audio") + || !strcasecmp(type, "enca") + || !strcasecmp(type, "samr") // 3GPP AMR + || !strcasecmp(type, "sawb") // 3GPP AMR/WB + || !strcasecmp(type, "mp4a")) { + return MP4_AUDIO_TRACK_TYPE; + } + + if (!strcasecmp(type, "sdsm") + || !strcasecmp(type, "scene") + || !strcasecmp(type, "bifs")) { + return MP4_SCENE_TRACK_TYPE; + } + + if (!strcasecmp(type, "odsm") + || !strcasecmp(type, "od")) { + return MP4_OD_TRACK_TYPE; + } + if (strcasecmp(type, "cntl") == 0) { + return MP4_CNTL_TRACK_TYPE; + } + VERBOSE_WARNING(verbosity, + printf("Attempt to normalize %s did not match\n", + type)); + return type; +} diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/mp4util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/mp4util.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,257 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __MP4_UTIL_INCLUDED__ +#define __MP4_UTIL_INCLUDED__ +#include + +#ifndef ASSERT +#ifdef NDEBUG +#define ASSERT(expr) +#else +#define ASSERT(expr) \ + if (!(expr)) { \ + fflush(stdout); \ + assert((expr)); \ + } +#endif +#endif +#ifdef NDEBUG +#define WARNING(expr) +#else +#define WARNING(expr) \ + if (expr) { \ + fflush(stdout); \ + fprintf(stderr, "Warning (%s) in %s at line %u\n", \ + __STRING(expr), __FILE__, __LINE__); \ + } +#endif + +#define VERBOSE(exprverbosity, verbosity, expr) \ + if (((exprverbosity) & (verbosity)) == (exprverbosity)) { expr; } + +#define VERBOSE_ERROR(verbosity, expr) \ + VERBOSE(MP4_DETAILS_ERROR, verbosity, expr) + +#define VERBOSE_WARNING(verbosity, expr) \ + VERBOSE(MP4_DETAILS_WARNING, verbosity, expr) + +#define VERBOSE_READ(verbosity, expr) \ + VERBOSE(MP4_DETAILS_READ, verbosity, expr) + +#define VERBOSE_READ_TABLE(verbosity, expr) \ + VERBOSE((MP4_DETAILS_READ | MP4_DETAILS_TABLE), verbosity, expr) + +#define VERBOSE_READ_SAMPLE(verbosity, expr) \ + VERBOSE((MP4_DETAILS_READ | MP4_DETAILS_SAMPLE), verbosity, expr) + +#define VERBOSE_READ_HINT(verbosity, expr) \ + VERBOSE((MP4_DETAILS_READ | MP4_DETAILS_HINT), verbosity, expr) + +#define VERBOSE_WRITE(verbosity, expr) \ + VERBOSE(MP4_DETAILS_WRITE, verbosity, expr) + +#define VERBOSE_WRITE_TABLE(verbosity, expr) \ + VERBOSE((MP4_DETAILS_WRITE | MP4_DETAILS_TABLE), verbosity, expr) + +#define VERBOSE_WRITE_SAMPLE(verbosity, expr) \ + VERBOSE((MP4_DETAILS_WRITE | MP4_DETAILS_SAMPLE), verbosity, expr) + +#define VERBOSE_WRITE_HINT(verbosity, expr) \ + VERBOSE((MP4_DETAILS_WRITE | MP4_DETAILS_HINT), verbosity, expr) + +#define VERBOSE_FIND(verbosity, expr) \ + VERBOSE(MP4_DETAILS_FIND, verbosity, expr) + +#define VERBOSE_ISMA(verbosity, expr) \ + VERBOSE(MP4_DETAILS_ISMA, verbosity, expr) + +#define VERBOSE_EDIT(verbosity, expr) \ + VERBOSE(MP4_DETAILS_EDIT, verbosity, expr) + +inline void Indent(FILE* pFile, u_int8_t depth) { + fprintf(pFile, "%*c", depth, ' '); +} + +static inline void MP4Printf(const char* fmt, ...) +#ifndef _WIN32 + __attribute__((format(__printf__, 1, 2))) +#endif +; + +static inline void MP4Printf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + // TBD API call to set error_msg_func instead of just printf + vprintf(fmt, ap); + va_end(ap); +} + +class MP4Error { +public: + MP4Error() { + m_errno = 0; + m_errstring = NULL; + m_where = NULL; + m_free = 0; + } + ~MP4Error() { + if (m_free != 0) { + free((void *)m_errstring); + } + } + MP4Error(int err, const char* where = NULL) { + m_errno = err; + m_errstring = NULL; + m_where = where; + m_free = 0; + } + MP4Error(const char *format, const char *where, ...) { + char *string; + m_errno = 0; + string = (char *)malloc(512); + m_where = where; + if (string) { + va_list ap; + va_start(ap, where); + vsnprintf(string, 512, format, ap); + va_end(ap); + m_errstring = string; + m_free = 1; + } else { + m_errstring = format; + m_free = 0; + } + } + MP4Error(int err, const char* format, const char* where, ...) { + char *string; + m_errno = err; + string = (char *)malloc(512); + m_where = where; + if (string) { + va_list ap; + va_start(ap, where); + vsnprintf(string, 512, format, ap); + va_end(ap); + m_errstring = string; + m_free = 1; + } else { + m_errstring = format; + m_free = 0; + } + } + + void Print(FILE* pFile = stderr); + int m_free; + int m_errno; + const char* m_errstring; + const char* m_where; +}; + +void MP4HexDump( + u_int8_t* pBytes, u_int32_t numBytes, + FILE* pFile = stdout, u_int8_t indent = 0); + +inline void* MP4Malloc(size_t size) { + void* p = malloc(size); + if (p == NULL && size > 0) { + throw new MP4Error(errno); + } + return p; +} + +inline void* MP4Calloc(size_t size) { + return memset(MP4Malloc(size), 0, size); +} + +inline char* MP4Stralloc(const char* s1) { + char* s2 = (char*)MP4Malloc(strlen(s1) + 1); + strcpy(s2, s1); + return s2; +} + +inline void* MP4Realloc(void* p, u_int32_t newSize) { + // workaround library bug + if (p == NULL && newSize == 0) { + return NULL; + } + p = realloc(p, newSize); + if (p == NULL && newSize > 0) { + throw new MP4Error(errno); + } + return p; +} + +inline void MP4Free(void* p) { + free(p); +} + +inline u_int32_t STRTOINT32(const char* s) { +#ifdef WORDS_BIGENDIAN + return (*(u_int32_t *)s); +#else + return htonl(*(uint32_t *)s); +#endif +#if 0 + return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; +#endif +} + +inline void INT32TOSTR(u_int32_t i, char* s) { +#ifdef WORDS_BIGENDIAN + *(uint32_t *)s = i; + s[4] = 0; +#else + s[0] = ((i >> 24) & 0xFF); s[1] = ((i >> 16) & 0xFF); + s[2] = ((i >> 8) & 0xFF); s[3] = (i & 0xFF); s[4] = 0; +#endif +} + +inline MP4Timestamp MP4GetAbsTimestamp() { + struct timeval tv; + gettimeofday(&tv, NULL); + MP4Timestamp ret; + ret = tv.tv_sec; + ret += 2082844800; + return ret; // MP4 start date is 1/1/1904 + // 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60 +} + +u_int64_t MP4ConvertTime(u_int64_t t, + u_int32_t oldTimeScale, u_int32_t newTimeScale); + +bool MP4NameFirstMatches(const char* s1, const char* s2); + +bool MP4NameFirstIndex(const char* s, u_int32_t* pIndex); + +char* MP4NameFirst(const char *s); + +const char* MP4NameAfterFirst(const char *s); + +char* MP4ToBase16(const u_int8_t* pData, u_int32_t dataSize); + +char* MP4ToBase64(const u_int8_t* pData, u_int32_t dataSize); + +const char* MP4NormalizeTrackType(const char* type, + uint32_t verbosity); + +#endif /* __MP4_UTIL_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/ocidescriptors.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/ocidescriptors.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,307 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4ContentClassDescriptor::MP4ContentClassDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4Integer32Property("classificationEntity")); + AddProperty( /* 1 */ + new MP4Integer16Property("classificationTable")); + AddProperty( /* 2 */ + new MP4BytesProperty("contentClassificationData")); +} + +void MP4ContentClassDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 6); + + ReadProperties(pFile); +} + +MP4KeywordDescriptor::MP4KeywordDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4BytesProperty("languageCode", 3)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("isUTF8String", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("reserved", 7)); + MP4Integer8Property* pCount = + new MP4Integer8Property("keywordCount"); + AddProperty(pCount); /* 3 */ + + MP4TableProperty* pTable = new MP4TableProperty("keywords", pCount); + AddProperty(pTable); /* 4 */ + + pTable->AddProperty( /* 4, 0 */ + new MP4StringProperty("string", Counted)); + + SetReadMutate(2); +} + +void MP4KeywordDescriptor::Mutate() +{ + bool utf8Flag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(); + MP4Property* pProperty = + ((MP4TableProperty*)m_pProperties[4])->GetProperty(0); + ASSERT(pProperty); + ((MP4StringProperty*)pProperty)->SetUnicode(!utf8Flag); +} + +MP4RatingDescriptor::MP4RatingDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4Integer32Property("ratingEntity")); + AddProperty( /* 1 */ + new MP4Integer16Property("ratingCriteria")); + AddProperty( /* 2 */ + new MP4BytesProperty("ratingInfo")); +} + +void MP4RatingDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 6); + + ReadProperties(pFile); +} + +MP4LanguageDescriptor::MP4LanguageDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4BytesProperty("languageCode", 3)); +} + +MP4ShortTextDescriptor::MP4ShortTextDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4BytesProperty("languageCode", 3)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("isUTF8String", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("reserved", 7)); + AddProperty( /* 3 */ + new MP4StringProperty("eventName", Counted)); + AddProperty( /* 4 */ + new MP4StringProperty("eventText", Counted)); + + SetReadMutate(2); +} + +void MP4ShortTextDescriptor::Mutate() +{ + bool utf8Flag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(); + ((MP4StringProperty*)m_pProperties[3])->SetUnicode(!utf8Flag); + ((MP4StringProperty*)m_pProperties[4])->SetUnicode(!utf8Flag); +} + +MP4ExpandedTextDescriptor::MP4ExpandedTextDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4BytesProperty("languageCode", 3)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("isUTF8String", 1)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("reserved", 7)); + MP4Integer8Property* pCount = + new MP4Integer8Property("itemCount"); + AddProperty(pCount); /* 3 */ + + MP4TableProperty* pTable = new MP4TableProperty("items", pCount); + AddProperty(pTable); /* 4 */ + + pTable->AddProperty( /* Table 0 */ + new MP4StringProperty("itemDescription", Counted)); + pTable->AddProperty( /* Table 1 */ + new MP4StringProperty("itemText", Counted)); + + AddProperty( /* 5 */ + new MP4StringProperty("nonItemText")); + ((MP4StringProperty*)m_pProperties[5])->SetExpandedCountedFormat(true); + + SetReadMutate(2); +} + +void MP4ExpandedTextDescriptor::Mutate() +{ + bool utf8Flag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(); + + MP4Property* pProperty = + ((MP4TableProperty*)m_pProperties[4])->GetProperty(0); + ASSERT(pProperty); + ((MP4StringProperty*)pProperty)->SetUnicode(!utf8Flag); + + pProperty = ((MP4TableProperty*)m_pProperties[4])->GetProperty(1); + ASSERT(pProperty); + ((MP4StringProperty*)pProperty)->SetUnicode(!utf8Flag); + + ((MP4StringProperty*)m_pProperties[5])->SetUnicode(!utf8Flag); +} + +class MP4CreatorTableProperty : public MP4TableProperty { +public: + MP4CreatorTableProperty(char* name, MP4Integer8Property* pCountProperty) : + MP4TableProperty(name, pCountProperty) { + }; +protected: + void ReadEntry(MP4File* pFile, u_int32_t index); + void WriteEntry(MP4File* pFile, u_int32_t index); +}; + +MP4CreatorDescriptor::MP4CreatorDescriptor(u_int8_t tag) + : MP4Descriptor(tag) +{ + MP4Integer8Property* pCount = + new MP4Integer8Property("creatorCount"); + AddProperty(pCount); /* 0 */ + + MP4TableProperty* pTable = new MP4CreatorTableProperty("creators", pCount); + AddProperty(pTable); /* 1 */ + + pTable->AddProperty( /* Table 0 */ + new MP4BytesProperty("languageCode", 3, 3)); + pTable->AddProperty( /* Table 1 */ + new MP4BitfieldProperty("isUTF8String", 1)); + pTable->AddProperty( /* Table 2 */ + new MP4BitfieldProperty("reserved", 7)); + pTable->AddProperty( /* Table 3 */ + new MP4StringProperty("name", Counted)); +} + +void MP4CreatorTableProperty::ReadEntry(MP4File* pFile, u_int32_t index) +{ + m_pProperties[0]->Read(pFile, index); + m_pProperties[1]->Read(pFile, index); + + bool utf8Flag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(index); + ((MP4StringProperty*)m_pProperties[3])->SetUnicode(!utf8Flag); + + m_pProperties[2]->Read(pFile, index); + m_pProperties[3]->Read(pFile, index); +} + +void MP4CreatorTableProperty::WriteEntry(MP4File* pFile, u_int32_t index) +{ + bool utf8Flag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue(index); + ((MP4StringProperty*)m_pProperties[3])->SetUnicode(!utf8Flag); + + MP4TableProperty::WriteEntry(pFile, index); +} + +MP4CreationDescriptor::MP4CreationDescriptor(u_int8_t tag) + : MP4Descriptor(tag) +{ + AddProperty( /* 0 */ + new MP4BitfieldProperty("contentCreationDate", 40)); +} + +MP4SmpteCameraDescriptor::MP4SmpteCameraDescriptor() + : MP4Descriptor() +{ + MP4Integer8Property* pCount = + new MP4Integer8Property("parameterCount"); + AddProperty(pCount); + + MP4TableProperty* pTable = new MP4TableProperty("parameters", pCount); + AddProperty(pTable); + + pTable->AddProperty( + new MP4Integer8Property("id")); + pTable->AddProperty( + new MP4Integer32Property("value")); +} + +MP4UnknownOCIDescriptor::MP4UnknownOCIDescriptor() + : MP4Descriptor() +{ + AddProperty( /* 0 */ + new MP4BytesProperty("data")); +} + +void MP4UnknownOCIDescriptor::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size); + + ReadProperties(pFile); +} + +MP4Descriptor* CreateOCIDescriptor(u_int8_t tag) +{ + MP4Descriptor* pDescriptor = NULL; + + switch (tag) { + case MP4ContentClassDescrTag: + pDescriptor = new MP4ContentClassDescriptor(); + break; + case MP4KeywordDescrTag: + pDescriptor = new MP4KeywordDescriptor(); + break; + case MP4RatingDescrTag: + pDescriptor = new MP4RatingDescriptor(); + break; + case MP4LanguageDescrTag: + pDescriptor = new MP4LanguageDescriptor(); + break; + case MP4ShortTextDescrTag: + pDescriptor = new MP4ShortTextDescriptor(); + break; + case MP4ExpandedTextDescrTag: + pDescriptor = new MP4ExpandedTextDescriptor(); + break; + case MP4ContentCreatorDescrTag: + case MP4OCICreatorDescrTag: + pDescriptor = new MP4CreatorDescriptor(tag); + break; + case MP4ContentCreationDescrTag: + case MP4OCICreationDescrTag: + pDescriptor = new MP4CreationDescriptor(tag); + break; + case MP4SmpteCameraDescrTag: + pDescriptor = new MP4SmpteCameraDescriptor(); + break; + } + + if (pDescriptor == NULL) { + if (tag >= MP4OCIDescrTagsStart && tag <= MP4OCIDescrTagsEnd) { + pDescriptor = new MP4UnknownOCIDescriptor(); + pDescriptor->SetTag(tag); + } + } + + return pDescriptor; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/ocidescriptors.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/ocidescriptors.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,101 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __OCIDESCRIPTORS_INCLUDED__ +#define __OCIDESCRIPTORS_INCLUDED__ + +const u_int8_t MP4OCIDescrTagsStart = 0x40; +const u_int8_t MP4ContentClassDescrTag = 0x40; +const u_int8_t MP4KeywordDescrTag = 0x41; +const u_int8_t MP4RatingDescrTag = 0x42; +const u_int8_t MP4LanguageDescrTag = 0x43; +const u_int8_t MP4ShortTextDescrTag = 0x44; +const u_int8_t MP4ExpandedTextDescrTag = 0x45; +const u_int8_t MP4ContentCreatorDescrTag = 0x46; +const u_int8_t MP4ContentCreationDescrTag = 0x47; +const u_int8_t MP4OCICreatorDescrTag = 0x48; +const u_int8_t MP4OCICreationDescrTag = 0x49; +const u_int8_t MP4SmpteCameraDescrTag = 0x4A; +const u_int8_t MP4OCIDescrTagsEnd = 0x5F; + +class MP4ContentClassDescriptor : public MP4Descriptor { +public: + MP4ContentClassDescriptor(); + void Read(MP4File* pFile); +}; + +class MP4KeywordDescriptor : public MP4Descriptor { +public: + MP4KeywordDescriptor(); +protected: + void Mutate(); +}; + +class MP4RatingDescriptor : public MP4Descriptor { +public: + MP4RatingDescriptor(); + void Read(MP4File* pFile); +}; + +class MP4LanguageDescriptor : public MP4Descriptor { +public: + MP4LanguageDescriptor(); +}; + +class MP4ShortTextDescriptor : public MP4Descriptor { +public: + MP4ShortTextDescriptor(); +protected: + void Mutate(); +}; + +class MP4ExpandedTextDescriptor : public MP4Descriptor { +public: + MP4ExpandedTextDescriptor(); +protected: + void Mutate(); +}; + +class MP4CreatorDescriptor : public MP4Descriptor { +public: + MP4CreatorDescriptor(u_int8_t tag); +}; + +class MP4CreationDescriptor : public MP4Descriptor { +public: + MP4CreationDescriptor(u_int8_t tag); +}; + +class MP4SmpteCameraDescriptor : public MP4Descriptor { +public: + MP4SmpteCameraDescriptor(); +}; + +class MP4UnknownOCIDescriptor : public MP4Descriptor { +public: + MP4UnknownOCIDescriptor(); + void Read(MP4File* pFile); +}; + + +extern MP4Descriptor *CreateOCIDescriptor(u_int8_t tag); + +#endif /* __OCIDESCRIPTORS_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/odcommands.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/odcommands.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,104 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4ODUpdateDescriptor::MP4ODUpdateDescriptor() + : MP4Descriptor(MP4ODUpdateODCommandTag) +{ + // just a container for ObjectDescriptors + AddProperty( /* 0 */ + new MP4DescriptorProperty(NULL, + MP4FileODescrTag, 0, Required, Many)); +} + +MP4ODRemoveDescriptor::MP4ODRemoveDescriptor() + : MP4Descriptor(MP4ODRemoveODCommandTag) +{ + MP4Integer32Property* pCount = + new MP4Integer32Property("entryCount"); + pCount->SetImplicit(); + AddProperty(pCount); /* 0 */ + + MP4TableProperty* pTable = + new MP4TableProperty("entries", pCount); + AddProperty(pTable); /* 1 */ + + pTable->AddProperty( /* 1, 0 */ + new MP4BitfieldProperty("objectDescriptorId", 10)); +} + +void MP4ODRemoveDescriptor::Read(MP4File* pFile) +{ + // table entry count computed from descriptor size + ((MP4Integer32Property*)m_pProperties[0])->SetReadOnly(false); + ((MP4Integer32Property*)m_pProperties[0])->SetValue((m_size * 8) / 10); + ((MP4Integer32Property*)m_pProperties[0])->SetReadOnly(true); + + MP4Descriptor::Read(pFile); +} + +MP4ESUpdateDescriptor::MP4ESUpdateDescriptor() + : MP4Descriptor(MP4ESUpdateODCommandTag) +{ + AddProperty( /* 0 */ + new MP4BitfieldProperty("objectDescriptorId", 10)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("pad", 6)); + AddProperty( /* 2 */ + new MP4DescriptorProperty("esIdRefs", + MP4ESIDRefDescrTag, 0, Required, Many)); +} + +// LATER might be able to combine with ESUpdateDescriptor +MP4ESRemoveDescriptor::MP4ESRemoveDescriptor() + : MP4Descriptor(MP4ESRemoveODCommandTag) +{ + AddProperty( /* 0 */ + new MP4BitfieldProperty("objectDescriptorId", 10)); + AddProperty( /* 1 */ + new MP4BitfieldProperty("pad", 6)); + AddProperty( /* 2 */ + new MP4DescriptorProperty("esIdRefs", + MP4ESIDRefDescrTag, 0, Required, Many)); +} + +MP4Descriptor* CreateODCommand(u_int8_t tag) +{ + MP4Descriptor* pDescriptor = NULL; + + switch (tag) { + case MP4ODUpdateODCommandTag: + pDescriptor = new MP4ODUpdateDescriptor(); + break; + case MP4ODRemoveODCommandTag: + pDescriptor = new MP4ODRemoveDescriptor(); + break; + case MP4ESUpdateODCommandTag: + pDescriptor = new MP4ESUpdateDescriptor(); + break; + case MP4ESRemoveODCommandTag: + pDescriptor = new MP4ESRemoveDescriptor(); + break; + } + return pDescriptor; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/odcommands.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/odcommands.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,58 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __ODCOMMANDS_INCLUDED__ +#define __ODCOMMANDS_INCLUDED__ + +// OD stream command descriptors +const u_int8_t MP4ODUpdateODCommandTag = 0x01; +const u_int8_t MP4ODRemoveODCommandTag = 0x02; +const u_int8_t MP4ESUpdateODCommandTag = 0x03; +const u_int8_t MP4ESRemoveODCommandTag = 0x04; +const u_int8_t MP4IPMPUpdateODCommandTag = 0x05; +const u_int8_t MP4IPMPRemoveODCommandTag = 0x06; +const u_int8_t MP4ESRemoveRefODCommandTag = 0x07; + +class MP4ODUpdateDescriptor : public MP4Descriptor { +public: + MP4ODUpdateDescriptor(); +}; + +class MP4ODRemoveDescriptor : public MP4Descriptor { +public: + MP4ODRemoveDescriptor(); + void Read(MP4File* pFile); +}; + +class MP4ESUpdateDescriptor : public MP4Descriptor { +public: + MP4ESUpdateDescriptor(); +}; + +class MP4ESRemoveDescriptor : public MP4Descriptor { +public: + MP4ESRemoveDescriptor(); +}; + +MP4Descriptor* CreateODCommand(u_int8_t tag); + +#endif /* __ODCOMMANDS_INCLUDED__ */ + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/qosqualifiers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/qosqualifiers.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,133 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +MP4QosDescriptor::MP4QosDescriptor() + : MP4Descriptor(MP4QosDescrTag) +{ + AddProperty( /* 0 */ + new MP4Integer8Property("predefined")); + AddProperty( /* 1 */ + new MP4QosQualifierProperty("qualifiers", + MP4QosTagsStart, MP4QosTagsEnd, Optional, Many)); +} + +MP4MaxDelayQosQualifier::MP4MaxDelayQosQualifier() + : MP4QosQualifier(MP4MaxDelayQosTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("maxDelay")); +} + +MP4PrefMaxDelayQosQualifier::MP4PrefMaxDelayQosQualifier() + : MP4QosQualifier(MP4PrefMaxDelayQosTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("prefMaxDelay")); +} + +MP4LossProbQosQualifier::MP4LossProbQosQualifier() + : MP4QosQualifier(MP4LossProbQosTag) +{ + AddProperty( /* 0 */ + new MP4Float32Property("lossProb")); +} + +MP4MaxGapLossQosQualifier::MP4MaxGapLossQosQualifier() + : MP4QosQualifier(MP4MaxGapLossQosTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("maxGapLoss")); +} + +MP4MaxAUSizeQosQualifier::MP4MaxAUSizeQosQualifier() + : MP4QosQualifier(MP4MaxAUSizeQosTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("maxAUSize")); +} + +MP4AvgAUSizeQosQualifier::MP4AvgAUSizeQosQualifier() + : MP4QosQualifier(MP4AvgAUSizeQosTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("avgAUSize")); +} + +MP4MaxAURateQosQualifier::MP4MaxAURateQosQualifier() + : MP4QosQualifier(MP4MaxAURateQosTag) +{ + AddProperty( /* 0 */ + new MP4Integer32Property("maxAURate")); +} + +MP4UnknownQosQualifier::MP4UnknownQosQualifier() + : MP4QosQualifier() +{ + AddProperty( /* 0 */ + new MP4BytesProperty("data")); +} + +void MP4UnknownQosQualifier::Read(MP4File* pFile) +{ + ReadHeader(pFile); + + /* byte properties need to know how long they are before reading */ + ((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size); + + ReadProperties(pFile); +} + +MP4Descriptor* MP4QosQualifierProperty::CreateDescriptor(u_int8_t tag) +{ + MP4Descriptor* pDescriptor = NULL; + + switch (tag) { + case MP4MaxDelayQosTag: + pDescriptor = new MP4MaxDelayQosQualifier(); + break; + case MP4PrefMaxDelayQosTag: + pDescriptor = new MP4PrefMaxDelayQosQualifier(); + break; + case MP4LossProbQosTag: + pDescriptor = new MP4LossProbQosQualifier(); + break; + case MP4MaxGapLossQosTag: + pDescriptor = new MP4MaxGapLossQosQualifier(); + break; + case MP4MaxAUSizeQosTag: + pDescriptor = new MP4MaxAUSizeQosQualifier(); + break; + case MP4AvgAUSizeQosTag: + pDescriptor = new MP4AvgAUSizeQosQualifier(); + break; + case MP4MaxAURateQosTag: + pDescriptor = new MP4MaxAURateQosQualifier(); + break; + default: + pDescriptor = new MP4UnknownQosQualifier(); + pDescriptor->SetTag(tag); + } + + return pDescriptor; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/qosqualifiers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/qosqualifiers.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,85 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __QOSQUALIFIERS_INCLUDED__ +#define __QOSQUALIFIERS_INCLUDED__ + +const u_int8_t MP4QosDescrTag = 0x0C; + +class MP4QosDescriptor : public MP4Descriptor { +public: + MP4QosDescriptor(); +}; + +typedef MP4Descriptor MP4QosQualifier; + +const u_int8_t MP4QosTagsStart = 0x01; +const u_int8_t MP4MaxDelayQosTag = 0x01; +const u_int8_t MP4PrefMaxDelayQosTag = 0x02; +const u_int8_t MP4LossProbQosTag = 0x03; +const u_int8_t MP4MaxGapLossQosTag = 0x04; +const u_int8_t MP4MaxAUSizeQosTag = 0x41; +const u_int8_t MP4AvgAUSizeQosTag = 0x42; +const u_int8_t MP4MaxAURateQosTag = 0x43; +const u_int8_t MP4QosTagsEnd = 0xFF; + +class MP4MaxDelayQosQualifier : public MP4QosQualifier { +public: + MP4MaxDelayQosQualifier(); +}; + +class MP4PrefMaxDelayQosQualifier : public MP4QosQualifier { +public: + MP4PrefMaxDelayQosQualifier(); +}; + +class MP4LossProbQosQualifier : public MP4QosQualifier { +public: + MP4LossProbQosQualifier(); +}; + +class MP4MaxGapLossQosQualifier : public MP4QosQualifier { +public: + MP4MaxGapLossQosQualifier(); +}; + +class MP4MaxAUSizeQosQualifier : public MP4QosQualifier { +public: + MP4MaxAUSizeQosQualifier(); +}; + +class MP4AvgAUSizeQosQualifier : public MP4QosQualifier { +public: + MP4AvgAUSizeQosQualifier(); +}; + +class MP4MaxAURateQosQualifier : public MP4QosQualifier { +public: + MP4MaxAURateQosQualifier(); +}; + +class MP4UnknownQosQualifier : public MP4QosQualifier { +public: + MP4UnknownQosQualifier(); + void Read(MP4File* pFile); +}; + +#endif /* __QOSQUALIFIERS_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/rtphint.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/rtphint.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,1363 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4common.h" + +/* rtp hint track operations */ + +MP4RtpHintTrack::MP4RtpHintTrack(MP4File* pFile, MP4Atom* pTrakAtom) + : MP4Track(pFile, pTrakAtom) +{ + m_pRefTrack = NULL; + + m_pRtpMapProperty = NULL; + m_pPayloadNumberProperty = NULL; + m_pMaxPacketSizeProperty = NULL; + m_pSnroProperty = NULL; + m_pTsroProperty = NULL; + + m_pReadHint = NULL; + m_pReadHintSample = NULL; + m_readHintSampleSize = 0; + + m_pWriteHint = NULL; + m_writeHintId = MP4_INVALID_SAMPLE_ID; + m_writePacketId = 0; + + m_pTrpy = NULL; + m_pNump = NULL; + m_pTpyl = NULL; + m_pMaxr = NULL; + m_pDmed = NULL; + m_pDimm = NULL; + m_pPmax = NULL; + m_pDmax = NULL; + + m_pMaxPdu = NULL; + m_pAvgPdu = NULL; + m_pMaxBitRate = NULL; + m_pAvgBitRate = NULL; + + m_thisSec = 0; + m_bytesThisSec = 0; + m_bytesThisHint = 0; + m_bytesThisPacket = 0; +} + +MP4RtpHintTrack::~MP4RtpHintTrack() +{ + delete m_pReadHint; + delete m_pReadHintSample; + delete m_pWriteHint; +} + +void MP4RtpHintTrack::InitRefTrack() +{ + if (m_pRefTrack == NULL) { + MP4Integer32Property* pRefTrackIdProperty = NULL; + m_pTrakAtom->FindProperty( + "trak.tref.hint.entries[0].trackId", + (MP4Property**)&pRefTrackIdProperty); + ASSERT(pRefTrackIdProperty); + + m_pRefTrack = m_pFile->GetTrack(pRefTrackIdProperty->GetValue()); + } +} + +void MP4RtpHintTrack::InitRtpStart() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + srandom((tv.tv_usec << 12) | (tv.tv_sec & 0xFFF)); + + ASSERT(m_pTrakAtom); + + m_pTrakAtom->FindProperty( + "trak.udta.hnti.rtp .snro.offset", + (MP4Property**)&m_pSnroProperty); + + if (m_pSnroProperty) { + m_rtpSequenceStart = m_pSnroProperty->GetValue(); + } else { + m_rtpSequenceStart = random(); + } + + m_pTrakAtom->FindProperty( + "trak.udta.hnti.rtp .tsro.offset", + (MP4Property**)&m_pTsroProperty); + + if (m_pTsroProperty) { + m_rtpTimestampStart = m_pTsroProperty->GetValue(); + } else { + m_rtpTimestampStart = random(); + } +} + +void MP4RtpHintTrack::ReadHint( + MP4SampleId hintSampleId, + u_int16_t* pNumPackets) +{ + if (m_pRefTrack == NULL) { + InitRefTrack(); + InitRtpStart(); + } + + // dispose of any old hint + delete m_pReadHint; + m_pReadHint = NULL; + delete m_pReadHintSample; + m_pReadHintSample = NULL; + m_readHintSampleSize = 0; + + // read the desired hint sample into memory + ReadSample( + hintSampleId, + &m_pReadHintSample, + &m_readHintSampleSize, + &m_readHintTimestamp); + + m_pFile->EnableMemoryBuffer(m_pReadHintSample, m_readHintSampleSize); + + m_pReadHint = new MP4RtpHint(this); + m_pReadHint->Read(m_pFile); + + m_pFile->DisableMemoryBuffer(); + + if (pNumPackets) { + *pNumPackets = GetHintNumberOfPackets(); + } +} + +u_int16_t MP4RtpHintTrack::GetHintNumberOfPackets() +{ + if (m_pReadHint == NULL) { + throw new MP4Error("no hint has been read", + "MP4GetRtpHintNumberOfPackets"); + } + return m_pReadHint->GetNumberOfPackets(); +} + +bool MP4RtpHintTrack::GetPacketBFrame(u_int16_t packetIndex) +{ + if (m_pReadHint == NULL) { + throw new MP4Error("no hint has been read", + "MP4GetRtpPacketBFrame"); + } + MP4RtpPacket* pPacket = + m_pReadHint->GetPacket(packetIndex); + + return pPacket->IsBFrame(); +} + +u_int16_t MP4RtpHintTrack::GetPacketTransmitOffset(u_int16_t packetIndex) +{ + if (m_pReadHint == NULL) { + throw new MP4Error("no hint has been read", + "MP4GetRtpPacketTransmitOffset"); + } + + MP4RtpPacket* pPacket = + m_pReadHint->GetPacket(packetIndex); + + return pPacket->GetTransmitOffset(); +} + +void MP4RtpHintTrack::ReadPacket( + u_int16_t packetIndex, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + u_int32_t ssrc, + bool addHeader, + bool addPayload) +{ + if (m_pReadHint == NULL) { + throw new MP4Error("no hint has been read", + "MP4ReadRtpPacket"); + } + if (!addHeader && !addPayload) { + throw new MP4Error("no data requested", + "MP4ReadRtpPacket"); + } + + MP4RtpPacket* pPacket = + m_pReadHint->GetPacket(packetIndex); + + *pNumBytes = 0; + if (addHeader) { + *pNumBytes += 12; + } + if (addPayload) { + *pNumBytes += pPacket->GetDataSize(); + } + + // if needed, allocate the packet memory + bool buffer_malloc = false; + + if (*ppBytes == NULL) { + *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes); + buffer_malloc = true; + } + + try { + u_int8_t* pDest = *ppBytes; + + if (addHeader) { + *pDest++ = + 0x80 | (pPacket->GetPBit() << 5) | (pPacket->GetXBit() << 4); + + *pDest++ = + (pPacket->GetMBit() << 7) | pPacket->GetPayload(); + + *((u_int16_t*)pDest) = + htons(m_rtpSequenceStart + pPacket->GetSequenceNumber()); + pDest += 2; + + *((u_int32_t*)pDest) = + htonl(m_rtpTimestampStart + (u_int32_t)m_readHintTimestamp); + pDest += 4; + + *((u_int32_t*)pDest) = + htonl(ssrc); + pDest += 4; + } + + if (addPayload) { + pPacket->GetData(pDest); + } + } + catch (MP4Error* e) { + if (buffer_malloc) { + MP4Free(*ppBytes); + *ppBytes = NULL; + } + throw e; + } + + VERBOSE_READ_HINT(m_pFile->GetVerbosity(), + printf("ReadPacket: %u ", packetIndex); + MP4HexDump(*ppBytes, *pNumBytes);); +} + +MP4Timestamp MP4RtpHintTrack::GetRtpTimestampStart() +{ + if (m_pRefTrack == NULL) { + InitRefTrack(); + InitRtpStart(); + } + + return m_rtpTimestampStart; +} + +void MP4RtpHintTrack::SetRtpTimestampStart(MP4Timestamp start) +{ + if (!m_pTsroProperty) { + MP4Atom* pTsroAtom = + m_pFile->AddDescendantAtoms(m_pTrakAtom, "udta.hnti.rtp .tsro"); + + ASSERT(pTsroAtom); + + pTsroAtom->FindProperty("offset", + (MP4Property**)&m_pTsroProperty); + + ASSERT(m_pTsroProperty); + } + + m_pTsroProperty->SetValue(start); + m_rtpTimestampStart = start; +} + +void MP4RtpHintTrack::InitPayload() +{ + ASSERT(m_pTrakAtom); + + if (m_pRtpMapProperty == NULL) { + m_pTrakAtom->FindProperty( + "trak.udta.hinf.payt.rtpMap", + (MP4Property**)&m_pRtpMapProperty); + } + + if (m_pPayloadNumberProperty == NULL) { + m_pTrakAtom->FindProperty( + "trak.udta.hinf.payt.payloadNumber", + (MP4Property**)&m_pPayloadNumberProperty); + } + + if (m_pMaxPacketSizeProperty == NULL) { + m_pTrakAtom->FindProperty( + "trak.mdia.minf.stbl.stsd.rtp .maxPacketSize", + (MP4Property**)&m_pMaxPacketSizeProperty); + } +} + +void MP4RtpHintTrack::GetPayload( + char** ppPayloadName, + u_int8_t* pPayloadNumber, + u_int16_t* pMaxPayloadSize, + char **ppEncodingParams) +{ + const char* pRtpMap; + char* pSlash; + u_int32_t length; + InitPayload(); + + if (ppPayloadName || ppEncodingParams) { + if (ppPayloadName) + *ppPayloadName = NULL; + if (ppEncodingParams) + *ppEncodingParams = NULL; + if (m_pRtpMapProperty) { + pRtpMap = m_pRtpMapProperty->GetValue(); + pSlash = strchr(pRtpMap, '/'); + + if (pSlash) { + length = pSlash - pRtpMap; + } else { + length = strlen(pRtpMap); + } + + if (ppPayloadName) { + *ppPayloadName = (char*)MP4Calloc(length + 1); + strncpy(*ppPayloadName, pRtpMap, length); + } + if (pSlash && ppEncodingParams) { + pSlash++; + pSlash = strchr(pSlash, '/'); + if (pSlash != NULL) { + pSlash++; + if (pSlash != '\0') { + length = strlen(pRtpMap) - (pSlash - pRtpMap); + *ppEncodingParams = (char *)MP4Calloc(length + 1); + strncpy(*ppEncodingParams, pSlash, length); + } + } + } + } + } + + if (pPayloadNumber) { + if (m_pPayloadNumberProperty) { + *pPayloadNumber = m_pPayloadNumberProperty->GetValue(); + } else { + *pPayloadNumber = 0; + } + } + + if (pMaxPayloadSize) { + if (m_pMaxPacketSizeProperty) { + *pMaxPayloadSize = m_pMaxPacketSizeProperty->GetValue(); + } else { + *pMaxPayloadSize = 0; + } + } +} + +void MP4RtpHintTrack::SetPayload( + const char* payloadName, + u_int8_t payloadNumber, + u_int16_t maxPayloadSize, + const char *encoding_parms, + bool include_rtp_map, + bool include_mpeg4_esid) +{ + InitRefTrack(); + InitPayload(); + + ASSERT(m_pRtpMapProperty); + ASSERT(m_pPayloadNumberProperty); + ASSERT(m_pMaxPacketSizeProperty); + + size_t len = strlen(payloadName) + 16; + if (encoding_parms != NULL) { + size_t temp = strlen(encoding_parms); + if (temp == 0) { + encoding_parms = NULL; + } else { + len += temp; + } + } + + char* rtpMapBuf = (char*)MP4Malloc(len); + sprintf(rtpMapBuf, "%s/%u%c%s", + payloadName, + GetTimeScale(), + encoding_parms != NULL ? '/' : '\0', + encoding_parms == NULL ? "" : encoding_parms); + m_pRtpMapProperty->SetValue(rtpMapBuf); + + m_pPayloadNumberProperty->SetValue(payloadNumber); + + if (maxPayloadSize == 0) { + maxPayloadSize = 1460; + } + m_pMaxPacketSizeProperty->SetValue(maxPayloadSize); + + // set sdp media type + const char* sdpMediaType; + if (!strcmp(m_pRefTrack->GetType(), MP4_AUDIO_TRACK_TYPE)) { + sdpMediaType = "audio"; + } else if (!strcmp(m_pRefTrack->GetType(), MP4_VIDEO_TRACK_TYPE)) { + sdpMediaType = "video"; + } else if (!strcmp(m_pRefTrack->GetType(), MP4_CNTL_TRACK_TYPE)) { + sdpMediaType = "control"; + } else { + sdpMediaType = "application"; + } + + char* sdpBuf = (char*)MP4Malloc( + strlen(sdpMediaType) + strlen(rtpMapBuf) + 256); + uint32_t buflen; + buflen = sprintf(sdpBuf, + "m=%s 0 RTP/AVP %u\015\012" + "a=control:trackID=%u\015\012", + sdpMediaType, payloadNumber, + m_trackId); + if (include_rtp_map) { + buflen += sprintf(sdpBuf + buflen, + "a=rtpmap:%u %s\015\012", + payloadNumber, rtpMapBuf); + } + if (include_mpeg4_esid) { + sprintf(sdpBuf + buflen, + "a=mpeg4-esid:%u\015\012", + m_pRefTrack->GetId()); + } + + MP4StringProperty* pSdpProperty = NULL; + m_pTrakAtom->FindProperty("trak.udta.hnti.sdp .sdpText", + (MP4Property**)&pSdpProperty); + ASSERT(pSdpProperty); + pSdpProperty->SetValue(sdpBuf); + + // cleanup + MP4Free(rtpMapBuf); + MP4Free(sdpBuf); +} + +void MP4RtpHintTrack::AddHint(bool isBFrame, u_int32_t timestampOffset) +{ + // on first hint, need to lookup the reference track + if (m_writeHintId == MP4_INVALID_SAMPLE_ID) { + InitRefTrack(); + InitStats(); + } + + if (m_pWriteHint) { + throw new MP4Error("unwritten hint is still pending", "MP4AddRtpHint"); + } + + m_pWriteHint = new MP4RtpHint(this); + m_pWriteHint->SetBFrame(isBFrame); + m_pWriteHint->SetTimestampOffset(timestampOffset); + + m_bytesThisHint = 0; + m_writeHintId++; +} + +void MP4RtpHintTrack::AddPacket(bool setMbit, int32_t transmitOffset) +{ + if (m_pWriteHint == NULL) { + throw new MP4Error("no hint pending", "MP4RtpAddPacket"); + } + + MP4RtpPacket* pPacket = m_pWriteHint->AddPacket(); + + ASSERT(m_pPayloadNumberProperty); + + pPacket->Set( + m_pPayloadNumberProperty->GetValue(), + m_writePacketId++, + setMbit); + pPacket->SetTransmitOffset(transmitOffset); + + m_bytesThisHint += 12; + if (m_bytesThisPacket > m_pPmax->GetValue()) { + m_pPmax->SetValue(m_bytesThisPacket); + } + m_bytesThisPacket = 12; + m_pNump->IncrementValue(); + m_pTrpy->IncrementValue(12); // RTP packet header size +} + +void MP4RtpHintTrack::AddImmediateData( + const u_int8_t* pBytes, + u_int32_t numBytes) +{ + if (m_pWriteHint == NULL) { + throw new MP4Error("no hint pending", "MP4RtpAddImmediateData"); + } + + MP4RtpPacket* pPacket = m_pWriteHint->GetCurrentPacket(); + if (pPacket == NULL) { + throw new MP4Error("no packet pending", "MP4RtpAddImmediateData"); + } + + if (pBytes == NULL || numBytes == 0) { + throw new MP4Error("no data", + "AddImmediateData"); + } + if (numBytes > 14) { + throw new MP4Error("data size is larger than 14 bytes", + "AddImmediateData"); + } + + MP4RtpImmediateData* pData = new MP4RtpImmediateData(pPacket); + pData->Set(pBytes, numBytes); + + pPacket->AddData(pData); + + m_bytesThisHint += numBytes; + m_bytesThisPacket += numBytes; + m_pDimm->IncrementValue(numBytes); + m_pTpyl->IncrementValue(numBytes); + m_pTrpy->IncrementValue(numBytes); +} + +void MP4RtpHintTrack::AddSampleData( + MP4SampleId sampleId, + u_int32_t dataOffset, + u_int32_t dataLength) +{ + if (m_pWriteHint == NULL) { + throw new MP4Error("no hint pending", "MP4RtpAddSampleData"); + } + + MP4RtpPacket* pPacket = m_pWriteHint->GetCurrentPacket(); + if (pPacket == NULL) { + throw new MP4Error("no packet pending", "MP4RtpAddSampleData"); + } + + MP4RtpSampleData* pData = new MP4RtpSampleData(pPacket); + + pData->SetReferenceSample(sampleId, dataOffset, dataLength); + + pPacket->AddData(pData); + + m_bytesThisHint += dataLength; + m_bytesThisPacket += dataLength; + m_pDmed->IncrementValue(dataLength); + m_pTpyl->IncrementValue(dataLength); + m_pTrpy->IncrementValue(dataLength); +} + +void MP4RtpHintTrack::AddESConfigurationPacket() +{ + if (m_pWriteHint == NULL) { + throw new MP4Error("no hint pending", + "MP4RtpAddESConfigurationPacket"); + } + + u_int8_t* pConfig = NULL; + u_int32_t configSize = 0; + + m_pFile->GetTrackESConfiguration(m_pRefTrack->GetId(), + &pConfig, &configSize); + + if (pConfig == NULL) { + return; + } + + ASSERT(m_pMaxPacketSizeProperty); + + if (configSize > m_pMaxPacketSizeProperty->GetValue()) { + throw new MP4Error("ES configuration is too large for RTP payload", + "MP4RtpAddESConfigurationPacket"); + } + + AddPacket(false); + + MP4RtpPacket* pPacket = m_pWriteHint->GetCurrentPacket(); + ASSERT(pPacket); + + // This is ugly! + // To get the ES configuration data somewhere known + // we create a sample data reference that points to + // this hint track (not the media track) + // and this sample of the hint track + // the offset into this sample is filled in during the write process + MP4RtpSampleData* pData = new MP4RtpSampleData(pPacket); + + pData->SetEmbeddedImmediate(m_writeSampleId, pConfig, configSize); + + pPacket->AddData(pData); + + m_bytesThisHint += configSize; + m_bytesThisPacket += configSize; + m_pTpyl->IncrementValue(configSize); + m_pTrpy->IncrementValue(configSize); +} + +void MP4RtpHintTrack::WriteHint(MP4Duration duration, bool isSyncSample) +{ + if (m_pWriteHint == NULL) { + throw new MP4Error("no hint pending", "MP4WriteRtpHint"); + } + + u_int8_t* pBytes; + u_int64_t numBytes; + + m_pFile->EnableMemoryBuffer(); + + m_pWriteHint->Write(m_pFile); + + m_pFile->DisableMemoryBuffer(&pBytes, &numBytes); + + WriteSample(pBytes, numBytes, duration, 0, isSyncSample); + + MP4Free(pBytes); + + // update statistics + if (m_bytesThisPacket > m_pPmax->GetValue()) { + m_pPmax->SetValue(m_bytesThisPacket); + } + + if (duration > m_pDmax->GetValue()) { + m_pDmax->SetValue(duration); + } + + MP4Timestamp startTime; + + GetSampleTimes(m_writeHintId, &startTime, NULL); + + if (startTime < m_thisSec + GetTimeScale()) { + m_bytesThisSec += m_bytesThisHint; + } else { + if (m_bytesThisSec > m_pMaxr->GetValue()) { + m_pMaxr->SetValue(m_bytesThisSec); + } + m_thisSec = startTime - (startTime % GetTimeScale()); + m_bytesThisSec = m_bytesThisHint; + } + + // cleanup + delete m_pWriteHint; + m_pWriteHint = NULL; +} + +void MP4RtpHintTrack::FinishWrite() +{ + if (m_writeHintId != MP4_INVALID_SAMPLE_ID) { + m_pMaxPdu->SetValue(m_pPmax->GetValue()); + if (m_pNump->GetValue()) { + m_pAvgPdu->SetValue(m_pTrpy->GetValue() / m_pNump->GetValue()); + } + + m_pMaxBitRate->SetValue(m_pMaxr->GetValue() * 8); + if (GetDuration()) { + m_pAvgBitRate->SetValue( + m_pTrpy->GetValue() * 8 * GetTimeScale() / GetDuration()); + } + } + + MP4Track::FinishWrite(); +} + +void MP4RtpHintTrack::InitStats() +{ + MP4Atom* pHinfAtom = m_pTrakAtom->FindAtom("trak.udta.hinf"); + + ASSERT(pHinfAtom); + + pHinfAtom->FindProperty("hinf.trpy.bytes", (MP4Property**)&m_pTrpy); + pHinfAtom->FindProperty("hinf.nump.packets", (MP4Property**)&m_pNump); + pHinfAtom->FindProperty("hinf.tpyl.bytes", (MP4Property**)&m_pTpyl); + pHinfAtom->FindProperty("hinf.maxr.bytes", (MP4Property**)&m_pMaxr); + pHinfAtom->FindProperty("hinf.dmed.bytes", (MP4Property**)&m_pDmed); + pHinfAtom->FindProperty("hinf.dimm.bytes", (MP4Property**)&m_pDimm); + pHinfAtom->FindProperty("hinf.pmax.bytes", (MP4Property**)&m_pPmax); + pHinfAtom->FindProperty("hinf.dmax.milliSecs", (MP4Property**)&m_pDmax); + + MP4Atom* pHmhdAtom = m_pTrakAtom->FindAtom("trak.mdia.minf.hmhd"); + + ASSERT(pHmhdAtom); + + pHmhdAtom->FindProperty("hmhd.maxPduSize", (MP4Property**)&m_pMaxPdu); + pHmhdAtom->FindProperty("hmhd.avgPduSize", (MP4Property**)&m_pAvgPdu); + pHmhdAtom->FindProperty("hmhd.maxBitRate", (MP4Property**)&m_pMaxBitRate); + pHmhdAtom->FindProperty("hmhd.avgBitRate", (MP4Property**)&m_pAvgBitRate); + + MP4Integer32Property* pMaxrPeriod = NULL; + pHinfAtom->FindProperty("hinf.maxr.granularity", + (MP4Property**)&pMaxrPeriod); + if (pMaxrPeriod) { + pMaxrPeriod->SetValue(1000); // 1 second + } +} + + +MP4RtpHint::MP4RtpHint(MP4RtpHintTrack* pTrack) +{ + m_pTrack = pTrack; + + AddProperty( /* 0 */ + new MP4Integer16Property("packetCount")); + AddProperty( /* 1 */ + new MP4Integer16Property("reserved")); +} + +MP4RtpHint::~MP4RtpHint() +{ + for (u_int32_t i = 0; i < m_rtpPackets.Size(); i++) { + delete m_rtpPackets[i]; + } +} + +MP4RtpPacket* MP4RtpHint::AddPacket() +{ + MP4RtpPacket* pPacket = new MP4RtpPacket(this); + m_rtpPackets.Add(pPacket); + + // packetCount property + ((MP4Integer16Property*)m_pProperties[0])->IncrementValue(); + + pPacket->SetBFrame(m_isBFrame); + pPacket->SetTimestampOffset(m_timestampOffset); + + return pPacket; +} + +void MP4RtpHint::Read(MP4File* pFile) +{ + // call base class Read for required properties + MP4Container::Read(pFile); + + u_int16_t numPackets = + ((MP4Integer16Property*)m_pProperties[0])->GetValue(); + + for (u_int16_t i = 0; i < numPackets; i++) { + MP4RtpPacket* pPacket = new MP4RtpPacket(this); + + m_rtpPackets.Add(pPacket); + + pPacket->Read(pFile); + } + + VERBOSE_READ_HINT(pFile->GetVerbosity(), + printf("ReadHint:\n"); Dump(stdout, 10, false);); +} + +void MP4RtpHint::Write(MP4File* pFile) +{ + u_int64_t hintStartPos = pFile->GetPosition(); + + MP4Container::Write(pFile); + + u_int64_t packetStartPos = pFile->GetPosition(); + + u_int32_t i; + + // first write out packet (and data) entries + for (i = 0; i < m_rtpPackets.Size(); i++) { + m_rtpPackets[i]->Write(pFile); + } + + // now let packets write their extra data into the hint sample + for (i = 0; i < m_rtpPackets.Size(); i++) { + m_rtpPackets[i]->WriteEmbeddedData(pFile, hintStartPos); + } + + u_int64_t endPos = pFile->GetPosition(); + + pFile->SetPosition(packetStartPos); + + // finally rewrite the packet and data entries + // which now contain the correct offsets for the embedded data + for (i = 0; i < m_rtpPackets.Size(); i++) { + m_rtpPackets[i]->Write(pFile); + } + + pFile->SetPosition(endPos); + + VERBOSE_WRITE_HINT(pFile->GetVerbosity(), + printf("WriteRtpHint:\n"); Dump(stdout, 14, false)); +} + +void MP4RtpHint::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits) +{ + MP4Container::Dump(pFile, indent, dumpImplicits); + + for (u_int32_t i = 0; i < m_rtpPackets.Size(); i++) { + Indent(pFile, indent); + fprintf(pFile, "RtpPacket: %u\n", i); + m_rtpPackets[i]->Dump(pFile, indent + 1, dumpImplicits); + } +} + +MP4RtpPacket::MP4RtpPacket(MP4RtpHint* pHint) +{ + m_pHint = pHint; + + AddProperty( /* 0 */ + new MP4Integer32Property("relativeXmitTime")); + AddProperty( /* 1 */ + new MP4BitfieldProperty("reserved1", 2)); + AddProperty( /* 2 */ + new MP4BitfieldProperty("Pbit", 1)); + AddProperty( /* 3 */ + new MP4BitfieldProperty("Xbit", 1)); + AddProperty( /* 4 */ + new MP4BitfieldProperty("reserved2", 4)); + AddProperty( /* 5 */ + new MP4BitfieldProperty("Mbit", 1)); + AddProperty( /* 6 */ + new MP4BitfieldProperty("payloadType", 7)); + AddProperty( /* 7 */ + new MP4Integer16Property("sequenceNumber")); + AddProperty( /* 8 */ + new MP4BitfieldProperty("reserved3", 13)); + AddProperty( /* 9 */ + new MP4BitfieldProperty("extraFlag", 1)); + AddProperty( /* 10 */ + new MP4BitfieldProperty("bFrameFlag", 1)); + AddProperty( /* 11 */ + new MP4BitfieldProperty("repeatFlag", 1)); + AddProperty( /* 12 */ + new MP4Integer16Property("entryCount")); +} + +MP4RtpPacket::~MP4RtpPacket() +{ + for (u_int32_t i = 0; i < m_rtpData.Size(); i++) { + delete m_rtpData[i]; + } +} + +void MP4RtpPacket::AddExtraProperties() +{ + AddProperty( /* 13 */ + new MP4Integer32Property("extraInformationLength")); + + // This is a bit of a hack, since the tlv entries are really defined + // as atoms but there is only one type defined now, rtpo, and getting + // our atom code hooked up here would be a major pain with little gain + + AddProperty( /* 14 */ + new MP4Integer32Property("tlvLength")); + AddProperty( /* 15 */ + new MP4StringProperty("tlvType")); + AddProperty( /* 16 */ + new MP4Integer32Property("timestampOffset")); + + ((MP4Integer32Property*)m_pProperties[13])->SetValue(16); + ((MP4Integer32Property*)m_pProperties[14])->SetValue(12); + ((MP4StringProperty*)m_pProperties[15])->SetFixedLength(4); + ((MP4StringProperty*)m_pProperties[15])->SetValue("rtpo"); +} + +void MP4RtpPacket::Read(MP4File* pFile) +{ + // call base class Read for required properties + MP4Container::Read(pFile); + + // read extra info if present + // we only support the rtpo field! + if (((MP4BitfieldProperty*)m_pProperties[9])->GetValue() == 1) { + ReadExtra(pFile); + } + + u_int16_t numDataEntries = + ((MP4Integer16Property*)m_pProperties[12])->GetValue(); + + // read data entries + for (u_int16_t i = 0; i < numDataEntries; i++) { + u_int8_t dataType; + pFile->PeekBytes(&dataType, 1); + + MP4RtpData* pData; + + switch (dataType) { + case 0: + pData = new MP4RtpNullData(this); + break; + case 1: + pData = new MP4RtpImmediateData(this); + break; + case 2: + pData = new MP4RtpSampleData(this); + break; + case 3: + pData = new MP4RtpSampleDescriptionData(this); + break; + default: + throw new MP4Error("unknown packet data entry type", + "MP4ReadHint"); + } + + m_rtpData.Add(pData); + + // read data entry's properties + pData->Read(pFile); + } +} + +void MP4RtpPacket::ReadExtra(MP4File* pFile) +{ + AddExtraProperties(); + + int32_t extraLength = (int32_t)pFile->ReadUInt32(); + + if (extraLength < 4) { + throw new MP4Error("bad packet extra info length", + "MP4RtpPacket::ReadExtra"); + } + extraLength -= 4; + + while (extraLength > 0) { + u_int32_t entryLength = pFile->ReadUInt32(); + u_int32_t entryTag = pFile->ReadUInt32(); + + if (entryLength < 8) { + throw new MP4Error("bad packet extra info entry length", + "MP4RtpPacket::ReadExtra"); + } + + if (entryTag == STRTOINT32("rtpo") && entryLength == 12) { + // read the rtp timestamp offset + m_pProperties[16]->Read(pFile); + } else { + // ignore it, LATER carry it along + pFile->SetPosition(pFile->GetPosition() + entryLength - 8); + } + + extraLength -= entryLength; + } + + if (extraLength < 0) { + throw new MP4Error("invalid packet extra info length", + "MP4RtpPacket::ReadExtra"); + } +} + +void MP4RtpPacket::Set(u_int8_t payloadNumber, + u_int32_t packetId, bool setMbit) +{ + ((MP4BitfieldProperty*)m_pProperties[5])->SetValue(setMbit); + ((MP4BitfieldProperty*)m_pProperties[6])->SetValue(payloadNumber); + ((MP4Integer16Property*)m_pProperties[7])->SetValue(packetId); +} + +int32_t MP4RtpPacket::GetTransmitOffset() +{ + return ((MP4Integer32Property*)m_pProperties[0])->GetValue(); +} + +void MP4RtpPacket::SetTransmitOffset(int32_t transmitOffset) +{ + ((MP4Integer32Property*)m_pProperties[0])->SetValue(transmitOffset); +} + +bool MP4RtpPacket::GetPBit() +{ + return ((MP4BitfieldProperty*)m_pProperties[2])->GetValue(); +} + +bool MP4RtpPacket::GetXBit() +{ + return ((MP4BitfieldProperty*)m_pProperties[3])->GetValue(); +} + +bool MP4RtpPacket::GetMBit() +{ + return ((MP4BitfieldProperty*)m_pProperties[5])->GetValue(); +} + +u_int8_t MP4RtpPacket::GetPayload() +{ + return ((MP4BitfieldProperty*)m_pProperties[6])->GetValue(); +} + +u_int16_t MP4RtpPacket::GetSequenceNumber() +{ + return ((MP4Integer16Property*)m_pProperties[7])->GetValue(); +} + +bool MP4RtpPacket::IsBFrame() +{ + return ((MP4BitfieldProperty*)m_pProperties[10])->GetValue(); +} + +void MP4RtpPacket::SetBFrame(bool isBFrame) +{ + ((MP4BitfieldProperty*)m_pProperties[10])->SetValue(isBFrame); +} + +void MP4RtpPacket::SetTimestampOffset(u_int32_t timestampOffset) +{ + if (timestampOffset == 0) { + return; + } + + ASSERT(((MP4BitfieldProperty*)m_pProperties[9])->GetValue() == 0); + + // set X bit + ((MP4BitfieldProperty*)m_pProperties[9])->SetValue(1); + + AddExtraProperties(); + + ((MP4Integer32Property*)m_pProperties[16])->SetValue(timestampOffset); +} + +void MP4RtpPacket::AddData(MP4RtpData* pData) +{ + m_rtpData.Add(pData); + + // increment entry count property + ((MP4Integer16Property*)m_pProperties[12])->IncrementValue(); +} + +u_int32_t MP4RtpPacket::GetDataSize() +{ + u_int32_t totalDataSize = 0; + + for (u_int32_t i = 0; i < m_rtpData.Size(); i++) { + totalDataSize += m_rtpData[i]->GetDataSize(); + } + + return totalDataSize; +} + +void MP4RtpPacket::GetData(u_int8_t* pDest) +{ + for (u_int32_t i = 0; i < m_rtpData.Size(); i++) { + m_rtpData[i]->GetData(pDest); + pDest += m_rtpData[i]->GetDataSize(); + } +} + +void MP4RtpPacket::Write(MP4File* pFile) +{ + MP4Container::Write(pFile); + + for (u_int32_t i = 0; i < m_rtpData.Size(); i++) { + m_rtpData[i]->Write(pFile); + } +} + +void MP4RtpPacket::WriteEmbeddedData(MP4File* pFile, u_int64_t startPos) +{ + for (u_int32_t i = 0; i < m_rtpData.Size(); i++) { + m_rtpData[i]->WriteEmbeddedData(pFile, startPos); + } +} + +void MP4RtpPacket::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits) +{ + MP4Container::Dump(pFile, indent, dumpImplicits); + + for (u_int32_t i = 0; i < m_rtpData.Size(); i++) { + Indent(pFile, indent); + fprintf(pFile, "RtpData: %u\n", i); + m_rtpData[i]->Dump(pFile, indent + 1, dumpImplicits); + } +} + +MP4RtpData::MP4RtpData(MP4RtpPacket* pPacket) +{ + m_pPacket = pPacket; + + AddProperty( /* 0 */ + new MP4Integer8Property("type")); +} + +MP4Track* MP4RtpData::FindTrackFromRefIndex(u_int8_t refIndex) +{ + MP4Track* pTrack; + + if (refIndex == (u_int8_t)-1) { + // ourselves + pTrack = GetPacket()->GetHint()->GetTrack(); + } else if (refIndex == 0) { + // our reference track + pTrack = GetPacket()->GetHint()->GetTrack()->GetRefTrack(); + } else { + // some other track + MP4RtpHintTrack* pHintTrack = + GetPacket()->GetHint()->GetTrack(); + + MP4Atom* pTrakAtom = pHintTrack->GetTrakAtom(); + ASSERT(pTrakAtom); + + MP4Integer32Property* pTrackIdProperty = NULL; + pTrakAtom->FindProperty( + "trak.tref.hint.entries", + (MP4Property**)&pTrackIdProperty); + ASSERT(pTrackIdProperty); + + u_int32_t refTrackId = + pTrackIdProperty->GetValue(refIndex - 1); + + pTrack = pHintTrack->GetFile()->GetTrack(refTrackId); + } + + return pTrack; +} + +MP4RtpNullData::MP4RtpNullData(MP4RtpPacket* pPacket) + : MP4RtpData(pPacket) +{ + ((MP4Integer8Property*)m_pProperties[0])->SetValue(0); + + AddProperty( /* 1 */ + new MP4BytesProperty("pad", 15)); + + ((MP4BytesProperty*)m_pProperties[1])->SetFixedSize(15); +} + +MP4RtpImmediateData::MP4RtpImmediateData(MP4RtpPacket* pPacket) + : MP4RtpData(pPacket) +{ + ((MP4Integer8Property*)m_pProperties[0])->SetValue(1); + + AddProperty( /* 1 */ + new MP4Integer8Property("count")); + AddProperty( /* 2 */ + new MP4BytesProperty("data", 14)); + + ((MP4BytesProperty*)m_pProperties[2])->SetFixedSize(14); +} + +void MP4RtpImmediateData::Set(const u_int8_t* pBytes, u_int8_t numBytes) +{ + ((MP4Integer8Property*)m_pProperties[1])->SetValue(numBytes); + ((MP4BytesProperty*)m_pProperties[2])->SetValue(pBytes, numBytes); +} + +u_int16_t MP4RtpImmediateData::GetDataSize() +{ + return ((MP4Integer8Property*)m_pProperties[1])->GetValue(); +} + +void MP4RtpImmediateData::GetData(u_int8_t* pDest) +{ + u_int8_t* pValue; + u_int32_t valueSize; + ((MP4BytesProperty*)m_pProperties[2])->GetValue(&pValue, &valueSize); + + memcpy(pDest, pValue, GetDataSize()); + MP4Free(pValue); +} + +MP4RtpSampleData::MP4RtpSampleData(MP4RtpPacket* pPacket) + : MP4RtpData(pPacket) +{ + ((MP4Integer8Property*)m_pProperties[0])->SetValue(2); + + AddProperty( /* 1 */ + new MP4Integer8Property("trackRefIndex")); + AddProperty( /* 2 */ + new MP4Integer16Property("length")); + AddProperty( /* 3 */ + new MP4Integer32Property("sampleNumber")); + AddProperty( /* 4 */ + new MP4Integer32Property("sampleOffset")); + AddProperty( /* 5 */ + new MP4Integer16Property("bytesPerBlock")); + AddProperty( /* 6 */ + new MP4Integer16Property("samplesPerBlock")); + + ((MP4Integer16Property*)m_pProperties[5])->SetValue(1); + ((MP4Integer16Property*)m_pProperties[6])->SetValue(1); + + m_pRefData = NULL; + m_pRefTrack = NULL; + m_refSampleId = MP4_INVALID_SAMPLE_ID; + m_refSampleOffset = 0; +} + +void MP4RtpSampleData::SetEmbeddedImmediate(MP4SampleId sampleId, + u_int8_t* pData, u_int16_t dataLength) +{ + ((MP4Integer8Property*)m_pProperties[1])->SetValue((u_int8_t)-1); + ((MP4Integer16Property*)m_pProperties[2])->SetValue(dataLength); + ((MP4Integer32Property*)m_pProperties[3])->SetValue(sampleId); + ((MP4Integer32Property*)m_pProperties[4])->SetValue(0); + CHECK_AND_FREE(m_pRefData); + m_pRefData = pData; +} + +void MP4RtpSampleData::SetReferenceSample( + MP4SampleId refSampleId, u_int32_t refSampleOffset, + u_int16_t sampleLength) +{ + ((MP4Integer8Property*)m_pProperties[1])->SetValue(0); + ((MP4Integer16Property*)m_pProperties[2])->SetValue(sampleLength); + ((MP4Integer32Property*)m_pProperties[3])->SetValue(refSampleId); + ((MP4Integer32Property*)m_pProperties[4])->SetValue(refSampleOffset); +} + +void MP4RtpSampleData::SetEmbeddedSample( + MP4SampleId sampleId, MP4Track* pRefTrack, + MP4SampleId refSampleId, u_int32_t refSampleOffset, + u_int16_t sampleLength) +{ + ((MP4Integer8Property*)m_pProperties[1])->SetValue((u_int8_t)-1); + ((MP4Integer16Property*)m_pProperties[2])->SetValue(sampleLength); + ((MP4Integer32Property*)m_pProperties[3])->SetValue(sampleId); + ((MP4Integer32Property*)m_pProperties[4])->SetValue(0); + m_pRefTrack = pRefTrack; + m_refSampleId = refSampleId; + m_refSampleOffset = refSampleOffset; +} + +u_int16_t MP4RtpSampleData::GetDataSize() +{ + return ((MP4Integer16Property*)m_pProperties[2])->GetValue(); +} + +void MP4RtpSampleData::GetData(u_int8_t* pDest) +{ + u_int8_t trackRefIndex = + ((MP4Integer8Property*)m_pProperties[1])->GetValue(); + + MP4Track* pSampleTrack = + FindTrackFromRefIndex(trackRefIndex); + + pSampleTrack->ReadSampleFragment( + ((MP4Integer32Property*)m_pProperties[3])->GetValue(), // sampleId + ((MP4Integer32Property*)m_pProperties[4])->GetValue(), // sampleOffset + ((MP4Integer16Property*)m_pProperties[2])->GetValue(), // sampleLength + pDest); +} + +void MP4RtpSampleData::WriteEmbeddedData(MP4File* pFile, u_int64_t startPos) +{ + // if not using embedded data, nothing to do + if (((MP4Integer8Property*)m_pProperties[1])->GetValue() != (u_int8_t)-1) { + return; + } + + // figure out the offset within this hint sample for this embedded data + u_int64_t offset = pFile->GetPosition() - startPos; + ASSERT(offset <= 0xFFFFFFFF); + ((MP4Integer32Property*)m_pProperties[4])->SetValue((u_int32_t)offset); + + u_int16_t length = ((MP4Integer16Property*)m_pProperties[2])->GetValue(); + + if (m_pRefData) { + pFile->WriteBytes(m_pRefData, length); + return; + } + + if (m_refSampleId != MP4_INVALID_SAMPLE_ID) { + u_int8_t* pSample = NULL; + u_int32_t sampleSize = 0; + + ASSERT(m_pRefTrack); + m_pRefTrack->ReadSample(m_refSampleId, &pSample, &sampleSize); + + ASSERT(m_refSampleOffset + length <= sampleSize); + + pFile->WriteBytes(&pSample[m_refSampleOffset], length); + + MP4Free(pSample); + return; + } +} + +MP4RtpSampleDescriptionData::MP4RtpSampleDescriptionData(MP4RtpPacket* pPacket) + : MP4RtpData(pPacket) +{ + ((MP4Integer8Property*)m_pProperties[0])->SetValue(3); + + AddProperty( /* 1 */ + new MP4Integer8Property("trackRefIndex")); + AddProperty( /* 2 */ + new MP4Integer16Property("length")); + AddProperty( /* 3 */ + new MP4Integer32Property("sampleDescriptionIndex")); + AddProperty( /* 4 */ + new MP4Integer32Property("sampleDescriptionOffset")); + AddProperty( /* 5 */ + new MP4Integer32Property("reserved")); +} + +void MP4RtpSampleDescriptionData::Set(u_int32_t sampleDescrIndex, + u_int32_t offset, u_int16_t length) +{ + ((MP4Integer16Property*)m_pProperties[2])->SetValue(length); + ((MP4Integer32Property*)m_pProperties[3])->SetValue(sampleDescrIndex); + ((MP4Integer32Property*)m_pProperties[4])->SetValue(offset); +} + +u_int16_t MP4RtpSampleDescriptionData::GetDataSize() +{ + return ((MP4Integer16Property*)m_pProperties[2])->GetValue(); +} + +void MP4RtpSampleDescriptionData::GetData(u_int8_t* pDest) +{ + // we start with the index into our track references + u_int8_t trackRefIndex = + ((MP4Integer8Property*)m_pProperties[1])->GetValue(); + + // from which we can find the track structure + MP4Track* pSampleTrack = + FindTrackFromRefIndex(trackRefIndex); + + // next find the desired atom in the track's sample description table + u_int32_t sampleDescrIndex = + ((MP4Integer32Property*)m_pProperties[3])->GetValue(); + + MP4Atom* pTrakAtom = + pSampleTrack->GetTrakAtom(); + + char sdName[64]; + sprintf(sdName, "trak.mdia.minf.stbl.stsd.*[%u]", sampleDescrIndex); + + MP4Atom* pSdAtom = + pTrakAtom->FindAtom(sdName); + + // bad reference + if (pSdAtom == NULL) { + throw new MP4Error("invalid sample description index", + "MP4RtpSampleDescriptionData::GetData"); + } + + // check validity of the upcoming copy + u_int16_t length = + ((MP4Integer16Property*)m_pProperties[2])->GetValue(); + u_int32_t offset = + ((MP4Integer32Property*)m_pProperties[4])->GetValue(); + + if (offset + length > pSdAtom->GetSize()) { + throw new MP4Error("offset and/or length are too large", + "MP4RtpSampleDescriptionData::GetData"); + } + + // now we use the raw file to get the desired bytes + + MP4File* pFile = GetPacket()->GetHint()->GetTrack()->GetFile(); + + u_int64_t orgPos = pFile->GetPosition(); + + // It's not entirely clear from the spec whether the offset is from + // the start of the sample descirption atom, or the start of the atom's + // data. I believe it is the former, but the commented out code will + // realize the latter interpretation if I turn out to be wrong. + u_int64_t dataPos = pSdAtom->GetStart(); + //u_int64_t dataPos = pSdAtom->GetEnd() - pSdAtom->GetSize(); + + pFile->SetPosition(dataPos + offset); + + pFile->ReadBytes(pDest, length); + + pFile->SetPosition(orgPos); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/rtphint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/rtphint.h Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,352 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#ifndef __RTPHINT_INCLUDED__ +#define __RTPHINT_INCLUDED__ + +// forward declarations +class MP4RtpHintTrack; +class MP4RtpHint; +class MP4RtpPacket; + +class MP4RtpData : public MP4Container { +public: + MP4RtpData(MP4RtpPacket* pPacket); + + MP4RtpPacket* GetPacket() { + return m_pPacket; + } + + virtual u_int16_t GetDataSize() = 0; + virtual void GetData(u_int8_t* pDest) = 0; + + MP4Track* FindTrackFromRefIndex(u_int8_t refIndex); + + virtual void WriteEmbeddedData(MP4File* pFile, u_int64_t startPos) { + // default is no-op + } + +protected: + MP4RtpPacket* m_pPacket; +}; + +MP4ARRAY_DECL(MP4RtpData, MP4RtpData*) + +class MP4RtpNullData : public MP4RtpData { +public: + MP4RtpNullData(MP4RtpPacket* pPacket); + + u_int16_t GetDataSize() { + return 0; + } + + void GetData(u_int8_t* pDest) { + // no-op + } +}; + +class MP4RtpImmediateData : public MP4RtpData { +public: + MP4RtpImmediateData(MP4RtpPacket* pPacket); + + void Set(const u_int8_t* pBytes, u_int8_t numBytes); + + u_int16_t GetDataSize(); + + void GetData(u_int8_t* pDest); +}; + +class MP4RtpSampleData : public MP4RtpData { +public: + MP4RtpSampleData(MP4RtpPacket* pPacket); + + ~MP4RtpSampleData(void) { + CHECK_AND_FREE(m_pRefData); + }; + + void SetEmbeddedImmediate( + MP4SampleId sampleId, + u_int8_t* pData, u_int16_t dataLength); + + void SetReferenceSample( + MP4SampleId refSampleId, u_int32_t refSampleOffset, + u_int16_t sampleLength); + + void SetEmbeddedSample( + MP4SampleId sampleId, MP4Track* pRefTrack, + MP4SampleId refSampleId, u_int32_t refSampleOffset, + u_int16_t sampleLength); + + u_int16_t GetDataSize(); + + void GetData(u_int8_t* pDest); + + void WriteEmbeddedData(MP4File* pFile, u_int64_t startPos); + +protected: + u_int8_t* m_pRefData; + + MP4Track* m_pRefTrack; + MP4SampleId m_refSampleId; + u_int32_t m_refSampleOffset; +}; + +class MP4RtpSampleDescriptionData : public MP4RtpData { +public: + MP4RtpSampleDescriptionData(MP4RtpPacket* pPacket); + + void Set(u_int32_t sampleDescrIndex, + u_int32_t offset, u_int16_t length); + + u_int16_t GetDataSize(); + + void GetData(u_int8_t* pDest); +}; + +class MP4RtpPacket : public MP4Container { +public: + MP4RtpPacket(MP4RtpHint* pHint); + + ~MP4RtpPacket(); + + void AddExtraProperties(); + + MP4RtpHint* GetHint() { + return m_pHint; + } + + void Set(u_int8_t payloadNumber, u_int32_t packetId, bool setMbit); + + int32_t GetTransmitOffset(); + + bool GetPBit(); + + bool GetXBit(); + + bool GetMBit(); + + u_int8_t GetPayload(); + + u_int16_t GetSequenceNumber(); + + void SetTransmitOffset(int32_t transmitOffset); + + bool IsBFrame(); + + void SetBFrame(bool isBFrame); + + void SetTimestampOffset(u_int32_t timestampOffset); + + void AddData(MP4RtpData* pData); + + u_int32_t GetDataSize(); + + void GetData(u_int8_t* pDest); + + void Read(MP4File* pFile); + + void ReadExtra(MP4File* pFile); + + void Write(MP4File* pFile); + + void WriteEmbeddedData(MP4File* pFile, u_int64_t startPos); + + void Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits); + +protected: + MP4RtpHint* m_pHint; + MP4RtpDataArray m_rtpData; +}; + +MP4ARRAY_DECL(MP4RtpPacket, MP4RtpPacket*) + +class MP4RtpHint : public MP4Container { +public: + MP4RtpHint(MP4RtpHintTrack* pTrack); + + ~MP4RtpHint(); + + MP4RtpHintTrack* GetTrack() { + return m_pTrack; + } + + u_int16_t GetNumberOfPackets() { + return m_rtpPackets.Size(); + } + + bool IsBFrame() { + return m_isBFrame; + } + void SetBFrame(bool isBFrame) { + m_isBFrame = isBFrame; + } + + u_int32_t GetTimestampOffset() { + return m_timestampOffset; + } + void SetTimestampOffset(u_int32_t timestampOffset) { + m_timestampOffset = timestampOffset; + } + + MP4RtpPacket* AddPacket(); + + MP4RtpPacket* GetPacket(u_int16_t index) { + return m_rtpPackets[index]; + } + + MP4RtpPacket* GetCurrentPacket() { + if (m_rtpPackets.Size() == 0) { + return NULL; + } + return m_rtpPackets[m_rtpPackets.Size() - 1]; + } + + void Read(MP4File* pFile); + + void Write(MP4File* pFile); + + void Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits); + +protected: + MP4RtpHintTrack* m_pTrack; + MP4RtpPacketArray m_rtpPackets; + + // values when adding packets to a hint (write mode) + bool m_isBFrame; + u_int32_t m_timestampOffset; +}; + +class MP4RtpHintTrack : public MP4Track { +public: + MP4RtpHintTrack(MP4File* pFile, MP4Atom* pTrakAtom); + + ~MP4RtpHintTrack(); + + void InitRefTrack(); + + void InitPayload(); + + void InitRtpStart(); + + void InitStats(); + + MP4Track* GetRefTrack() { + InitRefTrack(); + return m_pRefTrack; + } + + void GetPayload( + char** ppPayloadName = NULL, + u_int8_t* pPayloadNumber = NULL, + u_int16_t* pMaxPayloadSize = NULL, + char **ppEncodingParams = NULL); + + void SetPayload( + const char* payloadName, + u_int8_t payloadNumber, + u_int16_t maxPayloadSize, + const char *encoding_parms, + bool add_rtpmap, + bool add_mpeg4_esid); + + void ReadHint( + MP4SampleId hintSampleId, + u_int16_t* pNumPackets = NULL); + + u_int16_t GetHintNumberOfPackets(); + + bool GetPacketBFrame(u_int16_t packetIndex); + + u_int16_t GetPacketTransmitOffset(u_int16_t packetIndex); + + void ReadPacket( + u_int16_t packetIndex, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + u_int32_t ssrc, + bool includeHeader = true, + bool includePayload = true); + + MP4Timestamp GetRtpTimestampStart(); + + void SetRtpTimestampStart(MP4Timestamp start); + + void AddHint(bool isBFrame, u_int32_t timestampOffset); + + void AddPacket(bool setMbit, int32_t transmitOffset = 0); + + void AddImmediateData(const u_int8_t* pBytes, u_int32_t numBytes); + + void AddSampleData(MP4SampleId sampleId, + u_int32_t dataOffset, u_int32_t dataLength); + + void AddESConfigurationPacket(); + + void WriteHint(MP4Duration duration, bool isSyncSample); + + void FinishWrite(); + +protected: + MP4Track* m_pRefTrack; + + MP4StringProperty* m_pRtpMapProperty; + MP4Integer32Property* m_pPayloadNumberProperty; + MP4Integer32Property* m_pMaxPacketSizeProperty; + MP4Integer32Property* m_pSnroProperty; + MP4Integer32Property* m_pTsroProperty; + u_int32_t m_rtpSequenceStart; + u_int32_t m_rtpTimestampStart; + + // reading + MP4RtpHint* m_pReadHint; + u_int8_t* m_pReadHintSample; + u_int32_t m_readHintSampleSize; + MP4Timestamp m_readHintTimestamp; + + // writing + MP4RtpHint* m_pWriteHint; + MP4SampleId m_writeHintId; + u_int32_t m_writePacketId; + + // statistics + // in trak.udta.hinf + MP4Integer64Property* m_pTrpy; + MP4Integer64Property* m_pNump; + MP4Integer64Property* m_pTpyl; + MP4Integer32Property* m_pMaxr; + MP4Integer64Property* m_pDmed; + MP4Integer64Property* m_pDimm; + MP4Integer32Property* m_pPmax; + MP4Integer32Property* m_pDmax; + + // in trak.mdia.minf.hmhd + MP4Integer16Property* m_pMaxPdu; + MP4Integer16Property* m_pAvgPdu; + MP4Integer32Property* m_pMaxBitRate; + MP4Integer32Property* m_pAvgBitRate; + + MP4Timestamp m_thisSec; + u_int32_t m_bytesThisSec; + u_int32_t m_bytesThisHint; + u_int32_t m_bytesThisPacket; +}; + +#endif /* __RTPHINT_INCLUDED__ */ diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/Makefile.am Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,24 @@ + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/lib/mp4v2 + +check_PROGRAMS = c_api mp4broadcaster nullcreate nullvplayer urltrack mp4clip + +c_api_SOURCES = c_api.c +c_api_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la -lstdc++ + +mp4broadcaster_SOURCES = mp4broadcaster.cpp +mp4broadcaster_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la + +nullcreate_SOURCES = nullcreate.cpp +nullcreate_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la + +nullvplayer_SOURCES = nullvplayer.cpp +nullvplayer_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la + +urltrack_SOURCES = urltrack.cpp +urltrack_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la + +mp4clip_SOURCES = mp4clip.cpp +mp4clip_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/Makefile.in Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,592 @@ +# Makefile.in generated by automake 1.8.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SOURCES = $(c_api_SOURCES) $(mp4broadcaster_SOURCES) $(mp4clip_SOURCES) $(nullcreate_SOURCES) $(nullvplayer_SOURCES) $(urltrack_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +check_PROGRAMS = c_api$(EXEEXT) mp4broadcaster$(EXEEXT) \ + nullcreate$(EXEEXT) nullvplayer$(EXEEXT) urltrack$(EXEEXT) \ + mp4clip$(EXEEXT) +subdir = lib/mp4v2/test +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = $(top_builddir)/mpeg4ip_config.h +CONFIG_CLEAN_FILES = +am_c_api_OBJECTS = c_api.$(OBJEXT) +c_api_OBJECTS = $(am_c_api_OBJECTS) +c_api_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la +am_mp4broadcaster_OBJECTS = mp4broadcaster.$(OBJEXT) +mp4broadcaster_OBJECTS = $(am_mp4broadcaster_OBJECTS) +mp4broadcaster_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la +am_mp4clip_OBJECTS = mp4clip.$(OBJEXT) +mp4clip_OBJECTS = $(am_mp4clip_OBJECTS) +mp4clip_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +am_nullcreate_OBJECTS = nullcreate.$(OBJEXT) +nullcreate_OBJECTS = $(am_nullcreate_OBJECTS) +nullcreate_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la +am_nullvplayer_OBJECTS = nullvplayer.$(OBJEXT) +nullvplayer_OBJECTS = $(am_nullvplayer_OBJECTS) +nullvplayer_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la +am_urltrack_OBJECTS = urltrack.$(OBJEXT) +urltrack_OBJECTS = $(am_urltrack_OBJECTS) +urltrack_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/c_api.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mp4broadcaster.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mp4clip.Po ./$(DEPDIR)/nullcreate.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/nullvplayer.Po ./$(DEPDIR)/urltrack.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(c_api_SOURCES) $(mp4broadcaster_SOURCES) \ + $(mp4clip_SOURCES) $(nullcreate_SOURCES) \ + $(nullvplayer_SOURCES) $(urltrack_SOURCES) +DIST_SOURCES = $(c_api_SOURCES) $(mp4broadcaster_SOURCES) \ + $(mp4clip_SOURCES) $(nullcreate_SOURCES) \ + $(nullvplayer_SOURCES) $(urltrack_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AESICM_INC = @AESICM_INC@ +ALIGN_FUNCS = @ALIGN_FUNCS@ +ALIGN_JUMPS = @ALIGN_JUMPS@ +ALIGN_LOOPS = @ALIGN_LOOPS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BILLS_CPPWARNINGS = @BILLS_CPPWARNINGS@ +BILLS_CWARNINGS = @BILLS_CWARNINGS@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FAAC_LIB = @FAAC_LIB@ +FFLAGS = @FFLAGS@ +FFMPEG_INC = @FFMPEG_INC@ +FFMPEG_LIB = @FFMPEG_LIB@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_A52DEC_LIB_FALSE = @HAVE_A52DEC_LIB_FALSE@ +HAVE_A52DEC_LIB_TRUE = @HAVE_A52DEC_LIB_TRUE@ +HAVE_ALIGN_FUNCS_FALSE = @HAVE_ALIGN_FUNCS_FALSE@ +HAVE_ALIGN_FUNCS_TRUE = @HAVE_ALIGN_FUNCS_TRUE@ +HAVE_ALIGN_JUMPS_FALSE = @HAVE_ALIGN_JUMPS_FALSE@ +HAVE_ALIGN_JUMPS_TRUE = @HAVE_ALIGN_JUMPS_TRUE@ +HAVE_ALIGN_LOOPS_FALSE = @HAVE_ALIGN_LOOPS_FALSE@ +HAVE_ALIGN_LOOPS_TRUE = @HAVE_ALIGN_LOOPS_TRUE@ +HAVE_FFMPEG_FALSE = @HAVE_FFMPEG_FALSE@ +HAVE_FFMPEG_TRUE = @HAVE_FFMPEG_TRUE@ +HAVE_ID3_TAG_FALSE = @HAVE_ID3_TAG_FALSE@ +HAVE_ID3_TAG_TRUE = @HAVE_ID3_TAG_TRUE@ +HAVE_LIBMAD_FALSE = @HAVE_LIBMAD_FALSE@ +HAVE_LIBMAD_TRUE = @HAVE_LIBMAD_TRUE@ +HAVE_LIBMPEG2_FALSE = @HAVE_LIBMPEG2_FALSE@ +HAVE_LIBMPEG2_TRUE = @HAVE_LIBMPEG2_TRUE@ +HAVE_MAC_OSX_FALSE = @HAVE_MAC_OSX_FALSE@ +HAVE_MAC_OSX_TRUE = @HAVE_MAC_OSX_TRUE@ +HAVE_V4L2_FALSE = @HAVE_V4L2_FALSE@ +HAVE_V4L2_TRUE = @HAVE_V4L2_TRUE@ +HAVE_X264_FALSE = @HAVE_X264_FALSE@ +HAVE_X264_TRUE = @HAVE_X264_TRUE@ +HAVE_XVID_1_0_FALSE = @HAVE_XVID_1_0_FALSE@ +HAVE_XVID_1_0_TRUE = @HAVE_XVID_1_0_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +ISMACRYP_FLAGS = @ISMACRYP_FLAGS@ +ISMACRYP_INC = @ISMACRYP_INC@ +ISMACRYP_LIB = @ISMACRYP_LIB@ +LAME_LIB = @LAME_LIB@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_C_TAG = @LIBTOOL_C_TAG@ +LIBVORBIS_LIB = @LIBVORBIS_LIB@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MP4LIVE_FALSE = @MP4LIVE_FALSE@ +MP4LIVE_TRUE = @MP4LIVE_TRUE@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +NO_GLIB_GTK_FALSE = @NO_GLIB_GTK_FALSE@ +NO_GLIB_GTK_TRUE = @NO_GLIB_GTK_TRUE@ +NO_XVID_FALSE = @NO_XVID_FALSE@ +NO_XVID_TRUE = @NO_XVID_TRUE@ +OBJC = @OBJC@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLAYER_FALSE = @PLAYER_FALSE@ +PLAYER_PLUGIN_DIR = @PLAYER_PLUGIN_DIR@ +PLAYER_TRUE = @PLAYER_TRUE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +SDL_LIB_LIBS = @SDL_LIB_LIBS@ +SERVER_FALSE = @SERVER_FALSE@ +SERVER_TRUE = @SERVER_TRUE@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SUN_LIBS = @SUN_LIBS@ +USENASM = @USENASM@ +USE_MMX_FALSE = @USE_MMX_FALSE@ +USE_MMX_TRUE = @USE_MMX_TRUE@ +USE_PPC_FALSE = @USE_PPC_FALSE@ +USE_PPC_TRUE = @USE_PPC_TRUE@ +VERSION = @VERSION@ +X264_LIB = @X264_LIB@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/lib/mp4v2 +c_api_SOURCES = c_api.c +c_api_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la -lstdc++ +mp4broadcaster_SOURCES = mp4broadcaster.cpp +mp4broadcaster_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la +nullcreate_SOURCES = nullcreate.cpp +nullcreate_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la +nullvplayer_SOURCES = nullvplayer.cpp +nullvplayer_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la +urltrack_SOURCES = urltrack.cpp +urltrack_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la +mp4clip_SOURCES = mp4clip.cpp +mp4clip_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/mp4v2/test/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/mp4v2/test/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +c_api$(EXEEXT): $(c_api_OBJECTS) $(c_api_DEPENDENCIES) + @rm -f c_api$(EXEEXT) + $(LINK) $(c_api_LDFLAGS) $(c_api_OBJECTS) $(c_api_LDADD) $(LIBS) +mp4broadcaster$(EXEEXT): $(mp4broadcaster_OBJECTS) $(mp4broadcaster_DEPENDENCIES) + @rm -f mp4broadcaster$(EXEEXT) + $(CXXLINK) $(mp4broadcaster_LDFLAGS) $(mp4broadcaster_OBJECTS) $(mp4broadcaster_LDADD) $(LIBS) +mp4clip$(EXEEXT): $(mp4clip_OBJECTS) $(mp4clip_DEPENDENCIES) + @rm -f mp4clip$(EXEEXT) + $(CXXLINK) $(mp4clip_LDFLAGS) $(mp4clip_OBJECTS) $(mp4clip_LDADD) $(LIBS) +nullcreate$(EXEEXT): $(nullcreate_OBJECTS) $(nullcreate_DEPENDENCIES) + @rm -f nullcreate$(EXEEXT) + $(CXXLINK) $(nullcreate_LDFLAGS) $(nullcreate_OBJECTS) $(nullcreate_LDADD) $(LIBS) +nullvplayer$(EXEEXT): $(nullvplayer_OBJECTS) $(nullvplayer_DEPENDENCIES) + @rm -f nullvplayer$(EXEEXT) + $(CXXLINK) $(nullvplayer_LDFLAGS) $(nullvplayer_OBJECTS) $(nullvplayer_LDADD) $(LIBS) +urltrack$(EXEEXT): $(urltrack_OBJECTS) $(urltrack_DEPENDENCIES) + @rm -f urltrack$(EXEEXT) + $(CXXLINK) $(urltrack_LDFLAGS) $(urltrack_OBJECTS) $(urltrack_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_api.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4broadcaster.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4clip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nullcreate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nullvplayer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/urltrack.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/c_api.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/c_api.c Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,53 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4.h" + +main(int argc, char** argv) +{ +#if 0 + MP4FileHandle mp4File = MP4Read(argv[1], MP4_DETAILS_ERROR); + + if (!mp4File) { + exit(1); + } + + MP4Dump(mp4File, stdout, 0); + + MP4Close(mp4File); + + exit(0); +#else + MP4FileHandle mp4File; + + mp4File = MP4Modify(argv[1], MP4_DETAILS_ERROR, 0); + MP4SetVerbosity(mp4File, MP4_DETAILS_ALL); +#if 1 + u_int8_t* data=(u_int8_t*)"this is my tag data"; + u_int32_t len=strlen((char*)data); + MP4SetMetadataFreeForm(mp4File, "mytag1",data,len); + MP4SetMetadataFreeForm(mp4File, "my_tag2",data,len); +#endif + MP4Close(mp4File); + exit(0); +#endif +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/mp4broadcaster.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/mp4broadcaster.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,435 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mpeg4ip.h" +#include +#include "mp4.h" + +// forward declarations +static bool AssembleSdp( + MP4FileHandle mp4File, + const char* sdpFileName, + const char* destIpAddress); + +static bool InitSockets( + u_int32_t numSockets, + int* pSockets, + const char* destIpAddress); + +static u_int64_t GetUsecTime(); + +// globals +char* ProgName; +u_int16_t UdpBasePort = 20000; +u_int32_t MulticastTtl = 2; // increase value if necessary + +const u_int32_t SecsBetween1900And1970 = 2208988800U; + + +// the main show +int main(int argc, char** argv) +{ + // since we're a test program + // keep command line processing to a minimum + // and assume some defaults + ProgName = argv[0]; + char* sdpFileName = "./mp4broadcaster.sdp"; + char* destIpAddress = "224.1.2.3"; + + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", ProgName); + exit(1); + } + + char* mp4FileName = argv[1]; + u_int32_t verbosity = + MP4_DETAILS_ERROR | MP4_DETAILS_READ + | MP4_DETAILS_SAMPLE | MP4_DETAILS_HINT; + + // open the mp4 file + MP4FileHandle mp4File = MP4Read(mp4FileName, verbosity); + + if (mp4File == MP4_INVALID_FILE_HANDLE) { + // library will print an error message + exit(1); + } + + // check for hint tracks + u_int32_t numHintTracks = + MP4GetNumberOfTracks(mp4File, MP4_HINT_TRACK_TYPE); + + if (numHintTracks == 0) { + fprintf(stderr, "%s: File %s does not contain any hint tracks", + ProgName, mp4FileName); + exit(2); + } + + // assemble and write out sdp file + AssembleSdp(mp4File, sdpFileName, destIpAddress); + + // create two UDP sockets for each track that will be streamed + // one for the RTP media, one for the RTCP control + int* udpSockets = new int[numHintTracks * 2]; + + if (!InitSockets(numHintTracks, udpSockets, destIpAddress)) { + fprintf(stderr, "%s: Couldn't create UDP sockets\n", + ProgName); + exit(3); + } + + // initialize RTCP packet + u_int32_t ssrc = random(); + char rtcpCName[256]; + char* username = getlogin(); + char hostname[256]; + gethostname(hostname, sizeof(hostname)); + snprintf(rtcpCName, sizeof(rtcpCName), "%s@%s", username, hostname); + + u_int8_t rtcpPacket[512]; + u_int16_t rtcpPacketLength = 38; + + // RTCP SR + rtcpPacket[0] = 0x80; + rtcpPacket[1] = 0xC8; + rtcpPacket[2] = 0x00; + rtcpPacket[3] = 0x06; + *(u_int32_t*)&rtcpPacket[4] = htonl(ssrc); + + // RTCP SDES CNAME + rtcpPacket[28] = 0x80; + rtcpPacket[29] = 0xCA; + *(u_int32_t*)&rtcpPacket[32] = htonl(ssrc); + + rtcpPacket[36] = 0x01; + rtcpPacket[37] = strlen(rtcpCName); + strcpy((char*)&rtcpPacket[38], rtcpCName); + rtcpPacketLength += strlen(rtcpCName) + 1; + + // pad with zero's to 32 bit boundary + while (rtcpPacketLength % 4 != 0) { + rtcpPacket[rtcpPacketLength++] = 0; + } + + *(u_int16_t*)&rtcpPacket[30] = ntohs((rtcpPacketLength - 32) / 4); + + // initialize per track variables that we will use in main loop + MP4TrackId* hintTrackIds = new MP4TrackId[numHintTracks]; + MP4SampleId* nextHintIds = new MP4SampleId[numHintTracks]; + MP4SampleId* maxHintIds = new MP4SampleId[numHintTracks]; + u_int64_t* nextHintTimes = new MP4Timestamp[numHintTracks]; + u_int32_t* packetsSent = new u_int32_t[numHintTracks]; + u_int32_t* bytesSent = new u_int32_t[numHintTracks]; + + u_int32_t i; + + for (i = 0; i < numHintTracks; i++) { + hintTrackIds[i] = MP4FindTrackId(mp4File, i, MP4_HINT_TRACK_TYPE); + nextHintIds[i] = 1; + maxHintIds[i] = MP4GetTrackNumberOfSamples(mp4File, hintTrackIds[i]); + nextHintTimes[i] = (u_int64_t)-1; + packetsSent[i] = 0; + bytesSent[i] = 0; + } + + // remember the starting time + u_int64_t start = GetUsecTime(); + u_int64_t lastSR = 0; + + // main loop to stream data + while (true) { + u_int32_t nextTrackIndex = (u_int32_t)-1; + u_int64_t nextTime = (u_int64_t)-1; + + // find the next hint to send + for (i = 0; i < numHintTracks; i++) { + if (nextHintIds[i] > maxHintIds[i]) { + // have finished this track + continue; + } + + // need to get the time of the next hint + if (nextHintTimes[i] == (u_int64_t)-1) { + MP4Timestamp hintTime = + MP4GetSampleTime(mp4File, hintTrackIds[i], nextHintIds[i]); + + nextHintTimes[i] = + MP4ConvertFromTrackTimestamp(mp4File, hintTrackIds[i], + hintTime, MP4_USECS_TIME_SCALE); + } + + // check if this track's next hint is the earliest yet + if (nextHintTimes[i] > nextTime) { + continue; + } + + // make this our current choice for the next hint + nextTime = nextHintTimes[i]; + nextTrackIndex = i; + } + + // check exit condition, i.e all hints for all tracks have been used + if (nextTrackIndex == (u_int32_t)-1) { + break; + } + + // wait until the correct time to send next hint + // we assume we're not going to fall behind for testing purposes + // in a real application some skipping of samples might be needed + + u_int64_t now = GetUsecTime(); + int64_t waitTime = (start + nextTime) - now; + if (waitTime > 0) { + usleep(waitTime); + } + + now = GetUsecTime(); + + // emit RTCP Sender Reports every 5 seconds for all media streams + // not quite what a real app would do, but close enough for testing + if (now - lastSR >= 5000000) { + for (i = 0; i < numHintTracks; i++) { + now = GetUsecTime(); + + u_int32_t ntpSecs = + (now / MP4_USECS_TIME_SCALE) + SecsBetween1900And1970; + *(u_int32_t*)&rtcpPacket[8] = + htonl(ntpSecs); + + u_int32_t usecs = now % MP4_USECS_TIME_SCALE; + u_int32_t ntpUSecs = + (usecs << 12) + (usecs << 8) - ((usecs * 3650) >> 6); + *(u_int32_t*)&rtcpPacket[12] = + htonl(ntpUSecs); + + MP4Timestamp rtpStart = + MP4GetRtpTimestampStart(mp4File, hintTrackIds[i]); + + MP4Timestamp rtpOffset = + MP4ConvertToTrackTimestamp(mp4File, hintTrackIds[i], + now - start, MP4_USECS_TIME_SCALE); + + *(u_int32_t*)&rtcpPacket[16] = + htonl(rtpStart + rtpOffset); + + *(u_int32_t*)&rtcpPacket[20] = + htonl(packetsSent[i]); + *(u_int32_t*)&rtcpPacket[24] = + htonl(bytesSent[i]); + + send(udpSockets[i * 2 + 1], rtcpPacket, rtcpPacketLength, 0); + } + + lastSR = now; + } + + // send all the packets for this hint + // since this is just a test program + // we don't attempt to smooth out the transmission of the packets + + u_int16_t numPackets; + + MP4ReadRtpHint( + mp4File, + hintTrackIds[nextTrackIndex], + nextHintIds[nextTrackIndex], + &numPackets); + + // move along in this hint track + nextHintIds[nextTrackIndex]++; + nextHintTimes[nextTrackIndex] = (u_int64_t)-1; + + u_int16_t packetIndex; + + for (packetIndex = 0; packetIndex < numPackets; packetIndex++) { + u_int8_t* pPacket = NULL; + u_int32_t packetSize; + + // get the packet from the library + MP4ReadRtpPacket( + mp4File, + hintTrackIds[nextTrackIndex], + packetIndex, + &pPacket, + &packetSize, + ssrc); + + if (pPacket == NULL) { + // error, but forge on + continue; + } + + // send it out via UDP + send(udpSockets[nextTrackIndex * 2], pPacket, packetSize, 0); + + // free packet buffer + free(pPacket); + + bytesSent[nextTrackIndex] += packetSize - 12; + } + + packetsSent[nextTrackIndex] += numPackets; + } + + // main loop finished + + // close the UDP sockets + for (i = 0; i < numHintTracks; i++) { + close(udpSockets[i]); + } + + // close mp4 file + MP4Close(mp4File); + + // free up memory + delete [] hintTrackIds; + delete [] nextHintIds; + delete [] maxHintIds; + delete [] nextHintTimes; + delete [] packetsSent; + delete [] bytesSent; + + exit(0); +} + +static bool AssembleSdp( + MP4FileHandle mp4File, + const char* sdpFileName, + const char* destIpAddress) +{ + // open the destination sdp file + FILE* sdpFile = fopen(sdpFileName, "w"); + + if (sdpFile == NULL) { + fprintf(stderr, + "%s: couldn't open sdp file %s\n", + ProgName, sdpFileName); + return false; + } + + // add required header fields + fprintf(sdpFile, + "v=0\015\012" + "o=- 1 1 IN IP4 127.0.0.1\015\012" + "s=mp4broadcaster\015\012" + "e=NONE\015\012" + "c=IN IP4 %s/%u\015\012" + "b=RR:0\015\012", + destIpAddress, + MulticastTtl); + + // add session level info from mp4 file + fprintf(sdpFile, "%s", + MP4GetSessionSdp(mp4File)); + + // add per track info + u_int32_t numHintTracks = + MP4GetNumberOfTracks(mp4File, MP4_HINT_TRACK_TYPE); + + for (u_int32_t i = 0; i < numHintTracks; i++) { + MP4TrackId hintTrackId = + MP4FindTrackId(mp4File, i, MP4_HINT_TRACK_TYPE); + + if (hintTrackId == MP4_INVALID_TRACK_ID) { + continue; + } + + // get track sdp info from mp4 file + const char* mediaSdp = + MP4GetHintTrackSdp(mp4File, hintTrackId); + + // since we're going to broadcast instead of use RTSP for on-demand + // we need to fill in the UDP port numbers for the media + const char* portZero = strchr(mediaSdp, '0'); + if (portZero == NULL) { + continue; // mal-formed sdp + } + fprintf(sdpFile, "%.*s%u%s", + portZero - mediaSdp, + mediaSdp, + UdpBasePort + (i * 2), + portZero + 1); + } + + fclose(sdpFile); + + return true; +} + +static bool InitSockets( + u_int32_t numSocketPairs, + int* pSockets, + const char* destIpAddress) +{ + u_int32_t i; + + + for (i = 0; i < numSocketPairs * 2; i++) { + // create the socket + pSockets[i] = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + + if (pSockets[i] < 0) { + return false; + } + + // allow local listeners to multicast + int reuse = 1; + setsockopt(pSockets[i], SOL_SOCKET, SO_REUSEADDR, + &reuse, sizeof(reuse)); +#ifdef SO_REUSEPORT + // not all implementations have this option + setsockopt(pSockets[i], SOL_SOCKET, SO_REUSEPORT, + &reuse, sizeof(reuse)); +#endif + + // get a local source address + struct sockaddr_in sin; + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = INADDR_ANY; + + if (bind(pSockets[i], (struct sockaddr*)&sin, sizeof(sin))) { + return false; + } + + // bind to the destination address + sin.sin_port = htons(UdpBasePort + i); + inet_aton(destIpAddress, &sin.sin_addr); + + if (connect(pSockets[i], (struct sockaddr*)&sin, sizeof(sin)) < 0) { + return false; + } + + // set the multicast time to live + setsockopt(pSockets[i], IPPROTO_IP, IP_MULTICAST_TTL, + &MulticastTtl, sizeof(MulticastTtl)); + } + + return true; +} + +// get absolute time expressed in microseconds +static u_int64_t GetUsecTime() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec * 1000000) + tv.tv_usec; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/mp4clip.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/mp4clip.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,243 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001-2002. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +// N.B. mp4clips clips tracks in an mp4 file +// without regard to sync samples aka "key frames" +// as a testing app the burden is on the user to choose +// an appropriate clip start time + +#include "mp4.h" +#include "mpeg4ip_getopt.h" + +char* ProgName; + +// forward declaration +void ClipTrack( + MP4FileHandle srcFile, + MP4TrackId trackId, + MP4FileHandle dstFile, + float startTime, + float duration); + + +int main(int argc, char** argv) +{ + char* usageString = + "usage: %s [-t ] [-v []] [-s ] -l \n"; + char* srcFileName = NULL; + char* dstFileName = NULL; + MP4TrackId trackId = MP4_INVALID_TRACK_ID; + u_int32_t verbosity = MP4_DETAILS_ERROR; + float startTime = 0.0; + float duration = 0.0; + + /* begin processing command line */ + ProgName = argv[0]; + while (true) { + int c = -1; + int option_index = 0; + static struct option long_options[] = { + { "length", 1, 0, 'l' }, + { "start", 1, 0, 's' }, + { "track", 1, 0, 't' }, + { "verbose", 2, 0, 'v' }, + { "version", 0, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "l:s:t:v::V", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 'l': + if (sscanf(optarg, "%f", &duration) != 1) { + fprintf(stderr, + "%s: bad length specified: %s\n", + ProgName, optarg); + } + break; + case 's': + if (sscanf(optarg, "%f", &startTime) != 1) { + fprintf(stderr, + "%s: bad start time specified: %s\n", + ProgName, optarg); + } + break; + case 't': + if (sscanf(optarg, "%u", &trackId) != 1) { + fprintf(stderr, + "%s: bad track-id specified: %s\n", + ProgName, optarg); + exit(1); + } + break; + case 'v': + verbosity |= MP4_DETAILS_READ; + if (optarg) { + u_int32_t level; + if (sscanf(optarg, "%u", &level) == 1) { + if (level >= 2) { + verbosity |= MP4_DETAILS_TABLE; + } + if (level >= 3) { + verbosity |= MP4_DETAILS_SAMPLE; + } + if (level >= 4) { + verbosity = MP4_DETAILS_ALL; + } + } + } + break; + case '?': + fprintf(stderr, usageString, ProgName); + exit(0); + case 'V': + fprintf(stderr, "%s - %s version %s\n", + ProgName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); + exit(0); + default: + fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", + ProgName, c); + } + } + + /* check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, usageString, ProgName); + exit(1); + } + + if (verbosity) { + fprintf(stderr, "%s version %s\n", ProgName, MPEG4IP_VERSION); + } + + /* point to the specified file name */ + srcFileName = argv[optind++]; + + /* get dest file name */ + if ((argc - optind) > 0) { + dstFileName = argv[optind++]; + } + + /* warn about extraneous non-option arguments */ + if (optind < argc) { + fprintf(stderr, "%s: unknown options specified, ignoring: ", ProgName); + while (optind < argc) { + fprintf(stderr, "%s ", argv[optind++]); + } + fprintf(stderr, "\n"); + } + + if (duration == 0.0) { + fprintf(stderr, + "%s: please specify clip length with -l option\n", + ProgName); + } + + /* end processing of command line */ + + + MP4FileHandle srcFile = + MP4Modify(srcFileName, verbosity); + + if (!srcFile) { + exit(1); + } + + MP4FileHandle dstFile = + MP4_INVALID_FILE_HANDLE; + + if (dstFileName) { + dstFile = MP4Create(dstFileName, verbosity); + } + + if (trackId == MP4_INVALID_TRACK_ID) { + u_int32_t numTracks = MP4GetNumberOfTracks(srcFile); + + for (u_int32_t i = 0; i < numTracks; i++) { + trackId = MP4FindTrackId(srcFile, i); + ClipTrack(srcFile, trackId, dstFile, startTime, duration); + } + } else { + ClipTrack(srcFile, trackId, dstFile, startTime, duration); + } + + MP4Close(srcFile); + if (dstFile != MP4_INVALID_FILE_HANDLE) { + MP4Close(dstFile); + } + + return(0); +} + +void ClipTrack( + MP4FileHandle srcFile, + MP4TrackId trackId, + MP4FileHandle dstFile, + float startTime, + float duration) +{ + MP4Timestamp trackStartTime = + MP4ConvertToTrackTimestamp( + srcFile, + trackId, + (u_int64_t)(startTime * 1000), + MP4_MSECS_TIME_SCALE); + + MP4Duration trackDuration = + MP4ConvertToTrackDuration( + srcFile, + trackId, + (u_int64_t)(duration * 1000), + MP4_MSECS_TIME_SCALE); + + MP4EditId editId = + MP4AddTrackEdit( + srcFile, + trackId, + 1, + trackStartTime, + trackDuration); + + if (editId == MP4_INVALID_EDIT_ID) { + fprintf(stderr, + "%s: can't create track edit\n", + ProgName); + return; + } + + if (dstFile) { + MP4CopyTrack( + srcFile, + trackId, + dstFile, + true); + + MP4DeleteTrackEdit( + srcFile, + trackId, + editId); + } +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/nullcreate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/nullcreate.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,120 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4.h" +#if 0 +#include "mp4util.h" +#endif + +main(int argc, char** argv) +{ +#if 1 + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + + u_int32_t verbosity = MP4_DETAILS_ALL; + + MP4FileHandle mp4File = MP4Create(argv[1], verbosity); + + if (!mp4File) { + exit(1); + } + + printf("Created skeleton\n"); + MP4Dump(mp4File); + + MP4SetODProfileLevel(mp4File, 1); + MP4SetSceneProfileLevel(mp4File, 1); + MP4SetVideoProfileLevel(mp4File, 1); + MP4SetAudioProfileLevel(mp4File, 1); + MP4SetGraphicsProfileLevel(mp4File, 1); + + MP4TrackId odTrackId = + MP4AddODTrack(mp4File); + + MP4TrackId bifsTrackId = + MP4AddSceneTrack(mp4File); + + MP4TrackId videoTrackId = +#if 0 + MP4AddVideoTrack(mp4File, 90000, 3000, 320, 240); +#else + MP4AddH264VideoTrack(mp4File, 90000, 3000, 320, 240, + 1, 2, 3, 1); + static uint8_t pseq[] = { 0, 1, 2, 3, 4, 5, 6,7, 8, 9 }; + + MP4AddH264SequenceParameterSet(mp4File, videoTrackId, pseq, 10); + MP4AddH264SequenceParameterSet(mp4File, videoTrackId, pseq, 6); + MP4AddH264PictureParameterSet(mp4File, videoTrackId, pseq, 7); + MP4AddH264PictureParameterSet(mp4File, videoTrackId, pseq, 8); + MP4AddH264PictureParameterSet(mp4File, videoTrackId, pseq, 7); + +#endif + + MP4TrackId videoHintTrackId = + MP4AddHintTrack(mp4File, videoTrackId); + + MP4TrackId audioTrackId = + MP4AddAudioTrack(mp4File, 44100, 1152); + + MP4TrackId audioHintTrackId = + MP4AddHintTrack(mp4File, audioTrackId); + + printf("Added tracks\n"); + MP4Dump(mp4File); + + MP4Close(mp4File); + + // MP4MakeIsmaCompliant(argv[1], verbosity); + + exit(0); +#else + uint8_t *bin = NULL; + + for (uint32_t ix = 4; ix < 1024; ix++) { + printf("pass %d\n", ix); + bin = (uint8_t *)malloc(ix); + for (uint32_t jx = 0; jx < ix; jx++) { + bin[jx] = ((uint32_t)random()) >> 24; + } + char *test; + test = MP4ToBase64(bin, ix); + uint8_t *ret; + uint32_t retsize; + ret = Base64ToBinary(test, strlen(test), &retsize); + if (retsize != ix) { + printf("return size not same %d %d\n", ix, retsize); + exit(0); + } + if (memcmp(ret, bin, ix) != 0) { + printf("memory not same\n"); + exit(0); + } + free(test); + free(ret); + free(bin); + } + return 0; +#endif +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/nullvplayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/nullvplayer.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,114 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4.h" + +main(int argc, char** argv) +{ + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + + u_int32_t verbosity = MP4_DETAILS_ALL; + char* fileName = argv[1]; + + // open the mp4 file, and read meta-info + MP4FileHandle mp4File = MP4Read(fileName, verbosity); + + u_int8_t profileLevel = MP4GetVideoProfileLevel(mp4File); + + // get a handle on the first video track + MP4TrackId trackId = MP4FindTrackId(mp4File, 0, "video"); + + // gather the crucial track information + + u_int32_t timeScale = MP4GetTrackTimeScale(mp4File, trackId); + + // note all times and durations + // are in units of the track time scale + + MP4Duration trackDuration = MP4GetTrackDuration(mp4File, trackId); + + MP4SampleId numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId); + + u_int32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, trackId); + + u_int8_t* pConfig; + u_int32_t configSize = 0; + + MP4GetTrackESConfiguration(mp4File, trackId, &pConfig, &configSize); + + // initialize decoder with Elementary Stream (ES) configuration + + // done with our copy of ES configuration + free(pConfig); + + + // now consecutively read and display the track samples + + u_int8_t* pSample = (u_int8_t*)malloc(maxSampleSize); + u_int32_t sampleSize; + MP4Timestamp sampleTime; + MP4Duration sampleDuration; + MP4Duration sampleRenderingOffset; + bool isSyncSample; + + for (MP4SampleId sampleId = 1; sampleId <= numSamples; sampleId++) { + + // give ReadSample our own buffer, and let it know how big it is + sampleSize = maxSampleSize; + + // read next sample from video track + MP4ReadSample(mp4File, trackId, sampleId, + &pSample, &sampleSize, + &sampleTime, &sampleDuration, &sampleRenderingOffset, + &isSyncSample); + + // convert timestamp and duration from track time to milliseconds + u_int64_t myTime = MP4ConvertFromTrackTimestamp(mp4File, trackId, + sampleTime, MP4_MSECS_TIME_SCALE); + + u_int64_t myDuration = MP4ConvertFromTrackDuration(mp4File, trackId, + sampleDuration, MP4_MSECS_TIME_SCALE); + + // decode frame and display it + } + + // close mp4 file + MP4Close(mp4File); + + + // Note to seek to time 'when' in the track + // use MP4GetSampleIdFromTime(MP4FileHandle hFile, + // MP4Timestamp when, bool wantSyncSample) + // 'wantSyncSample' determines if a sync sample is desired or not + // e.g. + // MP4Timestamp when = + // MP4ConvertToTrackTimestamp(mp4File, trackId, 30, MP4_SECS_TIME_SCALE); + // MP4SampleId newSampleId = MP4GetSampleIdFromTime(mp4File, when, true); + // MP4ReadSample(mp4File, trackId, newSampleId, ...); + // + // Note that start time for sample may be later than 'when' + + exit(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/test/urltrack.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/test/urltrack.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,91 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4.h" + +main(int argc, char** argv) +{ + if (argc < 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(1); + } + + u_int32_t verbosity = 0 /* MP4_DETAILS_ALL */; + + MP4FileHandle mp4File = MP4Create(argv[1], verbosity); + + if (!mp4File) { + exit(1); + } + + MP4TrackId urlTrackId = +#if 0 + MP4AddTrack(mp4File, "URLF"); +#else + MP4AddHrefTrack(mp4File, 90000, MP4_INVALID_DURATION); +#endif + printf("urlTrackId %d\n", urlTrackId); + + u_int8_t i; + char url[128]; + + for (i = 1; i <= 5; i++) { + sprintf(url, "http://server.com/foo/bar%u.html", i); + + MP4WriteSample(mp4File, urlTrackId, + (u_int8_t*)url, strlen(url) + 1, (MP4Duration)i); + } + + MP4Close(mp4File); + + mp4File = MP4Read(argv[1], verbosity); + + // check that we can find the track again +#if 0 + urlTrackId = MP4FindTrackId(mp4File, 0, "URLF"); +#else + urlTrackId = MP4FindTrackId(mp4File, 0, MP4_CNTL_TRACK_TYPE); +#endif + printf("urlTrackId %d\n", urlTrackId); + + for (i = 1; i <= 5; i++) { + u_int8_t* pSample = NULL; + u_int32_t sampleSize = 0; + MP4Duration duration; + bool rc; + + rc = MP4ReadSample(mp4File, urlTrackId, i, + &pSample, &sampleSize, NULL, &duration); + + if (rc) { + printf("Sample %i duration "D64": %s\n", + i, duration, pSample); + free(pSample); + } else { + printf("Couldn't read sample %i\n", i); + } + } + + MP4Close(mp4File); + + exit(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/Makefile.am Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,38 @@ + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/lib/mp4v2 -I$(top_builddir)/lib/mp4av + +AM_CXXFLAGS = @BILLS_CPPWARNINGS@ + +bin_PROGRAMS = mp4dump mp4extract mp4info mp4trackdump mp4tags mp4art mp4videoinfo + +mp4dump_SOURCES = mp4dump.cpp +mp4dump_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4extract_SOURCES = mp4extract.cpp +mp4extract_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4info_SOURCES = mp4info.cpp +mp4info_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4trackdump_SOURCES = mp4trackdump.cpp +mp4trackdump_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4videoinfo_SOURCES = mp4videoinfo.cpp +mp4videoinfo_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/mp4av/libmp4av.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4tags_SOURCES = mp4tags.cpp +mp4tags_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4art_SOURCES = mp4art.cpp +mp4art_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +EXTRA_DIST = mp4dump60.dsp mp4extract60.dsp \ + mp4info.dsp diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/Makefile.in Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,619 @@ +# Makefile.in generated by automake 1.8.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +SOURCES = $(mp4art_SOURCES) $(mp4dump_SOURCES) $(mp4extract_SOURCES) $(mp4info_SOURCES) $(mp4tags_SOURCES) $(mp4trackdump_SOURCES) $(mp4videoinfo_SOURCES) + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +bin_PROGRAMS = mp4dump$(EXEEXT) mp4extract$(EXEEXT) mp4info$(EXEEXT) \ + mp4trackdump$(EXEEXT) mp4tags$(EXEEXT) mp4art$(EXEEXT) \ + mp4videoinfo$(EXEEXT) +subdir = lib/mp4v2/util +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(mkdir_p) +CONFIG_HEADER = $(top_builddir)/mpeg4ip_config.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_mp4art_OBJECTS = mp4art.$(OBJEXT) +mp4art_OBJECTS = $(am_mp4art_OBJECTS) +mp4art_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +am_mp4dump_OBJECTS = mp4dump.$(OBJEXT) +mp4dump_OBJECTS = $(am_mp4dump_OBJECTS) +mp4dump_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +am_mp4extract_OBJECTS = mp4extract.$(OBJEXT) +mp4extract_OBJECTS = $(am_mp4extract_OBJECTS) +mp4extract_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +am_mp4info_OBJECTS = mp4info.$(OBJEXT) +mp4info_OBJECTS = $(am_mp4info_OBJECTS) +mp4info_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +am_mp4tags_OBJECTS = mp4tags.$(OBJEXT) +mp4tags_OBJECTS = $(am_mp4tags_OBJECTS) +mp4tags_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +am_mp4trackdump_OBJECTS = mp4trackdump.$(OBJEXT) +mp4trackdump_OBJECTS = $(am_mp4trackdump_OBJECTS) +mp4trackdump_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +am_mp4videoinfo_OBJECTS = mp4videoinfo.$(OBJEXT) +mp4videoinfo_OBJECTS = $(am_mp4videoinfo_OBJECTS) +mp4videoinfo_DEPENDENCIES = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/mp4av/libmp4av.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/mp4art.Po ./$(DEPDIR)/mp4dump.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mp4extract.Po ./$(DEPDIR)/mp4info.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mp4tags.Po ./$(DEPDIR)/mp4trackdump.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mp4videoinfo.Po +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(mp4art_SOURCES) $(mp4dump_SOURCES) $(mp4extract_SOURCES) \ + $(mp4info_SOURCES) $(mp4tags_SOURCES) $(mp4trackdump_SOURCES) \ + $(mp4videoinfo_SOURCES) +DIST_SOURCES = $(mp4art_SOURCES) $(mp4dump_SOURCES) \ + $(mp4extract_SOURCES) $(mp4info_SOURCES) $(mp4tags_SOURCES) \ + $(mp4trackdump_SOURCES) $(mp4videoinfo_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +AESICM_INC = @AESICM_INC@ +ALIGN_FUNCS = @ALIGN_FUNCS@ +ALIGN_JUMPS = @ALIGN_JUMPS@ +ALIGN_LOOPS = @ALIGN_LOOPS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BILLS_CPPWARNINGS = @BILLS_CPPWARNINGS@ +BILLS_CWARNINGS = @BILLS_CWARNINGS@ +CC = @CC@ +CCAS = @CCAS@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FAAC_LIB = @FAAC_LIB@ +FFLAGS = @FFLAGS@ +FFMPEG_INC = @FFMPEG_INC@ +FFMPEG_LIB = @FFMPEG_LIB@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVE_A52DEC_LIB_FALSE = @HAVE_A52DEC_LIB_FALSE@ +HAVE_A52DEC_LIB_TRUE = @HAVE_A52DEC_LIB_TRUE@ +HAVE_ALIGN_FUNCS_FALSE = @HAVE_ALIGN_FUNCS_FALSE@ +HAVE_ALIGN_FUNCS_TRUE = @HAVE_ALIGN_FUNCS_TRUE@ +HAVE_ALIGN_JUMPS_FALSE = @HAVE_ALIGN_JUMPS_FALSE@ +HAVE_ALIGN_JUMPS_TRUE = @HAVE_ALIGN_JUMPS_TRUE@ +HAVE_ALIGN_LOOPS_FALSE = @HAVE_ALIGN_LOOPS_FALSE@ +HAVE_ALIGN_LOOPS_TRUE = @HAVE_ALIGN_LOOPS_TRUE@ +HAVE_FFMPEG_FALSE = @HAVE_FFMPEG_FALSE@ +HAVE_FFMPEG_TRUE = @HAVE_FFMPEG_TRUE@ +HAVE_ID3_TAG_FALSE = @HAVE_ID3_TAG_FALSE@ +HAVE_ID3_TAG_TRUE = @HAVE_ID3_TAG_TRUE@ +HAVE_LIBMAD_FALSE = @HAVE_LIBMAD_FALSE@ +HAVE_LIBMAD_TRUE = @HAVE_LIBMAD_TRUE@ +HAVE_LIBMPEG2_FALSE = @HAVE_LIBMPEG2_FALSE@ +HAVE_LIBMPEG2_TRUE = @HAVE_LIBMPEG2_TRUE@ +HAVE_MAC_OSX_FALSE = @HAVE_MAC_OSX_FALSE@ +HAVE_MAC_OSX_TRUE = @HAVE_MAC_OSX_TRUE@ +HAVE_V4L2_FALSE = @HAVE_V4L2_FALSE@ +HAVE_V4L2_TRUE = @HAVE_V4L2_TRUE@ +HAVE_X264_FALSE = @HAVE_X264_FALSE@ +HAVE_X264_TRUE = @HAVE_X264_TRUE@ +HAVE_XVID_1_0_FALSE = @HAVE_XVID_1_0_FALSE@ +HAVE_XVID_1_0_TRUE = @HAVE_XVID_1_0_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +ISMACRYP_FLAGS = @ISMACRYP_FLAGS@ +ISMACRYP_INC = @ISMACRYP_INC@ +ISMACRYP_LIB = @ISMACRYP_LIB@ +LAME_LIB = @LAME_LIB@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBTOOL_C_TAG = @LIBTOOL_C_TAG@ +LIBVORBIS_LIB = @LIBVORBIS_LIB@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MP4LIVE_FALSE = @MP4LIVE_FALSE@ +MP4LIVE_TRUE = @MP4LIVE_TRUE@ +NASM = @NASM@ +NASMFLAGS = @NASMFLAGS@ +NO_GLIB_GTK_FALSE = @NO_GLIB_GTK_FALSE@ +NO_GLIB_GTK_TRUE = @NO_GLIB_GTK_TRUE@ +NO_XVID_FALSE = @NO_XVID_FALSE@ +NO_XVID_TRUE = @NO_XVID_TRUE@ +OBJC = @OBJC@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PLAYER_FALSE = @PLAYER_FALSE@ +PLAYER_PLUGIN_DIR = @PLAYER_PLUGIN_DIR@ +PLAYER_TRUE = @PLAYER_TRUE@ +RANLIB = @RANLIB@ +SDL_LIBS = @SDL_LIBS@ +SDL_LIB_LIBS = @SDL_LIB_LIBS@ +SERVER_FALSE = @SERVER_FALSE@ +SERVER_TRUE = @SERVER_TRUE@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SUN_LIBS = @SUN_LIBS@ +USENASM = @USENASM@ +USE_MMX_FALSE = @USE_MMX_FALSE@ +USE_MMX_TRUE = @USE_MMX_TRUE@ +USE_PPC_FALSE = @USE_PPC_FALSE@ +USE_PPC_TRUE = @USE_PPC_TRUE@ +VERSION = @VERSION@ +X264_LIB = @X264_LIB@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/lib/mp4v2 -I$(top_builddir)/lib/mp4av +AM_CXXFLAGS = @BILLS_CPPWARNINGS@ +mp4dump_SOURCES = mp4dump.cpp +mp4dump_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4extract_SOURCES = mp4extract.cpp +mp4extract_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4info_SOURCES = mp4info.cpp +mp4info_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4trackdump_SOURCES = mp4trackdump.cpp +mp4trackdump_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4videoinfo_SOURCES = mp4videoinfo.cpp +mp4videoinfo_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/mp4av/libmp4av.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4tags_SOURCES = mp4tags.cpp +mp4tags_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +mp4art_SOURCES = mp4art.cpp +mp4art_LDADD = $(top_builddir)/lib/mp4v2/libmp4v2.la \ + $(top_builddir)/lib/gnu/libmpeg4ip_gnu.la + +EXTRA_DIST = mp4dump60.dsp mp4extract60.dsp \ + mp4info.dsp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/mp4v2/util/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/mp4v2/util/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +mp4art$(EXEEXT): $(mp4art_OBJECTS) $(mp4art_DEPENDENCIES) + @rm -f mp4art$(EXEEXT) + $(CXXLINK) $(mp4art_LDFLAGS) $(mp4art_OBJECTS) $(mp4art_LDADD) $(LIBS) +mp4dump$(EXEEXT): $(mp4dump_OBJECTS) $(mp4dump_DEPENDENCIES) + @rm -f mp4dump$(EXEEXT) + $(CXXLINK) $(mp4dump_LDFLAGS) $(mp4dump_OBJECTS) $(mp4dump_LDADD) $(LIBS) +mp4extract$(EXEEXT): $(mp4extract_OBJECTS) $(mp4extract_DEPENDENCIES) + @rm -f mp4extract$(EXEEXT) + $(CXXLINK) $(mp4extract_LDFLAGS) $(mp4extract_OBJECTS) $(mp4extract_LDADD) $(LIBS) +mp4info$(EXEEXT): $(mp4info_OBJECTS) $(mp4info_DEPENDENCIES) + @rm -f mp4info$(EXEEXT) + $(CXXLINK) $(mp4info_LDFLAGS) $(mp4info_OBJECTS) $(mp4info_LDADD) $(LIBS) +mp4tags$(EXEEXT): $(mp4tags_OBJECTS) $(mp4tags_DEPENDENCIES) + @rm -f mp4tags$(EXEEXT) + $(CXXLINK) $(mp4tags_LDFLAGS) $(mp4tags_OBJECTS) $(mp4tags_LDADD) $(LIBS) +mp4trackdump$(EXEEXT): $(mp4trackdump_OBJECTS) $(mp4trackdump_DEPENDENCIES) + @rm -f mp4trackdump$(EXEEXT) + $(CXXLINK) $(mp4trackdump_LDFLAGS) $(mp4trackdump_OBJECTS) $(mp4trackdump_LDADD) $(LIBS) +mp4videoinfo$(EXEEXT): $(mp4videoinfo_OBJECTS) $(mp4videoinfo_DEPENDENCIES) + @rm -f mp4videoinfo$(EXEEXT) + $(CXXLINK) $(mp4videoinfo_LDFLAGS) $(mp4videoinfo_OBJECTS) $(mp4videoinfo_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4art.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4dump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4extract.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4info.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4tags.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4trackdump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mp4videoinfo.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4art.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4art.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,121 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2004. All Rights Reserved. + * + * Contributor(s): + * Bill May wmay@cisco.com (from mp4info.cpp) + */ + +#include "mp4.h" +#include "mpeg4ip_getopt.h" + +static void strip_filename (const char *name, char *buffer) +{ + const char *suffix, *slash; + if (name != NULL) { + suffix = strrchr(name, '.'); + slash = strrchr(name, '/'); + if (slash == NULL) slash = name; + else slash++; + if (suffix == NULL) + suffix = slash + strlen(slash); + memcpy(buffer, slash, suffix - slash); + buffer[suffix - slash] = '\0'; + } else { + strcpy(buffer, "out"); + } +} + +int main(int argc, char** argv) +{ + const char* usageString = + "\n"; + + /* begin processing command line */ + char* ProgName = argv[0]; + while (true) { + int c = -1; + int option_index = 0; + static struct option long_options[] = { + { "version", 0, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "V", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case '?': + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(0); + case 'V': + fprintf(stderr, "%s - %s version %s\n", ProgName, + MPEG4IP_PACKAGE, MPEG4IP_VERSION); + exit(0); + default: + fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", + ProgName, c); + } + } + + /* check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(1); + } + + /* end processing of command line */ + printf("%s version %s\n", ProgName, MPEG4IP_VERSION); + + while (optind < argc) { + char *mp4FileName = argv[optind++]; + MP4FileHandle mp4file = MP4Read(mp4FileName); + if (mp4file != MP4_INVALID_FILE_HANDLE) { + uint8_t *art; + uint32_t art_size; + + if (MP4GetMetadataCoverArt(mp4file, &art, &art_size)) { + char filename[MAXPATHLEN]; + strip_filename(mp4FileName, filename); + strcat(filename, ".png"); + struct stat fstat; + if (stat(filename, &fstat) == 0) { + fprintf(stderr, "file %s already exists\n", filename); + } else { + FILE *ofile = fopen(filename, FOPEN_WRITE_BINARY); + if (ofile != NULL) { + fwrite(art, art_size, 1, ofile); + fclose(ofile); + printf("created file %s\n", filename); + } else { + fprintf(stderr, "couldn't create file %s\n", filename); + } + } + + free(art); + } else { + fprintf(stderr, "art not available for %s\n", mp4FileName); + } + MP4Close(mp4file); + } + } + + return(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4dump.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4dump.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,111 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4.h" +#include "mpeg4ip_getopt.h" + +int main(int argc, char** argv) +{ + char* usageString = "[-verbose=[]] \n"; + u_int32_t verbosity = MP4_DETAILS_ERROR; + bool dumpImplicits = false; + + /* begin processing command line */ + char* progName = argv[0]; + while (true) { + int c = -1; + int option_index = 0; + static struct option long_options[] = { + { "verbose", 2, 0, 'v' }, + { "version", 0, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "v::V", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 'v': + verbosity |= MP4_DETAILS_TABLE; + if (optarg) { + u_int32_t level; + if (sscanf(optarg, "%u", &level) == 1) { + if (level >= 2) { + dumpImplicits = true; + } + if (level >= 3) { + verbosity = MP4_DETAILS_ALL; + } + } + } + break; + case '?': + fprintf(stderr, "usage: %s %s", progName, usageString); + exit(0); + case 'V': + fprintf(stderr, "%s - %s version %s\n", + progName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); + exit(0); + default: + fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", + progName, c); + } + } + + /* check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, "usage: %s %s\n", progName, usageString); + exit(1); + } + + /* point to the specified file names */ + char* mp4FileName = argv[optind++]; + + /* warn about extraneous non-option arguments */ + if (optind < argc) { + fprintf(stderr, "%s: unknown options specified, ignoring: ", progName); + while (optind < argc) { + fprintf(stderr, "%s ", argv[optind++]); + } + fprintf(stderr, "\n"); + } + + /* end processing of command line */ + if (verbosity != 0) { + fprintf(stdout, "%s version %s\n", progName, MPEG4IP_VERSION); + } + + MP4FileHandle mp4File = MP4Read(mp4FileName, verbosity); + + if (!mp4File) { + exit(1); + } + + MP4Dump(mp4File, stdout, dumpImplicits); + + MP4Close(mp4File); + + return(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4dump60.dsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4dump60.dsp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="mp4dump" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mp4dump - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mp4dump60.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mp4dump60.mak" CFG="mp4dump - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mp4dump - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mp4dump - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mp4dump - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/mp4dump.exe" + +!ELSEIF "$(CFG)" == "mp4dump - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/mp4dump.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mp4dump - Win32 Release" +# Name "mp4dump - Win32 Debug" +# Begin Source File + +SOURCE=.\mp4dump.cpp +# End Source File +# End Target +# End Project diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4extract.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4extract.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,271 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +// N.B. mp4extract just extracts tracks/samples from an mp4 file +// For many track types this is insufficient to reconsruct a valid +// elementary stream (ES). Use "mp4creator -extract=" if +// you need the ES reconstructed. + +#include "mp4.h" +#include "mpeg4ip_getopt.h" + +char* ProgName; +char* Mp4PathName; +char* Mp4FileName; + +// forward declaration +void ExtractTrack(MP4FileHandle mp4File, MP4TrackId trackId, + bool sampleMode, MP4SampleId sampleId, char* dstFileName = NULL); + +int main(int argc, char** argv) +{ + const char* usageString = + "[-l] [-t ] [-s ] [-v []] \n"; + bool doList = false; + bool doSamples = false; + MP4TrackId trackId = MP4_INVALID_TRACK_ID; + MP4SampleId sampleId = MP4_INVALID_SAMPLE_ID; + char* dstFileName = NULL; + u_int32_t verbosity = MP4_DETAILS_ERROR; + +fprintf(stderr, "You don't want to use this utility - use mp4creator --extract instead\n"); +fprintf(stderr, "If you really want to use it, remove this warning and the exit call\n"); +fprintf(stderr, "from the source file\n"); + exit(-1); + /* begin processing command line */ + ProgName = argv[0]; + while (true) { + int c = -1; + int option_index = 0; + static struct option long_options[] = { + { "list", 0, 0, 'l' }, + { "track", 1, 0, 't' }, + { "sample", 2, 0, 's' }, + { "verbose", 2, 0, 'v' }, + { "version", 0, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "lt:s::v::V", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 'l': + doList = true; + break; + case 's': + doSamples = true; + if (optarg) { + if (sscanf(optarg, "%u", &sampleId) != 1) { + fprintf(stderr, + "%s: bad sample-id specified: %s\n", + ProgName, optarg); + } + } + break; + case 't': + if (sscanf(optarg, "%u", &trackId) != 1) { + fprintf(stderr, + "%s: bad track-id specified: %s\n", + ProgName, optarg); + exit(1); + } + break; + case 'v': + verbosity |= MP4_DETAILS_READ; + if (optarg) { + u_int32_t level; + if (sscanf(optarg, "%u", &level) == 1) { + if (level >= 2) { + verbosity |= MP4_DETAILS_TABLE; + } + if (level >= 3) { + verbosity |= MP4_DETAILS_SAMPLE; + } + if (level >= 4) { + verbosity = MP4_DETAILS_ALL; + } + } + } + break; + case '?': + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(0); + case 'V': + fprintf(stderr, "%s - %s version %s\n", + ProgName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); + exit(0); + default: + fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", + ProgName, c); + } + } + + /* check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(1); + } + + if (verbosity) { + fprintf(stderr, "%s version %s\n", ProgName, MPEG4IP_VERSION); + } + + /* point to the specified file names */ + Mp4PathName = argv[optind++]; + + /* get dest file name for a single track */ + if (trackId && (argc - optind) > 0) { + dstFileName = argv[optind++]; + } + + char* lastSlash = strrchr(Mp4PathName, '/'); + if (lastSlash) { + Mp4FileName = lastSlash + 1; + } else { + Mp4FileName = Mp4PathName; + } + + /* warn about extraneous non-option arguments */ + if (optind < argc) { + fprintf(stderr, "%s: unknown options specified, ignoring: ", ProgName); + while (optind < argc) { + fprintf(stderr, "%s ", argv[optind++]); + } + fprintf(stderr, "\n"); + } + + /* end processing of command line */ + + + MP4FileHandle mp4File = MP4Read(Mp4PathName, verbosity); + + if (!mp4File) { + exit(1); + } + + if (doList) { + MP4Info(mp4File); + exit(0); + } + + if (trackId == 0) { + u_int32_t numTracks = MP4GetNumberOfTracks(mp4File); + + for (u_int32_t i = 0; i < numTracks; i++) { + trackId = MP4FindTrackId(mp4File, i); + ExtractTrack(mp4File, trackId, doSamples, sampleId); + } + } else { + ExtractTrack(mp4File, trackId, doSamples, sampleId, dstFileName); + } + + MP4Close(mp4File); + + return(0); +} + +void ExtractTrack(MP4FileHandle mp4File, MP4TrackId trackId, + bool sampleMode, MP4SampleId sampleId, char* dstFileName) +{ + char outFileName[PATH_MAX]; + int outFd = -1; + int openFlags = O_WRONLY | O_TRUNC | OPEN_CREAT; + + if (!sampleMode) { + if (dstFileName == NULL) { + snprintf(outFileName, sizeof(outFileName), + "%s.t%u", Mp4FileName, trackId); + } else { + snprintf(outFileName, sizeof(outFileName), + "%s", dstFileName); + } + + outFd = open(outFileName, openFlags, 0644); + if (outFd == -1) { + fprintf(stderr, "%s: can't open %s: %s\n", + ProgName, outFileName, strerror(errno)); + return; + } + } + + MP4SampleId numSamples; + + if (sampleMode && sampleId != MP4_INVALID_SAMPLE_ID) { + numSamples = sampleId; + } else { + sampleId = 1; + numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId); + } + + u_int8_t* pSample; + u_int32_t sampleSize; + + for ( ; sampleId <= numSamples; sampleId++) { + int rc; + + // signals to ReadSample() that it should malloc a buffer for us + pSample = NULL; + sampleSize = 0; + + rc = MP4ReadSample(mp4File, trackId, sampleId, &pSample, &sampleSize); + if (rc == 0) { + fprintf(stderr, "%s: read sample %u for %s failed\n", + ProgName, sampleId, outFileName); + break; + } + + if (sampleMode) { + snprintf(outFileName, sizeof(outFileName), "%s.t%u.s%u", + Mp4FileName, trackId, sampleId); + + outFd = open(outFileName, openFlags, 0644); + + if (outFd == -1) { + fprintf(stderr, "%s: can't open %s: %s\n", + ProgName, outFileName, strerror(errno)); + break; + } + } + + rc = write(outFd, pSample, sampleSize); + if (rc == -1 || (u_int32_t)rc != sampleSize) { + fprintf(stderr, "%s: write to %s failed: %s\n", + ProgName, outFileName, strerror(errno)); + break; + } + + free(pSample); + + if (sampleMode) { + close(outFd); + outFd = -1; + } + } + + if (outFd != -1) { + close(outFd); + } +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4extract60.dsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4extract60.dsp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="mp4extract" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mp4extract - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mp4extract60.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mp4extract60.mak" CFG="mp4extract - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mp4extract - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mp4extract - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mp4extract - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "mp4extra" +# PROP BASE Intermediate_Dir "mp4extra" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"Release/mp4extract.exe" + +!ELSEIF "$(CFG)" == "mp4extract - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "mp4extr0" +# PROP BASE Intermediate_Dir "mp4extr0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/mp4extract.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mp4extract - Win32 Release" +# Name "mp4extract - Win32 Debug" +# Begin Source File + +SOURCE=.\mp4extract.cpp +# End Source File +# End Target +# End Project diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4info.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4info.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,143 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001-2002. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +#include "mp4.h" +#include "mpeg4ip_getopt.h" + + +int main(int argc, char** argv) +{ + const char* usageString = + "\n"; + + /* begin processing command line */ + char* ProgName = argv[0]; + while (true) { + int c = -1; + int option_index = 0; + static struct option long_options[] = { + { "version", 0, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "V", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case '?': + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(0); + case 'V': + fprintf(stderr, "%s - %s version %s\n", ProgName, + MPEG4IP_PACKAGE, MPEG4IP_VERSION); + exit(0); + default: + fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", + ProgName, c); + } + } + + /* check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(1); + } + + /* end processing of command line */ + printf("%s version %s\n", ProgName, MPEG4IP_VERSION); + + while (optind < argc) { + char *mp4FileName = argv[optind++]; + + printf("%s:\n", mp4FileName); + + char* info = MP4FileInfo(mp4FileName); + + if (!info) { + fprintf(stderr, + "%s: can't open %s\n", + ProgName, mp4FileName); + continue; + } + + fputs(info, stdout); + MP4FileHandle mp4file = MP4Read(mp4FileName); + if (mp4file != MP4_INVALID_FILE_HANDLE) { + char *value; + uint16_t numvalue, numvalue2; + if (MP4GetMetadataName(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Name: %s\n", value); + free(value); + } + if (MP4GetMetadataArtist(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Artist: %s\n", value); + free(value); + } + if (MP4GetMetadataWriter(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Writer: %s\n", value); + free(value); + } + if (MP4GetMetadataComment(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Comment: %s\n", value); + free(value); + } + if (MP4GetMetadataTool(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Tool: %s\n", value); + free(value); + } + if (MP4GetMetadataYear(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Year: %s\n", value); + free(value); + } + if (MP4GetMetadataAlbum(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Album: %s\n", value); + free(value); + } + if (MP4GetMetadataTrack(mp4file, &numvalue, &numvalue2)) { + fprintf(stdout, " Metadata track: %u of %u\n", numvalue, + numvalue2); + } + if (MP4GetMetadataDisk(mp4file, &numvalue, &numvalue2)) { + fprintf(stdout, " Metadata Disk: %u of %u\n", numvalue, + numvalue2); + } + if (MP4GetMetadataGenre(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Genre: %s\n", value); + free(value); + } + if (MP4GetMetadataGrouping(mp4file, &value) && value != NULL) { + fprintf(stdout, " Metadata Grouping: %s\n", value); + free(value); + } + if (MP4GetMetadataTempo(mp4file, &numvalue)) { + fprintf(stdout, " Metadata Tempo: %u\n", numvalue); + } + MP4Close(mp4file); + } + free(info); + } + + return(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4info.dsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4info.dsp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="mp4info" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=mp4info - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "mp4info.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mp4info.mak" CFG="mp4info - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mp4info - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "mp4info - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "mp4info - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "mp4info___Win32_Release" +# PROP BASE Intermediate_Dir "mp4info___Win32_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".." /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "mp4info - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "mp4info___Win32_Debug" +# PROP BASE Intermediate_Dir "mp4info___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "mp4info - Win32 Release" +# Name "mp4info - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\mp4info.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4tags.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4tags.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,235 @@ +/* mp4tags -- tool to set iTunes-compatible metadata tags + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Contributed to MPEG4IP + * by Christopher League + */ + +#include "mp4.h" +#include "mpeg4ip_getopt.h" + +/* One-letter options -- if you want to rearrange these, change them + here, immediately below in OPT_STRING, and in the help text. */ +#define OPT_HELP 'h' +#define OPT_VERSION 'v' +#define OPT_ALBUM 'A' +#define OPT_ARTIST 'a' +#define OPT_TEMPO 'b' +#define OPT_COMMENT 'c' +#define OPT_DISK 'd' +#define OPT_DISKS 'D' +#define OPT_GENRE 'g' +#define OPT_GROUPING 'G' +#define OPT_SONG 's' +#define OPT_TRACK 't' +#define OPT_TRACKS 'T' +#define OPT_WRITER 'w' /* _composer_ */ +#define OPT_YEAR 'y' +#define OPT_REMOVE 'r' + +#define OPT_STRING "hvA:a:b:c:d:D:g:G:s:t:T:w:y:r:" + +static const char* help_text = +"OPTION... FILE...\n" +"Adds or modifies iTunes-compatible tags on MP4 files.\n" +"\n" +" -h, -help Display this help text and exit\n" +" -v, -version Display version information and exit\n" +" -A, -album STR Set the album title\n" +" -a, -artist STR Set the artist information\n" +" -b, -tempo NUM Set the tempo (beats per minute)\n" +" -c, -comment STR Set a general comment\n" +" -d, -disk NUM Set the disk number\n" +" -D, -disks NUM Set the number of disks\n" +" -g, -genre STR Set the genre name\n" +" -G, -grouping STR Set the grouping name\n" +" -s, -song STR Set the song title\n" +" -t, -track NUM Set the track number\n" +" -T, -tracks NUM Set the number of tracks\n" +" -w, -writer STR Set the composer information\n" +" -y, -year NUM Set the year\n" +" -r, -remove STR Remove tags by code (e.g. \"-r cs\"\n" +" removes the comment and song tags)\n" +"\n"; + + +int +main(int argc, char** argv) +{ + static struct option long_options[] = { + { "help", 0, 0, OPT_HELP }, + { "version", 0, 0, OPT_VERSION }, + { "album", 1, 0, OPT_ALBUM }, + { "artist", 1, 0, OPT_ARTIST }, + { "comment", 1, 0, OPT_COMMENT }, + { "disk", 1, 0, OPT_DISK }, + { "disks", 1, 0, OPT_DISKS }, + { "genre", 1, 0, OPT_GENRE }, + { "grouping",1, 0, OPT_GROUPING}, + { "song", 1, 0, OPT_SONG }, + { "tempo", 1, 0, OPT_TEMPO }, + { "track", 1, 0, OPT_TRACK }, + { "tracks", 1, 0, OPT_TRACKS }, + { "writer", 1, 0, OPT_WRITER }, + { "year", 1, 0, OPT_YEAR }, + { "remove", 1, 0, OPT_REMOVE }, + { NULL, 0, 0, 0 } + }; + + /* Sparse arrays of tag data: some space is wasted, but it's more + convenient to say tags[OPT_SONG] than to enumerate all the + metadata types (again) as a struct. */ + char *tags[UCHAR_MAX]; + int nums[UCHAR_MAX]; + + memset(tags, 0, sizeof(tags)); + memset(nums, 0, sizeof(nums)); + + /* Any modifications requested? */ + int mods = 0; + + /* Option-processing loop. */ + int c = getopt_long_only(argc, argv, OPT_STRING, long_options, NULL); + while (c != -1) { + int r = 2; + switch(c) { + /* getopt() returns '?' if there was an error. It already + printed the error message, so just return. */ + case '?': + return 1; + + /* Help and version requests handled here. */ + case OPT_HELP: + fprintf(stderr, "usage %s %s", argv[0], help_text); + return 0; + case OPT_VERSION: + fprintf(stderr, "%s - %s version %s\n", argv[0], MPEG4IP_PACKAGE, + MPEG4IP_VERSION); + return 0; + + /* Numeric arguments: convert them using sscanf(). */ + case OPT_DISK: case OPT_DISKS: + case OPT_TRACK: case OPT_TRACKS: + case OPT_TEMPO: + r = sscanf(optarg, "%d", &nums[c]); + if (r < 1) { + fprintf(stderr, "%s: option requires numeric argument -- %c\n", + argv[0], c); + return 2; + } + /* Break not, lest ye be broken. :) */ + /* All arguments: all valid options end up here, and we just + stuff the string pointer into the tags[] array. */ + default: + tags[c] = optarg; + mods++; + } /* end switch */ + + c = getopt_long_only(argc, argv, OPT_STRING, long_options, NULL); + } /* end while */ + + /* Check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, + "%s: You must specify at least one MP4 file.\n", + argv[0]); + fprintf(stderr, "usage %s %s", argv[0], help_text); + return 3; + } + + /* Check that we have at least one requested modification. Probably + it's useful instead to print the metadata if no modifications are + requested? */ + if (!mods) { + fprintf(stderr, + "%s: You must specify at least one tag modification.\n", + argv[0]); + fprintf(stderr, "usage %s %s", argv[0], help_text); + return 4; + } + + /* Loop through the non-option arguments, and modify the tags as + requested. */ + while (optind < argc) { + char *mp4 = argv[optind++]; + + MP4FileHandle h = MP4Modify(mp4); + if (h == MP4_INVALID_FILE_HANDLE) { + fprintf(stderr, "Could not open '%s'... aborting\n", mp4); + return 5; + } + + /* Remove any tags */ + if( tags[OPT_REMOVE] ) { + for(const char *p = tags[OPT_REMOVE]; *p; p++ ) { + switch(*p) { + case OPT_ALBUM: MP4DeleteMetadataAlbum(h); break; + case OPT_ARTIST: MP4DeleteMetadataArtist(h); break; + case OPT_COMMENT: MP4DeleteMetadataComment(h); break; + case OPT_DISK: MP4DeleteMetadataDisk(h); break; + case OPT_DISKS: MP4DeleteMetadataDisk(h); break; + case OPT_GENRE: MP4DeleteMetadataGenre(h); break; + case OPT_GROUPING:MP4DeleteMetadataGrouping(h); break; + case OPT_SONG: MP4DeleteMetadataName(h); break; + case OPT_WRITER: MP4DeleteMetadataWriter(h); break; + case OPT_YEAR: MP4DeleteMetadataYear(h); break; + case OPT_TEMPO: MP4DeleteMetadataTempo(h); break; + case OPT_TRACK: MP4DeleteMetadataTrack(h); break; + case OPT_TRACKS: MP4DeleteMetadataTrack(h); break; + } + } + } + + /* Track/disk numbers need to be set all at once, but we'd like to + allow users to just specify -T 12 to indicate that all existing + track numbers are out of 12. This means we need to look up the + current info if it is not being set. */ + uint16_t n0, m0, n1, m1; + + if (tags[OPT_TRACK] || tags[OPT_TRACKS]) { + n0 = m0 = 0; + MP4GetMetadataTrack(h, &n0, &m0); + n1 = tags[OPT_TRACK]? nums[OPT_TRACK] : n0; + m1 = tags[OPT_TRACKS]? nums[OPT_TRACKS] : m0; + MP4SetMetadataTrack(h, n1, m1); + } + if (tags[OPT_DISK] || tags[OPT_DISKS]) { + n0 = m0 = 0; + MP4GetMetadataDisk(h, &n0, &m0); + n1 = tags[OPT_DISK]? nums[OPT_DISK] : n0; + m1 = tags[OPT_DISKS]? nums[OPT_DISKS] : m0; + MP4SetMetadataDisk(h, n1, m1); + } + + /* Set the other relevant attributes */ + for (int i = 0; i < UCHAR_MAX; i++) { + if (tags[i]) { + switch(i) { + case OPT_ALBUM: MP4SetMetadataAlbum(h, tags[i]); break; + case OPT_ARTIST: MP4SetMetadataArtist(h, tags[i]); break; + case OPT_COMMENT: MP4SetMetadataComment(h, tags[i]); break; + case OPT_GENRE: MP4SetMetadataGenre(h, tags[i]); break; + case OPT_GROUPING:MP4SetMetadataGrouping(h, tags[i]); break; + case OPT_SONG: MP4SetMetadataName(h, tags[i]); break; + case OPT_WRITER: MP4SetMetadataWriter(h, tags[i]); break; + case OPT_YEAR: MP4SetMetadataYear(h, tags[i]); break; + case OPT_TEMPO: MP4SetMetadataTempo(h, nums[i]); break; + } + } + } + + MP4Close(h); + } /* end while optind < argc */ + + return 0; +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4trackdump.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4trackdump.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,237 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +// N.B. mp4extract just extracts tracks/samples from an mp4 file +// For many track types this is insufficient to reconsruct a valid +// elementary stream (ES). Use "mp4creator -extract=" if +// you need the ES reconstructed. + +#include "mp4.h" +#include "mpeg4ip_getopt.h" + +char* ProgName; +char* Mp4PathName; +char* Mp4FileName; +static void DumpTrack (MP4FileHandle mp4file, MP4TrackId tid) +{ + uint32_t numSamples; + MP4SampleId sid; + MP4Duration time; + uint32_t timescale; + uint64_t msectime; + + uint64_t sectime, mintime, hrtime; + + numSamples = MP4GetTrackNumberOfSamples(mp4file, tid); + timescale = MP4GetTrackTimeScale(mp4file, tid); + printf("mp4file %s, track %d, samples %d, timescale %d\n", + Mp4FileName, tid, numSamples, timescale); + + for (sid = 1; sid <= numSamples; sid++) { + time = MP4GetSampleTime(mp4file, tid, sid); + msectime = time; + msectime *= TO_U64(1000); + msectime /= timescale; + if (msectime == 0) { + hrtime = mintime = sectime = TO_U64(0); + } else { + hrtime = msectime / TO_U64(3600 * 1000); + msectime -= hrtime * TO_U64(3600 * 1000); + mintime = msectime / TO_U64(60 * 1000); + msectime -= (mintime * TO_U64(60 * 1000)); + sectime = msectime / TO_U64(1000); + msectime -= sectime * TO_U64(1000); + } + + printf("sampleId %6d, size %5u duration %8"U64F" time %8"U64F" %02"U64F":%02"U64F":%02"U64F".%03"U64F" %c\n", + sid, MP4GetSampleSize(mp4file, tid, sid), + MP4GetSampleDuration(mp4file, tid, sid), + time, hrtime, mintime, sectime, msectime, + MP4GetSampleSync(mp4file, tid, sid) == 1 ? 'S' : ' '); + } +} + +int main(int argc, char** argv) +{ + const char* usageString = + "[-l] [-t ] [-s ] [-v []] \n"; + MP4TrackId trackId = MP4_INVALID_TRACK_ID; + MP4SampleId sampleId = MP4_INVALID_SAMPLE_ID; + u_int32_t verbosity = MP4_DETAILS_ERROR; + + /* begin processing command line */ + ProgName = argv[0]; + while (true) { + int c = -1; + int option_index = 0; + static struct option long_options[] = { + { "track", 1, 0, 't' }, + { "sample", 1, 0, 's' }, + { "verbose", 2, 0, 'v' }, + { "version", 0, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "t:v::V", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 's': + if (sscanf(optarg, "%u", &sampleId) != 1) { + fprintf(stderr, "%s: bad sample-id specified: %s\n", + ProgName, optarg); + exit(1); + } + break; + case 't': + if (sscanf(optarg, "%u", &trackId) != 1) { + fprintf(stderr, + "%s: bad track-id specified: %s\n", + ProgName, optarg); + exit(1); + } + break; + case 'v': + verbosity |= MP4_DETAILS_READ; + if (optarg) { + u_int32_t level; + if (sscanf(optarg, "%u", &level) == 1) { + if (level >= 2) { + verbosity |= MP4_DETAILS_TABLE; + } + if (level >= 3) { + verbosity |= MP4_DETAILS_SAMPLE; + } + if (level >= 4) { + verbosity = MP4_DETAILS_ALL; + } + } + } + break; + case '?': + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(0); + case 'V': + fprintf(stderr, "%s - %s version %s\n", + ProgName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); + exit(0); + default: + fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", + ProgName, c); + } + } + + /* check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(1); + } + + if (verbosity) { + fprintf(stderr, "%s version %s\n", ProgName, MPEG4IP_VERSION); + } + + /* point to the specified file names */ + Mp4PathName = argv[optind++]; + + char* lastSlash = strrchr(Mp4PathName, '/'); + if (lastSlash) { + Mp4FileName = lastSlash + 1; + } else { + Mp4FileName = Mp4PathName; + } + + /* warn about extraneous non-option arguments */ + if (optind < argc) { + fprintf(stderr, "%s: unknown options specified, ignoring: ", ProgName); + while (optind < argc) { + fprintf(stderr, "%s ", argv[optind++]); + } + fprintf(stderr, "\n"); + } + + /* end processing of command line */ + + + MP4FileHandle mp4File = MP4Read(Mp4PathName, verbosity); + + if (!mp4File) { + exit(1); + } + + if (sampleId != MP4_INVALID_SAMPLE_ID) { + if (trackId == 0) { + fprintf(stderr, "%s: Must specify track for sample\n", ProgName); + return -1; + } + if (sampleId > MP4GetTrackNumberOfSamples(mp4File, trackId)) { + fprintf(stderr, "%s: Sample number %u is past end %u\n", + ProgName, sampleId, MP4GetTrackNumberOfSamples(mp4File, trackId)); + return -1; + } + uint32_t sample_size = MP4GetTrackMaxSampleSize(mp4File, trackId); + uint8_t *sample = (uint8_t *)malloc(sample_size); + MP4Timestamp sampleTime; + MP4Duration sampleDuration, sampleRenderingOffset; + uint32_t this_size = sample_size; + bool isSyncSample; + bool ret = MP4ReadSample(mp4File, + trackId, + sampleId, + &sample, + &this_size, + &sampleTime, + &sampleDuration, + &sampleRenderingOffset, + &isSyncSample); + if (ret == false) { + fprintf(stderr, "Sample read error\n"); + return -1; + } + printf("Track %u, Sample %u, Length %u\n", + trackId, sampleId, this_size); + + for (uint32_t ix = 0; ix < this_size; ix++) { + if ((ix % 16) == 0) printf("\n%04u ", ix); + printf("%02x ", sample[ix]); + } + printf("\n"); + } else { + if (trackId == 0) { + u_int32_t numTracks = MP4GetNumberOfTracks(mp4File); + + for (u_int32_t i = 0; i < numTracks; i++) { + trackId = MP4FindTrackId(mp4File, i); + DumpTrack(mp4File, trackId); + } + } else { + DumpTrack(mp4File, trackId); + } + } + + MP4Close(mp4File); + + return(0); +} + diff -r 9780c2671a62 -r 6a86fdd4dea4 Input/aac/libmp4v2/util/mp4videoinfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Input/aac/libmp4v2/util/mp4videoinfo.cpp Mon Oct 24 15:33:32 2005 -0700 @@ -0,0 +1,309 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dmackie@cisco.com + */ + +// N.B. mp4extract just extracts tracks/samples from an mp4 file +// For many track types this is insufficient to reconsruct a valid +// elementary stream (ES). Use "mp4creator -extract=" if +// you need the ES reconstructed. + +#include "mp4.h" +#include "mpeg4ip_getopt.h" +#include "mp4av.h" +#include "mp4av_h264.h" +char* ProgName; +char* Mp4PathName; +char* Mp4FileName; +static void ParseH264 (uint8_t *bptr, uint32_t blen, + uint32_t len_size, bool dump_off) +{ + uint8_t *fptr = bptr; + while (blen > len_size) { + uint32_t nal_len = 0; + switch (len_size) { + case 1: nal_len = *bptr; break; + case 2: nal_len = (bptr[0] << 8) | bptr[1]; break; + case 3: nal_len = (bptr[0] << 16) | (bptr[1] << 8) | bptr[2]; break; + case 4: nal_len = (bptr[0] << 24) | (bptr[1] << 16) | (bptr[2] << 8) | bptr[3]; break; + } + bptr += len_size; + blen -= len_size; + uint8_t nal_type = *bptr & 0x1f; + switch (nal_type) { + case H264_NAL_TYPE_NON_IDR_SLICE: printf(" NIDR-"); break; + case H264_NAL_TYPE_DP_A_SLICE: printf(" DPA-"); break; + case H264_NAL_TYPE_DP_B_SLICE: printf(" DPB-"); break; + case H264_NAL_TYPE_DP_C_SLICE: printf(" DPC-"); break; + case H264_NAL_TYPE_IDR_SLICE: printf(" IDR-"); break; + case H264_NAL_TYPE_SEI: printf(" SEI"); break; + case H264_NAL_TYPE_SEQ_PARAM: printf(" SEQ"); break; + case H264_NAL_TYPE_PIC_PARAM: printf(" PIC"); break; + case H264_NAL_TYPE_ACCESS_UNIT: printf(" AU"); break; + case H264_NAL_TYPE_END_OF_SEQ: printf(" EOS"); break; + case H264_NAL_TYPE_END_OF_STREAM: printf(" EOST"); break; + case H264_NAL_TYPE_FILLER_DATA: printf(" FILL"); break; + default: printf(" UNK(0x%x)", nal_type); break; + } + if (h264_nal_unit_type_is_slice(nal_type)) { + uint8_t slice_type; + h264_find_slice_type(bptr, nal_len, &slice_type, true); + printf("%s", h264_get_slice_name(slice_type)); + } + uint32_t off = bptr - fptr - len_size; + if (dump_off) printf("(%u)", off); + bptr += nal_len; + if (nal_len > blen) { + blen = 0; + } else + blen -= nal_len; + } +} + +static void ParseMpeg4 (uint8_t *bptr, uint32_t blen, bool dump_off) +{ + uint8_t *fptr = bptr; + while (blen > 4) { + if (bptr[0] == 0 && + bptr[1] == 0 && + bptr[2] == 1) { + if (bptr[3] > 0 && bptr[3] < MP4AV_MPEG4_VOL_START) { + printf(" VDOS"); + } else if (bptr[3] < 0x2f) { + printf(" VOL"); + } else if (bptr[3] == MP4AV_MPEG4_VOSH_START) { + printf(" VOSH"); + } else if (bptr[3] == MP4AV_MPEG4_VOSH_END) { + printf(" VOSHE"); + } else if (bptr[3] == MP4AV_MPEG4_USER_DATA_START) { + printf(" UD"); + } else if (bptr[3] == MP4AV_MPEG4_GOV_START) { + printf(" GOV"); + } else if (bptr[3] == 0xB4) { + printf(" VSE"); + } else if (bptr[3] == MP4AV_MPEG4_VO_START) { + printf(" VOS"); + } else if (bptr[3] == MP4AV_MPEG4_VOP_START) { + int type = MP4AV_Mpeg4GetVopType(bptr, blen); + switch (type) { + case VOP_TYPE_I: printf(" VOP-I"); break; + case VOP_TYPE_P: printf(" VOP-P"); break; + case VOP_TYPE_B: printf(" VOP-B"); break; + case VOP_TYPE_S: printf(" VOP-S"); break; + } + } else printf(" 0x%x", bptr[3]); + uint32_t off = bptr - fptr; + if (dump_off) printf("(%u)", off); + } + bptr++; + blen--; + } +} +static void DumpTrack (MP4FileHandle mp4file, MP4TrackId tid, + bool dump_off, bool dump_rend) +{ + uint32_t numSamples; + MP4SampleId sid; + uint8_t *buffer; + uint32_t max_frame_size; + uint32_t timescale; + uint64_t msectime; + const char *media_data_name; + uint32_t len_size = 0; + + numSamples = MP4GetTrackNumberOfSamples(mp4file, tid); + max_frame_size = MP4GetTrackMaxSampleSize(mp4file, tid) + 4; + media_data_name = MP4GetTrackMediaDataName(mp4file, tid); + if (strcasecmp(media_data_name, "avc1") == 0) { + MP4GetTrackH264LengthSize(mp4file, tid, &len_size); + } + buffer = (uint8_t *)malloc(max_frame_size); + if (buffer == NULL) { + printf("couldn't get buffer\n"); + return; + } + + timescale = MP4GetTrackTimeScale(mp4file, tid); + printf("mp4file %s, track %d, samples %d, timescale %d\n", + Mp4FileName, tid, numSamples, timescale); + + for (sid = 1; sid <= numSamples; sid++) { + MP4Timestamp sampleTime; + MP4Duration sampleDuration, sampleRenderingOffset; + bool isSyncSample = FALSE; + bool ret; + u_int8_t *temp; + uint32_t this_frame_size = max_frame_size; + temp = buffer; + ret = MP4ReadSample(mp4file, + tid, + sid, + &temp, + &this_frame_size, + &sampleTime, + &sampleDuration, + &sampleRenderingOffset, + &isSyncSample); + + msectime = sampleTime; + msectime *= TO_U64(1000); + msectime /= timescale; + + printf("sampleId %6d, size %5u time "U64"("U64")", + sid, MP4GetSampleSize(mp4file, tid, sid), + sampleTime, msectime); + if (dump_rend) printf(" %6"U64F, sampleRenderingOffset); + if (strcasecmp(media_data_name, "mp4v") == 0) { + ParseMpeg4(temp, this_frame_size, dump_off); + } else if (strcasecmp(media_data_name, "avc1") == 0) { + ParseH264(temp, this_frame_size, len_size, dump_off); + } + printf("\n"); + } +} + +int main(int argc, char** argv) +{ + const char* usageString = + "[options] mp4file where:\n" + "\t--track(-t)= - display track id\n" + "\t--dump-offset(-d) - dump offset within sample\n" + "\t--rendering-offset(-r) - dump rendering offset\n" + "\t--verbose= - mp4 file verbosity\n" + "\t--version(-V) - display version\n"; + MP4TrackId trackId = MP4_INVALID_TRACK_ID; + u_int32_t verbosity = MP4_DETAILS_ERROR; + bool dump_offset = false; + bool dump_rend = false; + /* begin processing command line */ + ProgName = argv[0]; + while (true) { + int c = -1; + int option_index = 0; + static struct option long_options[] = { + { "track", 1, 0, 't' }, + { "verbose", 2, 0, 'v' }, + { "version", 0, 0, 'V' }, + { "dump-offset", 0, 0, 'd'}, + { "rendering-offset", 0, 0, 'r'}, + { "help", 0, 0, '?'}, + { NULL, 0, 0, 0 } + }; + + c = getopt_long_only(argc, argv, "t:v::V?", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 'd': dump_offset = true; break; + case 'r': dump_rend = true; break; + case 't': + if (sscanf(optarg, "%u", &trackId) != 1) { + fprintf(stderr, + "%s: bad track-id specified: %s\n", + ProgName, optarg); + exit(1); + } + break; + case 'v': + verbosity |= MP4_DETAILS_READ; + if (optarg) { + u_int32_t level; + if (sscanf(optarg, "%u", &level) == 1) { + if (level >= 2) { + verbosity |= MP4_DETAILS_TABLE; + } + if (level >= 3) { + verbosity |= MP4_DETAILS_SAMPLE; + } + if (level >= 4) { + verbosity = MP4_DETAILS_ALL; + } + } + } + break; + case '?': + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(0); + case 'V': + fprintf(stderr, "%s - %s version %s\n", + ProgName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); + exit(0); + default: + fprintf(stderr, "%s: unknown option specified, ignoring: %c\n", + ProgName, c); + } + } + + /* check that we have at least one non-option argument */ + if ((argc - optind) < 1) { + fprintf(stderr, "usage: %s %s", ProgName, usageString); + exit(1); + } + + if (verbosity) { + fprintf(stderr, "%s version %s\n", ProgName, MPEG4IP_VERSION); + } + + /* point to the specified file names */ + Mp4PathName = argv[optind++]; + + char* lastSlash = strrchr(Mp4PathName, '/'); + if (lastSlash) { + Mp4FileName = lastSlash + 1; + } else { + Mp4FileName = Mp4PathName; + } + + /* warn about extraneous non-option arguments */ + if (optind < argc) { + fprintf(stderr, "%s: unknown options specified, ignoring: ", ProgName); + while (optind < argc) { + fprintf(stderr, "%s ", argv[optind++]); + } + fprintf(stderr, "\n"); + } + + /* end processing of command line */ + + + MP4FileHandle mp4File = MP4Read(Mp4PathName, verbosity); + + if (!mp4File) { + exit(1); + } + + if (trackId == MP4_INVALID_TRACK_ID) { + u_int32_t numTracks = MP4GetNumberOfTracks(mp4File, MP4_VIDEO_TRACK_TYPE); + printf("tracks %d\n", numTracks); + for (u_int32_t ix = 0; ix < numTracks; ix++) { + trackId = MP4FindTrackId(mp4File, ix, MP4_VIDEO_TRACK_TYPE); + DumpTrack(mp4File, trackId, dump_offset, dump_rend); + } + } else { + DumpTrack(mp4File, trackId, dump_offset, dump_rend); + } + + MP4Close(mp4File); + + return(0); +} +