Internal change
PiperOrigin-RevId: 139268906
Change-Id: I7c35776cd8d76fab690cf6368d219cbe778ed87a
diff --git a/CHANGES.logging b/CHANGES.logging
new file mode 100644
index 0000000..e1db8f2
--- /dev/null
+++ b/CHANGES.logging
@@ -0,0 +1,339 @@
+change log for logging branch
+
+$Revision$
+$Date$
+
+-------------------
+
+(31-jan-11, dbyron)
+
+- fix ASSERTs in win32 implementation of
+StandardFileProvider to check against _INVALID_FILE_HANDLE
+instead of NULL since that's what the constructor and close
+method use
+
+- merge r440, r441, r442, r443, r444 from trunk
+
+- fix return value of win32 implementation of
+StandardFileProvider::close
+
+- merge r439 from trunk
+
+(18-jan-11, dbyron)
+
+- add __FUNCTION__, filename to warning messages
+
+- add warning to MP4File::Modify when failing because the
+file has no moov atom
+
+- add __FUNCTION__, filename to error messages
+
+- add filename to verbose log messages in mp4descriptor.cpp
+
+- remove __FUNCTION__ from verbose log messages in
+mp4atom.cpp since it makes the dump output hard to read
+
+- add filename to descriptions passed to Log::dump
+
+- change log messages with Warning: to use Log::warningf
+
+- fix Log::hexdump to make sure output begins with format
+string/varargs instead of overwriting with ascii-hex
+
+(17-jan-11, dbyron)
+
+- change the MP4RtpData, MP4RtpNullData,
+MP4RtpImmediateData, MP4RtpSampleData,
+MP4RtpSampleDescriptionData, MP4RtpPacket, MP4RtpHint and
+MP4Track to take references instead of pointers, with
+accessors changed appropriately.
+
+(14-jan-11, dbyron)
+
+- change the MP4Descriptor constructor (and the constructors
+of all its child classes) to take a (MP4Atom &) and remove
+MP4Descriptor::SetParentAtom to remove the chance to
+dereference a NULL pointer. Similarly for MP4Property and
+all its children. Declare default and copy constructors and
+assignment operator private to prevent using
+compiler-generated routines.
+
+- change all Read and Write methods that took (MP4File *) to
+take a (MP4File &).
+
+- change the MP4Track, MP4RtpHintTrack constructors to take a
+(MP4File &). Corresponding changes to MP4Track::GetFile.
+
+(13-jan-11, dbyron)
+
+- change the MP4Atom constructor to take an (MP4File &), remove
+MP4Atom::SetFile and change MP4Atom::GetFile to return an
+(MP4File &). Change the internal member variable to an
+(MP4File &) as well. Corresponding changes to
+MP4Atom::ReadAtom, CreateAtom, factory and child class
+constructors. This makes it impossible to dereference a
+NULL pointer by accident.
+
+- convert messages with warning in the text to use
+Log::warningf
+
+- include __FUNCTION__ and filename in log messages in
+mp4atom.cpp
+
+(11-jan-11, dbyron)
+
+- declare Log copy constructor and assignment operator
+private but don't implement them to prohibit copies
+
+(6-jan-11, dbyron)
+
+- add mp4subtitle.vcproj to build on windows
+
+(3-jan-11, dbyron)
+
+- declare MP4File copy constructor and assignment operator
+private but don't implement them to prohibit copies
+
+- remove MP4HexDump and Indent from mp4util since they're
+not used anymore
+
+- change Log::hexDump to dump printable bytes as well as the
+hex values
+
+- remove error_msg_func_t, lib_message_func_t and
+MP4SetLibFunc from general.h since they're not used and
+don't really make sense now that MP4SetLogCallback exists
+
+- add MP4TagsHasMetadata to indicate whether a file contains
+any metadata at all
+
+(31-dec-10, dbyron)
+
+- add MP4GetFilename so the filename associated with a
+MP4FileHandle is available. Add MP4File::GetFilename to
+support it.
+
+(27-dec-10, dbyron)
+
+- remove m_tempFileName from MP4File since it's not used
+
+- throw an exception from the win32 implementation of
+FileSystem::exists, FileSystem::isDirectory and
+FileSystem::isFile if there's an error
+
+- add logging to win32 FileSystem
+
+- add Utf8ToFilename::GetUTF8 to get the UTF-8
+representation of the filename actually used
+
+- add Utf8ToFilename::IsUTF16Valid so users of the class can
+detect errors
+
+- rename Utf8ToWideChar to Utf8ToFilename to more accurately
+reflect what the class does
+
+- replace MultiByteToWideChar with custom code to remove
+differences across versions of windows and for improved
+error detection and illegal character handling
+
+- add long filename support to Utf8ToWideChar
+
+(21-dec-10, dbyron)
+
+- add logging to win32 StandardFileProvider
+
+(20-dec-10, dbyron)
+
+- make try/catch blocks more granular in MP4Read,
+MP4ReadProvider, MP4Create, MP4CreateEx, MP4Modify,
+MP4Optimize, MP4Make3GPCompliant, MP4MakeIsmaCompliant,
+MP4MakeIsmaSdpIod so it's easier to figure out the cause of
+failure based on the log message.
+
+- log more specific messages, clean up leak if there's an
+error adding the IpodUUID atom in MP4AddIPodUUID
+
+- remove MP4_DETAILS_* as it was only used in a few internal
+places where an MP4_LOG_* replacement is fine until the
+verbosity-altering code disappears. For some reason
+MP4File::MakeIsmaCompliant alters the verbosity before
+calling MP4GetVideoProfileLevel, MP4IsIsmaCrypMediaTrack
+does the same before calling MP4File::IsIsmaCrypMediaTrack,
+as does MP4CloneTrack before calling
+MP4GetTrackESConfiguration.
+
+- change command line programs to map debug levels as
+follows:
+ 0: MP4_LOG_NONE
+ 1: MP4_LOG_ERROR
+ 2, 3: MP4_LOG_VERBOSE2
+ 4: MP4_LOG_VERBOSE4
+
+- change MP4NormalizeTrackType (an internal function) to
+always use MP4_LOG_VERBOSE1.
+
+- another fix to Log::hexDump so that it now actually dumps
+all the bytes it was asked to dump
+
+- MP4File is no longer a child of Log. Use the global log
+object everywhere.
+
+- remove the verbosity argument to MP4Read, MP4ReadProvider,
+MP4Create and MP4CreateEx, MP4Modify, MP4Optimize,
+MP4MakeIsmaCompliant, MP4MakeIsmaSdpIod, MP4Make3GPCompliant
+and MP4NormalizeTrackType. Remove MP4GetVerbosity,
+MP4SetVerbosity and MP4Atom::GetVerbosity. Use
+MP4LogSetLevel to change the global log level instead.
+There is no more file-specific verbosity since it is more
+complicated than one global log level and it's not clear
+anyone needs the added complexity.
+
+- remove the MP4FileHandle argument to MP4LogSetLevel and
+MP4LogGetLevel and move them to general.h/log.cpp since
+they're no longer file-specific. The default log level is
+MP4_LOG_WARNING without any call to MP4LogSetLevel.
+
+- change MP4BytesProperty::Dump to use Log::hexDump for
+large (> 16) byte hex output
+
+- remove the FILE* argument from MP4Dump, the internal Dump
+methods (e.g. MP4File::Dump, MP4Atom::Dump,
+MP4Property::Dump, etc.). Use Log::dump instead.
+
+- remove Indent from mp4util since it may pollute
+stdout/stderr
+
+- add Log::dump, Log::vdump to support dumping with a
+particular indent
+
+- fix Log::hexDump to print the correct ascii-hex info
+
+(17-dec-10, dbyron)
+
+- remove C_ASSERT from mp4util.h since it's not used
+
+- remove MP4Printf to keep from writing to stdout when
+logging
+
+(7-jun-09, dbyron)
+
+- add MP4LogGetLevel, MP4LogSetLevel
+
+(5-jun-09, dbyron)
+
+- change return value of MP4DeleteTrack,
+MP4SetTrackTimeScale, MP4GetTrackH264SeqPictHeaders from
+void to bool
+
+- change MP4AddIPodUUID to return bool, check for valid
+hFile and catch exceptions
+
+- check for NULL existingFileName, newFileName in
+MP4Optimize
+
+- check for NULL fileName in MP4ReadProvider, MP4CreateEx,
+MP4Modify, MP4Make3GPCompliant, MP4MakeIsmaCompliant
+
+- properly handle NULL pFile when catching Exception
+
+- check for NULL parameters in genericAddItem,
+genericSetItem, genericRemoveItem
+
+- change signature of C wrappers to return bool and check
+for NULL parameters:
+ - MP4TagsAddArtwork
+ - MP4TagsFetch
+ - MP4TagsRemoveArtwork
+ - MP4TagsSetArtwork
+ - MP4TagsStore
+ - MP4TagsSetName
+ - MP4TagsSetArtist
+ - MP4TagsSetAlbumArtist
+ - MP4TagsSetAlbum
+ - MP4TagsSetGrouping
+ - MP4TagsSetComposer(
+ - MP4TagsSetComments
+ - MP4TagsSetGenre
+ - MP4TagsSetGenreType
+ - MP4TagsSetReleaseDate
+ - MP4TagsSetTrack
+ - MP4TagsSetDisk
+ - MP4TagsSetTempo
+ - MP4TagsSetCompilation
+ - MP4TagsSetTVShow
+ - MP4TagsSetTVNetwork
+ - MP4TagsSetTVEpisodeID
+ - MP4TagsSetTVSeason
+ - MP4TagsSetTVEpisode
+ - MP4TagsSetSortName
+ - MP4TagsSetSortArtist
+ - MP4TagsSetSortAlbumArtist
+ - MP4TagsSetSortAlbum
+ - MP4TagsSetSortComposer
+ - MP4TagsSetSortTVShow
+ - MP4TagsSetDescription
+ - MP4TagsSetLongDescription
+ - MP4TagsSetLyrics
+ - MP4TagsSetCopyright
+ - MP4TagsSetEncodingTool
+ - MP4TagsSetEncodedBy
+ - MP4TagsSetPurchaseDate
+ - MP4TagsSetPodcast
+ - MP4TagsSetKeywords
+ - MP4TagsSetCategory
+ - MP4TagsSetHDVideo
+ - MP4TagsSetMediaType
+ - MP4TagsSetContentRating
+ - MP4TagsSetGapless
+ - MP4TagsSetITunesAccount
+ - MP4TagsSetITunesAccountType
+ - MP4TagsSetITunesCountry
+ - MP4TagsSetCNID
+ - MP4TagsSetATID
+ - MP4TagsSetPLID
+ - MP4TagsSetGEID
+
+- add catch( ... ) blocks to C wrapper functions
+
+- add static void errorf ( Log *olog,
+ const char *format,
+ ... ) MP4V2_WFORMAT_PRINTF(3,4);
+
+- add static void errorf ( Log *olog,
+ const Exception &x );
+- remove MP4Exception, replace with Exception
+
+- change MP4File::ProtectWriteOperation to take file, line,
+function instead of one "where" string.
+
+- change exception catching code to call Log::errorf();
+
+- remove VERBOSE, VERBOSE_ERROR from mp4util.h
+
+- remove MP4Error, replace with Exception, PlatformException
+as appropriate
+
+- add Exception class and Log::errorf( const Exception &x );
+
+(16-feb-09, dbyron)
+
+- First pass of actually using the Log class:
+
+ - MP4LogNone --> MP4_LOG_NONE
+ - add global log object (log, declared in log.h)
+ - change MP4File to inherit from Log
+ - remove m_verbosity member variable
+ - remove MP4File::GetVerbosity, SetVerbosity methods
+ - change MP4NormalizeTrackType to take MP4LogLevel
+ - replace VERBOSE_* with corresponding Log method calls
+ (VERBOSE_ERROR remains until exception handling gets
+ revisited)
+ - change WARNING macro to take a Log object as the first
+ argument
+ - add Log::hexDump to mostly replace MP4HexDump (though
+ MP4HexDump is still called if there's no logging callback)
+ - fix MP4_DETAILS_ALL handling in Log::detailsToLevel
+ - add uint32_t Log::getVerbosity() const
+ - add Log::hexDump
+ - add uint32_t Log::getVerbosity
+ - add Log::verbose3f, verbose4f
diff --git a/GNUmakefile.am b/GNUmakefile.am
new file mode 100644
index 0000000..947e6e3
--- /dev/null
+++ b/GNUmakefile.am
@@ -0,0 +1,322 @@
+lib_LTLIBRARIES = libmp4v2.la
+
+bin_PROGRAMS =
+
+check_PROGRAMS =
+
+###############################################################################
+
+libmp4v2_la_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ -version-number $(PROJECT_version_major):$(PROJECT_version_minor):$(PROJECT_version_point) $(X_libmp4v2_la_LDFLAGS)
+
+libmp4v2_la_SOURCES = \
+ src/3gp.cpp \
+ src/atom_ac3.cpp \
+ src/atom_amr.cpp \
+ src/atom_avc1.cpp \
+ src/atom_avcC.cpp \
+ src/atom_chpl.cpp \
+ src/atom_colr.cpp \
+ src/atom_d263.cpp \
+ src/atom_dac3.cpp \
+ src/atom_damr.cpp \
+ src/atom_dref.cpp \
+ src/atom_elst.cpp \
+ src/atom_enca.cpp \
+ src/atom_encv.cpp \
+ src/atom_free.cpp \
+ src/atom_ftyp.cpp \
+ src/atom_ftab.cpp \
+ src/atom_gmin.cpp \
+ src/atom_hdlr.cpp \
+ src/atom_hinf.cpp \
+ src/atom_hnti.cpp \
+ src/atom_href.cpp \
+ src/atom_mdat.cpp \
+ src/atom_mdhd.cpp \
+ src/atom_meta.cpp \
+ src/atom_mp4s.cpp \
+ src/atom_mp4v.cpp \
+ src/atom_mvhd.cpp \
+ src/atom_nmhd.cpp \
+ src/atom_ohdr.cpp \
+ src/atom_pasp.cpp \
+ src/atom_root.cpp \
+ src/atom_rtp.cpp \
+ src/atom_s263.cpp \
+ src/atom_sdp.cpp \
+ src/atom_sdtp.cpp \
+ src/atom_smi.cpp \
+ src/atom_sound.cpp \
+ src/atom_standard.cpp \
+ src/atom_stbl.cpp \
+ src/atom_stdp.cpp \
+ src/atom_stsc.cpp \
+ src/atom_stsd.cpp \
+ src/atom_stsz.cpp \
+ src/atom_stz2.cpp \
+ src/atom_text.cpp \
+ src/atom_tfhd.cpp \
+ src/atom_tkhd.cpp \
+ src/atom_treftype.cpp \
+ src/atom_trun.cpp \
+ src/atom_tx3g.cpp \
+ src/atom_udta.cpp \
+ src/atom_url.cpp \
+ src/atom_urn.cpp \
+ src/atom_uuid.cpp \
+ src/atom_video.cpp \
+ src/atom_vmhd.cpp \
+ src/atoms.h \
+ src/cmeta.cpp \
+ src/descriptors.cpp \
+ src/descriptors.h \
+ src/exception.cpp \
+ src/exception.h \
+ src/enum.h \
+ src/enum.tcc \
+ src/impl.h \
+ src/isma.cpp \
+ src/log.h \
+ src/log.cpp \
+ src/mp4.cpp \
+ src/mp4array.h \
+ src/mp4atom.cpp \
+ src/mp4atom.h \
+ src/mp4container.cpp \
+ src/mp4container.h \
+ src/mp4descriptor.cpp \
+ src/mp4descriptor.h \
+ src/mp4file.cpp \
+ src/mp4file.h \
+ src/mp4file_io.cpp \
+ src/mp4info.cpp \
+ src/mp4property.cpp \
+ src/mp4property.h \
+ src/mp4track.cpp \
+ src/mp4track.h \
+ src/mp4util.cpp \
+ src/mp4util.h \
+ src/ocidescriptors.cpp \
+ src/ocidescriptors.h \
+ src/odcommands.cpp \
+ src/odcommands.h \
+ src/qosqualifiers.cpp \
+ src/qosqualifiers.h \
+ src/rtphint.cpp \
+ src/rtphint.h \
+ src/src.h \
+ src/text.cpp \
+ src/text.h \
+ src/util.h
+
+libmp4v2_la_SOURCES += \
+ src/bmff/bmff.h \
+ src/bmff/impl.h \
+ src/bmff/typebmff.cpp \
+ src/bmff/typebmff.h
+
+libmp4v2_la_SOURCES += \
+ src/itmf/CoverArtBox.cpp \
+ src/itmf/CoverArtBox.h \
+ src/itmf/Tags.cpp \
+ src/itmf/Tags.h \
+ src/itmf/generic.cpp \
+ src/itmf/generic.h \
+ src/itmf/impl.h \
+ src/itmf/itmf.h \
+ src/itmf/type.cpp \
+ src/itmf/type.h
+
+libmp4v2_la_SOURCES += \
+ src/qtff/ColorParameterBox.cpp \
+ src/qtff/ColorParameterBox.h \
+ src/qtff/PictureAspectRatioBox.cpp \
+ src/qtff/PictureAspectRatioBox.h \
+ src/qtff/coding.cpp \
+ src/qtff/coding.h \
+ src/qtff/impl.h \
+ src/qtff/qtff.h
+
+libmp4v2_la_SOURCES += \
+ libplatform/endian.h \
+ libplatform/impl.h \
+ libplatform/io/File.cpp \
+ libplatform/io/File.h \
+ libplatform/io/FileSystem.cpp \
+ libplatform/io/FileSystem.h \
+ libplatform/number/random.h \
+ libplatform/platform.h \
+ libplatform/platform_base.h \
+ libplatform/platform_posix.h \
+ libplatform/platform_win32.h \
+ libplatform/process/process.h \
+ libplatform/prog/option.cpp \
+ libplatform/prog/option.h \
+ libplatform/sys/error.cpp \
+ libplatform/sys/error.h \
+ libplatform/time/time.cpp \
+ libplatform/time/time.h \
+ libplatform/warning.h
+
+if ADD_PLATFORM_POSIX
+ libmp4v2_la_SOURCES += \
+ libplatform/io/File_posix.cpp \
+ libplatform/io/FileSystem_posix.cpp \
+ libplatform/number/random_posix.cpp \
+ libplatform/process/process_posix.cpp \
+ libplatform/time/time_posix.cpp
+endif
+if ADD_PLATFORM_WIN32
+ libmp4v2_la_SOURCES += \
+ libplatform/io/File_win32.cpp \
+ libplatform/io/FileSystem_win32.cpp \
+ libplatform/number/random_win32.cpp \
+ libplatform/process/process_win32.cpp \
+ libplatform/time/time_win32.cpp
+endif
+
+if ADD_UTIL
+ libmp4v2_la_SOURCES += \
+ libutil/Database.cpp \
+ libutil/Database.h \
+ libutil/Timecode.cpp \
+ libutil/Timecode.h \
+ libutil/TrackModifier.cpp \
+ libutil/TrackModifier.h \
+ libutil/Utility.cpp \
+ libutil/Utility.h \
+ libutil/crc.cpp \
+ libutil/crc.h \
+ libutil/impl.h \
+ libutil/other.cpp \
+ libutil/other.h \
+ libutil/util.h
+
+ bin_PROGRAMS += mp4art
+ bin_PROGRAMS += mp4chaps
+ bin_PROGRAMS += mp4extract
+ bin_PROGRAMS += mp4file
+ bin_PROGRAMS += mp4info
+ bin_PROGRAMS += mp4subtitle
+ bin_PROGRAMS += mp4tags
+ bin_PROGRAMS += mp4track
+ bin_PROGRAMS += mp4trackdump
+endif
+
+mp4art_SOURCES = util/impl.h util/mp4art.cpp
+mp4chaps_SOURCES = util/impl.h util/mp4chaps.cpp
+mp4extract_SOURCES = util/impl.h util/mp4extract.cpp
+mp4file_SOURCES = util/impl.h util/mp4file.cpp
+mp4info_SOURCES = util/impl.h util/mp4info.cpp
+mp4subtitle_SOURCES = util/impl.h util/mp4subtitle.cpp
+mp4tags_SOURCES = util/impl.h util/mp4tags.cpp
+mp4track_SOURCES = util/impl.h util/mp4track.cpp
+mp4trackdump_SOURCES = util/impl.h util/mp4trackdump.cpp
+
+mp4art_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4chaps_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4extract_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4file_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4info_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4subtitle_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4tags_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4track_LDADD = libmp4v2.la $(X_LDFLAGS)
+mp4trackdump_LDADD = libmp4v2.la $(X_LDFLAGS)
+
+###############################################################################
+
+DEJATOOL = main
+
+TESTLOGDIR = $(top_builddir)/testlog
+
+override RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir/testsuite --outdir $(TESTLOGDIR)
+
+###############################################################################
+
+mp4v2incdir = $(pkgincludedir)
+
+mp4v2inc_HEADERS = \
+ include/mp4v2/project.h \
+ \
+ include/mp4v2/chapter.h \
+ include/mp4v2/file.h \
+ include/mp4v2/file_prop.h \
+ include/mp4v2/general.h \
+ include/mp4v2/isma.h \
+ include/mp4v2/itmf_generic.h \
+ include/mp4v2/itmf_tags.h \
+ include/mp4v2/mp4v2.h \
+ include/mp4v2/platform.h \
+ include/mp4v2/sample.h \
+ include/mp4v2/streaming.h \
+ include/mp4v2/track.h \
+ include/mp4v2/track_prop.h
+
+###############################################################################
+
+EXTRA_DIST = project/project.m4
+
+###############################################################################
+
+clean-local:
+
+distclean-local:
+ rm -f $(top_builddir)/Makefile
+ rm -f $(top_builddir)/testlog/*.log
+ rm -f $(top_builddir)/testlog/*.sum
+
+###############################################################################
+
+AM_CPPFLAGS = $(strip $(MK_CXX_ARCH) $(X_CXX_ARCH) $(MK_CXX_I) $(X_CXX_I))
+
+AM_LDFLAGS = $(strip $(MK_CXX_ARCH) $(X_CXX_ARCH))
+
+AM_CXXFLAGS = $(strip $(MK_CXX_W) $(X_CXX_W))
+
+LIBS := $(LIBS) $(X_MINGW_LIBS)
+
+###############################################################################
+
+MK_CXX_ARCH =
+MK_CXX_W = -Wall -Wformat
+MK_CXX_D =
+
+MK_CXX_I = \
+ -I$(top_builddir)/include -I$(top_srcdir)/include \
+ -I$(top_builddir) -I$(top_srcdir)
+
+###############################################################################
+
+if ADD_UTIL
+if ADD_MANS
+ man1_MANS = \
+ doc/man/man1/mp4art.1 \
+ doc/man/man1/mp4file.1 \
+ doc/man/man1/mp4subtitle.1 \
+ doc/man/man1/mp4track.1
+endif
+endif
+
+###############################################################################
+
+##
+## workaround: DejaGNU adds a hard-coded dependency on Makefile
+## and need to create logdir
+##
+Makefile: ${Makefile}
+ touch $@
+ $(mkdir_p) $(TESTLOGDIR)
+
+dist-hook:
+
+###############################################################################
+
+##
+## include GNUmakefiles which are not full-fledged automake citizens but
+## they are aware of automake variables and targets. Note that we purposely
+## use a GNUmakefile extension (-include) to prevent automake from parsing
+## the file.
+##
+-include $(top_srcdir)/doc/GNUmakefile.mk
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..d3c5b40
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,237 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 6. Often, you can also type `make uninstall' to remove the installed
+ files again.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0c3dd64
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,458 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``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): ...
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
diff --git a/README b/README
new file mode 100644
index 0000000..bce10af
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+All docs are located in doc/ subdirectory. Useful starting points:
+
+Release Notes -- doc/ReleaseNotes.txt
+Building the Source -- doc/BuildSource.txt
+Building the Repository -- doc/BuildRepository.txt
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..83e9dce
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,419 @@
+###############################################################################
+# prelude
+###############################################################################
+
+m4_include([project/project.m4sugar])
+
+m4_define([SVNINFO],m4_esyscmd([LANG=en svn info 2>/dev/null]))
+
+changequote(<<,>>)dnl
+ m4_define(<<PRJ_repo_url>>,m4_bregexp(SVNINFO,<<^URL: *\(.+\)>>,<<\1>>))
+ m4_define(<<PRJ_repo_branch>>,m4_bregexp(PRJ_repo_url,<<\([^/]+\)$>>,<<\1>>))
+ m4_define(<<PRJ_repo_root>>,m4_bregexp(SVNINFO,<<^Repository Root: *\(.+\)>>,<<\1>>))
+ m4_define(<<PRJ_repo_uuid>>,m4_bregexp(SVNINFO,<<^Repository UUID: *\(.+\)>>,<<\1>>))
+ m4_define(<<PRJ_repo_rev>>,m4_bregexp(SVNINFO,<<^Last Changed Rev: *\(.+\)>>,<<\1>>))
+ m4_define(<<PRJ_repo_date>>,m4_bregexp(SVNINFO,<<^Last Changed Date: *\(.+\)>>,<<\1>>))
+ m4_define(<<PRJ_repo_type>>,ifelse(m4_bregexp(PRJ_repo_url,<</releases/>>),<<-1>>,<<developer>>,<<stable>>))
+changequote([,])dnl
+
+m4_define([PRJ_version_hex],m4_format([0x%04x%02x%02x],PRJ_version_major,PRJ_version_minor,PRJ_version_point))
+
+m4_define([PRJ_version],ifelse(
+ PRJ_repo_type,[stable],m4_format([%s],PRJ_repo_branch),
+ m4_format([%s-r%s],PRJ_repo_branch,PRJ_repo_rev)))
+
+###############################################################################
+# initialization
+###############################################################################
+
+AC_PREREQ([2.61])
+AC_INIT(PRJ_name,PRJ_version,PRJ_bugreport)
+
+AC_MSG_NOTICE([
+ -->
+ --> Configuring ]AC_PACKAGE_STRING[
+ -->])
+
+AC_CONFIG_AUX_DIR([autoaux])
+AM_INIT_AUTOMAKE([1.9.6 foreign -Wall -Wno-portability -Werror subdir-objects nostdinc no-dist-gzip dist-bzip2 dist-zip dejagnu])
+
+AC_CONFIG_SRCDIR([src/mp4.cpp])
+
+# disable unused langs (improves config speed, reduces configure file size)
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG], [:])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], [:])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG], [:])
+
+AC_CANONICAL_HOST
+
+###############################################################################
+# add configure options
+###############################################################################
+
+if test -z "$enable_dependency_tracking"; then
+ enable_dependency_tracking=no
+fi
+
+AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--disable-debug],[disable debugging compilation])])
+AC_ARG_ENABLE([optimize],
+ [AS_HELP_STRING([--disable-optimize],[disable optimizing compilation])])
+AC_ARG_ENABLE([fvisibility],
+ [AS_HELP_STRING([--disable-fvisibility],[disable use of -fvisibility])])
+AC_ARG_ENABLE([gch],
+ [AS_HELP_STRING([--disable-gch],[disable GCC precompiled-headers])])
+AC_ARG_ENABLE([largefile],
+ [AS_HELP_STRING([--disable-largefile],[disable LFS (large file support)])])
+AC_ARG_ENABLE([util],
+ [AS_HELP_STRING([--disable-util],[disable build of command-line utilities])])
+AC_ARG_ENABLE([bi],
+ [AS_HELP_STRING([--enable-bi=ARCH],[enable -mARCH for bi-arch compilation])])
+AC_ARG_ENABLE([ub],
+ [AS_HELP_STRING([--enable-ub@<:@=ARCHS@:>@],[enable -arch ARCH for universal-binaries (OSX only)])])
+AC_ARG_ENABLE([cygwin_win32],
+ [AS_HELP_STRING([--enable-cygwin-win32],[when building with Cygwin use -mwin32])])
+AC_ARG_ENABLE([mingw_mt],
+ [AS_HELP_STRING([--enable-mingw-threads],[when building with MinGW use -mthreads])])
+
+###############################################################################
+# checks for programs
+###############################################################################
+
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+
+AC_CHECK_PROG([FOUND_HELP2MAN],[help2man],[yes],[no])
+
+###############################################################################
+# top-level platform check
+###############################################################################
+
+AC_MSG_CHECKING([$PACKAGE_NAME platform portability])
+X_PLATFORM=posix
+case ${host} in
+*-*-cygwin)
+ X_CXX_W="$X_CXX_W -Wno-format"
+ if test "$enable_cygwin_win32" = "yes"; then
+ X_PLATFORM=win32
+ X_CXX_ARCH="$X_CXX_ARCH -mwin32"
+ fi
+ ;;
+*-*-mingw*)
+ # do not support shared
+ enable_shared=no
+ X_PLATFORM=win32
+ X_MINGW_LIBS="$X_MINGW_LIBS"
+ X_CXX_W="$X_CXX_W -Wno-format"
+ if test "$enable_mingw_threads" = "yes"; then
+ X_CXX_ARCH="$X_CXX_ARCH -mthreads"
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$X_PLATFORM])
+
+###############################################################################
+# prepare project metadata
+###############################################################################
+
+PROJECT_name="PRJ_name"
+PROJECT_name_lower="PRJ_name_lower"
+PROJECT_name_upper="PRJ_name_upper"
+PROJECT_name_formal="PRJ_name PRJ_version"
+PROJECT_url_website="PRJ_url_website"
+PROJECT_url_downloads="PRJ_url_downloads"
+PROJECT_url_discussion="PRJ_url_discussion"
+PROJECT_irc="PRJ_irc"
+PROJECT_bugreport="<PRJ_bugreport>"
+
+PROJECT_version="PRJ_version"
+PROJECT_version_hex="PRJ_version_hex"
+PROJECT_version_major="PRJ_version_major"
+PROJECT_version_minor="PRJ_version_minor"
+PROJECT_version_point="PRJ_version_point"
+PROJECT_repo_url="PRJ_repo_url"
+PROJECT_repo_branch="PRJ_repo_branch"
+PROJECT_repo_root="PRJ_repo_root"
+PROJECT_repo_uuid="PRJ_repo_uuid"
+PROJECT_repo_rev="PRJ_repo_rev"
+PROJECT_repo_date="PRJ_repo_date"
+PROJECT_repo_type="PRJ_repo_type"
+PROJECT_build="`date`"
+
+test -z "$PROJECT_version_hex" && PROJECT_version_hex="0x0000000000000000LL"
+test -z "$PROJECT_version_major" && PROJECT_version_major="0"
+test -z "$PROJECT_version_minor" && PROJECT_version_minor="0"
+test -z "$PROJECT_version_point" && PROJECT_version_point="0"
+test -z "$PROJECT_repo_url" && PROJECT_repo_url="svn://nowhere.com/project/unknown"
+test -z "$PROJECT_repo_branch" && PROJECT_repo_branch="unknown"
+test -z "$PROJECT_repo_root" && PROJECT_repo_root="svn://nowhere.com/project"
+test -z "$PROJECT_repo_uuid" && PROJECT_repo_uuid="00000000-0000-0000-0000-000000000000"
+test -z "$PROJECT_repo_rev" && PROJECT_repo_rev="0"
+test -z "$PROJECT_repo_date" && PROJECT_repo_date="unknown"
+test -z "$PROJECT_repo_type" && PROJECT_repo_type="unknown"
+test -z "$PROJECT_build" && PROJECT_build="unknown"
+
+AC_SUBST([PROJECT_name])
+AC_SUBST([PROJECT_name_lower])
+AC_SUBST([PROJECT_name_upper])
+AC_SUBST([PROJECT_name_formal])
+AC_SUBST([PROJECT_url_website])
+AC_SUBST([PROJECT_url_downloads])
+AC_SUBST([PROJECT_url_discussion])
+AC_SUBST([PROJECT_irc])
+AC_SUBST([PROJECT_bugreport])
+AC_SUBST([PROJECT_version])
+AC_SUBST([PROJECT_version_hex])
+AC_SUBST([PROJECT_version_major])
+AC_SUBST([PROJECT_version_minor])
+AC_SUBST([PROJECT_version_point])
+AC_SUBST([PROJECT_repo_url])
+AC_SUBST([PROJECT_repo_branch])
+AC_SUBST([PROJECT_repo_root])
+AC_SUBST([PROJECT_repo_uuid])
+AC_SUBST([PROJECT_repo_rev])
+AC_SUBST([PROJECT_repo_date])
+AC_SUBST([PROJECT_repo_type])
+AC_SUBST([PROJECT_build])
+
+###############################################################################
+# checks for libraries
+###############################################################################
+
+###############################################################################
+# checks for header files
+###############################################################################
+
+###############################################################################
+# checks for typedefs, structures, and compiler characteristics
+###############################################################################
+
+###############################################################################
+# replace -ggdb3 with -ggdb2 to avoid GNU 'as' from failing
+# See http://code.google.com/p/mp4v2/issues/detail?id=27
+###############################################################################
+if test "$GXX" = "yes"; then
+ CXXFLAGS_GGDB3=`echo "$CXXFLAGS" | sed -e 's/-ggdb3/-ggdb2/'`
+ CXXFLAGS="$CXXFLAGS_GGDB3"
+fi
+
+###############################################################################
+# additional ldflags
+###############################################################################
+
+case ${host} in
+ *-*-darwin*)
+ X_libmp4v2_la_LDFLAGS='-Wl,-current_version,$(PROJECT_version_major).$(PROJECT_version_minor).$(PROJECT_version_point) -Wl,-compatibility_version,$(PROJECT_version_major).0.0'
+ ;;
+ *-*-cygwin*)
+ X_libmp4v2_la_LDFLAGS='-no-undefined'
+ ;;
+ *)
+ X_libmp4v2_la_LDFLAGS=
+ ;;
+esac
+
+AC_SUBST([X_libmp4v2_la_LDFLAGS])
+
+###############################################################################
+# check for --disable-fvisibility
+###############################################################################
+
+if test "$enable_fvisibility" != "no" -a "$GXX" = "yes"; then
+ case ${host} in
+ *-*-cygwin)
+ ;;
+ *-*-mingw*)
+ ;;
+ *)
+ AC_LANG(C++)
+ AC_CACHE_CHECK([if $CXX supports -fvisibility],[x_cv_fvisibility],[
+ x_save="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
+ AC_TRY_COMPILE([],[],[x_cv_fvisibility=yes],[x_cv_fvisibility=no])
+ if test "$x_cv_fvisibility" != "yes"; then
+ CXXFLAGS="$x_save"
+ fi
+ x_save=
+ ])
+ ;;
+ esac
+fi
+
+###############################################################################
+# check for --disable-gch
+###############################################################################
+
+AC_MSG_CHECKING([if GCC precompiled-headers should be created])
+
+X_GCH=0
+X_GCH_FLAGS=
+X_GCH_STATIC=0
+X_GCH_STATIC_FLAGS="$lt_prog_compiler_static_CXX"
+X_GCH_SHARED=0
+X_GCH_SHARED_FLAGS="$lt_prog_compiler_pic_CXX"
+
+if test "$enable_gch" = "yes"; then
+ X_GCH=1
+elif test "$enable_gch" != "no"; then
+ if test "$GXX" = "yes"; then
+ case ${host_os} in
+ cygwin*|darwin*|freebsd*|linux*|mingw*|solaris*)
+ X_GCH=1
+ ;;
+ esac
+ fi
+fi
+
+if test "$X_GCH" -eq 1; then
+ x_gch_result="yes"
+ if test "$enable_static" = "yes"; then
+ X_GCH_STATIC=1
+ fi
+ if test "$enable_shared" = "yes"; then
+ X_GCH_SHARED=1
+ fi
+else
+ x_gch_result="no"
+fi
+
+AC_MSG_RESULT([$x_gch_result])
+
+AC_SUBST([X_GCH])
+AC_SUBST([X_GCH_FLAGS])
+AC_SUBST([X_GCH_STATIC])
+AC_SUBST([X_GCH_STATIC_FLAGS])
+AC_SUBST([X_GCH_SHARED])
+AC_SUBST([X_GCH_SHARED_FLAGS])
+
+###############################################################################
+# check for --disable-largefile
+###############################################################################
+
+if test "$enable_largefile" != "no" -a "$ac_cv_header_unistd_h" = "yes"; then
+ case ${host_cpu} in
+ i?86|ppc)
+ AC_LANG(C++)
+ AC_CACHE_CHECK([if LFS (large file support) is required],[x_cv_largefile],[
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <unistd.h>
+#ifndef _LFS_LARGEFILE
+ error: not LFS conformant
+#endif
+ ]])],[x_cv_largefile=yes],[x_cv_largefile=no])
+ ])
+ if test "$x_cv_largefile" = "yes"; then
+ AC_DEFINE([NEED_LFS_ACTIVATION],[1],[Define to 1 if LFS should be activated])
+ fi
+ ;;
+ esac
+fi
+
+###############################################################################
+# set arch flags
+###############################################################################
+
+if test "$GXX" = "yes"; then
+ AC_MSG_CHECKING([arch flags])
+ x_flags=
+ x_save_IFS=$IFS; IFS=,
+ for arch in ${enable_ub}; do
+ case "$arch" in
+ ""|no)
+ ;;
+ yes)
+ case ${host} in
+ *-*-darwin*)
+ x_flags="$xflags -arch i386 -arch x86_64 -arch ppc -arch ppc64"
+ ;;
+ esac
+ ;;
+ *)
+ x_flags="$x_flags -arch $arch"
+ ;;
+ esac
+ done
+ IFS=$x_save_IFS
+
+ case "$enable_bi" in
+ ""|no|yes)
+ ;;
+ *)
+ x_flags="$x_flags -m${enable_bi}"
+ ;;
+ esac
+
+ if test -n "$x_flags"; then
+ AC_MSG_RESULT([$x_flags])
+ X_CXX_ARCH="$X_CXX_ARCH $x_flags"
+ else
+ AC_MSG_RESULT([none])
+ fi
+
+ x_flags=
+fi
+
+###############################################################################
+# disable debugging
+###############################################################################
+
+if test "$enable_debug" = "no"; then
+ changequote(<<,>>)dnl
+ if test "$GCC" = "yes"; then
+ CFLAGS=`echo "$CFLAGS" | sed -e 's/-g[^ ]*[ ]*//' -e 's/^ //' -e 's/ $//'`
+ fi
+ if test "$GXX" = "yes"; then
+ CXXFLAGS=`echo "$CXXFLAGS" | sed -e 's/-g[^ ]*[ ]*//' -e 's/^ //' -e 's/ $//'`
+ fi
+ changequote([,])dnl
+fi
+
+###############################################################################
+# disable optimizing
+###############################################################################
+
+if test "$enable_optimize" = "no"; then
+ changequote(<<,>>)dnl
+ if test "$GCC" = "yes"; then
+ CFLAGS=`echo "$CFLAGS" | sed -e 's/-O[^ ]*[ ]*//' -e 's/^ //' -e 's/ $//'`
+ fi
+ if test "$GXX" = "yes"; then
+ CXXFLAGS=`echo "$CXXFLAGS" | sed -e 's/-O[^ ]*[ ]*//' -e 's/^ //' -e 's/ $//'`
+ fi
+ changequote([,])dnl
+fi
+
+###############################################################################
+# checks for library functions
+###############################################################################
+
+###############################################################################
+# conditional compilation
+###############################################################################
+
+AM_CONDITIONAL([ADD_PLATFORM_POSIX],[test "$X_PLATFORM" = "posix"])
+AM_CONDITIONAL([ADD_PLATFORM_WIN32],[test "$X_PLATFORM" = "win32"])
+
+AM_CONDITIONAL([ADD_UTIL],[test "$enable_util" != "no"])
+AM_CONDITIONAL([ADD_MANS],[test "$X_PLATFORM" != "win32"])
+
+###############################################################################
+# declare common substitutions
+###############################################################################
+
+AC_SUBST([X_CXX_ARCH])
+AC_SUBST([X_CXX_W])
+AC_SUBST([X_CXX_D])
+AC_SUBST([X_CXX_I])
+AC_SUBST([X_MINGW_LIBS])
+
+###############################################################################
+# output files
+###############################################################################
+
+AC_CONFIG_HEADERS([libplatform/config.h])
+
+AC_CONFIG_FILES([GNUmakefile])
+AC_CONFIG_FILES([include/mp4v2/project.h])
+AC_CONFIG_FILES([project/project.m4])
+
+AC_OUTPUT
diff --git a/doc/GNUmakefile.mk b/doc/GNUmakefile.mk
new file mode 100644
index 0000000..131b03f
--- /dev/null
+++ b/doc/GNUmakefile.mk
@@ -0,0 +1,387 @@
+###############################################################################
+##
+## makefile for documentation creation
+##
+## INTPUT FILES (SOURCE/doc)
+## doc/
+## dox/ <-- generated API docs support files
+## doxygen/ <-- generated API docs support files
+## texi/ <-- hand-written project articles
+##
+## OUTPUT FILES (BUILD/doc)
+## doc/
+## doc/
+## api/
+## html/ <-- API in html format
+## xml/ <-- API in xml format
+## articles/
+## html/ <-- articles in html format
+## txt/ <-- articles in txt format
+## wiki/ <-- articles in Google Code Wiki format
+## xml/ <-- articles in xml-texinfo format
+## man/
+## man1/ <-- man-pages for utilities
+##
+###############################################################################
+
+# Conventional VPATH directive breaks too many things so we use vpath and its
+# pattern-spec feature. If new files or extensions are introduced they may need
+# to be added here.
+
+VPATH =
+
+vpath COPYING $(top_srcdir)
+vpath INSTALL $(top_srcdir)
+vpath README $(top_srcdir)
+vpath autoaux/% $(top_srcdir)
+vpath %.1 $(top_srcdir)
+vpath %.cpp $(top_srcdir)
+vpath %.h $(top_srcdir)
+vpath %.m4 $(top_srcdir)
+vpath %.tcc $(top_srcdir)
+
+###############################################################################
+
+SOURCE/ = $(top_srcdir)/
+BUILD/ = $(top_builddir)/
+
+DOC.in/ = $(SOURCE/)doc/
+DOC.out/ = $(BUILD/)doc/
+
+DOC.out.api/ = $(DOC.out/)api/
+DOC.out.articles/ = $(DOC.out/)articles/
+DOC.out.site/ = $(DOC.out/)site/
+
+###############################################################################
+
+M4 = m4
+M4.flags = -I$(BUILD/)project
+M4.cmd = $(M4) $(M4.flags) $(1) > $(2)
+M4.deps = $(BUILD/)project/project.m4
+
+ifeq ($(FOUND_HELP2MAN),yes)
+HELP2MAN = help2man
+HELP2MAN.flags = -m "$(PROJECT_name) Utilities" -N
+HELP2MAN.cmd = $(HELP2MAN) $(HELP2MAN.flags) ./$(1) -o $(2)
+else
+HELP2MAN.cmd = touch $(2)
+endif
+
+MAKEINFO.flags = -I$(DOC.in/)texi -I$(DOC.out/)texi
+MAKEINFO.flags.html = --html --no-headers --no-split
+MAKEINFO.flags.txt = --plaintext --no-headers
+MAKEINFO.flags.xml = --xml --output-indent=4
+MAKEINFO.cmd = makeinfo $(MAKEINFO.flags) $(MAKEINFO.flags.$(1)) $(2) -o $(3)
+
+HTMLCOMBINE = $(SOURCE/)project/htmlcombine.py
+HTMLCOMBINE.cmd = $(HTMLCOMBINE) --header $(1) --footer $(2) --body $(3) > $(4)
+HTMLCOMBINE.deps = $(HTMLCOMBINE)
+
+XML2WIKI = $(SOURCE/)project/xml2wiki.py
+XML2WIKI.flags = --date --toc
+XML2WIKI.cmd = $(XML2WIKI) $(XML2WIKI.flags) $(1) > $(2)
+XML2WIKI.deps = $(XML2WIKI)
+
+DOXYGEN = doxygen
+DOXYGEN.cmd = $(DOXYGEN) $(1)
+
+###############################################################################
+
+DOC.m4.out = \
+ doc/texi/base/project.texi \
+ doc/doxygen/Doxyfile \
+ doc/doxygen/header.html \
+ doc/doxygen/footer.html \
+ doc/html/header.html \
+ doc/html/footer.html
+
+DOC.man.utils = mp4art mp4file mp4subtitle mp4track
+DOC.man.out = $(DOC.man.utils:%=$(DOC.out/)man/man1/%.1)
+
+DOC.texi.articles = $(wildcard $(DOC.in/)texi/*.texi $(DOC.out/)texi/*.texi)
+
+DOC.texi.includes = \
+ doc/texi/base/project.texi \
+ $(wildcard $(DOC.in/)texi/*/*.texi $(DOC.out/)texi/*/*.texi)
+
+DOC.texi2html.out = $(DOC.texi.articles:$(DOC.in/)texi/%.texi=$(DOC.out.articles/)html/%.html)
+DOC.texi2txt.out = $(DOC.texi.articles:$(DOC.in/)texi/%.texi=$(DOC.out.articles/)txt/%.txt)
+DOC.texi2xml.out = $(DOC.texi.articles:$(DOC.in/)texi/%.texi=$(DOC.out.articles/)xml/%.xml)
+
+DOC.xml2wiki.out = $(DOC.texi2xml.out:$(DOC.out.articles/)xml/%.xml=$(DOC.out.articles/)wiki/%.wiki)
+
+DOC.api.out = $(DOC.out.api/).stamp
+
+DOC.site.out = $(DOC.out.site/).stamp
+DOC.site.out.copy = $(patsubst $(DOC.in/)html/%,$(DOC.out.site/)%, \
+ $(filter-out %.in,$(wildcard $(DOC.in/)html/*)))
+DOC.site.out.index = $(DOC.out.site/)index.html
+DOC.site.out.html = $(patsubst $(DOC.out.articles/)html/%,$(DOC.out.site/)%, \
+ $(filter-out %/Documentation.html,$(DOC.texi2html.out)))
+
+###############################################################################
+
+MKDIRS += $(dir $(DOC.m4.out))
+MKDIRS += $(DOC.out/)man/man1/
+MKDIRS += $(foreach n,html man texi txt wiki xml,$(DOC.out.articles/)$n)
+MKDIRS += $(DOC.out.api/)
+MKDIRS += $(DOC.out.site/)
+
+###############################################################################
+
+EXTRA_DIST += \
+ $(SOURCE/)vstudio9.0/include/mp4v2/project.h \
+ $(SOURCE/)vstudio9.0/mp4v2.sln \
+ $(wildcard $(SOURCE/)vstudio9.0/*/*.vcproj)
+
+###############################################################################
+
+dist-hook: $(DOC.texi2txt.out) $(DOC.man.out)
+ rm -fr $(distdir)/doc
+ $(mkdir_p) $(distdir)/doc
+ $(INSTALL_DATA) $(DOC.in/)GNUmakefile.mk $(distdir)/doc/.
+ifneq (,$(DOC.texi2txt.out))
+ $(INSTALL_DATA) $(DOC.texi2txt.out) $(distdir)/doc/.
+endif
+ifneq (,$(DOC.man.out))
+ $(mkdir_p) $(distdir)/doc/man/man1
+ $(INSTALL_DATA) $(DOC.man.out) $(distdir)/doc/man/man1
+endif
+
+distclean-local: docclean
+
+###############################################################################
+
+$(DOC.m4.out): %: %.m4 $(M4.deps) | $(dir $(DOC.m4.out))
+ $(call M4.cmd,$<,$@)
+
+###############################################################################
+
+.PHONY: articles doc
+articles: html txt xml wiki
+doc: man articles api site
+
+.PHONY: articlesclean apiclean docclean
+articlesclean: htmlclean txtclean xmlclean wikiclean
+docclean: manclean articlesclean apiclean siteclean
+
+.PHONY: man html txt xml wiki api
+man: $(DOC.man.out)
+html: $(DOC.texi2html.out)
+txt: $(DOC.texi2txt.out)
+xml: $(DOC.texi2xml.out)
+wiki: $(DOC.xml2wiki.out)
+api: $(DOC.api.out)
+site: $(DOC.site.out)
+
+.PHONY: manclean htmlclean txtclean xmlclean wikiclean apiclean
+manclean:
+ rm -f $(DOC.man.out)
+
+htmlclean:
+ rm -f $(DOC.texi2html.out)
+
+txtclean:
+ rm -f $(DOC.texi2txt.out)
+
+xmlclean:
+ rm -f $(DOC.texi2xml.out)
+
+wikiclean:
+ rm -f $(DOC.xml2wiki.out)
+
+apiclean:
+ rm -f $(DOC.api.out)
+ rm -fr $(DOC.out.api/)html/ $(DOC.out.api/)xml/
+
+siteclean:
+ rm -fr $(DOC.out.site/)
+
+###############################################################################
+
+$(DOC.man.out): | $(dir $(DOC.man.out))
+$(DOC.man.out): $(DOC.out/)man/man1/%.1: $(BUILD/)%$(EXEEXT)
+ $(call HELP2MAN.cmd,$<,$@)
+
+$(DOC.texi2html.out): $(DOC.texi.includes) | $(dir $(DOC.texi2html.out))
+$(DOC.texi2html.out): $(DOC.out.articles/)html/%.html: $(DOC.in/)texi/%.texi
+ $(call MAKEINFO.cmd,html,$<,$@)
+
+$(DOC.texi2txt.out): $(DOC.texi.includes) | $(dir $(DOC.texi2txt.out))
+$(DOC.texi2txt.out): $(DOC.out.articles/)txt/%.txt: $(DOC.in/)texi/%.texi
+ $(call MAKEINFO.cmd,txt,$<,$@)
+
+$(DOC.texi2xml.out): $(DOC.texi.includes) | $(dir $(DOC.texi2xml.out))
+$(DOC.texi2xml.out): $(DOC.out.articles/)xml/%.xml: $(DOC.in/)texi/%.texi
+ $(call MAKEINFO.cmd,xml,$<,$@)
+
+$(DOC.xml2wiki.out): $(XML2WIKI.deps) | $(dir $(DOC.xml2wiki.out))
+$(DOC.xml2wiki.out): $(DOC.out.articles/)wiki/%.wiki: $(DOC.out.articles/)xml/%.xml
+ $(call XML2WIKI.cmd,$<,$@)
+
+$(DOC.api.out): | $(dir $(DOC.api.out))
+$(DOC.api.out): $(DOC.in/)doxygen/banner.png
+$(DOC.api.out): $(DOC.in/)doxygen/project.css
+$(DOC.api.out): $(DOC.out/)doxygen/header.html
+$(DOC.api.out): $(DOC.out/)doxygen/footer.html
+$(DOC.api.out): $(DOC.out/)doxygen/Doxyfile
+ $(call DOXYGEN.cmd,$<)
+ $(INSTALL_DATA) $(DOC.in/)doxygen/banner.png $(DOC.out.api/)html/
+ touch $@
+
+###############################################################################
+
+$(DOC.site.out): | $(DOC.out.site/)articles
+$(DOC.site.out): | $(DOC.out.site/)api
+$(DOC.site.out): $(DOC.site.out.copy)
+$(DOC.site.out): $(DOC.site.out.index)
+$(DOC.site.out): $(DOC.site.out.html)
+
+$(DOC.out.site/)articles: | html $(DOC.out.site/)
+ rm -f $@
+ ln -s ../articles/html $@
+
+$(DOC.out.site/)api: | api $(DOC.out.site/)
+ rm -f $@
+ ln -s ../api/html $@
+
+$(DOC.site.out.copy): $(DOC.out.site/)%: $(DOC.in/)html/%
+ $(INSTALL_DATA) $^ $(@D)/.
+
+$(DOC.site.out.index): $(DOC.out/)html/header.html $(DOC.out/)html/footer.html
+$(DOC.site.out.index): $(HTMLCOMBINE.deps)
+$(DOC.site.out.index): $(DOC.out.articles/)html/Documentation.html
+ $(call HTMLCOMBINE.cmd,$(word 2,$^),$(word 3,$^),$<,$@)
+
+$(DOC.site.out.html): $(DOC.out/)html/header.html $(DOC.out/)html/footer.html
+$(DOC.site.out.html): $(HTMLCOMBINE.deps)
+$(DOC.site.out.html): $(DOC.out.site/)%: $(DOC.out.articles/)html/%
+ $(call HTMLCOMBINE.cmd,$(word 2,$^),$(word 3,$^),$<,$@)
+
+###############################################################################
+
+GOOGLE.out/ = $(top_builddir)/google/
+GOOGLE.repo.doc = $(PROJECT_repo_branch)
+
+google.clean:
+ rm -fr $(GOOGLE.out/)
+
+google.post: site wiki
+google.post: | $(GOOGLE.out/)
+google.post: google.rsync google.rm google.add google.propset
+
+$(GOOGLE.out/):
+ svn co --depth immediates $(PROJECT_repo_root) $(GOOGLE.out/)
+ svn update --set-depth immediates google/wiki
+ svn update --set-depth infinity google/doc/$(GOOGLE.repo.doc)
+
+google.rsync:
+ rsync -vrptPL --delete \
+ --exclude=".svn/*" --exclude=".svn" \
+ --exclude="*/.svn/*" --exclude="*/.svn" \
+ --exclude=".stamp" --exclude="*/.stamp" \
+ --exclude="*.m4" --exclude="*/*.m4" \
+ $(DOC.out.site/). $(GOOGLE.out/)doc/$(GOOGLE.repo.doc)/.
+ $(INSTALL_DATA) $(DOC.out.articles/)wiki/BuildRepository.wiki $(GOOGLE.out/)wiki/.
+ $(INSTALL_DATA) $(DOC.out.articles/)wiki/BuildSource.wiki $(GOOGLE.out/)wiki/.
+
+google.rm:
+ @files=`svn status $(GOOGLE.out/) | grep '^!' | awk '{ print $$2 }'`; \
+ if [ -n "$$files" ]; then \
+ svn rm $$files; \
+ fi
+
+google.add:
+ @files=`svn status $(GOOGLE.out/) | grep '^?' | awk '{ print $$2 }'`; \
+ if [ -n "$$files" ]; then \
+ svn add $$files; \
+ fi
+
+google.propset:
+ find $(GOOGLE.out/)doc/$(GOOGLE.repo.doc) -type f -a \( -name "*.html" -o -name "*.css" \) -print0 \
+ | xargs -0 svn propset svn:eol-style native
+ find $(GOOGLE.out/)doc/$(GOOGLE.repo.doc) -type f -a -name "*.html" -print0 \
+ | xargs -0 svn propset svn:mime-type "text/html"
+
+###############################################################################
+
+dist-hb: distdir=lib$(PACKAGE)
+dist-hb: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >lib$(PACKAGE)-$(VERSION).tar.gz
+ $(am__remove_distdir)
+
+###############################################################################
+
+## Precompiled header support is tricky given libtool's complexity and its
+## historical aversion to supporting it.
+##
+## What we do is add rules to precompile. Unfortunately, we cannot
+## automatically determine what flags libtool adds for compilation variants;
+## ie: PIC or non-PIC compilation. So instead we will hardcode the flags
+## to match. The reason for this is the precompiled-header will not be used if
+## (relevent) compilation flags differ.
+
+CXX.gch.static.flags = $(X_GCH_STATIC_FLAGS)
+CXX.gch.static.in = libplatform/impl.h src/impl.h libutil/impl.h
+CXX.gch.static.out = $(CXX.gch.static.in:%=$(BUILD/)%.gch/static)
+
+CXX.gch.shared.flags = $(X_GCH_SHARED_FLAGS)
+CXX.gch.shared.in = libplatform/impl.h src/impl.h libutil/impl.h
+CXX.gch.shared.out = $(CXX.gch.shared.in:%=$(BUILD/)%.gch/shared)
+
+CXX.gch.exe.flags = $(X_GCH_FLAGS)
+CXX.gch.exe.in = util/impl.h
+CXX.gch.exe.out = $(CXX.gch.exe.in:%=$(BUILD/)%.gch/exe)
+
+CXX.gch.static.dependents = $(libmp4v2_la_OBJECTS)
+CXX.gch.shared.dependents = $(libmp4v2_la_OBJECTS)
+
+CXX.gch.exe.dependents = \
+ $(mp4art_OBJECTS) \
+ $(mp4chaps_OBJECTS) \
+ $(mp4extract_OBJECTS) \
+ $(mp4file_OBJECTS) \
+ $(mp4info_OBJECTS) \
+ $(mp4subtitle_OBJECTS) \
+ $(mp4syncfiles_OBJECTS) \
+ $(mp4tags_OBJECTS) \
+ $(mp4track_OBJECTS) \
+ $(mp4trackdump_OBJECTS)
+
+ifeq ($(X_GCH_STATIC),1)
+$(CXX.gch.static.dependents): $(CXX.gch.static.out)
+endif
+
+ifeq ($(X_GCH_SHARED),1)
+$(CXX.gch.shared.dependents): $(CXX.gch.shared.out)
+endif
+
+ifeq ($(X_GCH),1)
+$(CXX.gch.exe.dependents): $(CXX.gch.exe.out)
+endif
+
+$(CXX.gch.static.out): | $(sort $(dir $(CXX.gch.static.out)))
+$(CXX.gch.static.out): $(BUILD/)%.gch/static: %
+ $(CXXCOMPILE) $(CXX.gch.static.flags) -c $< -o $@
+
+$(CXX.gch.shared.out): | $(sort $(dir $(CXX.gch.shared.out)))
+$(CXX.gch.shared.out): $(BUILD/)%.gch/shared: %
+ $(CXXCOMPILE) $(CXX.gch.shared.flags) -c $< -o $@
+
+$(CXX.gch.exe.out): | $(sort $(dir $(CXX.gch.exe.out)))
+$(CXX.gch.exe.out): $(BUILD/)%.gch/exe: %
+ $(CXXCOMPILE) $(CXX.gch.exe.flags) -c $< -o $@
+
+MKDIRS += $(dir $(CXX.gch.static.out))
+MKDIRS += $(dir $(CXX.gch.shared.out))
+MKDIRS += $(dir $(CXX.gch.exe.out))
+
+clean-local:
+ rm -f $(CXX.gch.static.out)
+ rm -f $(CXX.gch.shared.out)
+ rm -f $(CXX.gch.exe.out)
+
+###############################################################################
+
+$(sort $(MKDIRS)):
+ $(mkdir_p) $@
diff --git a/doc/MP4.3 b/doc/MP4.3
new file mode 100644
index 0000000..9b3378e
--- /dev/null
+++ b/doc/MP4.3
@@ -0,0 +1,47 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "DESCRIPTION"
+.LP
+The MP4 library provides an API to create and modify mp4 files as defined by ISO\-IEC:14496\-1:2001 MPEG\-4 Systems. This file format is derived from Apple's QuickTime file format that has been used as a multimedia file format in a variety of platforms and applications. It is a very powerful and extensible format that can accomodate practically any type of media.
+.LP
+The basic structure of an mp4 file is that the file is a container for one or more tracks. These tracks contain one type of media, such as audio or video. Each track has its own timeline, samples, and properties. An example of a sample is a frame of video. The file describes how to synchronize the timelines of the tracks and the aggregate properties of the tracks.
+.LP
+The MP4 library is focussed on providing an easy to use API for the mp4 file format. It has been used with an encoder, a server, a player, and a number of mp4 utilities. However, it may not be adequate for multimedia editors that wish to work directly with mp4 files. It can be used by these type of tools to export an mp4 file. (The library is open source so contributions of extensions to the library are welcome.)
+.LP
+In providing a easy to use API not all the information in the mp4 file is directly exposed via the API. To accomodate applications that need access to information not otherwise available via the API there are file and track level generic get and set property routines that use arbitary string property names. To use these routines you will need to be familar with the mp4 file specification or be willing to wade thru the output of MP4Dump() to determine what you want. See MP4GetIntegerProperty() for more details.
+.SH "INVOCATION"
+.LP
+The libary API is defined in <mp4.h> which includes all the necessary dependent include files.
+.LP
+The MP4 library can be used by either C or C++ programs. The calling convention is C, but if C++ is used then the default argument feature of that language can be used.
+.LP
+For example:
+.br
+ MP4Create("foo.mp4", 0, 0, 0); /* OK in C++ and C */
+.br
+ MP4Create("foo.mp4"); /* OK in C++, ERROR in C */
+.SH "EXAMPLES"
+See mpeg4ip/lib/mp4v2/util and mpeg4ip/lib/mp4v2/test for simple example programs that use the MP4 library.
+.LP
+In particular:
+.br
+ mp4nullcreate.cpp
+.br
+ Program that creates an empty mp4 file.
+.LP
+ mp4dump.cpp
+.br
+ Simple program to print a text version of an mp4 file
+.LP
+ mp4extract.cpp
+.br
+ Program to read each track and sample and place them in a separate file to ease inspection or recombination.
+.LP
+ mp4broadcaster.cpp
+.br
+ Program to broadcast the hinted tracks of an mp4 file using RTP.
+.LP
+ mp4nullvplayer.cpp
+.br
+ Program that reads the video track but doesn't actually render the video.
+.LP
+For more complete applications that use the MP4 library see mpeg4ip/server/mp4creator, mpeg4ip/server/mp4live, and mpeg4ip/player/src.
diff --git a/doc/MP4AddRtpESConfigurationPacket.3 b/doc/MP4AddRtpESConfigurationPacket.3
new file mode 100644
index 0000000..989febc
--- /dev/null
+++ b/doc/MP4AddRtpESConfigurationPacket.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AddRtpESConfigurationPacket\fR \- Add ES configuration information to an RTP hint
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AddRtpESConfigurationPacket\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AddRtpESConfigurationPacket\fR adds a packet to the current RTP hint that contains a copy of the elementary stream configuration information of the reference media track. Some RTP payloads require this information to be transmitted at the start of streaming or periodically during streaming.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetTrackESConfiguration(3)
diff --git a/doc/MP4AddRtpHint.3 b/doc/MP4AddRtpHint.3
new file mode 100644
index 0000000..8b505af
--- /dev/null
+++ b/doc/MP4AddRtpHint.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AddRtpHint\fR \- Add an RTP hint
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AddRtpHint\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AddRtpHint\fR creates a new hint sample for the specified hint track and enables subsequent calls to MP4AddRtpPacket() to create the RTP packets associated with this hint. After all the RTP packets for the hint have been created, MP4WriteRtpHint() should be called to write the hint to the track.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpPacket(3) MP4WriteRtpHint (3)
diff --git a/doc/MP4AddRtpImmediateData.3 b/doc/MP4AddRtpImmediateData.3
new file mode 100644
index 0000000..81cfc79
--- /dev/null
+++ b/doc/MP4AddRtpImmediateData.3
@@ -0,0 +1,42 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AddRtpImmediateData\fR \- Add immediate data to an RTP packet
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AddRtpImmediateData\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP,
+.br
+ u_int8_t* \fIpBytes\fP,
+.br
+ u_int32_t \fInumBytes\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIpBytes\fP
+Specifies a pointer to the immediate data that should be included in the current RTP packet.
+.TP
+\fInumBytes\fP
+Specifies the length in bytes of the immediate data that should be included in the current RTP packet.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AddRtpImmediateData\fR adds immediate data to the current pending RTP packet. Typically, this is used to add RTP payload specific headers to RTP packets. Note that the size of a block of immediate data is limited to 14 bytes. But multiple immediate data blocks can be added if more space is needed.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpPacket (3) MP4AddRtpImmediateData (3)
diff --git a/doc/MP4AddRtpPacket.3 b/doc/MP4AddRtpPacket.3
new file mode 100644
index 0000000..14f2600
--- /dev/null
+++ b/doc/MP4AddRtpPacket.3
@@ -0,0 +1,42 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AddRtpPacket\fR \- Add an RTP packet
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AddRtpPacket\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ bool setMBit = false,
+.br
+ int32 transmitOffset = 0
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIsetMBit\fP
+Specifies the value of the RTP packet header marker bit for this packet. The value depends on the rules of the RTP payload used for this hint track.
+.TP
+\fItransmitOffset\fP
+Specifies an offset to apply to the normal transmission time of this packet. The purpose of this offset is to allow smoothing of packet transmission over the duration of the hint.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AddRtpPacket\fR creates a new RTP packet for the currently pending RTP hint sample for the specified hint track. It also enables subsequent calls to MP4AddRtpImmediateData() and MP4AddRtpSampleData to add data to the RTP packets. After all the RTP packets for the hint have been created, MP4WriteRtpHint() should be called to write the hint to the track.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpHint(3) MP4AddRtpImmediateData (3) MP4AddRtpSampleData (3) MP4WriteRtpHint (3)
diff --git a/doc/MP4AddRtpSampleData.3 b/doc/MP4AddRtpSampleData.3
new file mode 100644
index 0000000..95642c6
--- /dev/null
+++ b/doc/MP4AddRtpSampleData.3
@@ -0,0 +1,47 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AddRtpSampleData\fR \- Add media sample data to an RTP packet
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AddRtpSampleData\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP,
+.br
+ MP4SampleId \fIsampleId\fP,
+.br
+ u_int32_t \fIdataOffset\fP,
+.br
+ u_int32_t \fIdataLength\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIsampleId\fP
+Specifies the reference media sample id from which the media data should be taken.
+.TP
+\fIdataOffset\fP
+Specifies the byte offset in the specified media sample where data should be taken from for the current RTP packet.
+.TP
+\fIdataLength\fP
+Specifies the length in bytes of the media data that should be included in the current RTP packet.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AddRtpSampleData\fR adds a reference in the current pending RTP packet to the media data in the specified media sample of the reference media track. Note this is a reference, not a copy, of the media data.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpPacket (3) MP4AddRtpImmediateData (3)
diff --git a/doc/MP4AddRtpVideoHint.3 b/doc/MP4AddRtpVideoHint.3
new file mode 100644
index 0000000..a845e88
--- /dev/null
+++ b/doc/MP4AddRtpVideoHint.3
@@ -0,0 +1,49 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AddRtpVideoHint\fR \- Add an RTP video specific hint
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AddRtpVideoHint\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ bool \fIisBFrame\fP = false,
+.br
+ u_int32_t \fItimestampOffset\fP = 0
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIisBFrame\fP
+Specifies if this hint will contain packets for a video B frame
+.TP
+\fItimestampOffset\fP
+Specifies a positive offset to add to the RTP timestamp for this hint. Caveat: the value is in the hint track timescale.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AddRtpVideoHint\fR is an extended version of MP4AddRtpHint specifically to handle MPEG video frames.
+.LP
+The isBFrame parameter allows the packets in the RTP hint to be marked as belonging to a video B frame. This can be useful to a streaming server if packets must be dropped due to system load or network congestion. No other video frames are dependent on the contents of B frames, so they are least damaging type of frames to drop.
+.LP
+The timestampOffset parameter allows an offset to be added to the RTP timestamp of the packets in the RTP hint. This is necessary for MPEG video that contains B frames since the video frames are transmitted out of order with respect to when they should be rendered. I.e I and P frames are transmitted before any B frames that depend on them. The RTP timestamp must represent the rendering time of the data in the packets hence an offset must be added.
+.LP
+Note: The timestampOffset is equivalent to the sample rendering offset of a video media track. See MP4GetSampleRenderingOffset().
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpHint(3) MP4AddRtpPacket(3) MP4WriteRtpHint (3)
diff --git a/doc/MP4AddTrackEdit.3 b/doc/MP4AddTrackEdit.3
new file mode 100644
index 0000000..a3809fd
--- /dev/null
+++ b/doc/MP4AddTrackEdit.3
@@ -0,0 +1,64 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AddTrackEdit\fR \- Add an edit segment to a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4TrackId \fBMP4AddTrackEdit\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP,
+.br
+ MP4Timestamp \fIstartTime\fP = 0,
+.br
+ MP4Duration \fIduration\fP = 0,
+.br
+ bool \fIdwell\fP = false
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the desired position in the edit list sequence for the new edit segment. If the value is MP4_INVALID_EDIT_ID, then the edit segment is added at the end of the existing edit list. Note editId's start with the value of 1, not 0.
+.TP
+\fIstartTime\fP
+Specifies the starting time of the edit segment in the track time scale.
+.TP
+\fIduration\fP
+Specifies the duration of the edit segment in the track time scale.
+.TP
+\fIdwell\fP
+If false, the track media should be played at its normal rate. If true, the media should be paused for the duration of this edit segment. This is a mechanism by which one can delay the start of a media track.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, the edit id of the new edit segment. Upon an error, MP4_INVALID_EDIT_ID.
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4AddTrackEdit\fR adds an edit segment to the track edit list.
+.LP
+The track edit list is a feature that allows creation of an alternate timeline for the track, typically cutting out segments of the full track to form an shorten, cleaned up version. The edit segments that form the edit list are a sequence of track start times and durations, they do not alter the track media in any way. I.e. no data can be lost via edit list operations.
+.LP
+To read out the editted version of the track, use MP4ReadSampleFromEditTime() instead of MP4ReadSample().
+.LP
+To export the editted version of the track to a new track, potentially in a new mp4 file, see MP4CopyTrack().
+.LP
+Note with many media encodings such as MPEG\-4, AAC, and MP3, care must be taken when choosing the edit segment start times. E.g. for video tracks a reference or key frame should be selected as the starting sample of any edit segment. For audio tracks, an audio sample start time should be used.
+
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4DeleteTrackEdit(3) MP4ReadSampleFromEditTime(3) MP4CopyTrack(3)
diff --git a/doc/MP4AppendHintTrackSdp.3 b/doc/MP4AppendHintTrackSdp.3
new file mode 100644
index 0000000..d75eeba
--- /dev/null
+++ b/doc/MP4AppendHintTrackSdp.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AppendHintTrackSdp\fR \- Add to the SDP media level description of the hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AppendHintTrackSdp\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ const char* sdpString
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIsdpString\fP
+Specifies the addition to the hint track sdp string.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AppendHintTrackSdp\fR appends the specified string to the SDP (IETF RFC 2327) media level fragment for the hint track. This is used by a streaming server to create a complete SDP description of the multimedia session represented by the file.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetHintTrackSdp(3) MP4SetHintTrackSdp(3)
diff --git a/doc/MP4AppendSessionSdp.3 b/doc/MP4AppendSessionSdp.3
new file mode 100644
index 0000000..9d6d011
--- /dev/null
+++ b/doc/MP4AppendSessionSdp.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4AppendSessionSdp\fR \- Add to the SDP session level description of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4AppendSessionSdp\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ const char* sdpString
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIsdpString\fP
+Specifies the addition to the session sdp string.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4AppendSessionSdp\fR appends the specified string to the SDP (IETF RFC 2327) session level fragment for the file. This is used by a streaming server to create a complete SDP description of the multimedia session represented by the file.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetSessionSdp(3) MP4SetSessionSdp(3)
diff --git a/doc/MP4BinaryToBase16.3 b/doc/MP4BinaryToBase16.3
new file mode 100644
index 0000000..fbe16df
--- /dev/null
+++ b/doc/MP4BinaryToBase16.3
@@ -0,0 +1,37 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4BinaryToBase16\fR \- Convert binary data to a base 16 string
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+char* \fBMP4BinaryToBase16\fR(
+.br
+ const u_int8_t* \fIpData\fP,
+.br
+ u_int32_t \fIdataSize\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIpData\fP
+Specifies the pointer to the binary data.
+.TP
+\fIdataSize\fP
+Specifies the size in bytes of the binary data.
+.SH "RETURN VALUES"
+.LP
+Upon success, a null terminated string representing the data in base 16. Upon error, NULL.
+.SH "DESCRIPTION"
+.LP
+\fBMP4BinaryToBase16\fR converts binary data to a base 16 string. This encoding maps groups of 4 bits into the character set [0\-9a\-f]. The string is in malloc'd memory, so the caller is responsible for free'ing the memory.
+.LP
+This utility is useful for generating the SDP descriptions for some RTP payloads.
+.LP
+Example:
+ 0x12, 0xAB \-> "12ab"
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4BinaryToBase64.3 b/doc/MP4BinaryToBase64.3
new file mode 100644
index 0000000..d7d29dd
--- /dev/null
+++ b/doc/MP4BinaryToBase64.3
@@ -0,0 +1,37 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4BinaryToBase64\fR \- Convert binary data to a base 64 string
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+char* \fBMP4BinaryToBase64\fR(
+.br
+ const u_int8_t* \fIpData\fP,
+.br
+ u_int32_t \fIdataSize\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIpData\fP
+Specifies the pointer to the binary data.
+.TP
+\fIdataSize\fP
+Specifies the size in bytes of the binary data.
+.SH "RETURN VALUES"
+.LP
+Upon success, a null terminated string representing the data in base 64. Upon error, NULL.
+.SH "DESCRIPTION"
+.LP
+\fBMP4BinaryToBase64\fR converts binary data to a base 64 string. This encoding maps groups of 6 bits into the character set [A\-Za\-z0\-9+/=]. The string is in malloc'd memory, so the caller is responsible for free'ing the memory.
+.LP
+This utility is useful for generating the SDP descriptions for some RTP payloads.
+.LP
+Example:
+ 0x12, 0xAB \-> "Eqs="
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4CloneTrack.3 b/doc/MP4CloneTrack.3
new file mode 100644
index 0000000..edfd672
--- /dev/null
+++ b/doc/MP4CloneTrack.3
@@ -0,0 +1,47 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4CloneTrack\fR \- Make a clone of a specified track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4TrackId \fBMP4CloneTrack\fR(
+.br
+ MP4FileHandle \fIsrcFile\fP,
+.br
+ MP4TrackId \fIsrcTrackId\fP,
+.br
+ MP4FileHandle \fIdstFile\fP = MP4_INVALID_FILE_HANDLE,
+.br
+ MP4TrackId \fIdstHintTrackReferenceTrack\fP = MP4_INVALID_TRACK_ID
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIsrcFile\fP
+Specifies the mp4 file of the source track of the operation.
+.TP
+\fIsrcTrackId\fP
+Specifies the track id of the track to be cloned.
+.TP
+\fIdstFile\fP
+Specifies the mp4 file of the new, cloned track. If the value is MP4_INVALID_FILE_HANDLE, the new track is created in the same file as the source track.
+.TP
+\fIdstHintTrackReferenceTrack\fP
+When cloning a hint track, this parameter specifies the track id of the reference track in the destination file.
+.SH "RETURN VALUES"
+.LP
+Upon success, the track id of the new track. Upon an error, MP4_INVALID_TRACK_ID.
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4CloneTrack\fR creates a new track to an mp4 file that is a copy of an existing track with respect to the track media type, and other control information.
+.LP
+Note this function does not copy the media samples of the source track to the new track. If you want to do that use MP4CopyTrack() instead.
+
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4CopyTrack(3)
diff --git a/doc/MP4ConvertFromMovieDuration.3 b/doc/MP4ConvertFromMovieDuration.3
new file mode 100644
index 0000000..9afa50b
--- /dev/null
+++ b/doc/MP4ConvertFromMovieDuration.3
@@ -0,0 +1,37 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4ConvertFromMovieDuration\fR \- Convert a duration from the movie (file) time scale to a specified time scale.
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int64_t \fBMP4ConvertFromMovieDuration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4Duration \fIduration\fP,
+.br
+ u_int32_t \fInewTimeScale\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIduration\fP
+Specifies the duration that is to be converted.
+.TP
+\fInewTimeScale\fP
+Specifies the new time scale in ticks per second to which the duration should be converted.
+.SH "RETURN VALUES"
+.LP
+Upon success, the duration in the new time scale units. Upon error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4ConvertFromMovieDuration\fR converts a duration such as the total movie (file) duration from the movie time scale to another specified time scale.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetDuration(3)
diff --git a/doc/MP4ConvertFromTrackTimestamp.3 b/doc/MP4ConvertFromTrackTimestamp.3
new file mode 100644
index 0000000..62274a8
--- /dev/null
+++ b/doc/MP4ConvertFromTrackTimestamp.3
@@ -0,0 +1,43 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4ConvertFromTrackTimestamp\fR \- Convert a timestamp from the track time scale to a specified time scale.
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int64_t \fBMP4ConvertFromTrackTimestamp\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4Timestamp \fItimestamp\fP,
+.br
+ u_int32_t \fInewTimeScale\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track from which the timestamp originates.
+.TP
+\fItimestamp\fP
+Specifies the timestamp that is to be converted.
+.TP
+\fInewTimeScale\fP
+Specifies the new time scale in ticks per second to which the timestamp should be converted.
+.SH "RETURN VALUES"
+.LP
+Upon success, the timestamp in the new time scale units. Upon error, 0xFFFFFFFFFFFFFFFF.
+.SH "DESCRIPTION"
+.LP
+\fBMP4ConvertFromTrackTimestamp\fR converts a timestamp such as a sample start time from the track time scale to another specified time scale. This can be used by a player application to map all track samples to a common time scale.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4ConvertToTrackTimestamp(3)
diff --git a/doc/MP4ConvertToTrackTimestamp.3 b/doc/MP4ConvertToTrackTimestamp.3
new file mode 100644
index 0000000..ee994e0
--- /dev/null
+++ b/doc/MP4ConvertToTrackTimestamp.3
@@ -0,0 +1,42 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4ConvertToTrackTimestamp\fR \- Convert a timestamp from a specified time scale to the track time scale.
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Timestamp \fBMP4ConvertToTrackTimestamp\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ u_int64_t \fItimestamp\fP,
+.br
+ u_int32_t \fIoldTimeScale\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track from which the duration originates.
+.TP
+\fItimestamp\fP
+Specifies the timestamp that is to be converted.
+.TP
+\fIoldTimeScale\fP
+Specifies the time scale in ticks per second in which the timestamp is currently expressed.
+.SH "RETURN VALUES"
+.LP
+Upon success, the timestamp in the track time scale units. Upon error, MP4_INVALID_TIMESTAMP.
+.SH "DESCRIPTION"
+.LP
+\fBMP4ConvertToTrackTimestamp\fR converts a timestamp such as a sample start time from the specified time scale to the track time scale.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4ConvertFromTrackTimestamp(3)
diff --git a/doc/MP4CopyTrack.3 b/doc/MP4CopyTrack.3
new file mode 100644
index 0000000..7cf29c9
--- /dev/null
+++ b/doc/MP4CopyTrack.3
@@ -0,0 +1,54 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4CopyTrack\fR \- Make a copy of a specified track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4TrackId \fBMP4CopyTrack\fR(
+.br
+ MP4FileHandle \fIsrcFile\fP,
+.br
+ MP4TrackId \fIsrcTrackId\fP,
+.br
+ MP4FileHandle \fIdstFile\fP = MP4_INVALID_FILE_HANDLE,
+.br
+ bool \fIapplyEdits\fP = false,
+.br
+ MP4TrackId \fIdstHintTrackReferenceTrack\fP = MP4_INVALID_TRACK_ID
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIsrcFile\fP
+Specifies the mp4 file of the source track of the operation.
+.TP
+\fIsrcTrackId\fP
+Specifies the track id of the track to be copied.
+.TP
+\fIdstFile\fP
+Specifies the mp4 file of the new, copied track. If the value is MP4_INVALID_FILE_HANDLE, the new track is created in the same file as the source track.
+.TP
+\fIapplyEdits\fP
+Specifies if the track edit list is to be applied during the copying of media samples. If false, then all samples are copied, if true then only those samples included by the track edit list are copied.
+.TP
+\fIdstHintTrackReferenceTrack\fP
+When cloning a hint track, this parameter specifies the track id of the reference track in the destination file.
+.SH "RETURN VALUES"
+.LP
+Upon success, the track id of the new track. Upon an error, MP4_INVALID_TRACK_ID.
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4CopyTrack\fR creates a new track to an mp4 file that is a copy of an existing track with respect to the track media type, other control information, and media samples.
+.LP
+The applyEdits parameter of this function allows for easy creation of standalone clips from a larger mp4 file. To do this use MP4AddTrackEdit() to specify the start and duration of the clip, and then use MP4CopyTrack() to export that portion of the media to a new mp4 file.
+.LP
+Note if you do not want to copy the media samples, but just want to create a track with the same type and control information of the source track use MP4CloneTrack().
+
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4CloneTrack(3) MP4AddTrackEdit(3)
diff --git a/doc/MP4DeleteTrack.3 b/doc/MP4DeleteTrack.3
new file mode 100644
index 0000000..28ba106
--- /dev/null
+++ b/doc/MP4DeleteTrack.3
@@ -0,0 +1,35 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4DeleteTrack\fR \- Delete a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4DeleteTrack\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4DeleteTrack\fR deletes the control information associated with the specified track. The trackId will become invalid if this call succeeds.
+.LP
+Note that the samples associated with this track are not deleted with this call. This can be accomplished via MP4Optimize(). The reason for this is that multiple tracks can reference the same samples so a global view must be taken when deleting them.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4DeleteTrackEdit.3 b/doc/MP4DeleteTrackEdit.3
new file mode 100644
index 0000000..3359dc4
--- /dev/null
+++ b/doc/MP4DeleteTrackEdit.3
@@ -0,0 +1,41 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4DeleteTrackEdit\fR \- Delete a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4DeleteTrackEdit\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment to be deleted.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4DeleteTrackEdit\fR deletes the specified track edit segment. Note that since editId's form a sequence, deleting an editId will cause all edit segments with editId's greater than the deleted one to be reassigned to their editId minus one.
+.LP
+Deleting an edit segment does not delete any media samples.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddTrackEdit(3)
diff --git a/doc/MP4FindTrackId.3 b/doc/MP4FindTrackId.3
new file mode 100644
index 0000000..f0eea59
--- /dev/null
+++ b/doc/MP4FindTrackId.3
@@ -0,0 +1,51 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4FindTrackId\fR \- Find a track id
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4TrackId \fBMP4FindTrackId\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ u_int16_t \fIindex\fP,
+.br
+ const char* \fItype\fP = NULL,
+.br
+ u_int8_t \fIsubType\fP = 0
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIindex\fP
+Specifies which track is desired from matching tracks.
+.TP
+\fItype\fP
+Specifies the type of track to be matched. A NULL value implies any type of track. See MP4GetTrackType() for predefined values.
+.TP
+\fIsubType\fP
+Specifies the subtype of the track to be matched. Subtypes are only defined for audio and video tracks, see MP4GetAudioTrackType() and MP4GetVideoTrackType() for predefined values. A zero value implies any subtype.
+.SH "RETURN VALUES"
+.LP
+Upon success, the track id of the specified track. Upon an error, MP4_INVALID_TRACK_ID.
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4FindTrackId\fR gets the track id associated with the index'th track of the specified track type. For example, to get the track id of the first video track:
+.LP
+ MP4FindTrackId(hFile, 0, MP4_VIDEO_TRACK_TYPE);
+.LP
+For audio and video tracks, a subtype can be specified to find a track of a particular encoding. For example, to get the track id of the first audio track encoded with MPEG\-1 audio:
+.LP
+ MP4FindTrackId(hFile, 0, MP4_AUDIO_TRACK_TYPE, MP4_MPEG1_AUDIO_TYPE);
+.LP
+Caveat: The track id's do not imply anything about the ordering of the track information within the mp4 file.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4FindTrackIndex(3)
diff --git a/doc/MP4FindTrackIndex.3 b/doc/MP4FindTrackIndex.3
new file mode 100644
index 0000000..c979250
--- /dev/null
+++ b/doc/MP4FindTrackIndex.3
@@ -0,0 +1,34 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4FindTrackIndex\fR \- Find a track index
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int16_t \fBMP4FindTrackIndex\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the index is desired.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, the track index of the specified track. Upon an error, 0xFFFF.
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4FindTrackIndex\fR gets the index of the track with the specified track id.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4FindTrackId(3)
diff --git a/doc/MP4GetAudioProfileLevel.3 b/doc/MP4GetAudioProfileLevel.3
new file mode 100644
index 0000000..eaf5a88
--- /dev/null
+++ b/doc/MP4GetAudioProfileLevel.3
@@ -0,0 +1,27 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetAudioProfileLevel\fR \- Gets the minimum MPEG\-4 audio profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetAudioProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The current audio profile/level for the file. See MP4SetAudioProfileLevel() for known values.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetAudioProfileLevel\fR returns the minumum profile/level of MPEG\-4 audio support necessary to render the contents of the file.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetAudioProfileLevel(3)
diff --git a/doc/MP4GetDuration.3 b/doc/MP4GetDuration.3
new file mode 100644
index 0000000..b39d4c5
--- /dev/null
+++ b/doc/MP4GetDuration.3
@@ -0,0 +1,29 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetDuration\fR \- Get the duration of the movie (file)
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Duration \fBMP4GetDuration\fR(
+.br
+ MP4FileHandle \fIhFile\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The duration of the movie (file) in movie (file) time scale units.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetDuration\fR returns the maximum duration of all the tracks in the specified mp4 file.
+.LP
+Caveat: the duration is the movie (file) time scale units.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTimeScale(3) MP4ConvertFromMovieDuration(3)
diff --git a/doc/MP4GetGraphicsProfileLevel.3 b/doc/MP4GetGraphicsProfileLevel.3
new file mode 100644
index 0000000..f531c66
--- /dev/null
+++ b/doc/MP4GetGraphicsProfileLevel.3
@@ -0,0 +1,27 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetGraphicsProfileLevel\fR \- Gets the minimum MPEG\-4 graphics profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetGraphicsProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The current graphics profile/level for the file. See MP4SetGraphicsProfileLevel() for known values.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetGraphicsProfileLevel\fR returns the minumum profile/level of MPEG\-4 graphics support necessary to render the contents of the file.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetGraphicsProfileLevel(3)
diff --git a/doc/MP4GetHintTrackReferenceTrackId.3 b/doc/MP4GetHintTrackReferenceTrackId.3
new file mode 100644
index 0000000..a44ae74
--- /dev/null
+++ b/doc/MP4GetHintTrackReferenceTrackId.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetHintTrackReferenceTrackId\fR \- Get the reference track id for a hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4TrackId \fBMP4GetHintTrackReferenceTrackId\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, the track id of the reference media track. Upon an error, MP4_INVALID_TRACK_ID.
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetHintTrackReferenceTrackId\fR gets the track id of the reference media track associated with the specified hint track.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddHintTrack(3)
diff --git a/doc/MP4GetHintTrackRtpPayload.3 b/doc/MP4GetHintTrackRtpPayload.3
new file mode 100644
index 0000000..03b0767
--- /dev/null
+++ b/doc/MP4GetHintTrackRtpPayload.3
@@ -0,0 +1,53 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetHintTrackRtpPayload\fR \- Get the RTP payload parameters of the hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4GetHintTrackRtpPayload\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP,
+.br
+ char** \fIppPayloadName\fP = NULL,
+.br
+ u_int8_t* \fIpPayloadNumber\fP = NULL,
+.br
+ u_int16_t* \fIpMaxPayloadSize\fP = NULL
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIppPayloadName\fP
+Specifies a pointer to the variable to receive the string RTP payload name.
+.TP
+\fIpPayloadNumber\fP
+Specifies a pointer to the variable to receive the RTP payload number.
+.TP
+\fIpMaxPayloadSize\fP
+Specifies a pointer to the variable to receive the maximum RTP payload size in bytes.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetHintTrackRtpPayload\fR gets the RTP payload parameters for the hint track. The RTP payload is the set of rules by which media samples are packed into RTP packets. This call is typically used in constructing the SDP media level description for the hint track.
+.LP
+The payloadName identifies which RTP payload is being used for the RTP packets created from the hint track. This value is sent to the receiver in the SDP description. For example, MP3 audio sent according to the rules in IETF RFC 2250 uses the name "MPA" for the RTP payload.
+.LP
+The payloadNumber is a shorter form of the payloadName. This value is associated with the payload name in the SDP description and then sent in every RTP packet. Payload numbers 1 thru 95 are statically assigned in IETF RFC 1890, numbers 96 thru 127 are dynamically assigned within a session.
+.LP
+The maxPayloadSize specifies the maximum number of bytes that should be placed in the RTP payload section of the RTP packets.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetHintTrackPayload(3)
diff --git a/doc/MP4GetHintTrackSdp.3 b/doc/MP4GetHintTrackSdp.3
new file mode 100644
index 0000000..4a84f0b
--- /dev/null
+++ b/doc/MP4GetHintTrackSdp.3
@@ -0,0 +1,34 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetHintTrackSdp\fR \- Get the SDP media level description associated with a hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+const char* \fBMP4GetHintTrackSdp\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The SDP media level description fragment associated with the hint track.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetHintTrackSdp\fR returns the SDP (IETF RFC 2327) media level fragment associated with the hint track. This is used by a streaming server to create a complete SDP description of the multimedia session represented by the file.
+.LP
+The mp4broadcaster test program provided with the MP4 library gives an example of using this call to create the complete SDP description.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetHintTrackSdp(3) MP4AppendHintTrackSdp(3) MP4GetSessionSdp(3)
diff --git a/doc/MP4GetNumberOfTracks.3 b/doc/MP4GetNumberOfTracks.3
new file mode 100644
index 0000000..2686fb0
--- /dev/null
+++ b/doc/MP4GetNumberOfTracks.3
@@ -0,0 +1,39 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetNumberOfTracks\fR \- Get the number of tracks
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int32_t \fBMP4GetNumberOfTracks\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ const char* \fItype\fP = NULL,
+.br
+ u_int8_t subType = 0
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItype\fP
+Species the type of track for which a count is desired. A NULL value implies any type of track. See MP4GetTrackType() for predefined values.
+.TP
+\fIsubType\fP
+Specifies the subtype of the tracks to be counted. Subtypes are only defined for audio and video tracks, see MP4GetAudioTrackType() and MP4GetVideoTrackType() for predefined values. A zero value implies any subtype.
+.SH "RETURN VALUES"
+.LP
+The number of tracks of the specified type and subType in the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetNumberOfTracks\fR returns how many tracks of the specified type and subtype exist in the mp4 file. This can be used to determine if an mp4 file contains a track of a given type of media, for instance audio or video. It can also be used to determine if multiple options may be available. For instance multiple audio tracks in different languages.
+.LP
+For audio and video tracks, a subtype can be specified to only count tracks of a particular encoding.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4GetODProfileLevel.3 b/doc/MP4GetODProfileLevel.3
new file mode 100644
index 0000000..ba13663
--- /dev/null
+++ b/doc/MP4GetODProfileLevel.3
@@ -0,0 +1,27 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetODProfileLevel\fR \- Gets the minimum MPEG\-4 object descriptor profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetODProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The current object descriptor profile/level for the file. See MP4SetODProfileLevel() for known values.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetODProfileLevel\fR returns the minumum profile/level of MPEG\-4 object descriptor support necessary to render the contents of the file.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetODProfileLevel(3)
diff --git a/doc/MP4GetRtpHintNumberOfPackets.3 b/doc/MP4GetRtpHintNumberOfPackets.3
new file mode 100644
index 0000000..5f5b1df
--- /dev/null
+++ b/doc/MP4GetRtpHintNumberOfPackets.3
@@ -0,0 +1,32 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetRtpHintNumberOfPackets\fR \- Get the number of packets in an RTP hint
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int16_t \fBMP4GetRtpHintNumberOfPackets\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, the number of packets in the current RTP hint. Upon an error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetRtpHintNumberOfPackets\fR returns the number of packets contained in the current RTP hint as established by a call to MP4ReadRtpHint().
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4ReadRtpHint(3)
diff --git a/doc/MP4GetRtpPacketBFrame.3 b/doc/MP4GetRtpPacketBFrame.3
new file mode 100644
index 0000000..6fb5ec3
--- /dev/null
+++ b/doc/MP4GetRtpPacketBFrame.3
@@ -0,0 +1,38 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetRtpPacketBFrame\fR \- Get the B frame flag of an RTP packet
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+int8_t \fBMP4GetRtpPacketBFrame\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP,
+.br
+ u_int16_t \fIpacketIndex\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIpacketIndex\fP
+Specifies the packet to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, the state of the B frame flag for the specified packet. Upon an error, \-1.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetRtpPacketBFrame\fR returns the state of the B Frame flag of an RTP packet. See MP4AddRtpHint for a description of this flag.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpHint(3) MP4ReadRtpPacket(3)
diff --git a/doc/MP4GetRtpPacketTransmitOffset.3 b/doc/MP4GetRtpPacketTransmitOffset.3
new file mode 100644
index 0000000..f8de7a8
--- /dev/null
+++ b/doc/MP4GetRtpPacketTransmitOffset.3
@@ -0,0 +1,38 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetRtpPacketTransmitOffset\fR \- Get the transmit offset of an RTP packet
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+int32_t \fBMP4GetRtpPacketTransmitOffset\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP,
+.br
+ u_int16_t \fIpacketIndex\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIpacketIndex\fP
+Specifies the packet to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The transmit offset for the specified packet in the hint track timescale.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetRtpPacketTransmitOffset\fR returns the transmit offset of an RTP packet. This offset may be set by some hinters to smooth out the packet transmission times and reduce network burstiness. A transmitter would need to apply this offset to the calculated transmission time based on the hint start time.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpPacket(3) MP4ReadRtpPacket(3)
diff --git a/doc/MP4GetRtpTimestampStart.3 b/doc/MP4GetRtpTimestampStart.3
new file mode 100644
index 0000000..84d1e23
--- /dev/null
+++ b/doc/MP4GetRtpTimestampStart.3
@@ -0,0 +1,38 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetRtpTimestampStart\fR \- Get the RTP start time of a hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Timestamp \fBMP4GetRtpTimestampStart\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+
+
+.SH "RETURN VALUES"
+.LP
+Upon success, the RTP start time in the RTP time scale which is identical to the hint track time scale. Upon an error, MP4_INVALID_TIMESTAMP.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetRtpTimestampStart\fR returns the RTP timestamp start of the specified hint track. Typically this is a random value that is chosen when the first RTP packet is constructed by the MP4 library. However the value can be set explicitly for the hint track and stored. Typically this is used if it is desired that timestamps start at zero.
+.LP
+An application will need this value in order to construct RTCP Sender Reports that relate the hint track time to an real time clock. The mp4broadcaster test program provided with the MP4 library gives an example of this.
+.LP
+See IETF RFC 1889 for details regarding RTP timestamps and RTCP.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetRtpTimestampStart(3)
diff --git a/doc/MP4GetSampleIdFromEditTime.3 b/doc/MP4GetSampleIdFromEditTime.3
new file mode 100644
index 0000000..4a71a3d
--- /dev/null
+++ b/doc/MP4GetSampleIdFromEditTime.3
@@ -0,0 +1,52 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetSampleIdFromEditTime\fR \- Get the sample id of a specified time in the edit list timeline
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4SampleId \fBMP4GetSampleIdFromEditTime\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4Timestamp \fIwhen\fP,
+.br
+ MP4Timestamp* \fIpStartTime\fP = NULL,
+.br
+ MP4Duration* \fIpDuration\fP = NULL
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIwhen\fP
+Specifies the time in the track time scale that is desired.
+.TP
+\fIpStartTime\fP
+If non\-NULL, pointer to variable that will receive the starting timestamp for this sample. Caveat: The timestamp is in the track edit list timescale.
+.TP
+\fIpDuration\fP
+If non\-NULL, pointer to variable that will receive the duration for this sample in the edit list timeline. Caveat: The duration is in the track timescale units.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, the sample id that occurs at the specified time. Upon an error, MP4_INVALID_SAMPLE_ID.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetSampleIdFromEditTime\fR returns the sample id of the track sample in which the specified time occurs in the edit list timeline.
+.LP
+The specified time should be in the track time scale. See MP4ConvertToTrackTimestamp() for how to map a time value to this time scale.
+.LP
+Since the edit list can cause the sample start time and duration to be different that it in the standard track timeline, it is strongly advised that the caller retrieve the new sample start time and duration via this function.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetSampleIdFromTime(3)
diff --git a/doc/MP4GetSceneProfileLevel.3 b/doc/MP4GetSceneProfileLevel.3
new file mode 100644
index 0000000..92d8cbc
--- /dev/null
+++ b/doc/MP4GetSceneProfileLevel.3
@@ -0,0 +1,27 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetSceneProfileLevel\fR \- Gets the minimum MPEG\-4 scene graph profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetSceneProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The current scene graph profile/level for the file. See MP4SetSceneProfileLevel() for known values.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetSceneProfileLevel\fR returns the minumum profile/level of MPEG\-4 scene graph support necessary to render the contents of the file.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetSceneProfileLevel(3)
diff --git a/doc/MP4GetSessionSdp.3 b/doc/MP4GetSessionSdp.3
new file mode 100644
index 0000000..e92c9f5
--- /dev/null
+++ b/doc/MP4GetSessionSdp.3
@@ -0,0 +1,29 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetSessionSdp\fR \- Get the SDP session level description of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+const char* \fBMP4GetSessionSdp\fR(
+.br
+ MP4FileHandle \fIhFile\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The SDP session level description fragment of the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetSessionSdp\fR returns the SDP (IETF RFC 2327) session level fragment for the file. This is used by a streaming server to create a complete SDP description of the multimedia session represented by the file.
+.LP
+The mp4broadcaster test program provided with the MP4 library gives an example of using this call to create the complete SDP description.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetSessionSdp(3) MP4AppendSessionSdp(3) MP4GetHintTrackSdp(3)
diff --git a/doc/MP4GetTrackAudioMpeg4Type.3 b/doc/MP4GetTrackAudioMpeg4Type.3
new file mode 100644
index 0000000..77c2911
--- /dev/null
+++ b/doc/MP4GetTrackAudioMpeg4Type.3
@@ -0,0 +1,83 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackAudioMpeg4Type\fR \- Get the encoding type of an MPEG\-4 audio track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetTrackAudioMpeg4Type\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the MPEG\-4 audio type is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the MPEG\-4 audio type of the track. Upon error, MP4_MPEG4_INVALID_AUDIO_TYPE is returned.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackAudioMpeg4Type\fR returns the MPEG\-4 encoding type of the specified MPEG\-4 audio track in the mp4 file. If an mp4 audio track has type MP4_MPEG4_AUDIO_TYPE, this call can be used to determine which specific MPEG\-4 audio encoding is contained in the track. (Note: This information is retrieved from the audio track ES configuration.)
+.LP
+Known audio encoding types are:
+.LP
+MP4_MPEG4_AAC_MAIN_AUDIO_TYPE
+.br
+ MPEG\-4 AAC Main profile
+.LP
+MP4_MPEG4_AAC_LC_AUDIO_TYPE
+.br
+ MPEG\-4 AAC Low Complexity profile
+.LP
+MP4_MPEG4_AAC_SSR_AUDIO_TYPE
+.br
+ MPEG\-4 AAC SSR profile
+.LP
+MP4_MPEG4_AAC_LTP_AUDIO_TYPE
+.br
+ MPEG\-4 AAC Long Term Prediction profile
+.LP
+MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE
+.br
+ MPEG\-4 AAC Scalable
+.LP
+MP4_MPEG4_CELP_AUDIO_TYPE
+.br
+ MPEG\-4 CELP
+.LP
+MP4_MPEG4_HVXC_AUDIO_TYPE
+.br
+ MPEG\-4 HVXC
+.LP
+MP4_MPEG4_TTSI_AUDIO_TYPE
+.br
+ MPEG\-4 Text To Speech
+.LP
+MP4_MPEG4_MAIN_SYNTHETIC_AUDIO_TYPE
+.br
+ MPEG\-4 Main Synthetic profile
+.LP
+MP4_MPEG4_WAVETABLE_AUDIO_TYPE
+.br
+ MPEG\-4 Wavetable Synthesis profile
+.LP
+MP4_MPEG4_MIDI_AUDIO_TYPE
+.br
+ MPEG\-4 MIDI profile
+.LP
+MP4_MPEG4_ALGORITHMIC_FX_AUDIO_TYPE
+.br
+ MPEG\-4 Algorithmic Synthesis and Audio FX profile
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTrackAudioType(3)
diff --git a/doc/MP4GetTrackAudioType.3 b/doc/MP4GetTrackAudioType.3
new file mode 100644
index 0000000..d545ebb
--- /dev/null
+++ b/doc/MP4GetTrackAudioType.3
@@ -0,0 +1,64 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackAudioType\fR \- Get the encoding type of an audio track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetTrackAudioType\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the audio type is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the audio type of the track. Upon error, MP4_INVALID_AUDIO_TYPE is returned.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackAudioType\fR returns the encoding type of the specified audio track in the mp4 file.
+.LP
+Known audio encoding types are:
+.LP
+MP4_MPEG1_AUDIO_TYPE
+.br
+ MPEG\-1 Audio Layers I, II, & III
+.LP
+MP4_MPEG2_AUDIO_TYPE
+.br
+ MPEG\-2 low bitrate extensions to MPEG\-1 Audio
+.br
+ MP4_MP3_AUDIO_TYPE is an alias for this value
+.LP
+MP4_MPEG2_AAC_MAIN_AUDIO_TYPE
+.br
+ MPEG\-2 AAC Main profile
+.LP
+MP4_MPEG2_AAC_LC_AUDIO_TYPE
+.br
+ MPEG\-2 AAC Low Complexity profile
+.LP
+MP4_MPEG2_AAC_SSR_AUDIO_TYPE
+.br
+ MPEG\-2 AAC SSR profile
+.LP
+MP4_MPEG4_AUDIO_TYPE
+.br
+ MPEG\-4 Audio, includes MPEG\-4 extensions to AAC
+.LP
+MP4_PRIVATE_AUDIO_TYPE
+.br
+ User private type
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddAudioTrack(3)
diff --git a/doc/MP4GetTrackBitRate.3 b/doc/MP4GetTrackBitRate.3
new file mode 100644
index 0000000..1ca6a3b
--- /dev/null
+++ b/doc/MP4GetTrackBitRate.3
@@ -0,0 +1,34 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackBitRate\fR \- Get the average bit rate in bits per second of the specified track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int32_t \fBMP4GetTrackBitRate\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the bit rate is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the average bit rate in bits per second of the track. Upon an error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackBitRate\fR returns the average bit rate in bits per second in the specified track in the mp4 file.
+.LP
+Note: hint tracks will not return their bit rate via this mechanism.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4GetTrackDuration.3 b/doc/MP4GetTrackDuration.3
new file mode 100644
index 0000000..4992968
--- /dev/null
+++ b/doc/MP4GetTrackDuration.3
@@ -0,0 +1,34 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackDuration\fR \- Get the duration of a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Duration \fBMP4GetTrackDuration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the duration is desired.
+.SH "RETURN VALUES"
+.LP
+The duration in track time scale units of the track in the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackDuration\fR returns the total duration of all the samples in the specified track in the mp4 file.
+.LP
+Caveat: The value is in units of the track time scale.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4GetTrackESConfiguration.3 b/doc/MP4GetTrackESConfiguration.3
new file mode 100644
index 0000000..a6746cb
--- /dev/null
+++ b/doc/MP4GetTrackESConfiguration.3
@@ -0,0 +1,44 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackESConfiguration\fR \- Get the elementary stream (ES) configuration of a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+void \fBMP4GetTrackESConfiguration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+ u_int8_t** \fIppConfig\fP,
+.br
+ u_int32_t* \fIpConfigSize\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the ES configuration is desired.
+.TP
+\fIppConfig\fP
+Specifies a pointer to a pointer variable that will be given the address of the configuration information.
+.TP
+\fIpConfigSize\fP
+Specifies a pointer to a variable to hold the size of the ES configuration information.
+.SH "RETURN VALUES"
+.LP
+Upon success, *ppConfig will point to a malloc'd block of memory with the ES configuration, and *pConfigSize will indicated the number of bytes of the ES configuration. Upon error, *ppConfig will be NULL, and *pConfigSize will be 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackESConfiguration\fR returns the elementary stream (ES) configuration of the specified track in the mp4 file. This information is codec specific and contains the configuration necessary for the given codec to decode the samples in the track.
+.LP
+Caveat: the returned block of memory has been malloc'd. The caller may safely modify the value without effecting the library, but the caller takes responsiblity for free'ing the memory.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4GetTrackEditDuration.3 b/doc/MP4GetTrackEditDuration.3
new file mode 100644
index 0000000..ab86c55
--- /dev/null
+++ b/doc/MP4GetTrackEditDuration.3
@@ -0,0 +1,39 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackEditDuration\fR \- Get the duration of a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Duration \fBMP4GetTrackEditDuration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment for which the duration is desired.
+.SH "RETURN VALUES"
+.LP
+The duration of the edit segment in track time scale units of the track in the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackEditDuration\fR returns the duration of the specified track edit segment.
+.LP
+Caveat: The value is in units of the track time scale.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetTrackEditDuration(3)
diff --git a/doc/MP4GetTrackEditDwell.3 b/doc/MP4GetTrackEditDwell.3
new file mode 100644
index 0000000..b1505e1
--- /dev/null
+++ b/doc/MP4GetTrackEditDwell.3
@@ -0,0 +1,37 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackEditDwell\fR \- Get the dwell value of a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Duration \fBMP4GetTrackEditDwell\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment for which the dwell value is desired.
+.SH "RETURN VALUES"
+.LP
+The dwell value of the edit segment of the track in the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackEditDwell\fR returns the dwell value of the specified track edit segment. A value of true (1) indicates that during this edit segment the media will be paused; a value of false (0) indicates that during this edit segment the media will be played at its normal rate.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetTrackEditDwell(3)
diff --git a/doc/MP4GetTrackEditMediaStart.3 b/doc/MP4GetTrackEditMediaStart.3
new file mode 100644
index 0000000..7cb868f
--- /dev/null
+++ b/doc/MP4GetTrackEditMediaStart.3
@@ -0,0 +1,48 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackEditMediaStart\fR \- Get the media start time of a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Timestamp \fBMP4GetTrackEditMediaStart\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment for which the media start time is desired.
+.SH "RETURN VALUES"
+.LP
+The media start time of the edit segment in track time scale units of the track in the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackEditMediaStart\fR returns the media start time of the of the specified track edit segment.
+.LP
+Caveat: The value is in units of the track time scale.
+.LP
+Note that this differs from the edit segment start time, MP4GetTrackEditStart(). For example:
+.LP
+EditId Start MediaStart Duration
+1 0 15 30
+.br
+2 30 120 20
+.br
+3 50 3000 10
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetTrackEditMediaStart(3)
diff --git a/doc/MP4GetTrackEditStart.3 b/doc/MP4GetTrackEditStart.3
new file mode 100644
index 0000000..1e5a789
--- /dev/null
+++ b/doc/MP4GetTrackEditStart.3
@@ -0,0 +1,48 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackEditStart\fR \- Get the start time of a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Timestamp \fBMP4GetTrackEditStart\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment for which the start time is desired.
+.SH "RETURN VALUES"
+.LP
+The start time of the edit segment in track time scale units of the track in the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackEditStart\fR returns the start time of the of the specified track edit segment in the timeline of the track edit list.
+.LP
+Caveat: The value is in units of the track time scale.
+.LP
+Note that this differs from the edit segment media start time, MP4GetTrackEditMediaStart(). For example:
+.LP
+EditId Start MediaStart Duration
+1 0 15 30
+.br
+2 30 120 20
+.br
+3 50 3000 10
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetTrackEditStart(3)
diff --git a/doc/MP4GetTrackEditTotalDuration.3 b/doc/MP4GetTrackEditTotalDuration.3
new file mode 100644
index 0000000..701c0d5
--- /dev/null
+++ b/doc/MP4GetTrackEditTotalDuration.3
@@ -0,0 +1,39 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackEditTotalDuration\fR \- Get the total duration of a sequence of track edit segments
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Duration \fBMP4GetTrackEditTotalDuration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP = MP4_INVALID_EDIT_ID
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment for which the total duration is desired. A value of MP4_INVALID_EDIT_ID specifies that all edit segments should be included.
+.SH "RETURN VALUES"
+.LP
+The total duration of the edit segment sequence in track time scale units of the track in the mp4 file.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackEditTotalDuration\fR returns the total duration of the specified sequence of track edit segments from the first edit segment up to and including the specified edit segment. If the edit id value is MP4_INVALID_EDIT_ID, then the total duration of all of the edit segments is returned.
+.LP
+Caveat: The value is in units of the track time scale.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTrackEditDuration(3)
diff --git a/doc/MP4GetTrackFixedSampleDuration.3 b/doc/MP4GetTrackFixedSampleDuration.3
new file mode 100644
index 0000000..f5e42c2
--- /dev/null
+++ b/doc/MP4GetTrackFixedSampleDuration.3
@@ -0,0 +1,32 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackFixedSampleDuration\fR \- Get the fixed duration of samples in a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+MP4Duration \fBMP4GetTrackFixedSampleDuration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, the number of fixed duration of the samples in the track in track time scale units. Upon an error, MP4_INVALID_DURATION.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackFixedSampleDuration\fR returns the duration of samples in the specified track in the mp4 file, if this value is fixed for all samples. This is typically the case for audio tracks and video tracks. If the track samples have variable duration, then MP4_INVALID_DURATION is returned.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4GetTrackNumberOfEdits.3 b/doc/MP4GetTrackNumberOfEdits.3
new file mode 100644
index 0000000..1782b9f
--- /dev/null
+++ b/doc/MP4GetTrackNumberOfEdits.3
@@ -0,0 +1,32 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackNumberOfEdits\fR \- Get the number of edit segments for a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int32_t \fBMP4GetTrackNumberOfEdits\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the number of edit segments is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the number of edit segments for the track. Upon an error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackNumberOfEdits\fR returns the number of edit segments in the specified track in the mp4 file. Edit id's are the consecutive sequence of numbers from 1 to the total number of edit segments, i.e. 1\-based indexing, not 0\-based indexing.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddTrackEdit(3) MP4DeleteTrackEdit(3)
diff --git a/doc/MP4GetTrackNumberOfSamples.3 b/doc/MP4GetTrackNumberOfSamples.3
new file mode 100644
index 0000000..093d5b2
--- /dev/null
+++ b/doc/MP4GetTrackNumberOfSamples.3
@@ -0,0 +1,32 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackNumberOfSamples\fR \- Get the number of samples in a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int32_t \fBMP4GetTrackNumberOfSamples\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the number of samples is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the number of samples in the track. Upon an error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackNumberOfSamples\fR returns the number of samples in the specified track in the mp4 file. Sample id's are the consecutive sequence of numbers from 1 to the total number of samples, i.e. 1\-based indexing, not 0\-based indexing.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4GetTrackVideoFrameRate.3 b/doc/MP4GetTrackVideoFrameRate.3
new file mode 100644
index 0000000..0893fdb
--- /dev/null
+++ b/doc/MP4GetTrackVideoFrameRate.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackVideoFrameRate\fR \- Get the video frame rate of the specified video track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+float \fBMP4GetTrackVideoFrameRate\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the video frame rate is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the number of video frames per second of the track. Upon an error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackVideoFrameRate\fR returns the frame rate of the video in the specified track in the mp4 file. If the video is variable rate, the average frame rate is returned.
+
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4GetTrackVideoHeight.3 b/doc/MP4GetTrackVideoHeight.3
new file mode 100644
index 0000000..448cfce
--- /dev/null
+++ b/doc/MP4GetTrackVideoHeight.3
@@ -0,0 +1,35 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackVideoHeight\fR \- Get the video height in pixels of the specified video track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int16_t \fBMP4GetTrackVideoHeight\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the video height is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the number of pixels of the video height in the track. Upon an error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackVideoWidth\fR returns the height of the video in pixels in the specified track in the mp4 file.
+.LP
+Caveat: Not all mp4 implementations set this value accurately. The mp4 specification states that the authoritative values are contained in the track ES configuration which is video encoding specific, and hence not interpretable by the mp4 library.
+If the value of 240 is returned, care should be taken to verify the accuracy of this value since this is the default value in the mp4 specification.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTrackVideoWidth(3) MP4GetTrackESConfiguration(3)
diff --git a/doc/MP4GetTrackVideoType.3 b/doc/MP4GetTrackVideoType.3
new file mode 100644
index 0000000..cf01e4b
--- /dev/null
+++ b/doc/MP4GetTrackVideoType.3
@@ -0,0 +1,74 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackVideoType\fR \- Get the encoding type of a video track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetTrackVideoType\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the video type is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the video type of the track. Upon error, MP4_INVALID_VIDEO_TYPE is returned.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackVideoType\fR returns the encoding type of the specified video track in the mp4 file.
+.LP
+Known video encoding types are:
+.LP
+MP4_MPEG1_VIDEO_TYPE
+.br
+ MPEG\-1 Video
+.LP
+MP4_MPEG2_SIMPLE_VIDEO_TYPE
+.br
+ MPEG\-2 Simple Profile Video
+.LP
+MP4_MPEG2_MAIN_VIDEO_TYPE
+.br
+ MPEG\-2 Main Profile Video (Broadcast/DVD)
+.LP
+MP4_MPEG2_SNR_VIDEO_TYPE
+.br
+ MPEG\-2 SNR Profile Video
+.LP
+MP4_MPEG2_SPATIAL_VIDEO_TYPE
+.br
+ MPEG\-2 Spatial Scalability Profile Video
+.LP
+MP4_MPEG2_HIGH_VIDEO_TYPE
+.br
+ MPEG\-2 High Profile Video (HDTV)
+.LP
+MP4_MPEG2_442_VIDEO_TYPE
+.br
+ MPEG\-2 442 Profile Video (Studio)
+.LP
+MP4_MPEG4_VIDEO_TYPE
+.br
+ MPEG\-4 Video
+.LP
+MP4_JPEG_VIDEO_TYPE
+.br
+ JPEG stills or motion JPEG
+.LP
+MP4_PRIVATE_VIDEO_TYPE
+.br
+ User private type
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddVideoTrack(3)
diff --git a/doc/MP4GetTrackVideoWidth.3 b/doc/MP4GetTrackVideoWidth.3
new file mode 100644
index 0000000..df095fc
--- /dev/null
+++ b/doc/MP4GetTrackVideoWidth.3
@@ -0,0 +1,35 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetTrackVideoWidth\fR \- Get the video width in pixels of the specified video track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int16_t \fBMP4GetTrackVideoWidth\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track for which the video width is desired.
+.SH "RETURN VALUES"
+.LP
+Upon success, the number of pixels of the video width in the track. Upon an error, 0.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetTrackVideoWidth\fR returns the width of the video in pixels in the specified track in the mp4 file.
+.LP
+Caveat: Not all mp4 implementations set this value accurately. The mp4 specification states that the authoritative values are contained in the track ES configuration which is video encoding specific, and hence not interpretable by the mp4 library.
+If the value of 320 is returned, care should be taken to verify the accuracy of this value since this is the default value in the mp4 specification.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTrackVideoHeight(3) MP4GetTrackESConfiguration(3)
diff --git a/doc/MP4GetVideoProfileLevel.3 b/doc/MP4GetVideoProfileLevel.3
new file mode 100644
index 0000000..427ce9c
--- /dev/null
+++ b/doc/MP4GetVideoProfileLevel.3
@@ -0,0 +1,27 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4GetVideoProfileLevel\fR \- Gets the minimum MPEG\-4 video profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+u_int8_t \fBMP4GetVideoProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+The current video profile/level for the file. See MP4SetVideoProfileLevel() for known values.
+.SH "DESCRIPTION"
+.LP
+\fBMP4GetVideoProfileLevel\fR returns the minumum profile/level of MPEG\-4 video support necessary to render the contents of the file.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4SetVideoProfileLevel(3)
diff --git a/doc/MP4MakeIsmaCompliant.3 b/doc/MP4MakeIsmaCompliant.3
new file mode 100644
index 0000000..c2117cf
--- /dev/null
+++ b/doc/MP4MakeIsmaCompliant.3
@@ -0,0 +1,36 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4MakeIsmaCompliant\fR \- Add ISMA compliant OD and Scene tracks
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4MakeIsmaCompliant\fR(
+.br
+ const char* \fIfileName\fP,
+.br
+ u_int32_t \fIverbosity\fP = 0
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIfileName\fP
+Specifies the path name of the file to be modified.
+.TP
+\fIverbosity\fP
+Specifies a bitmask of diagnostic details the library should print to stdout during its functioning. See MP4SetVerbosity() for values.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4MakeIsmaCompliant\fR modifies an mp4 file so that it complies with the minimal MPEG\-4 Systems requirements defined by the Internet Streaming Media Alliance (ISMA, http://www.isma.tv)
+.LP
+This involves creating an OD and Scene track, and using them to describe a simple scene of one audio, or one video, or one of each. An SDP version of this information is also added to the mp4 file.
+.LP
+Caveat: whether the file is truly ISMA compliant also depends on the contents of the media and hint tracks. This function does not guarantee that these tracks are compliant.
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4ReadRtpHint.3 b/doc/MP4ReadRtpHint.3
new file mode 100644
index 0000000..2a23923
--- /dev/null
+++ b/doc/MP4ReadRtpHint.3
@@ -0,0 +1,44 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4ReadRtpHint\fR \- Read an RTP hint
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4ReadRtpHint\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4SampleId \fIsampleId\fP,
+.br
+ u_int16_t* \fIpNumPackets\fP = NULL
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIsampleId\fP
+Specifies which hint sample is to be read. Caveat: the first sample has id 1 not 0.
+.TP
+\fIpNumPackets\fP
+Pointer to variable that will be hold the number of packets in the hint.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4ReadRtpHint\fR reads the specified hint sample from the specified hint track and enables subsequent calls to MP4ReadRtpPacket() to read the individual RTP packets associated with this hint. If desired, the number of RTP packets associated with this hint is returned.
+.LP
+Note that a hint track sample is just like any other track sample. I.e MP4ReadSample(), MP4GetSampleSize(), MP4GetSampleTime(), etc. are all valid. The RTP specific functions are provided to interpret the information contain in the hint track samples that give instructions on how to form the actual RTP packets.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4ReadRtpPacket(3)
diff --git a/doc/MP4ReadRtpPacket.3 b/doc/MP4ReadRtpPacket.3
new file mode 100644
index 0000000..80b42ff
--- /dev/null
+++ b/doc/MP4ReadRtpPacket.3
@@ -0,0 +1,75 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4ReadRtpPacket\fR \- Read an RTP packet
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4ReadRtpPacket\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ u_int16_t \fIpacketIndex\fP,
+.br
+ u_int8_t** \fIppBytes\fP,
+.br
+ u_int32_t* \fIpNumBytes\fP,
+.br
+ u_int32_t \fIssrc\fP = 0,
+.br
+ bool includeHeader = true,
+.br
+ bool includePayload = true
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIpacketIndex\fP
+Specifies which packet is to be read. Valid values range from zero to the number of packets in this hint minus one.
+.TP
+\fIpNumPackets\fP
+Pointer to variable that will be hold the number of packets in the hint.
+.TP
+\fIppBytes\fP
+Pointer to the pointer to the packet data. See DESCRIPTION for details on this argument.
+.TP
+\fIpNumBytes\fP
+Pointer to variable that will be hold the size in bytes of the packet.
+.TP
+\fIssrc\fP
+Specifies the RTP SSRC to be used when constructing the RTP packet header.
+.TP
+\fIincludeHeader\fP
+Specifies whether the library should include the standard 12 byte RTP header to the returned packet. The header is constructed from the information in the hint sample and the specified ssrc.
+.TP
+\fIincludePayload\fP
+Specifies whether the library should include the packet payload (RTP payload header and media data) in the returned packet.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4ReadRtpPacket\fR reads the specified packet from the current hint sample, as previously read by MP4ReadRtpHint().
+.LP
+The argument, ppBytes, allows for two possible approaches for buffering:
+.LP
+If the calling application wishes to handle its own buffering it can set *ppBytes to the buffer it wishes to use. The calling application is responsible for ensuring that the buffer is large enough to hold the packet. This can be done by using MP4GetRtpPayload() to retrieve the maximum packet payload size and hence how large the receiving buffer must be. Caveat: the value returned by MP4GetRtpPayload is the maxiumum payload size, if the RTP packet header is going to be included by the library this value should be incremented by 12.
+.LP
+If the value of *ppBytes is NULL, then an appropriately sized buffer is automatically malloc'ed for the sample data and *ppBytes set to this pointer. The calling application is responsible for free'ing this memory.
+.LP
+The application is expected to provide the value of the RTP SSRC identifier which uniquely identifies the originator of the media stream. For most applications, a single random value can be provided. The value should be the same for all packets for the duration of the RTP transmission. If the parameter "includeHeader" is false, then this value has no effect.
+.LP
+By default the library constructs the standard 12 byte RTP header from the information in the hint sample, and the specified SSRC. It then concatenates the RTP header with the packet payload, that is the RTP payload specific header and the media data for the packet. The "includeHeader" and "includePayload" parameters allow control over these steps, so that either just the packet payloads or just the RTP headers can be returned. A potential use of this feature is if the calling application wishes to construct an extended RTP header with non\-standard options.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4ReadRtpHint(3)
diff --git a/doc/MP4ReadSampleFromEditTime.3 b/doc/MP4ReadSampleFromEditTime.3
new file mode 100644
index 0000000..e930b91
--- /dev/null
+++ b/doc/MP4ReadSampleFromEditTime.3
@@ -0,0 +1,81 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4ReadSampleFromEditTime\fR \- Read a track sample based on a specified edit list time
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4ReadSampleFromEditTime\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4Timestamp \fIeditWhen\fP,
+.br
+ u_int8_t** \fIppBytes\fP,
+.br
+ u_int32_t* \fIpNumBytes\fP,
+.br
+ MP4Timestamp* \fIpStartTime\fP = NULL,
+.br
+ MP4Duration* \fIpDuration\fP = NULL,
+.br
+ MP4Duration* \fIpRenderingOffset\fP = NULL,
+.br
+ bool \fIpIsSyncSample\fP = NULL
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditWhen\fP
+Specifies which sample is to be read based on a time in the edit list timeline. See MP4GetSampleIdFromEditTime() for details.
+.TP
+\fIppBytes\fP
+Pointer to the pointer to the sample data. See DESCRIPTION for details on this argument.
+.TP
+\fIpNumBytes\fP
+Pointer to variable that will be hold the size in bytes of the sample.
+.TP
+\fIpStartTime\fP
+If non\-NULL, pointer to variable that will receive the starting timestamp for this sample. Caveat: The timestamp is in the track timescale.
+.TP
+\fIpDuration\fP
+If non\-NULL, pointer to variable that will receive the duration for this sample. Caveat: The duration is in the track timescale units.
+.TP
+\fIpRenderingOffset\fP
+If non\-NULL, pointer to variable that will receive the rendering offset for this sample. Currently the only media type that needs this feature is MPEG video. Caveat: The offset is in the track timescale units.
+.TP
+\fIpIsSyncSample\fP
+If non\-NULL, pointer to variable that will receive the state of the sync/random access flag for this sample.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4ReadSampleFromEditTime\fR reads the sample corresponding to the time on the track edit list timeline from the specified track. Typically this sample is then decoded in a codec dependent fashion and rendered in an appropriate fashion.
+.LP
+The argument, ppBytes, allows for two possible approaches for buffering:
+.LP
+If the calling application wishes to handle its own buffering it can set *ppBytes to the buffer it wishes to use. The calling application is responsible for ensuring that the buffer is large enough to hold the sample. This can be done by using either MP4GetSampleSize() or MP4GetTrackMaxSampleSize() to determine before\-hand how large the receiving buffer must be.
+.LP
+If the value of *ppBytes is NULL, then an appropriately sized buffer is automatically malloc'ed for the sample data and *ppBytes set to this pointer. The calling application is responsible for free'ing this memory.
+
+The last four arguments are pointers to variables that can receive optional sample information.
+.LP
+Typically for audio none of these are needed. MPEG audio such as MP3 or AAC has a fixed sample duration and every sample can be accessed at random.
+.LP
+For video, all of these optional values could be needed. MPEG video can be encoded at a variable frame rate, with only occasional random access points, and with "B frames" which cause the rendering (display) order of the video frames to differ from the storage/decoding order.
+.LP
+Other media types fall between these two extremes.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4ReadSample(3) MP4GetSampleIdFromEditTime(3) MP4ReadSampleFromTime(3)
diff --git a/doc/MP4SetAudioProfileLevel.3 b/doc/MP4SetAudioProfileLevel.3
new file mode 100644
index 0000000..9b03409
--- /dev/null
+++ b/doc/MP4SetAudioProfileLevel.3
@@ -0,0 +1,67 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetAudioProfileLevel\fR \- Sets the minimum MPEG\-4 audio profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetAudioProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ u_int8_t \fIprofileLevel\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetAudioProfileLevel\fR sets the minumum profile/level of MPEG\-4 audio support necessary to render the contents of the file.
+.LP
+ISO/IEC 14496\-1:2001 MPEG\-4 Systems defines the following values:
+.br
+ 0x00 Reserved
+.br
+ 0x01 Main Profile @ Level 1
+.br
+ 0x02 Main Profile @ Level 2
+.br
+ 0x03 Main Profile @ Level 3
+.br
+ 0x04 Main Profile @ Level 4
+.br
+ 0x05 Scalable Profile @ Level 1
+.br
+ 0x06 Scalable Profile @ Level 2
+.br
+ 0x07 Scalable Profile @ Level 3
+.br
+ 0x08 Scalable Profile @ Level 4
+.br
+ 0x09 Speech Profile @ Level 1
+.br
+ 0x0A Speech Profile @ Level 2
+.br
+ 0x0B Synthesis Profile @ Level 1
+.br
+ 0x0C Synthesis Profile @ Level 2
+.br
+ 0x0D Synthesis Profile @ Level 3
+.br
+ 0x0E\-0x7F Reserved
+.br
+ 0x80\-0xFD User private
+.br
+ 0xFE No audio profile specified
+.br
+ 0xFF No audio required
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetAudioProfileLevel(3)
diff --git a/doc/MP4SetGraphicsProfileLevel.3 b/doc/MP4SetGraphicsProfileLevel.3
new file mode 100644
index 0000000..984aaa6
--- /dev/null
+++ b/doc/MP4SetGraphicsProfileLevel.3
@@ -0,0 +1,43 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetGraphicsProfileLevel\fR \- Sets the minimum MPEG\-4 graphics profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetGraphicsProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ u_int8_t \fIprofileLevel\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetGraphicsProfileLevel\fR sets the minumum profile/level of MPEG\-4 graphics support necessary to render the contents of the file.
+.LP
+ISO/IEC 14496\-1:2001 MPEG\-4 Systems defines the following values:
+.br
+ 0x00 Reserved
+.br
+ 0x01 Simple 2D Profile @ Level 1
+.br
+ 0x02\-0x7F Reserved
+.br
+ 0x80\-0xFD User private
+.br
+ 0xFE No audio profile specified
+.br
+ 0xFF No audio required
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetGraphicsProfileLevel(3)
diff --git a/doc/MP4SetHintTrackRtpPayload.3 b/doc/MP4SetHintTrackRtpPayload.3
new file mode 100644
index 0000000..a7764ee
--- /dev/null
+++ b/doc/MP4SetHintTrackRtpPayload.3
@@ -0,0 +1,67 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetHintTrackRtpPayload\fR \- Set the RTP payload parameters of the hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetHintTrackRtpPayload\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP,
+.br
+ const char* \fIpPayloadName\fP,
+.br
+ u_int8_t* \fIpPayloadNumber\fP,
+.br
+ u_int16_t \fImaxPayloadSize\fP = 0
+.br
+ bool \fIinclude_rtp_map\fP = true
+.br
+ bool \fIinclude_mpeg4_esid\fP = true
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIhintTrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIpPayloadName\fP
+Specifies the RTP payload name.
+.TP
+\fIpPayloadNumber\fP
+Specifies a pointer to the RTP payload number.
+.TP
+\fImaxPayloadSize\fP
+Specifies the maximum RTP payload size in bytes.
+.TP
+\fIinclude_rtp_map\fP
+Specifies if the a=rtpmap statement is included.
+.TP
+\fIinclude_mpeg4_esid\fP
+Specifies if the a=mpeg4-esid statement is included.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetHintTrackRtpPayload\fR sets the RTP payload parameters for the hint track. The RTP payload is the set of rules by which media samples are packed into RTP packets.
+.LP
+The payload name identifies which RTP payload is being used for the RTP packets created from the hint track. This value is sent to the receiver in the SDP description. For example, MP3 audio sent according to the rules in IETF RFC 2250 uses the name "MPA" for the RTP payload.
+.LP
+The payload number is a shorter form of the payload name. This value is associated with the payload name in the SDP description and then sent in every RTP packet. Payload numbers 1 thru 95 are statically assigned in IETF RFC 1890, numbers 96 thru 127 are dynamically assigned within a session. If the RTP payload in use is one of the statically assigned ones, you should pass this value to the library. If you need a dynamic payload number assigned, pass the define value MP4_SET_DYNAMIC_PAYLOAD for this parameter and the library will choose an valid available number and return this value.
+.LP
+The maxPayloadSize specifies the maximum number of bytes that should be placed in the RTP payload section of the RTP packets. It is desirable that RTP packets not exceed the maximum transmission unit (MTU) of the IP network they travel over since otherwise the packets must be fragmented at the IP level which consumes router resources and can lead to less robust behavior in the face of packet loss.
+.LP
+The default value for maxPayloadSize is 1460, which is the MTU for an Ethernet or similar network minus the standard sizes of the IP, UDP, and RTP headers (1500 \- 20 \- 8 \- 12 = 1460).
+.LP
+If you anticipate streaming over IP networks with smaller MTU sizes, or that extensions to the network headers might be used, a more conservative value should be chosen. The minimum MTU for an IP network is 576 bytes.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetHintTrackPayload(3)
diff --git a/doc/MP4SetHintTrackSdp.3 b/doc/MP4SetHintTrackSdp.3
new file mode 100644
index 0000000..ff3dd1b
--- /dev/null
+++ b/doc/MP4SetHintTrackSdp.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetHintTrackSdp\fR \- Set the SDP media level description of the hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetHintTrackSdp\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ const char* sdpString
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIsdpString\fP
+Specifies the new value of the hint track sdp string.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetHintTrackSdp\fR sets the SDP (IETF RFC 2327) media level fragment for the hint track. This is used by a streaming server to create a complete SDP description of the multimedia session represented by the file.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetHintTrackSdp(3) MP4AppendHintTrackSdp(3)
diff --git a/doc/MP4SetODProfileLevel.3 b/doc/MP4SetODProfileLevel.3
new file mode 100644
index 0000000..07d71c7
--- /dev/null
+++ b/doc/MP4SetODProfileLevel.3
@@ -0,0 +1,41 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetODProfileLevel\fR \- Sets the minimum MPEG\-4 object descriptor profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetODProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ u_int8_t \fIprofileLevel\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetODProfileLevel\fR sets the minumum profile/level of MPEG\-4 object descriptor support necessary to render the contents of the file.
+.LP
+ISO/IEC 14496\-1:2001 MPEG\-4 Systems defines the following values:
+.br
+ 0x00 Reserved
+.br
+ 0x01\-0x7F Reserved
+.br
+ 0x80\-0xFD User private
+.br
+ 0xFE No object descriptor profile specified
+.br
+ 0xFF No object descriptor required
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetODProfileLevel(3)
diff --git a/doc/MP4SetRtpTimestampStart.3 b/doc/MP4SetRtpTimestampStart.3
new file mode 100644
index 0000000..54c5f44
--- /dev/null
+++ b/doc/MP4SetRtpTimestampStart.3
@@ -0,0 +1,39 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetRtpTimestampStart\fR \- Set the RTP start time of a hint track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetRtpTimestampStart\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fIhintTrackId\fP,
+.br
+ MP4Timestamp \fIstartTime\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIstartTime\fP
+Specifies the desired RTP start timestamp for the hint track.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetRtpTimestampStart\fR sets the RTP timestamp start of the specified hint track. Typically this is a random value that is chosen when the first RTP packet is constructed by the MP4 library. However the value can be set explicitly for the hint track and stored. Typically this is used if it is desired that timestamps start at zero.
+.LP
+See IETF RFC 1889 for details regarding RTP timestamps and RTCP.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetRtpTimestampStart(3)
diff --git a/doc/MP4SetSceneProfileLevel.3 b/doc/MP4SetSceneProfileLevel.3
new file mode 100644
index 0000000..ae36ccf
--- /dev/null
+++ b/doc/MP4SetSceneProfileLevel.3
@@ -0,0 +1,43 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetSceneProfileLevel\fR \- Sets the minimum MPEG\-4 scene graph profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetSceneProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ u_int8_t \fIprofileLevel\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetSceneProfileLevel\fR sets the minumum profile/level of MPEG\-4 scene graph support necessary to render the contents of the file.
+.LP
+ISO/IEC 14496\-1:2001 MPEG\-4 Systems defines the following values:
+.br
+ 0x00 Reserved
+.br
+ 0x01 Simple 2D Profile @ Level 1
+.br
+ 0x02\-0x7F Reserved
+.br
+ 0x80\-0xFD User private
+.br
+ 0xFE No scene graph profile specified
+.br
+ 0xFF No scene graph required
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetSceneProfileLevel(3)
diff --git a/doc/MP4SetSessionSdp.3 b/doc/MP4SetSessionSdp.3
new file mode 100644
index 0000000..5d85cfc
--- /dev/null
+++ b/doc/MP4SetSessionSdp.3
@@ -0,0 +1,33 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetSessionSdp\fR \- Set the SDP session level description of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetSessionSdp\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ const char* sdpString
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fIsdpString\fP
+Specifies the new value of the session sdp string.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetSessionSdp\fR sets the SDP (IETF RFC 2327) session level fragment for the file. This is used by a streaming server to create a complete SDP description of the multimedia session represented by the file.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetSessionSdp(3) MP4AppendSessionSdp(3)
diff --git a/doc/MP4SetTrackESConfiguration.3 b/doc/MP4SetTrackESConfiguration.3
new file mode 100644
index 0000000..ba99eb7
--- /dev/null
+++ b/doc/MP4SetTrackESConfiguration.3
@@ -0,0 +1,43 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetTrackESConfiguration\fR \- Set the elementary stream (ES) configuration of a track
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetTrackESConfiguration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP
+.br
+ const u_int8_t* \fIpConfig\fP,
+.br
+ u_int32_t \fIconfigSize\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIpConfig\fP
+Specifies a pointer to the ES configuration information.
+.TP
+\fIconfigSize\fP
+Specifies the size of the ES configuration information.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetTrackESConfiguration\fR sets the elementary stream (ES) configuration of the specified track in the mp4 file. This information is codec specific and contains the configuration necessary for the given codec to decode the samples in the track.
+
+.SH "SEE ALSO"
+.LP
+MP4(3)
diff --git a/doc/MP4SetTrackEditDuration.3 b/doc/MP4SetTrackEditDuration.3
new file mode 100644
index 0000000..0e666c6
--- /dev/null
+++ b/doc/MP4SetTrackEditDuration.3
@@ -0,0 +1,45 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetTrackEditDuration\fR \- Set the duration of a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetTrackEditDuration\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP,
+.br
+ MP4Duration \fIduration\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment to which the operation applies. Caveat: the first edit has id 1 not 0.
+.TP
+\fIduration\fP
+Species the new value for the duration in track time scale units.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetTrackEditDuration\fR sets the duration of the specified edit segment from the specified track in the track time scale units. See MP4ConvertToTrackDuration() for how to map this value from another time scale.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTrackEditDuration(3)
diff --git a/doc/MP4SetTrackEditDwell.3 b/doc/MP4SetTrackEditDwell.3
new file mode 100644
index 0000000..15324f0
--- /dev/null
+++ b/doc/MP4SetTrackEditDwell.3
@@ -0,0 +1,46 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetTrackEditDwell\fR \- Set the dwell value of a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetTrackEditDwell\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP,
+.br
+ bool \fIdwell\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment to which the operation applies. Caveat: the first edit has id 1 not 0.
+.TP
+\fIdwell\fP
+Species the new dwell value.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetTrackEditDwell\fR sets the dwell value of the specified edit segment from the specified track.
+.LP
+A value of true (1) indicates that during this edit segment the media will be paused; a value of false (0) indicates that during this edit segment the media will be played at its normal rate.
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTrackEditDwell(3)
diff --git a/doc/MP4SetTrackEditMediaStart.3 b/doc/MP4SetTrackEditMediaStart.3
new file mode 100644
index 0000000..9fbcf29
--- /dev/null
+++ b/doc/MP4SetTrackEditMediaStart.3
@@ -0,0 +1,54 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetTrackEditMediaStart\fR \- Set the media start time of a track edit segment
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetTrackEditMediaStart\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4EditId \fIeditId\fP,
+.br
+ MP4Timestamp \fImediaStartTime\fP
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the track to which the operation applies.
+.TP
+\fIeditId\fP
+Specifies the edit segment to which the operation applies. Caveat: the first edit has id 1 not 0.
+.TP
+\fImediaStartTime\fP
+Species the new value for the media start in track time scale units.
+
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetTrackEditMediaStart\fR sets the media start time of the specified edit segment from the specified track in the track time scale units. See MP4ConvertToTrackTimestamp() for how to map this value from another time scale.
+.LP
+Note that this differs from the edit segment start time. For example:
+.LP
+EditId Start MediaStart Duration
+1 0 15 30
+.br
+2 30 120 20
+.br
+3 50 3000 10
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetTrackEditMediaStart(3)
diff --git a/doc/MP4SetVideoProfileLevel.3 b/doc/MP4SetVideoProfileLevel.3
new file mode 100644
index 0000000..538bcfb
--- /dev/null
+++ b/doc/MP4SetVideoProfileLevel.3
@@ -0,0 +1,81 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4SetVideoProfileLevel\fR \- Sets the minimum MPEG\-4 video profile and level required to render the contents of the file
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4SetVideoProfileLevel\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ u_int8_t \fIprofileLevel\fP
+.br
+)
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4SetVideoProfileLevel\fR sets the minumum profile/level of MPEG\-4 video support necessary to render the contents of the file.
+.LP
+ISO/IEC 14496\-1:2001 MPEG\-4 Systems defines the following values:
+.br
+ 0x00 Reserved
+.br
+ 0x01 Simple Profile @ Level 3
+.br
+ 0x02 Simple Profile @ Level 2
+.br
+ 0x03 Simple Profile @ Level 1
+.br
+ 0x04 Simple Scalable Profile @ Level 2
+.br
+ 0x05 Simple Scalable Profile @ Level 1
+.br
+ 0x06 Core Profile @ Level 2
+.br
+ 0x07 Core Profile @ Level 1
+.br
+ 0x08 Main Profile @ Level 4
+.br
+ 0x09 Main Profile @ Level 3
+.br
+ 0x0A Main Profile @ Level 2
+.br
+ 0x0B N\-Bit Profile @ Level 2
+.br
+ 0x0C Hybrid Profile @ Level 2
+.br
+ 0x0D Hybrid Profile @ Level 1
+.br
+ 0x0E Basic Animated Texture @ Level 2
+.br
+ 0x0F Basic Animated Texture @ Level 1
+.br
+ 0x10 Scalable Texture @ Level 3
+.br
+ 0x11 Scalable Texture @ Level 2
+.br
+ 0x12 Scalable Texture @ Level 1
+.br
+ 0x13 Simple Face Animation @ Level 2
+.br
+ 0x14 Simple Face Animation @ Level 1
+.br
+ 0x15\-0x7F Reserved
+.br
+ 0x80\-0xFD User private
+.br
+ 0xFE No audio profile specified
+.br
+ 0xFF No audio required
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4GetVideoProfileLevel(3)
diff --git a/doc/MP4WriteRtpHint.3 b/doc/MP4WriteRtpHint.3
new file mode 100644
index 0000000..53220ca
--- /dev/null
+++ b/doc/MP4WriteRtpHint.3
@@ -0,0 +1,43 @@
+.TH "MP4" "3" "Version 0.9" "Cisco Systems Inc." "MP4 File Format Library"
+.SH "NAME"
+.LP
+\fBMP4WriteRtpHint\fR \- Write an RTP hint
+.SH "SYNTAX"
+.LP
+#include <mp4.h>
+.LP
+bool \fBMP4WriteRtpHint\fR(
+.br
+ MP4FileHandle \fIhFile\fP,
+.br
+ MP4TrackId \fItrackId\fP,
+.br
+ MP4Duration \fIduration\fP,
+.br
+ bool \fIisSyncSample\fP = true
+.br
+);
+.SH "ARGUMENTS"
+.LP
+.TP
+\fIhFile\fP
+Specifies the mp4 file to which the operation applies.
+.TP
+\fItrackId\fP
+Specifies the hint track to which the operation applies.
+.TP
+\fIduration\fP
+The duration for this hint sample. Typically this is the same duration as for the corresponding sample in the reference media track. Caveat: The duration should be in the hint track timescale units, again typically the same as the reference media track.
+.TP
+\fIisSyncSample\fP
+The sync/random access flag for this sample. Typically this is the same as for the corresponding sample in the reference media track.
+.SH "RETURN VALUES"
+.LP
+Upon success, true (1). Upon an error, false (0).
+.SH "DESCRIPTION"
+.LP
+\fBMP4WriteRtpHint\fR writes the current pending hint created with MP4AddRtpHint() to the specified hint track.
+
+.SH "SEE ALSO"
+.LP
+MP4(3) MP4AddRtpHint (3)
diff --git a/doc/doxygen/Doxyfile.m4 b/doc/doxygen/Doxyfile.m4
new file mode 100644
index 0000000..a2d83ec
--- /dev/null
+++ b/doc/doxygen/Doxyfile.m4
@@ -0,0 +1,1468 @@
+changequote(<<,>>)dnl
+include(<<project.m4>>)dnl
+# Doxyfile 1.5.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = PROJECT_name
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+#PROJECT_NUMBER = PROJECT_version
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = __MAKE_ABS_TOP_BUILDDIR/doc/api
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene,
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH = __MAKE_ABS_TOP_SRCDIR
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = NO
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = NO
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = __MAKE_ABS_TOP_SRCDIR/doc/doxygen/mainpage.h \
+ __MAKE_ABS_TOP_SRCDIR/include \
+ __MAKE_ABS_TOP_SRCDIR/libplatform \
+ __MAKE_ABS_TOP_SRCDIR/src/itmf \
+ __MAKE_ABS_TOP_SRCDIR/src/qtff
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = __MAKE_ABS_TOP_SRCDIR
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = __MAKE_ABS_TOP_BUILDDIR/doc/doxygen/header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = __MAKE_ABS_TOP_BUILDDIR/doc/doxygen/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET = __MAKE_ABS_TOP_SRCDIR/doc/doxygen/project.css
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#namespace">Qt Help Project / Namespace</a>.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file .
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 3
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = YES
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = MP4V2_EXPORT MP4V2_DEPRECATED DEFAULT(x)=" =x" MP4V2_WFORMAT_PRINTF()=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/doc/doxygen/banner.png b/doc/doxygen/banner.png
new file mode 100644
index 0000000..52dd326
--- /dev/null
+++ b/doc/doxygen/banner.png
Binary files differ
diff --git a/doc/doxygen/footer.html.m4 b/doc/doxygen/footer.html.m4
new file mode 100644
index 0000000..5a938c7
--- /dev/null
+++ b/doc/doxygen/footer.html.m4
@@ -0,0 +1,10 @@
+changequote(<<,>>)dnl
+include(<<project.m4>>)dnl
+<div class="footer">
+ <div>
+ generated on $datetime for <b>__PROJECT_name (__PROJECT_version)</b>
+ by <a href="http://www.doxygen.org">Doxygen</a> $doxygenversion
+ </div>
+</div>
+</body>
+</html>
diff --git a/doc/doxygen/header.html.m4 b/doc/doxygen/header.html.m4
new file mode 100644
index 0000000..d7f1d1b
--- /dev/null
+++ b/doc/doxygen/header.html.m4
@@ -0,0 +1,24 @@
+changequote(<<,>>)dnl
+include(<<project.m4>>)dnl
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+ <title>__PROJECT_name_formal $title</title>
+ <link href="project.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<div id="sitebanner">
+ <div id="home">
+ <a href="__PROJECT_url_website"></a>
+ </div>
+ <div id="title">
+ $title
+ </div>
+ <div id="menu">
+ <ul>
+ <li><a href="__PROJECT_url_website">__PROJECT_name Home</a></li>
+ <li><a href="../index.html">Documentation</a></li>
+ <li class="active">API Reference</li>
+ </ul>
+ </div>
+</div>
diff --git a/doc/doxygen/mainpage.h b/doc/doxygen/mainpage.h
new file mode 100644
index 0000000..dbbc258
--- /dev/null
+++ b/doc/doxygen/mainpage.h
@@ -0,0 +1,63 @@
+/** @mainpage MP4v2 API Reference
+
+@section api Public API
+
+The public API is documented in the <a href="modules.html">modules</a>
+section (as seen at the top of this page).
+Other documentation available for C++ namespaces and classes are for
+internal documentation purposes and not to be used or depended-upon by
+code external to this project.
+
+@section introducation Introduction
+
+The MP4v2 library provides an API to create and modify mp4 files as defined
+by ISO base media file format, document number ISO/IEC 14496-12:2005(E). It
+is a very powerful and extensible format that can accomodate practically
+any type of media.
+
+The conceptual structure of an mp4 file is that it is a container for one
+or more tracks of media. Each track represents exactly one type of media
+such as audio or video. Each track is composed of high-level structural
+data which describes the raw media data stream in a manner that is as
+generic as possible. Tracks have their own timeline, properties and
+samples. An example of a sample is a frame of video. Thus, the file
+file describes how to synchronize the timeline of the tracks.
+
+In a self-contained file, the samples accounts for the majority of file
+size. For playback performance reasons, when an mp4 file contains multiple
+media tracks their samples (raw media data) are usually interleaved to
+provide optimal playback performance.
+
+@section invocation Invocation
+
+The mp4 library is focussed on providing an easy to use API for the mp4
+file format. It has been used with an encoder, a server, a player, and a
+number of mp4 utilities. However, it may not be adequate for multimedia
+editors that wish to work directly with mp4 files. It may be used by these
+type of tools to export an mp4 file.
+
+In providing a easy to use API not all the information in the mp4 file is
+directly exposed via the API. To accomodate applications that need access
+to information not otherwise available via the API there are file and
+track level generic get and set property routines that use arbitary string
+property names. To use these routines you will need to be familar with the
+mp4 file specification or be willing to wade through the output of a
+file-dump which may be produced using MP4Dump() or with some of the
+command-line tools bundled with MP4v2.
+
+@section headers Public Headers
+
+The public libary API is defined in @c <mp4v2/mp4v2.h> which includes all the
+necessary dependent header files. <b>You must never use any other header
+files</b> for public API. Using other header files or symbols which are
+not exported via the public API is expressly not supported and may change
+at any time without notice.
+
+The MP4v2 library can be used by either C or C++ programs. The calling
+convention is C but for convenience if C++ is used default function arguments
+have been added where appropriate.
+
+@example example/provider/provider.c
+@example example/itmf/generic.c
+@example example/itmf/tags.c
+*/
diff --git a/doc/doxygen/project.css b/doc/doxygen/project.css
new file mode 100644
index 0000000..3df0b10
--- /dev/null
+++ b/doc/doxygen/project.css
@@ -0,0 +1,347 @@
+* {
+ margin: 0px;
+ padding: 0px;
+}
+
+body,table {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 13px;
+}
+
+body {
+ background-color: #3C464D;
+ min-width: 800px;
+ max-width: 1360px;
+ padding-top: 0.5em;
+ padding-bottom: 1em;
+}
+
+a {
+ color: #5382A1;
+ text-decoration: none;
+ font-weight: bold;
+}
+
+a:hover {
+ color: #9E005D;
+}
+
+h1 {
+ text-align: center;
+ font-size: 140%;
+}
+
+h2 {
+ font-size: 120%;
+}
+
+h3 {
+ font-size: 100%;
+}
+
+img {
+ border: none;
+ vertical-align: middle;
+}
+
+/* ----------------------------------*/
+
+dd,ul {
+ padding-left: 40px;
+}
+
+h1,h2,h3 {
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+
+h2,h3 {
+ font-weight: normal;
+ border-bottom: 2px solid;
+ margin-top: 2em;
+}
+
+h1 a, h2 a, h3 a {
+ color: black;
+}
+
+h1 small a {
+ color: #5382A1;
+ text-decoration: none;
+ font-weight: bold;
+}
+
+p,ul {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+/* ----------------------------------*/
+
+dl ul,
+ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+/* ----------------------------------*/
+
+div#sitebanner,
+div.navigation, div.contents, div.footer {
+ margin-left: 40px;
+ margin-right: 40px;
+ background-color: #EDEFF2;
+ position: relative;
+}
+
+div.navigation div.tabs, div.navigation div.navpath, div.contents, div.footer div {
+ padding-left: 16px;
+ padding-right: 16px;
+}
+
+div.navigation, div.navigation, div.contents, div.footer {
+ -webkit-box-shadow: 5px 5px 5px black;
+}
+
+div#sitebanner {
+ background-color: gray;
+ background-image: url(banner.png);
+ background-repeat: no-repeat;
+ background-position: top left;
+ min-height: 128px;
+ max-height: 128px;
+ text-shadow: black 1px 1px 0px;
+ -webkit-border-top-left-radius: 1em;
+ -webkit-border-top-right-radius: 1em;
+ -webkit-box-shadow: 5px 5px 5px black;
+ -moz-border-radius-topleft: 1em;
+ -moz-border-radius-topright: 1em;
+}
+
+/* enable to make banner logo clickable */
+/*
+div#sitebanner div#home a {
+ display: block;
+ background: none;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ height: 80px;
+ width: 220px;
+}
+*/
+
+div#sitebanner div#title {
+ display: none;
+ position: absolute;
+ top: 40%;
+ right: 0;
+ left: 0;
+ text-align: center;
+ color: white;
+ color: #C9F08D;
+ font-weight: bold;
+ font-size: 150%;
+}
+
+div#sitebanner div#menu {
+ position: absolute;
+ top: 16px;
+ right: 16px;
+ color: white;
+ text-align: right;
+}
+
+div#sitebanner div#menu li {
+ list-style-type: none;
+}
+
+div#sitebanner div#menu li a {
+ color: white;
+ font-weight: normal;
+}
+
+div#sitebanner div#menu li.active,
+div#sitebanner div#menu li a:hover {
+ color: #C9F08D;
+}
+
+div.navigation {
+ background-color: #F8F9FA;
+}
+
+div.contents {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+div.footer {
+ padding-top: 2em;
+ padding-bottom: 1em;
+ -webkit-border-bottom-left-radius: 1em;
+ -webkit-border-bottom-right-radius: 1em;
+ -moz-border-radius-bottomleft: 1em;
+ -moz-border-radius-bottomright: 1em;
+}
+
+div.footer div {
+ text-align: right;
+ font-size: x-small;
+ border-top: 2px solid #5382A1;
+}
+
+div.navigation > div {
+ padding-top: 4px;
+ padding-bottom: 4px;
+ border-bottom: 2px solid #5382A1;
+}
+
+div.navigation div.tabs ul {
+ margin: 0;
+ padding: 0;
+}
+
+div.navigation div.tabs ul li {
+ display: inline;
+ font-weight: bold;
+ margin-right: 1em;
+}
+
+div.navigation div.tabs ul li a {
+ color: #707277;
+}
+
+div.navigation div.tabs ul li a:hover {
+ color: #9E005D;
+}
+
+div.navigation div.tabs ul li.current a {
+ color: #5382A1;
+}
+
+div.navigation div.tabs ul li.current a:hover {
+ color: #9E005D;
+}
+
+/* ----------------------------------*/
+
+pre.fragment {
+ background-color: #FFFCE5;
+ border: 1px dashed;
+ margin: 1em;
+ padding: 0.5em;
+}
+
+pre.fragment span.comment {
+ color: #CF2FCF;
+}
+
+pre.fragment span.stringliteral {
+ color: #DB0D10;
+}
+
+div.navigation div.fragment {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+/* ----------------------------------*/
+
+h1 + table {
+ margin-top: 1em;
+}
+
+table {
+ table-layout: auto;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+
+td.indexkey, td.indexvalue {
+ background-color: #D7D7D7;
+ border: 1px solid;
+ padding: 0.4em 0.5em;
+}
+
+td.memItemLeft, td.memItemRight {
+ background-color: #D7D7D7;
+}
+
+td.mdescLeft, td.mdescRight {
+ background-color: #E7E7E7;
+}
+
+td.memItemLeft, td.mdescLeft {
+ padding-left: 1em;
+}
+
+td.memItemRight, td.mdescRight {
+ padding-right: 1em;
+}
+
+hr {
+ border: 1px solid;
+ display: none;
+}
+
+/* ----------------------------------*/
+
+div.memitem {
+ border: 1px solid gray;
+ -webkit-border-radius: 0.5em;
+ -webkit-box-shadow: 2px 2px 2px black;
+ -moz-border-radius: 0.5em;
+}
+
+div.memproto {
+ background-color: #D7D7D7;
+ border-bottom: 1px solid gray;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ -webkit-border-top-left-radius: 0.5em;
+ -webkit-border-top-right-radius: 0.5em;
+ -moz-border-radius-topleft: 0.5em;
+ -moz-border-radius-topright: 0.5em;
+}
+
+div.memdoc {
+ background-color: #E7E7E7;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ -webkit-border-bottom-left-radius: 0.5em;
+ -webkit-border-bottom-right-radius: 0.5em;
+ -moz-border-radius-bottomleft: 0.5em;
+ -moz-border-radius-bottomright: 0.5em;
+}
+
+div.memproto,
+div.memdoc {
+ padding-left: 1em;
+ padding-right: 1em;
+}
+
+div.memproto td.memname {
+ padding-right: 1px;
+}
+
+div.memproto td.paramtype {
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+
+div.memproto td code {
+ color: #AA0000;
+ padding-left: 0.5em;
+ font-weight: bold;
+ text-align: right;
+}
+
+div.memdoc p:first-child {
+ margin-top: 0;
+}
+
+/* ----------------------------------*/
+
+dl.see p {
+ margin: 0;
+}
diff --git a/doc/html/banner.png b/doc/html/banner.png
new file mode 100644
index 0000000..52dd326
--- /dev/null
+++ b/doc/html/banner.png
Binary files differ
diff --git a/doc/html/footer.html.m4 b/doc/html/footer.html.m4
new file mode 100644
index 0000000..54504a8
--- /dev/null
+++ b/doc/html/footer.html.m4
@@ -0,0 +1,10 @@
+changequote(<<,>>)dnl
+include(<<project.m4>>)dnl
+</div>
+<div id="footer">
+ <div>
+ generated on __PROJECT_build for <b>__PROJECT_name (__PROJECT_version)</b>
+ </div>
+</div>
+</body>
+</html>
diff --git a/doc/html/header.html.m4 b/doc/html/header.html.m4
new file mode 100644
index 0000000..bf11af1
--- /dev/null
+++ b/doc/html/header.html.m4
@@ -0,0 +1,26 @@
+changequote(<<,>>)dnl
+include(<<project.m4>>)dnl
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+ <title>__TITLE__</title>
+ <link href="project.css" rel="stylesheet" type="text/css">
+</head>
+<body>
+<div id="page">
+<div id="sitebanner">
+ <div id="home">
+ <a href="__PROJECT_url_website"></a>
+ </div>
+ <div id="title">
+ __SHORT_TITLE__
+ </div>
+ <div id="menu">
+ <ul>
+ <li><a href="__PROJECT_url_website">__PROJECT_name Home</a></li>
+__MENU__
+ <!-- <li class="active">Documentation</li> -->
+ </ul>
+ </div>
+</div>
+<div id="content">
diff --git a/doc/html/project.css b/doc/html/project.css
new file mode 100644
index 0000000..2745b92
--- /dev/null
+++ b/doc/html/project.css
@@ -0,0 +1,198 @@
+* {
+ margin: 0px;
+ padding: 0px;
+}
+
+body,table {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 13px;
+}
+
+body {
+ background-color: #3C464D;
+ min-width: 800px;
+ max-width: 1360px;
+ padding-top: 0.5em;
+ padding-bottom: 1em;
+}
+
+a {
+ color: #5382A1;
+ text-decoration: none;
+ font-weight: bold;
+}
+
+a:hover {
+ color: #9E005D;
+}
+
+h1 {
+ text-align: center;
+ font-size: 140%;
+}
+
+h2 {
+ font-size: 120%;
+}
+
+h3 {
+ font-size: 100%;
+}
+
+img {
+ border: none;
+ vertical-align: middle;
+}
+
+/* ----------------------------------*/
+
+dd,ul {
+ padding-left: 40px;
+}
+
+h1,h2,h3 {
+ margin-top: 1.5em;
+ margin-bottom: 1.0em;
+}
+
+h2 {
+ border-bottom: 2px solid;
+}
+
+p,ul {
+ margin-top: 1em;
+}
+
+dd,ol {
+ padding-left: 40px;
+}
+
+ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+/* ----------------------------------*/
+
+blockquote, dl, pre {
+ margin: 1em 4em;
+}
+
+pre {
+ background-color: #CCCCCC;
+ padding: 0.5em;
+ border: 1px solid #888888;
+}
+
+dl span.samp, dl span.command {
+ font-weight: bold;
+}
+
+/* ----------------------------------*/
+
+div#page {
+ margin-left: 40px;
+ margin-right: 40px;
+ position: relative;
+ background-color: #EDEFF2;
+ -webkit-border-radius: 1em;
+ -webkit-box-shadow: 5px 5px 5px black;
+ -moz-border-radius: 1em;
+}
+
+div#sitebanner, div#content, div#footer div {
+ padding-left: 16px;
+ padding-right: 16px;
+}
+
+div#sitebanner {
+ position: relative;
+ background-color: gray;
+ background-image: url(banner.png);
+ background-repeat: no-repeat;
+ background-position: top left;
+ min-height: 128px;
+ max-height: 128px;
+ text-shadow: black 1px 1px 0px;
+ -webkit-border-top-left-radius: 1em;
+ -webkit-border-top-right-radius: 1em;
+ -moz-border-radius-topleft: 1em;
+ -moz-border-radius-topright: 1em;
+}
+
+/* enable to make banner logo clickable */
+/*
+div#sitebanner div#home a {
+ display: block;
+ background: none;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ height: 80px;
+ width: 220px;
+}
+*/
+
+div#sitebanner div#title {
+ display: none;
+ position: absolute;
+ top: 40%;
+ left: 50%;
+ text-align: lef;
+ color: white;
+ color: #C9F08D;
+ font-weight: bold;
+ font-size: 150%;
+}
+
+div#sitebanner div#menu {
+ position: absolute;
+ top: 16px;
+ right: 16px;
+ color: white;
+ text-align: right;
+}
+
+div#sitebanner div#menu li {
+ list-style-type: none;
+}
+
+div#sitebanner div#menu li a {
+ color: white;
+ font-weight: normal;
+}
+
+div#sitebanner div#menu li.active,
+div#sitebanner div#menu li a:hover {
+ color: #C9F08D;
+}
+
+div#contents {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+div#footer {
+ padding-top: 2em;
+ padding-bottom: 1em;
+ -webkit-border-bottom-left-radius: 1em;
+ -webkit-border-bottom-right-radius: 1em;
+ -moz-border-radius-bottomleft: 1em;
+ -moz-border-radius-bottomright: 1em;
+}
+
+div#footer div {
+ text-align: right;
+ font-size: x-small;
+ border-top: 2px solid #5382A1;
+}
+
+/* ----------------------------------*/
+
+div.contents ul {
+ list-style-type: none;
+ padding-left: 2em;
+}
+
+div.contents ul {
+}
diff --git a/doc/texi/Authors.texi b/doc/texi/Authors.texi
new file mode 100644
index 0000000..9ec4920
--- /dev/null
+++ b/doc/texi/Authors.texi
@@ -0,0 +1,27 @@
+@input texinfo @c -*- Texinfo -*-
+@c %**start of header
+@setfilename Authors.info
+@include base/article.texi
+@paragraphindent none
+@c %**end of header
+
+@majorheading @value{PROJECT.name.formal} Authors
+
+This document lists significant contributors to @value{PROJECT.name}. If any contributors are missing please contact one of the project members. More extensive contributor information may be found in sources, docs, and other files where appropriate.
+
+@example
+Edward Groenendaal egroenen@@cisco.com
+Jonathon Rubin jb.rubin@@gmail.com
+Kona Blend kona8lend@@gmail.com
+Rouven Wessling mp4v2@@rouvenwessling.de
+@end example
+
+@heading Authors from original MPEG4IP/libmp4v2
+
+@example
+Dave Mackie dmackie@@cisco.com
+Alix Marchandise-Franquet alix@@cisco.com
+Bill May wmay@@cisco.com
+Ximpo Group Ltd. mp4v2@@ximpo.com
+Danijel Kopcinovic danijel.kopcinovic@@adnecto.net
+@end example
diff --git a/doc/texi/BuildRepository.texi b/doc/texi/BuildRepository.texi
new file mode 100644
index 0000000..dcae56e
--- /dev/null
+++ b/doc/texi/BuildRepository.texi
@@ -0,0 +1,42 @@
+@input texinfo @c -*- Texinfo -*-
+@c %**start of header
+@setfilename BuildRepository.info
+@include base/article.texi
+@include build/commands.texi
+@paragraphindent none
+@c %**end of header
+
+@majorheading @value{PROJECT.name.formal} Building the Repository
+@contents
+
+@chapter Overview
+@include build/overview.texi
+
+@chapter Introduction
+This document describes the recommended process to build @value{PROJECT.name} from the repository. This process is a @b{superset} of the process to build from a @value{TERM.srcdist} bundle. If you are interested in building from a @value{TERM.srcdist} bundle then this document is not for you.
+
+@chapter Quickstart
+This chapter is for the impatient or those just looking for a quick summary of all the commands used in a typical build. You may skip this summary and jump to @ref{Build Process}.
+
+@example
+@COMMAND.checkout{}
+@COMMAND.bootstrap{}
+@COMMAND.configure{}
+@COMMAND.build{}
+@COMMAND.install{}
+@COMMAND.dist{}
+@end example
+
+@anchor{Build Process}
+@chapter Build Process
+
+@include build/process.checkout.texi
+@include build/process.bootstrap.texi
+@include build/process.configure.texi
+@include build/process.build.texi
+@include build/process.install.texi
+@include build/process.dist.texi
+@include build/process.doc.texi
+@include build/process.google.texi
+
+@include build/platforms.texi
diff --git a/doc/texi/BuildSource.texi b/doc/texi/BuildSource.texi
new file mode 100644
index 0000000..233ecdb
--- /dev/null
+++ b/doc/texi/BuildSource.texi
@@ -0,0 +1,36 @@
+@input texinfo @c -*- Texinfo -*-
+@c %**start of header
+@setfilename BuildSource.info
+@include base/article.texi
+@include build/commands.texi
+@paragraphindent none
+@c %**end of header
+
+@majorheading @value{PROJECT.name.formal} Building the Source
+@contents
+
+@chapter Overview
+@include build/overview.texi
+
+@chapter Introduction
+This document describes the recommended process to build @value{PROJECT.name} from a @value{TERM.srcdist} bundle. This process is a @b{subset} of the process to build directly from the project's repository. If you are interested in building from the repository then this document is not for you.
+
+@chapter Quickstart
+This chapter is for the impatient or those just looking for a quick summary of all the commands used in a typical build. You may skip this summary and jump to @ref{Build Process}.
+
+@example
+@COMMAND.extract{}
+@COMMAND.configure{}
+@COMMAND.build{}
+@COMMAND.install{}
+@end example
+
+@anchor{Build Process}
+@chapter Build Process
+
+@include build/process.extract.texi
+@include build/process.configure.texi
+@include build/process.build.texi
+@include build/process.install.texi
+
+@include build/platforms.texi
diff --git a/doc/texi/Documentation.texi b/doc/texi/Documentation.texi
new file mode 100644
index 0000000..7b85fa1
--- /dev/null
+++ b/doc/texi/Documentation.texi
@@ -0,0 +1,47 @@
+@input texinfo @c -*- Texinfo -*-
+@c %**start of header
+@setfilename Documentation.info
+@include base/article.texi
+@paragraphindent none
+@c %**end of header
+
+@titlepage
+@end titlepage
+
+@majorheading @value{PROJECT.name.formal} Documentation
+@include releasenotes/intro.@value{PROJECT.repo.type}.texi
+
+@heading Introduction
+Project @value{PROJECT.name} consists of a C-library and various command-line utilities which permit creation and modification of MP4 files as defined by as defined by @cite{ISO base media file format}, document number @cite{ISO/IEC 14496-12:2005(E)}.
+
+@heading Official website
+The official @url{@value{PROJECT.url.website},website} makes various @url{@value{PROJECT.url.downloads},downloads} available and archives online browesable documentation for releases, including API Reference. Questions, bug-reports and general feedback may be submitted to the @url{@value{PROJECT.url.discussion},discussion} group.
+
+@ifnothtml
+@unnumbered Articles
+ See Release Notes (@file{doc/ReleaseNotes.txt})
+@* See Building the Source (@file{doc/BuildSource.txt})
+@* See Building the Repository (@file{doc/BuildRepository.txt})
+@* See Authors (@file{doc/Authors.txt})
+
+@unnumbered Guides
+ See Command-line Tools Guide (@file{doc/ToolGuide.txt})
+@end ifnothtml
+
+@ifhtml
+@unnumbered Articles
+@enumerate
+@item @url{ReleaseNotes.html,Release Notes}.
+@item @url{BuildSource.html,Building the Source}.
+@item @url{BuildRepository.html,Building the Repository}.
+@item @url{Authors.html,Authors}.
+@end enumerate
+@unnumbered Guides
+@enumerate
+@item @url{ToolGuide.html,Command-line Tools Guide}.
+@end enumerate
+@unnumbered Reference
+@enumerate
+@item @url{api/index.html,API Reference}.
+@end enumerate
+@end ifhtml
diff --git a/doc/texi/ReleaseNotes.texi b/doc/texi/ReleaseNotes.texi
new file mode 100644
index 0000000..2e3d189
--- /dev/null
+++ b/doc/texi/ReleaseNotes.texi
@@ -0,0 +1,63 @@
+@input texinfo @c -*- Texinfo -*-
+@c %**start of header
+@setfilename ReleaseNotes.info
+@include base/article.texi
+@paragraphindent none
+@c %**end of header
+
+@titlepage
+@end titlepage
+
+@majorheading @value{PROJECT.name.formal} Release Notes
+@include releasenotes/intro.@value{PROJECT.repo.type}.texi
+@contents
+
+@chapter What's New?
+[TODO]
+
+@chapter Breaking Changes
+@section Removed deprecated metadata/free-form API.
+The following functions have been removed and replaced with iTMF Generic and Tags API. Detailed documentation can be found under API modules section.
+
+DeleteMetadataAtom(),
+DeleteMetadataFreeForm(),
+DeleteMetadataGenre(),
+GetMetadataByIndex(),
+GetMetadataCoverArt(),
+GetMetadataCoverArtCount(),
+GetMetadataDisk(),
+GetMetadataFreeForm(),
+GetMetadataGenre(),
+GetMetadataString(),
+GetMetadataTrack(),
+GetMetadataUint16(),
+GetMetadataUint8(),
+MetadataDelete(),
+SetMetadataCoverArt(),
+SetMetadataDisk(),
+SetMetadataFreeForm(),
+SetMetadataGenre(),
+SetMetadataString(),
+SetMetadataTrack(),
+SetMetadataUint16(),
+SetMetadataUint8().
+
+@appendix Changelog
+@appendixsection Version 2.0
+@include changelog/version-2.0.texi
+
+@appendixsection Version 1.9
+@include changelog/version-1.9.texi
+
+@appendixsection Version 1.6
+@include changelog/version-1.6.texi
+
+@appendix SCM repository details
+@example
+url: @value{PROJECT.repo.url}
+root: @value{PROJECT.repo.root}
+uuid: @value{PROJECT.repo.uuid}
+rev: @value{PROJECT.repo.rev}
+date: @value{PROJECT.repo.date}
+type: @value{PROJECT.repo.type}
+@end example
diff --git a/doc/texi/ToolGuide.texi b/doc/texi/ToolGuide.texi
new file mode 100644
index 0000000..a951f26
--- /dev/null
+++ b/doc/texi/ToolGuide.texi
@@ -0,0 +1,95 @@
+@input texinfo @c -*- Texinfo -*-
+@c %**start of header
+@setfilename ToolGuide.info
+@include base/guide.texi
+@paragraphindent none
+@c %**end of header
+
+@majorheading @value{PROJECT.name.formal} Command-line Tools Guide
+@contents
+
+@chapter Overview
+@value{PROJECT.name} bundles several command-line tools which, in general, allow some basic manipulation of mp4 files which have been created by other means. They are not meant to be a complete solution to management of mp4 file structure.
+
+The following is a brief summary of the tools available and the functionality offered. Other tools may be packaged with the distribution but are not yet stable enough to even document. User beware.
+
+@table @samp
+@item mp4file
+Operates on the entire file with actions such as list (summary information), optimization and ASCII dumps.
+
+@item mp4track
+Operates on individual tracks with actions such as colr-box and pasp-box manipulation.
+
+@item mp4art
+Operates on iTunes Metadata Cover-art Boxes with actions such as list, add, replace, remove and extraction of Cover-art images.
+@end table
+
+@chapter Introduction
+The tools are invoked by their command-name, followed by one or more options, actions, parameters for actions, and finally one or more files on which the tool will operate. Options are specified in one of two ways; in @b{short} or @b{long} syntax. A short-syntax option is prefixed with exactly one @i{dash} while a long-syntax option is prefixed with exactly two @i{dashes}. Depending on the option, it may or may not expect an argument. Specifying an option which expects an argument usually follows either of the following patterns:
+
+@example
+toolname --something value ...
+toolname --something=value ...
+@end example
+
+The rest of this guide will use the @i{equals} sign method.
+
+@chapter Common Options
+Many of the tools share a common set of options which. These common options usually have identically behaving short or long syntax. In some cases short-syntax differs from long-syntax in that it may not require an argument. This style is used sparingly and only when truly convenient. Even though it is common practice in many unix-style tools to permit @i{optional} arguments, the tools used in this project will tend to avoid that because it can create a great deal of confusion.
+
+The following is a list of common options available:
+
+@table @samp
+@item -y, --dryrun
+do not actually create or modify any files.
+In situations where the command will create new or modify existing files, specifying this option will cause the tool to do as much as possible stopping short of performing any actual writes. This is useful to guard against user mistakes or unexpected behavior.
+
+@item -k, --keepgoing
+continue batch processing even after errors.
+When actions involve multiple files or operations, the default behavior is to stop and exit on the first error encountered. Specify this option if it is desirable to record the error but continue processing.
+
+@item -o, --overwrite
+overwrite existing files when creating.
+In situations where a new file will be created, the default behavior is to not overwrite a file if it already exists. Use this option to allow overwriting.
+
+@item -f, --force
+force overwrite even if file is read-only.
+If overwriting is enabled, file permissions may prevent writes. Specify this option to try and overwrite the file anyways. This usually involves deleting the file, then creating a new one.
+
+@item -q, --quiet
+equivalent to --verbose 0.
+Default behavior is to print a low amount of informative information, usually one line of text per action/file. Specify this option to omit normal messages. Errors will still be reported.
+
+@item -d, --debug NUM
+increase debug or long-option to set NUM.
+File I/O with mp4 file structures have special debug options available to users interested in all the fine details. Default is level 1 . The short-syntax is accumulative and takes no argument, while long-syntax takes an argument. For exmaple, the following are equivalent and would set level 3: @samp{-dd} or @samp{-d -d} or @samp{--debug=3}. The following levels are available:
+@enumerate 0
+@item supressed
+@item add warnings and errors (default)
+@item add table details
+@item add implicits
+@item everything
+@end enumerate
+
+@item -v, --verbose NUM
+increase verbosity or long-option to set NUM.
+Tool activity by default will generally print one informative message per action/file. Specify this option to change the default behavior. The short-syntax is accumulative and takes no argument, while long-syntax takes an argument.
+@enumerate 0
+@item warnings and errors
+@item normal informative messages (default)
+@item more informative messages
+@item everything
+@end enumerate
+
+@item -h, --help
+print brief help or long-option for extended help.
+The short-syntax will produce brief help. Specify the long-option for more extensive help.
+
+@item --version
+print version information and exit.
+Extended version information used for SCM purposes is not listed in help, but is available by specifying @samp{--verionx}.
+@end table
+
+@include tool/mp4file.texi
+@include tool/mp4track.texi
+@include tool/mp4art.texi
diff --git a/doc/texi/base/article.texi b/doc/texi/base/article.texi
new file mode 100644
index 0000000..a5fdf76
--- /dev/null
+++ b/doc/texi/base/article.texi
@@ -0,0 +1,6 @@
+@ifhtml
+@exampleindent 0
+@end ifhtml
+
+@include base/project.texi
+@include base/glossary.texi
diff --git a/doc/texi/base/glossary.texi b/doc/texi/base/glossary.texi
new file mode 100644
index 0000000..c46a4f3
--- /dev/null
+++ b/doc/texi/base/glossary.texi
@@ -0,0 +1,9 @@
+@set OS.cygwin Cygwin
+@set OS.freebsd FreeBSD
+@set OS.linux Linux
+@set OS.osx Mac OS X
+@set OS.solaris Solaris
+@set OS.unix unix
+@set OS.windows Windows
+
+@set TERM.srcdist source-distribution
diff --git a/doc/texi/base/guide.texi b/doc/texi/base/guide.texi
new file mode 100644
index 0000000..a5fdf76
--- /dev/null
+++ b/doc/texi/base/guide.texi
@@ -0,0 +1,6 @@
+@ifhtml
+@exampleindent 0
+@end ifhtml
+
+@include base/project.texi
+@include base/glossary.texi
diff --git a/doc/texi/base/project.texi.m4 b/doc/texi/base/project.texi.m4
new file mode 100644
index 0000000..5a37bce
--- /dev/null
+++ b/doc/texi/base/project.texi.m4
@@ -0,0 +1,24 @@
+changequote(<<,>>)dnl
+include(<<project.m4>>)dnl
+@set PROJECT.name __PROJECT_name
+@set PROJECT.name.lower __PROJECT_name_lower
+@set PROJECT.name.upper __PROJECT_name_upper
+@set PROJECT.name.formal __PROJECT_name_formal
+@set PROJECT.url.website __PROJECT_url_website
+@set PROJECT.url.downloads __PROJECT_url_downloads
+@set PROJECT.url.discussion __PROJECT_url_discussion
+@set PROJECT.irc __PROJECT_irc
+@set PROJECT.bugreport patsubst(__PROJECT_bugreport,@,@@)
+@set PROJECT.version __PROJECT_version
+@set PROJECT.version.hex __PROJECT_version_hex
+@set PROJECT.version.major __PROJECT_version_major
+@set PROJECT.version.minor __PROJECT_version_minor
+@set PROJECT.version.point __PROJECT_version_point
+@set PROJECT.repo.url __PROJECT_repo_url
+@set PROJECT.repo.branch __PROJECT_repo_branch
+@set PROJECT.repo.root __PROJECT_repo_root
+@set PROJECT.repo.uuid __PROJECT_repo_uuid
+@set PROJECT.repo.rev __PROJECT_repo_rev
+@set PROJECT.repo.date __PROJECT_repo_date
+@set PROJECT.repo.type __PROJECT_repo_type
+@set PROJECT.build __PROJECT_build
diff --git a/doc/texi/build/commands.texi b/doc/texi/build/commands.texi
new file mode 100644
index 0000000..8ef9ec9
--- /dev/null
+++ b/doc/texi/build/commands.texi
@@ -0,0 +1,33 @@
+@macro COMMAND.checkout{}
+svn checkout @value{PROJECT.repo.url} @value{PROJECT.name.lower}
+cd @value{PROJECT.name.lower}
+@end macro
+
+@macro COMMAND.bootstrap{}
+autoreconf -fiv
+@end macro
+
+@macro COMMAND.extract{}
+tar xf @value{PROJECT.name.lower}-@value{PROJECT.version}.tar.bz2
+cd @value{PROJECT.name.lower}-@value{PROJECT.version}/
+@end macro
+
+@macro COMMAND.configure{}
+rm -fr build/
+mkdir build/
+cd build/
+../configure
+@end macro
+
+@macro COMMAND.build{}
+make
+@end macro
+
+@macro COMMAND.install{}
+make install
+make install-man
+@end macro
+
+@macro COMMAND.dist{}
+make dist
+@end macro
diff --git a/doc/texi/build/overview.texi b/doc/texi/build/overview.texi
new file mode 100644
index 0000000..e33c35b
--- /dev/null
+++ b/doc/texi/build/overview.texi
@@ -0,0 +1,3 @@
+The documented and supported method to build @value{PROJECT.name} uses the GNU build system (also known as the Autotools). You must first obtain the sources by either downloading and extracting the @value{TERM.srcdist} bundle or working directly @value{PROJECT.name}'s Subversion repository. We have build documents for both methods, but unless you are a member of the @value{PROJECT.name} project, you are @b{strongly encouraged} to use the @value{TERM.srcdist} method.
+
+On other supported platforms which lack Autotools we provide an alternative method for building the software. Please see the appropriate platform section.
diff --git a/doc/texi/build/platform.common.bundled.texi b/doc/texi/build/platform.common.bundled.texi
new file mode 100644
index 0000000..d5c00ee
--- /dev/null
+++ b/doc/texi/build/platform.common.bundled.texi
@@ -0,0 +1,3 @@
+@quotation Note
+It is recommended to use the platform distribution's bundled compiler for maximum C++ compatibility. If you build with a custom compiler it will likely introduce non-standard runtime requirements for your users. There are of course many valid reasons to build with unbundled compilers, but be aware that is generally unsupported and left as an exercise to the reader.
+@end quotation
diff --git a/doc/texi/build/platform.common.conf.bi.texi b/doc/texi/build/platform.common.conf.bi.texi
new file mode 100644
index 0000000..bb5e0eb
--- /dev/null
+++ b/doc/texi/build/platform.common.conf.bi.texi
@@ -0,0 +1,10 @@
+@subsection Bi-arch compilation
+The preferred method to produce a bi-arch binary is to specify the target (eg. 32-bit) with the following option to configure. This example will produce a 32-bit binary if compiling on a platform which defaults to producing 64-bit binaries. The inverse is also possible.
+
+@example
+../configure --enable-bi=32
+@end example
+
+@quotation Warning
+Currently bi-arch cross-compilation is not supported due to a bug with libtool which fails miserably during linking.
+@end quotation
diff --git a/doc/texi/build/platform.common.conf.default.texi b/doc/texi/build/platform.common.conf.default.texi
new file mode 100644
index 0000000..e127c60
--- /dev/null
+++ b/doc/texi/build/platform.common.conf.default.texi
@@ -0,0 +1,20 @@
+@subsection Default Binaries
+The preferred method to produce default binaries is to run configure without any options which will compile with debug+optimize and produce static+shared libraries and dynamic executables.
+
+@example
+../configure
+@end example
+
+@subsection Release Binaries
+The preferred method to produce binaries suitable for releases, (ie. which does not contain debug information) is to pass the following to configure:
+
+@example
+../configure --disable-debug
+@end example
+
+@subsection Developer Binaries
+The preferred method to produce binaries suitable for development is to pass the following to configure. Default Binaries will work, however for the best debugging experience we recommend no optimize and no static libraries.
+
+@example
+../configure --disable-optimize --disable-static
+@end example
diff --git a/doc/texi/build/platform.cygwin.texi b/doc/texi/build/platform.cygwin.texi
new file mode 100644
index 0000000..90574c7
--- /dev/null
+++ b/doc/texi/build/platform.cygwin.texi
@@ -0,0 +1,20 @@
+@section @value{OS.cygwin}
+Building on @value{OS.cygwin} is supported. The following are the recommended specifications for this platform; but is not necessarily the only configuration that is possible:
+
+@itemize @bullet
+@item Intel 32-bit or 64-bit hardware
+@item @value{OS.cygwin}, gcc 4.3.2
+@item gcc 3.4.0 or higher is reported to work
+@end itemize
+
+@quotation Note
+As of this writing, @value{OS.cygwin} has available to it several versions of gcc; only one of which may be found and used in the path as @code{gcc} and @code{g++}. Configure will thus find what is probably the older more stable version of gcc in a typical @value{OS.cygwin} environment. If you desire to build with the newer gcc, it is found in the path as @code{gcc-4} and @code{g++-4} respectively and you must indicate to configure the desired versions. Defining the following variables beforing running configure should do the trick:
+@end quotation
+
+@example
+setenv CC gcc-4
+setenv CXX gcc-4
+../configure
+@end example
+
+@include build/platform.common.conf.default.texi
diff --git a/doc/texi/build/platform.freebsd.texi b/doc/texi/build/platform.freebsd.texi
new file mode 100644
index 0000000..a707ff6
--- /dev/null
+++ b/doc/texi/build/platform.freebsd.texi
@@ -0,0 +1,12 @@
+@section @value{OS.freebsd}
+Building on @value{OS.freebsd} is supported. The following are the recommended specifications for this platform; but is not necessarily the only configuration that is possible:
+
+@itemize @bullet
+@item Intel 32-bit or 64-bit hardware
+@item @value{OS.freebsd} 7.0 Release, gcc 4.2.1
+@item gcc 3.4.0 or higher is reported to work
+@end itemize
+
+@include build/platform.common.bundled.texi
+@include build/platform.common.conf.default.texi
+@include build/platform.common.conf.bi.texi
diff --git a/doc/texi/build/platform.linux.texi b/doc/texi/build/platform.linux.texi
new file mode 100644
index 0000000..ddc04df
--- /dev/null
+++ b/doc/texi/build/platform.linux.texi
@@ -0,0 +1,12 @@
+@section @value{OS.linux}
+Building on @value{OS.linux} is well supported as it is used by maintainers of this project. The following are the recommended specifications for this platform; but is not necessarily the only configuration that is possible:
+
+@itemize @bullet
+@item Intel 32-bit or 64-bit hardware
+@item Fedora 10, gcc 4.3.2
+@item gcc 3.4.0 or higher is reported to work
+@end itemize
+
+@include build/platform.common.bundled.texi
+@include build/platform.common.conf.default.texi
+@include build/platform.common.conf.bi.texi
diff --git a/doc/texi/build/platform.osx.texi b/doc/texi/build/platform.osx.texi
new file mode 100644
index 0000000..ac2bc05
--- /dev/null
+++ b/doc/texi/build/platform.osx.texi
@@ -0,0 +1,28 @@
+@section @value{OS.osx}
+Building on @value{OS.osx} is well supported as it is used by maintainers of this project. The following are the recommended specifications for this platform; but is not necessarily the only configuration that is possible:
+
+@itemize @bullet
+@item Mac Intel hardware
+@item Mac OS X 10.5.7
+@item Xcode-3.1.2
+@item gcc 4.0.1 (Apple Inc. build 5493)
+@item gcc 4.2.1 (Apple Inc. build 5570)
+@end itemize
+
+@include build/platform.common.bundled.texi
+
+@include build/platform.common.conf.default.texi
+
+@subsection Universal Binaries - all architectures
+The preferred method to produce universal binaries for all supported architectures is to pass the following option to configure. As of this writing, architectures @{ i386, x86_64, ppc, ppc64 @} are built.
+
+@example
+../configure --enable-ub
+@end example
+
+@subsection Universal Binaries - selected architectures
+The preferred method to produce universal binaries for selected architectures is to specify a comma-delimited list specifying the desired architecture identifiers. Passing the following option will produce universal binaries for architectures @{ i386, x86_64 @}.
+
+@example
+../configure --enable-ub=i386,x86_64
+@end example
diff --git a/doc/texi/build/platform.solaris.texi b/doc/texi/build/platform.solaris.texi
new file mode 100644
index 0000000..87e9959
--- /dev/null
+++ b/doc/texi/build/platform.solaris.texi
@@ -0,0 +1,16 @@
+@section @value{OS.solaris}
+Building on @value{OS.solaris} is supported. The following are the recommended specifications for this platform; but is not necessarily the only configuration that is possible:
+
+@itemize @bullet
+@item Intel 32-bit or 64-bit hardware
+@item @value{OS.solaris} 10u6, gcc 3.4.3
+@item gcc 3.4.0 or higher is reported to work
+@end itemize
+
+@include build/platform.common.bundled.texi
+@quotation Note
+@value{OS.solaris} does not (yet) really bundle a compiler. The recommendation is to use the companion-disk compiler for maximum C++ runtime compatibility. It is usually found in @file{/usr/sfw/bin}.
+@end quotation
+
+@include build/platform.common.conf.default.texi
+@include build/platform.common.conf.bi.texi
diff --git a/doc/texi/build/platform.windows.texi b/doc/texi/build/platform.windows.texi
new file mode 100644
index 0000000..ace30b9
--- /dev/null
+++ b/doc/texi/build/platform.windows.texi
@@ -0,0 +1,18 @@
+@section @value{OS.windows}
+Native builds on @value{OS.windows} is supported via Microsoft's Visual Studio package. Both the commercial version and free version (express) are known to work. The following are the recommended specifications for this platform; but is not necessarily the only configuration that is possible:
+
+@itemize @bullet
+@item Intel 32-bit or 64-bit hardware
+@item @value{OS.windows} 2000 or higher, Visual Studio 9.0 (aka. Visual Studio 2008)
+@item Visual Studio 9.0 Express is reported to work
+@end itemize
+
+Only 32-bit binaries are targeted, and win32-API is set to @value{OS.windows} 2000 or higher. Older versions of @value{OS.windows}, or win32-API are not supported.
+
+@value{PROJECT.name} has directory @file{vstudio9.0/} which contains the necessary solution+project files to produce a basic build of libmp4v2's DLL and several command-line executables. Enabling things such as debugging, optimization, etc, are all left as an exercise to the user.
+
+@quotation Warning
+Project meta-data is stored in header @file{project.h}. A proper source distribution is built using autotools and generates @file{TOP/include/mp4v2/project.h} correctly, which is then bundled with our source distribution. This is adequate for building on the @value{OS.windows} platform.
+
+However, if you are building from the repository, be warned that there is no method to automatically generate @file{project.h} on Windows. Instead, we periodically checkin a copy of this file (generated using autotools) as @file{vstudio9.0/include/mp4v2/project.h} which may from time to time get out of date. If it is significantly out of date, you should find the latest source distribution and copy the @file{project.h} from there.
+@end quotation
diff --git a/doc/texi/build/platforms.texi b/doc/texi/build/platforms.texi
new file mode 100644
index 0000000..ae6f8f2
--- /dev/null
+++ b/doc/texi/build/platforms.texi
@@ -0,0 +1,11 @@
+@chapter Platform Notes
+@value{PROJECT.name} builds on many unix-style platforms, also commonly referred to as posix-style systems. Building on @value{OS.osx}, @value{OS.linux}, @value{OS.freebsd}, @value{OS.solaris}, @value{OS.cygwin}, @value{OS.windows} are known to work.
+
+Similar platforms should also work. Please see the following platform specific notes for instructions on commonly used options for various platforms.
+
+@include build/platform.osx.texi
+@include build/platform.linux.texi
+@include build/platform.freebsd.texi
+@include build/platform.solaris.texi
+@include build/platform.cygwin.texi
+@include build/platform.windows.texi
diff --git a/doc/texi/build/process.bootstrap.texi b/doc/texi/build/process.bootstrap.texi
new file mode 100644
index 0000000..f8153e9
--- /dev/null
+++ b/doc/texi/build/process.bootstrap.texi
@@ -0,0 +1,15 @@
+@section Boostrap (Autotools)
+
+The following command causes forces Autotools to regenerate all files and install helper scripts needed at configure-time and to regenerate all files.
+
+@example
+@COMMAND.bootstrap{}
+@end example
+
+If you are a project member and preparing for a release, it is important to note that the versions of Autotools available in your path will directly effect files added to the bundle. At the time of writing, the following versions of Autotools are recommended; in some cases a minimum is hard-coded and warnings will be issued if in violation:
+
+@itemize
+@item GNU autoconf 2.61 or higher (lower versions might work)
+@item GNU automake 1.10 or higher (lower versions might work)
+@item GNU libtool 1.5.26 or higher (lower versions might work)
+@end itemize
diff --git a/doc/texi/build/process.build.texi b/doc/texi/build/process.build.texi
new file mode 100644
index 0000000..5e9d7a8
--- /dev/null
+++ b/doc/texi/build/process.build.texi
@@ -0,0 +1,9 @@
+@section Build
+
+The following command will build @value{PROJECT.name}.
+
+@example
+@COMMAND.build{}
+@end example
+
+On some platforms @code{make} refers to a BSD-flavor of make which is not compatible with this project. Check if @code{gmake} is installed, and if it is, substitute @code{gmake} wherever you may see @code{make} in this document. Otherwise you will need to install GNU make package version 3.81 or higher. Lower versions might work.
diff --git a/doc/texi/build/process.checkout.texi b/doc/texi/build/process.checkout.texi
new file mode 100644
index 0000000..5bf371a
--- /dev/null
+++ b/doc/texi/build/process.checkout.texi
@@ -0,0 +1,14 @@
+@section Checkout Sources
+
+Checkout sources from the project's Subversion repository.
+
+Sources are checked out from either the trunk, release or a branch. This document was generated from one of those, and for example purposes, we will use exactly the same URL which used to create the distribution which contains this document.
+
+If you are a project member, then you may add the appropriate login/password information as needed.
+
+@example
+@COMMAND.checkout{}
+@end example
+
+It is recommended to use Subversion 1.5.0 or higher.
+Lower versions might work.
diff --git a/doc/texi/build/process.configure.texi b/doc/texi/build/process.configure.texi
new file mode 100644
index 0000000..19f427d
--- /dev/null
+++ b/doc/texi/build/process.configure.texi
@@ -0,0 +1,40 @@
+@anchor{Configure}
+@section Configure
+The following command configures the project for a build. It is highly recommended that you invoke configure from an empty directory.
+
+@example
+@COMMAND.configure{}
+@end example
+
+Please see @file{INSTALL} for details on configure usage, and standard options. Additionally, the following custom options have been added to @file{configure}:
+
+@table @samp
+
+@item --disable-debug
+Do not generate debug information. Do not direct compiler to generate debugging information. By default the compiler will generate debug information if the platform supports it.
+
+@item --disable-optimize
+Do not optimize. Do not direct compiler to optimize code. By default compiler optimization is enabled if the platform supports it.
+
+@item --disable-fvisibility
+Do not set default ELF symbol visibility. By default configure attempts to detect if the compiler supports this feature. However on some platforms detecting incompatibilty of this feature might not be accurate in which case this option should be given.
+
+@item --disable-gch
+By default certain platforms are marked to use GCC precompiled headers. Generally this greatly decrease build times but may require more diligence for iterative development; that is to say dependencies may not properly be tracked and more frequent @command{make clean} may be required when headers are changed. Use this option to disable GCC precompiled headers.
+
+@item --disable-largefile
+On some 32-bit platforms or configurations it might be desirable to build without largefile (LFS) support. By default configure attempts to detect formal LFS support and enables it if found.
+
+@item --disable-util
+Do not build/install utilities. This is convenience option for users who desire to skip building the utilities (eg. command-line executables) which are enabled by default.
+
+@item --enable-bi=ARCH
+On bi-arch capable platforms it is possible to generate 32 or 64 bit code. This is supported by adding arguments @samp{-m32} or @samp{-m64}, respectively, when compiling or linking. Use this option to override the platform-specific default.
+
+@item --enable-ub[=ARCHS]
+On OSX systems it is possible to generate universal binaries. This is supported by adding one or more argument patterns @samp{-arch ARCH} when compiling or linking. Use this option to either target an architecture different from the platform default, or to produce universal binaries.
+
+@item --enable-dependency-tracking
+Enable automatic dependency tracking for include-files. By default this feature is disabled.
+
+@end table
diff --git a/doc/texi/build/process.dist.texi b/doc/texi/build/process.dist.texi
new file mode 100644
index 0000000..2d8b10b
--- /dev/null
+++ b/doc/texi/build/process.dist.texi
@@ -0,0 +1,17 @@
+@section Create Distribution
+
+The following command will create a @value{PROJECT.name} source distribution. It is during this step that shipped documentation is generated.
+
+@example
+@COMMAND.dist{}
+@end example
+
+This step in the build process introduces additional requirements to the host system. While most of the following utilities are generally available, @command{help2man} is used to generate man-pages; however if this command is not available the man-pages will be empty. This is acceptable for non-release builds but for full quality builds this command is required.
+
+@itemize
+@item GNU help2man 1.36 or higher (lower versions should work)
+@item GNU tar 1.15.1 or higher (lower versions should work)
+@item GNU gzip 1.3.10 or higher (lower versions should work)
+@item bzip2 1.0.4 or higher (lower versions should work)
+@item Info-ZIP zip 2.32 or higher (lower versions should work)
+@end itemize
diff --git a/doc/texi/build/process.doc.texi b/doc/texi/build/process.doc.texi
new file mode 100644
index 0000000..be17bc3
--- /dev/null
+++ b/doc/texi/build/process.doc.texi
@@ -0,0 +1,64 @@
+@section Build Documentation
+
+This step in the build process introduces some significant requirements to the host system:
+
+@itemize
+@item GNU texinfo 4.8 or higher (lower versions should work)
+@item Doxygen 1.5.7 or higher (lower versions should work)
+@end itemize
+
+Documentation that is shipped with @value{TERM.srcdist} is generated as part of the @ref{Build Process} step. This section documents builds all of the supported methods to build documentation. There are three kinds of documentation in this project; man-pages, articles and API. @b{Documentation must be build from the repository}.
+
+Man-pages are automatically generated for command-line utilities by using @command{html2man} which invokes standard options @command{--help} and @command{--version} and gleans the information, generating a man-page in @b{nroff} script. Note that the utilities will first be built as they are depdendencies of man-page generation.
+
+Artcles are usually hand-written and authored in Texinfo format which permits macro-expansions, simple formatting and conversion to several popular formats using the GNU @command{makeinfo}. A Texinfo @url{http://www.gnu.org/software/texinfo,manual} is available.
+
+API is documented inline to C and C++ source files, usually headers using Doxygen comment-formatting. Doxygen is then used to post-process these files and generate documentation in various formats. A Doxygen manual is available at it's main @url{http://www.doxygen.org,site} .
+
+The project's goal is to document as thoroughly as possible the public API in @value{PROJECT.name}. Since we never have enough time to document everything, we try to set some priorities in this regard. Generally the public API is the highest priority to document. Next most important is probably underlying utility code which is shared by many developers; for example @b{libplatform}.
+
+If you need examples of how to document C-compatible source see @file{include/mp4v2/mp4v2.h} and for C++-only source
+see @file{libplatform/io/File.h} .
+
+The following table describes the various make targets available for building docs. Note you must first have completed the @ref{Configure} step.
+
+@table @samp
+
+@item make man
+Generate man-pages for command-line utilities.
+
+@item make html
+Generate articles in HTML format from @file{texi} files.
+
+@item make txt
+Generate articles in plaintext format from @file{texi} files.
+
+@item make wiki
+Generate articles in Google Code Wiki format from @file{texi} files.
+
+@item make xml
+Generate articles in (Texinfo) XML format from @file{texi} files.
+
+@item make api
+Generate API in HTML format from header files.
+
+@item make articles
+Convenience; the equivalent of @command{make html txt wiki xml} .
+
+@item make doc
+Convenience; the equivalent of @command{make man articles api} .
+
+@end table
+
+And finally all of the document targets have a corresponding @b{clean} target which cleans up generated files. Simply prefix as follows:
+
+@example
+make manclean
+make htmlclean
+make txtclean
+make wikiclean
+make xmlclean
+make apiclean
+make articlesclean
+make docclean
+@end example
diff --git a/doc/texi/build/process.extract.texi b/doc/texi/build/process.extract.texi
new file mode 100644
index 0000000..b019cac
--- /dev/null
+++ b/doc/texi/build/process.extract.texi
@@ -0,0 +1,22 @@
+@section Extract
+Extract sources from a @value{TERM.srcdist} bundle. Releases are available from @url{@value{PROJECT.url.website}} in the @url{@value{PROJECT.url.downloads},downloads} section.
+
+@example
+@COMMAND.extract{}
+@end example
+
+Older versions of @code{tar} may not automatically uncompress the bundle, so you might have to either enter additional flags manually, or first decompress the bundle before extracting. Some possible command variations for uncompressing a @file{bz2} file:
+
+@example
+tar xjf @value{PROJECT.name.lower}-@value{PROJECT.version}.tar.bz2
+bunzip2 -c @value{PROJECT.name.lower}-@value{PROJECT.version}.tar.bz2 | tar xf -
+bzcat @value{PROJECT.name.lower}-@value{PROJECT.version}.tar.bz2 | tar xf -
+@end example
+
+And for a @file{gz} file:
+
+@example
+tar xzf @value{PROJECT.name.lower}-@value{PROJECT.version}.tar.gz
+gunzip -c @value{PROJECT.name.lower}-@value{PROJECT.version}.tar.gz | tar xf -
+gzcat @value{PROJECT.name.lower}-@value{PROJECT.version}.tar.gz | tar xf -
+@end example
diff --git a/doc/texi/build/process.google.texi b/doc/texi/build/process.google.texi
new file mode 100644
index 0000000..52b4135
--- /dev/null
+++ b/doc/texi/build/process.google.texi
@@ -0,0 +1,24 @@
+@section Post Site and API Documentation to project website.
+
+This step is for project maintainers and can be used to update Site and API documentation. The following components are updated:
+
+@itemize
+@item Featured Wiki article: BuildRepository
+@item Featured Wiki article: BuildSource
+@item MP4v2 (trunk) docs (includes Release Notes and other articles, and API docs).
+@end itemize
+
+This procedure may only be run from a *nix platform and has only been tested on @value{OS.osx}.
+
+@table @samp
+
+@item make google.clean
+Clean any local working copy of google changeset.
+
+@item make google.post
+Generate required docs, sparse-checkout google tree, remove files which are no longer generated, add new files which are generated, and update existing files.
+
+@item svn ci -m "-refreshed GoogleCode site+api docs." google/.
+Check-in changes. This might take several minutes, especially if your upstream bandwidth is limited.
+
+@end table
diff --git a/doc/texi/build/process.install.texi b/doc/texi/build/process.install.texi
new file mode 100644
index 0000000..9087853
--- /dev/null
+++ b/doc/texi/build/process.install.texi
@@ -0,0 +1,8 @@
+@anchor{Install}
+@section Install
+
+The following command will install @value{PROJECT.name}.
+
+@example
+@COMMAND.install{}
+@end example
diff --git a/doc/texi/changelog/version-1.6.texi b/doc/texi/changelog/version-1.6.texi
new file mode 100644
index 0000000..4268820
--- /dev/null
+++ b/doc/texi/changelog/version-1.6.texi
@@ -0,0 +1,4 @@
+@enumerate
+@item
+Branched libmp4v2 module from mpeg4ip project version 1.6.1.
+@end enumerate
diff --git a/doc/texi/changelog/version-1.9.texi b/doc/texi/changelog/version-1.9.texi
new file mode 100644
index 0000000..8a6f8e4
--- /dev/null
+++ b/doc/texi/changelog/version-1.9.texi
@@ -0,0 +1,62 @@
+@enumerate
+@item
+Renamed public API top-level header to @code{<mp4v2/mp4v2.h>} and added namespaces for implementation (private) symbols. Only public API symbols are exported for dynamic (shared) or DLL libraries. All other symbols are now private, notwithstanding static-library usage.
+
+@item
+Added initial AC3 support.
+
+@item
+Added native Windows port. The port targets @code{WINVER 0x0500} which is Windows 2000 or higher.
+
+@item
+Added QuickTime and Nero chapter support. See @command{mp4chaps} command-line utility.
+@* Contributed by Ullrich Pollähne <u.pollaehne@@gmail.com>.
+
+@item
+Enhanced @command{mp4art} to support multiple cover-art atoms.
+
+@item
+Dropped @command{mp4dump} and replaced with @command{mp4file} which supports general file operations.
+
+@item
+Added @command{mp4track} with colr-box and pasp-box support.
+
+@item
+Fixed corruption of @b{udta.name} atom during read-in.
+
+@item
+Enhanced @command{mp4file --dump} to show hexdump-style canonical hex+ASCII data.
+
+@item
+Enhanced @command{mp4file --dump} to show human-readble value for tag @b{typeCode} values.
+
+@item
+Enhanced @command{mp4file --dump} to show human-readble value for ISO-639-2/T language codes.
+
+@item
+Added new public-API: MP4GetTrackLanguage().
+
+@item
+Added new public-API: MP4SetTrackLanguage().
+
+@item
+Added support for GCC precompiled-headers on various *nix platforms to speed up builds as we are using quite a few C++ headers.
+
+@item
+Enhanced @command{mp4track} to facilitate modification of @{ enabled, inmovie, inpreview, altgroup, volume, width, height, language, hdlrname, udtaname @} properties.
+
+@item
+Added new public-API: MP4GetTrackDurationPerChunk().
+
+@item
+Added new public-API: MP4SetTrackDurationPerChunk() to override default per-track chunk duration.
+
+@item
+Added new public-API: MP4WriteSampleDependency().
+
+@item
+Replaced (undocumented) public-API: MP4CreateEx() with MP4CreateProvider().
+
+@item
+Added new public-API for iTMF Generic functionality.
+@end enumerate
diff --git a/doc/texi/changelog/version-2.0.texi b/doc/texi/changelog/version-2.0.texi
new file mode 100644
index 0000000..ad57fac
--- /dev/null
+++ b/doc/texi/changelog/version-2.0.texi
@@ -0,0 +1,8 @@
+@enumerate
+@item
+Removed deprecated metadata/free-form API and replaced with iTMF Generic and Tags API.
+
+@item
+Added new public-API: MP4SetLogCallback().
+
+@end enumerate
diff --git a/doc/texi/releasenotes/intro.developer.texi b/doc/texi/releasenotes/intro.developer.texi
new file mode 100644
index 0000000..8260e9d
--- /dev/null
+++ b/doc/texi/releasenotes/intro.developer.texi
@@ -0,0 +1,5 @@
+@quotation Warning
+This is a @b{developer} release which includes all the normal pieces of a stable release but is considered @b{unstable}.
+The purpose of a developer release is to make available to @value{PROJECT.name} developers features which require collaborative testing.
+@end quotation
+
diff --git a/doc/texi/releasenotes/intro.stable.texi b/doc/texi/releasenotes/intro.stable.texi
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/texi/releasenotes/intro.stable.texi
diff --git a/doc/texi/tool/mp4art.texi b/doc/texi/tool/mp4art.texi
new file mode 100644
index 0000000..338e2f4
--- /dev/null
+++ b/doc/texi/tool/mp4art.texi
@@ -0,0 +1,55 @@
+@chapter mp4art
+This tool is used to manage iTunes Metadata Cover-art which is typically used to embed an image to a song file. For example, the songs in an album collection might all contain an image of the album cover art. This data is usually found in @samp{.m4a}, @samp{.m4v} and @samp{.mov} files.
+
+@table @samp
+@item --art-any
+act on all covr-boxes (default).
+Specifies the scope of the action to operate on all, if applicable, covr-boxes.
+
+@item --art-index IDX
+act on covr-box index IDX.
+Specifies the scope of the action to operate on single covr-box INDEX.
+@end table
+
+@table @samp
+@item --list
+list all covr-boxes.
+@example
+IDX BYTES CRC32 TYPE FILE
+----------------------------------------------------------------------
+ 0 173613 710a3ec9 JPEG 01 Life In Technicolor.m4a
+ 0 173613 710a3ec9 JPEG 02 Cemeteries Of London.m4a
+ 0 173613 710a3ec9 JPEG 03 Lost!.m4a
+ 0 173613 710a3ec9 JPEG 04 42.m4a
+ 0 173613 710a3ec9 JPEG 05 Lovers In Japan _ Reign Of Love.m4a
+ 0 173613 710a3ec9 JPEG 06 Yes.m4a
+ 0 173613 710a3ec9 JPEG 07 Viva La Vida.m4a
+ 0 173613 710a3ec9 JPEG 08 Violet Hill.m4a
+ 0 173613 710a3ec9 JPEG 09 Strawberry Swing.m4a
+ 0 173613 710a3ec9 JPEG 10 Death And All His Friends.m4a
+@end example
+
+@item --add IMG
+add covr-box from IMG file.
+
+@item --replace IMG
+replace covr-box with IMG file.
+
+@item --remove
+remove covr-box.
+
+@item --extract
+extract covr-box.
+This will extract all covr-box data to image files in the format of @samp{BASENAME.art[INDEX].TYPE} .
+
+Example, add PNG image file:
+@example
+mp4art --add ACDC.png mysong.m4a
+@end example
+
+Example, extract image files from file:
+@example
+mp4art --extract mysong.m4a
+@end example
+
+@end table
diff --git a/doc/texi/tool/mp4file.texi b/doc/texi/tool/mp4file.texi
new file mode 100644
index 0000000..123f0e1
--- /dev/null
+++ b/doc/texi/tool/mp4file.texi
@@ -0,0 +1,40 @@
+@chapter mp4file
+
+@table @samp
+@item --list
+list (summary information).
+This will produce brief report when summarizing each mp4 file.
+@b{BRAND} shows the file's main brand identifier.
+@b{COMPAT} shows additional brands for which the file purports to be comaptible with.
+@b{SIZING} displays if the file has 64-bit extensions of any kind, otherwise 32-bit.
+Example output:
+@example
+BRAND COMPAT SIZING FILE
+----------------------------------------------------------------------
+M4A M4A,isom,mp42 32-bit Song.m4a
+mp42 isom,mp42 32-bit Movie1.m4v
+mp42 isom,mp42 32-bit Movie2.m4v
+@end example
+
+@item --optimize
+optimize mp4 structure.
+This will rewrite the entire mp4 file which, if needed, will clean up
+any unused (free) sections, and re-order the atoms in a manner somewhat
+consistent with the best-practices described in the ISO base media file
+specification.
+
+@item --dump
+dump mp4 structure in human-readable format.
+An ASCII dump of mp4 atoms is printed to stdout. This action is heavily
+influenced by @samp{--debug} option.
+
+Example, list some files:
+@example
+mp4file --list *.mp4 *.m4a *.m4v
+@end example
+
+Example, dump a file with more than usual debugging information:
+@example
+mp4file -dd --dump movie.m4v
+@end example
+@end table
diff --git a/doc/texi/tool/mp4track.texi b/doc/texi/tool/mp4track.texi
new file mode 100644
index 0000000..8c5706e
--- /dev/null
+++ b/doc/texi/tool/mp4track.texi
@@ -0,0 +1,182 @@
+@chapter mp4track
+This tool is used to manage various aspects of individual tracks in an mp4 file. Some of the actions are mp4 (generic) while others may support standards based on mp4 files such as @samp{.m4a} or @samp{.m4v} files. Each action has an appropriate scope upon which it acts. See individual actions for details. The following parameters are used to set scopes for actions:
+
+@table @samp
+@item --track-any
+act on any/all tracks.
+
+@item --track-index IDX
+act on a single track specified by @b{index} value.
+A track index is 0-based and counts upwards for each track available.
+
+@item --track-id ID
+act on a single track specified by @b{id} value.
+A track id is a unique value assigned to each track and never changes.
+@end table
+
+The @b{list} action will produce a brief report of each track for each mp4 file.
+Many (but not all) of the values shown may be modified by actions documented later in this article.
+This will produce a brief report of each track for each mp4 file.
+
+@table @samp
+@item --list
+list all tracks in mp4.
+Example output:
+@example
+track[0] id=1
+ type = video
+ enabled = true
+ inMovie = false
+ inPreview = false
+ layer = 0
+ alternateGroup = 0
+ volume = 0.0000
+ width = 850.96295166
+ height = 360.00000000
+ language = UNDEFINED(0)
+ handlerName =
+ userDataName = <absent>
+@end example
+@end table
+
+The following group of actions are used to modify the values shown by @b{--list} action. The modification of these values should be done with great care on any files, and as always you are cautioned to @b{backup} your media files before modification.
+
+@table @samp
+@item --enabled BOOL
+set trak.tkhd.flags (enabled bit).
+When @b{true} indicates the track is enabled.
+
+@item --inmovie BOOL
+set trak.tkhd.flags (inMovie bit).
+When @b{true} indicates the track is used in the movie.
+
+@item --inpreview BOOL
+set trak.tkhd.flags (inPreview bit).
+When @b{true} indicates the track is used in the movie's preview.
+
+@item --layer NUM
+set trak.tkhd.layer.
+Specifies the front-to-back ordering of video tracks; tracks with lower numbers are closer to the viewer.
+@b{0} is the normal value, and @b{-1} would be in front of track 0, and so on.
+
+@item --altgroup NUM
+set trak.tkhd.alternate_group.
+An integer that specifies a group or collection of tracks. If this field is 0 there is no information on possible relations to other tracks. If this field is not 0, it should be the same for tracks that contain alternate data for one another and different for tracks belonging to different such groups. Only one track within an alternate group should be played or streamed at any one time, and must be distinguishable from other tracks in the group via attributes such as bitrate, codec, language, packet size etc. A group may have only one member.
+
+@item --volume FLOAT
+set trak.tkhd.volume.
+Specifies the track's relative audio volume. Full volume is @b{1.0} and is the normal value.
+
+@item --width FLOAT
+set trak.tkhd.width.
+Specifies the track's visual presentation width. By default this is the same as the pixel width of the images. All images in the sequence are scaled to this size @b{before} any overall transformation by the matrix.
+
+@item --height FLOAT
+set trak.tkhd.height.
+Specifies the track's visual presentation height. By default this is the same as the pixel width of the images. All images in the sequence are scaled to this size @b{before} any overall transformation by the matrix.
+
+@item --language CODE
+set trak.mdia.mdhd.language.
+Specifies the ISO-639-2/T langauge code of the track. For example, @samp{eng} for English, @samp{fra} for French.
+
+@item --hdlrname STR
+set trak.mdia.hdlr.name.
+Specifies a human-readable track type (for debugging and inspection purposes).
+
+@item --udtaname STR
+set trak.udta.name.value.
+Specifies an arbitrary track-name. This value is optional (may be absent).
+
+@item --udtaname-remove
+remove trak.udta.name atom.
+This action will remove the @b{optional} atom.
+
+@end table
+
+The @b{colr} related actions manage @b{Color Parameter} boxes which are used by QuickTime to map numerical values of pixels in a file to a common representation of color for video tracks. They may or may not be suitable for other Apple media players. Community feedback on compatibility is welcome.
+
+@table @samp
+@item --colr-list
+list all colr-boxes in mp4.
+
+@item --colr-add
+add colr-box to a video track.
+An individual track must be specified.
+
+@item --colr-set
+set colr-box parms.
+An individual track must be specified.
+
+@item --colr-remove
+remove colr-box from track.
+By default all colr-boxes will be removed unless an individual track is specified.
+
+@item --colr-parms CSV
+where CSV is IDX1,IDX2,IDX3 .
+Specify the exact parameters of an NCLC Color Parameter box as specified in the QuickTime specification.
+IDX1 correlates to the 16-bit primaries index.
+IDX2 correlates to the 16-bit transferFunction index.
+IDX3 correlates to the 16-bit matrixIndex index.
+Effects actions --colr-add, --colr-set.
+
+@item --colr-parm-hd
+equivalent to --colr-parms=1,1,1 .
+This is a convenience setting generally suitable for HD content.
+Effects actions --colr-add, --colr-set.
+
+@item --colr-parm-sd
+equivalent to --colr-parms=6,1,6 .
+This is a convenience setting generally suitable for SD content.
+Effects actions --colr-add, --colr-set.
+
+Example, add a colr-box tuned for HD content:
+@example
+mp4track --track-id=1 --colr-add --colr-parm-hd mymovie.m4v
+@end example
+
+Example, add a colr-box with arbitrary index parameters:
+@example
+mp4track --track-id=1 --colr-add --colr-parms=2,3,4 mymovie.m4v
+@end example
+
+@end table
+
+The @b{pasp} related actions manage @b{Picture Aspect Ratio} boxes which are used by QuickTime to specify height-to-width ratio of pixels for video tracks. They may or may not be suitable for other Apple media players. Community feedback on compatibility is welcome.
+
+@table @samp
+@item --pasp-list
+list all pasp-boxes in mp4.
+
+@item --pasp-add
+add pasp-box to a video track.
+An individual track must be specified.
+
+@item --pasp-set
+set pasp-box parms.
+An individual track must be specified.
+
+@item --pasp-remove
+remove pasp-box from track
+By default all pasp-boxes will be removed unless an individual track is specified.
+
+@item --pasp-parms CSV
+where CSV is hSPACING,vSPACING.
+Specify the exact parameters of Picture Aspect Ratio box as specified in the QuickTime specification.
+Effects actions --pasp-add, --pasp-set.
+
+Example, add a pasp-box with default (1,1) parameters for square pixels:
+@example
+mp4track --track-id=1 --pasp-add --pasp-parms=1,1 mymovie.m4v
+@end example
+
+Example, add a pasp-box for 16:9 digital 525 (NTSC):
+@example
+mp4track --track-id=1 --pasp-add --pasp-parms=40,33 mymovie.m4v
+@end example
+
+Example, add a pasp-box for 16:9 digital 625 (PAL):
+@example
+mp4track --track-id=1 --pasp-add --pasp-parms=118,81 mymovie.m4v
+@end example
+
+@end table
diff --git a/example/itmf/generic.c b/example/itmf/generic.c
new file mode 100644
index 0000000..3de14f2
--- /dev/null
+++ b/example/itmf/generic.c
@@ -0,0 +1,96 @@
+/* This is an example of iTMF Generic API.
+ * WARNING: this program will change/destroy certain tags in an mp4 file.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <mp4v2/mp4v2.h>
+
+int main( int argc, char** argv )
+{
+ if( argc != 2 ) {
+ printf( "usage: %s file.mp4\n", argv[0] );
+ return 1;
+ }
+
+ /* open file for modification */
+ MP4FileHandle file = MP4Modify( argv[1], MP4_DETAILS_ERROR, 0 );
+ if( file == MP4_INVALID_FILE_HANDLE ) {
+ printf( "MP4Modify failed\n" );
+ return 1;
+ }
+
+ /* show existing iTMF items */
+ MP4ItmfItemList* list = MP4ItmfGetItems( file );
+ printf( "list=%p\n", list );
+ if( list ) {
+ printf( "list size=%u\n", list->size );
+ uint32_t i;
+ for( i = 0; i < list->size; i++ ) {
+ MP4ItmfItem* item = &list->elements[i];
+ printf( "item[%u] type=%s\n", i, item->code );
+
+ if( item->mean )
+ printf( " mean=%s\n", item->mean );
+ if( item->name )
+ printf( " name=%s\n", item->name );
+
+ int j;
+ for( j = 0; j < item->dataList.size; j++ ) {
+ MP4ItmfData* data = &item->dataList.elements[j];
+ printf( " data[%u] typeCode=%u valueSize=%u\n", j, data->typeCode, data->valueSize );
+ }
+ }
+
+ /* caller responsiblity to free */
+ MP4ItmfItemListFree( list );
+ }
+
+ /* add bogus item to file */
+ {
+ /* allocate item with 1 data element */
+ MP4ItmfItem* bogus = MP4ItmfItemAlloc( "bogu", 1 );
+
+ const char* const hello = "hello one";
+
+ MP4ItmfData* data = &bogus->dataList.elements[0];
+ data->typeCode = MP4_ITMF_BT_UTF8;
+ data->valueSize = strlen( hello );
+ data->value = (uint8_t*)malloc( data->valueSize );
+ memcpy( data->value, hello, data->valueSize );
+
+ /* add to mp4 file */
+ MP4ItmfAddItem( file, bogus );
+
+ /* caller responsibility to free */
+ MP4ItmfItemFree( bogus );
+ }
+
+ /* add bogus item with meaning and name to file */
+ {
+ /* allocate item with 1 data element */
+ MP4ItmfItem* bogus = MP4ItmfItemAlloc( "----", 1 );
+ bogus->mean = strdup( "com.garden.Tomato" );
+ bogus->name = strdup( "weight" );
+
+ const char* const hello = "hello two";
+
+ MP4ItmfData* data = &bogus->dataList.elements[0];
+ data->typeCode = MP4_ITMF_BT_UTF8;
+ data->valueSize = strlen( hello );
+ data->value = (uint8_t*)malloc( data->valueSize );
+ memcpy( data->value, hello, data->valueSize );
+
+ /* add to mp4 file */
+ MP4ItmfAddItem( file, bogus );
+
+ /* caller responsibility to free */
+ MP4ItmfItemFree( bogus );
+ }
+
+ /* free memory associated with structure and close */
+ MP4Close( file );
+
+ return 0;
+}
diff --git a/example/itmf/tags.c b/example/itmf/tags.c
new file mode 100644
index 0000000..a915865
--- /dev/null
+++ b/example/itmf/tags.c
@@ -0,0 +1,277 @@
+/* This is an example of iTMF Tags convenience API.
+ * WARNING: this program will change/destroy many tags in an mp4 file.
+ */
+
+#include <mp4v2/mp4v2.h>
+
+int main( int argc, char** argv )
+{
+ if( argc != 2 ) {
+ printf( "usage: %s file.mp4\n", argv[0] );
+ return 1;
+ }
+
+ /* open file for modification */
+ MP4FileHandle file = MP4Modify( argv[1], MP4_DETAILS_ERROR, 0 );
+ if( file == MP4_INVALID_FILE_HANDLE ) {
+ printf( "MP4Modify failed\n" );
+ return 1;
+ }
+
+ /* allocate */
+ const MP4Tags* tags = MP4TagsAlloc();
+
+ /* fetch data from MP4 file and populate structure */
+ MP4TagsFetch( tags, file );
+
+ /***************************************************************************
+ * print various tag values
+ */
+
+ if( tags->name )
+ printf( "name: %s\n", tags->name );
+
+ if( tags->artist )
+ printf( "artist: %s\n", tags->artist );
+
+ if( tags->albumArtist )
+ printf( "albumArtist: %s\n", tags->albumArtist );
+
+ if( tags->album )
+ printf( "album: %s\n", tags->album );
+
+ if( tags->grouping )
+ printf( "grouping: %s\n", tags->grouping );
+
+ if( tags->composer )
+ printf( "composer: %s\n", tags->composer );
+
+ if( tags->comments )
+ printf( "comments: %s\n", tags->comments );
+
+ if( tags->genre )
+ printf( "genre: %s\n", tags->genre );
+
+ if( tags->genreType )
+ printf( "genreType: %u\n", *tags->genreType );
+
+ if( tags->releaseDate )
+ printf( "releaseDate: %s\n", tags->releaseDate );
+
+ if( tags->track )
+ printf( "track: index=%u total=%u\n", tags->track->index, tags->track->total );
+
+ if( tags->disk )
+ printf( "disk: index=%u total=%u\n", tags->disk->index, tags->disk->total );
+
+ if( tags->tempo )
+ printf( "tempo: %u\n", *tags->tempo );
+
+ if( tags->compilation )
+ printf( "compilation: %u\n", *tags->compilation );
+
+ if( tags->tvShow )
+ printf( "tvShow: %s\n", tags->tvShow );
+
+ if( tags->tvNetwork )
+ printf( "tvNetwork: %s\n", tags->tvNetwork );
+
+ if( tags->tvEpisodeID )
+ printf( "tvEpisodeID: %s\n", tags->tvEpisodeID );
+
+ if( tags->tvSeason )
+ printf( "tvSeason: %u\n", *tags->tvSeason );
+
+ if( tags->tvEpisode )
+ printf( "tvEpisode: %u\n", *tags->tvEpisode );
+
+ if( tags->description )
+ printf( "description: %s\n", tags->description );
+
+ if( tags->longDescription )
+ printf( "longDescription: %s\n", tags->longDescription );
+
+ if( tags->lyrics )
+ printf( "lyrics: %s\n", tags->lyrics );
+
+ if( tags->sortName )
+ printf( "sortName: %s\n", tags->sortName );
+
+ if( tags->sortArtist )
+ printf( "sortArtist: %s\n", tags->sortArtist );
+
+ if( tags->sortAlbumArtist )
+ printf( "sortAlbumArtist: %s\n", tags->sortAlbumArtist );
+
+ if( tags->sortAlbum )
+ printf( "sortAlbum: %s\n", tags->sortAlbum );
+
+ if( tags->sortComposer )
+ printf( "sortComposer: %s\n", tags->sortComposer );
+
+ if( tags->sortTVShow )
+ printf( "sortTVShow: %s\n", tags->sortTVShow );
+
+ if( tags->artworkCount ) {
+ const MP4TagArtwork* art = tags->artwork; /* artwork != NULL when artworkCount > 0 */
+ uint32_t i;
+ for( i = 0; i < tags->artworkCount; i++, art++ )
+ printf( "art[%d]: type=%d size=%u data=%p\n", i, art->type, art->size, art->data );
+ }
+
+ if( tags->copyright )
+ printf( "copyright: %s\n", tags->copyright );
+
+ if( tags->encodingTool )
+ printf( "encodingTool: %s\n", tags->encodingTool );
+
+ if( tags->encodedBy )
+ printf( "encodedBy: %s\n", tags->encodedBy );
+
+ if( tags->purchaseDate )
+ printf( "purchaseDate: %s\n", tags->purchaseDate );
+
+ if( tags->podcast )
+ printf( "podcast: %u\n", *tags->podcast );
+
+ if( tags->keywords )
+ printf( "keywords: %s\n", tags->keywords );
+
+ if( tags->category )
+ printf( "category: %s\n", tags->category );
+
+ if( tags->hdVideo )
+ printf( "hdVideo: %u\n", *tags->hdVideo );
+
+ if( tags->mediaType )
+ printf( "mediaType: %u\n", *tags->mediaType );
+
+ if( tags->contentRating )
+ printf( "contentRating: %u\n", *tags->contentRating );
+
+ if( tags->gapless )
+ printf( "gapless: %u\n", *tags->gapless );
+
+ if( tags->contentID )
+ printf( "contentID: %u\n", *tags->contentID );
+
+ if( tags->artistID )
+ printf( "artistID: %u\n", *tags->artistID );
+
+ if( tags->playlistID )
+ printf( "playlistID: %llu\n", *tags->playlistID );
+
+ if( tags->genreID )
+ printf( "genreID: %u\n", *tags->genreID );
+
+ if( tags->xid )
+ printf( "xid: %s\n", tags->xid );
+
+ if( tags->iTunesAccount )
+ printf( "iTunesAccount: %s\n", tags->iTunesAccount );
+
+ if( tags->iTunesAccountType )
+ printf( "iTunesAccountType: %u\n", *tags->iTunesAccountType );
+
+ if( tags->iTunesCountry )
+ printf( "iTunesCountry: %u\n", *tags->iTunesCountry );
+
+ /**************************************************************************
+ * modify various tags values
+ */
+
+ uint8_t n8;
+ uint16_t n16;
+ uint32_t n32;
+ uint64_t n64;
+
+ MP4TagTrack dtrack;
+ dtrack.index = 1;
+ dtrack.total = 1;
+
+ MP4TagDisk ddisk;
+ ddisk.index = 1;
+ ddisk.total = 1;
+
+ MP4TagsSetName ( tags, "my name" );
+ MP4TagsSetArtist ( tags, "my artist" );
+ MP4TagsSetAlbumArtist ( tags, "my albumArtist" );
+ MP4TagsSetAlbum ( tags, "my album" );
+ MP4TagsSetGrouping ( tags, "my grouping" );
+ MP4TagsSetComposer ( tags, "my composer" );
+ MP4TagsSetComments ( tags, "my comments" );
+ MP4TagsSetGenre ( tags, "my genre" );
+ n16 = 5; /* disco */
+ MP4TagsSetGenreType ( tags, &n16 );
+ MP4TagsSetReleaseDate ( tags, "my releaseDate" );
+ MP4TagsSetTrack ( tags, &dtrack );
+ MP4TagsSetDisk ( tags, &ddisk );
+ n16 = 60; /* bpm */
+ MP4TagsSetTempo ( tags, &n16 );
+ n8 = 0; /* false */
+ MP4TagsSetCompilation ( tags, &n8 );
+
+ MP4TagsSetTVShow ( tags, "my tvShow" );
+ MP4TagsSetTVNetwork ( tags, "my tvNetwork" );
+ MP4TagsSetTVEpisodeID ( tags, "my tvEpisodeID" );
+ n32 = 0;
+ MP4TagsSetTVSeason ( tags, &n32 );
+ n32 = 0;
+ MP4TagsSetTVEpisode ( tags, &n32 );
+
+ MP4TagsSetDescription ( tags, "my description" );
+ MP4TagsSetLongDescription ( tags, "my longDescription" );
+ MP4TagsSetLyrics ( tags, "my lyrics" );
+
+ MP4TagsSetSortName ( tags, "my sortName" );
+ MP4TagsSetSortArtist ( tags, "my sortArtist" );
+ MP4TagsSetSortAlbumArtist ( tags, "my sortAlbumArtist" );
+ MP4TagsSetSortAlbum ( tags, "my sortAlbum" );
+ MP4TagsSetSortComposer ( tags, "my sortComposer" );
+ MP4TagsSetSortTVShow ( tags, "my sortTVShow" );
+
+ MP4TagsSetCopyright ( tags, "my copyright" );
+ MP4TagsSetEncodingTool ( tags, "my encodingTool" );
+ MP4TagsSetEncodedBy ( tags, "my encodedBy" );
+ MP4TagsSetPurchaseDate ( tags, "my purchaseDate" );
+
+ n8 = 0; /* false */
+ MP4TagsSetPodcast ( tags, &n8 );
+ MP4TagsSetKeywords ( tags, "my keywords" );
+ MP4TagsSetCategory ( tags, "my category" );
+
+ n8 = 0; /* false */
+ MP4TagsSetHDVideo ( tags, &n8 ); // false
+ n8 = 9; /* movie */
+ MP4TagsSetMediaType ( tags, &n8 ); // movie
+ n8 = 0; /* none */
+ MP4TagsSetContentRating ( tags, &n8 ); // none
+ n8 = 0; /* false */
+ MP4TagsSetGapless ( tags, &n8 ); // false
+
+ MP4TagsSetITunesAccount ( tags, "my iTunesAccount" );
+ n8 = 0; /* iTunes */
+ MP4TagsSetITunesAccountType ( tags, &n8 );
+ n32 = 143441; /* USA */
+ MP4TagsSetITunesCountry ( tags, &n32 );
+ n32 = 0;
+ MP4TagsSetContentID ( tags, &n32 );
+ n32 = 0;
+ MP4TagsSetArtistID ( tags, &n32 );
+ n64 = 0;
+ MP4TagsSetPlaylistID ( tags, &n64 );
+ n32 = 0;
+ MP4TagsSetGenreID ( tags, &n32 );
+ n32 = 0;
+ MP4TagsSetComposerID ( tags, &n32 );
+ MP4TagsSetXID ( tags, "my prefix:my scheme:my identifier" );
+
+ /* push data to mp4 file */
+ MP4TagsStore( tags, file );
+
+ /* free memory associated with structure and close */
+ MP4TagsFree( tags );
+ MP4Close( file );
+
+ return 0;
+}
diff --git a/example/provider/provider.c b/example/provider/provider.c
new file mode 100644
index 0000000..03e55e2
--- /dev/null
+++ b/example/provider/provider.c
@@ -0,0 +1,88 @@
+/* This example makes use of the MP4FileProvider API to use custom file
+ * input/output routines.
+ */
+
+#include <mp4v2/mp4v2.h>
+#include <stdio.h>
+
+/*****************************************************************************/
+
+static void* my_open( const char* name, MP4FileMode mode )
+{
+ const char* om;
+ switch( mode ) {
+ case FILEMODE_READ: om = "rb"; break;
+ case FILEMODE_MODIFY: om = "r+b"; break;
+ case FILEMODE_CREATE: om = "w+b"; break;
+
+ case FILEMODE_UNDEFINED:
+ default:
+ om = "rb";
+ break;
+ }
+
+ return fopen( name, om );
+}
+
+static int my_seek( void* handle, int64_t pos )
+{
+ return fseeko( (FILE*)handle, pos, SEEK_SET ) != 0;
+}
+
+static int my_read( void* handle, void* buffer, int64_t size, int64_t* nin, int64_t maxChunkSize )
+{
+ if( fread( buffer, size, 1, (FILE*)handle ) != 1)
+ return 1;
+ *nin = size;
+ return 0;
+}
+
+static int my_write( void* handle, const void* buffer, int64_t size, int64_t* nout, int64_t maxChunkSize )
+{
+ if( fwrite( buffer, size, 1, (FILE*)handle ) != 1)
+ return 1;
+ *nout = size;
+ return 0;
+}
+
+static int my_close( void* handle )
+{
+ return fclose( (FILE*)handle ) != 0;
+}
+
+/*****************************************************************************/
+
+int main( int argc, char** argv )
+{
+ if( argc != 2 ) {
+ printf( "usage: %s file.mp4\n", argv[0] );
+ return 1;
+ }
+
+ /* populate data structure with custom functions.
+ * safe to put on stack as it will be immediately copied internally.
+ */
+ MP4FileProvider provider;
+
+ provider.open = my_open;
+ provider.seek = my_seek;
+ provider.read = my_read;
+ provider.write = my_write;
+ provider.close = my_close;
+
+ /* open file for read */
+ MP4FileHandle file = MP4ReadProvider( argv[1], 0, &provider );
+ if( file == MP4_INVALID_FILE_HANDLE ) {
+ printf( "MP4Read failed\n" );
+ return 1;
+ }
+
+ /* dump file contents */
+ if( !MP4Dump( file, stdout, 0 ))
+ printf( "MP4Dump failed\n" );
+
+ /* cleanup and close */
+ MP4Close( file );
+
+ return 0;
+}
diff --git a/include/mp4v2/chapter.h b/include/mp4v2/chapter.h
new file mode 100644
index 0000000..5b493a5
--- /dev/null
+++ b/include/mp4v2/chapter.h
@@ -0,0 +1,176 @@
+#ifndef MP4V2_CHAPTER_H
+#define MP4V2_CHAPTER_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_chapter MP4v2 Chapter
+ * @{
+ *
+ *****************************************************************************/
+
+/** The maximum length of a QuickTime chapter title (in 8-bit chars)
+ */
+#define MP4V2_CHAPTER_TITLE_MAX 1023
+
+/** Chapter item.
+ * This item defines various attributes for a chapter.
+ * @ingroup mp4_chapter
+ */
+typedef struct MP4Chapter_s {
+ MP4Duration duration; /**< duration of chapter in milliseconds */
+ char title[MP4V2_CHAPTER_TITLE_MAX+1]; /**< title of chapter */
+} MP4Chapter_t;
+
+/** Known chapter types.
+ * @ingroup mp4_chapter
+ */
+typedef enum {
+ MP4ChapterTypeNone = 0, /**< no chapters found return value */
+ MP4ChapterTypeAny = 1, /**< any or all known chapter types */
+ MP4ChapterTypeQt = 2, /**< QuickTime chapter type */
+ MP4ChapterTypeNero = 4 /**< Nero chapter type */
+} MP4ChapterType;
+
+/** Add a QuickTime chapter.
+ *
+ * This function adds a QuickTime chapter to file <b>hFile</b>.
+ *
+ * @param hFile handle of file to add chapter.
+ * @param chapterTrackId ID of chapter track or #MP4_INVALID_TRACK_ID
+ * if unknown.
+ * @param chapterDuration duration (in the timescale of the chapter track).
+ * @param chapterTitle title text for the chapter or NULL to use default
+ * title format ("Chapter %03d", n) where n is the chapter number.
+ */
+MP4V2_EXPORT
+void MP4AddChapter(
+ MP4FileHandle hFile,
+ MP4TrackId chapterTrackId,
+ MP4Duration chapterDuration,
+ const char* chapterTitle DEFAULT(0));
+
+/** Add a QuickTime chapter track.
+ *
+ * This function adds a chapter (text) track to file <b>hFile</b>.
+ * The optional parameter <b>timescale</b> may be supplied to give the new
+ * chapter a specific timescale. Otherwise the chapter track will have
+ * the same timescale as the reference track defined in parameter refTrackId.
+ *
+ * @param hFile handle of file to add chapter track.
+ * @param refTrackId ID of the track that will reference the chapter track.
+ * @param timescale the timescale of the chapter track or 0 to use the
+ * timescale of track specified by <b>refTrackId</b>.
+ *
+ * @return ID of the created chapter track.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddChapterTextTrack(
+ MP4FileHandle hFile,
+ MP4TrackId refTrackId,
+ uint32_t timescale DEFAULT(0) );
+
+/** Add a Nero chapter.
+ *
+ * This function adds a Nero chapter to file <b>hFile</b>.
+ *
+ * @param hFile handle of file to add chapter.
+ * @param chapterStart the start time of the chapter in 100 nanosecond units
+ * @param chapterTitle title text for the chapter or NULL to use default
+ * title format ("Chapter %03d", n) where n is the chapter number.
+ */
+MP4V2_EXPORT
+void MP4AddNeroChapter(
+ MP4FileHandle hFile,
+ MP4Timestamp chapterStart,
+ const char* chapterTitle DEFAULT(0));
+
+/** Convert chapters to another type.
+ *
+ * This function converts existing chapters in file <b>hFile</b>
+ * from one type to another type.
+ * Conversion from Nero to QuickTime or QuickTime to Nero is supported.
+ *
+ * @param hFile handle of file to convert.
+ * @param toChapterType the chapter type to convert to:
+ * @li #MP4ChapterTypeQt (convert from Nero to Qt)
+ * @li #MP4ChapterTypeNero (convert from Qt to Nero)
+ *
+ * @return the chapter type before conversion or #MP4ChapterTypeNone
+ * if the source chapters do not exist
+ * or invalid <b>toChapterType</b> was specified.
+ */
+MP4V2_EXPORT
+MP4ChapterType MP4ConvertChapters(
+ MP4FileHandle hFile,
+ MP4ChapterType toChapterType DEFAULT(MP4ChapterTypeQt));
+
+/** Delete chapters.
+ *
+ * This function deletes existing chapters in file <b>hFile</b>.
+ *
+ * @param hFile handle of file to delete chapters.
+ * @param chapterType the type of chapters to delete:
+ * @li #MP4ChapterTypeAny (delete all known chapter types)
+ * @li #MP4ChapterTypeQt
+ * @li #MP4ChapterTypeNero
+ * @param chapterTrackId ID of the chapter track if known,
+ * or #MP4_INVALID_TRACK_ID.
+ * Only applies when <b>chapterType</b>=#MP4ChapterTypeQt.
+ *
+ * @return the type of deleted chapters
+ */
+MP4V2_EXPORT
+MP4ChapterType MP4DeleteChapters(
+ MP4FileHandle hFile,
+ MP4ChapterType chapterType DEFAULT(MP4ChapterTypeQt),
+ MP4TrackId chapterTrackId DEFAULT(MP4_INVALID_TRACK_ID) );
+
+/** Get list of chapters.
+ *
+ * This function gets a chpter list from file <b>hFile</b>.
+ *
+ * @param hFile handle of file to read.
+ * @param chapterList address receiving array of chapter items.
+ * If a non-NULL is received the caller is responsible for freeing the
+ * memory with MP4Free().
+ * @param chapterCount address receiving count of items in array.
+ * @param chapterType the type of chapters to read:
+ * @li #MP4ChapterTypeAny (any chapters, searched in order of Qt, Nero)
+ * @li #MP4ChapterTypeQt
+ * @li #MP4ChapterTypeNero
+ *
+ * @result the first type of chapters found.
+ */
+MP4V2_EXPORT
+MP4ChapterType MP4GetChapters(
+ MP4FileHandle hFile,
+ MP4Chapter_t** chapterList,
+ uint32_t* chapterCount,
+ MP4ChapterType chapterType DEFAULT(MP4ChapterTypeQt));
+
+/** Set list of chapters OKOK.
+ *
+ * This functions sets the complete chapter list in file <b>hFile</b>.
+ * If any chapters of the same type already exist they will first
+ * be deleted.
+ *
+ * @param hFile handle of file to modify.
+ * @param chapterList array of chapters items.
+ * @param chapterCount count of items in array.
+ * @param chapterType type of chapters to write:
+ * @li #MP4ChapterTypeAny (chapters of all types are written)
+ * @li #MP4ChapterTypeQt
+ * @li #MP4ChapterTypeNero
+ *
+ * @return the type of chapters written.
+ */
+MP4V2_EXPORT
+MP4ChapterType MP4SetChapters(
+ MP4FileHandle hFile,
+ MP4Chapter_t* chapterList,
+ uint32_t chapterCount,
+ MP4ChapterType chapterType DEFAULT(MP4ChapterTypeQt));
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_CHAPTER_H */
diff --git a/include/mp4v2/file.h b/include/mp4v2/file.h
new file mode 100644
index 0000000..b2124d2
--- /dev/null
+++ b/include/mp4v2/file.h
@@ -0,0 +1,435 @@
+#ifndef MP4V2_FILE_H
+#define MP4V2_FILE_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_file MP4v2 File I/O
+ * @{
+ *
+ *****************************************************************************/
+
+/** Bit: enable 64-bit data-atoms. */
+#define MP4_CREATE_64BIT_DATA 0x01
+/** Bit: enable 64-bit time-atoms. @note Incompatible with QuickTime. */
+#define MP4_CREATE_64BIT_TIME 0x02
+/** Bit: do not recompute avg/max bitrates on file close. @note See http://code.google.com/p/mp4v2/issues/detail?id=66 */
+#define MP4_CLOSE_DO_NOT_COMPUTE_BITRATE 0x01
+
+/** Enumeration of file modes for custom file provider. */
+typedef enum MP4FileMode_e
+{
+ FILEMODE_UNDEFINED, /**< undefined */
+ FILEMODE_READ, /**< file may be read */
+ FILEMODE_MODIFY, /**< file may be read/written */
+ FILEMODE_CREATE /**< file will be created/truncated for read/write */
+} MP4FileMode;
+
+/** Structure of functions implementing custom file provider.
+ *
+ * Except for <b>open</b>, all the functions must return a true value
+ * to indicate failure or false on success. The open function must return
+ * a pointer or handle which represents the open file, otherwise NULL.
+ *
+ * maxChunkSize is a hint suggesting what the max size of data should be read
+ * as in underlying read/write operations. A value of 0 indicates there is no hint.
+ */
+typedef struct MP4FileProvider_s
+{
+ void* ( *open )( const char* name, MP4FileMode mode );
+ int ( *seek )( void* handle, int64_t pos );
+ int ( *read )( void* handle, void* buffer, int64_t size, int64_t* nin, int64_t maxChunkSize );
+ int ( *write )( void* handle, const void* buffer, int64_t size, int64_t* nout, int64_t maxChunkSize );
+ int ( *close )( void* handle );
+ int ( *getSize )( void* handle, int64_t* nout );
+} MP4FileProvider;
+
+/** Close an mp4 file.
+ * MP4Close closes a previously opened mp4 file. If the file was opened
+ * writable with MP4Create() or MP4Modify(), then MP4Close() will write
+ * out all pending information to disk.
+ *
+ * @param hFile handle of file to close.
+ * @param flags bitmask that allows the user to set extra options for the
+ * close commands. Valid options include:
+ * @li #MP4_CLOSE_DO_NOT_COMPUTE_BITRATE
+ */
+MP4V2_EXPORT
+void MP4Close(
+ MP4FileHandle hFile,
+ uint32_t flags DEFAULT(0) );
+
+/** Create a new mp4 file.
+ *
+ * MP4Create is the first call that should be used when you want to create
+ * a new, empty mp4 file. It is equivalent to opening a file for writing,
+ * but also involved with creation of necessary mp4 framework structures.
+ * ie. invoking MP4Create() followed by MP4Close() will result in a file
+ * with a non-zero size.
+ *
+ * @param fileName pathname of the file to be created.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param flags bitmask that allows the user to set 64-bit values for
+ * data or time atoms. Valid bits may be any combination of:
+ * @li #MP4_CREATE_64BIT_DATA
+ * @li #MP4_CREATE_64BIT_TIME
+ *
+ * @return On success a handle of the newly created file for use in
+ * subsequent calls to the library.
+ * On error, #MP4_INVALID_FILE_HANDLE.
+ */
+MP4V2_EXPORT
+MP4FileHandle MP4Create(
+ const char* fileName,
+ uint32_t flags DEFAULT(0) );
+
+/** Create a new mp4 file with extended options.
+ *
+ * MP4CreateEx is an extended version of MP4Create().
+ *
+ * @param fileName pathname of the file to be created.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param flags bitmask that allows the user to set 64-bit values for
+ * data or time atoms. Valid bits may be any combination of:
+ * @li #MP4_CREATE_64BIT_DATA
+ * @li #MP4_CREATE_64BIT_TIME
+ * @param add_ftyp if true an <b>ftyp</b> atom is automatically created.
+ * @param add_iods if true an <b>iods</b> atom is automatically created.
+ * @param majorBrand <b>ftyp</b> brand identifier.
+ * @param minorVersion <b>ftyp</b> informative integer for the minor version
+ * of the major brand.
+ * @param compatibleBrands <b>ftyp</b> list of compatible brands.
+ * @param compatibleBrandsCount is the count of items specified in
+ * compatibleBrands.
+ *
+ * @return On success a handle of the newly created file for use in
+ * subsequent calls to the library.
+ * On error, #MP4_INVALID_FILE_HANDLE.
+ */
+MP4V2_EXPORT
+MP4FileHandle MP4CreateEx(
+ const char* fileName,
+ uint32_t flags DEFAULT(0),
+ int add_ftyp DEFAULT(1),
+ int add_iods DEFAULT(1),
+ char* majorBrand DEFAULT(0),
+ uint32_t minorVersion DEFAULT(0),
+ char** compatibleBrands DEFAULT(0),
+ uint32_t compatibleBrandsCount DEFAULT(0) );
+
+/** Create a new mp4 file.
+ *
+ * MP4CreateProvider is the first call that should be used when you want to
+ * create a new, empty mp4 file. It is equivalent to opening a file for
+ * writing, but also involved with creation of necessary mp4 framework
+ * structures. ie. invoking MP4CreateProvider() followed by MP4Close() will
+ * result in a file with a non-zero size.
+ *
+ * @param fileName pathname of the file to be created.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param flags bitmask that allows the user to set 64-bit values for
+ * data or time atoms. Valid bits may be any combination of:
+ * @li #MP4_CREATE_64BIT_DATA
+ * @li #MP4_CREATE_64BIT_TIME
+ * @param fileProvider custom implementation of file I/O operations.
+ * All functions in structure must be implemented.
+ * The structure is immediately copied internally.
+ *
+ * @return On success a handle of the newly created file for use in
+ * subsequent calls to the library.
+ * On error, #MP4_INVALID_FILE_HANDLE.
+ */
+MP4V2_EXPORT
+MP4FileHandle MP4CreateProvider(
+ const char* fileName,
+ uint32_t flags DEFAULT(0),
+ const MP4FileProvider* fileProvider DEFAULT(NULL) );
+
+/** Create a new mp4 file with extended options.
+ *
+ * MP4CreateProviderEx is an extended version of MP4CreateProvider().
+ *
+ * @param fileName pathname of the file to be created.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param flags bitmask that allows the user to set 64-bit values for
+ * data or time atoms. Valid bits may be any combination of:
+ * @li #MP4_CREATE_64BIT_DATA
+ * @li #MP4_CREATE_64BIT_TIME
+ * @param fileProvider custom implementation of file I/O operations.
+ * All functions in structure must be implemented.
+ * The structure is immediately copied internally.
+ * @param add_ftyp if true an <b>ftyp</b> atom is automatically created.
+ * @param add_iods if true an <b>iods</b> atom is automatically created.
+ * @param majorBrand <b>ftyp</b> brand identifier.
+ * @param minorVersion <b>ftyp</b> informative integer for the minor version
+ * of the major brand.
+ * @param compatibleBrands <b>ftyp</b> list of compatible brands.
+ * @param compatibleBrandsCount is the count of items specified in
+ * compatibleBrands.
+ *
+ * @return On success a handle of the newly created file for use in
+ * subsequent calls to the library.
+ * On error, #MP4_INVALID_FILE_HANDLE.
+ */
+MP4V2_EXPORT
+MP4FileHandle MP4CreateProviderEx(
+ const char* fileName,
+ uint32_t flags DEFAULT(0),
+ const MP4FileProvider* fileProvider DEFAULT(NULL),
+ int add_ftyp DEFAULT(1),
+ int add_iods DEFAULT(1),
+ char* majorBrand DEFAULT(0),
+ uint32_t minorVersion DEFAULT(0),
+ char** compatibleBrands DEFAULT(0),
+ uint32_t compatibleBrandsCount DEFAULT(0) );
+
+/** Dump mp4 file contents as ASCII either to stdout or the
+ * log callback (@p see MP4SetLogCallback)
+ *
+ * Dump is an invaluable debugging tool in that in can reveal all the details
+ * of the mp4 control structures. However, the output will not make much sense
+ * until you familiarize yourself with the mp4 specification (or the Quicktime
+ * File Format specification).
+ *
+
+ * Note that MP4Dump() will not print the individual values of control tables,
+ * such as the size of each sample, unless the current log level is at least
+ * #MP4_LOG_VERBOSE2. @p see MP4LogSetLevel() for how to set this.
+ *
+ * @param hFile handle of file to dump.
+ * @param dumpImplicits prints properties which would not actually be
+ * written to the mp4 file, but still exist in mp4 control structures.
+ * ie. they are implicit given the current values of other controlling
+ * properties.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4Dump(
+ MP4FileHandle hFile,
+ bool dumpImplicits DEFAULT(0) );
+
+/** Return a textual summary of an mp4 file.
+ *
+ * MP4FileInfo provides a string that contains a textual summary of the
+ * contents of an mp4 file. This includes the track id's, the track type,
+ * and track specific information. For example, for a video track, media
+ * encoding, image size, frame rate, and bitrate are summarized.
+ *
+ * Note that the returned string is malloc'ed, so it is the caller's
+ * responsibility to free() the string. Also note that the returned string
+ * contains newlines and tabs which may or may not be desirable.
+ *
+ * The following is an example of the output of MP4Info():
+@verbatim
+Track Type Info
+1 video MPEG-4 Simple @ L3, 119.625 secs, 1008 kbps, 352x288 @ 24.00 fps
+2 audio MPEG-4, 119.327 secs, 128 kbps, 44100 Hz
+3 hint Payload MP4V-ES for track 1
+4 hint Payload mpeg4-generic for track 2
+5 od Object Descriptors
+6 scene BIFS
+@endverbatim
+ *
+ * @param fileName pathname to mp4 file to summarize.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param trackId specifies track to summarize. If the value is
+ * #MP4_INVALID_TRACK_ID, the summary info is created for all
+ * tracks in the file.
+ *
+ * @return On success a malloc'd string containing summary information.
+ * On failure, <b>NULL</b>.
+ *
+ * @see MP4Info().
+ */
+MP4V2_EXPORT
+char* MP4FileInfo(
+ const char* fileName,
+ MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID) );
+
+/** Accessor for the filename associated with a file handle
+ *
+ * @param hFile a file handle
+ *
+ * @return the NUL-terminated, UTF-8 encoded filename
+ * associated with @p hFile
+ */
+MP4V2_EXPORT
+const char* MP4GetFilename(
+ MP4FileHandle hFile );
+
+/** Return a textual summary of an mp4 file.
+ *
+ * MP4FileInfo provides a string that contains a textual summary of the
+ * contents of an mp4 file. This includes the track id's, the track type,
+ * and track specific information. For example, for a video track, media
+ * encoding, image size, frame rate, and bitrate are summarized.
+ *
+ * Note that the returned string is malloc'ed, so it is the caller's
+ * responsibility to free() the string. Also note that the returned string
+ * contains newlines and tabs which may or may not be desirable.
+ *
+ * The following is an example of the output of MP4Info():
+@verbatim
+Track Type Info
+1 video MPEG-4 Simple @ L3, 119.625 secs, 1008 kbps, 352x288 @ 24.00 fps
+2 audio MPEG-4, 119.327 secs, 128 kbps, 44100 Hz
+3 hint Payload MP4V-ES for track 1
+4 hint Payload mpeg4-generic for track 2
+5 od Object Descriptors
+6 scene BIFS
+@endverbatim
+ *
+ * @param hFile handle of file to summarize.
+ * @param trackId specifies track to summarize. If the value is
+ * #MP4_INVALID_TRACK_ID, the summary info is created for all
+ * tracks in the file.
+ *
+ * @return On success a malloc'd string containing summary information.
+ * On failure, <b>NULL</b>.
+ *
+ * @see MP4FileInfo().
+ */
+MP4V2_EXPORT
+char* MP4Info(
+ MP4FileHandle hFile,
+ MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID) );
+
+/** Modify an existing mp4 file.
+ *
+ * MP4Modify is the first call that should be used when you want to modify
+ * an existing mp4 file. It is roughly equivalent to opening a file in
+ * read/write mode.
+ *
+ * Since modifications to an existing mp4 file can result in a sub-optimal
+ * file layout, you may want to use MP4Optimize() after you have modified
+ * and closed the mp4 file.
+ *
+ * @param fileName pathname of the file to be modified.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param flags currently ignored.
+ *
+ * @return On success a handle of the target file for use in subsequent calls
+ * to the library.
+ * On error, #MP4_INVALID_FILE_HANDLE.
+ */
+MP4V2_EXPORT
+MP4FileHandle MP4Modify(
+ const char* fileName,
+ uint32_t flags DEFAULT(0) );
+
+/** Optimize the layout of an mp4 file.
+ *
+ * MP4Optimize reads an existing mp4 file and writes a new version of the
+ * file with the two important changes:
+ *
+ * First, the mp4 control information is moved to the beginning of the file.
+ * (Frequenty it is at the end of the file due to it being constantly
+ * modified as track samples are added to an mp4 file). This optimization
+ * is useful in that in allows the mp4 file to be HTTP streamed.
+ *
+ * Second, the track samples are interleaved so that the samples for a
+ * particular instant in time are colocated within the file. This
+ * eliminates disk seeks during playback of the file which results in
+ * better performance.
+ *
+ * There are also two important side effects of MP4Optimize():
+ *
+ * First, any free blocks within the mp4 file are eliminated.
+ *
+ * Second, as a side effect of the sample interleaving process any media
+ * data chunks that are not actually referenced by the mp4 control
+ * structures are deleted. This is useful if you have called MP4DeleteTrack()
+ * which only deletes the control information for a track, and not the
+ * actual media data.
+ *
+ * @param fileName pathname of (existing) file to be optimized.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param newFileName pathname of the new optimized file.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * If NULL a temporary file in the same directory as the
+ * <b>fileName</b> will be used and <b>fileName</b>
+ * will be over-written upon successful completion.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4Optimize(
+ const char* fileName,
+ const char* newFileName DEFAULT(NULL) );
+
+
+/** Read an existing mp4 file.
+ *
+ * MP4Read is the first call that should be used when you want to just
+ * read an existing mp4 file. It is equivalent to opening a file for
+ * reading, but in addition the mp4 file is parsed and the control
+ * information is loaded into memory. Note that actual track samples are not
+ * read into memory until MP4ReadSample() is called.
+ *
+ * @param fileName pathname of the file to be read.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+(
+ * @return On success a handle of the file for use in subsequent calls to
+ * the library.
+ * On error, #MP4_INVALID_FILE_HANDLE.
+ */
+MP4V2_EXPORT
+MP4FileHandle MP4Read(
+ const char* fileName );
+
+/** Read an existing mp4 file.
+ *
+ * MP4ReadProvider is the first call that should be used when you want to just
+ * read an existing mp4 file. It is equivalent to opening a file for
+ * reading, but in addition the mp4 file is parsed and the control
+ * information is loaded into memory. Note that actual track samples are not
+ * read into memory until MP4ReadSample() is called.
+ *
+ * @param fileName pathname of the file to be read.
+ * On Windows, this should be a UTF-8 encoded string.
+ * On other platforms, it should be an 8-bit encoding that is
+ * appropriate for the platform, locale, file system, etc.
+ * (prefer to use UTF-8 when possible).
+ * @param fileProvider custom implementation of file I/O operations.
+ * All functions in structure must be implemented.
+ * The structure is immediately copied internally.
+ *
+ * @return On success a handle of the file for use in subsequent calls to
+ * the library.
+ * On error, #MP4_INVALID_FILE_HANDLE.
+ */
+MP4V2_EXPORT
+MP4FileHandle MP4ReadProvider(
+ const char* fileName,
+ const MP4FileProvider* fileProvider DEFAULT(NULL) );
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_FILE_H */
diff --git a/include/mp4v2/file_prop.h b/include/mp4v2/file_prop.h
new file mode 100644
index 0000000..15435e8
--- /dev/null
+++ b/include/mp4v2/file_prop.h
@@ -0,0 +1,148 @@
+#ifndef MP4V2_FILE_PROP_H
+#define MP4V2_FILE_PROP_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_file_prop MP4v2 File Property
+ * @{
+ *
+ *****************************************************************************/
+
+/* generic props */
+
+MP4V2_EXPORT
+bool MP4HaveAtom(
+ MP4FileHandle hFile,
+ const char* atomName );
+
+MP4V2_EXPORT
+bool MP4GetIntegerProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ uint64_t* retval );
+
+MP4V2_EXPORT
+bool MP4GetFloatProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ float* retvalue );
+
+MP4V2_EXPORT
+bool MP4GetStringProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ const char** retvalue );
+
+MP4V2_EXPORT
+bool MP4GetBytesProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ uint8_t** ppValue,
+ uint32_t* pValueSize );
+
+MP4V2_EXPORT
+bool MP4SetIntegerProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ int64_t value );
+
+MP4V2_EXPORT
+bool MP4SetFloatProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ float value );
+
+MP4V2_EXPORT
+bool MP4SetStringProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ const char* value );
+
+MP4V2_EXPORT
+bool MP4SetBytesProperty(
+ MP4FileHandle hFile,
+ const char* propName,
+ const uint8_t* pValue,
+ uint32_t valueSize );
+
+/* specific props */
+
+MP4V2_EXPORT
+MP4Duration MP4GetDuration( MP4FileHandle hFile );
+
+/** Get the time scale of the movie (file).
+ *
+ * MP4GetTimeScale returns the time scale in units of ticks per second for
+ * the mp4 file. Caveat: tracks may use the same time scale as the movie
+ * or may use their own time scale.
+ *
+ * @param hFile handle of file for operation.
+ *
+ * @return timescale (ticks per second) of the mp4 file.
+ */
+MP4V2_EXPORT
+uint32_t MP4GetTimeScale( MP4FileHandle hFile );
+
+/** Set the time scale of the movie (file).
+ *
+ * MP4SetTimeScale sets the time scale of the mp4 file. The time scale is
+ * in the number of clock ticks per second. Caveat: tracks may use the
+ * same time scale as the movie or may use their own time scale.
+ *
+ * @param hFile handle of file for operation.
+ * @param value desired timescale for the movie.
+ *
+ * @return On success, true. On failure, false.
+ */
+MP4V2_EXPORT
+bool MP4SetTimeScale( MP4FileHandle hFile, uint32_t value );
+
+/** Change the general timescale of file hFile.
+ *
+ * This function changes the general timescale of the file <b>hFile</b>
+ * to the new timescale <b>value</b> by recalculating all values that depend
+ * on the timescale in "moov.mvhd".
+ *
+ * If the timescale is already equal to value nothing is done.
+ *
+ * @param hFile handle of file to change.
+ * @param value the new timescale.
+ */
+MP4V2_EXPORT
+void MP4ChangeMovieTimeScale( MP4FileHandle hFile, uint32_t value );
+
+MP4V2_EXPORT
+uint8_t MP4GetODProfileLevel( MP4FileHandle hFile );
+
+MP4V2_EXPORT
+bool MP4SetODProfileLevel( MP4FileHandle hFile, uint8_t value );
+
+MP4V2_EXPORT
+uint8_t MP4GetSceneProfileLevel( MP4FileHandle hFile );
+
+MP4V2_EXPORT
+bool MP4SetSceneProfileLevel( MP4FileHandle hFile, uint8_t value );
+
+MP4V2_EXPORT
+uint8_t MP4GetVideoProfileLevel(
+ MP4FileHandle hFile,
+ MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID) );
+
+MP4V2_EXPORT
+void MP4SetVideoProfileLevel( MP4FileHandle hFile, uint8_t value );
+
+MP4V2_EXPORT
+uint8_t MP4GetAudioProfileLevel( MP4FileHandle hFile );
+
+MP4V2_EXPORT
+void MP4SetAudioProfileLevel( MP4FileHandle hFile, uint8_t value );
+
+MP4V2_EXPORT
+uint8_t MP4GetGraphicsProfileLevel( MP4FileHandle hFile );
+
+MP4V2_EXPORT
+bool MP4SetGraphicsProfileLevel( MP4FileHandle hFile, uint8_t value );
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_FILE_PROP_H */
diff --git a/include/mp4v2/general.h b/include/mp4v2/general.h
new file mode 100644
index 0000000..f9713bf
--- /dev/null
+++ b/include/mp4v2/general.h
@@ -0,0 +1,495 @@
+#ifndef MP4V2_GENERAL_H
+#define MP4V2_GENERAL_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_general MP4v2 General
+ * @{
+ *
+ *****************************************************************************/
+
+/* MP4 API types */
+typedef void* MP4FileHandle;
+typedef uint32_t MP4TrackId;
+typedef uint32_t MP4SampleId;
+typedef uint64_t MP4Timestamp;
+typedef uint64_t MP4Duration;
+typedef uint32_t MP4EditId;
+
+typedef enum {
+ MP4_LOG_NONE = 0,
+ MP4_LOG_ERROR = 1,
+ MP4_LOG_WARNING = 2,
+ MP4_LOG_INFO = 3,
+ MP4_LOG_VERBOSE1 = 4,
+ MP4_LOG_VERBOSE2 = 5,
+ MP4_LOG_VERBOSE3 = 6,
+ MP4_LOG_VERBOSE4 = 7
+} MP4LogLevel;
+
+/*****************************************************************************/
+
+typedef void (*MP4LogCallback)(
+ MP4LogLevel loglevel,
+ const char* fmt,
+ va_list ap );
+
+/*****************************************************************************/
+
+/** Encryption function pointer.
+ *
+ * @see MP4EncAndCopySample().
+ * @see MP4EncAndCopyTrack().
+ */
+typedef uint32_t (*encryptFunc_t)( uint32_t, uint32_t, uint8_t*, uint32_t*, uint8_t** );
+
+/*****************************************************************************/
+
+#define MP4_INVALID_FILE_HANDLE ((MP4FileHandle)NULL) /**< Constant: invalid MP4FileHandle. */
+#define MP4_INVALID_TRACK_ID ((MP4TrackId)0) /**< Constant: invalid MP4TrackId. */
+#define MP4_INVALID_SAMPLE_ID ((MP4SampleId)0) /**< Constant: invalid MP4SampleId. */
+#define MP4_INVALID_TIMESTAMP ((MP4Timestamp)-1) /**< Constant: invalid MP4Timestamp. */
+#define MP4_INVALID_DURATION ((MP4Duration)-1) /**< Constant: invalid MP4Duration. */
+#define MP4_INVALID_EDIT_ID ((MP4EditId)0) /**< Constant: invalid MP4EditId. */
+
+/* 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 Known track type names - e.g. MP4GetNumberOfTracks(type)
+ *
+ * Note this first group of track types should be created
+ * via the MP4Add<Type>Track() functions, and not MP4AddTrack(type)
+ */
+#define MP4_OD_TRACK_TYPE "odsm" /**< Constant: OD track. */
+#define MP4_SCENE_TRACK_TYPE "sdsm" /**< Constant: scene track. */
+#define MP4_AUDIO_TRACK_TYPE "soun" /**< Constant: audio track. */
+#define MP4_VIDEO_TRACK_TYPE "vide" /**< Constant: video track. */
+#define MP4_HINT_TRACK_TYPE "hint" /**< Constant: hint track. */
+#define MP4_CNTL_TRACK_TYPE "cntl" /**< Constant: control track. */
+#define MP4_TEXT_TRACK_TYPE "text" /**< Constant: text track. */
+#define MP4_SUBTITLE_TRACK_TYPE "sbtl" /**< Constant: subtitle track. */
+#define MP4_SUBPIC_TRACK_TYPE "subp" /**< Constant: subpic track. */
+/*
+ * This second set of track types should be created
+ * via MP4AddSystemsTrack(type)
+ */
+#define MP4_CLOCK_TRACK_TYPE "crsm" /**< Constant: clock track. */
+#define MP4_MPEG7_TRACK_TYPE "m7sm" /**< Constant: mpeg7 track. */
+#define MP4_OCI_TRACK_TYPE "ocsm" /**< Constant: OCI track. */
+#define MP4_IPMP_TRACK_TYPE "ipsm" /**< Constant: IPMP track. */
+#define MP4_MPEGJ_TRACK_TYPE "mjsm" /**< Constant: MPEGJ track. */
+
+#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
+#define MP4_MPEG4_ALS_AUDIO_TYPE 31
+#define MP4_MPEG4_LAYER1_AUDIO_TYPE 32
+#define MP4_MPEG4_LAYER2_AUDIO_TYPE 33
+#define MP4_MPEG4_LAYER3_AUDIO_TYPE 34
+#define MP4_MPEG4_SLS_AUDIO_TYPE 35
+
+/* 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)
+
+/*****************************************************************************/
+
+/* 3GP specific utilities */
+
+MP4V2_EXPORT
+bool MP4Make3GPCompliant(
+ const char* fileName,
+ char* majorBrand DEFAULT(0),
+ uint32_t minorVersion DEFAULT(0),
+ char** supportedBrands DEFAULT(NULL),
+ uint32_t supportedBrandsCount DEFAULT(0),
+ bool deleteIodsAtom DEFAULT(true) );
+
+/* NOTE this section of functionality has not yet been fully tested */
+
+MP4V2_EXPORT
+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) );
+
+MP4V2_EXPORT
+bool MP4DeleteTrackEdit(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId );
+
+MP4V2_EXPORT
+uint32_t MP4GetTrackNumberOfEdits(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+MP4Timestamp MP4GetTrackEditStart(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId );
+
+MP4V2_EXPORT
+MP4Duration MP4GetTrackEditTotalDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID) );
+
+MP4V2_EXPORT
+MP4Timestamp MP4GetTrackEditMediaStart(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId );
+
+MP4V2_EXPORT
+bool MP4SetTrackEditMediaStart(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId,
+ MP4Timestamp startTime );
+
+MP4V2_EXPORT
+MP4Duration MP4GetTrackEditDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId );
+
+MP4V2_EXPORT
+bool MP4SetTrackEditDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId,
+ MP4Duration duration );
+
+MP4V2_EXPORT
+int8_t MP4GetTrackEditDwell(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId );
+
+MP4V2_EXPORT
+bool MP4SetTrackEditDwell(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId,
+ bool dwell );
+
+MP4V2_EXPORT
+bool MP4ReadSampleFromEditTime(
+ /* input parameters */
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ /* input/output parameters */
+ uint8_t** ppBytes,
+ uint32_t* pNumBytes,
+ /* output parameters */
+ MP4Timestamp* pStartTime DEFAULT(NULL),
+ MP4Duration* pDuration DEFAULT(NULL),
+ MP4Duration* pRenderingOffset DEFAULT(NULL),
+ bool* pIsSyncSample DEFAULT(NULL) );
+
+MP4V2_EXPORT
+MP4SampleId MP4GetSampleIdFromEditTime(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ MP4Timestamp* pStartTime DEFAULT(NULL),
+ MP4Duration* pDuration DEFAULT(NULL) );
+
+/* 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
+
+MP4V2_EXPORT
+uint64_t MP4ConvertFromMovieDuration(
+ MP4FileHandle hFile,
+ MP4Duration duration,
+ uint32_t timeScale );
+
+MP4V2_EXPORT
+uint64_t MP4ConvertFromTrackTimestamp(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp timeStamp,
+ uint32_t timeScale );
+
+MP4V2_EXPORT
+MP4Timestamp MP4ConvertToTrackTimestamp(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint64_t timeStamp,
+ uint32_t timeScale );
+
+/** Convert duration from track time scale to an arbitrary time scale.
+ *
+ * MP4ConvertFromTrackDuration converts a duration such as a sample duration
+ * from the track time scale to another time scale. This can be used by a
+ * player application to map all track samples to a common time scale.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param duration value to be converted.
+ * @param timeScale time scale in ticks per second.
+ *
+ * @return On success, the duration in arbitrary time scale units.
+ * On error, <b>0</b>.
+ *
+ * @see MP4GetSampleDuration().
+ * @see MP4ConvertToTrackDuration().
+ */
+MP4V2_EXPORT
+uint64_t MP4ConvertFromTrackDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Duration duration,
+ uint32_t timeScale );
+
+/** Convert duration from arbitrary time scale to track time scale.
+ *
+ * MP4ConvertToTrackDuration converts a duration such as a sample duration
+ * from the specified time scale to the track time scale.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param duration value to be converted.
+ * @param timeScale time scale in ticks per second.
+ *
+ * @return On success, the duration in track time scale units.
+ * On error, #MP4_INVALID_DURATION.
+ *
+ * @see MP4ConvertFromTrackDuration().
+ */
+MP4V2_EXPORT
+MP4Duration MP4ConvertToTrackDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint64_t duration,
+ uint32_t timeScale );
+
+MP4V2_EXPORT
+char* MP4BinaryToBase16(
+ const uint8_t* pData,
+ uint32_t dataSize );
+
+MP4V2_EXPORT
+char* MP4BinaryToBase64(
+ const uint8_t* pData,
+ uint32_t dataSize );
+
+MP4V2_EXPORT
+uint8_t* Base64ToBinary(
+ const char* pData,
+ uint32_t decodeSize,
+ uint32_t* pDataSize );
+
+MP4V2_EXPORT
+void MP4Free(
+ void* p );
+
+/** Set the function to call in place of default logging behavior
+ *
+ * @param cb_func the function to call
+ */
+MP4V2_EXPORT
+void MP4SetLogCallback(
+ MP4LogCallback cb_func );
+/** @} ***********************************************************************/
+
+/**
+ * Accessor for the maximum level for diagnostic information
+ *
+ * @return the maximum level for diagnostic information
+ *
+ * @see MP4LogSetLevel() for further details.
+ */
+MP4V2_EXPORT
+MP4LogLevel MP4LogGetLevel( void );
+
+/**
+ * Set the maximum level for diagnostic information
+ *
+ * @param verbosity the level to set
+ */
+MP4V2_EXPORT
+void MP4LogSetLevel( MP4LogLevel verbosity );
+
+#endif /* MP4V2_GENERAL_H */
diff --git a/include/mp4v2/isma.h b/include/mp4v2/isma.h
new file mode 100644
index 0000000..074a06e
--- /dev/null
+++ b/include/mp4v2/isma.h
@@ -0,0 +1,96 @@
+#ifndef MP4V2_ISMA_H
+#define MP4V2_ISMA_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_isma MP4v2 ISMA (Internet Streaming Media Alliance)
+ * @{
+ *
+ *****************************************************************************/
+
+/** something */
+typedef struct mp4v2_ismacryp_session_params {
+ uint32_t scheme_type;
+ uint16_t scheme_version;
+ uint8_t key_ind_len;
+ uint8_t iv_len;
+ uint8_t selective_enc;
+ const char* kms_uri;
+} mp4v2_ismacrypParams;
+
+/*
+ * API to initialize ismacryp properties to sensible defaults
+ * if input param is null then mallocs a params struct
+ */
+
+MP4V2_EXPORT
+mp4v2_ismacrypParams* MP4DefaultISMACrypParams( mp4v2_ismacrypParams* ptr );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddEncAudioTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ mp4v2_ismacrypParams* icPp,
+ uint8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE) );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddEncVideoTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ uint16_t width,
+ uint16_t height,
+ mp4v2_ismacrypParams* icPp,
+ uint8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE),
+ const char* oFormat DEFAULT(NULL) );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddEncH264VideoTrack(
+ MP4FileHandle dstFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ uint16_t width,
+ uint16_t height,
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ mp4v2_ismacrypParams* icPp );
+
+MP4V2_EXPORT
+MP4TrackId MP4EncAndCloneTrack(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ mp4v2_ismacrypParams* icPp,
+ MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+ MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) );
+
+MP4V2_EXPORT
+MP4TrackId MP4EncAndCopyTrack(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ mp4v2_ismacrypParams* icPp,
+ encryptFunc_t encfcnp,
+ uint32_t encfcnparam1,
+ MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+ bool applyEdits DEFAULT(false),
+ MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) );
+
+MP4V2_EXPORT
+bool MP4MakeIsmaCompliant(
+ const char* fileName,
+ bool addIsmaComplianceSdp DEFAULT(true) );
+
+MP4V2_EXPORT
+char* MP4MakeIsmaSdpIod(
+ uint8_t videoProfile,
+ uint32_t videoBitrate,
+ uint8_t* videoConfig,
+ uint32_t videoConfigLength,
+ uint8_t audioProfile,
+ uint32_t audioBitrate,
+ uint8_t* audioConfig,
+ uint32_t audioConfigLength );
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_ISMA_H */
diff --git a/include/mp4v2/itmf_generic.h b/include/mp4v2/itmf_generic.h
new file mode 100644
index 0000000..b780b1e
--- /dev/null
+++ b/include/mp4v2/itmf_generic.h
@@ -0,0 +1,207 @@
+#ifndef MP4V2_ITMF_GENERIC_H
+#define MP4V2_ITMF_GENERIC_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_itmf_generic MP4v2 iTMF (iTunes Metadata Format) Generic
+ * @{
+ *
+ * This is a low-level API used to manage iTMF metadata.
+ *
+ * It provides support for virtually any kind of iTMF metadata item,
+ * including meaning atoms, sometimes referred to as reverse-DNS meanings.
+ * Structures are directly modified; ie: there are no fuctions which
+ * modify values for you. There is little type-safety, logic checks, or
+ * specifications compliance checks. For these reasons it is recommended
+ * to use iTMF Tags API when possible.
+ *
+ * At the heart of this API is an #MP4ItmfItem which corresponds to an
+ * iTMF metadata item atom. The item, and any recursive data structures
+ * contained within require <b>manual</b> memory management. The general
+ * rule to follow is that you must always check/free a ptr if you intend
+ * to resize data. In cases where you know the existing data size is
+ * exactly what is needed, you may overwrite the buffer contents.
+ *
+ * Each item always has at least 1 data elements which corresponds to
+ * a data atom. Additionally, each item has optional <b>mean</b> and
+ * <b>name</b> values which correspond to mean and name atoms.
+ *
+ * Each #MP4ItmfItem has a list of #MP4ItmfData. Similarily, care must
+ * be taken to manage memory with one key difference; these structures
+ * also have a valueSize field. If value is NULL then set valueSize=0.
+ * Otherwise, set valueSize to the size (in bytes) of value buffer.
+ *
+ * In rare cases where the number of data elements in a single item
+ * is > 1, the user must manually free/alloc/copy the <b>elements</b>
+ * buffer and update <b>size</b> accordingly.
+ *
+ * The mp4 file structure is modified only when MP4AddItem(),
+ * MP4SetItem() and MP4RemoveItem() are used. Simply free'ing
+ * the item list does not modify the mp4 file.
+ *
+ * <b>iTMF Generic read workflow:</b>
+ *
+ * @li MP4ItmfGetItems()
+ * @li inspect each item...
+ * @li MP4ItmfItemListFree()
+ *
+ * <b>iTMF Generic read/modify/remove workflow:</b>
+ *
+ * @li MP4ItmfGetItems()
+ * @li inspect/modify item...
+ * @li MP4ItmfSetItem() each modified item...
+ * @li MP4ItmfRemoveItem()...
+ * @li MP4ItmfItemListFree()
+ *
+ * <b>iTMF Generic add workflow:</b>
+ *
+ * @li MP4ItmfItemAlloc()
+ * @li MP4ItmfAddItem()
+ * @li MP4ItmfItemFree()
+ *
+ * @par Warning:
+ * Care must be taken when using multiple mechanisms to modify an open mp4
+ * file as it is not thread-safe, nor does it permit overlapping different
+ * API workflows which have a begin/end to their workflow. That is to say
+ * do not interleave an iTMF Generic workflow with an iTMF Tags workflow.
+ *
+ *****************************************************************************/
+
+/** Basic types of value data as enumerated in spec. */
+typedef enum MP4ItmfBasicType_e
+{
+ MP4_ITMF_BT_IMPLICIT = 0, /**< for use with tags for which no type needs to be indicated */
+ MP4_ITMF_BT_UTF8 = 1, /**< without any count or null terminator */
+ MP4_ITMF_BT_UTF16 = 2, /**< also known as UTF-16BE */
+ MP4_ITMF_BT_SJIS = 3, /**< deprecated unless it is needed for special Japanese characters */
+ MP4_ITMF_BT_HTML = 6, /**< the HTML file header specifies which HTML version */
+ MP4_ITMF_BT_XML = 7, /**< the XML header must identify the DTD or schemas */
+ MP4_ITMF_BT_UUID = 8, /**< also known as GUID; stored as 16 bytes in binary (valid as an ID) */
+ MP4_ITMF_BT_ISRC = 9, /**< stored as UTF-8 text (valid as an ID) */
+ MP4_ITMF_BT_MI3P = 10, /**< stored as UTF-8 text (valid as an ID) */
+ MP4_ITMF_BT_GIF = 12, /**< (deprecated) a GIF image */
+ MP4_ITMF_BT_JPEG = 13, /**< a JPEG image */
+ MP4_ITMF_BT_PNG = 14, /**< a PNG image */
+ MP4_ITMF_BT_URL = 15, /**< absolute, in UTF-8 characters */
+ MP4_ITMF_BT_DURATION = 16, /**< in milliseconds, 32-bit integer */
+ MP4_ITMF_BT_DATETIME = 17, /**< in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits */
+ MP4_ITMF_BT_GENRES = 18, /**< a list of enumerated values */
+ MP4_ITMF_BT_INTEGER = 21, /**< a signed big-endian integer with length one of { 1,2,3,4,8 } bytes */
+ MP4_ITMF_BT_RIAA_PA = 24, /**< RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit ingteger */
+ MP4_ITMF_BT_UPC = 25, /**< Universal Product Code, in text UTF-8 format (valid as an ID) */
+ MP4_ITMF_BT_BMP = 27, /**< Windows bitmap image */
+
+ MP4_ITMF_BT_UNDEFINED = 255 /**< undefined */
+} MP4ItmfBasicType;
+
+/** Data structure.
+ * Models an iTMF data atom contained in an iTMF metadata item atom.
+ */
+typedef struct MP4ItmfData_s
+{
+ uint8_t typeSetIdentifier; /**< always zero. */
+ MP4ItmfBasicType typeCode; /**< iTMF basic type. */
+ uint32_t locale; /**< always zero. */
+ uint8_t* value; /**< may be NULL. */
+ uint32_t valueSize; /**< value size in bytes. */
+} MP4ItmfData;
+
+/** List of data. */
+typedef struct MP4ItmfDataList_s
+{
+ MP4ItmfData* elements; /**< flat array. NULL when size is zero. */
+ uint32_t size; /**< number of elements. */
+} MP4ItmfDataList;
+
+/** Item structure.
+ * Models an iTMF metadata item atom contained in an ilst atom.
+ */
+typedef struct MP4ItmfItem_s
+{
+ void* __handle; /**< internal use only. */
+
+ char* code; /**< four-char code identifing atom type. NULL-terminated. */
+ char* mean; /**< may be NULL. UTF-8 meaning. NULL-terminated. */
+ char* name; /**< may be NULL. UTF-8 name. NULL-terminated. */
+ MP4ItmfDataList dataList; /**< list of data. can be zero length. */
+} MP4ItmfItem;
+
+/** List of items. */
+typedef struct MP4ItmfItemList_s
+{
+ MP4ItmfItem* elements; /**< flat array. NULL when size is zero. */
+ uint32_t size; /**< number of elements. */
+} MP4ItmfItemList;
+
+/** Allocate an item on the heap.
+ * @param code four-char code identifying atom type. NULL-terminated.
+ * @param numData number of data elements to allocate. Must be >= 1.
+ * @return newly allocated item.
+ */
+MP4V2_EXPORT MP4ItmfItem*
+MP4ItmfItemAlloc( const char* code, uint32_t numData );
+
+/** Free an item (deep free).
+ * @param item to be free'd.
+ */
+MP4V2_EXPORT void
+MP4ItmfItemFree( MP4ItmfItem* item );
+
+/** Free an item list (deep free).
+ * @param itemList to be free'd.
+ */
+MP4V2_EXPORT void
+MP4ItmfItemListFree( MP4ItmfItemList* itemList );
+
+/** Get list of all items from file.
+ * @param hFile handle of file to operate on.
+ * @return On succes, list of items, which must be free'd. On failure, NULL.
+ */
+MP4V2_EXPORT MP4ItmfItemList*
+MP4ItmfGetItems( MP4FileHandle hFile );
+
+/** Get list of items by code from file.
+ * @param hFile handle of file to operate on.
+ * @param code four-char code identifying atom type. NULL-terminated.
+ * @return On succes, list of items, which must be free'd. On failure, NULL.
+ */
+MP4V2_EXPORT MP4ItmfItemList*
+MP4ItmfGetItemsByCode( MP4FileHandle hFile, const char* code );
+
+/** Get list of items by meaning from file.
+ * Implicitly only returns atoms of code @b{----}.
+ * @param hFile handle of file to operate on.
+ * @param meaning UTF-8 meaning. NULL-terminated.
+ * @param name may be NULL. UTF-8 name. NULL-terminated.
+ * @return On succes, list of items, which must be free'd. On failure, NULL.
+ */
+MP4V2_EXPORT MP4ItmfItemList*
+MP4ItmfGetItemsByMeaning( MP4FileHandle hFile, const char* meaning, const char* name );
+
+/** Add an item to file.
+ * @param hFile handle of file to operate on.
+ * @param item object to add.
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT bool
+MP4ItmfAddItem( MP4FileHandle hFile, const MP4ItmfItem* item );
+
+/** Overwrite an existing item in file.
+ * @param hFile handle of file to operate on.
+ * @param item object to overwrite. Must have a valid index obtained from prior get.
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT bool
+MP4ItmfSetItem( MP4FileHandle hFile, const MP4ItmfItem* item );
+
+/** Remove an existing item from file.
+ * @param hFile handle of file to operate on.
+ * @param item object to remove. Must have a valid index obtained from prior get.
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT bool
+MP4ItmfRemoveItem( MP4FileHandle hFile, const MP4ItmfItem* item );
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_ITMF_GENERIC_H */
diff --git a/include/mp4v2/itmf_tags.h b/include/mp4v2/itmf_tags.h
new file mode 100644
index 0000000..3115a3c
--- /dev/null
+++ b/include/mp4v2/itmf_tags.h
@@ -0,0 +1,289 @@
+#ifndef MP4V2_ITMF_TAGS_H
+#define MP4V2_ITMF_TAGS_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_itmf_tags MP4v2 iTMF (iTunes Metadata Format) Tags
+ * @{
+ *
+ * This is a high-level API used to manage iTMF metadata.
+ *
+ * It provides more type-safety and simplified memory management as compared
+ * to iTMF Generic API.
+ *
+ * At the heart of this API is a read-only structure that holds all known
+ * items and their current values. The value is always a pointer which if
+ * NULL indicates its corresponding atom does not exist. Thus, one must
+ * always check if the pointer is non-NULL before attempting to extract
+ * its value.
+ *
+ * The structure may not be directly modified. Instead, <b>set</b> functions
+ * corresponding to each item are used to modify the backing-store of
+ * the read-only structure. Setting the value ptr to NULL will effectively
+ * remove it. Setting the value ptr to real data will immediately make a
+ * copy of the value in the backing-store and the read-only structure
+ * will correctly reflect the change.
+ *
+ * The hidden data cache memory is automatically managed. Thus the user need
+ * only guarantee the data is available during the lifetime of the set-function
+ * call.
+ *
+ * <b>iTMF Tags read workflow:</b>
+ *
+ * @li MP4TagsAlloc()
+ * @li MP4TagsFetch()
+ * @li inspect each tag of interest...
+ * @li MP4TagsStore() (if modified)
+ * @li MP4TagsFree()
+ *
+ * <b>iTMF Tags read/modify/add/remove workflow:</b>
+ *
+ * @li MP4TagsAlloc()
+ * @li MP4TagsFetch()
+ * @li inspect each tag of interest...
+ * @li MP4TagsSetName(), MP4TagsSetArtist()...
+ * @li MP4TagsStore()
+ * @li MP4TagsFree()
+ *
+ * @par Warning:
+ * Care must be taken when using multiple mechanisms to modify an open mp4
+ * file as it is not thread-safe, nor does it permit overlapping different
+ * API workflows which have a begin/end to their workflow. That is to say
+ * do not interleave an iTMF Generic workflow with an iTMF Tags workflow.
+ *
+ *****************************************************************************/
+
+/** Enumeration of possible MP4TagArtwork::type values. */
+typedef enum MP4TagArtworkType_e
+{
+ MP4_ART_UNDEFINED = 0,
+ MP4_ART_BMP = 1,
+ MP4_ART_GIF = 2,
+ MP4_ART_JPEG = 3,
+ MP4_ART_PNG = 4
+} MP4TagArtworkType;
+
+/** Data object representing a single piece of artwork. */
+typedef struct MP4TagArtwork_s
+{
+ void* data; /**< raw picture data */
+ uint32_t size; /**< data size in bytes */
+ MP4TagArtworkType type; /**< data type */
+} MP4TagArtwork;
+
+typedef struct MP4TagTrack_s
+{
+ uint16_t index;
+ uint16_t total;
+} MP4TagTrack;
+
+typedef struct MP4TagDisk_s
+{
+ uint16_t index;
+ uint16_t total;
+} MP4TagDisk;
+
+/** Tags <b>convenience</b> structure.
+ *
+ * This structure is used in the tags convenience API which allows for
+ * simplified retrieval and modification of the majority of known tags.
+ *
+ * This is a read-only structure and each tag is present if and only if the
+ * pointer is a <b>non-NULL</b> value. The actual data is backed by a hidden
+ * data cache which is only updated when the appropriate metadata <b>set</b>
+ * function is used, or if MP4TagsFetch() is invoked. Thus, if other API
+ * is used to manipulate relevent atom structure of the MP4 file, the user
+ * is responsible for re-fetching the data in this structure.
+ */
+typedef struct MP4Tags_s
+{
+ void* __handle; /* internal use only */
+
+ const char* name;
+ const char* artist;
+ const char* albumArtist;
+ const char* album;
+ const char* grouping;
+ const char* composer;
+ const char* comments;
+ const char* genre;
+ const uint16_t* genreType;
+ const char* releaseDate;
+ const MP4TagTrack* track;
+ const MP4TagDisk* disk;
+ const uint16_t* tempo;
+ const uint8_t* compilation;
+
+ const char* tvShow;
+ const char* tvNetwork;
+ const char* tvEpisodeID;
+ const uint32_t* tvSeason;
+ const uint32_t* tvEpisode;
+
+ const char* description;
+ const char* longDescription;
+ const char* lyrics;
+
+ const char* sortName;
+ const char* sortArtist;
+ const char* sortAlbumArtist;
+ const char* sortAlbum;
+ const char* sortComposer;
+ const char* sortTVShow;
+
+ const MP4TagArtwork* artwork;
+ uint32_t artworkCount;
+
+ const char* copyright;
+ const char* encodingTool;
+ const char* encodedBy;
+ const char* purchaseDate;
+
+ const uint8_t* podcast;
+ const char* keywords; /* TODO: Needs testing */
+ const char* category;
+
+ const uint8_t* hdVideo;
+ const uint8_t* mediaType;
+ const uint8_t* contentRating;
+ const uint8_t* gapless;
+
+ const char* iTunesAccount;
+ const uint8_t* iTunesAccountType;
+ const uint32_t* iTunesCountry;
+ const uint32_t* contentID;
+ const uint32_t* artistID;
+ const uint64_t* playlistID;
+ const uint32_t* genreID;
+ const uint32_t* composerID;
+ const char* xid;
+} MP4Tags;
+
+/** Allocate tags convenience structure for reading and settings tags.
+ *
+ * This function allocates a new structure which represents a snapshot
+ * of all the tags therein, tracking if the tag is missing,
+ * or present and with value. It is the caller's responsibility to free
+ * the structure with MP4TagsFree().
+ *
+ * @return structure with all tags missing.
+ */
+MP4V2_EXPORT
+const MP4Tags* MP4TagsAlloc( void );
+
+/** Fetch data from mp4 file and populate structure.
+ *
+ * The tags structure and its hidden data-cache is updated to
+ * reflect the actual tags values found in the <b>hFile</b>.
+ *
+ * @param tags structure to fetch (write) into.
+ * @param hFile handle of file to fetch data from.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4TagsFetch( const MP4Tags* tags, MP4FileHandle hFile );
+
+/** Store data to mp4 file from structure.
+ *
+ * The tags structure is pushed out to the mp4 file,
+ * adding tags if needed, removing tags if needed, and updating
+ * the values to modified tags.
+ *
+ * @param tags structure to store (read) from.
+ * @param hFile handle of file to store data to.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4TagsStore( const MP4Tags* tags, MP4FileHandle hFile );
+
+/** Free tags convenience structure.
+ *
+ * This function frees memory associated with the structure.
+ *
+ * @param tags structure to destroy.
+ */
+MP4V2_EXPORT
+void MP4TagsFree( const MP4Tags* tags );
+
+/** Accessor that indicates whether a tags structure
+ * contains any metadata
+ *
+ * @param tags the structure to inspect
+ *
+ * @param hasMetadata populated with false if @p tags
+ * contains no metadata, true if @p tags contains metadata
+ *
+ * @retval false error determining if @p tags contains
+ * metadata
+ *
+ * @retval true successfully determined if @p tags contains
+ * metadata
+ */
+MP4V2_EXPORT
+bool MP4TagsHasMetadata ( const MP4Tags* tags, bool *hasMetadata );
+
+MP4V2_EXPORT bool MP4TagsSetName ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetArtist ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetAlbumArtist ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetAlbum ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetGrouping ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetComposer ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetComments ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetGenre ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetGenreType ( const MP4Tags*, const uint16_t* );
+MP4V2_EXPORT bool MP4TagsSetReleaseDate ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetTrack ( const MP4Tags*, const MP4TagTrack* );
+MP4V2_EXPORT bool MP4TagsSetDisk ( const MP4Tags*, const MP4TagDisk* );
+MP4V2_EXPORT bool MP4TagsSetTempo ( const MP4Tags*, const uint16_t* );
+MP4V2_EXPORT bool MP4TagsSetCompilation ( const MP4Tags*, const uint8_t* );
+
+MP4V2_EXPORT bool MP4TagsSetTVShow ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetTVNetwork ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetTVEpisodeID ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetTVSeason ( const MP4Tags*, const uint32_t* );
+MP4V2_EXPORT bool MP4TagsSetTVEpisode ( const MP4Tags*, const uint32_t* );
+
+MP4V2_EXPORT bool MP4TagsSetDescription ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetLongDescription ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetLyrics ( const MP4Tags*, const char* );
+
+MP4V2_EXPORT bool MP4TagsSetSortName ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetSortArtist ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetSortAlbumArtist ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetSortAlbum ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetSortComposer ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetSortTVShow ( const MP4Tags*, const char* );
+
+MP4V2_EXPORT bool MP4TagsAddArtwork ( const MP4Tags*, MP4TagArtwork* );
+MP4V2_EXPORT bool MP4TagsSetArtwork ( const MP4Tags*, uint32_t, MP4TagArtwork* );
+MP4V2_EXPORT bool MP4TagsRemoveArtwork ( const MP4Tags*, uint32_t );
+
+MP4V2_EXPORT bool MP4TagsSetCopyright ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetEncodingTool ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetEncodedBy ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetPurchaseDate ( const MP4Tags*, const char* );
+
+MP4V2_EXPORT bool MP4TagsSetPodcast ( const MP4Tags*, const uint8_t* );
+MP4V2_EXPORT bool MP4TagsSetKeywords ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetCategory ( const MP4Tags*, const char* );
+
+MP4V2_EXPORT bool MP4TagsSetHDVideo ( const MP4Tags*, const uint8_t* );
+MP4V2_EXPORT bool MP4TagsSetMediaType ( const MP4Tags*, const uint8_t* );
+MP4V2_EXPORT bool MP4TagsSetContentRating ( const MP4Tags*, const uint8_t* );
+MP4V2_EXPORT bool MP4TagsSetGapless ( const MP4Tags*, const uint8_t* );
+
+MP4V2_EXPORT bool MP4TagsSetITunesAccount ( const MP4Tags*, const char* );
+MP4V2_EXPORT bool MP4TagsSetITunesAccountType ( const MP4Tags*, const uint8_t* );
+MP4V2_EXPORT bool MP4TagsSetITunesCountry ( const MP4Tags*, const uint32_t* );
+MP4V2_EXPORT bool MP4TagsSetContentID ( const MP4Tags*, const uint32_t* );
+MP4V2_EXPORT bool MP4TagsSetArtistID ( const MP4Tags*, const uint32_t* );
+MP4V2_EXPORT bool MP4TagsSetPlaylistID ( const MP4Tags*, const uint64_t* );
+MP4V2_EXPORT bool MP4TagsSetGenreID ( const MP4Tags*, const uint32_t* );
+MP4V2_EXPORT bool MP4TagsSetComposerID ( const MP4Tags*, const uint32_t* );
+MP4V2_EXPORT bool MP4TagsSetXID ( const MP4Tags*, const char* );
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_ITMF_TAGS_H */
diff --git a/include/mp4v2/mp4v2.h b/include/mp4v2/mp4v2.h
new file mode 100644
index 0000000..4d8e807
--- /dev/null
+++ b/include/mp4v2/mp4v2.h
@@ -0,0 +1,83 @@
+/*
+ * 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 MP4V2_MP4V2_H
+#define MP4V2_MP4V2_H
+
+/*****************************************************************************/
+
+#include <mp4v2/platform.h>
+#include <mp4v2/project.h>
+
+/*****************************************************************************/
+
+/* exploit C++ ability of default values for function parameters */
+#if defined( DEFAULT )
+# define __MP4V2_SAVE_DEFAULT DEFAULT
+#endif
+#undef DEFAULT
+#if defined( __cplusplus )
+# define DEFAULT(x) =x
+#else
+# define DEFAULT(x)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************/
+
+#include <mp4v2/general.h>
+#include <mp4v2/file.h>
+#include <mp4v2/file_prop.h>
+#include <mp4v2/track.h>
+#include <mp4v2/track_prop.h>
+#include <mp4v2/sample.h>
+#include <mp4v2/chapter.h>
+#include <mp4v2/itmf_generic.h>
+#include <mp4v2/itmf_tags.h>
+#include <mp4v2/streaming.h>
+#include <mp4v2/isma.h>
+
+/*****************************************************************************/
+
+/* restore macro DEFAULT to state prior to mp4v2 headers */
+#undef DEFAULT
+#if defined( __MP4V2_SAVE_DEFAULT )
+# define DEFAULT __MP4V2_SAVE_DEFAULT
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+/*****************************************************************************/
+
+#endif /* MP4V2_MP4V2_H */
diff --git a/include/mp4v2/platform.h b/include/mp4v2/platform.h
new file mode 100644
index 0000000..aea948a
--- /dev/null
+++ b/include/mp4v2/platform.h
@@ -0,0 +1,95 @@
+#ifndef MP4V2_PLATFORM_H
+#define MP4V2_PLATFORM_H
+
+/*****************************************************************************/
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+// Thanks, MSFT, for making C99 a total PITA. Declare this not to define any stdint stuff; this is useful
+// if you're going to be using mp4v2 on windows with some other library that defines its own stdint.
+// The 1600 version check is for Visual Studio 2010 which has stdint once again.
+#ifndef MP4V2_NO_STDINT_DEFS
+ #if defined( _WIN32 ) && !defined( __MINGW32__ ) && !(defined(_MSC_VER) && _MSC_VER >= 1600)
+ typedef char int8_t;
+ typedef short int16_t;
+ typedef int int32_t;
+ typedef long long int64_t;
+
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+ typedef unsigned long long uint64_t;
+ #else
+ #include <stdint.h>
+ #endif
+#endif
+
+#if defined( _WIN32 ) || defined( __MINGW32__ )
+# if defined( MP4V2_EXPORTS )
+# define MP4V2_EXPORT __declspec(dllexport)
+# elif defined( MP4V2_USE_DLL_IMPORT ) || !defined( MP4V2_USE_STATIC_LIB )
+# define MP4V2_EXPORT __declspec(dllimport)
+# else
+# define MP4V2_EXPORT
+# endif
+#else
+# define MP4V2_EXPORT __attribute__((visibility("default")))
+#endif
+
+#if defined( __GNUC__ )
+# define MP4V2_DEPRECATED __attribute__((deprecated))
+#else
+# define MP4V2_DEPRECATED
+#endif
+
+/******************************************************************************
+ *
+ * TODO-KB: cleanup -- absolutely no need for a C-API to fuss with reserved
+ * C++ keywords. This will involve changing the public interface and current
+ * plan of action:
+ *
+ * typdef enum {
+ * mp4_false,
+ * mp4_true,
+ * } mp4_bool_t;
+ *
+ * followed by updating all public signatures and implementation.
+ */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#if !defined( __cplusplus )
+#ifndef bool
+#if SIZEOF_BOOL == 8
+typedef uint64_t bool;
+#else
+#if SIZEOF_BOOL == 4
+typedef uint32_t bool;
+#else
+#if SIZEOF_BOOL == 2
+typedef uint16_t bool;
+#else
+typedef unsigned char bool;
+#endif
+#endif
+#endif
+#ifndef false
+#define false FALSE
+#endif
+#ifndef true
+#define true TRUE
+#endif
+#endif
+#endif
+
+/*****************************************************************************/
+
+#endif /* MP4V2_PLATFORM_H */
diff --git a/include/mp4v2/project.h b/include/mp4v2/project.h
new file mode 100644
index 0000000..07ff7b9
--- /dev/null
+++ b/include/mp4v2/project.h
@@ -0,0 +1,31 @@
+#ifndef MP4V2_PROJECT_H
+#define MP4V2_PROJECT_H
+
+/*****************************************************************************/
+
+#define MP4V2_PROJECT_name "MP4v2"
+#define MP4V2_PROJECT_name_lower "mp4v2"
+#define MP4V2_PROJECT_name_upper "MP4V2"
+#define MP4V2_PROJECT_name_formal "MP4v2 -r"
+#define MP4V2_PROJECT_url_website "http://code.google.com/p/mp4v2"
+#define MP4V2_PROJECT_url_downloads "http://code.google.com/p/mp4v2/downloads/list"
+#define MP4V2_PROJECT_url_discussion "http://groups.google.com/group/mp4v2"
+#define MP4V2_PROJECT_irc "irc://irc.freenode.net/handbrake"
+#define MP4V2_PROJECT_bugreport "<kidjan@gmail.com>"
+#define MP4V2_PROJECT_version "-r"
+#define MP4V2_PROJECT_version_hex 0x00020100
+#define MP4V2_PROJECT_version_major 2
+#define MP4V2_PROJECT_version_minor 1
+#define MP4V2_PROJECT_version_point 0
+#define MP4V2_PROJECT_repo_url "svn://nowhere.com/project/unknown"
+#define MP4V2_PROJECT_repo_branch "unknown"
+#define MP4V2_PROJECT_repo_root "svn://nowhere.com/project"
+#define MP4V2_PROJECT_repo_uuid "00000000-0000-0000-0000-000000000000"
+#define MP4V2_PROJECT_repo_rev 0
+#define MP4V2_PROJECT_repo_date "unknown"
+#define MP4V2_PROJECT_repo_type "developer"
+#define MP4V2_PROJECT_build "Tue Nov 15 12:09:50 PST 2016"
+
+/*****************************************************************************/
+
+#endif /* MP4V2_PROJECT_H */
diff --git a/include/mp4v2/project.h.in b/include/mp4v2/project.h.in
new file mode 100644
index 0000000..59777c6
--- /dev/null
+++ b/include/mp4v2/project.h.in
@@ -0,0 +1,31 @@
+#ifndef MP4V2_PROJECT_H
+#define MP4V2_PROJECT_H
+
+/*****************************************************************************/
+
+#define MP4V2_PROJECT_name "@PROJECT_name@"
+#define MP4V2_PROJECT_name_lower "@PROJECT_name_lower@"
+#define MP4V2_PROJECT_name_upper "@PROJECT_name_upper@"
+#define MP4V2_PROJECT_name_formal "@PROJECT_name_formal@"
+#define MP4V2_PROJECT_url_website "@PROJECT_url_website@"
+#define MP4V2_PROJECT_url_downloads "@PROJECT_url_downloads@"
+#define MP4V2_PROJECT_url_discussion "@PROJECT_url_discussion@"
+#define MP4V2_PROJECT_irc "@PROJECT_irc@"
+#define MP4V2_PROJECT_bugreport "@PROJECT_bugreport@"
+#define MP4V2_PROJECT_version "@PROJECT_version@"
+#define MP4V2_PROJECT_version_hex @PROJECT_version_hex@
+#define MP4V2_PROJECT_version_major @PROJECT_version_major@
+#define MP4V2_PROJECT_version_minor @PROJECT_version_minor@
+#define MP4V2_PROJECT_version_point @PROJECT_version_point@
+#define MP4V2_PROJECT_repo_url "@PROJECT_repo_url@"
+#define MP4V2_PROJECT_repo_branch "@PROJECT_repo_branch@"
+#define MP4V2_PROJECT_repo_root "@PROJECT_repo_root@"
+#define MP4V2_PROJECT_repo_uuid "@PROJECT_repo_uuid@"
+#define MP4V2_PROJECT_repo_rev @PROJECT_repo_rev@
+#define MP4V2_PROJECT_repo_date "@PROJECT_repo_date@"
+#define MP4V2_PROJECT_repo_type "@PROJECT_repo_type@"
+#define MP4V2_PROJECT_build "@PROJECT_build@"
+
+/*****************************************************************************/
+
+#endif /* MP4V2_PROJECT_H */
diff --git a/include/mp4v2/sample.h b/include/mp4v2/sample.h
new file mode 100644
index 0000000..ba35a57
--- /dev/null
+++ b/include/mp4v2/sample.h
@@ -0,0 +1,557 @@
+#ifndef MP4V2_SAMPLE_H
+#define MP4V2_SAMPLE_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_sample MP4v2 Sample
+ * @{
+ *
+ *****************************************************************************/
+
+/** Sample dependency types.
+ *
+ * Bit combinations 0x03, 0x30, 0xc0 are reserved.
+ */
+typedef enum MP4SampleDependencyType_e {
+ MP4_SDT_UNKNOWN = 0x00, /**< unknown */
+ MP4_SDT_HAS_REDUNDANT_CODING = 0x01, /**< contains redundant coding */
+ MP4_SDT_HAS_NO_REDUNDANT_CODING = 0x02, /**< does not contain redundant coding */
+ MP4_SDT_HAS_DEPENDENTS = 0x04, /**< referenced by other samples */
+ MP4_SDT_HAS_NO_DEPENDENTS = 0x08, /**< not referenced by other samples */
+ MP4_SDT_IS_DEPENDENT = 0x10, /**< references other samples */
+ MP4_SDT_IS_INDEPENDENT = 0x20, /**< does not reference other samples */
+ MP4_SDT_EARLIER_DISPLAY_TIMES_ALLOWED = 0x40, /**< subequent samples in GOP may display earlier */
+ _MP4_SDT_RESERVED = 0x80 /**< reserved */
+} MP4SampleDependencyType;
+
+/** Read a track sample.
+ *
+ * MP4ReadSample reads the specified sample from the specified track.
+ * Typically this sample is then decoded in a codec dependent fashion and
+ * rendered in an appropriate fashion.
+ *
+ * The argument <b>ppBytes</b> allows for two possible approaches for
+ * buffering:
+ *
+ * If the calling application wishes to handle its own buffering it can set
+ * *ppBytes to the buffer it wishes to use. The calling application is
+ * responsible for ensuring that the buffer is large enough to hold the
+ * sample. This can be done by using either MP4GetSampleSize() or
+ * MP4GetTrackMaxSampleSize() to determine before-hand how large the
+ * receiving buffer must be.
+ *
+ * If the value of *ppBytes is NULL, then an appropriately sized buffer is
+ * automatically malloc'ed for the sample data and *ppBytes set to this
+ * pointer. The calling application is responsible for free'ing this
+ * memory.
+ *
+ * The last four arguments are pointers to variables that can receive
+ * optional sample information.
+ *
+ * Typically for audio none of these are needed. MPEG audio such as MP3 or
+ * AAC has a fixed sample duration and every sample can be accessed at
+ * random.
+ *
+ * For video, all of these optional values could be needed. MPEG video can
+ * be encoded at a variable frame rate, with only occasional random access
+ * points, and with "B frames" which cause the rendering (display) order
+ * of the video frames to differ from the storage/decoding order.
+ *
+ * Other media types fall between these two extremes.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param sampleId specifies which sample is to be read.
+ * Caveat: the first sample has id <b>1</b> not <b>0</b>.
+ * @param ppBytes pointer to the pointer to the sample data.
+ * @param pNumBytes pointer to variable that will be hold the size in bytes
+ * of the sample.
+ * @param pStartTime if non-NULL, pointer to variable that will receive the
+ * starting timestamp for this sample. Caveat: The timestamp is in
+ * <b>trackId</b>'s timescale.
+ * @param pDuration if non-NULL, pointer to variable that will receive the
+ * duration for this sample. Caveat: The duration is in
+ * <b>trackId</b>'s timescale.
+ * @param pRenderingOffset if non-NULL, pointer to variable that will
+ * receive the rendering offset for this sample. Currently the only
+ * media type that needs this feature is MPEG video. Caveat: The offset
+ * is in <b>trackId</b>'s timescale.
+ * @param pIsSyncSample if non-NULL, pointer to variable that will receive
+ * the state of the sync/random access flag for this sample.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ *
+ * @see MP4GetSampleSize().
+ * @see MP4GetTrackMaxSampleSize().
+ */
+MP4V2_EXPORT
+bool MP4ReadSample(
+ /* input parameters */
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId,
+ /* input/output parameters */
+ uint8_t** ppBytes,
+ uint32_t* pNumBytes,
+ /* output parameters */
+ MP4Timestamp* pStartTime DEFAULT(NULL),
+ MP4Duration* pDuration DEFAULT(NULL),
+ MP4Duration* pRenderingOffset DEFAULT(NULL),
+ bool* pIsSyncSample DEFAULT(NULL) );
+
+/** Read a track sample based on a specified time.
+ *
+ * MP4ReadSampleFromTime is similar to MP4ReadSample() except the sample
+ * is specified by using a timestamp instead of sampleId.
+ * Typically this sample is then decoded in a codec dependent fashion and
+ * rendered in an appropriate fashion.
+ *
+ * The argument <b>ppBytes</b> allows for two possible approaches for
+ * buffering:
+ *
+ * If the calling application wishes to handle its own buffering it can set
+ * *ppBytes to the buffer it wishes to use. The calling application is
+ * responsible for ensuring that the buffer is large enough to hold the
+ * sample. This can be done by using either MP4GetSampleSize() or
+ * MP4GetTrackMaxSampleSize() to determine before-hand how large the
+ * receiving buffer must be.
+ *
+ * If the value of *ppBytes is NULL, then an appropriately sized buffer is
+ * automatically malloc'ed for the sample data and *ppBytes set to this
+ * pointer. The calling application is responsible for free'ing this
+ * memory.
+ *
+ * The last four arguments are pointers to variables that can receive
+ * optional sample information.
+ *
+ * Typically for audio none of these are needed. MPEG audio such as MP3 or
+ * AAC has a fixed sample duration and every sample can be accessed at
+ * random.
+ *
+ * For video, all of these optional values could be needed. MPEG video can
+ * be encoded at a variable frame rate, with only occasional random access
+ * points, and with "B frames" which cause the rendering (display) order
+ * of the video frames to differ from the storage/decoding order.
+ *
+ * Other media types fall between these two extremes.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param when specifies which sample is to be read based on a time in the
+ * track timeline. See MP4GetSampleIdFromTime() for details.
+ * @param ppBytes pointer to the pointer to the sample data.
+ * @param pNumBytes pointer to variable that will be hold the size in bytes
+ * of the sample.
+ * @param pStartTime if non-NULL, pointer to variable that will receive the
+ * starting timestamp for this sample. Caveat: The timestamp is in
+ * <b>trackId</b>'s timescale.
+ * @param pDuration if non-NULL, pointer to variable that will receive the
+ * duration for this sample. Caveat: The duration is in
+ * <b>trackId</b>'s timescale.
+ * @param pRenderingOffset if non-NULL, pointer to variable that will
+ * receive the rendering offset for this sample. Currently the only
+ * media type that needs this feature is MPEG video. Caveat: The offset
+ * is in <b>trackId</b>'s timescale.
+ * @param pIsSyncSample if non-NULL, pointer to variable that will receive
+ * the state of the sync/random access flag for this sample.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ *
+ * @see MP4ReadSample().
+ * @see MP4GetSampleIdFromTime().
+ * @see MP4GetSampleSize().
+ * @see MP4GetTrackMaxSampleSize().
+ */
+MP4V2_EXPORT
+bool MP4ReadSampleFromTime(
+ /* input parameters */
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ /* input/output parameters */
+ uint8_t** ppBytes,
+ uint32_t* pNumBytes,
+ /* output parameters */
+ MP4Timestamp* pStartTime DEFAULT(NULL),
+ MP4Duration* pDuration DEFAULT(NULL),
+ MP4Duration* pRenderingOffset DEFAULT(NULL),
+ bool* pIsSyncSample DEFAULT(NULL) );
+
+/** Write a track sample.
+ *
+ * MP4WriteSample writes the given sample at the end of the specified track.
+ * Currently the library does not support random insertion of samples into
+ * the track timeline. Note that with mp4 there cannot be any holes or
+ * overlapping samples in the track timeline. The last three arguments give
+ * optional sample information.
+ *
+ * The value of duration can be given as #MP4_INVALID_DURATION if all samples
+ * in the track have the same duration. This can be specified with
+ * MP4AddTrack() and related functions.
+ *
+ * Typically for audio none of the optional arguments are needed. MPEG audio
+ * such as MP3 or AAC has a fixed sample duration and every sample can be
+ * accessed at random.
+ *
+ * For video, all of the optional arguments could be needed. MPEG video
+ * can be encoded at a variable frame rate, with only occasional random
+ * access points, and with "B frames" which cause the rendering (display)
+ * order of the video frames to differ from the storage/decoding order.
+ *
+ * Other media types fall between these two extremes.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param pBytes pointer to sample data.
+ * @param numBytes length of sample data in bytes.
+ * @param duration sample duration. Caveat: should be in track timescale.
+ * @param renderingOffset the rendering offset for this sample.
+ * Currently the only media type that needs this feature is MPEG
+ * video. Caveat: The offset should be in the track timescale.
+ * @param isSyncSample the sync/random access flag for this sample.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ *
+ * @see MP4AddTrack().
+ */
+MP4V2_EXPORT
+bool MP4WriteSample(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const uint8_t* pBytes,
+ uint32_t numBytes,
+ MP4Duration duration DEFAULT(MP4_INVALID_DURATION),
+ MP4Duration renderingOffset DEFAULT(0),
+ bool isSyncSample DEFAULT(true) );
+
+/** Write a track sample and supply dependency information.
+ *
+ * MP4WriteSampleDependency writes the given sample at the end of the specified track.
+ * Currently the library does not support random insertion of samples into
+ * the track timeline. Note that with mp4 there cannot be any holes or
+ * overlapping samples in the track timeline. The last three arguments give
+ * optional sample information.
+ *
+ * The value of duration can be given as #MP4_INVALID_DURATION if all samples
+ * in the track have the same duration. This can be specified with
+ * MP4AddTrack() and related functions.
+ *
+ * When this method is used instead of MP4WriteSample() it enables <b>sdtp</b>
+ * atom to be written out. This atom may be used by advanced players to
+ * optimize trick-operations such as fast-fwd, reverse or scrubbing.
+ *
+ * An <b>sdtp</b> atom will always be written out if this method is used.
+ * To avoid writing the atom, use MP4WriteSample() instead.
+ *
+ * Intermixing use of MP4WriteSampleDependency() and MP4WriteSample() on the
+ * same track is not permitted.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param pBytes pointer to sample data.
+ * @param numBytes length of sample data in bytes.
+ * @param duration sample duration. Caveat: should be in track timescale.
+ * @param renderingOffset the rendering offset for this sample.
+ * Currently the only media type that needs this feature is MPEG
+ * video. Caveat: The offset should be in the track timescale.
+ * @param isSyncSample the sync/random access flag for this sample.
+ * @param dependencyFlags bitmask specifying sample dependency characteristics.
+ * See #MP4SampleDependencyType for bit constants.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ *
+ * @see MP4AddTrack().
+ */
+MP4V2_EXPORT
+bool MP4WriteSampleDependency(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const uint8_t* pBytes,
+ uint32_t numBytes,
+ MP4Duration duration,
+ MP4Duration renderingOffset,
+ bool isSyncSample,
+ uint32_t dependencyFlags );
+
+/** Make a copy of a sample.
+ *
+ * MP4CopySample creates a new sample based on an existing sample. Note that
+ * another copy of the media sample data is created in the file using this
+ * function. ie. this call is equivalent to MP4ReadSample() followed by
+ * MP4WriteSample().
+ *
+ * Note that is the responsibility of the caller to ensure that the copied
+ * media sample makes sense in the destination track. eg. copying a video
+ * sample to an audio track is unlikely to result in anything good happening,
+ * even copying a sample from video track to another requires that the tracks
+ * use the same encoding and that issues such as image size are addressed.
+ *
+ * @param srcFile source sample file handle.
+ * @param srcTrackId source sample track id.
+ * @param srcSampleId source sample id.
+ * @param dstFile destination file handle for new (copied) sample.
+ * If the value is #MP4_INVALID_FILE_HANDLE, the copy is created in
+ * the same file as <b>srcFile</b>.
+ * @param dstTrackId destination track id for new sample.
+ * If the value is #MP4_INVALID_TRACK_ID, the the copy is created in
+ * the same track as the <b>srcTrackId</b>.
+ * @param dstSampleDuration duration in track timescale for new sample.
+ * If the value is #MP4_INVALID_DURATION, then the duration of
+ * the source sample is used.
+ *
+ * @return On success, thew id of the new sample.
+ * On error, #MP4_INVALID_SAMPLE_ID.
+ *
+ * @see MP4ReadSample().
+ * @see MP4WriteSample().
+ */
+MP4V2_EXPORT
+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) );
+
+/** Make a copy of a sample.
+ *
+ * MP4EncAndCopySample is similar to MP4CopySample() except that it
+ * offers an encryption hook to the caller.
+ *
+ * @param srcFile source sample file handle.
+ * @param srcTrackId source sample track id.
+ * @param srcSampleId source sample id.
+ * @param encfcnp undocumented.
+ * @param encfcnparam1 undocumented.
+ * @param dstFile destination file handle for new (copied) sample.
+ * If the value is #MP4_INVALID_FILE_HANDLE, the copy is created in
+ * the same file as <b>srcFile</b>.
+ * @param dstTrackId destination track id for new sample.
+ * If the value is #MP4_INVALID_TRACK_ID, the the copy is created in
+ * the same track as the <b>srcTrackId</b>.
+ * @param dstSampleDuration duration in track timescale for new sample.
+ * If the value is #MP4_INVALID_DURATION, then the duration of
+ * the source sample is used.
+ *
+ * @return On success, thew id of the new sample.
+ * On error, #MP4_INVALID_SAMPLE_ID.
+ *
+ * @see MP4CopySample().
+ */
+MP4V2_EXPORT
+bool MP4EncAndCopySample(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4SampleId srcSampleId,
+ encryptFunc_t encfcnp,
+ uint32_t encfcnparam1,
+ MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+ MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID),
+ MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION) );
+
+/** Not implemented.
+ */
+MP4V2_EXPORT
+bool MP4ReferenceSample(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4SampleId srcSampleId,
+ MP4FileHandle dstFile,
+ MP4TrackId dstTrackId,
+ MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION) );
+
+/** Get size of a track sample.
+ *
+ * MP4GetSampleSize returns the size in bytes of the specified sample from the
+ * the specified track.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param sampleId id of sample for operation. Caveat: the first sample has
+ * id <b>1</b>, not <b>0</b>.
+ *
+ * @return On success the sample size in bytes. On error, <b>0</b>.
+ */
+MP4V2_EXPORT
+uint32_t MP4GetSampleSize(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId);
+
+/** Get the maximum sample size of a track.
+ *
+ * MP4GetTrackMaxSampleSize returns the maximum size in bytes of all the
+ * samples in the specified track.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ *
+ * @return On success, the maximum sample size in bytes. On error, <b>0</b>.
+ *
+ * @see MP4GetSampleSize().
+ */
+MP4V2_EXPORT
+uint32_t MP4GetTrackMaxSampleSize(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/** Get sample id of a specified time.
+ *
+ * MP4GetSampleIdFromTime returns the sample id of the track sample in which
+ * the specified time occurs.
+ *
+ * The specified time should be in the track timescale.
+ *
+ * It is wise to use MP4GetSampleTime() with the returned sample id so one
+ * can adjust for any difference between the specified time and the actual
+ * start time of the sample.
+ *
+ * If the calling application needs a sample that can be accessed randomly
+ * then the <b>wantSyncSample</b> argument should be set to true. This could
+ * be the case for a player that is implementing a positioning function and
+ * needs to be able to start decoding a track from the returned sample id.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param when time in track timescale.
+ * @param wantSyncSample specifies if the result sample id must correspond
+ * to a sample whose sync/random access flag is true.
+ *
+ * @return On success, the sample id that occurs at the specified time.
+ * On error, #MP4_INVALID_SAMPLE_ID.
+ *
+ * @see MP4ConvertToTrackTimestamp() for how to map a time value to this
+ * timescale.
+ */
+MP4V2_EXPORT
+MP4SampleId MP4GetSampleIdFromTime(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ bool wantSyncSample DEFAULT(false) );
+
+/** Get start time of track sample.
+ *
+ * MP4GetSampleTime returns the start time of the specified sample from
+ * the specified track in the track timescale units.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param sampleId id of sample for operation. Caveat: the first sample has
+ * id <b>1</b>, not <b>0</b>.
+ *
+ * @return On success, sample start time in track timescale units.
+ * On error, #MP4_INVALID_TIMESTAMP.
+ *
+ * @see MP4ConvertFromTrackTimestamp() for how to map this value to another
+ * timescale.
+ */
+MP4V2_EXPORT
+MP4Timestamp MP4GetSampleTime(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId );
+
+/** Get the duration of a track sample.
+ *
+ * MP4GetSampleDuration returns the duration of the specified sample from
+ * the specified track in the track timescale units.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param sampleId id of sample for operation. Caveat: the first sample has
+ * id <b>1</b>, not <b>0</b>.
+ *
+ * @return On success, the sample duration in track timescale units.
+ * On error, #MP4_INVALID_DURATION.
+ *
+ * @see MP4ConvertFromTrackDuration() for how to map this value to another
+ * timescale.
+ */
+MP4V2_EXPORT
+MP4Duration MP4GetSampleDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId );
+
+/** Get the rendering offset of a track sample.
+ *
+ * MP4GetSampleRenderingOffset returns the rendering offset of the specified
+ * sample from the specified track in the track timescale units.
+ *
+ * The sample rendering offset is typically zero for all media types other
+ * than video. For video, encodings such as those defined by MPEG have
+ * three types of frames: I, P, and B. To increase coding efficiency B
+ * frames can depend on I or P frames that should be rendered after the B
+ * frame. However to decode the B frame the I or P frame must already have
+ * been decoded. This situation is addressed by placing the frames in
+ * decoding order in the video track, and then setting the rendering offset
+ * property to indicate when the video frame should actually be rendered to
+ * the screen. Hence the start time of a sample indicates when it should be
+ * decoded, the start time plus the rendering offset indicates when it
+ * should be rendered.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param sampleId id of sample for operation. Caveat: the first sample has
+ * id <b>1</b>, not <b>0</b>.
+ *
+ * @return On success, the rendering offset in track timescale units.
+ * On error, #MP4_INVALID_DURATION.
+ *
+ * @see MP4ConvertFromTrackDuration() for how to map this value to another
+ * timescale.
+ */
+MP4V2_EXPORT
+MP4Duration MP4GetSampleRenderingOffset(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId );
+
+/** Set the rendering offset of a track sample.
+ *
+ * MP4SetSampleRenderingOffset sets the rendering offset of the specified
+ * sample from the specified track in the track timescale units.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param sampleId id of sample for operation. Caveat: the first sample has
+ * id <b>1</b>, not <b>0</b>.
+ * @param renderingOffset new offset value in timescale units.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ *
+ * @see MP4ConvertToTrackDuration() for how to map this value from another
+ * timescale.
+ * @see MP4GetSampleRenderingOffset() for a description of this sample
+ * property.
+ */
+MP4V2_EXPORT
+bool MP4SetSampleRenderingOffset(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId,
+ MP4Duration renderingOffset );
+
+/** Get sync/random access state of sample.
+ *
+ * MP4GetSampleSync returns the state of the sync/random access flag of
+ * the specified sample from the specified track.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param sampleId id of sample for operation. Caveat: the first sample has
+ * id <b>1</b>, not <b>0</b>.
+ *
+ * @return <b>1</b> when true, <b>0</b> when false. On error, <b>-1</b>.
+ */
+MP4V2_EXPORT
+int8_t MP4GetSampleSync(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId );
+
+/* @} ***********************************************************************/
+
+#endif /* MP4V2_SAMPLE_H */
diff --git a/include/mp4v2/streaming.h b/include/mp4v2/streaming.h
new file mode 100644
index 0000000..36389d6
--- /dev/null
+++ b/include/mp4v2/streaming.h
@@ -0,0 +1,163 @@
+#ifndef MP4V2_STREAMING_H
+#define MP4V2_STREAMING_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_hint MP4v2 Streaming
+ * @{
+ *
+ *****************************************************************************/
+
+MP4V2_EXPORT
+bool MP4GetHintTrackRtpPayload(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ char** ppPayloadName DEFAULT(NULL),
+ uint8_t* pPayloadNumber DEFAULT(NULL),
+ uint16_t* pMaxPayloadSize DEFAULT(NULL),
+ char** ppEncodingParams DEFAULT(NULL) );
+
+#define MP4_SET_DYNAMIC_PAYLOAD 0xff
+
+MP4V2_EXPORT
+bool MP4SetHintTrackRtpPayload(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const char* pPayloadName,
+ uint8_t* pPayloadNumber,
+ uint16_t maxPayloadSize DEFAULT(0),
+ const char * encode_params DEFAULT(NULL),
+ bool include_rtp_map DEFAULT(true),
+ bool include_mpeg4_esid DEFAULT(true) );
+
+MP4V2_EXPORT
+const char* MP4GetSessionSdp(
+ MP4FileHandle hFile );
+
+MP4V2_EXPORT
+bool MP4SetSessionSdp(
+ MP4FileHandle hFile,
+ const char* sdpString );
+
+MP4V2_EXPORT
+bool MP4AppendSessionSdp(
+ MP4FileHandle hFile,
+ const char* sdpString );
+
+MP4V2_EXPORT
+const char* MP4GetHintTrackSdp(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId );
+
+MP4V2_EXPORT
+bool MP4SetHintTrackSdp(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const char* sdpString );
+
+MP4V2_EXPORT
+bool MP4AppendHintTrackSdp(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const char* sdpString );
+
+MP4V2_EXPORT
+MP4TrackId MP4GetHintTrackReferenceTrackId(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId );
+
+MP4V2_EXPORT
+bool MP4ReadRtpHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4SampleId hintSampleId,
+ uint16_t* pNumPackets DEFAULT(NULL) );
+
+MP4V2_EXPORT
+uint16_t MP4GetRtpHintNumberOfPackets(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId );
+
+MP4V2_EXPORT
+int8_t MP4GetRtpPacketBFrame(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ uint16_t packetIndex );
+
+MP4V2_EXPORT
+int32_t MP4GetRtpPacketTransmitOffset(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ uint16_t packetIndex );
+
+MP4V2_EXPORT
+bool MP4ReadRtpPacket(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ uint16_t packetIndex,
+ uint8_t** ppBytes,
+ uint32_t* pNumBytes,
+ uint32_t ssrc DEFAULT(0),
+ bool includeHeader DEFAULT(true),
+ bool includePayload DEFAULT(true) );
+
+MP4V2_EXPORT
+MP4Timestamp MP4GetRtpTimestampStart(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId );
+
+MP4V2_EXPORT
+bool MP4SetRtpTimestampStart(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4Timestamp rtpStart );
+
+MP4V2_EXPORT
+bool MP4AddRtpHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId );
+
+MP4V2_EXPORT
+bool MP4AddRtpVideoHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ bool isBframe DEFAULT(false),
+ uint32_t timestampOffset DEFAULT(0) );
+
+MP4V2_EXPORT
+bool MP4AddRtpPacket(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ bool setMbit DEFAULT(false),
+ int32_t transmitOffset DEFAULT(0) );
+
+MP4V2_EXPORT
+bool MP4AddRtpImmediateData(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const uint8_t* pBytes,
+ uint32_t numBytes );
+
+MP4V2_EXPORT
+bool MP4AddRtpSampleData(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4SampleId sampleId,
+ uint32_t dataOffset,
+ uint32_t dataLength );
+
+MP4V2_EXPORT
+bool MP4AddRtpESConfigurationPacket(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId );
+
+MP4V2_EXPORT
+bool MP4WriteRtpHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4Duration duration,
+ bool isSyncSample DEFAULT(true) );
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_STREAMING_H */
diff --git a/include/mp4v2/track.h b/include/mp4v2/track.h
new file mode 100644
index 0000000..90eb7bc
--- /dev/null
+++ b/include/mp4v2/track.h
@@ -0,0 +1,451 @@
+#ifndef MP4V2_TRACK_H
+#define MP4V2_TRACK_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_track MP4v2 Track
+ * @{
+ *
+ *****************************************************************************/
+
+/** Add a user defined track.
+ *
+ * MP4AddTrack adds a user defined track to the mp4 file. Care should be
+ * taken to avoid any of the standardized track type names. A useful
+ * convention is use only uppercase characters for user defined track types.
+ * The string should be exactly four characters in length, e.g. "MINE".
+ *
+ * Note this should not be used to add any of the known track types defined
+ * in the MP4 standard (ISO/IEC 14496-1:2001).
+ *
+ * @param hFile handle of file for operation.
+ * @param type specifies the type of track to be added.
+ * @param timeScale the time scale in ticks per second of the track. Default is 1000.
+ *
+ * @return On success, the track-id of new track.
+ * On failure, #MP4_INVALID_TRACK_ID.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddTrack(
+ MP4FileHandle hFile,
+ const char* type,
+ uint32_t timeScale DEFAULT(MP4_MSECS_TIME_SCALE) );
+
+/** Add an MPEG-4 systems track.
+ *
+ * MP4AddSystemsTrack adds an MPEG-4 Systems track to the mp4 file. Note
+ * this should not be used to add OD or scene tracks, MP4AddODTrack() and
+ * MP4AddSceneTrack() should be used for those purposes. Other known
+ * MPEG-4 System track types are:
+ * @li #MP4_CLOCK_TRACK_TYPE
+ * @li #MP4_MPEG7_TRACK_TYPE
+ * @li #MP4_OCI_TRACK_TYPE
+ * @li #MP4_IPMP_TRACK_TYPE
+ * @li #MP4_MPEGJ_TRACK_TYPE
+ *
+ * @param hFile handle of file for operation.
+ * @param type specifies the type of track to be added.
+ *
+ * @return On success, the track-id of new track.
+ * On failure, #MP4_INVALID_TRACK_ID.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddSystemsTrack(
+ MP4FileHandle hFile,
+ const char* type );
+
+/** Add a object descriptor (OD) track.
+ *
+ * MP4AddODTrack adds an object descriptor (aka OD) track to the mp4 file.
+ * MP4WriteSample() can then be used to add the desired OD commands to the
+ * track. The burden is currently on the calling application to understand
+ * OD.
+ *
+ * Those wishing to have a simple audio/video scene without understanding
+ * OD may wish to use MP4MakeIsmaCompliant() to create the minimal OD and
+ * BIFS information.
+ *
+ * @param hFile handle of file for operation.
+ *
+ * @return On success, the track-id of new track.
+ * On failure, #MP4_INVALID_TRACK_ID.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddODTrack(
+ MP4FileHandle hFile );
+
+/** Add a scene (BIFS) track.
+ *
+ * MP4AddSceneTrack adds a scene (aka BIFS) track to the mp4 file.
+ * MP4WriteSample() can then be used to add the desired BIFS commands to
+ * the track. The burden is currently on the calling application to
+ * understand BIFS.
+ *
+ * Those wishing to have a simple audio/video scene without understanding
+ * BIFS may wish to use MP4MakeIsmaCompliant() to create the minimal OD
+ * and BIFS information.
+ *
+ * @param hFile handle of file for operation.
+ *
+ * @return On success, the track-id of new track.
+ * On failure, #MP4_INVALID_TRACK_ID.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddSceneTrack(
+ MP4FileHandle hFile );
+
+/** Add audio track to mp4 file.
+ *
+ * MP4AddAudioTrack adds an audio track to the mp4 file. MP4WriteSample()
+ * can then be used to add the desired audio samples.
+ *
+ * It is recommended that the time scale be set to the sampling frequency
+ * (eg. 44100 Hz) of the audio so as to preserve the timing information
+ * accurately.
+ *
+ * If the audio encoding uses a fixed duration for each sample that should
+ * be specified here. If not then the value #MP4_INVALID_DURATION
+ * should be given for the sampleDuration argument.
+ *
+ * @param hFile handle of file for operation.
+ * @param timeScale the time scale in ticks per second of the track.
+ * @param sampleDuration the fixed duration for all track samples.
+ * Caveat: the value should be in track-timescale units.
+ * @param audioType the audio encoding type.
+ * See MP4GetTrackEsdsObjectTypeId() for known values.
+ *
+ * @return On success, the track-id of the new track.
+ * On error, #MP4_INVALID_TRACK_ID.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddAudioTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ uint8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE) );
+
+/** Add ulaw track to mp4 file.
+ *
+ * MP4AddULawAudioTrack adds a ulaw track to the mp4 file. MP4WriteSample()
+ * can then be used to add the desired audio samples.
+ *
+ * @param hFile handle of file for operation.
+ * @param timeScale the time scale in ticks per second of the track.
+ *
+ * @return On success, the track-id of the new track.
+ * On error, #MP4_INVALID_TRACK_ID.
+*/
+MP4V2_EXPORT
+MP4TrackId MP4AddULawAudioTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale);
+
+/** Add alaw track to mp4 file.
+ *
+ * MP4AddALawAudioTrack adds a alaw track to the mp4 file. MP4WriteSample()
+ * can then be used to add the desired audio samples.
+ *
+ * @param hFile handle of file for operation.
+ * @param timeScale the time scale in ticks per second of the track.
+ *
+ * @return On success, the track-id of the new track.
+ * On error, #MP4_INVALID_TRACK_ID.
+*/
+MP4V2_EXPORT
+MP4TrackId MP4AddALawAudioTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale);
+
+MP4V2_EXPORT
+MP4TrackId MP4AddAC3AudioTrack(
+ MP4FileHandle hFile,
+ uint32_t samplingRate,
+ uint8_t fscod,
+ uint8_t bsid,
+ uint8_t bsmod,
+ uint8_t acmod,
+ uint8_t lfeon,
+ uint8_t bit_rate_code );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddAmrAudioTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ uint16_t modeSet,
+ uint8_t modeChangePeriod,
+ uint8_t framesPerSample,
+ bool isAmrWB );
+
+MP4V2_EXPORT
+void MP4SetAmrVendor(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint32_t vendor );
+
+MP4V2_EXPORT
+void MP4SetAmrDecoderVersion(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t decoderVersion );
+
+MP4V2_EXPORT
+void MP4SetAmrModeSet(
+ MP4FileHandle hFile,
+ MP4TrackId trakId,
+ uint16_t modeSet );
+
+MP4V2_EXPORT
+uint16_t MP4GetAmrModeSet(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddHrefTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ const char* base_url DEFAULT(NULL) );
+
+MP4V2_EXPORT
+const char* MP4GetHrefTrackBaseUrl(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/** Add a video track.
+ *
+ * MP4AddVideoTrack adds a video track to the mp4 file. MP4WriteSample()
+ * can then be used to add the desired video samples.
+ *
+ * It is recommended that the time scale be set to 90000 so as to preserve
+ * the timing information accurately for the range of video frame rates
+ * commonly in use.
+ *
+ * If the video frame rate is to be fixed then the sampleDuration argument
+ * should be give the appropriate fixed value. If the video frame rate is
+ * to be variable then the value #MP4_INVALID_DURATION should be
+ * given for the sampleDuration argument.
+ *
+ * @param hFile handle of file for operation.
+ * @param timeScale the timescale in ticks per second of the track.
+ * @param sampleDuration specifies fixed sample duration for all track
+ * samples. Caveat: the value should be in track timescale units.
+ * @param width specifies the video frame width in pixels.
+ * @param height specifies the video frame height in pixels.
+ * @param videoType specifies the video encoding type.
+ * See MP4GetTrackVideoType() for known values.
+ *
+ * @return On success, the track-id of the new track.
+ * On error, #MP4_INVALID_TRACK_ID.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddVideoTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ uint16_t width,
+ uint16_t height,
+ uint8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE) );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddH264VideoTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ uint16_t width,
+ uint16_t height,
+ uint8_t AVCProfileIndication,
+ uint8_t profile_compat,
+ uint8_t AVCLevelIndication,
+ uint8_t sampleLenFieldSizeMinusOne );
+
+MP4V2_EXPORT
+void MP4AddH264SequenceParameterSet(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const uint8_t* pSequence,
+ uint16_t sequenceLen );
+
+MP4V2_EXPORT
+void MP4AddH264PictureParameterSet(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const uint8_t* pPict,
+ uint16_t pictLen );
+
+MP4V2_EXPORT
+void MP4SetH263Vendor(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint32_t vendor );
+
+MP4V2_EXPORT
+void MP4SetH263DecoderVersion(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t decoderVersion );
+
+MP4V2_EXPORT
+void MP4SetH263Bitrates(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint32_t avgBitrate,
+ uint32_t maxBitrate );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddH263VideoTrack(
+ MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ uint16_t width,
+ uint16_t height,
+ uint8_t h263Level,
+ uint8_t h263Profile,
+ uint32_t avgBitrate,
+ uint32_t maxBitrate );
+
+/** Add a hint track.
+ *
+ * MP4AddHintTrack adds a hint track to the mp4 file. A hint track is used
+ * to describe how to send the reference media track over a particular
+ * network transport. In the case of the IETF RTP protocol, the hint track
+ * describes how the media data should be placed into packets and any
+ * media specific protocol headers that should be added.
+ *
+ * Typically there is a one to one correspondence between reference media
+ * track samples and hint track samples. The start time, duration, and
+ * sync flags are typically the same, however provisions are made for
+ * deviations from this rule.
+ *
+ * The MP4 library provides extensive support for RTP hint tracks. This
+ * includes a easy to use API to create RTP hint tracks, and read out
+ * fully constructed RTP packets based on the hint track.
+ *
+ * @param hFile handle of file for operation.
+ * @param refTrackId specifies the reference media track for this hint track.
+ *
+ * @return On success, the track-id of the new track.
+ * On error, #MP4_INVALID_TRACK_ID.
+ */
+MP4V2_EXPORT
+MP4TrackId MP4AddHintTrack(
+ MP4FileHandle hFile,
+ MP4TrackId refTrackId );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddTextTrack(
+ MP4FileHandle hFile,
+ MP4TrackId refTrackId );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddSubtitleTrack(
+ MP4FileHandle hFile,
+ uint32_t timescale,
+ uint16_t width,
+ uint16_t height );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddSubpicTrack(
+ MP4FileHandle hFile,
+ uint32_t timescale,
+ uint16_t width,
+ uint16_t height );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddPixelAspectRatio(
+ MP4FileHandle hFile,
+ MP4TrackId refTrackId,
+ uint32_t hSpacing,
+ uint32_t vSpacing );
+
+MP4V2_EXPORT
+MP4TrackId MP4AddColr(
+ MP4FileHandle hFile,
+ MP4TrackId refTrackId,
+ uint16_t primary,
+ uint16_t transfer,
+ uint16_t matrix );
+
+MP4V2_EXPORT
+MP4TrackId MP4CloneTrack(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+ MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) );
+
+MP4V2_EXPORT
+MP4TrackId MP4CopyTrack(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+ bool applyEdits DEFAULT(false),
+ MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID) );
+
+MP4V2_EXPORT
+bool MP4DeleteTrack(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+uint32_t MP4GetNumberOfTracks(
+ MP4FileHandle hFile,
+ const char* type DEFAULT(NULL),
+ uint8_t subType DEFAULT(0) );
+
+MP4V2_EXPORT
+MP4TrackId MP4FindTrackId(
+ MP4FileHandle hFile,
+ uint16_t index,
+ const char* type DEFAULT(NULL),
+ uint8_t subType DEFAULT(0) );
+
+MP4V2_EXPORT
+uint16_t MP4FindTrackIndex(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/** Get maximum duration of chunk.
+ *
+ * MP4GetTrackDurationPerChunk gets the maximum duration for each chunk.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param duration out value of duration in track timescale units.
+ *
+ * return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4GetTrackDurationPerChunk(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Duration* duration );
+
+/** Set maximum duration of chunk.
+ *
+ * MP4SetTrackDurationPerChunk sets the maximum duration for each chunk.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param duration in timescale units.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4SetTrackDurationPerChunk(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Duration duration );
+
+/**
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4AddIPodUUID(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_TRACK_H */
diff --git a/include/mp4v2/track_prop.h b/include/mp4v2/track_prop.h
new file mode 100644
index 0000000..4b3adf4
--- /dev/null
+++ b/include/mp4v2/track_prop.h
@@ -0,0 +1,366 @@
+#ifndef MP4V2_TRACK_PROP_H
+#define MP4V2_TRACK_PROP_H
+
+/**************************************************************************//**
+ *
+ * @defgroup mp4_track_prop MP4v2 Track Property
+ * @{
+ *
+ *****************************************************************************/
+
+/* specific track properties */
+
+MP4V2_EXPORT
+bool MP4HaveTrackAtom(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* atomname );
+
+/** Get the track type.
+ *
+ * MP4GetTrackType gets the type of the track with the specified track id.
+ *
+ * Note: the library does not provide a MP4SetTrackType function, the
+ * track type needs to be specified when the track is created, e.g.
+ * MP4AddSystemsTrack(MP4_OCI_TRACK_TYPE).
+ *
+ * Known track types are:
+ * @li #MP4_OD_TRACK_TYPE
+ * @li #MP4_SCENE_TRACK_TYPE
+ * @li #MP4_AUDIO_TRACK_TYPE
+ * @li #MP4_VIDEO_TRACK_TYPE
+ * @li #MP4_HINT_TRACK_TYPE
+ * @li #MP4_CNTL_TRACK_TYPE
+ * @li #MP4_TEXT_TRACK_TYPE
+ * @li #MP4_CLOCK_TRACK_TYPE
+ * @li #MP4_MPEG7_TRACK_TYPE
+ * @li #MP4_OCI_TRACK_TYPE
+ * @li #MP4_IPMP_TRACK_TYPE
+ * @li #MP4_MPEGJ_TRACK_TYPE
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ *
+ * @return On success, a string indicating track type. On failure, NULL.
+ */
+MP4V2_EXPORT
+const char* MP4GetTrackType(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+const char* MP4GetTrackMediaDataName(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/*
+ * MP4GetTrackMediaDataOriginalFormat is to be used to get the original
+ * MediaDataName if a track has been encrypted.
+ */
+
+MP4V2_EXPORT
+bool MP4GetTrackMediaDataOriginalFormat(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ char* originalFormat,
+ uint32_t buflen );
+
+MP4V2_EXPORT
+MP4Duration MP4GetTrackDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/** Get the time scale of a track.
+ *
+ * MP4GetTrackTimeScale returns the time scale of the specified track in
+ * the mp4 file. The time scale determines the number of clock ticks per
+ * second for this track.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ *
+ * @return timescale (ticks per second) of the track in the mp4 file.
+ */
+MP4V2_EXPORT
+uint32_t MP4GetTrackTimeScale(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/** Set the time scale of a track.
+ *
+ * MP4SetTrackTimeScale sets the time scale of the specified track in the
+ * mp4 file. The time scale determines the number of clock ticks per
+ * second for this track.
+ *
+ * Typically this value is set once when the track is created. However
+ * this call can be used to modify the value if that is desired. Since
+ * track sample durations are expressed in units of the track time scale,
+ * any change to the time scale value will effect the real time duration
+ * of the samples.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param timeScale desired time scale for the track.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4SetTrackTimeScale(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint32_t value );
+
+/** Get ISO-639-2/T language code of a track.
+ * The language code is a 3-char alpha code consisting of lower-case letters.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param code buffer to hold 3-char+null (4-bytes total).
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4GetTrackLanguage(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ char* code );
+
+/** Set ISO-639-2/T language code of a track.
+ * The language code is a 3-char alpha code consisting of lower-case letters.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ * @param code 3-char language code.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4SetTrackLanguage(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* code );
+
+/** Get track name.
+ *
+ * MP4GetTrackName gets the name of the track via udta.name property.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4GetTrackName(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ char** name );
+
+/** Set track name.
+ *
+ * MP4SetTrackName sets the name of the track via udta.name property.
+ * The udta atom is created if needed.
+ *
+ * @param hFile handle of file for operation.
+ * @param trackId id of track for operation.
+ *
+ * @return <b>true</b> on success, <b>false</b> on failure.
+ */
+MP4V2_EXPORT
+bool MP4SetTrackName(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* name );
+
+MP4V2_EXPORT
+uint8_t MP4GetTrackAudioMpeg4Type(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+uint8_t MP4GetTrackEsdsObjectTypeId(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/* returns MP4_INVALID_DURATION if track samples do not have a fixed duration */
+MP4V2_EXPORT
+MP4Duration MP4GetTrackFixedSampleDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+uint32_t MP4GetTrackBitRate(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+bool MP4GetTrackVideoMetadata(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t** ppConfig,
+ uint32_t* pConfigSize );
+
+MP4V2_EXPORT
+bool MP4GetTrackESConfiguration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t** ppConfig,
+ uint32_t* pConfigSize );
+
+MP4V2_EXPORT
+bool MP4SetTrackESConfiguration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const uint8_t* pConfig,
+ uint32_t configSize );
+
+/* h264 information routines */
+
+/** Frees the memory allocated by MP4GetTrackH264SeqPictHeaders.
+ *
+ * MP4FreeH264SeqPictHeaders frees the memory that was allocated by a
+ * call to the MP4GetTrackH264SeqPictHeaders function.
+ *
+ * When a client application wants to extract the H.264 video data from
+ * an MP4 file it will call MP4GetTrackH264SeqPictHeaders to obtain the
+ * sequence and picture parameter sets. These parameter sets are
+ * required for decoding a sequence of one, or more, coded slices. When
+ * the client application is done with the data it must free it. On the
+ * Windows platform this cannot be done directly by the client
+ * application because the C runtime of the client application and the C
+ * runtime of the mp4v2 DLL may be different, which will result in an
+ * error at runtime. This function allows the client application to let
+ * the mp4v2 DLL free the memory with the appropriate CRT heap manager.
+ *
+ * @param pSeqHeaders pointer to an array of SPS pointers.
+ * @param pSeqHeaderSize pointer to array of SPS sizes.
+ * @param pPictHeader pointer to an array of PPS pointers.
+ * @param pPictHeaderSize pointer to array of PPS sizes.
+ */
+MP4V2_EXPORT
+void MP4FreeH264SeqPictHeaders(
+ uint8_t** pSeqHeaders,
+ uint32_t* pSeqHeaderSize,
+ uint8_t** pPictHeader,
+ uint32_t* pPictHeaderSize );
+
+MP4V2_EXPORT
+bool MP4GetTrackH264ProfileLevel(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t* pProfile,
+ uint8_t* pLevel );
+
+MP4V2_EXPORT
+bool MP4GetTrackH264SeqPictHeaders(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t*** pSeqHeaders,
+ uint32_t** pSeqHeaderSize,
+ uint8_t*** pPictHeader,
+ uint32_t** pPictHeaderSize );
+
+MP4V2_EXPORT
+bool MP4GetTrackH264LengthSize(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint32_t* pLength );
+
+MP4V2_EXPORT
+MP4SampleId MP4GetTrackNumberOfSamples(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+uint16_t MP4GetTrackVideoWidth(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+uint16_t MP4GetTrackVideoHeight(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+double MP4GetTrackVideoFrameRate(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+int MP4GetTrackAudioChannels(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+MP4V2_EXPORT
+bool MP4IsIsmaCrypMediaTrack(
+ MP4FileHandle hFile,
+ MP4TrackId trackId );
+
+/* generic track properties */
+
+MP4V2_EXPORT
+bool MP4HaveTrackAtom(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* atomName );
+
+MP4V2_EXPORT
+bool MP4GetTrackIntegerProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ uint64_t* retvalue );
+
+MP4V2_EXPORT
+bool MP4GetTrackFloatProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ float* ret_value );
+
+MP4V2_EXPORT
+bool MP4GetTrackStringProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ const char** retvalue );
+
+MP4V2_EXPORT
+bool MP4GetTrackBytesProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ uint8_t** ppValue,
+ uint32_t* pValueSize );
+
+MP4V2_EXPORT
+bool MP4SetTrackIntegerProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ int64_t value );
+
+MP4V2_EXPORT
+bool MP4SetTrackFloatProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ float value );
+
+MP4V2_EXPORT
+bool MP4SetTrackStringProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ const char* value );
+
+MP4V2_EXPORT
+bool MP4SetTrackBytesProperty(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char* propName,
+ const uint8_t* pValue,
+ uint32_t valueSize);
+
+/** @} ***********************************************************************/
+
+#endif /* MP4V2_TRACK_PROP_H */
diff --git a/libplatform/config.h b/libplatform/config.h
new file mode 100644
index 0000000..e23dea0
--- /dev/null
+++ b/libplatform/config.h
@@ -0,0 +1,66 @@
+/* libplatform/config.h. Generated from config.h.in by configure. */
+/* libplatform/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if LFS should be activated */
+/* #undef NEED_LFS_ACTIVATION */
+
+/* Name of package */
+#define PACKAGE "mp4v2"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "kidjan@gmail.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "MP4v2"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "MP4v2 -r"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "mp4v2"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "-r"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "-r"
diff --git a/libplatform/config.h.in b/libplatform/config.h.in
new file mode 100644
index 0000000..47a5a04
--- /dev/null
+++ b/libplatform/config.h.in
@@ -0,0 +1,65 @@
+/* libplatform/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if LFS should be activated */
+#undef NEED_LFS_ACTIVATION
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
diff --git a/libplatform/endian.h b/libplatform/endian.h
new file mode 100644
index 0000000..83fe69e
--- /dev/null
+++ b/libplatform/endian.h
@@ -0,0 +1,42 @@
+#ifndef MP4V2_PLATFORM_ENDIAN_H
+#define MP4V2_PLATFORM_ENDIAN_H
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define MP4V2_BYTESWAP_16(x) \
+ mp4v2::platform::uint16_t( ((mp4v2::platform::uint16_t(x) & 0xff00U) >> 8) \
+ | ((mp4v2::platform::uint16_t(x) & 0x00ffU) << 8) )
+
+#define MP4V2_BYTESWAP_32(x) \
+ mp4v2::platform::uint32_t( ((mp4v2::platform::uint32_t(x) & 0xff000000U) >> 24) \
+ | ((mp4v2::platform::uint32_t(x) & 0x00ff0000U) >> 8) \
+ | ((mp4v2::platform::uint32_t(x) & 0x0000ff00U) << 8) \
+ | ((mp4v2::platform::uint32_t(x) & 0x000000ffU) << 24) )
+
+#define MP4V2_BYTESWAP_64(x) \
+ mp4v2::platform::uint64_t( ((mp4v2::platform::uint64_t(x) & 0xff00000000000000ULL) >> 56) \
+ | ((mp4v2::platform::uint64_t(x) & 0x00ff000000000000ULL) >> 40) \
+ | ((mp4v2::platform::uint64_t(x) & 0x0000ff0000000000ULL) >> 24) \
+ | ((mp4v2::platform::uint64_t(x) & 0x000000ff00000000ULL) >> 8) \
+ | ((mp4v2::platform::uint64_t(x) & 0x00000000ff000000ULL) << 8) \
+ | ((mp4v2::platform::uint64_t(x) & 0x0000000000ff0000ULL) << 24) \
+ | ((mp4v2::platform::uint64_t(x) & 0x000000000000ff00ULL) << 40) \
+ | ((mp4v2::platform::uint64_t(x) & 0x00000000000000ffULL) << 56) )
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined( __BIG_ENDIAN__ )
+# define MP4V2_HTONS(x) (x)
+# define MP4V2_HTONL(x) (x)
+# define MP4V2_NTOHS(x) (x)
+# define MP4V2_NTOHL(x) (x)
+#else
+# define MP4V2_HTONS(x) MP4V2_BYTESWAP_16(x)
+# define MP4V2_HTONL(x) MP4V2_BYTESWAP_32(x)
+# define MP4V2_NTOHS(x) MP4V2_BYTESWAP_16(x)
+# define MP4V2_NTOHL(x) MP4V2_BYTESWAP_32(x)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif // MP4V2_PLATFORM_ENDIAN_H
diff --git a/libplatform/impl.h b/libplatform/impl.h
new file mode 100644
index 0000000..6c0068c
--- /dev/null
+++ b/libplatform/impl.h
@@ -0,0 +1,13 @@
+#ifndef MP4V2_PLATFORM_IMPL_H
+#define MP4V2_PLATFORM_IMPL_H
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "libplatform/platform.h"
+#if defined _WIN32
+#include "libplatform/platform_win32_impl.h"
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#endif // MP4V2_PLATFORM_IMPL_H
diff --git a/libplatform/io/File.cpp b/libplatform/io/File.cpp
new file mode 100644
index 0000000..2ea0e8d
--- /dev/null
+++ b/libplatform/io/File.cpp
@@ -0,0 +1,201 @@
+#include "libplatform/impl.h"
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace {
+ const File::Size __maxChunkSize = 1024*1024;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+File::File( std::string name_, Mode mode_, FileProvider* provider_ )
+ : _name ( name_ )
+ , _isOpen ( false )
+ , _mode ( mode_ )
+ , _size ( 0 )
+ , _position ( 0 )
+ , _provider ( provider_ ? *provider_ : standard() )
+ , name ( _name )
+ , isOpen ( _isOpen )
+ , mode ( _mode )
+ , size ( _size )
+ , position ( _position )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+File::~File()
+{
+ close();
+ delete &_provider;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void
+File::setMode( Mode mode_ )
+{
+ _mode = mode_;
+}
+
+void
+File::setName( const std::string& name_ )
+{
+ _name = name_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+File::open( std::string name_, Mode mode_ )
+{
+ if( _isOpen )
+ return true;
+
+ if( !name_.empty() )
+ setName( name_ );
+ if( mode_ != MODE_UNDEFINED )
+ setMode( mode_ );
+
+ if( _provider.open( _name, _mode ))
+ return true;
+
+ if( _provider.getSize( _size ))
+ return true;
+
+ _isOpen = true;
+ return false;
+}
+
+bool
+File::seek( Size pos )
+{
+ if( !_isOpen )
+ return true;
+
+ if( _provider.seek( pos ))
+ return true;
+ _position = pos;
+ return false;
+}
+
+bool
+File::read( void* buffer, Size size, Size& nin, Size maxChunkSize )
+{
+ nin = 0;
+
+ if( !_isOpen )
+ return true;
+
+ if( _provider.read( buffer, size, nin, maxChunkSize ))
+ return true;
+
+ _position += nin;
+ if( _position > _size )
+ _size = _position;
+
+ return false;
+}
+
+bool
+File::write( const void* buffer, Size size, Size& nout, Size maxChunkSize )
+{
+ nout = 0;
+
+ if( !_isOpen )
+ return true;
+
+ if( _provider.write( buffer, size, nout, maxChunkSize ))
+ return true;
+
+ _position += nout;
+ if( _position > _size )
+ _size = _position;
+
+ return false;
+}
+
+bool
+File::close()
+{
+ if( !_isOpen )
+ return false;
+ if( _provider.close() )
+ return true;
+
+ _isOpen = false;
+ return false;
+}
+
+bool
+File::getSize( Size& nout )
+{
+ if( !_isOpen )
+ return false;
+
+ return _provider.getSize( nout );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+CustomFileProvider::CustomFileProvider( const MP4FileProvider& provider )
+ : _handle( NULL )
+{
+ memcpy( &_call, &provider, sizeof(MP4FileProvider) );
+}
+
+bool
+CustomFileProvider::open( std::string name, Mode mode )
+{
+ MP4FileMode fm;
+ switch( mode ) {
+ case MODE_READ: fm = FILEMODE_READ; break;
+ case MODE_MODIFY: fm = FILEMODE_MODIFY; break;
+ case MODE_CREATE: fm = FILEMODE_CREATE; break;
+
+ case MODE_UNDEFINED:
+ default:
+ fm = FILEMODE_UNDEFINED;
+ break;
+ }
+
+ _handle = _call.open( name.c_str(), fm );
+ return _handle == NULL;
+}
+
+bool
+CustomFileProvider::seek( Size pos )
+{
+ return _call.seek( _handle, pos );
+}
+
+bool
+CustomFileProvider::read( void* buffer, Size size, Size& nin, Size maxChunkSize )
+{
+ return _call.read( _handle, buffer, size, &nin, maxChunkSize );
+}
+
+bool
+CustomFileProvider::write( const void* buffer, Size size, Size& nout, Size maxChunkSize )
+{
+ return _call.write( _handle, buffer, size, &nout, maxChunkSize );
+}
+
+bool
+CustomFileProvider::close()
+{
+ return _call.close( _handle );
+}
+
+bool
+CustomFileProvider::getSize( Size& nout )
+{
+ return _call.getSize( _handle, &nout );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::platform::io
diff --git a/libplatform/io/File.h b/libplatform/io/File.h
new file mode 100644
index 0000000..bf8536c
--- /dev/null
+++ b/libplatform/io/File.h
@@ -0,0 +1,222 @@
+#ifndef MP4V2_PLATFORM_IO_FILE_H
+#define MP4V2_PLATFORM_IO_FILE_H
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class MP4V2_EXPORT FileProvider
+{
+public:
+ static FileProvider& standard();
+
+public:
+ //! file operation mode flags
+ enum Mode {
+ MODE_UNDEFINED, //!< undefined
+ MODE_READ, //!< file may be read
+ MODE_MODIFY, //!< file may be read/written
+ MODE_CREATE, //!< file will be created/truncated for read/write
+ };
+
+ //! type used to represent all file sizes and offsets
+ typedef int64_t Size;
+
+public:
+ virtual ~FileProvider() { }
+
+ virtual bool open( std::string name, Mode mode ) = 0;
+ virtual bool seek( Size pos ) = 0;
+ virtual bool read( void* buffer, Size size, Size& nin, Size maxChunkSize ) = 0;
+ virtual bool write( const void* buffer, Size size, Size& nout, Size maxChunkSize ) = 0;
+ virtual bool close() = 0;
+ virtual bool getSize( Size& nout ) = 0;
+
+protected:
+ FileProvider() { }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+///
+/// File implementation.
+///
+/// File objects model real filesystem files in a 1:1 releationship and always
+/// treated as binary; there are no translations of text content performed.
+///
+/// The interface represents all sizes with a signed 64-bit value, thus
+/// the limit to this interface is 63-bits of size, roughly 9.22 million TB.
+///
+///////////////////////////////////////////////////////////////////////////////
+
+class MP4V2_EXPORT File : public FileProvider
+{
+public:
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Constructor.
+ //!
+ //! A new file object is constructed but not opened.
+ //!
+ //! @param name filename of file object, or empty-string.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //! @param mode bitmask specifying mode flags.
+ //! See #Mode for bit constants.
+ //! @param provider a fileprovider instance. If NULL a standard file
+ //! provider will be used otherwise the supplied provider must be
+ //! new-allocated and will be delete'd via ~File().
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ explicit File( std::string name = "", Mode mode = MODE_UNDEFINED, FileProvider* = NULL );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Destructor.
+ //!
+ //! File object is destroyed. If the file is opened it is closed prior
+ //! to destruction.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ ~File();
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Open file.
+ //!
+ //! @param name filename of file object, or empty-string to use #name.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //!
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool open( std::string name = "", Mode mode = MODE_UNDEFINED );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Closes file.
+ //!
+ //! If the file has not been opened or is not considered the
+ //! owner of a filehandle, no action is taken.
+ //!
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool close();
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Set current file position in bytes.
+ //!
+ //! @param pos new file position in bytes.
+ //!
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool seek( Size pos );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Binary stream read.
+ //!
+ //! The function reads up to a maximum <b>size</b> bytes from file,
+ //! storing them in <b>buffer</b>. The number of bytes actually read are
+ //! returned in <b>nin</b>.
+ //!
+ //! @param buffer storage for data read from file.
+ //! @param size maximum number of bytes to read from file.
+ //! @param nin output indicating number of bytes read from file.
+ //! @param maxChunkSize maximum chunk size for reads issued to operating
+ //! system or 0 for default.
+ //!
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool read( void* buffer, Size size, Size& nin, Size maxChunkSize = 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Binary stream write.
+ //!
+ //! The function writes up to a maximum <b>size</b> bytes from
+ //! <b>buffer</b> to file. The number of bytes actually written are
+ //! returned in <b>nout</b>.
+ //!
+ //! @param buffer data to be written out to file.
+ //! @param size maximum number of bytes to read from file.
+ //! @param nout output indicating number of bytes written to file.
+ //! @param maxChunkSize maximum chunk size for writes issued to operating
+ //! system or 0 for default.
+ //!
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool write( const void* buffer, Size size, Size& nout, Size maxChunkSize = 0 );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Get size of file in bytes.
+ //!
+ //! @param nout output indicating the size of the file in bytes.
+ //!
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ bool getSize( Size& nout );
+
+private:
+ std::string _name;
+ bool _isOpen;
+ Mode _mode;
+ Size _size;
+ Size _position;
+ FileProvider& _provider;
+
+public:
+ const std::string& name; //!< read-only: file pathname or empty-string if not applicable
+ const bool& isOpen; //!< read-only: true if file is open
+ const Mode& mode; //!< read-only: file mode
+ const Size& size; //!< read-only: file size
+ const Size& position; //!< read-only: file position
+
+public:
+ void setName( const std::string& name );
+ void setMode( Mode mode );
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class CustomFileProvider : public FileProvider
+{
+public:
+ CustomFileProvider( const MP4FileProvider& );
+
+ bool open( std::string name, Mode mode );
+ bool seek( Size pos );
+ bool read( void* buffer, Size size, Size& nin, Size maxChunkSize );
+ bool write( const void* buffer, Size size, Size& nout, Size maxChunkSize );
+ bool close();
+ bool getSize( Size& nout );
+
+private:
+ MP4FileProvider _call;
+ void* _handle;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::platform::io
+
+#endif // MP4V2_PLATFORM_IO_FILE_H
diff --git a/libplatform/io/FileSystem.cpp b/libplatform/io/FileSystem.cpp
new file mode 100644
index 0000000..073b026
--- /dev/null
+++ b/libplatform/io/FileSystem.cpp
@@ -0,0 +1,103 @@
+#include "libplatform/impl.h"
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+
+void
+FileSystem::pathnameCleanup( string& name )
+{
+ string bad;
+
+ // fold repeating directory separators
+ bad = DIR_SEPARATOR;
+ bad += DIR_SEPARATOR;
+ for( string::size_type pos = name.find( bad );
+ pos != string::npos;
+ pos = name.find( bad, pos ) )
+ {
+ name.replace( pos, bad.length(), DIR_SEPARATOR );
+ }
+
+ // replace occurances of /./ with /
+ bad = DIR_SEPARATOR;
+ bad += '.';
+ bad += DIR_SEPARATOR;
+ for( string::size_type pos = name.find( bad );
+ pos != string::npos;
+ pos = name.find( bad, pos ) )
+ {
+ name.replace( pos, bad.length(), DIR_SEPARATOR );
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void
+FileSystem::pathnameOnlyExtension( string& name )
+{
+ // compute basename
+ string::size_type dot_pos = name.rfind( '.' );
+ string::size_type slash_pos = name.rfind( DIR_SEPARATOR );
+
+ // dot_pos must be after slash_pos
+ if( slash_pos != string::npos && dot_pos < slash_pos )
+ dot_pos = string::npos;
+
+ // return empty-string if no dot
+ if( dot_pos == string::npos ) {
+ name.resize( 0 );
+ return;
+ }
+
+ name = name.substr( dot_pos + 1 );
+ pathnameCleanup( name );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void
+FileSystem::pathnameStripExtension( string& name )
+{
+ pathnameCleanup( name );
+
+ // compute basename
+ string::size_type dot_pos = name.rfind( '.' );
+ string::size_type slash_pos = name.rfind( DIR_SEPARATOR );
+
+ // dot_pos must be after slash_pos
+ if( slash_pos != string::npos && dot_pos < slash_pos )
+ dot_pos = string::npos;
+
+ // chop extension
+ if( dot_pos != string::npos )
+ name.resize( dot_pos );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void
+FileSystem::pathnameTemp( string& name, string dir, string prefix, string suffix )
+{
+ ostringstream buf;
+
+ if( !dir.empty() ) {
+ buf << dir;
+
+ // add dir separator if needed
+ // TODO there's a platform specific bug here, if someone passes in a pathname ending
+ // in '\', which would be legitimate on Windows.
+ if( dir[dir.length()-1] != '/' )
+ buf << '/';
+ }
+
+ buf << prefix;
+ buf << setfill('0') << setw(8) << number::random32();
+ buf << suffix;
+
+ name = buf.str();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::platform::io
diff --git a/libplatform/io/FileSystem.h b/libplatform/io/FileSystem.h
new file mode 100644
index 0000000..b348752
--- /dev/null
+++ b/libplatform/io/FileSystem.h
@@ -0,0 +1,215 @@
+#ifndef MP4V2_PLATFORM_IO_FILESYSTEM_H
+#define MP4V2_PLATFORM_IO_FILESYSTEM_H
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+///
+/// General file-system abstraction.
+///
+/// FileSystem abstracts operations on files and directories.
+///
+///////////////////////////////////////////////////////////////////////////////
+class MP4V2_EXPORT FileSystem
+{
+public:
+ static string DIR_SEPARATOR; //!< separator string used in file pathnames
+ static string PATH_SEPARATOR; //!< separator string used in search-paths
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Query file presence.
+ //! Check if <b>name</b> exists.
+ //! @param name filename to query.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //! @return true if present, false otherwise.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static bool exists( std::string name );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Query directory type.
+ //! Check if <b>name</b> exists and is a directory.
+ //! @param name pathname to query.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //! @return true if directory, false otherwise.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static bool isDirectory( std::string name );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Query file type.
+ //! Check if <b>name</b> exists and is a file.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //! @param name filename to query.
+ //! @return true if file, false otherwise.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static bool isFile( std::string name );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Query file size.
+ //! Check if <b>name</b> exists and is a file.
+ //! @param name filename to query.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //! @param size output indicating file size in bytes.
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static bool getFileSize( std::string name, File::Size& size );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Rename file or directory.
+ //!
+ //! Rename <b>oldname</b> to <b>newname</b>.
+ //! If <b>newname</b> exists, it is first removed.
+ //! Both <b>oldname</b> and <b>newname</b> must be of the same type;
+ //! that is, both must be either files or directories and must reside on
+ //! the same filesystem.
+ //!
+ //! @param oldname existing pathname to rename.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //! @param newname new pathname.
+ //! On Windows, this should be a UTF-8 encoded string.
+ //! On other platforms, it should be an 8-bit encoding that is
+ //! appropriate for the platform, locale, file system, etc.
+ //! (prefer to use UTF-8 when possible).
+ //!
+ //! @return true on failure, false on success.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static bool rename( std::string oldname, std::string newname );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Generate temporary pathname.
+ //!
+ //! @param name output containing generated pathname.
+ //! @param dir relative or absolute directory of pathname.
+ //! @param prefix text prepended to base pathname.
+ //! @param suffix text appended to base pathname.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static void pathnameTemp( string& name, string dir = ".", string prefix = "tmp", string suffix = "" );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Cleanup pathname.
+ //!
+ //! Redundant (repeating) directory-separators are folded into a single
+ //! directory-separator.
+ //!
+ //! Redundant /./ are folded into a single directory-separator.
+ //!
+ //! @param name pathname to modify.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static void pathnameCleanup( string& name );
+
+#if 0
+TODO-KB: implement
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Remove everything after the last directory component.
+ //!
+ //! A pathname cleanup is always performed. See pathnameCleanup().
+ //! If no directory component is present then "." is assumed.
+ //!
+ //! @param name pathname to modify.
+ //! @param trailing when true all results are suffixed with exactly one
+ //! directory-separator, otherwise the result is guaranteed to not
+ //! end in a directory-separator.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+ static void pathnameOnlyDirectory( string& name, bool trailing = true );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Remove everything except the file component of pathname.
+ //!
+ //! A pathname cleanup is always performed. See pathnameCleanup().
+ //! If no file component exists then an empty-string is output.
+ //! A file component may include an extension.
+ //!
+ //! @param name pathname to modify.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+ static void pathnameOnlyFile( string& name );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Remove everything except file basename.
+ //!
+ //! A pathname cleanup is always performed. See pathnameCleanup().
+ //! A basename is considered to be everything before the last '.'
+ //! in the file component of a pathname.
+ //! If no file extension exists then an empty-string is output.
+ //!
+ //! @param name pathname to modify.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+ static void pathnameOnlyBasename( string& name );
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Remove everything except file extension.
+ //!
+ //! A pathname cleanup is always performed. See pathnameCleanup().
+ //! A file extension is considered to everything <b>after</b>
+ //! the last '.' in the file component of a pathname.
+ //! If no file extension exists then an empty-string is output.
+ //!
+ //! @param name pathname to modify.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static void pathnameOnlyExtension( string& name );
+
+ ///////////////////////////////////////////////////////////////////////////
+ //!
+ //! Remove file extension from pathname.
+ //!
+ //! A pathname cleanup is always performed. See pathnameCleanup().
+ //! A file extension is considered to everything <b>after</b>
+ //! the last '.' in the file component of a pathname.
+ //! The last '.' is also removed.
+ //!
+ //! @param name pathname to modify.
+ //!
+ ///////////////////////////////////////////////////////////////////////////
+
+ static void pathnameStripExtension( string& name );
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::platform::io
+
+#endif // MP4V2_PLATFORM_IO_FILESYSTEM_H
diff --git a/libplatform/io/FileSystem_posix.cpp b/libplatform/io/FileSystem_posix.cpp
new file mode 100644
index 0000000..46cf933
--- /dev/null
+++ b/libplatform/io/FileSystem_posix.cpp
@@ -0,0 +1,65 @@
+#include "libplatform/impl.h"
+#include <sys/stat.h>
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::exists( string path_ )
+{
+ struct stat buf;
+ return stat( path_.c_str(), &buf ) == 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::isDirectory( string path_ )
+{
+ struct stat buf;
+ if( stat( path_.c_str(), &buf ))
+ return false;
+ return S_ISDIR( buf.st_mode );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::isFile( string path_ )
+{
+ struct stat buf;
+ if( stat( path_.c_str(), &buf ))
+ return false;
+ return S_ISREG( buf.st_mode );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::getFileSize( string path_, File::Size& size_ )
+{
+ size_ = 0;
+ struct stat buf;
+ if( stat( path_.c_str(), &buf ))
+ return true;
+ size_ = buf.st_size;
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::rename( string from, string to )
+{
+ return ::rename( from.c_str(), to.c_str() ) != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+string FileSystem::DIR_SEPARATOR = "/";
+string FileSystem::PATH_SEPARATOR = ":";
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::platform::io
diff --git a/libplatform/io/FileSystem_win32.cpp b/libplatform/io/FileSystem_win32.cpp
new file mode 100644
index 0000000..4a21381
--- /dev/null
+++ b/libplatform/io/FileSystem_win32.cpp
@@ -0,0 +1,146 @@
+#include "src/impl.h"
+#include "libplatform/impl.h" /* for platform_win32_impl.h which declares Utf8ToFilename */
+#include <windows.h>
+
+namespace mp4v2 {
+ using namespace impl;
+}
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+
+static DWORD getAttributes ( string path_ );
+
+/**
+ * Call GetFileAttributesW throw exceptions for errors
+ *
+ * @param path_ the path to get attributes for
+ *
+ * @retval INVALID_FILE_ATTRIBUTES @p path_ doesn't exist
+ * @retval anything else the attributes of @p path_
+ */
+static DWORD
+getAttributes ( string path_ )
+{
+ win32::Utf8ToFilename filename(path_);
+
+ if (!filename.IsUTF16Valid())
+ {
+ // throw an exception to avoid changing the
+ // signature of this function and dealing with all
+ // the places it's called.
+ ostringstream msg;
+ msg << "can't convert file to UTF-16(" << filename.utf8 << ")";
+ throw new Exception(msg.str(),__FILE__,__LINE__,__FUNCTION__);
+ }
+
+ DWORD attributes = ::GetFileAttributesW(filename);
+ if( attributes == INVALID_FILE_ATTRIBUTES )
+ {
+ DWORD last_err = GetLastError();
+
+ // Distinguish between an error and the path not existing
+ if ((last_err == ERROR_FILE_NOT_FOUND) || (last_err == ERROR_PATH_NOT_FOUND))
+ {
+ return attributes;
+ }
+
+ // Anything else is an error
+ ostringstream msg;
+ msg << "GetFileAttributes(" << filename.utf8 << ") failed (" << last_err << ")";
+ throw new Exception(msg.str(),__FILE__,__LINE__,__FUNCTION__);
+ }
+
+ // path exists so return its attributes
+ return attributes;
+}
+
+bool
+FileSystem::exists( string path_ )
+{
+ return( getAttributes(path_) != INVALID_FILE_ATTRIBUTES );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::isDirectory( string path_ )
+{
+ DWORD attributes = getAttributes( path_ );
+ if( attributes == INVALID_FILE_ATTRIBUTES )
+ return false;
+
+ return ( ( attributes & FILE_ATTRIBUTE_DIRECTORY ) == FILE_ATTRIBUTE_DIRECTORY );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::isFile( string path_ )
+{
+ DWORD attributes = getAttributes( path_ );
+ if( attributes == INVALID_FILE_ATTRIBUTES )
+ return false;
+
+ return ( ( attributes & FILE_ATTRIBUTE_DIRECTORY ) != FILE_ATTRIBUTE_DIRECTORY );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::getFileSize( string path_, File::Size& size_ )
+{
+ win32::Utf8ToFilename filename(path_);
+
+ if (!filename.IsUTF16Valid())
+ {
+ // The logging is done
+ return true;
+ }
+
+ size_ = 0;
+ WIN32_FILE_ATTRIBUTE_DATA data = {0};
+ if( !GetFileAttributesExW( filename, GetFileExInfoStandard, (LPVOID)&data ) )
+ {
+ log.errorf("%s: GetFileAttributesExW(%s) failed (%d)",__FUNCTION__,filename.utf8.c_str(),
+ GetLastError());
+ return true;
+ }
+
+ size_ = ( (File::Size)data.nFileSizeHigh << 32 ) | data.nFileSizeLow;
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+FileSystem::rename( string from, string to )
+{
+ win32::Utf8ToFilename from_file(from);
+ win32::Utf8ToFilename to_file(to);
+
+ if (!from_file.IsUTF16Valid() || !to_file.IsUTF16Valid())
+ {
+ return true;
+ }
+
+ if (!::MoveFileExW( from_file, to_file,
+ MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH ) )
+ {
+ log.errorf("%s: MoveFileExW(%s,%s) failed (%d)",__FUNCTION__,from_file.utf8.c_str(),to_file.utf8.c_str(),
+ GetLastError());
+ return true;
+ }
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+string FileSystem::DIR_SEPARATOR = "\\";
+string FileSystem::PATH_SEPARATOR = ";";
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::platform::io
diff --git a/libplatform/io/File_posix.cpp b/libplatform/io/File_posix.cpp
new file mode 100644
index 0000000..1c961ab
--- /dev/null
+++ b/libplatform/io/File_posix.cpp
@@ -0,0 +1,123 @@
+#include "libplatform/impl.h"
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class StandardFileProvider : public FileProvider
+{
+public:
+ StandardFileProvider();
+
+ bool open( std::string name, Mode mode );
+ bool seek( Size pos );
+ bool read( void* buffer, Size size, Size& nin, Size maxChunkSize );
+ bool write( const void* buffer, Size size, Size& nout, Size maxChunkSize );
+ bool close();
+ bool getSize( Size& nout );
+
+private:
+ bool _seekg;
+ bool _seekp;
+ std::fstream _fstream;
+ std::string _name;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+StandardFileProvider::StandardFileProvider()
+ : _seekg ( false )
+ , _seekp ( false )
+{
+}
+
+bool
+StandardFileProvider::open( std::string name, Mode mode )
+{
+ ios::openmode om = ios::binary;
+ switch( mode ) {
+ case MODE_UNDEFINED:
+ case MODE_READ:
+ default:
+ om |= ios::in;
+ _seekg = true;
+ _seekp = false;
+ break;
+
+ case MODE_MODIFY:
+ om |= ios::in | ios::out;
+ _seekg = true;
+ _seekp = true;
+ break;
+
+ case MODE_CREATE:
+ om |= ios::in | ios::out | ios::trunc;
+ _seekg = true;
+ _seekp = true;
+ break;
+ }
+
+ _fstream.open( name.c_str(), om );
+ _name = name;
+ return _fstream.fail();
+}
+
+bool
+StandardFileProvider::seek( Size pos )
+{
+ if( _seekg )
+ _fstream.seekg( pos, ios::beg );
+ if( _seekp )
+ _fstream.seekp( pos, ios::beg );
+ return _fstream.fail();
+}
+
+bool
+StandardFileProvider::read( void* buffer, Size size, Size& nin, Size maxChunkSize )
+{
+ _fstream.read( (char*)buffer, size );
+ if( _fstream.fail() )
+ return true;
+ nin = _fstream.gcount();
+ return false;
+}
+
+bool
+StandardFileProvider::write( const void* buffer, Size size, Size& nout, Size maxChunkSize )
+{
+ _fstream.write( (const char*)buffer, size );
+ if( _fstream.fail() )
+ return true;
+ nout = size;
+ return false;
+}
+
+bool
+StandardFileProvider::close()
+{
+ _fstream.close();
+ return _fstream.fail();
+}
+
+bool
+StandardFileProvider::getSize( Size& nout )
+{
+ bool retval;
+
+ // getFileSize will log if it fails
+ retval = FileSystem::getFileSize( _name, nout );
+
+ return retval;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+FileProvider&
+FileProvider::standard()
+{
+ return *new StandardFileProvider();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::platform::io
diff --git a/libplatform/io/File_win32.cpp b/libplatform/io/File_win32.cpp
new file mode 100644
index 0000000..0b3ebe8
--- /dev/null
+++ b/libplatform/io/File_win32.cpp
@@ -0,0 +1,287 @@
+#include "src/impl.h"
+#include "libplatform/impl.h" /* for platform_win32_impl.h which declares Utf8ToFilename */
+#include <windows.h>
+
+namespace mp4v2 {
+ using namespace impl;
+}
+
+/**
+ * Set this to 1 to compile in extra debugging
+ */
+#define EXTRA_DEBUG 0
+
+/**
+ * @def LOG_PRINTF
+ *
+ * call log.printf if EXTRA_DEBUG is defined to 1. Do
+ * nothing otherwise
+ */
+#if EXTRA_DEBUG
+#define LOG_PRINTF(X) log.printf X
+#else
+#define LOG_PRINTF(X)
+#endif
+
+namespace mp4v2 { namespace platform { namespace io {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class StandardFileProvider : public FileProvider
+{
+public:
+ StandardFileProvider();
+
+ bool open( std::string name, Mode mode );
+ bool seek( Size pos );
+ bool read( void* buffer, Size size, Size& nin, Size maxChunkSize );
+ bool write( const void* buffer, Size size, Size& nout, Size maxChunkSize );
+ bool close();
+ bool getSize( Size& nout );
+
+private:
+ HANDLE _handle;
+
+ /**
+ * The UTF-8 encoded file name
+ */
+ std::string _name;
+
+ /**
+ * Argument for FileSystem::getFileSize()
+ */
+ std::string _orig_name;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+StandardFileProvider::StandardFileProvider()
+ : _handle( INVALID_HANDLE_VALUE )
+{
+}
+
+/**
+ * Open a file
+ *
+ * @param name the name of a file to open
+ * @param mode the mode to open @p name
+ *
+ * @retval false successfully opened @p name
+ * @retval true error opening @p name
+ */
+bool
+StandardFileProvider::open( std::string name, Mode mode )
+{
+ _orig_name = name;
+
+ DWORD access = 0;
+ DWORD share = 0;
+ DWORD crdisp = 0;
+ DWORD flags = FILE_ATTRIBUTE_NORMAL;
+
+ switch( mode ) {
+ case MODE_UNDEFINED:
+ case MODE_READ:
+ default:
+ access |= GENERIC_READ;
+ share |= FILE_SHARE_READ;
+ crdisp |= OPEN_EXISTING;
+ break;
+
+ case MODE_MODIFY:
+ access |= GENERIC_READ | GENERIC_WRITE;
+ share |= FILE_SHARE_READ;
+ crdisp |= OPEN_EXISTING;
+ break;
+
+ case MODE_CREATE:
+ access |= GENERIC_READ | GENERIC_WRITE;
+ share |= FILE_SHARE_READ;
+ crdisp |= CREATE_ALWAYS;
+ break;
+ }
+
+ win32::Utf8ToFilename filename(name);
+
+ if (!filename.IsUTF16Valid())
+ {
+ // The logging is done
+ return true;
+ }
+
+ ASSERT(LPCWSTR(filename));
+ _handle = CreateFileW( filename, access, share, NULL, crdisp, flags, NULL );
+ if (_handle == INVALID_HANDLE_VALUE)
+ {
+ log.errorf("%s: CreateFileW(%s) failed (%d)",__FUNCTION__,filename.utf8.c_str(),GetLastError());
+ return true;
+ }
+
+ /*
+ ** Make a copy of the name for future log messages, etc.
+ */
+ log.verbose2f("%s: CreateFileW(%s) succeeded",__FUNCTION__,filename.utf8.c_str());
+
+ _name = filename.utf8;
+ return false;
+}
+
+/**
+ * Seek to an offset in the file
+ *
+ * @param pos the offset from the beginning of the file to
+ * seek to
+ *
+ * @retval false successfully seeked to @p pos
+ * @retval true error seeking to @p pos
+ */
+bool
+StandardFileProvider::seek( Size pos )
+{
+ LARGE_INTEGER n;
+
+ ASSERT(_handle != INVALID_HANDLE_VALUE);
+
+ n.QuadPart = pos;
+ if (!SetFilePointerEx( _handle, n, NULL, FILE_BEGIN ))
+ {
+ log.errorf("%s: SetFilePointerEx(%s,%" PRId64 ") failed (%d)",__FUNCTION__,_name.c_str(),
+ pos,GetLastError());
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Read from the file
+ *
+ * @param buffer populated with at most @p size bytes from
+ * the file
+ *
+ * @param size the maximum number of bytes to read
+ *
+ * @param nin the
+ *
+ * @retval false successfully read from the file
+ * @retval true error reading from the file
+ */
+bool
+StandardFileProvider::read( void* buffer, Size size, Size& nin, Size maxChunkSize )
+{
+ DWORD nread = 0;
+
+ ASSERT(_handle != INVALID_HANDLE_VALUE);
+
+ // ReadFile takes a DWORD for number of bytes to read so
+ // make sure we're not asking for more than fits.
+ // MAXDWORD from WinNT.h.
+ ASSERT(size <= MAXDWORD);
+ if( ReadFile( _handle, buffer, (DWORD)(size & MAXDWORD), &nread, NULL ) == 0 )
+ {
+ log.errorf("%s: ReadFile(%s,%d) failed (%d)",__FUNCTION__,_name.c_str(),
+ (DWORD)(size & MAXDWORD),GetLastError());
+ return true;
+ }
+ LOG_PRINTF((MP4_LOG_VERBOSE3,"%s: ReadFile(%s,%d) succeeded: read %d byte(s)",__FUNCTION__,
+ _name.c_str(),(DWORD)(size & MAXDWORD),nread));
+ nin = nread;
+ return false;
+}
+
+/**
+ * Write to the file
+ *
+ * @param buffer the data to write
+ *
+ * @param size the number of bytes of @p buffer to write
+ *
+ * @param nout populated with the number of bytes actually
+ * written if the function succeeds
+ *
+ * @retval false successfully wrote to the file
+ * @retval true error writing to the file
+ */
+bool
+StandardFileProvider::write( const void* buffer, Size size, Size& nout, Size maxChunkSize )
+{
+ DWORD nwrote = 0;
+
+ ASSERT(_handle != INVALID_HANDLE_VALUE);
+
+ // ReadFile takes a DWORD for number of bytes to read so
+ // make sure we're not asking for more than fits.
+ // MAXDWORD from WinNT.h.
+ ASSERT(size <= MAXDWORD);
+ if( WriteFile( _handle, buffer, (DWORD)(size & MAXDWORD), &nwrote, NULL ) == 0 )
+ {
+ log.errorf("%s: WriteFile(%s,%d) failed (%d)",__FUNCTION__,_name.c_str(),
+ (DWORD)(size & MAXDWORD),GetLastError());
+ return true;
+ }
+ log.verbose2f("%s: WriteFile(%s,%d) succeeded: wrote %d byte(s)",__FUNCTION__,
+ _name.c_str(),(DWORD)(size & MAXDWORD),nwrote);
+ nout = nwrote;
+ return false;
+}
+
+/**
+ * Close the file
+ *
+ * @retval false successfully closed the file
+ * @retval true error closing the file
+ */
+bool
+StandardFileProvider::close()
+{
+ BOOL retval;
+
+ retval = CloseHandle( _handle );
+ if (!retval)
+ {
+ log.errorf("%s: CloseHandle(%s) failed (%d)",__FUNCTION__,
+ _name.c_str(),GetLastError());
+ }
+
+ // Whether we succeeded or not, clear the handle and
+ // forget the name
+ _handle = INVALID_HANDLE_VALUE;
+ _name.clear();
+
+ // CloseHandle return 0/false to indicate failure, but
+ // we return 0/false to indicate success, so negate.
+ return !retval;
+}
+
+/**
+ * Get the size of a the file