shithub: aacenc

Download patch

ref: 4aed7fa3dc77418e63ed96884382dacf4e48b473
parent: 40cf917f072def9bd123f721be73bc8e52b2e97f
author: menno <menno>
date: Sat Jan 24 20:14:34 EST 2009

Updated to newest mpeg4ip library
Removed VS6 projects

--- a/common/mp4v2/3gp.cpp
+++ b/common/mp4v2/3gp.cpp
@@ -41,19 +41,6 @@
 		}
 	}
 
-	m_fileName = MP4Stralloc(fileName);
-	m_mode = 'r';
-	// first load meta-info into memory
-	Open("rb");
-	ReadFromFile();
-
-	CacheProperties();	// of moov atom
-
-	// now switch over to writing the new file
-	MP4Free(m_fileName);
-	// create a temporary file 
-	m_fileName = MP4Stralloc(TempFileName());
-
 	MakeFtypAtom(
 			majorBrand ? majorBrand : (char*)brand,
 			majorBrand ? minorVersion  : _3GP_MINOR_VERSION,
@@ -71,32 +58,6 @@
 		}
 	}
 
-
-	FILE* pReadFile = m_pFile;
-	m_pFile = NULL;
-	m_mode = 'w';
-
-	Open("wb");
-
-	SetIntegerProperty("moov.mvhd.modificationTime", 
-		MP4GetAbsTimestamp());
-
-	// writing meta info in the optimal order
-	((MP4RootAtom*)m_pRootAtom)->BeginOptimalWrite();
-
-	// write data in optimal order
-	RewriteMdat(pReadFile, m_pFile);
-
-	// finish writing
-	((MP4RootAtom*)m_pRootAtom)->FinishOptimalWrite();
-
-	// cleanup
-	fclose(m_pFile);
-	m_pFile = NULL;
-	fclose(pReadFile);
-
-	// move temporary file into place
-	Rename(m_fileName, fileName);
 }
 
 void MP4File::MakeFtypAtom(char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount)
@@ -103,43 +64,43 @@
 {
 	bool rewriteNeeded = false;
 	u_int32_t currentSupportedBrandsCount;
-	u_int64_t currentSize;
 	u_int32_t i;
 
 		
-
-		
 	MP4Atom* ftypAtom = m_pRootAtom->FindAtom("ftyp");
-	ASSERT(ftypAtom);
-
-	currentSize = ftypAtom->GetSize();
-
+	if (ftypAtom == NULL) {
+	  ftypAtom = InsertChildAtom(m_pRootAtom, "ftyp", 0);
+	}
+	if (majorBrand == NULL)
+	  return;
 	MP4StringProperty* pMajorBrandProperty;
-	ftypAtom->FindProperty(
-		"ftyp.majorBrand",
-		(MP4Property**)&pMajorBrandProperty);
+	if (!ftypAtom->FindProperty(
+				   "ftyp.majorBrand",
+				   (MP4Property**)&pMajorBrandProperty))
+	  return;
 
 	pMajorBrandProperty->SetValue(majorBrand);
 
 
 	MP4Integer32Property* pMinorVersionProperty;
-	ftypAtom->FindProperty(
-		"ftype.minorVersion",
-		(MP4Property**)&pMinorVersionProperty);
+	if (!ftypAtom->FindProperty(
+				   "ftype.minorVersion",
+				   (MP4Property**)&pMinorVersionProperty))
+	  return;
 
 	pMinorVersionProperty->SetValue(minorVersion);
 
 	MP4Integer32Property* pCompatibleBrandsCountProperty;
-	ftypAtom->FindProperty(
+	if (!ftypAtom->FindProperty(
 		"ftyp.compatibleBrandsCount",
-		(MP4Property**)&pCompatibleBrandsCountProperty);
+		(MP4Property**)&pCompatibleBrandsCountProperty)) return;
 
 	currentSupportedBrandsCount = pCompatibleBrandsCountProperty->GetValue();
 
 	MP4TableProperty* pCompatibleBrandsProperty;
-	ftypAtom->FindProperty(
+	if (!ftypAtom->FindProperty(
 		"ftyp.compatibleBrands",
-		(MP4Property**)&pCompatibleBrandsProperty);
+		(MP4Property**)&pCompatibleBrandsProperty)) return;
 
 	MP4StringProperty* pBrandProperty = (MP4StringProperty*)
 		pCompatibleBrandsProperty->GetProperty(0);
--- a/common/mp4v2/INTERNALS
+++ b/common/mp4v2/INTERNALS
@@ -50,13 +50,18 @@
 any combination of properties, other atoms, or descriptors.
 
 The mp4atom files contain the base class for all the atoms, and provide 
-generic functions that cover most cases. However, each atom has it's own 
-subclass contained in file atom_<name>.cpp, where <name> is the four 
-letter name of the atom defined in the MP4 specification. Typically this 
-atom file just specifies the properties of the atom or the possible child 
-atoms in the case of a container atom. In more specialized cases the atom 
-specific file provides routines to initialize, read, or write the atom.
+generic functions that cover most cases. Most atoms are covered in
+atom_standard.cpp.  Atoms that have a special read, generation or
+write needs are contained in their subclass contained in file atom_<name>.cpp,
+ where <name> is the four letter name of the atom defined in the MP4 
+specification. 
 
+Atoms that only specifies the properties of the atom or the possible child 
+atoms in the case of a container atom are located in atom_standard.cpp.
+
+In more specialized cases the atom specific file provides routines to 
+initialize, read, or write the atom.
+
 Properties are the atomic pieces of information. The basic types of 
 properties are integers, floats, strings, and byte arrays. For integers 
 and floats there are subclasses that represent the different storage sizes,
@@ -102,6 +107,15 @@
 
 Note that internally when performance matters the code looks up a property
 by name once, and then stores the returned pointer to the property class.
+
+To add an atom, first you should see if an existing atom exists that
+can be used.  If not, you need to decide if special read/write or
+generate properties need to be established; for example a property in the atom
+changes other properties (adds, or subtracts).  If there are no
+special cases, add the atom properties to atom_standard.cpp.  If there
+are special properties, add a new file, add a new class to atoms.h, and
+add the class to  MP4Atom::CreateAtom in mp4atom.cpp.
+
 
 
 Generic Tracks
--- a/common/mp4v2/Makefile.am
+++ b/common/mp4v2/Makefile.am
@@ -8,89 +8,52 @@
 
 libmp4v2_a_SOURCES = \
 	3gp.cpp \
-	atom_bitr.cpp \
-	atom_co64.cpp \
-	atom_cprt.cpp \
-	atom_ctts.cpp \
+	atom_amr.cpp \
+	atom_avc1.cpp \
+	atom_avcC.cpp \
 	atom_d263.cpp \
 	atom_damr.cpp \
-	atom_dimm.cpp \
-	atom_dinf.cpp \
-	atom_dmax.cpp \
-	atom_dmed.cpp \
 	atom_dref.cpp \
-	atom_drep.cpp \
-	atom_edts.cpp \
 	atom_elst.cpp \
 	atom_enca.cpp \
 	atom_encv.cpp \
-	atom_esds.cpp \
 	atom_free.cpp \
-	atom_frma.cpp \
 	atom_ftyp.cpp \
+	atom_gmin.cpp \
 	atom_hdlr.cpp \
 	atom_hinf.cpp \
-	atom_hmhd.cpp \
 	atom_hnti.cpp \
-	atom_iods.cpp \
-	atom_iKMS.cpp \
-	atom_iSFM.cpp \
-	atom_maxr.cpp \
+	atom_href.cpp \
 	atom_mdat.cpp \
 	atom_mdhd.cpp \
-	atom_mdia.cpp \
 	atom_meta.cpp \
-	atom_mfhd.cpp \
-	atom_minf.cpp \
-	atom_moof.cpp \
-	atom_moov.cpp \
-	atom_mp4a.cpp \
 	atom_mp4s.cpp \
 	atom_mp4v.cpp \
-	atom_mvex.cpp \
 	atom_mvhd.cpp \
-	atom_nmhd.cpp \
-	atom_nump.cpp \
-	atom_payt.cpp \
-	atom_pmax.cpp \
+	atom_ohdr.cpp \
 	atom_root.cpp \
 	atom_rtp.cpp \
 	atom_s263.cpp \
-	atom_samr.cpp \
-	atom_sawb.cpp \
-	atom_schi.cpp \
-	atom_schm.cpp \
 	atom_sdp.cpp \
 	atoms.h \
-	atom_sinf.cpp \
-	atom_smhd.cpp \
-	atom_snro.cpp \
+	atom_smi.cpp \
+	atom_sound.cpp \
+	atom_standard.cpp \
 	atom_stbl.cpp \
-	atom_stco.cpp \
 	atom_stdp.cpp \
 	atom_stsc.cpp \
 	atom_stsd.cpp \
-	atom_stsh.cpp \
-	atom_stss.cpp \
 	atom_stsz.cpp \
-	atom_stts.cpp \
+	atom_stz2.cpp \
+	atom_text.cpp \
 	atom_tfhd.cpp \
-	atom_tims.cpp \
 	atom_tkhd.cpp \
-	atom_tmax.cpp \
-	atom_tmin.cpp \
-	atom_tpyl.cpp \
-	atom_traf.cpp \
-	atom_trak.cpp \
-	atom_tref.cpp \
 	atom_treftype.cpp \
-	atom_trex.cpp \
-	atom_trpy.cpp \
 	atom_trun.cpp \
-	atom_tsro.cpp \
 	atom_udta.cpp \
 	atom_url.cpp \
 	atom_urn.cpp \
+	atom_video.cpp \
 	atom_vmhd.cpp \
 	descriptors.cpp \
 	descriptors.h \
@@ -122,7 +85,9 @@
 	qosqualifiers.cpp \
 	qosqualifiers.h \
 	rtphint.cpp \
-	rtphint.h 
+	rtphint.h \
+	virtual_io.cpp \
+	virtual_io.h
 
 EXTRA_DIST = API_CHANGES \
 	INTERNALS \
--- a/common/mp4v2/README
+++ b/common/mp4v2/README
@@ -17,14 +17,12 @@
 The test and util subdirectories contain some simple programs that use 
 this library.
 
+Once make install is run, to use this library, you should:
 To use this library in your application, it should be sufficient to:
 
-1) add mpeg4ip/include and mpeg4ip/lib/mp4v2 to your INCLUDE path,
-	e.g. gcc -Impeg4ip/include -Impeg4ip/lib/mp4v2 ...
+1) add the installed library to your final link:
+	e.g. gcc ... -o foo foo.cpp -lmp4v2
 
-2) add mpeg4ip/lib/mp4v2/libmp4v2.la (or /usr/local/lib/libmp4v2.la)
-	e.g. gcc ... -o foo foo.cpp mpeg4ip/lib/mp4v2/libmp4v2.a
-
-3) include mp4.h into your code,
+2) include mp4.h into your code,
 	e.g. #include <mp4.h>
 
--- /dev/null
+++ b/common/mp4v2/atom_amr.cpp
@@ -1,0 +1,65 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
+ *
+ * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
+ * and was contributed by Ximpo Group Ltd.
+ *
+ * Portions created by Ximpo Group Ltd. are
+ * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved.
+ *
+ * Contributor(s):
+ *              Ximpo Group Ltd.          [email protected]
+ */
+
+#include "mp4common.h"
+
+MP4AmrAtom::MP4AmrAtom(const char *type) 
+	: MP4Atom(type) 
+{
+	AddReserved("reserved1", 6); /* 0 */
+
+	AddProperty( /* 1 */
+		new MP4Integer16Property("dataReferenceIndex"));
+
+	AddReserved("reserved2", 16); /* 2 */
+
+	AddProperty( /* 3 */
+		new MP4Integer16Property("timeScale"));
+
+	AddReserved("reserved3", 2); /* 4 */
+
+	ExpectChildAtom("damr", Required, OnlyOne);
+}
+
+void MP4AmrAtom::Generate()
+{
+	MP4Atom::Generate();
+
+	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+	// property reserved2 has non-zero fixed values
+	static u_int8_t reserved2[16] = {
+		0x00, 0x00, 0x00, 0x00, 
+		0x00, 0x00, 0x00, 0x00, 
+		0x00, 0x02, 0x00, 0x10,
+		0x00, 0x00, 0x00, 0x00, 
+	};
+	m_pProperties[2]->SetReadOnly(false);
+	((MP4BytesProperty*)m_pProperties[2])->
+		SetValue(reserved2, sizeof(reserved2));
+	m_pProperties[2]->SetReadOnly(true);
+}
--- /dev/null
+++ b/common/mp4v2/atom_avc1.cpp
@@ -1,0 +1,81 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2004.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Bill May [email protected]
+ */
+
+#include "mp4common.h"
+
+MP4Avc1Atom::MP4Avc1Atom() 
+	: MP4Atom("avc1")
+{
+	AddReserved("reserved1", 6); /* 0 */
+
+	AddProperty( /* 1 */
+		new MP4Integer16Property("dataReferenceIndex"));
+
+	AddReserved("reserved2", 16); /* 2 */
+
+	AddProperty( /* 3 */
+		new MP4Integer16Property("width"));
+	AddProperty( /* 4 */
+		new MP4Integer16Property("height"));
+
+	AddReserved("reserved3", 14); /* 5 */
+
+	MP4StringProperty* pProp = 
+		new MP4StringProperty("compressorName");
+	pProp->SetFixedLength(32);
+	pProp->SetValue("AVC Coding");
+	AddProperty(pProp); /* 6 */
+
+	AddReserved("reserved4", 4); /* 7 */
+
+	ExpectChildAtom("avcC", Required, OnlyOne);
+	ExpectChildAtom("btrt", Optional, OnlyOne);
+	// for now ExpectChildAtom("m4ds", Optional, OnlyOne);
+}
+
+void MP4Avc1Atom::Generate()
+{
+	MP4Atom::Generate();
+
+	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+	// property reserved3 has non-zero fixed values
+	static u_int8_t reserved3[14] = {
+		0x00, 0x48, 0x00, 0x00, 
+		0x00, 0x48, 0x00, 0x00, 
+		0x00, 0x00, 0x00, 0x00, 
+		0x00, 0x01,
+	};
+	m_pProperties[5]->SetReadOnly(false);
+	((MP4BytesProperty*)m_pProperties[5])->
+		SetValue(reserved3, sizeof(reserved3));
+	m_pProperties[5]->SetReadOnly(true);
+
+	// property reserved4 has non-zero fixed values
+	static u_int8_t reserved4[4] = {
+		0x00, 0x18, 0xFF, 0xFF, 
+	};
+	m_pProperties[7]->SetReadOnly(false);
+	((MP4BytesProperty*)m_pProperties[7])->
+		SetValue(reserved4, sizeof(reserved4));
+	m_pProperties[7]->SetReadOnly(true);
+}
+
--- /dev/null
+++ b/common/mp4v2/atom_avcC.cpp
@@ -1,0 +1,261 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2004.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Bill May [email protected]
+ */
+
+#include "mp4common.h"
+
+/*
+ * SizeTableProperty is a special version of the MP4TableProperty - 
+ * the BytesProperty will need to set the value before it can read
+ * from the file
+ */
+class SizeTableProperty : public MP4TableProperty 
+{
+ public:
+  SizeTableProperty(char *name, MP4IntegerProperty *pCountProperty) :
+    MP4TableProperty(name, pCountProperty) {};
+ protected:
+  void ReadEntry(MP4File *pFile, u_int32_t index) {
+    // Each table has a size, followed by the length field
+    // first, read the length
+    m_pProperties[0]->Read(pFile, index);
+    MP4IntegerProperty *pIntProp = (MP4IntegerProperty *)m_pProperties[0];
+    // set the size in the bytes property
+    MP4BytesProperty *pBytesProp = (MP4BytesProperty *)m_pProperties[1];
+    pBytesProp->SetValueSize(pIntProp->GetValue(index), index);
+    // And read the bytes
+    m_pProperties[1]->Read(pFile, index);
+  };
+};
+
+MP4AvcCAtom::MP4AvcCAtom() 
+	: MP4Atom("avcC")
+{
+  MP4BitfieldProperty *pCount;
+  MP4TableProperty *pTable;
+
+  AddProperty( new MP4Integer8Property("configurationVersion")); /* 0 */
+
+  AddProperty( new MP4Integer8Property("AVCProfileIndication")); /* 1 */
+
+  AddProperty( new MP4Integer8Property("profile_compatibility")); /* 2 */
+
+  AddProperty( new MP4Integer8Property("AVCLevelIndication")); /* 3 */
+
+  AddProperty( new MP4BitfieldProperty("reserved", 6)); /* 4 */
+  AddProperty( new MP4BitfieldProperty("lengthSizeMinusOne", 2)); /* 5 */
+  AddProperty( new MP4BitfieldProperty("reserved1", 3)); /* 6 */
+  pCount = new MP4BitfieldProperty("numOfSequenceParameterSets", 5);
+  AddProperty(pCount); /* 7 */
+
+  pTable = new SizeTableProperty("sequenceEntries", pCount);
+  AddProperty(pTable); /* 8 */
+  pTable->AddProperty(new MP4Integer16Property("sequenceParameterSetLength"));
+  pTable->AddProperty(new MP4BytesProperty("sequenceParameterSetNALUnit"));
+
+  MP4Integer8Property *pCount2 = new MP4Integer8Property("numOfPictureParameterSets");
+  AddProperty(pCount2); /* 9 */
+
+  pTable = new SizeTableProperty("pictureEntries", pCount2);
+  AddProperty(pTable); /* 10 */
+  pTable->AddProperty(new MP4Integer16Property("pictureParameterSetLength"));
+  pTable->AddProperty(new MP4BytesProperty("pictureParameterSetNALUnit"));
+}
+
+void MP4AvcCAtom::Generate()
+{
+	MP4Atom::Generate();
+
+	((MP4Integer8Property*)m_pProperties[0])->SetValue(1);
+
+	m_pProperties[4]->SetReadOnly(false);
+	((MP4BitfieldProperty*)m_pProperties[4])->SetValue(0x3f);
+	m_pProperties[4]->SetReadOnly(true);
+
+	m_pProperties[6]->SetReadOnly(false);
+	((MP4BitfieldProperty*)m_pProperties[6])->SetValue(0x7);
+	m_pProperties[6]->SetReadOnly(true);
+#if 0
+	// property reserved4 has non-zero fixed values
+	static u_int8_t reserved4[4] = {
+		0x00, 0x18, 0xFF, 0xFF, 
+	};
+	m_pProperties[7]->SetReadOnly(false);
+	((MP4BytesProperty*)m_pProperties[7])->
+		SetValue(reserved4, sizeof(reserved4));
+	m_pProperties[7]->SetReadOnly(true);
+#endif
+}
+
+// 
+// Clone - clone my properties to destination atom
+//
+// this method simplifies duplicating avcC atom properties from 
+// source to destination file using a single API rather than 
+// having to copy each property.  This API encapsulates the object 
+// so the application layer need not concern with each property 
+// thereby isolating any future changes to atom properties.
+//
+// ----------------------------------------
+// property   description
+// ----------------------------------------
+//  
+// 0 	configurationVersion
+// 1 	AVCProfileIndication
+// 2	profile_compatibility
+// 3	AVCLevelIndication
+// 4 	reserved
+// 5 	lengthSizeMinusOne 
+// 6 	reserved
+// 7 	number of SPS
+// 8	SPS entries
+// 9	number of PPS
+// 10	PPS entries
+//
+//
+void MP4AvcCAtom::Clone(MP4AvcCAtom *dstAtom)
+{
+
+	MP4Property *dstProperty;
+  	MP4TableProperty *pTable;
+	u_int16_t i16;
+	u_int64_t i32;
+	u_int64_t i64;
+	u_int8_t *tmp;
+
+	// source pointer Property I16
+	MP4Integer16Property *spPI16;
+	// source pointer Property Bytes
+	MP4BytesProperty *spPB;
+
+	// dest pointer Property I16
+	MP4Integer16Property *dpPI16;
+	// dest pointer Property Bytes
+	MP4BytesProperty *dpPB;
+
+
+	// start with defaults and reserved fields
+	dstAtom->Generate();
+
+	// 0, 4, 6 are now generated from defaults
+	// leaving 1, 2, 3, 5, 7, 8, 9, 10 to export
+	
+	dstProperty=dstAtom->GetProperty(1);
+	((MP4Integer8Property *)dstProperty)->SetValue(
+		((MP4Integer8Property *)m_pProperties[1])->GetValue());
+	
+	dstProperty=dstAtom->GetProperty(2);
+	((MP4Integer8Property *)dstProperty)->SetValue(
+		((MP4Integer8Property *)m_pProperties[2])->GetValue());
+	
+	dstProperty=dstAtom->GetProperty(3);
+	((MP4Integer8Property *)dstProperty)->SetValue(
+		((MP4Integer8Property *)m_pProperties[3])->GetValue());
+	
+	dstProperty=dstAtom->GetProperty(5);
+	((MP4BitfieldProperty *)dstProperty)->SetValue(
+		((MP4BitfieldProperty *)m_pProperties[5])->GetValue());
+
+	// 
+	// 7 and 8 are related SPS (one set of sequence parameters) 
+	//
+	// first the count bitfield 
+	//
+	dstProperty=dstAtom->GetProperty(7);
+	dstProperty->SetReadOnly(false);
+	((MP4BitfieldProperty *)dstProperty)->SetValue(
+		((MP4BitfieldProperty *)m_pProperties[7])->GetValue());
+	dstProperty->SetReadOnly(true);
+
+	// next export SPS Length and NAL bytes */
+
+	// first source pointers
+	pTable = (MP4TableProperty *) m_pProperties[8];
+	spPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
+	spPB = (MP4BytesProperty *)pTable->GetProperty(1);
+
+	// now dest pointers
+	dstProperty=dstAtom->GetProperty(8);
+	pTable = (MP4TableProperty *) dstProperty;
+	dpPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
+	dpPB = (MP4BytesProperty *)pTable->GetProperty(1);
+	
+	// sps length
+	i16 = spPI16->GetValue();
+	i64 = i16;
+	// FIXME - this leaves m_maxNumElements =2
+	// but src atom m_maxNumElements is 1 
+	dpPI16->InsertValue(i64, 0);
+
+	// export byte array
+	i32 = i16;
+	// copy bytes to local buffer 
+	tmp = (u_int8_t *)MP4Malloc(i32);
+	ASSERT(tmp != NULL);
+	spPB->CopyValue(tmp, 0);	
+	// set element count
+	dpPB->SetCount(1);
+	// copy bytes 
+	dpPB->SetValue(tmp, i32, 0);
+	MP4Free((void *)tmp);
+
+	// 
+	// 9 and 10 are related PPS (one set of picture parameters) 
+	//
+	// first the integer8 count
+	//
+	dstProperty=dstAtom->GetProperty(9);
+	dstProperty->SetReadOnly(false);
+	((MP4Integer8Property *)dstProperty)->SetValue(
+		((MP4Integer8Property *)m_pProperties[9])->GetValue());
+	dstProperty->SetReadOnly(true);
+
+	// next export PPS Length and NAL bytes */
+
+	// first source pointers
+	pTable = (MP4TableProperty *) m_pProperties[10];
+	spPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
+	spPB = (MP4BytesProperty *)pTable->GetProperty(1);
+
+	// now dest pointers
+	dstProperty=dstAtom->GetProperty(10);
+	pTable = (MP4TableProperty *) dstProperty;
+	dpPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
+	dpPB = (MP4BytesProperty *)pTable->GetProperty(1);
+	
+	// pps length
+	i16 = spPI16->GetValue();
+	i64 = i16;
+	dpPI16->InsertValue(i64, 0);
+
+	// export byte array
+	i32 = i16;
+	// copy bytes to local buffer 
+	tmp = (u_int8_t *)MP4Malloc(i32);
+	ASSERT(tmp != NULL);
+	spPB->CopyValue(tmp, 0);	
+	// set element count
+	dpPB->SetCount(1);
+	// copy bytes 
+	dpPB->SetValue(tmp, i32, 0);
+	MP4Free((void *)tmp);
+}
+
+
--- a/common/mp4v2/atom_bitr.cpp
+++ /dev/null
@@ -1,41 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is MPEG4IP.
- *
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- *
- * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
- * and was contributed by Ximpo Group Ltd.
- *
- * Portions created by Ximpo Group Ltd. are
- * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved.
- *
- * Contributor(s):
- *              Ximpo Group Ltd.          [email protected]
- */
-
-#include "mp4common.h"
-
-MP4BitrAtom::MP4BitrAtom() 
-	: MP4Atom("bitr") 
-{
-	AddProperty( /* 0 */
-		new MP4Integer32Property("avgBitrate"));
-
-	AddProperty( /* 1 */
-		new MP4Integer32Property("maxBitrate"));
-
-
-}
-
--- a/common/mp4v2/atom_co64.cpp
+++ /dev/null
@@ -1,38 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4Co64Atom::MP4Co64Atom() 
-	: MP4Atom("co64") 
-{
-	AddVersionAndFlags();
-
-	MP4Integer32Property* pCount = 
-		new MP4Integer32Property("entryCount"); 
-	AddProperty(pCount);
-
-	MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
-	AddProperty(pTable);
-
-	pTable->AddProperty(
-		new MP4Integer64Property("chunkOffset"));
-}
--- a/common/mp4v2/atom_cprt.cpp
+++ /dev/null
@@ -1,32 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4CprtAtom::MP4CprtAtom() 
-	: MP4Atom("cprt") 
-{
-	AddVersionAndFlags();
-	AddProperty(
-		new MP4Integer16Property("language"));
-	AddProperty(
-		new MP4StringProperty("notice"));
-}
--- a/common/mp4v2/atom_ctts.cpp
+++ /dev/null
@@ -1,40 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4CttsAtom::MP4CttsAtom() 
-	: MP4Atom("ctts") 
-{
-	AddVersionAndFlags();
-
-	MP4Integer32Property* pCount = 
-		new MP4Integer32Property("entryCount"); 
-	AddProperty(pCount);
-
-	MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
-	AddProperty(pTable);
-
-	pTable->AddProperty(
-		new MP4Integer32Property("sampleCount"));
-	pTable->AddProperty(
-		new MP4Integer32Property("sampleOffset"));
-}
--- a/common/mp4v2/atom_dimm.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4DimmAtom::MP4DimmAtom() 
-	: MP4Atom("dimm") 
-{
-	AddProperty( // bytes of immediate data
-		new MP4Integer64Property("bytes"));
-}
--- a/common/mp4v2/atom_dinf.cpp
+++ /dev/null
@@ -1,28 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4DinfAtom::MP4DinfAtom() 
-	: MP4Atom("dinf") 
-{
-	ExpectChildAtom("dref", Required, OnlyOne);
-}
--- a/common/mp4v2/atom_dmax.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4DmaxAtom::MP4DmaxAtom() 
-	: MP4Atom("dmax")
-{
-	AddProperty( // max packet duration 
-		new MP4Integer32Property("milliSecs"));
-}
--- a/common/mp4v2/atom_dmed.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4DmedAtom::MP4DmedAtom() 
-	: MP4Atom("dmed") 
-{
-	AddProperty( // bytes sent from media data
-		new MP4Integer64Property("bytes"));
-}
--- a/common/mp4v2/atom_dref.cpp
+++ b/common/mp4v2/atom_dref.cpp
@@ -33,6 +33,7 @@
 
 	ExpectChildAtom("url ", Optional, Many);
 	ExpectChildAtom("urn ", Optional, Many);
+	ExpectChildAtom("alis", Optional, Many);
 }
 
 void MP4DrefAtom::Read() 
--- a/common/mp4v2/atom_drep.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4DrepAtom::MP4DrepAtom() 
-	: MP4Atom("drep") 
-{
-	AddProperty( // bytes of repeated data
-		new MP4Integer64Property("bytes"));
-}
--- a/common/mp4v2/atom_edts.cpp
+++ /dev/null
@@ -1,28 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4EdtsAtom::MP4EdtsAtom() 
-	: MP4Atom("edts") 
-{ 
-	ExpectChildAtom("elst", Required, OnlyOne);
-}
--- a/common/mp4v2/atom_encv.cpp
+++ b/common/mp4v2/atom_encv.cpp
@@ -48,6 +48,7 @@
 
 	ExpectChildAtom("esds", Required, OnlyOne);
 	ExpectChildAtom("sinf", Required, OnlyOne);
+	ExpectChildAtom("avcC", Optional, OnlyOne);
 }	
 
 void MP4EncvAtom::Generate()
--- a/common/mp4v2/atom_esds.cpp
+++ /dev/null
@@ -1,31 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4EsdsAtom::MP4EsdsAtom() 
-	: MP4Atom("esds") 
-{
-	AddVersionAndFlags();
-	AddProperty(
-		new MP4DescriptorProperty(NULL, 
-			MP4ESDescrTag, 0, Required, OnlyOne));
-}
--- a/common/mp4v2/atom_free.cpp
+++ b/common/mp4v2/atom_free.cpp
@@ -37,7 +37,13 @@
 
 	bool use64 = (GetSize() > (0xFFFFFFFF - 8)); 
 	BeginWrite(use64);
+#if 1
+	for (uint64_t ix = 0; ix < GetSize(); ix++) {
+	  m_pFile->WriteUInt8(0);
+	}
+#else
 	m_pFile->SetPosition(m_pFile->GetPosition() + GetSize());
+#endif
 	FinishWrite(use64);
 }
 
--- a/common/mp4v2/atom_frma.cpp
+++ /dev/null
@@ -1,32 +1,0 @@
-/*
- * 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): 
- *		Alix Marchandise-Franquet [email protected]
- *
- * Add the OriginalFormatBox for ISMACrypt 
- * contains the original format of the data (i.e. decrypted format)
- */
-
-#include "mp4common.h"
-
-MP4FrmaAtom::MP4FrmaAtom() 
-	: MP4Atom("frma") 
-{
-        AddProperty( /* 0 */
-                new MP4Integer32Property("data-format"));			
-}
--- /dev/null
+++ b/common/mp4v2/atom_gmin.cpp
@@ -1,0 +1,49 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * Contributer has declined to give copyright information, and gives
+ * it freely to the world.
+ * 
+ * Contributor(s): 
+ */
+
+#include "mp4common.h"
+
+MP4GminAtom::MP4GminAtom() 
+	: MP4Atom("gmin") 
+{
+
+	AddVersionAndFlags(); /* 0, 1 */
+
+	AddProperty(new MP4Integer16Property("graphicsMode")); /* 2 */
+	AddProperty(new MP4Integer16Property("opColorRed")); /* 3 */
+	AddProperty(new MP4Integer16Property("opColorGreen")); /* 4 */
+	AddProperty(new MP4Integer16Property("opColorBlue")); /* 5 */
+	AddProperty(new MP4Integer16Property("balance")); /* 6 */
+	AddReserved("reserved", 2); /* 7 */
+
+}
+
+void MP4GminAtom::Generate()
+{
+
+	MP4Atom::Generate();
+
+	((MP4Integer16Property*)m_pProperties[2])->SetValue(0x0040);
+	((MP4Integer16Property*)m_pProperties[3])->SetValue(0x8000);
+	((MP4Integer16Property*)m_pProperties[4])->SetValue(0x8000);
+	((MP4Integer16Property*)m_pProperties[5])->SetValue(0x8000);
+	((MP4Integer16Property*)m_pProperties[6])->SetValue(0x0000);
+
+}
+
--- a/common/mp4v2/atom_hdlr.cpp
+++ b/common/mp4v2/atom_hdlr.cpp
@@ -42,13 +42,15 @@
 {
 	// read all the properties but the "name" field
 	ReadProperties(0, 5);
+	uint64_t pos = m_pFile->GetPosition();
+	uint64_t end = GetEnd();
+	if (pos == end) return;
 
 	// take a peek at the next byte
 	u_int8_t strLength;
 	m_pFile->PeekBytes(&strLength, 1);
-
 	// if the value matches the remaining atom length
-	if (m_pFile->GetPosition() + strLength + 1 == GetEnd()) {
+	if (pos + strLength + 1 == end) {
 		// read a counted string
 		MP4StringProperty* pNameProp = 
 			(MP4StringProperty*)m_pProperties[5];
--- a/common/mp4v2/atom_hmhd.cpp
+++ /dev/null
@@ -1,39 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4HmhdAtom::MP4HmhdAtom() 
-	: MP4Atom("hmhd")
-{
-	AddVersionAndFlags();
-
-	AddProperty(	
-		new MP4Integer16Property("maxPduSize")); 
-	AddProperty(	
-		new MP4Integer16Property("avgPduSize")); 
-	AddProperty(	
-		new MP4Integer32Property("maxBitRate")); 
-	AddProperty(	
-		new MP4Integer32Property("avgBitRate")); 
-	AddProperty(	
-		new MP4Integer32Property("slidingAvgBitRate")); 
-}
--- /dev/null
+++ b/common/mp4v2/atom_href.cpp
@@ -1,0 +1,40 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2005.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Bill May [email protected]
+ */
+
+#include "mp4common.h"
+
+MP4HrefAtom::MP4HrefAtom() 
+	: MP4Atom("href") 
+{
+	AddReserved("reserved1", 6); /* 0 */
+
+	AddProperty( /* 1 */
+		new MP4Integer16Property("dataReferenceIndex"));
+	ExpectChildAtom("burl", Optional, OnlyOne);
+}
+
+void MP4HrefAtom::Generate()
+{
+	MP4Atom::Generate();
+
+	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+}
--- a/common/mp4v2/atom_iKMS.cpp
+++ /dev/null
@@ -1,34 +1,0 @@
-/*
- * 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): 
- *		Alix Marchandise-Franquet [email protected]
- *
- * ISMAKMSBox for ISMACrypt
- * Do we care about the string length? Do we need to handle the null-term
- * issue like in the hdlr atom?
- */
-
-#include "mp4common.h"
-
-MP4IKMSAtom::MP4IKMSAtom() 
-	: MP4Atom("iKMS") 
-{
-	AddVersionAndFlags(); /* 0, 1 */
-	MP4StringProperty* pProp = new MP4StringProperty("kms_URI");
-	AddProperty(pProp); /* 2 */
-}
--- a/common/mp4v2/atom_iSFM.cpp
+++ /dev/null
@@ -1,38 +1,0 @@
-/*
- * 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): 
- *		Alix Marchandise-Franquet [email protected]
- *
- * ISMASampleFormatBox for ISMACrypt		
- */
-
-#include "mp4common.h"
-
-MP4ISFMAtom::MP4ISFMAtom() 
-	: MP4Atom("iSFM") 
-{
-	AddVersionAndFlags(); /* 0, 1 */
-	AddProperty( /* 2 */
-		new MP4BitfieldProperty("selective-encryption", 1));
-	AddProperty( /* 3 */
-		new MP4BitfieldProperty("reserved", 7));
-	AddProperty( /* 4 */
-		new MP4Integer8Property("key-indicator-length"));	
-	AddProperty( /* 5 */
-		new MP4Integer8Property("IV-length"));	
-}
--- a/common/mp4v2/atom_iods.cpp
+++ /dev/null
@@ -1,31 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4IodsAtom::MP4IodsAtom() 
-	: MP4Atom("iods") 
-{
-	AddVersionAndFlags();
-	AddProperty(
-		new MP4DescriptorProperty(NULL, 
-			MP4FileIODescrTag, MP4FileODescrTag, Required, OnlyOne));
-}
--- a/common/mp4v2/atom_maxr.cpp
+++ /dev/null
@@ -1,31 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4MaxrAtom::MP4MaxrAtom() 
-	: MP4Atom("maxr") 
-{
-	AddProperty(
-		new MP4Integer32Property("granularity"));
-	AddProperty(
-		new MP4Integer32Property("bytes"));
-}
--- a/common/mp4v2/atom_mdia.cpp
+++ /dev/null
@@ -1,30 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4MdiaAtom::MP4MdiaAtom() 
-	: MP4Atom("mdia") 
-{
-	ExpectChildAtom("mdhd", Required, OnlyOne);
-	ExpectChildAtom("hdlr", Required, OnlyOne);
-	ExpectChildAtom("minf", Required, OnlyOne);
-}
--- a/common/mp4v2/atom_meta.cpp
+++ b/common/mp4v2/atom_meta.cpp
@@ -23,26 +23,16 @@
 
 #include "mp4common.h"
 
-MP4MetaAtom::MP4MetaAtom()
-    : MP4Atom("meta")
+MP4Meta1Atom::MP4Meta1Atom(const char *name)
+    : MP4Atom(name)
 {
-	AddVersionAndFlags(); /* 0, 1 */
+  AddVersionAndFlags(); /* 0, 1 */
 
-    ExpectChildAtom("hdlr", Required, OnlyOne);
-    ExpectChildAtom("ilst", Required, OnlyOne);
+  AddProperty(new MP4BytesProperty("metadata")); /* 2 */
 }
 
-MP4MeanAtom::MP4MeanAtom()
-    : MP4Atom("mean")
+void MP4Meta1Atom::Read() 
 {
-	AddVersionAndFlags(); /* 0, 1 */
-
-    AddProperty(
-        new MP4BytesProperty("metadata")); /* 2 */
-}
-
-void MP4MeanAtom::Read() 
-{
 	// calculate size of the metadata from the atom size
 	((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 4);
 
@@ -49,23 +39,6 @@
 	MP4Atom::Read();
 }
 
-MP4NameAtom::MP4NameAtom()
-    : MP4Atom("name")
-{
-	AddVersionAndFlags(); /* 0, 1 */
-
-    AddProperty(
-        new MP4BytesProperty("metadata")); /* 2 */
-}
-
-void MP4NameAtom::Read() 
-{
-	// calculate size of the metadata from the atom size
-	((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 4);
-
-	MP4Atom::Read();
-}
-
 MP4DataAtom::MP4DataAtom()
     : MP4Atom("data")
 {
@@ -84,114 +57,28 @@
 	MP4Atom::Read();
 }
 
-MP4IlstAtom::MP4IlstAtom()
-    : MP4Atom("ilst")
-{
-    ExpectChildAtom("\251nam", Optional, OnlyOne); /* name */
-    ExpectChildAtom("\251ART", Optional, OnlyOne); /* artist */
-    ExpectChildAtom("\251wrt", Optional, OnlyOne); /* writer */
-    ExpectChildAtom("\251alb", Optional, OnlyOne); /* album */
-    ExpectChildAtom("\251day", Optional, OnlyOne); /* date */
-    ExpectChildAtom("\251too", Optional, OnlyOne); /* tool */
-    ExpectChildAtom("\251cmt", Optional, OnlyOne); /* comment */
-    ExpectChildAtom("\251gen", Optional, OnlyOne); /* custom genre */
-    ExpectChildAtom("trkn", Optional, OnlyOne); /* tracknumber */
-    ExpectChildAtom("disk", Optional, OnlyOne); /* disknumber */
-    ExpectChildAtom("gnre", Optional, OnlyOne); /* genre (ID3v1 index + 1) */
-    ExpectChildAtom("cpil", Optional, OnlyOne); /* compilation */
-    ExpectChildAtom("tmpo", Optional, OnlyOne); /* BPM */
-    ExpectChildAtom("covr", Optional, OnlyOne); /* cover art */
-    ExpectChildAtom("----", Optional, Many); /* ---- free form */
-}
 
-MP4DashAtom::MP4DashAtom()
-    : MP4Atom("----")
+// MP4Meta2Atom is for \251nam and \251cmt flags, which appear differently
+// in .mov and in itunes file.  In .movs, they appear under udata, in 
+// itunes, they appear under ilst.
+MP4Meta2Atom::MP4Meta2Atom (const char *name) : MP4Atom(name)
 {
-    ExpectChildAtom("mean", Required, OnlyOne);
-    ExpectChildAtom("name", Required, OnlyOne);
-    ExpectChildAtom("data", Required, OnlyOne);
 }
 
-MP4NamAtom::MP4NamAtom()
-    : MP4Atom("\251nam")
+void MP4Meta2Atom::Read ()
 {
-    ExpectChildAtom("data", Required, OnlyOne);
-}
+  MP4Atom *parent = GetParentAtom();
+  if (ATOMID(parent->GetType()) == ATOMID("udta")) {
+    // add data property
+    AddReserved("reserved2", 4); /* 0 */
 
-MP4ArtAtom::MP4ArtAtom()
-    : MP4Atom("\251ART")
-{
+    AddProperty(
+        new MP4BytesProperty("metadata")); /* 1 */
+    ((MP4BytesProperty*)m_pProperties[1])->SetValueSize(m_size - 4);
+  } else {
     ExpectChildAtom("data", Required, OnlyOne);
+  }
+  MP4Atom::Read();
 }
 
-MP4WrtAtom::MP4WrtAtom()
-    : MP4Atom("\251wrt")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4AlbAtom::MP4AlbAtom()
-    : MP4Atom("\251alb")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4CmtAtom::MP4CmtAtom()
-    : MP4Atom("\251cmt")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4TrknAtom::MP4TrknAtom()
-    : MP4Atom("trkn")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4DiskAtom::MP4DiskAtom()
-    : MP4Atom("disk")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4DayAtom::MP4DayAtom()
-    : MP4Atom("\251day")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4GenAtom::MP4GenAtom()
-    : MP4Atom("\251gen")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4TooAtom::MP4TooAtom()
-    : MP4Atom("\251too")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4GnreAtom::MP4GnreAtom()
-    : MP4Atom("gnre")
-{
-    ExpectChildAtom("data", Optional, OnlyOne);
-}
-
-MP4CpilAtom::MP4CpilAtom()
-    : MP4Atom("cpil")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4TmpoAtom::MP4TmpoAtom()
-    : MP4Atom("tmpo")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
-
-MP4CovrAtom::MP4CovrAtom()
-    : MP4Atom("covr")
-{
-    ExpectChildAtom("data", Required, OnlyOne);
-}
+  
--- a/common/mp4v2/atom_mfhd.cpp
+++ /dev/null
@@ -1,31 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4MfhdAtom::MP4MfhdAtom() 
-	: MP4Atom("mfhd")
-{
-	AddVersionAndFlags();	/* 0, 1 */
-	AddProperty( /* 2 */
-		new MP4Integer32Property("sequenceNumber"));
-}
-
--- a/common/mp4v2/atom_minf.cpp
+++ /dev/null
@@ -1,33 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4MinfAtom::MP4MinfAtom() 
-	: MP4Atom("minf") 
-{
-	ExpectChildAtom("vmhd", Optional, OnlyOne);
-	ExpectChildAtom("smhd", Optional, OnlyOne);
-	ExpectChildAtom("hmhd", Optional, OnlyOne);
-	ExpectChildAtom("nmhd", Optional, OnlyOne);
-	ExpectChildAtom("dinf", Required, OnlyOne);
-	ExpectChildAtom("stbl", Required, OnlyOne);
-}
--- a/common/mp4v2/atom_moof.cpp
+++ /dev/null
@@ -1,30 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4MoofAtom::MP4MoofAtom() 
-	: MP4Atom("moof")
-{
-	ExpectChildAtom("mfhd", Required, OnlyOne);
-	ExpectChildAtom("traf", Optional, Many);
-}
-
--- a/common/mp4v2/atom_moov.cpp
+++ /dev/null
@@ -1,33 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4MoovAtom::MP4MoovAtom() 
-	: MP4Atom("moov")
-{
-	ExpectChildAtom("mvhd", Required, OnlyOne);
-	ExpectChildAtom("iods", Required, OnlyOne);
-	ExpectChildAtom("trak", Required, Many);
-	ExpectChildAtom("udta", Optional, Many);
-	ExpectChildAtom("mvex", Optional, OnlyOne);
-}
-
--- a/common/mp4v2/atom_mvex.cpp
+++ /dev/null
@@ -1,28 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4MvexAtom::MP4MvexAtom() 
-	: MP4Atom("mvex")
-{
-	ExpectChildAtom("trex", Required, Many);
-}
--- a/common/mp4v2/atom_nmhd.cpp
+++ /dev/null
@@ -1,28 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4NmhdAtom::MP4NmhdAtom() 
-	: MP4Atom("nmhd") 
-{
-	AddVersionAndFlags();
-}
--- a/common/mp4v2/atom_nump.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4NumpAtom::MP4NumpAtom() 
-	: MP4Atom("nump") 
-{
-	AddProperty( // packets sent
-		new MP4Integer64Property("packets"));
-}
--- /dev/null
+++ b/common/mp4v2/atom_ohdr.cpp
@@ -1,0 +1,92 @@
+/**	\file atom_ohdr.cpp
+
+  	\author Danijel Kopcinovic ([email protected])
+*/
+
+#include "mp4common.h"
+
+/*! \brief Patch class for read/write operations when string is 0-length.
+
+    We want to use string property, but mpeg4ip doesn't support ohdr way of
+    encoding of string (in ohdr atom we first have 3 lengths of 3 strings and
+    then their string values, and it cannot be simulated with any of the
+    current mpeg4ip string property parameters), so we have to write our own
+    Read() and Write() routines.
+*/
+class OhdrMP4StringProperty: public MP4StringProperty {
+public:
+  /*! \brief Constructor.
+  
+      \param name                name of the property.
+      \param useCountedFormat    counted format flag.
+      \param useUnicode          unicode flag.
+  */
+	OhdrMP4StringProperty(char* name, bool useCountedFormat = false,
+    bool useUnicode = false): MP4StringProperty(name, useCountedFormat,
+    useUnicode) {
+  }
+    
+  /*! \brief Read property from file.
+  
+      \param pFile                input, file handle.
+      \param index                input, index to read.
+  */
+	void Read(MP4File* pFile, u_int32_t index = 0) {
+	  MP4Free(m_values[index]);
+	  m_values[index] = (char*)MP4Calloc(m_fixedLength + 1);
+	  (void)pFile->ReadBytes((u_int8_t*)m_values[index], m_fixedLength);
+  }
+	
+  /*! \brief Write property to file.
+  
+      \param pFile                input, file handle.
+      \param index                input, index to write.
+  */
+	void Write(MP4File* pFile, u_int32_t index = 0) {
+    pFile->WriteBytes((u_int8_t*)m_values[index], m_fixedLength);
+  }
+};
+
+/*! \brief OMA DRM headers atom.
+
+    Contained in OMA DRM key management atom. It must contain content identifier.
+*/
+/*! \brief Constructor.
+*/
+MP4OhdrAtom::MP4OhdrAtom(): MP4Atom("ohdr") {
+	AddVersionAndFlags();
+
+	AddProperty(new MP4Integer8Property("EncryptionMethod"));
+	AddProperty(new MP4Integer8Property("EncryptionPadding"));
+	AddProperty(new MP4Integer64Property("PlaintextLength"));
+	AddProperty(new MP4Integer16Property("ContentIDLength"));
+	AddProperty(new MP4Integer16Property("RightsIssuerURLLength"));
+	AddProperty(new MP4Integer16Property("TextualHeadersLength"));
+	AddProperty(new OhdrMP4StringProperty("ContentID"));
+	AddProperty(new OhdrMP4StringProperty("RightsIssuerURL"));
+	AddProperty(new MP4BytesProperty("TextualHeaders"));
+}
+
+MP4OhdrAtom::~MP4OhdrAtom() {
+}
+
+/*! \brief Read atom.
+*/
+void MP4OhdrAtom::Read() {
+  ReadProperties(0, 8);
+  MP4Property* lProperty;
+  MP4Property* property;
+  lProperty = GetProperty(5);
+  property = GetProperty(8);
+  ((OhdrMP4StringProperty*)property)->SetFixedLength(
+    ((MP4Integer16Property*)lProperty)->GetValue());
+  lProperty = GetProperty(6);
+  property = GetProperty(9);
+  ((OhdrMP4StringProperty*)property)->SetFixedLength(
+    ((MP4Integer16Property*)lProperty)->GetValue());
+  lProperty = GetProperty(7);
+  property = GetProperty(10);
+  ((MP4BytesProperty*)property)->SetFixedSize(
+    ((MP4Integer16Property*)lProperty)->GetValue());
+  ReadProperties(8, 3);
+}
--- a/common/mp4v2/atom_payt.cpp
+++ /dev/null
@@ -1,31 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4PaytAtom::MP4PaytAtom() 
-	: MP4Atom("payt")
-{
-	AddProperty( 
-		new MP4Integer32Property("payloadNumber"));
-	AddProperty( 
-		new MP4StringProperty("rtpMap", Counted));
-}
--- a/common/mp4v2/atom_pmax.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4PmaxAtom::MP4PmaxAtom() 
-	: MP4Atom("pmax") 
-{
-	AddProperty( // max packet size 
-		new MP4Integer32Property("bytes"));
-}
--- a/common/mp4v2/atom_root.cpp
+++ b/common/mp4v2/atom_root.cpp
@@ -24,8 +24,8 @@
 MP4RootAtom::MP4RootAtom() 
 	: MP4Atom(NULL)
 {
-	ExpectChildAtom("ftyp", Required, OnlyOne);
 	ExpectChildAtom("moov", Required, OnlyOne);
+	ExpectChildAtom("ftyp", Optional, OnlyOne);
 	ExpectChildAtom("mdat", Optional, Many);
 	ExpectChildAtom("free", Optional, Many);
 	ExpectChildAtom("skip", Optional, Many);
@@ -85,6 +85,7 @@
 		}
 	}
 	ASSERT(i < size);
+	ASSERT(pMoovAtom != NULL);
 
 	// rewrite moov so that updated chunkOffsets are written to disk
 	m_pFile->SetPosition(pMoovAtom->GetStart());
--- a/common/mp4v2/atom_rtp.cpp
+++ b/common/mp4v2/atom_rtp.cpp
@@ -120,6 +120,7 @@
 	// read sdp string, length is implicit in size of atom
 	u_int64_t size = GetEnd() - m_pFile->GetPosition();
 	char* data = (char*)MP4Malloc(size + 1);
+	ASSERT(data != NULL);
 	m_pFile->ReadBytes((u_int8_t*)data, size);
 	data[size] = '\0';
 	((MP4StringProperty*)m_pProperties[1])->SetValue(data);
--- a/common/mp4v2/atom_samr.cpp
+++ /dev/null
@@ -1,65 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is MPEG4IP.
- *
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- *
- * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
- * and was contributed by Ximpo Group Ltd.
- *
- * Portions created by Ximpo Group Ltd. are
- * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved.
- *
- * Contributor(s):
- *              Ximpo Group Ltd.          [email protected]
- */
-
-#include "mp4common.h"
-
-MP4SamrAtom::MP4SamrAtom() 
-	: MP4Atom("samr") 
-{
-	AddReserved("reserved1", 6); /* 0 */
-
-	AddProperty( /* 1 */
-		new MP4Integer16Property("dataReferenceIndex"));
-
-	AddReserved("reserved2", 16); /* 2 */
-
-	AddProperty( /* 3 */
-		new MP4Integer16Property("timeScale"));
-
-	AddReserved("reserved3", 2); /* 4 */
-
-	ExpectChildAtom("damr", Required, OnlyOne);
-}
-
-void MP4SamrAtom::Generate()
-{
-	MP4Atom::Generate();
-
-	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
-
-	// property reserved2 has non-zero fixed values
-	static u_int8_t reserved2[16] = {
-		0x00, 0x00, 0x00, 0x00, 
-		0x00, 0x00, 0x00, 0x00, 
-		0x00, 0x02, 0x00, 0x10,
-		0x00, 0x00, 0x00, 0x00, 
-	};
-	m_pProperties[2]->SetReadOnly(false);
-	((MP4BytesProperty*)m_pProperties[2])->
-		SetValue(reserved2, sizeof(reserved2));
-	m_pProperties[2]->SetReadOnly(true);
-}
--- a/common/mp4v2/atom_sawb.cpp
+++ /dev/null
@@ -1,65 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is MPEG4IP.
- *
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- *
- * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
- * and was contributed by Ximpo Group Ltd.
- *
- * Portions created by Ximpo Group Ltd. are
- * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved.
- *
- * Contributor(s):
- *              Ximpo Group Ltd.          [email protected]
- */
-
-#include "mp4common.h"
-
-MP4SawbAtom::MP4SawbAtom() 
-	: MP4Atom("sawb") 
-{
-	AddReserved("reserved1", 6); /* 0 */
-
-	AddProperty( /* 1 */
-		new MP4Integer16Property("dataReferenceIndex"));
-
-	AddReserved("reserved2", 16); /* 2 */
-
-	AddProperty( /* 3 */
-		new MP4Integer16Property("timeScale"));
-
-	AddReserved("reserved3", 2); /* 4 */
-
-	ExpectChildAtom("damr", Required, OnlyOne);
-}
-
-void MP4SawbAtom::Generate()
-{
-	MP4Atom::Generate();
-
-	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
-
-	// property reserved2 has non-zero fixed values
-	static u_int8_t reserved2[16] = {
-		0x00, 0x00, 0x00, 0x00, 
-		0x00, 0x00, 0x00, 0x00, 
-		0x00, 0x02, 0x00, 0x10,
-		0x00, 0x00, 0x00, 0x00, 
-	};
-	m_pProperties[2]->SetReadOnly(false);
-	((MP4BytesProperty*)m_pProperties[2])->
-		SetValue(reserved2, sizeof(reserved2));
-	m_pProperties[2]->SetReadOnly(true);
-}
--- a/common/mp4v2/atom_schi.cpp
+++ /dev/null
@@ -1,33 +1,0 @@
-/*
- * 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): 
- *		Alix Marchandise-Franquet  [email protected]
- *
- * SchemeInformationBox for ISMACrypt
- */
-
-#include "mp4common.h"
-
-MP4SchiAtom::MP4SchiAtom() 
-	: MP4Atom("schi") 
-{
-	// not sure if this is child atoms or table of boxes
-	// get clarification on spec 9.1.2.5
-	ExpectChildAtom("iKMS", Required, OnlyOne);
-	ExpectChildAtom("iSFM", Required, OnlyOne);
-}
--- a/common/mp4v2/atom_schm.cpp
+++ /dev/null
@@ -1,35 +1,0 @@
-/*
- * 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): 
- *              Alix Marchandise-Franquet [email protected]
- *
- * Add the SchemeTypeBox for ISMACrypt
- */
-
-#include "mp4common.h"
-
-MP4SchmAtom::MP4SchmAtom() 
-	: MP4Atom("schm") 
-{
-	AddVersionAndFlags(); /* 0, 1 */
-	AddProperty( /* 2 */
-                new MP4Integer32Property("scheme_type"));
-	AddProperty( /* 3 */
-	        new MP4Integer32Property("scheme_version"));
-	// browser URI if flags set, TODO
-}
--- a/common/mp4v2/atom_sdp.cpp
+++ b/common/mp4v2/atom_sdp.cpp
@@ -32,6 +32,7 @@
 	// read sdp string, length is implicit in size of atom 
 	u_int64_t size = GetEnd() - m_pFile->GetPosition();
 	char* data = (char*)MP4Malloc(size + 1);
+	ASSERT(data != NULL);
 	m_pFile->ReadBytes((u_int8_t*)data, size);
 	data[size] = '\0';
 	((MP4StringProperty*)m_pProperties[0])->SetValue(data);
--- a/common/mp4v2/atom_sinf.cpp
+++ /dev/null
@@ -1,33 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *              Dave Mackie                [email protected]
- *		Alix Marchandise-Franquet  [email protected]
- *
- * Add the ProtectionInfoBox for ISMACrypt
- */
-
-#include "mp4common.h"
-
-MP4SinfAtom::MP4SinfAtom() 
-	: MP4Atom("sinf") 
-{
-	ExpectChildAtom("frma", Required, OnlyOne);
-	ExpectChildAtom("schm", Required, OnlyOne);
-	ExpectChildAtom("schi", Required, OnlyOne);
-}
--- a/common/mp4v2/atom_smhd.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4SmhdAtom::MP4SmhdAtom() 
-	: MP4Atom("smhd")
-{
-	AddVersionAndFlags();
-	AddReserved("reserved", 4);
-}
--- /dev/null
+++ b/common/mp4v2/atom_smi.cpp
@@ -1,0 +1,41 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2004.  All Rights Reserved.
+ *
+ * Contributor(s):
+ *       Bill May  [email protected]
+ *
+ * Apple iTunes META data
+ */
+
+#include "mp4common.h"
+
+MP4SmiAtom::MP4SmiAtom()
+    : MP4Atom("meta")
+{
+
+  AddProperty( new MP4BytesProperty("metadata"));
+
+}
+
+void MP4SmiAtom::Read() 
+{
+	// calculate size of the metadata from the atom size
+	((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size);
+
+	MP4Atom::Read();
+}
+
--- a/common/mp4v2/atom_snro.cpp
+++ /dev/null
@@ -1,30 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4SnroAtom::MP4SnroAtom() 
-	: MP4Atom("snro") 
-{
-	AddProperty( 
-		new MP4Integer32Property("offset"));
-}
-
--- /dev/null
+++ b/common/mp4v2/atom_sound.cpp
@@ -1,0 +1,125 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2004.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Bill May		[email protected]
+ */
+
+#include "mp4common.h"
+
+MP4SoundAtom::MP4SoundAtom(const char *atomid) 
+	: MP4Atom(atomid) 
+{
+	AddReserved("reserved1", 6); /* 0 */
+
+	AddProperty( /* 1 */
+		new MP4Integer16Property("dataReferenceIndex"));
+	AddProperty( /* 2 */
+		    new MP4Integer16Property("soundVersion"));
+	AddReserved( "reserved2", 6); /* 3 */
+	
+	AddProperty( /* 4 */
+		    new MP4Integer16Property("channels"));
+	AddProperty( /* 5 */
+		    new MP4Integer16Property("sampleSize"));
+	AddProperty( /* 6 */
+		    new MP4Integer16Property("packetSize"));
+	AddProperty( /* 7 */
+		    new MP4Integer32Property("timeScale"));
+
+	if (ATOMID(atomid) == ATOMID("mp4a")) {
+	  AddReserved("reserved3", 2); /* 8 */
+	  ExpectChildAtom("esds", Required, OnlyOne);
+	  ExpectChildAtom("wave", Optional, OnlyOne);
+	} else if (ATOMID(atomid) == ATOMID("alac")) {
+	  AddReserved("reserved3", 2); /* 8 */
+	  ExpectChildAtom("alac", Optional, Optional);
+	  //AddProperty( new MP4BytesProperty("alacInfo", 36));
+	}
+}
+
+void MP4SoundAtom::AddProperties (uint8_t version)
+{
+  if (version > 0) {
+    AddProperty( /* 8 */
+		new MP4Integer32Property("samplesPerPacket"));
+    AddProperty( /* 9 */
+		new MP4Integer32Property("bytesPerPacket"));
+    AddProperty( /* 10 */
+		new MP4Integer32Property("bytesPerFrame"));
+    AddProperty( /* 11 */
+		new MP4Integer32Property("bytesPerSample"));
+  }
+  if (version == 2) {
+    AddReserved("reserved4", 20);
+  }
+}
+void MP4SoundAtom::Generate()
+{
+	MP4Atom::Generate();
+
+	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+	// property reserved2 has non-zero fixed values
+	((MP4Integer16Property*)m_pProperties[2])->SetValue(0);
+	static const u_int8_t reserved2[6] = {
+		0x00, 0x00, 0x00, 0x00, 
+		0x00, 0x00, 
+	};
+	m_pProperties[3]->SetReadOnly(false);
+	((MP4BytesProperty*)m_pProperties[3])->
+		SetValue(reserved2, sizeof(reserved2));
+	m_pProperties[3]->SetReadOnly(true);
+	((MP4Integer16Property*)m_pProperties[4])->SetValue(2);
+	((MP4Integer16Property*)m_pProperties[5])->SetValue(0x0010);
+	((MP4Integer16Property*)m_pProperties[6])->SetValue(0);
+
+}
+
+void MP4SoundAtom::Read()
+{
+  MP4Atom *parent = GetParentAtom();
+  if (ATOMID(parent->GetType()) != ATOMID("stsd")) {
+    // Quicktime has an interesting thing - they'll put an mp4a atom
+    // which is blank inside a wave atom, which is inside an mp4a atom
+    // we have a mp4a inside an wave inside an mp4a - delete all properties
+    m_pProperties.Delete(8);
+    m_pProperties.Delete(7);
+    m_pProperties.Delete(6);
+    m_pProperties.Delete(5);
+    m_pProperties.Delete(4);
+    m_pProperties.Delete(3);
+    m_pProperties.Delete(2);
+    m_pProperties.Delete(1);
+    m_pProperties.Delete(0);
+    if (ATOMID(GetType()) == ATOMID("alac")) {
+      AddProperty(new MP4BytesProperty("decoderConfig", m_size));
+      ReadProperties();
+    }
+    if (m_pChildAtomInfos.Size() > 0) {
+      ReadChildAtoms();
+    }
+  } else {
+    ReadProperties(0, 3); // read first 3 properties
+    AddProperties(((MP4IntegerProperty *)m_pProperties[2])->GetValue());
+    ReadProperties(3); // continue
+    if (m_pChildAtomInfos.Size() > 0) {
+      ReadChildAtoms();
+    }
+  }
+  Skip();
+}
--- /dev/null
+++ b/common/mp4v2/atom_standard.cpp
@@ -1,0 +1,463 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2004.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Bill May (from others work).
+ */
+
+#include "mp4common.h"
+#include "atoms.h"
+
+static const char name[5]={0251,'n', 'a', 'm', '\0'};
+static const char art[5]={0251,'A', 'R', 'T', '\0'};
+static const char wrt[5]={0251,'w', 'r', 't', '\0'};
+static const char alb[5]={0251,'a', 'l', 'b', '\0'};
+static const char day[5]={0251,'d', 'a', 'y', '\0'};
+static const char too[5]={0251,'t', 'o', 'o', '\0'};
+static const char cmt[5]={0251,'c', 'm', 't', '\0'};
+static const char gen[5]={0251,'g', 'e', 'n', '\0'};
+static const char grp[5]={0251,'g', 'r', 'p', '\0'};
+
+MP4StandardAtom::MP4StandardAtom (const char *type) : MP4Atom(type)
+{
+  /*
+   * This is a big if else loop.  Make sure that you don't break it 
+   * when adding new atoms, or you will set the unknown type flag
+   *
+   * Try to keep it in alphabetical order - it should only be called
+   * 1 time per atom, so it's not that urgent.
+   */
+  if (ATOMID(type) == ATOMID("aART") ||
+      ATOMID(type) == ATOMID("akID") ||
+      ATOMID(type) == ATOMID("apID") ||
+      ATOMID(type) == ATOMID("atID")) {
+      ExpectChildAtom("data", Required, OnlyOne);
+  /*
+   * b???
+   */
+  } else if (ATOMID(type) == ATOMID("bitr")) {
+    AddProperty( /* 0 */
+		new MP4Integer32Property("avgBitrate"));
+    
+    AddProperty( /* 1 */
+		new MP4Integer32Property("maxBitrate"));
+
+  } else if (ATOMID(type) == ATOMID("btrt")) {
+    AddProperty( new MP4Integer32Property("bufferSizeDB")); /* 0 */
+    AddProperty( new MP4Integer32Property("avgBitrate"));   /* 1 */
+    AddProperty( new MP4Integer32Property("maxBitrate"));   /* 2 */
+  } else if (ATOMID(type) == ATOMID("burl")) {
+    AddProperty( new MP4StringProperty("base_url"));
+  /*
+   * c???
+   */
+  } else if (ATOMID(type) == ATOMID("co64")) {
+    AddVersionAndFlags();
+    
+    MP4Integer32Property* pCount = 
+      new MP4Integer32Property("entryCount"); 
+    AddProperty(pCount);
+    
+    MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
+    AddProperty(pTable);
+    
+    pTable->AddProperty(
+			new MP4Integer64Property("chunkOffset"));
+
+  } else if (ATOMID(type) == ATOMID("cpil")) {
+    ExpectChildAtom("data", Required, OnlyOne);
+  } else if (ATOMID(type) == ATOMID("covr")) { /* Apple iTunes */
+    ExpectChildAtom("data", Required, Many);
+  } else if (ATOMID(type) == ATOMID("cprt") ||
+	     ATOMID(type) == ATOMID("cnID")) {
+#if 0
+    AddVersionAndFlags();
+    AddProperty(
+		new MP4Integer16Property("language"));
+    AddProperty(
+		new MP4StringProperty("notice"));
+#else
+    ExpectChildAtom("data", Required, OnlyOne);
+#endif
+
+  } else if (ATOMID(type) == ATOMID("ctts")) {
+    AddVersionAndFlags();
+    
+    MP4Integer32Property* pCount = 
+      new MP4Integer32Property("entryCount"); 
+    AddProperty(pCount);
+    
+    MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
+    AddProperty(pTable);
+    
+    pTable->AddProperty(new MP4Integer32Property("sampleCount"));
+    pTable->AddProperty(new MP4Integer32Property("sampleOffset"));
+  /*
+   * d???
+   */
+  } else if (ATOMID(type) == ATOMID("dinf")) {
+    ExpectChildAtom("dref", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("dimm")) {
+    AddProperty( // bytes of immediate data
+		new MP4Integer64Property("bytes"));
+
+  } else if (ATOMID(type) == ATOMID("disk")) { /* Apple iTunes */
+    ExpectChildAtom("data", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("dmax")) {
+    AddProperty( // max packet duration 
+		new MP4Integer32Property("milliSecs"));
+
+  } else if (ATOMID(type) == ATOMID("dmed")) {
+    AddProperty( // bytes sent from media data
+		new MP4Integer64Property("bytes"));
+
+  } else if (ATOMID(type) == ATOMID("drep")) {
+    AddProperty( // bytes of repeated data
+		new MP4Integer64Property("bytes"));
+  /*
+   * e???
+   */
+  } else if (ATOMID(type) == ATOMID("edts")) {
+    ExpectChildAtom("elst", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("esds")) {
+    AddVersionAndFlags();
+    AddProperty(
+		new MP4DescriptorProperty(NULL, MP4ESDescrTag, 0, 
+					  Required, OnlyOne));
+  /*
+   * f???
+   */
+  } else if (ATOMID(type) == ATOMID("frma")) {
+    AddProperty( /* 0 */
+                new MP4Integer32Property("data-format"));			
+  /*
+   * g???
+   */
+  } else if (ATOMID(type) == ATOMID("gmhd")) { 
+    ExpectChildAtom("gmin", Required, OnlyOne);
+    ExpectChildAtom("tmcd", Optional, OnlyOne);
+    ExpectChildAtom("text", Optional, OnlyOne);
+  } else if (ATOMID(type) == ATOMID("gnre") ||
+	     ATOMID(type) == ATOMID("geID")) { // Apple iTunes 
+    ExpectChildAtom("data", Optional, OnlyOne);
+
+  /*
+   * h???
+   */
+  } else if (ATOMID(type) == ATOMID("hmhd")) {
+    AddVersionAndFlags();
+    
+    AddProperty(new MP4Integer16Property("maxPduSize")); 
+    AddProperty(new MP4Integer16Property("avgPduSize")); 
+    AddProperty(new MP4Integer32Property("maxBitRate")); 
+    AddProperty(new MP4Integer32Property("avgBitRate")); 
+    AddProperty(new MP4Integer32Property("slidingAvgBitRate")); 
+  /*
+   * i???
+   */
+  } else if (ATOMID(type) == ATOMID("iKMS")) {
+    AddVersionAndFlags(); /* 0, 1 */
+    MP4StringProperty* pProp = new MP4StringProperty("kms_URI");
+    AddProperty(pProp); /* 2 */
+
+  } else if (ATOMID(type) == ATOMID("iSFM")) {
+    AddVersionAndFlags(); /* 0, 1 */
+    AddProperty( /* 2 */
+		new MP4BitfieldProperty("selective-encryption", 1));
+    AddProperty( /* 3 */
+		new MP4BitfieldProperty("reserved", 7));
+    AddProperty( /* 4 */
+		new MP4Integer8Property("key-indicator-length"));	
+    AddProperty( /* 5 */
+		new MP4Integer8Property("IV-length"));	
+
+  } else if (ATOMID(type) == ATOMID("ilst")) {
+    ExpectChildAtom("\251nam", Optional, OnlyOne); /* name */
+    ExpectChildAtom("\251ART", Optional, OnlyOne); /* artist */
+    ExpectChildAtom("\251wrt", Optional, OnlyOne); /* writer */
+    ExpectChildAtom("\251alb", Optional, OnlyOne); /* album */
+    ExpectChildAtom("\251day", Optional, OnlyOne); /* date */
+    ExpectChildAtom("\251too", Optional, OnlyOne); /* tool */
+    ExpectChildAtom("\251cmt", Optional, OnlyOne); /* comment */
+    ExpectChildAtom("\251gen", Optional, OnlyOne); /* custom genre */
+    ExpectChildAtom("trkn", Optional, OnlyOne); /* tracknumber */
+    ExpectChildAtom("disk", Optional, OnlyOne); /* disknumber */
+    ExpectChildAtom("gnre", Optional, OnlyOne); /* genre (ID3v1 index + 1) */
+    ExpectChildAtom("cpil", Optional, OnlyOne); /* compilation */
+    ExpectChildAtom("tmpo", Optional, OnlyOne); /* BPM */
+    ExpectChildAtom("covr", Optional, OnlyOne); /* cover art */
+    ExpectChildAtom("aART", Optional, OnlyOne); /* album artist */
+    ExpectChildAtom("----", Optional, Many); /* ---- free form */
+    ExpectChildAtom("pgap", Optional, OnlyOne); /* part of gapless album */
+
+  }  else if (ATOMID(type) == ATOMID("imif")) {
+    AddVersionAndFlags();
+    AddProperty(new MP4DescriptorProperty("ipmp_desc", MP4IPMPDescrTag,
+					  MP4IPMPDescrTag, Required, Many));
+  } else if (ATOMID(type) == ATOMID("iods")) {
+    AddVersionAndFlags();
+    AddProperty(
+		new MP4DescriptorProperty(NULL, MP4FileIODescrTag, 
+					  MP4FileODescrTag, 
+					  Required, OnlyOne));
+  /*
+   * m???
+   */
+  } else if (ATOMID(type) == ATOMID("maxr")) {
+    AddProperty(new MP4Integer32Property("granularity"));
+    AddProperty(new MP4Integer32Property("bytes"));
+
+  } else if (ATOMID(type) == ATOMID("mdia")) {
+    ExpectChildAtom("mdhd", Required, OnlyOne);
+    ExpectChildAtom("hdlr", Required, OnlyOne);
+    ExpectChildAtom("minf", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("meta")) { // iTunes
+    AddVersionAndFlags(); /* 0, 1 */
+    ExpectChildAtom("hdlr", Required, OnlyOne);
+    ExpectChildAtom("ilst", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("mfhd")) {
+    AddVersionAndFlags();	/* 0, 1 */
+    AddProperty( /* 2 */
+		new MP4Integer32Property("sequenceNumber"));
+
+  } else if (ATOMID(type) == ATOMID("minf")) {
+    ExpectChildAtom("vmhd", Optional, OnlyOne);
+    ExpectChildAtom("smhd", Optional, OnlyOne);
+    ExpectChildAtom("hmhd", Optional, OnlyOne);
+    ExpectChildAtom("nmhd", Optional, OnlyOne);
+    ExpectChildAtom("gmhd", Optional, OnlyOne);
+    ExpectChildAtom("dinf", Required, OnlyOne);
+    ExpectChildAtom("stbl", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("moof")) {
+    ExpectChildAtom("mfhd", Required, OnlyOne);
+    ExpectChildAtom("traf", Optional, Many);
+
+  } else if (ATOMID(type) == ATOMID("moov")) {
+    ExpectChildAtom("mvhd", Required, OnlyOne);
+    ExpectChildAtom("iods", Optional, OnlyOne);
+    ExpectChildAtom("trak", Required, Many);
+    ExpectChildAtom("udta", Optional, Many);
+    ExpectChildAtom("mvex", Optional, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("mvex")) {
+    ExpectChildAtom("trex", Required, Many);
+
+  /*
+   * n???
+   */
+  } else if (ATOMID(type) == ATOMID("nmhd")) {
+    AddVersionAndFlags();
+
+  } else if (ATOMID(type) == ATOMID("nump")) {
+    AddProperty( // packets sent
+		new MP4Integer64Property("packets"));
+  /*
+    * o???
+    */
+  } else if (ATOMID(type) == ATOMID("odkm")) {
+    AddVersionAndFlags();
+    ExpectChildAtom("ohdr", Required, OnlyOne);
+  /*
+   * p???
+   */
+  } else if (ATOMID(type) == ATOMID("payt")) {
+    AddProperty(new MP4Integer32Property("payloadNumber"));
+    AddProperty(new MP4StringProperty("rtpMap", Counted));
+
+  } else if (ATOMID(type) == ATOMID("pinf")) {
+    ExpectChildAtom("frma", Required, OnlyOne);
+  } else if (ATOMID(type) == ATOMID("pmax")) {
+    AddProperty( // max packet size 
+		new MP4Integer32Property("bytes"));
+  } else if (ATOMID(type) == ATOMID("pgap") ||
+	     ATOMID(type) == ATOMID("plID") ||
+	     ATOMID(type) == ATOMID("purd") ||
+	     ATOMID(type) == ATOMID("rtng")) {
+    ExpectChildAtom("data", Required, OnlyOne);
+  /*
+   * s???
+   */
+  } else if (ATOMID(type) == ATOMID("schi")) {
+    // not sure if this is child atoms or table of boxes
+    // get clarification on spec 9.1.2.5
+    ExpectChildAtom("odkm", Optional, OnlyOne);
+    ExpectChildAtom("iKMS", Optional, OnlyOne);
+    ExpectChildAtom("iSFM", Optional, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("schm")) {
+    AddVersionAndFlags(); /* 0, 1 */
+    AddProperty( /* 2 */
+                new MP4Integer32Property("scheme_type"));
+    AddProperty( /* 3 */
+	        new MP4Integer32Property("scheme_version"));
+    // browser URI if flags set, TODO
+
+  } else if (ATOMID(type) == ATOMID("sinf")) {
+    ExpectChildAtom("frma", Required, OnlyOne);
+    ExpectChildAtom("imif", Optional, OnlyOne);
+    ExpectChildAtom("schm", Optional, OnlyOne);
+    ExpectChildAtom("schi", Optional, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("smhd")) {
+    AddVersionAndFlags();
+    AddReserved("reserved", 4);
+
+  } else if (ATOMID(type) == ATOMID("snro")) {
+    AddProperty(new MP4Integer32Property("offset"));
+
+  } else if (ATOMID(type) == ATOMID("stco")) {
+    AddVersionAndFlags();
+
+    MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); 
+    AddProperty(pCount);
+
+    MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
+    AddProperty(pTable);
+
+    pTable->AddProperty(new MP4Integer32Property("chunkOffset"));
+
+  } else if (ATOMID(type) == ATOMID("stsh")) {
+    AddVersionAndFlags();
+
+    MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); 
+    AddProperty(pCount);
+
+    MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
+    AddProperty(pTable);
+
+    pTable->AddProperty(new MP4Integer32Property("shadowedSampleNumber"));
+    pTable->AddProperty(new MP4Integer32Property("syncSampleNumber"));
+
+  } else if (ATOMID(type) == ATOMID("stss")) {
+    AddVersionAndFlags();
+
+    MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); 
+    AddProperty(pCount);
+
+    MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
+    AddProperty(pTable);
+
+    pTable->AddProperty(new MP4Integer32Property("sampleNumber"));
+
+  } else if (ATOMID(type) == ATOMID("stts")) {
+    AddVersionAndFlags();
+    MP4Integer32Property* pCount = new MP4Integer32Property("entryCount"); 
+    AddProperty(pCount);
+
+    MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
+    AddProperty(pTable);
+
+    pTable->AddProperty(new MP4Integer32Property("sampleCount"));
+    pTable->AddProperty(new MP4Integer32Property("sampleDelta"));
+  } else if (ATOMID(type) == ATOMID("sfID") ||
+	     ATOMID(type) == ATOMID("stik")) {
+    ExpectChildAtom("data", Required, OnlyOne);
+  /*
+   * t???
+   */
+  } else if (ATOMID(type) == ATOMID("tims")) {
+    AddProperty( 
+		new MP4Integer32Property("timeScale"));
+
+  } else if (ATOMID(type) == ATOMID("tmin")) {
+    AddProperty( // min relative xmit time
+		new MP4Integer32Property("milliSecs"));
+
+  } else if (ATOMID(type) == ATOMID("tmax")) {
+    AddProperty( // max relative xmit time
+		new MP4Integer32Property("milliSecs"));
+
+  } else if (ATOMID(type) == ATOMID("tmpo")) { // iTunes
+    ExpectChildAtom("data", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("traf")) {
+    ExpectChildAtom("tfhd", Required, OnlyOne);
+    ExpectChildAtom("trun", Optional, Many);
+
+  } else if (ATOMID(type) == ATOMID("trak")) {
+    ExpectChildAtom("tkhd", Required, OnlyOne);
+    ExpectChildAtom("tref", Optional, OnlyOne);
+    ExpectChildAtom("edts", Optional, OnlyOne);
+    ExpectChildAtom("mdia", Required, OnlyOne);
+    ExpectChildAtom("udta", Optional, Many);
+
+  } else if (ATOMID(type) == ATOMID("tref")) {
+    ExpectChildAtom("chap", Optional, OnlyOne);
+    ExpectChildAtom("dpnd", Optional, OnlyOne);
+    ExpectChildAtom("hint", Optional, OnlyOne);
+    ExpectChildAtom("ipir", Optional, OnlyOne);
+    ExpectChildAtom("mpod", Optional, OnlyOne);
+    ExpectChildAtom("sync", Optional, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("trex")) {
+    AddVersionAndFlags();	/* 0, 1 */
+    AddProperty( /* 2 */
+		new MP4Integer32Property("trackId"));
+    AddProperty( /* 3 */
+		new MP4Integer32Property("defaultSampleDesriptionIndex"));
+    AddProperty( /* 4 */
+		new MP4Integer32Property("defaultSampleDuration"));
+    AddProperty( /* 5 */
+		new MP4Integer32Property("defaultSampleSize"));
+    AddProperty( /* 6 */
+		new MP4Integer32Property("defaultSampleFlags"));
+
+  } else if (ATOMID(type) == ATOMID("trkn")) { // iTunes
+    ExpectChildAtom("data", Required, OnlyOne);
+
+  } else if (ATOMID(type) == ATOMID("trpy") ||
+	     ATOMID(type) == ATOMID("tpyl")) {
+    AddProperty( // bytes sent including RTP headers
+		new MP4Integer64Property("bytes"));
+
+  } else if (ATOMID(type) == ATOMID("tsro")) {
+    AddProperty( 
+		new MP4Integer32Property("offset"));
+  } else if (ATOMID(type) == ATOMID("wave")) {
+    ExpectChildAtom("esds", Required, OnlyOne);
+  /*
+   * copyright???
+   */
+  } else if (ATOMID(type) == ATOMID(art) ||
+	     ATOMID(type) == ATOMID(wrt) ||
+	     ATOMID(type) == ATOMID(alb) ||
+	     ATOMID(type) == ATOMID(day) ||
+	     ATOMID(type) == ATOMID(too) ||
+	     ATOMID(type) == ATOMID(gen) ||
+	     ATOMID(type) == ATOMID(grp)) { /* Apple iTunes */
+    ExpectChildAtom("data", Required, OnlyOne);
+  /*
+   * ---- 
+   */
+  } else if (ATOMID(type) == ATOMID("----")) { /* Apple iTunes */
+    ExpectChildAtom("mean", Required, OnlyOne);
+    ExpectChildAtom("name", Required, OnlyOne);
+    ExpectChildAtom("data", Required, OnlyOne);
+  } else {
+  /*
+   * default - unknown type
+   */
+    SetUnknownType(true);
+  }
+  
+}
--- a/common/mp4v2/atom_stbl.cpp
+++ b/common/mp4v2/atom_stbl.cpp
@@ -28,6 +28,7 @@
 	ExpectChildAtom("stts", Required, OnlyOne);
 	ExpectChildAtom("ctts", Optional, OnlyOne);
 	ExpectChildAtom("stsz", Required, OnlyOne);
+	ExpectChildAtom("stz2", Optional, OnlyOne);
 	ExpectChildAtom("stsc", Required, OnlyOne);
 	ExpectChildAtom("stco", Optional, OnlyOne);
 	ExpectChildAtom("co64", Optional, OnlyOne);
--- a/common/mp4v2/atom_stco.cpp
+++ /dev/null
@@ -1,38 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4StcoAtom::MP4StcoAtom() 
-	: MP4Atom("stco") 
-{
-	AddVersionAndFlags();
-
-	MP4Integer32Property* pCount = 
-		new MP4Integer32Property("entryCount"); 
-	AddProperty(pCount);
-
-	MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
-	AddProperty(pTable);
-
-	pTable->AddProperty(
-		new MP4Integer32Property("chunkOffset"));
-}
--- a/common/mp4v2/atom_stsd.cpp
+++ b/common/mp4v2/atom_stsd.cpp
@@ -48,6 +48,9 @@
  	ExpectChildAtom("samr", Optional, Many); // For AMR-NB
  	ExpectChildAtom("sawb", Optional, Many); // For AMR-WB
  	ExpectChildAtom("s263", Optional, Many); // For H.263
+	ExpectChildAtom("avc1", Optional, Many);
+	ExpectChildAtom("alac", Optional, Many);
+	ExpectChildAtom("text", Optional, Many);
 }
 
 void MP4StsdAtom::Read() 
--- a/common/mp4v2/atom_stsh.cpp
+++ /dev/null
@@ -1,40 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4StshAtom::MP4StshAtom() 
-	: MP4Atom("stsh") 
-{
-	AddVersionAndFlags();
-
-	MP4Integer32Property* pCount = 
-		new MP4Integer32Property("entryCount"); 
-	AddProperty(pCount);
-
-	MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
-	AddProperty(pTable);
-
-	pTable->AddProperty(
-		new MP4Integer32Property("shadowedSampleNumber"));
-	pTable->AddProperty(
-		new MP4Integer32Property("syncSampleNumber"));
-}
--- a/common/mp4v2/atom_stss.cpp
+++ /dev/null
@@ -1,38 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4StssAtom::MP4StssAtom() 
-	: MP4Atom("stss") 
-{
-	AddVersionAndFlags();
-
-	MP4Integer32Property* pCount = 
-		new MP4Integer32Property("entryCount"); 
-	AddProperty(pCount);
-
-	MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
-	AddProperty(pTable);
-
-	pTable->AddProperty(
-		new MP4Integer32Property("sampleNumber"));
-}
--- a/common/mp4v2/atom_stsz.cpp
+++ b/common/mp4v2/atom_stsz.cpp
@@ -37,7 +37,7 @@
 	AddProperty(pTable); /* 4 */
 
 	pTable->AddProperty( /* 4/0 */
-		new MP4Integer32Property("sampleSize"));
+		new MP4Integer32Property("entrySize"));
 }
 
 void MP4StszAtom::Read() 
--- a/common/mp4v2/atom_stts.cpp
+++ /dev/null
@@ -1,40 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4SttsAtom::MP4SttsAtom() 
-	: MP4Atom("stts") 
-{
-	AddVersionAndFlags();
-
-	MP4Integer32Property* pCount = 
-		new MP4Integer32Property("entryCount"); 
-	AddProperty(pCount);
-
-	MP4TableProperty* pTable = new MP4TableProperty("entries", pCount);
-	AddProperty(pTable);
-
-	pTable->AddProperty(
-		new MP4Integer32Property("sampleCount"));
-	pTable->AddProperty(
-		new MP4Integer32Property("sampleDelta"));
-}
--- /dev/null
+++ b/common/mp4v2/atom_stz2.cpp
@@ -1,0 +1,95 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Dave Mackie		[email protected]
+ */
+
+#include "mp4common.h"
+
+/*
+ * This is used for the 4 bit sample size below.  We need the sampleCount
+ * to be correct for the number of samples, but the table size needs to
+ * be correct to read and write it.
+ */
+
+class MP4HalfSizeTableProperty : public MP4TableProperty
+{
+public:
+  MP4HalfSizeTableProperty(char *name, MP4IntegerProperty *pCountProperty) :
+    MP4TableProperty(name, pCountProperty) {};
+
+  // The count is half the actual size
+  u_int32_t GetCount() {
+    return (m_pCountProperty->GetValue() + 1)/ 2;
+  };
+  void SetCount(u_int32_t count) {
+    m_pCountProperty->SetValue(count * 2);
+  };
+};
+
+
+MP4Stz2Atom::MP4Stz2Atom() 
+	: MP4Atom("stz2") 
+{
+	AddVersionAndFlags(); /* 0, 1 */
+
+	AddReserved("reserved", 3); /* 2 */
+
+	AddProperty( /* 3 */
+		new MP4Integer8Property("fieldSize")); 
+
+	MP4Integer32Property* pCount = 
+		new MP4Integer32Property("sampleCount"); 
+	AddProperty(pCount); /* 4 */
+
+}
+
+void MP4Stz2Atom::Read() 
+{
+	ReadProperties(0, 4);
+
+	uint8_t fieldSize = 
+	  ((MP4Integer8Property *)m_pProperties[3])->GetValue();
+	//	uint32_t sampleCount = 0;
+
+	MP4Integer32Property* pCount = 
+	  (MP4Integer32Property *)m_pProperties[4]; 
+
+	MP4TableProperty *pTable;
+	if (fieldSize != 4) {
+	  pTable = new MP4TableProperty("entries", pCount);
+	} else {
+	  // 4 bit field size uses a special table.
+	  pTable = new MP4HalfSizeTableProperty("entries", pCount);
+	}
+
+	AddProperty(pTable);
+
+	if (fieldSize == 16) {
+	  pTable->AddProperty( /* 5/0 */
+			      new MP4Integer16Property("entrySize"));
+	} else {
+	  pTable->AddProperty( /* 5/0 */
+			      new MP4Integer8Property("entrySize"));
+	}
+	  
+	ReadProperties(4);
+
+	Skip();	// to end of atom
+}
+
--- /dev/null
+++ b/common/mp4v2/atom_text.cpp
@@ -1,0 +1,138 @@
+/*
+ * 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.
+ * 
+ * Contributer has declined to give copyright information, and gives
+ * it freely to the world.
+ */
+
+#include "mp4common.h"
+
+MP4TextAtom::MP4TextAtom() 
+	: MP4Atom("text") 
+{
+	// The atom type "text" is used in two complete unrelated ways
+	// i.e. it's real two atoms with the same name
+	// To handle that we need to postpone property creation until
+	// we know who our parent atom is (stsd or gmhd) which gives us
+	// the context info we need to know who we are
+}
+
+void MP4TextAtom::AddPropertiesStsdType()
+{
+
+	AddReserved("reserved1", 6); /* 0 */
+
+	AddProperty(new MP4Integer16Property("dataReferenceIndex"));/* 1 */
+
+	AddProperty(new MP4Integer32Property("displayFlags")); /* 2 */
+	AddProperty(new MP4Integer32Property("textJustification")); /* 3 */
+
+	AddProperty(new MP4Integer16Property("bgColorRed")); /* 4 */
+	AddProperty(new MP4Integer16Property("bgColorGreen")); /* 5 */
+	AddProperty(new MP4Integer16Property("bgColorBlue")); /* 6 */
+
+	AddProperty(new MP4Integer16Property("defTextBoxTop")); /* 7 */
+	AddProperty(new MP4Integer16Property("defTextBoxLeft")); /* 8 */
+	AddProperty(new MP4Integer16Property("defTextBoxBottom")); /* 9 */
+	AddProperty(new MP4Integer16Property("defTextBoxRight")); /* 10 */
+
+	AddReserved("reserved2", 8); /* 11 */
+
+	AddProperty(new MP4Integer16Property("fontNumber")); /* 12 */
+	AddProperty(new MP4Integer16Property("fontFace")); /* 13 */
+
+	AddReserved("reserved3", 1); /* 14 */
+	AddReserved("reserved4", 2); /* 15 */
+
+	AddProperty(new MP4Integer16Property("foreColorRed")); /* 16 */
+	AddProperty(new MP4Integer16Property("foreColorGreen")); /* 17 */
+	AddProperty(new MP4Integer16Property("foreColorBlue")); /* 18 */
+
+}
+
+void MP4TextAtom::AddPropertiesGmhdType()
+{
+
+	AddProperty(new MP4BytesProperty("textData", 36)); /* 0 */
+
+}
+
+
+void MP4TextAtom::Generate()
+{
+
+	if (ATOMID(m_pParentAtom->GetType()) == ATOMID("stsd")) {
+		AddPropertiesStsdType();
+		GenerateStsdType();
+	} else if (ATOMID(m_pParentAtom->GetType()) == ATOMID("gmhd")) {
+		AddPropertiesGmhdType();
+		GenerateGmhdType();
+	} else {
+		VERBOSE_WARNING(m_pFile->GetVerbosity(),
+			printf("Warning: text atom in unexpected context, can not generate"));
+	}
+
+}
+
+void MP4TextAtom::GenerateStsdType() 
+{
+	// generate children
+	MP4Atom::Generate();
+
+	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+	((MP4Integer32Property*)m_pProperties[2])->SetValue(1);
+	((MP4Integer32Property*)m_pProperties[3])->SetValue(1);
+
+}
+
+void MP4TextAtom::GenerateGmhdType() 
+{
+	MP4Atom::Generate();
+
+	// property 0 has non-zero fixed values
+	static u_int8_t textData[36] = {
+		0x00, 0x01, 
+		0x00, 0x00,
+		0x00, 0x00,
+		0x00, 0x00,
+		0x00, 0x00, 
+		0x00, 0x00,
+		0x00, 0x00, 
+		0x00, 0x00,
+		0x00, 0x01, 
+		0x00, 0x00,
+		0x00, 0x00, 
+		0x00, 0x00,
+		0x00, 0x00, 
+		0x00, 0x00,
+		0x00, 0x00, 
+		0x00, 0x00,
+		0x40, 0x00, 
+		0x00, 0x00, 
+	};
+	((MP4BytesProperty*)m_pProperties[0])->SetValue(textData, sizeof(textData));
+	
+}
+
+void MP4TextAtom::Read ()
+{
+  if (ATOMID(m_pParentAtom->GetType()) == ATOMID("stsd")) {
+    AddPropertiesStsdType();
+  } else if (ATOMID(m_pParentAtom->GetType()) == ATOMID("gmhd")) {
+    AddPropertiesGmhdType();
+  }
+   
+  MP4Atom::Read();
+}
+
--- a/common/mp4v2/atom_tims.cpp
+++ /dev/null
@@ -1,30 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TimsAtom::MP4TimsAtom() 
-	: MP4Atom("tims") 
-{
-	AddProperty( 
-		new MP4Integer32Property("timeScale"));
-}
-
--- a/common/mp4v2/atom_tkhd.cpp
+++ b/common/mp4v2/atom_tkhd.cpp
@@ -61,15 +61,17 @@
 	pProp->SetFixed16Format();
 	AddProperty(pProp); /* 8 */
 
-	AddReserved("reserved3", 38); /* 9 */
+	AddReserved("reserved3", 2); /* 9 */
 
+	AddProperty(new MP4BytesProperty("matrix", 36)); /* 10 */
+
 	pProp = new MP4Float32Property("width");
 	pProp->SetFixed32Format();
-	AddProperty(pProp); /* 10 */
+	AddProperty(pProp); /* 11 */
 
 	pProp = new MP4Float32Property("height");
 	pProp->SetFixed32Format();
-	AddProperty(pProp); /* 11 */
+	AddProperty(pProp); /* 12 */
 }
 
 void MP4TkhdAtom::Generate() 
@@ -90,9 +92,14 @@
 		((MP4Integer32Property*)m_pProperties[3])->SetValue(now);
 	}
 
-	// property reserved3 has non-zero fixed values
-	static u_int8_t reserved3[38] = {
-		0x00, 0x00, 
+	// property "matrix" has non-zero fixed values
+	// this default identity matrix indicates no transformation, i.e.
+	// 1, 0, 0
+	// 0, 1, 0
+	// 0, 0, 1
+	// see http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap4/chapter_5_section_4.html
+
+	static u_int8_t matrix[36] = {
 		0x00, 0x01, 0x00, 0x00, 
 		0x00, 0x00, 0x00, 0x00, 
 		0x00, 0x00, 0x00, 0x00, 
@@ -103,10 +110,9 @@
 		0x00, 0x00, 0x00, 0x00, 
 		0x40, 0x00, 0x00, 0x00, 
 	};
-	m_pProperties[9]->SetReadOnly(false);
-	((MP4BytesProperty*)m_pProperties[9])->
-		SetValue(reserved3, sizeof(reserved3));
-	m_pProperties[9]->SetReadOnly(true);
+
+	((MP4BytesProperty*)m_pProperties[10])->
+		SetValue(matrix, sizeof(matrix));
 }
 
 void MP4TkhdAtom::Read() 
--- a/common/mp4v2/atom_tmax.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TmaxAtom::MP4TmaxAtom() 
-	: MP4Atom("tmax") 
-{
-	AddProperty( // max relative xmit time
-		new MP4Integer32Property("milliSecs"));
-}
--- a/common/mp4v2/atom_tmin.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TminAtom::MP4TminAtom() 
-	: MP4Atom("tmin") 
-{
-	AddProperty( // min relative xmit time
-		new MP4Integer32Property("milliSecs"));
-}
--- a/common/mp4v2/atom_tpyl.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TpylAtom::MP4TpylAtom() 
-	: MP4Atom("tpyl") 
-{
-	AddProperty( // bytes sent of RTP payload data
-		new MP4Integer64Property("bytes"));
-}
--- a/common/mp4v2/atom_traf.cpp
+++ /dev/null
@@ -1,30 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TrafAtom::MP4TrafAtom() 
-	: MP4Atom("traf")
-{
-	ExpectChildAtom("tfhd", Required, OnlyOne);
-	ExpectChildAtom("trun", Optional, Many);
-}
-
--- a/common/mp4v2/atom_trak.cpp
+++ /dev/null
@@ -1,32 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TrakAtom::MP4TrakAtom() 
-	: MP4Atom("trak") 
-{
-	ExpectChildAtom("tkhd", Required, OnlyOne);
-	ExpectChildAtom("tref", Optional, OnlyOne);
-	ExpectChildAtom("edts", Optional, OnlyOne);
-	ExpectChildAtom("mdia", Required, OnlyOne);
-	ExpectChildAtom("udta", Optional, Many);
-}
--- a/common/mp4v2/atom_tref.cpp
+++ /dev/null
@@ -1,32 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TrefAtom::MP4TrefAtom() 
-	: MP4Atom("tref")
-{
-	ExpectChildAtom("dpnd", Optional, OnlyOne);
-	ExpectChildAtom("hint", Optional, OnlyOne);
-	ExpectChildAtom("ipir", Optional, OnlyOne);
-	ExpectChildAtom("mpod", Optional, OnlyOne);
-	ExpectChildAtom("sync", Optional, OnlyOne);
-}
--- a/common/mp4v2/atom_trex.cpp
+++ /dev/null
@@ -1,39 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TrexAtom::MP4TrexAtom() 
-	: MP4Atom("trex")
-{
-	AddVersionAndFlags();	/* 0, 1 */
-	AddProperty( /* 2 */
-		new MP4Integer32Property("trackId"));
-	AddProperty( /* 3 */
-		new MP4Integer32Property("defaultSampleDesriptionIndex"));
-	AddProperty( /* 4 */
-		new MP4Integer32Property("defaultSampleDuration"));
-	AddProperty( /* 5 */
-		new MP4Integer32Property("defaultSampleSize"));
-	AddProperty( /* 6 */
-		new MP4Integer32Property("defaultSampleFlags"));
-}
-
--- a/common/mp4v2/atom_trpy.cpp
+++ /dev/null
@@ -1,29 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TrpyAtom::MP4TrpyAtom() 
-	: MP4Atom("trpy") 
-{
-	AddProperty( // bytes sent including RTP headers
-		new MP4Integer64Property("bytes"));
-}
--- a/common/mp4v2/atom_trun.cpp
+++ b/common/mp4v2/atom_trun.cpp
@@ -42,7 +42,8 @@
 	}
 
 	MP4TableProperty* pTable = 
-		new MP4TableProperty("samples", m_pProperties[2]);
+	  new MP4TableProperty("samples", 
+			       (MP4Integer32Property *)m_pProperties[2]);
 	AddProperty(pTable);
 
 	if (flags & 0x100) {
--- a/common/mp4v2/atom_tsro.cpp
+++ /dev/null
@@ -1,30 +1,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is MPEG4IP.
- * 
- * The Initial Developer of the Original Code is Cisco Systems Inc.
- * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
- * 
- * Contributor(s): 
- *		Dave Mackie		[email protected]
- */
-
-#include "mp4common.h"
-
-MP4TsroAtom::MP4TsroAtom() 
-	: MP4Atom("tsro") 
-{
-	AddProperty( 
-		new MP4Integer32Property("offset"));
-}
-
--- a/common/mp4v2/atom_udta.cpp
+++ b/common/mp4v2/atom_udta.cpp
@@ -27,6 +27,11 @@
 	ExpectChildAtom("cprt", Optional, Many);
 	ExpectChildAtom("hnti", Optional, OnlyOne);
 	ExpectChildAtom("meta", Optional, OnlyOne);
+	ExpectChildAtom("\251cpy", Optional, OnlyOne);
+	ExpectChildAtom("\251des", Optional, OnlyOne);
+	ExpectChildAtom("\251nam", Optional, OnlyOne);
+	ExpectChildAtom("\251cmt", Optional, OnlyOne);
+	ExpectChildAtom("\251prd", Optional, OnlyOne);
 }
 
 void MP4UdtaAtom::Read() 
--- a/common/mp4v2/atom_url.cpp
+++ b/common/mp4v2/atom_url.cpp
@@ -21,8 +21,8 @@
 
 #include "mp4common.h"
 
-MP4UrlAtom::MP4UrlAtom() 
-	: MP4Atom("url ")
+MP4UrlAtom::MP4UrlAtom(const char *type) 
+	: MP4Atom(type)
 {
 	AddVersionAndFlags();
 	AddProperty(new MP4StringProperty("location"));
--- /dev/null
+++ b/common/mp4v2/atom_video.cpp
@@ -1,0 +1,78 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2004.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Bill May  [email protected]
+ */
+
+#include "mp4common.h"
+
+MP4VideoAtom::MP4VideoAtom (const char *type) 
+	: MP4Atom(type)
+{
+	AddReserved("reserved1", 6); /* 0 */
+
+	AddProperty( /* 1 */
+		new MP4Integer16Property("dataReferenceIndex"));
+
+	AddReserved("reserved2", 16); /* 2 */
+
+	AddProperty( /* 3 */
+		new MP4Integer16Property("width"));
+	AddProperty( /* 4 */
+		new MP4Integer16Property("height"));
+
+	AddReserved("reserved3", 14); /* 5 */
+
+	MP4StringProperty* pProp = 
+		new MP4StringProperty("compressorName");
+	pProp->SetFixedLength(32);
+	pProp->SetValue("");
+	AddProperty(pProp); /* 6 */
+
+	AddProperty(/* 7 */
+		    new MP4Integer16Property("depth"));
+	AddProperty(/* 8 */
+		    new MP4Integer16Property("colorTableId"));
+	ExpectChildAtom("smi ", Optional, OnlyOne);
+}
+
+void MP4VideoAtom::Generate()
+{
+	MP4Atom::Generate();
+
+	((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+	// property reserved3 has non-zero fixed values
+	static u_int8_t reserved3[14] = {
+		0x00, 0x48, 0x00, 0x00, 
+		0x00, 0x48, 0x00, 0x00, 
+		0x00, 0x00, 0x00, 0x00, 
+		0x00, 0x01,
+	};
+	m_pProperties[5]->SetReadOnly(false);
+	((MP4BytesProperty*)m_pProperties[5])->
+		SetValue(reserved3, sizeof(reserved3));
+	m_pProperties[5]->SetReadOnly(true);
+
+	// depth and color table id values - should be set later
+	// as far as depth - color table is most likely 0xff
+	((MP4IntegerProperty *)m_pProperties[7])->SetValue(0x18);
+	((MP4IntegerProperty *)m_pProperties[8])->SetValue(0xffff);
+
+}
+
--- a/common/mp4v2/atoms.h
+++ b/common/mp4v2/atoms.h
@@ -13,7 +13,7 @@
  * 
  * The Initial Developer of the Original Code is Cisco Systems Inc.
  * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001 - 2004.  All Rights Reserved.
+ * 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.
@@ -24,6 +24,7 @@
  * Contributor(s): 
  *		Dave Mackie		[email protected]
  *              Ximpo Group Ltd.                [email protected]
+ *              Bill May                [email protected]
  */
 
 #ifndef __MP4_ATOMS_INCLUDED__
@@ -51,58 +52,15 @@
 	void WriteAtomType(const char* type, bool onlyOne);
 };
 
-class MP4FtypAtom : public MP4Atom {
-public:
-	MP4FtypAtom();
-	void Generate();
-	void Read();
+/***********************************************************************
+ * Common atom classes - standard for anything that just contains atoms
+ * and non-maleable properties, treftype and url
+ ***********************************************************************/
+class MP4StandardAtom : public MP4Atom {
+ public:
+  MP4StandardAtom(const char *name);
 };
 
-class MP4MdatAtom : public MP4Atom {
-public:
-	MP4MdatAtom();
-	void Read();
-	void Write();
-};
-
-class MP4MoovAtom : public MP4Atom {
-public:
-	MP4MoovAtom();
-};
-
-class MP4MvhdAtom : public MP4Atom {
-public:
-	MP4MvhdAtom();
-	void Generate();
-	void Read();
-protected:
-	void AddProperties(u_int8_t version);
-};
-
-class MP4IodsAtom : public MP4Atom {
-public:
-	MP4IodsAtom();
-};
-
-class MP4TrakAtom : public MP4Atom {
-public:
-	MP4TrakAtom();
-};
-
-class MP4TkhdAtom : public MP4Atom {
-public:
-	MP4TkhdAtom();
-	void Generate();
-	void Read();
-protected:
-	void AddProperties(u_int8_t version);
-};
-
-class MP4TrefAtom : public MP4Atom {
-public:
-	MP4TrefAtom();
-};
-
 class MP4TrefTypeAtom : public MP4Atom {
 public:
 	MP4TrefTypeAtom(const char* type);
@@ -109,88 +67,79 @@
 	void Read();
 };
 
-class MP4MdiaAtom : public MP4Atom {
+class MP4UrlAtom : public MP4Atom {
 public:
-	MP4MdiaAtom();
+	MP4UrlAtom(const char *type="url ");
+	void Read();
+	void Write();
 };
 
-class MP4MdhdAtom : public MP4Atom {
-public:
-	MP4MdhdAtom();
-	void Generate();
-	void Read();
+/***********************************************************************
+ * Sound and Video atoms - use the generic atoms when possible
+ * (MP4SoundAtom and MP4VideoAtom)
+ ***********************************************************************/
+class MP4SoundAtom : public MP4Atom {
+ public:
+  MP4SoundAtom(const char *atomid);
+  void Generate();
+  void Read();
 protected:
-	void AddProperties(u_int8_t version);
+  void AddProperties(u_int8_t version);
 };
 
-class MP4HdlrAtom : public MP4Atom {
-public:
-	MP4HdlrAtom();
-	void Read();
+class MP4VideoAtom : public MP4Atom {
+ public:
+  MP4VideoAtom(const char *atomid);
+  void Generate();
 };
 
-class MP4MinfAtom : public MP4Atom {
-public:
-	MP4MinfAtom();
+class MP4AmrAtom : public MP4Atom {
+ public:
+  MP4AmrAtom(const char *type);
+  void Generate();
 };
 
-class MP4VmhdAtom : public MP4Atom {
-public:
-	MP4VmhdAtom();
-	void Generate();
-};
+// H.264 atoms
 
-class MP4SmhdAtom : public MP4Atom {
-public:
-	MP4SmhdAtom();
+class MP4Avc1Atom : public MP4Atom {
+ public:
+  MP4Avc1Atom();
+  void Generate();
 };
 
-class MP4HmhdAtom : public MP4Atom {
-public:
-	MP4HmhdAtom();
+class MP4AvcCAtom : public MP4Atom {
+ public:
+  MP4AvcCAtom();
+  void Generate();
+  void Clone(MP4AvcCAtom *dstAtom);
 };
 
-class MP4NmhdAtom : public MP4Atom {
-public:
-	MP4NmhdAtom();
-};
 
-class MP4DinfAtom : public MP4Atom {
-public:
-	MP4DinfAtom();
+class MP4D263Atom : public MP4Atom {
+ public:
+  MP4D263Atom();
+  void Generate();
+  void Write();
 };
-
-class MP4DrefAtom : public MP4Atom {
-public:
-	MP4DrefAtom();
-	void Read();
+ 
+class MP4DamrAtom : public MP4Atom {
+ public: 
+  MP4DamrAtom();
+  void Generate();
 };
 
-class MP4UrlAtom : public MP4Atom {
+class MP4EncaAtom : public MP4Atom {
 public:
-	MP4UrlAtom();
-	void Read();
-	void Write();
+        MP4EncaAtom();
+        void Generate();
 };
 
-class MP4UrnAtom : public MP4Atom {
+class MP4EncvAtom : public MP4Atom {
 public:
-	MP4UrnAtom();
-	void Read();
+        MP4EncvAtom();
+        void Generate();
 };
 
-class MP4StblAtom : public MP4Atom {
-public:
-	MP4StblAtom();
-	void Generate();
-};
-
-class MP4StsdAtom : public MP4Atom {
-public:
-	MP4StsdAtom();
-	void Read();
-};
-
 class MP4Mp4aAtom : public MP4Atom {
 public:
 	MP4Mp4aAtom();
@@ -209,68 +158,89 @@
 	void Generate();
 };
 
-class MP4EsdsAtom : public MP4Atom {
-public:
-	MP4EsdsAtom();
+
+class MP4S263Atom : public MP4Atom {
+ public:
+  MP4S263Atom();
+  void Generate();
 };
+ 
+ 
+ 
+/************************************************************************
+ * Specialized Atoms
+ ************************************************************************/
 
-class MP4SttsAtom : public MP4Atom {
+class MP4DataAtom : public MP4Atom {
 public:
-	MP4SttsAtom();
+    MP4DataAtom();
+    void Read();
 };
 
-class MP4CttsAtom : public MP4Atom {
+class MP4DrefAtom : public MP4Atom {
 public:
-	MP4CttsAtom();
+	MP4DrefAtom();
+	void Read();
 };
 
-class MP4StszAtom : public MP4Atom {
+class MP4ElstAtom : public MP4Atom {
 public:
-	MP4StszAtom();
+	MP4ElstAtom();
+	void Generate();
 	void Read();
-	void Write();
+protected:
+	void AddProperties(u_int8_t version);
 };
 
-class MP4StscAtom : public MP4Atom {
+class MP4FreeAtom : public MP4Atom {
 public:
-	MP4StscAtom();
+	MP4FreeAtom();
 	void Read();
+	void Write();
 };
 
-class MP4StcoAtom : public MP4Atom {
+class MP4FtypAtom : public MP4Atom {
 public:
-	MP4StcoAtom();
+	MP4FtypAtom();
+	void Generate();
+	void Read();
 };
 
-class MP4Co64Atom : public MP4Atom {
+class MP4GminAtom : public MP4Atom {
 public:
-	MP4Co64Atom();
+	MP4GminAtom();
+	void Generate();
 };
 
-class MP4StssAtom : public MP4Atom {
+class MP4HdlrAtom : public MP4Atom {
 public:
-	MP4StssAtom();
+	MP4HdlrAtom();
+	void Read();
 };
 
-class MP4StshAtom : public MP4Atom {
+class MP4HinfAtom : public MP4Atom {
 public:
-	MP4StshAtom();
+	MP4HinfAtom();
+	void Generate();
 };
 
-class MP4StdpAtom : public MP4Atom {
+class MP4HntiAtom : public MP4Atom {
 public:
-	MP4StdpAtom();
+	MP4HntiAtom();
 	void Read();
 };
 
-class MP4EdtsAtom : public MP4Atom {
+
+class MP4MdatAtom : public MP4Atom {
 public:
-	MP4EdtsAtom();
+	MP4MdatAtom();
+	void Read();
+	void Write();
 };
 
-class MP4ElstAtom : public MP4Atom {
+class MP4MdhdAtom : public MP4Atom {
 public:
-	MP4ElstAtom();
+	MP4MdhdAtom();
 	void Generate();
 	void Read();
 protected:
@@ -277,23 +247,34 @@
 	void AddProperties(u_int8_t version);
 };
 
-class MP4UdtaAtom : public MP4Atom {
-public:
-	MP4UdtaAtom();
-	void Read();
+class MP4Meta1Atom : public MP4Atom {
+ public:
+  MP4Meta1Atom(const char *name);
+  void Read();
 };
 
-class MP4CprtAtom : public MP4Atom {
-public:
-	MP4CprtAtom();
+class MP4Meta2Atom : public MP4Atom {
+ public:
+  MP4Meta2Atom(const char *name);
+  void Read();
 };
-
-class MP4HntiAtom : public MP4Atom {
+	       
+class MP4MvhdAtom : public MP4Atom {
 public:
-	MP4HntiAtom();
+	MP4MvhdAtom();
+	void Generate();
 	void Read();
+protected:
+	void AddProperties(u_int8_t version);
 };
 
+class MP4OhdrAtom : public MP4Atom {
+ public:
+  MP4OhdrAtom();
+  ~MP4OhdrAtom();
+  void Read();
+};
+
 class MP4RtpAtom : public MP4Atom {
 public:
 	MP4RtpAtom();
@@ -314,21 +295,6 @@
 	void WriteHntiType();
 };
 
-class MP4TimsAtom : public MP4Atom {
-public:
-	MP4TimsAtom();
-};
-
-class MP4TsroAtom : public MP4Atom {
-public:
-	MP4TsroAtom();
-};
-
-class MP4SnroAtom : public MP4Atom {
-public:
-	MP4SnroAtom();
-};
-
 class MP4SdpAtom : public MP4Atom {
 public:
 	MP4SdpAtom();
@@ -336,97 +302,62 @@
 	void Write();
 };
 
-class MP4HinfAtom : public MP4Atom {
-public:
-	MP4HinfAtom();
-	void Generate();
+class MP4SmiAtom : public MP4Atom {
+ public:
+  MP4SmiAtom(void);
+  void Read();
 };
 
-class MP4TrpyAtom : public MP4Atom {
+class MP4StblAtom : public MP4Atom {
 public:
-	MP4TrpyAtom();
+	MP4StblAtom();
+	void Generate();
 };
 
-class MP4NumpAtom : public MP4Atom {
+class MP4StdpAtom : public MP4Atom {
 public:
-	MP4NumpAtom();
+	MP4StdpAtom();
+	void Read();
 };
 
-class MP4TpylAtom : public MP4Atom {
+class MP4StscAtom : public MP4Atom {
 public:
-	MP4TpylAtom();
+	MP4StscAtom();
+	void Read();
 };
 
-class MP4MaxrAtom : public MP4Atom {
+class MP4StsdAtom : public MP4Atom {
 public:
-	MP4MaxrAtom();
+	MP4StsdAtom();
+	void Read();
 };
 
-class MP4DmedAtom : public MP4Atom {
+class MP4StszAtom : public MP4Atom {
 public:
-	MP4DmedAtom();
+	MP4StszAtom();
+	void Read();
+	void Write();
 };
 
-class MP4DimmAtom : public MP4Atom {
+class MP4Stz2Atom : public MP4Atom {
 public:
-	MP4DimmAtom();
+	MP4Stz2Atom();
+	void Read();
 };
 
-class MP4DrepAtom : public MP4Atom {
+class MP4TextAtom : public MP4Atom {
 public:
-	MP4DrepAtom();
-};
+	MP4TextAtom();
+	void Generate();
+	void Read();
+protected:
+	void AddPropertiesStsdType();
+	void AddPropertiesGmhdType();
 
-class MP4TminAtom : public MP4Atom {
-public:
-	MP4TminAtom();
+	void GenerateStsdType();
+	void GenerateGmhdType();
 };
 
-class MP4TmaxAtom : public MP4Atom {
-public:
-	MP4TmaxAtom();
-};
-
-class MP4PmaxAtom : public MP4Atom {
-public:
-	MP4PmaxAtom();
-};
-
-class MP4DmaxAtom : public MP4Atom {
-public:
-	MP4DmaxAtom();
-};
-
-class MP4PaytAtom : public MP4Atom {
-public:
-	MP4PaytAtom();
-};
-
-class MP4MvexAtom : public MP4Atom {
-public:
-	MP4MvexAtom();
-};
-
-class MP4TrexAtom : public MP4Atom {
-public:
-	MP4TrexAtom();
-};
-
-class MP4MoofAtom : public MP4Atom {
-public:
-	MP4MoofAtom();
-};
-
-class MP4MfhdAtom : public MP4Atom {
-public:
-	MP4MfhdAtom();
-};
-
-class MP4TrafAtom : public MP4Atom {
-public:
-	MP4TrafAtom();
-};
-
 class MP4TfhdAtom : public MP4Atom {
 public:
 	MP4TfhdAtom();
@@ -435,6 +366,14 @@
 	void AddProperties(u_int32_t flags);
 };
 
+class MP4TkhdAtom : public MP4Atom {
+public:
+	MP4TkhdAtom();
+	void Generate();
+	void Read();
+protected:
+	void AddProperties(u_int8_t version);
+};
 class MP4TrunAtom : public MP4Atom {
 public:
 	MP4TrunAtom();
@@ -443,193 +382,27 @@
 	void AddProperties(u_int32_t flags);
 };
 
-class MP4FreeAtom : public MP4Atom {
+class MP4UdtaAtom : public MP4Atom {
 public:
-	MP4FreeAtom();
+	MP4UdtaAtom();
 	void Read();
-	void Write();
 };
 
-class MP4EncaAtom : public MP4Atom {
+class MP4UrnAtom : public MP4Atom {
 public:
-        MP4EncaAtom();
-        void Generate();
+	MP4UrnAtom();
+	void Read();
 };
-
-class MP4EncvAtom : public MP4Atom {
+class MP4VmhdAtom : public MP4Atom {
 public:
-        MP4EncvAtom();
-        void Generate();
+	MP4VmhdAtom();
+	void Generate();
 };
 
-class MP4FrmaAtom : public MP4Atom {
-public:
-        MP4FrmaAtom();
-};
-
-class MP4IKMSAtom : public MP4Atom {
-public:
-        MP4IKMSAtom();
-};
-
-class MP4ISFMAtom : public MP4Atom {
-public:
-        MP4ISFMAtom();
-};
-
-class MP4SchiAtom : public MP4Atom {
-public:
-        MP4SchiAtom();
-};
-
-class MP4SchmAtom : public MP4Atom {
-public:
-        MP4SchmAtom();
-};
-
-class MP4SinfAtom : public MP4Atom {
-public:
-        MP4SinfAtom();
-};
-
-/* iTunes META data atoms */
-class MP4MetaAtom : public MP4Atom {
-public:
-	MP4MetaAtom();
-};
-
-class MP4NameAtom : public MP4Atom {
-public:
-    MP4NameAtom();
-    void Read();
-};
-
-class MP4MeanAtom : public MP4Atom {
-public:
-    MP4MeanAtom();
-    void Read();
-};
-
-class MP4DataAtom : public MP4Atom {
-public:
-    MP4DataAtom();
-    void Read();
-};
-
-class MP4IlstAtom : public MP4Atom {
-public:
-	MP4IlstAtom();
-};
-
-class MP4DashAtom : public MP4Atom {
-public:
-    MP4DashAtom();
-};
-
-class MP4NamAtom : public MP4Atom {
-public:
-	MP4NamAtom();
-};
-
-class MP4ArtAtom : public MP4Atom {
-public:
-	MP4ArtAtom();
-};
-
-class MP4WrtAtom : public MP4Atom {
-public:
-	MP4WrtAtom();
-};
-
-class MP4AlbAtom : public MP4Atom {
-public:
-	MP4AlbAtom();
-};
-
-class MP4TrknAtom : public MP4Atom {
-public:
-	MP4TrknAtom();
-};
-
-class MP4DayAtom : public MP4Atom {
-public:
-	MP4DayAtom();
-};
-
-class MP4GenAtom : public MP4Atom {
-public:
-	MP4GenAtom();
-};
-
-class MP4TooAtom : public MP4Atom {
-public:
-	MP4TooAtom();
-};
-
-class MP4GnreAtom : public MP4Atom {
-public:
-	MP4GnreAtom();
-};
-
-class MP4CpilAtom : public MP4Atom {
-public:
-	MP4CpilAtom();
-};
-
-class MP4TmpoAtom : public MP4Atom {
-public:
-	MP4TmpoAtom();
-};
-
-class MP4CmtAtom : public MP4Atom {
-public:
-	MP4CmtAtom();
-};
-
-class MP4CovrAtom : public MP4Atom {
+class MP4HrefAtom : public MP4Atom {
  public:
-  MP4CovrAtom();
-};
-
-class MP4DiskAtom : public MP4Atom {
-public:
-	MP4DiskAtom();
-};
-
-class MP4BitrAtom : public MP4Atom {
- public:
-  MP4BitrAtom();
-};
- 
-class MP4D263Atom : public MP4Atom {
- public:
-  MP4D263Atom();
-  void Generate();
-  void Write();
-};
- 
-class MP4DamrAtom : public MP4Atom {
- public: 
-  MP4DamrAtom();
-  void Generate();
-};
- 
-class MP4S263Atom : public MP4Atom {
- public:
-  MP4S263Atom();
-  void Generate();
-};
- 
-class MP4SamrAtom : public MP4Atom {
- public:
-  MP4SamrAtom();
-  void Generate();
-};
- 
-class MP4SawbAtom : public MP4Atom {
- public:
-  MP4SawbAtom();
-  void Generate();
+  MP4HrefAtom();
+  void Generate(void);
 };
 
 #endif /* __MP4_ATOMS_INCLUDED__ */
--- a/common/mp4v2/descriptors.cpp
+++ b/common/mp4v2/descriptors.cpp
@@ -21,6 +21,105 @@
 
 #include "mp4common.h"
 
+MP4BaseDescriptor::MP4BaseDescriptor (u_int8_t tag) : MP4Descriptor(tag)
+{
+  switch (tag) {
+  case MP4ESIDIncDescrTag:
+    AddProperty( /* 0 */
+		new MP4Integer32Property("id"));
+    break;
+  case MP4ESIDRefDescrTag:
+    AddProperty( /* 0 */
+		new MP4Integer16Property("refIndex"));
+    break;
+  case MP4IPIPtrDescrTag:
+    AddProperty( /* 0 */
+		new MP4Integer16Property("IPIESId"));
+    break;
+  case MP4SupplContentIdDescrTag:
+    AddProperty( /* 0 */
+		new MP4BytesProperty("languageCode", 3));
+    AddProperty( /* 1 */
+		new MP4StringProperty("title", Counted));
+    AddProperty( /* 2 */
+		new MP4StringProperty("value", Counted));
+    break;
+  case MP4IPMPPtrDescrTag:
+    AddProperty( /* 0 */
+		new MP4Integer8Property("IPMPDescriptorId"));
+    break;
+  case MP4ExtProfileLevelDescrTag:
+    AddProperty( /* 0 */
+		new MP4Integer8Property("profileLevelIndicationIndex"));
+    AddProperty( /* 1 */
+		new MP4Integer8Property("ODProfileLevelIndication"));
+    AddProperty( /* 2 */
+		new MP4Integer8Property("sceneProfileLevelIndication"));
+    AddProperty( /* 3 */
+		new MP4Integer8Property("audioProfileLevelIndication"));
+    AddProperty( /* 4 */
+		new MP4Integer8Property("visualProfileLevelIndication"));
+    AddProperty( /* 5 */
+		new MP4Integer8Property("graphicsProfileLevelIndication"));
+    AddProperty( /* 6 */
+		new MP4Integer8Property("MPEGJProfileLevelIndication"));
+    break;
+  default:
+    MP4Printf("error in base descriptor - tag %u", tag);
+    break;
+
+  }
+}
+
+MP4BytesDescriptor::MP4BytesDescriptor (u_int8_t tag) : MP4Descriptor(tag)
+{
+  m_size_offset = 0;
+  m_bytes_index = 0;
+  if (tag >= MP4ExtDescrTagsStart && tag <= MP4ExtDescrTagsEnd) {
+    AddProperty( /* 0 */
+		new MP4BytesProperty("data"));
+  } else {
+    switch (tag) {
+    case MP4DecSpecificDescrTag:
+      AddProperty( /* 0 */
+		  new MP4BytesProperty("info"));
+      // no change to m_size
+      break;
+    case MP4IPMPDescrTag:
+      AddProperty( /* 0 */
+		  new MP4Integer8Property("IPMPDescriptorId"));
+      AddProperty( /* 1 */
+		  new MP4Integer16Property("IPMPSType"));
+      AddProperty( /* 2 */
+		  new MP4BytesProperty("IPMPData"));
+      /* note: if IPMPSType == 0, IPMPData is an URL */
+      m_size_offset = 3;
+      m_bytes_index = 2;
+      break;
+    case MP4RegistrationDescrTag:
+      AddProperty( /* 0 */
+		  new MP4Integer32Property("formatIdentifier"));
+      AddProperty( /* 1 */
+		  new MP4BytesProperty("additionalIdentificationInfo"));
+      m_size_offset = 4;
+      m_bytes_index = 1;
+      break;
+    default:
+      MP4Printf("error in bytes descriptor - tag %u", tag);
+      break;
+    }
+  }
+}
+
+void MP4BytesDescriptor::Read(MP4File *pFile)
+{
+  ReadHeader(pFile);
+  
+  /* byte properties need to know how long they are before reading */
+  ((MP4BytesProperty*)m_pProperties[m_bytes_index])->SetValueSize(m_size - m_size_offset);
+
+  ReadProperties(pFile);
+}
 MP4IODescriptor::MP4IODescriptor()
 	: MP4Descriptor(MP4FileIODescrTag)
 {
@@ -123,20 +222,6 @@
 	}
 }
 
-MP4ESIDIncDescriptor::MP4ESIDIncDescriptor()
-	: MP4Descriptor(MP4ESIDIncDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4Integer32Property("id"));
-}
-
-MP4ESIDRefDescriptor::MP4ESIDRefDescriptor()
-	: MP4Descriptor(MP4ESIDRefDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4Integer16Property("refIndex"));
-}
-
 MP4ESDescriptor::MP4ESDescriptor()
 	: MP4Descriptor(MP4ESDescrTag)
 {
@@ -233,23 +318,6 @@
 	((MP4BitfieldProperty*)m_pProperties[3])->SetValue(1);
 }
 
-MP4DecSpecificDescriptor::MP4DecSpecificDescriptor()
-	: MP4Descriptor(MP4DecSpecificDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4BytesProperty("info"));
-}
-
-void MP4DecSpecificDescriptor::Read(MP4File* pFile)
-{
-	ReadHeader(pFile);
-
-	/* byte properties need to know how long they are before reading */
-	((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size);
-
-	ReadProperties(pFile);
-}
-
 MP4SLConfigDescriptor::MP4SLConfigDescriptor()
 	: MP4Descriptor(MP4SLConfigDescrTag)
 {
@@ -401,13 +469,6 @@
 	}
 }
 
-MP4IPIPtrDescriptor::MP4IPIPtrDescriptor()
-	: MP4Descriptor(MP4IPIPtrDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4Integer16Property("IPIESId"));
-}
-
 MP4ContentIdDescriptor::MP4ContentIdDescriptor()
 	: MP4Descriptor(MP4ContentIdDescrTag)
 {
@@ -450,113 +511,39 @@
 	/* which allows us to reconfigure ourselves */
 	Mutate();
 
-	/* read the remaining properties */
-	ReadProperties(pFile, 5);
-}
-
-void MP4ContentIdDescriptor::Mutate()
-{
 	bool contentTypeFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue();
-	m_pProperties[5]->SetImplicit(!contentTypeFlag);
 
 	bool contentIdFlag = ((MP4BitfieldProperty*)m_pProperties[2])->GetValue();
-	m_pProperties[6]->SetImplicit(!contentIdFlag);
-	m_pProperties[7]->SetImplicit(!contentIdFlag);
-}
 
-MP4SupplContentIdDescriptor::MP4SupplContentIdDescriptor()
-	: MP4Descriptor(MP4SupplContentIdDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4BytesProperty("languageCode", 3));
-	AddProperty( /* 1 */
-		new MP4StringProperty("title", Counted));
-	AddProperty( /* 2 */
-		new MP4StringProperty("value", Counted));
-}
+  if (contentIdFlag) {
 
-MP4IPMPPtrDescriptor::MP4IPMPPtrDescriptor()
-	: MP4Descriptor(MP4IPMPPtrDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4Integer8Property("IPMPDescriptorId"));
-}
+    u_int32_t cIdOffset = 2;
 
-MP4IPMPDescriptor::MP4IPMPDescriptor()
-	: MP4Descriptor(MP4IPMPDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4Integer8Property("IPMPDescriptorId"));
-	AddProperty( /* 1 */
-		new MP4Integer16Property("IPMPSType"));
-	AddProperty( /* 2 */
-		new MP4BytesProperty("IPMPData"));
-	/* note: if IPMPSType == 0, IPMPData is an URL */
-}
+    if (contentTypeFlag) {
 
-void MP4IPMPDescriptor::Read(MP4File* pFile)
-{
-	ReadHeader(pFile);
+      cIdOffset++;
 
-	/* byte properties need to know how long they are before reading */
-	((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 3);
+    }
 
-	ReadProperties(pFile);
-}
+  	((MP4BytesProperty*)m_pProperties[7])->SetValueSize(m_size - cIdOffset);
 
-MP4RegistrationDescriptor::MP4RegistrationDescriptor()
-	: MP4Descriptor(MP4RegistrationDescrTag)
-{
-	AddProperty( /* 0 */
-		new MP4Integer32Property("formatIdentifier"));
-	AddProperty( /* 1 */
-		new MP4BytesProperty("additionalIdentificationInfo"));
-}
+  }
 
-void MP4RegistrationDescriptor::Read(MP4File* pFile)
-{
-	ReadHeader(pFile);
 
-	/* byte properties need to know how long they are before reading */
-	((MP4BytesProperty*)m_pProperties[1])->SetValueSize(m_size - 4);
 
-	ReadProperties(pFile);
+	/* read the remaining properties */
+	ReadProperties(pFile, 5);
 }
 
-MP4ExtProfileLevelDescriptor::MP4ExtProfileLevelDescriptor()
-	: MP4Descriptor(MP4ExtProfileLevelDescrTag)
+void MP4ContentIdDescriptor::Mutate()
 {
-	AddProperty( /* 0 */
-		new MP4Integer8Property("profileLevelIndicationIndex"));
-	AddProperty( /* 1 */
-		new MP4Integer8Property("ODProfileLevelIndication"));
-	AddProperty( /* 2 */
-		new MP4Integer8Property("sceneProfileLevelIndication"));
-	AddProperty( /* 3 */
-		new MP4Integer8Property("audioProfileLevelIndication"));
-	AddProperty( /* 4 */
-		new MP4Integer8Property("visualProfileLevelIndication"));
-	AddProperty( /* 5 */
-		new MP4Integer8Property("graphicsProfileLevelIndication"));
-	AddProperty( /* 6 */
-		new MP4Integer8Property("MPEGJProfileLevelIndication"));
-}
+	bool contentTypeFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue();
+	m_pProperties[5]->SetImplicit(!contentTypeFlag);
 
-MP4ExtensionDescriptor::MP4ExtensionDescriptor()
-	: MP4Descriptor()
-{
-	AddProperty( /* 0 */
-		new MP4BytesProperty("data"));
-}
+	bool contentIdFlag = ((MP4BitfieldProperty*)m_pProperties[2])->GetValue();
+	m_pProperties[6]->SetImplicit(!contentIdFlag);
+	m_pProperties[7]->SetImplicit(!contentIdFlag);
 
-void MP4ExtensionDescriptor::Read(MP4File* pFile)
-{
-	ReadHeader(pFile);
-
-	/* byte properties need to know how long they are before reading */
-	((MP4BytesProperty*)m_pProperties[0])->SetValueSize(m_size);
-
-	ReadProperties(pFile);
 }
 
 MP4Descriptor* MP4DescriptorProperty::CreateDescriptor(u_int8_t tag) 
@@ -571,7 +558,9 @@
 		pDescriptor = new MP4DecConfigDescriptor();
 		break;
 	case MP4DecSpecificDescrTag:
-		pDescriptor = new MP4DecSpecificDescriptor();
+	case MP4IPMPDescrTag:
+	case MP4RegistrationDescrTag:
+		pDescriptor = new MP4BytesDescriptor(tag);
 		break;
 	case MP4SLConfigDescrTag:
 		pDescriptor = new MP4SLConfigDescriptor();
@@ -579,30 +568,17 @@
 	case MP4ContentIdDescrTag:
 		pDescriptor = new MP4ContentIdDescriptor();
 		break;
-	case MP4SupplContentIdDescrTag:
-		pDescriptor = new MP4SupplContentIdDescriptor();
-		break;
+	case MP4ESIDIncDescrTag:
+	case MP4ESIDRefDescrTag:
 	case MP4IPIPtrDescrTag:
-		pDescriptor = new MP4IPIPtrDescriptor();
-		break;
+	case MP4SupplContentIdDescrTag:
 	case MP4IPMPPtrDescrTag:
-		pDescriptor = new MP4IPMPPtrDescriptor();
+	case MP4ExtProfileLevelDescrTag:
+	        pDescriptor = new MP4BaseDescriptor(tag);
 		break;
-	case MP4IPMPDescrTag:
-		pDescriptor = new MP4IPMPDescriptor();
-		break;
 	case MP4QosDescrTag:
-		pDescriptor = new MP4QosDescriptor();
+		pDescriptor = new MP4QosDescriptorBase(MP4QosDescrTag);
 		break;
-	case MP4RegistrationDescrTag:
-		pDescriptor = new MP4RegistrationDescriptor();
-		break;
-	case MP4ESIDIncDescrTag:
-		pDescriptor = new MP4ESIDIncDescriptor();
-		break;
-	case MP4ESIDRefDescrTag:
-		pDescriptor = new MP4ESIDRefDescriptor();
-		break;
 	case MP4IODescrTag:
 	case MP4FileIODescrTag:
 		pDescriptor = new MP4IODescriptor();
@@ -613,9 +589,6 @@
 		pDescriptor = new MP4ODescriptor();
 		pDescriptor->SetTag(tag);
 		break;
-	case MP4ExtProfileLevelDescrTag:
-		pDescriptor = new MP4ExtProfileLevelDescriptor();
-		break;
 	}
 
 	if (pDescriptor == NULL) {
@@ -624,8 +597,7 @@
 		}
 
 		if (tag >= MP4ExtDescrTagsStart && tag <= MP4ExtDescrTagsEnd) {
-			pDescriptor = new MP4ExtensionDescriptor();
-			pDescriptor->SetTag(tag);
+			pDescriptor = new MP4BytesDescriptor(tag);
 		}
 	}
 
--- a/common/mp4v2/descriptors.h
+++ b/common/mp4v2/descriptors.h
@@ -42,6 +42,20 @@
 const u_int8_t MP4ExtDescrTagsStart			= 0x80; 
 const u_int8_t MP4ExtDescrTagsEnd			= 0xFE; 
 
+class MP4BaseDescriptor : public MP4Descriptor {
+ public:
+  MP4BaseDescriptor(u_int8_t tag);
+};
+
+class MP4BytesDescriptor : public MP4Descriptor {
+ public:
+  MP4BytesDescriptor(u_int8_t tag);
+  void Read(MP4File* pFile);
+ protected:
+  uint m_size_offset; // size to adjust the size for the bytes property
+  uint m_bytes_index; // index into properties for bytes property
+};
+
 class MP4IODescriptor : public MP4Descriptor {
 public:
 	MP4IODescriptor();
@@ -58,16 +72,7 @@
 	void Mutate();
 };
 
-class MP4ESIDIncDescriptor : public MP4Descriptor {
-public:
-	MP4ESIDIncDescriptor();
-};
 
-class MP4ESIDRefDescriptor : public MP4Descriptor {
-public:
-	MP4ESIDRefDescriptor();
-};
-
 class MP4ESDescriptor : public MP4Descriptor {
 public:
 	MP4ESDescriptor();
@@ -81,11 +86,6 @@
 	void Generate();
 };
 
-class MP4DecSpecificDescriptor : public MP4Descriptor {
-public:
-	MP4DecSpecificDescriptor();
-	void Read(MP4File* pFile);
-};
 
 class MP4SLConfigDescriptor : public MP4Descriptor {
 public:
@@ -107,39 +107,6 @@
 	void Read(MP4File* pFile);
 protected:
 	void Mutate();
-};
-
-class MP4SupplContentIdDescriptor : public MP4Descriptor {
-public:
-	MP4SupplContentIdDescriptor();
-};
-
-class MP4IPMPPtrDescriptor : public MP4Descriptor {
-public:
-	MP4IPMPPtrDescriptor();
-};
-
-class MP4IPMPDescriptor : public MP4Descriptor {
-public:
-	MP4IPMPDescriptor();
-	void Read(MP4File* pFile);
-};
-
-class MP4RegistrationDescriptor : public MP4Descriptor {
-public:
-	MP4RegistrationDescriptor();
-	void Read(MP4File* pFile);
-};
-
-class MP4ExtProfileLevelDescriptor : public MP4Descriptor {
-public:
-	MP4ExtProfileLevelDescriptor();
-};
-
-class MP4ExtensionDescriptor : public MP4Descriptor {
-public:
-	MP4ExtensionDescriptor();
-	void Read(MP4File* pFile);
 };
 
 // associated values in descriptors
--- a/common/mp4v2/isma.cpp
+++ b/common/mp4v2/isma.cpp
@@ -29,7 +29,7 @@
 
 #include "mp4common.h"
 
-static u_int8_t BifsV2Config[3] = {
+static const u_int8_t BifsV2Config[3] = {
 	0x00, 0x00, 0x60 // IsCommandStream = 1, PixelMetric = 1
 };
 
@@ -59,20 +59,42 @@
 	catch (MP4Error* e) {
 		delete e;
 	}
-	// Check whether it's an AMR-NB or AMR-WB trak
-        if ((MP4HaveTrackIntegerProperty(this, audioTrackId, "mdia.minf.stbl.stsd.sawb.damr.vendor"))  ||
-            (MP4HaveTrackIntegerProperty(this, audioTrackId, "mdia.minf.stbl.stsd.samr.damr.vendor"))) {
-		throw new MP4Error("can't make ISMA compliant when file contains an AMR track", "MakeIsmaCompliant");
+	if (audioTrackId == MP4_INVALID_TRACK_ID &&
+	    videoTrackId == MP4_INVALID_TRACK_ID) return;
+
+	const char *audio_media_data_name, *video_media_data_name;
+	uint8_t videoProfile = 0xff;
+	if (audioTrackId != MP4_INVALID_TRACK_ID) {
+	  audio_media_data_name = MP4GetTrackMediaDataName(this, audioTrackId);
+	  if (!(ATOMID(audio_media_data_name) == ATOMID("mp4a") ||
+		ATOMID(audio_media_data_name) == ATOMID("enca"))) {
+	    VERBOSE_ERROR(m_verbosity,
+			  printf("MakeIsmaCompliant:can't make ISMA compliant when file contains an %s track\n", audio_media_data_name);
+			  );
+	    return;
+	  }
 	}
 	//
-	// Check whether it's an H.263 file
-        if (MP4HaveTrackIntegerProperty(this, videoTrackId, "mdia.minf.stbl.stsd.s263.d263.vendor")) {
-		throw new MP4Error("can't make ISMA compliant when file contains an H.263 track", "MakeIsmaCompliant");
+	// Note - might have to check for avc1 here...
+	if (videoTrackId != MP4_INVALID_TRACK_ID) {
+	  video_media_data_name = MP4GetTrackMediaDataName(this, videoTrackId);
+	  if (!(ATOMID(video_media_data_name) == ATOMID("mp4v") ||
+		ATOMID(video_media_data_name) == ATOMID("encv"))) {
+	    VERBOSE_ERROR(m_verbosity,
+			  printf("MakeIsmaCompliant:can't make ISMA compliant when file contains an %s track\n", video_media_data_name);
+			  );
+	    return;
+	  }
+	  uint32_t verb = GetVerbosity();
+	  SetVerbosity(verb & ~MP4_DETAILS_ERROR);
+	  videoProfile = MP4GetVideoProfileLevel(this, videoTrackId);
+	  SetVerbosity(verb);
 	}
 
 	m_useIsma = true;
 
-	u_int64_t fileMsDuration =
+	u_int64_t fileMsDuration = 0;
+	fileMsDuration = 
 		ConvertFromMovieDuration(GetDuration(), MP4_MSECS_TIME_SCALE);
 
 	// delete any existing OD track
@@ -80,15 +102,19 @@
 		DeleteTrack(m_odTrackId);
 	}
 
-	AddODTrack();
+	if (m_pRootAtom->FindAtom("moov.iods") == NULL) {
+	  (void)AddChildAtom("moov", "iods");
+	}
+	(void)AddODTrack();
 	SetODProfileLevel(0xFF);
 
 	if (audioTrackId != MP4_INVALID_TRACK_ID) {
 		AddTrackToOd(audioTrackId);
+		MP4SetAudioProfileLevel(this, 0xf);
 	}
-
 	if (videoTrackId != MP4_INVALID_TRACK_ID) {
 		AddTrackToOd(videoTrackId);
+		MP4SetVideoProfileLevel(this, videoProfile);
 	}
 
 	// delete any existing scene track
@@ -153,13 +179,17 @@
 
 	char* iodBase64 = MP4ToBase64(pBytes, numBytes);
 
-	char* sdpBuf = (char*)MP4Calloc(strlen(iodBase64) + 256);
+	uint sdpBufLen = strlen(iodBase64) + 256;
+	uint used;
+	char* sdpBuf = (char*)MP4Calloc(sdpBufLen);
 
 	if (addIsmaComplianceSdp) {
-		strcpy(sdpBuf, "a=isma-compliance:1,1.0,1\015\012");
+	  strncpy(sdpBuf, "a=isma-compliance:1,1.0,1\015\012", sdpBufLen);
 	}
 
-	sprintf(&sdpBuf[strlen(sdpBuf)], 
+	used = strlen(sdpBuf);
+	sdpBufLen -= used;
+	snprintf(&sdpBuf[used], sdpBufLen, 
 		"a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042\015\012",
 		iodBase64);
 
@@ -184,9 +214,8 @@
 	MP4IntegerProperty* pGetProperty;
 	MP4IntegerProperty* pSetProperty;
 
-	pSrc->FindProperty(name, (MP4Property**)&pGetProperty);
-	pDest->FindProperty(name, (MP4Property**)&pSetProperty);
-
+	if (!pSrc->FindProperty(name, (MP4Property**)&pGetProperty)) return;
+	if (!pDest->FindProperty(name, (MP4Property**)&pSetProperty)) return;
 	pSetProperty->SetValue(pGetProperty->GetValue());
 } 
 
@@ -216,7 +245,7 @@
 
 	// mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
 	MP4DescriptorProperty* pEsProperty;
-	pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
+	if (!pIod->FindProperty("esIds", (MP4Property**)&pEsProperty)) return;
 	pEsProperty->SetTags(MP4ESDescrTag);
 
 	MP4IntegerProperty* pSetProperty;
@@ -228,15 +257,14 @@
 		pEsProperty->AddDescriptor(MP4ESDescrTag);
 	pOdEsd->Generate();
 
-	pOdEsd->FindProperty("ESID", 
-		(MP4Property**)&pOdESID);
+	if (!pOdEsd->FindProperty("ESID", (MP4Property**)&pOdESID)) return;
 
 	// we set the OD ESID to a non-zero unique value
 	pOdESID->SetValue(m_odTrackId);
 
-	pOdEsd->FindProperty("URLFlag", 
-		(MP4Property**)&pSetProperty);
-	pSetProperty->SetValue(1);
+	if (pOdEsd->FindProperty("URLFlag", 
+				 (MP4Property**)&pSetProperty))
+	  pSetProperty->SetValue(1);
 
 	u_int8_t* pBytes;
 	u_int64_t numBytes;
@@ -252,16 +280,17 @@
 
 	char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);
 
-	char* urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);
+	uint urlBufLen = strlen(odCmdBase64) + 64;
+	char* urlBuf = (char*)MP4Malloc(urlBufLen);
 
-	sprintf(urlBuf, 
+	snprintf(urlBuf, urlBufLen,
 		"data:application/mpeg4-od-au;base64,%s",
 		odCmdBase64);
 
 	MP4StringProperty* pUrlProperty;
-	pOdEsd->FindProperty("URL", 
-		(MP4Property**)&pUrlProperty);
-	pUrlProperty->SetValue(urlBuf);
+	if (pOdEsd->FindProperty("URL", 
+				 (MP4Property**)&pUrlProperty))
+	  pUrlProperty->SetValue(urlBuf);
 
 	VERBOSE_ISMA(GetVerbosity(),
 		printf("OD data URL = \042%s\042\n", urlBuf));
@@ -276,7 +305,7 @@
 	MP4DescriptorProperty* pSrcDcd = NULL;
 
 	// HACK temporarily point to scene decoder config
-	FindProperty(MakeTrackName(odTrackId, 
+	(void)FindProperty(MakeTrackName(odTrackId, 
 		"mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
 		(MP4Property**)&pSrcDcd);
 	ASSERT(pSrcDcd);
@@ -286,15 +315,16 @@
 
 	// bufferSizeDB needs to be set appropriately
 	MP4BitfieldProperty* pBufferSizeProperty = NULL;
-	pOdEsd->FindProperty("decConfigDescr.bufferSizeDB",
-		(MP4Property**)&pBufferSizeProperty);
-	ASSERT(pBufferSizeProperty);
-	pBufferSizeProperty->SetValue(numBytes);
+	if (pOdEsd->FindProperty("decConfigDescr.bufferSizeDB",
+				 (MP4Property**)&pBufferSizeProperty)) {
+	  ASSERT(pBufferSizeProperty);
+	  pBufferSizeProperty->SetValue(numBytes);
+	}
 
 	// SL config needs to change from 2 (file) to 1 (null)
-	pOdEsd->FindProperty("slConfigDescr.predefined", 
-		(MP4Property**)&pSetProperty);
-	pSetProperty->SetValue(1);
+	if (pOdEsd->FindProperty("slConfigDescr.predefined", 
+				 (MP4Property**)&pSetProperty))
+	  pSetProperty->SetValue(1);
 
 
 	// Scene
@@ -302,14 +332,15 @@
 		pEsProperty->AddDescriptor(MP4ESDescrTag);
 	pSceneEsd->Generate();
 
-	pSceneEsd->FindProperty("ESID", 
-		(MP4Property**)&pSceneESID);
-	// we set the Scene ESID to a non-zero unique value
-	pSceneESID->SetValue(sceneTrackId);
+	if (pSceneEsd->FindProperty("ESID", 
+				    (MP4Property**)&pSceneESID)) {
+	  // we set the Scene ESID to a non-zero unique value
+	  pSceneESID->SetValue(sceneTrackId);
+	}
 
-	pSceneEsd->FindProperty("URLFlag", 
-		(MP4Property**)&pSetProperty);
-	pSetProperty->SetValue(1);
+	if (pSceneEsd->FindProperty("URLFlag", 
+				    (MP4Property**)&pSetProperty))
+	  pSetProperty->SetValue(1);
 
 	CreateIsmaSceneCommand(
 		MP4_IS_VALID_TRACK_ID(audioTrackId), 
@@ -323,12 +354,12 @@
 	char *sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);
 
 	urlBuf = (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
-	sprintf(urlBuf, 
-		"data:application/mpeg4-bifs-au;base64,%s",
-		sceneCmdBase64);
+	snprintf(urlBuf, strlen(sceneCmdBase64) + 64,
+	  "data:application/mpeg4-bifs-au;base64,%s",
+	  sceneCmdBase64);
 
-	pSceneEsd->FindProperty("URL", 
-		(MP4Property**)&pUrlProperty);
+	if (pSceneEsd->FindProperty("URL", 
+				    (MP4Property**)&pUrlProperty))
 	pUrlProperty->SetValue(urlBuf);
 
 	VERBOSE_ISMA(GetVerbosity(),
@@ -342,9 +373,9 @@
 	pBytes = NULL;
 
 	// HACK temporarily point to scene decoder config
-	FindProperty(MakeTrackName(sceneTrackId, 
+	ASSERT(FindProperty(MakeTrackName(sceneTrackId, 
 		"mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
-		(MP4Property**)&pSrcDcd);
+			 (MP4Property**)&pSrcDcd));
 	ASSERT(pSrcDcd);
 	MP4Property* pOrgSceneEsdProperty = 
 		pSceneEsd->GetProperty(8);
@@ -352,14 +383,15 @@
 
 	// bufferSizeDB needs to be set
 	pBufferSizeProperty = NULL;
-	pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB",
-		(MP4Property**)&pBufferSizeProperty);
+	if (pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB",
+				    (MP4Property**)&pBufferSizeProperty)) {
 	ASSERT(pBufferSizeProperty);
 	pBufferSizeProperty->SetValue(numBytes);
+	}
 
 	// SL config needs to change from 2 (file) to 1 (null)
-	pSceneEsd->FindProperty("slConfigDescr.predefined", 
-		(MP4Property**)&pSetProperty);
+	if (pSceneEsd->FindProperty("slConfigDescr.predefined", 
+				    (MP4Property**)&pSetProperty))
 	pSetProperty->SetValue(1);
 
 
@@ -401,17 +433,17 @@
 	pIod->Generate();
 	
 	// Set audio and video profileLevels
-	pIod->FindProperty("audioProfileLevelId", 
-		(MP4Property**)&pInt);
+	if (pIod->FindProperty("audioProfileLevelId", 
+			       (MP4Property**)&pInt))
 	pInt->SetValue(audioProfile);
 
-	pIod->FindProperty("visualProfileLevelId", 
-		(MP4Property**)&pInt);
-	pInt->SetValue(videoProfile);
+	if (pIod->FindProperty("visualProfileLevelId", 
+			       (MP4Property**)&pInt))
+	    pInt->SetValue(videoProfile);
 
 	// Mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
 	MP4DescriptorProperty* pEsProperty;
-	pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
+	if (!pIod->FindProperty("esIds", (MP4Property**)&pEsProperty)) return;
 	pEsProperty->SetTags(MP4ESDescrTag);
 
 	// Add ES Descriptors
@@ -430,29 +462,29 @@
 
 	char* urlBuf = 
 		(char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
-	sprintf(urlBuf, 
-		"data:application/mpeg4-bifs-au;base64,%s",
-		sceneCmdBase64);
-
-	VERBOSE_ISMA(GetVerbosity(),
-		printf("Scene data URL = \042%s\042\n", urlBuf));
-
-	/* MP4Descriptor* pSceneEsd = */
-		CreateESD(
-			pEsProperty,
-			201,				// esid
-			MP4SystemsV2ObjectType,
+	  snprintf(urlBuf, strlen(sceneCmdBase64) + 64,
+		  "data:application/mpeg4-bifs-au;base64,%s",
+		  sceneCmdBase64);
+	  
+	  VERBOSE_ISMA(GetVerbosity(),
+		       printf("Scene data URL = \042%s\042\n", urlBuf));
+	  
+	  /* MP4Descriptor* pSceneEsd = */
+	  CreateESD(
+		    pEsProperty,
+		    201,				// esid
+		    MP4SystemsV2ObjectType,
 			MP4SceneDescriptionStreamType,
-			numBytes,			// bufferSize
-			numBytes * 8,		// bitrate
-			BifsV2Config,
-			sizeof(BifsV2Config),
-			urlBuf);
+		    numBytes,			// bufferSize
+		    numBytes * 8,		// bitrate
+		    BifsV2Config,
+		    sizeof(BifsV2Config),
+		    urlBuf);
+	  MP4Free(urlBuf);
+	  urlBuf = NULL;
 
 	MP4Free(sceneCmdBase64);
 	sceneCmdBase64 = NULL;
-	MP4Free(urlBuf);
-	urlBuf = NULL;
 	MP4Free(pBytes);
 	pBytes = NULL;
 
@@ -508,11 +540,11 @@
 	char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);
 
 	urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);
+	if (urlBuf != NULL) {
+	  snprintf(urlBuf, strlen(odCmdBase64) + 64,
+		  "data:application/mpeg4-od-au;base64,%s",
+		  odCmdBase64);
 
-	sprintf(urlBuf, 
-		"data:application/mpeg4-od-au;base64,%s",
-		odCmdBase64);
-
 	VERBOSE_ISMA(GetVerbosity(),
 		printf("OD data URL = \042%s\042\n", urlBuf));
 
@@ -528,12 +560,13 @@
 			0,				// configLength
 			urlBuf);
 
+	MP4Free(urlBuf);
+	urlBuf = NULL;
+	}
 	MP4Free(odCmdBase64);
 	odCmdBase64 = NULL;
 	MP4Free(pBytes);
 	pBytes = NULL;
-	MP4Free(urlBuf);
-	urlBuf = NULL;
 
 	// finally get the whole thing written to a memory 
 	pIod->WriteToMemory(this, ppIodBytes, pIodNumBytes);
@@ -544,7 +577,7 @@
 		printf("IOD data =\n"); MP4HexDump(*ppIodBytes, *pIodNumBytes));
 }
 
-MP4Descriptor* MP4File::CreateESD(
+void MP4File::CreateESD(
 	MP4DescriptorProperty* pEsProperty,
 	u_int32_t esid,
 	u_int8_t objectType,
@@ -551,7 +584,7 @@
 	u_int8_t streamType,
 	u_int32_t bufferSize,
 	u_int32_t bitrate,
-	u_int8_t* pConfig,
+	const u_int8_t* pConfig,
 	u_int32_t configLength,
 	char* url)
 {
@@ -564,62 +597,63 @@
 		pEsProperty->AddDescriptor(MP4ESDescrTag);
 	pEsd->Generate();
 
-	pEsd->FindProperty("ESID", 
-		(MP4Property**)&pInt);
-	pInt->SetValue(esid);
+	if (pEsd->FindProperty("ESID", 
+			       (MP4Property**)&pInt))
+	  pInt->SetValue(esid);
 
-	pEsd->FindProperty("decConfigDescr.objectTypeId", 
-		(MP4Property**)&pInt);
-	pInt->SetValue(objectType);
+	if (pEsd->FindProperty("decConfigDescr.objectTypeId", 
+			       (MP4Property**)&pInt))
+	  pInt->SetValue(objectType);
 
-	pEsd->FindProperty("decConfigDescr.streamType", 
-		(MP4Property**)&pInt);
-	pInt->SetValue(streamType);
+	if (pEsd->FindProperty("decConfigDescr.streamType",
+			       (MP4Property**)&pInt))
+	  pInt->SetValue(streamType);
 
-	pEsd->FindProperty("decConfigDescr.bufferSizeDB", 
-		(MP4Property**)&pInt);
-	pInt->SetValue(bufferSize);
+	if (pEsd->FindProperty("decConfigDescr.bufferSizeDB", 
+			       (MP4Property**)&pInt))
+	  pInt->SetValue(bufferSize);
 
-	pEsd->FindProperty("decConfigDescr.maxBitrate", 
-		(MP4Property**)&pInt);
-	pInt->SetValue(bitrate);
+	if (pEsd->FindProperty("decConfigDescr.maxBitrate", 
+			       (MP4Property**)&pInt))
+	  pInt->SetValue(bitrate);
 
-	pEsd->FindProperty("decConfigDescr.avgBitrate", 
-		(MP4Property**)&pInt);
-	pInt->SetValue(bitrate);
+	if (pEsd->FindProperty("decConfigDescr.avgBitrate", 
+			       (MP4Property**)&pInt))
+	  pInt->SetValue(bitrate);
 	
 	MP4DescriptorProperty* pConfigDescrProperty;
-	pEsd->FindProperty("decConfigDescr.decSpecificInfo",
-		(MP4Property**)&pConfigDescrProperty);
+	if (pEsd->FindProperty("decConfigDescr.decSpecificInfo",
+			       (MP4Property**)&pConfigDescrProperty)) {
 
 	MP4Descriptor* pConfigDescr =
 		pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag);
 	pConfigDescr->Generate();
 
-	pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
-		(MP4Property**)&pBytes);
-	pBytes->SetValue(pConfig, configLength);
+	if (pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
+					       (MP4Property**)&pBytes))
+	  pBytes->SetValue(pConfig, configLength);
+	}
 
-	pEsd->FindProperty("slConfigDescr.predefined", 
-		(MP4Property**)&pInt);
-	// changed 12/5/02 from plugfest to value 0
-	pInt->SetValue(0);
+	if (pEsd->FindProperty("slConfigDescr.predefined", 
+			       (MP4Property**)&pInt))
+	  // changed 12/5/02 from plugfest to value 0
+	  pInt->SetValue(0);
 
-	pEsd->FindProperty("slConfig.useAccessUnitEndFlag",
-			   (MP4Property **)&pBits);
-	pBits->SetValue(1);
+	if (pEsd->FindProperty("slConfig.useAccessUnitEndFlag",
+			       (MP4Property **)&pBits))
+	    pBits->SetValue(1);
 
 	if (url) {
-		pEsd->FindProperty("URLFlag", 
-			(MP4Property**)&pInt);
-		pInt->SetValue(1);
+	  if (pEsd->FindProperty("URLFlag", 
+				 (MP4Property**)&pInt))
+	    pInt->SetValue(1);
 
-		pEsd->FindProperty("URL", 
-			(MP4Property**)&pString);
-		pString->SetValue(url);
+	  if (pEsd->FindProperty("URL", 
+				 (MP4Property**)&pString))
+	    pString->SetValue(url);
 	}
 
-	return pEsd;
+	//return pEsd;
 }
 
 void MP4File::CreateIsmaODUpdateCommandFromFileForFile(
@@ -659,13 +693,13 @@
 		pOd->Generate();
 
 		MP4BitfieldProperty* pOdIdProperty = NULL;
-		pOd->FindProperty("objectDescriptorId", 
-			(MP4Property**)&pOdIdProperty);
-		pOdIdProperty->SetValue(odId);
+		if (pOd->FindProperty("objectDescriptorId", 
+				      (MP4Property**)&pOdIdProperty))
+		  pOdIdProperty->SetValue(odId);
 
 		MP4DescriptorProperty* pEsIdsDescriptorProperty = NULL;
-		pOd->FindProperty("esIds", 
-			(MP4Property**)&pEsIdsDescriptorProperty);
+		ASSERT(pOd->FindProperty("esIds", 
+					 (MP4Property**)&pEsIdsDescriptorProperty));
 		ASSERT(pEsIdsDescriptorProperty);
 
 		pEsIdsDescriptorProperty->SetTags(MP4ESIDRefDescrTag);
@@ -675,8 +709,8 @@
 		pRefDescriptor->Generate();
 
 		MP4Integer16Property* pRefIndexProperty = NULL;
-		pRefDescriptor->FindProperty("refIndex", 
-			(MP4Property**)&pRefIndexProperty);
+		ASSERT(pRefDescriptor->FindProperty("refIndex", 
+						    (MP4Property**)&pRefIndexProperty));
 		ASSERT(pRefIndexProperty);
 
 		u_int32_t mpodIndex = FindTrackReference(
@@ -717,23 +751,25 @@
 
 		pAudioEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
 		// ESID is 0 for file, stream needs to be non-ze
-		pAudioEsd->FindProperty("ESID", 
-					(MP4Property**)&pAudioEsdId);
+		ASSERT(pAudioEsd->FindProperty("ESID", 
+					       (MP4Property**)&pAudioEsdId));
 
 		ASSERT(pAudioEsdId);
 		pAudioEsdId->SetValue(audioTrackId);
 
 		// SL config needs to change from 2 (file) to 1 (null)
-		pAudioEsd->FindProperty("slConfigDescr.predefined", 
-			(MP4Property**)&pAudioSLConfigPredef);
-		ASSERT(pAudioSLConfigPredef);
-		pAudioSLConfigPredef->SetValue(0);
+		if (pAudioEsd->FindProperty("slConfigDescr.predefined", 
+					    (MP4Property**)&pAudioSLConfigPredef)) {
+		  ASSERT(pAudioSLConfigPredef);
+		  pAudioSLConfigPredef->SetValue(0);
+		}
 
-		pAudioEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
-					(MP4Property **)&pAudioAccessUnitEndFlag);
-		oldAudioUnitEndFlagValue = 
-		  pAudioAccessUnitEndFlag->GetValue();
-		pAudioAccessUnitEndFlag->SetValue(1);
+		if (pAudioEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
+					    (MP4Property **)&pAudioAccessUnitEndFlag)) {
+		  oldAudioUnitEndFlagValue = 
+		    pAudioAccessUnitEndFlag->GetValue();
+		  pAudioAccessUnitEndFlag->SetValue(1);
+		}
 	}
 
 	if (videoTrackId != MP4_INVALID_TRACK_ID) {
@@ -744,23 +780,24 @@
 		ASSERT(pEsdsAtom);
 
 		pVideoEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
-		pVideoEsd->FindProperty("ESID", 
-					(MP4Property**)&pVideoEsdId);
+		ASSERT(pVideoEsd->FindProperty("ESID", 
+					       (MP4Property**)&pVideoEsdId));
 
 		ASSERT(pVideoEsdId);
 		pVideoEsdId->SetValue(videoTrackId);
 
 		// SL config needs to change from 2 (file) to 1 (null)
-		pVideoEsd->FindProperty("slConfigDescr.predefined", 
-			(MP4Property**)&pVideoSLConfigPredef);
+		ASSERT(pVideoEsd->FindProperty("slConfigDescr.predefined", 
+					       (MP4Property **)&pVideoSLConfigPredef));
 		ASSERT(pVideoSLConfigPredef);
 		pVideoSLConfigPredef->SetValue(0);
 
-		pVideoEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
-					(MP4Property **)&pVideoAccessUnitEndFlag);
-		oldVideoUnitEndFlagValue = 
-		  pVideoAccessUnitEndFlag->GetValue();
-		pVideoAccessUnitEndFlag->SetValue(1);
+		if (pVideoEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
+					    (MP4Property **)&pVideoAccessUnitEndFlag)) {
+		  oldVideoUnitEndFlagValue = 
+		    pVideoAccessUnitEndFlag->GetValue();
+		  pVideoAccessUnitEndFlag->SetValue(1);
+		}
 	}
 
 	CreateIsmaODUpdateCommandForStream(
@@ -834,9 +871,10 @@
 		}
 
 		MP4BitfieldProperty* pOdIdProperty = NULL;
-		pOd->FindProperty("objectDescriptorId", 
-			(MP4Property**)&pOdIdProperty);
-		pOdIdProperty->SetValue(odId);
+		if (pOd->FindProperty("objectDescriptorId", 
+				      (MP4Property**)&pOdIdProperty)) {
+		  pOdIdProperty->SetValue(odId);
+		}
 
 		delete (MP4DescriptorProperty*)pOd->GetProperty(4);
 		pOd->SetProperty(4, pEsdProperty);
@@ -864,11 +902,11 @@
 	u_int64_t* pNumBytes)
 {
 	// from ISMA 1.0 Tech Spec Appendix E
-	static u_int8_t bifsAudioOnly[] = {
+	static const u_int8_t bifsAudioOnly[] = {
 		0xC0, 0x10, 0x12, 
 		0x81, 0x30, 0x2A, 0x05, 0x6D, 0xC0
 	};
-	static u_int8_t bifsVideoOnly[] = {
+	static const u_int8_t bifsVideoOnly[] = {
 		0xC0, 0x10, 0x12, 
 		0x61, 0x04, 
 			0x1F, 0xC0, 0x00, 0x00, 
@@ -875,7 +913,7 @@
 			0x1F, 0xC0, 0x00, 0x00,
 		0x44, 0x28, 0x22, 0x82, 0x9F, 0x80
 	};
-	static u_int8_t bifsAudioVideo[] = {
+	static const u_int8_t bifsAudioVideo[] = {
 		0xC0, 0x10, 0x12, 
 		0x81, 0x30, 0x2A, 0x05, 0x6D, 0x26,
 		0x10, 0x41, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
--- a/common/mp4v2/libmp4v260.dsp
+++ /dev/null
@@ -1,561 +1,0 @@
-# Microsoft Developer Studio Project File - Name="libmp4v2" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=libmp4v2 - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "libmp4v260.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "libmp4v260.mak" CFG="libmp4v2 - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "libmp4v2 - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "libmp4v2 - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "libmp4v2 - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# SUBTRACT CPP /Fr
-# ADD BASE RSC /l 0x409
-# ADD RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "libmp4v2 - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
-# ADD BASE RSC /l 0x409
-# ADD RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "libmp4v2 - Win32 Release"
-# Name "libmp4v2 - Win32 Debug"
-# Begin Group "source"
-
-# PROP Default_Filter ".c, .cpp"
-# Begin Source File
-
-SOURCE=.\3gp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_bitr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_co64.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_cprt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_ctts.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_d263.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_damr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dimm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dinf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dmax.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dmed.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dref.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_drep.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_edts.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_elst.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_enca.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_encv.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_esds.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_free.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_frma.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_ftyp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hdlr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hinf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hmhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hnti.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_iKMS.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_iods.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_iSFM.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_maxr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mdat.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mdhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mdia.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_meta.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mfhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_minf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_moof.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_moov.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mp4a.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mp4s.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mp4v.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mvex.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mvhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_nmhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_nump.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_payt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_pmax.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_root.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_rtp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_s263.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_samr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_sawb.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_schi.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_schm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_sdp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_sinf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_smhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_snro.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stbl.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stco.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stdp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsc.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsh.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stss.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsz.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stts.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tfhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tims.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tkhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tmax.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tmin.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tpyl.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_traf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trak.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tref.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_treftype.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trex.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trpy.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trun.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tsro.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_udta.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_url.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_urn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_vmhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\descriptors.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\isma.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4atom.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4container.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4descriptor.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4file.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4file_io.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4info.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4meta.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4property.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4track.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4util.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\ocidescriptors.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\odcommands.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\qosqualifiers.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\rtphint.cpp
-# End Source File
-# End Group
-# Begin Group "include"
-
-# PROP Default_Filter ".h"
-# Begin Source File
-
-SOURCE=.\atoms.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\descriptors.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4array.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4atom.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4common.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4container.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4descriptor.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4file.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4property.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4track.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4util.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ocidescriptors.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\odcommands.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\qosqualifiers.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\rtphint.h
-# End Source File
-# End Group
-# End Target
-# End Project
--- a/common/mp4v2/libmp4v2_st60.dsp
+++ /dev/null
@@ -1,568 +1,0 @@
-# Microsoft Developer Studio Project File - Name="libmp4v2_st" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=libmp4v2_st - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "libmp4v2_st60.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "libmp4v2_st60.mak" CFG="libmp4v2_st - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "libmp4v2_st - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "libmp4v2_st - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=xicl6.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "libmp4v2_st - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "ST_Release"
-# PROP Intermediate_Dir "ST_Release"
-# PROP Target_Dir ""
-MTL=midl.exe
-F90=df.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD BASE RSC /l 0x409
-# ADD RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "libmp4v2_st - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "ST_Debug"
-# PROP Intermediate_Dir "ST_Debug"
-# PROP Target_Dir ""
-MTL=midl.exe
-F90=df.exe
-# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
-# ADD BASE RSC /l 0x409
-# ADD RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "libmp4v2_st - Win32 Release"
-# Name "libmp4v2_st - Win32 Debug"
-# Begin Group "source"
-
-# PROP Default_Filter ".c, .cpp"
-# Begin Source File
-
-SOURCE=.\3gp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_bitr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_co64.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_cprt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_ctts.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_d263.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_damr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dimm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dinf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dmax.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dmed.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_dref.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_drep.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_edts.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_elst.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_esds.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_free.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_ftyp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hdlr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hinf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hmhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_hnti.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_iods.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_maxr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mdat.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mdhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mdia.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_meta.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mfhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_minf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_moof.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_moov.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mp4a.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mp4s.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mp4v.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mvex.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_mvhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_nmhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_nump.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_payt.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_pmax.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_root.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_rtp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_s263.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_samr.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_sawb.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_sdp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_smhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_snro.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stbl.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stco.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stdp.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsc.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsh.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stss.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stsz.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_stts.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tfhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tims.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tkhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tmax.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tmin.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tpyl.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_traf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trak.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tref.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_treftype.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trex.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trpy.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_trun.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_tsro.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_udta.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_url.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_urn.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_vmhd.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\descriptors.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\isma.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4atom.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4container.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4descriptor.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4file.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4file_io.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4meta.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4property.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4track.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4util.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\need_for_win32.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\ocidescriptors.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\odcommands.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\qosqualifiers.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\rtphint.cpp
-# End Source File
-# End Group
-# Begin Group "include"
-
-# PROP Default_Filter ".h"
-# Begin Source File
-
-SOURCE=.\atoms.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\descriptors.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4array.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4atom.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4common.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4container.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4descriptor.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4file.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4property.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4track.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4util.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ocidescriptors.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\odcommands.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\qosqualifiers.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\rtphint.h
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\atom_enca.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_encv.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_frma.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_iKMS.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_iSFM.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_schi.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_schm.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\atom_sinf.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\mp4info.cpp
-# End Source File
-# End Target
-# End Project
--- /dev/null
+++ b/common/mp4v2/libmp4v2_st60.vcproj
@@ -1,0 +1,1475 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="libmp4v2_st"
+	ProjectGUID="{55C87BFB-9C9C-41E0-B9DC-57F41F679D4B}"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory=".\ST_Release"
+			IntermediateDirectory=".\ST_Release"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories="..\..\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				PrecompiledHeaderFile=".\ST_Release/libmp4v2_st60.pch"
+				AssemblerListingLocation=".\ST_Release/"
+				ObjectFile=".\ST_Release/"
+				ProgramDataBaseFileName=".\ST_Release/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile=".\ST_Release\libmp4v2_st60.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\ST_Release/libmp4v2_st60.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory=".\ST_Debug"
+			IntermediateDirectory=".\ST_Debug"
+			ConfigurationType="4"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="false"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="..\..\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				RuntimeLibrary="1"
+				PrecompiledHeaderFile=".\ST_Debug/libmp4v2_st60.pch"
+				AssemblerListingLocation=".\ST_Debug/"
+				ObjectFile=".\ST_Debug/"
+				ProgramDataBaseFileName=".\ST_Debug/"
+				WarningLevel="3"
+				SuppressStartupBanner="true"
+				DebugInformationFormat="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				Culture="1033"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile=".\ST_Debug\libmp4v2_st60.lib"
+				SuppressStartupBanner="true"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+				SuppressStartupBanner="true"
+				OutputFile=".\ST_Debug/libmp4v2_st60.bsc"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="source"
+			Filter=".c, .cpp"
+			>
+			<File
+				RelativePath="3gp.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\atom_amr.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\atom_avc1.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\atom_avcC.cpp"
+				>
+			</File>
+			<File
+				RelativePath="atom_d263.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_damr.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_dref.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_elst.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_enca.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_encv.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_free.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_ftyp.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\atom_gmin.cpp"
+				>
+			</File>
+			<File
+				RelativePath="atom_hdlr.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_hinf.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_hnti.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\atom_href.cpp"
+				>
+			</File>
+			<File
+				RelativePath="atom_mdat.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_mdhd.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_meta.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_mp4a.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_mp4s.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_mp4v.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_mvhd.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\atom_ohdr.cpp"
+				>
+			</File>
+			<File
+				RelativePath="atom_root.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_rtp.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_s263.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_sdp.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\atom_smi.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\atom_sound.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\atom_standard.cpp"
+				>
+			</File>
+			<File
+				RelativePath="atom_stbl.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_stdp.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_stsc.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_stsd.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_stsz.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\atom_stz2.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\atom_text.cpp"
+				>
+			</File>
+			<File
+				RelativePath="atom_tfhd.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_tkhd.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_treftype.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_trun.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_udta.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_url.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="atom_urn.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\atom_video.cpp"
+				>
+			</File>
+			<File
+				RelativePath="atom_vmhd.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="descriptors.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="isma.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4atom.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4container.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4descriptor.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4file.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4file_io.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4info.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4meta.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4property.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4track.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="mp4util.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\need_for_win32.c"
+				>
+			</File>
+			<File
+				RelativePath="ocidescriptors.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="odcommands.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="qosqualifiers.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="rtphint.cpp"
+				>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						AdditionalIncludeDirectories=""
+						PreprocessorDefinitions=""
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\virtual_io.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="include"
+			Filter=".h"
+			>
+			<File
+				RelativePath="atoms.h"
+				>
+			</File>
+			<File
+				RelativePath="descriptors.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4array.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4atom.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4common.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4container.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4descriptor.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4file.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4property.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4track.h"
+				>
+			</File>
+			<File
+				RelativePath="mp4util.h"
+				>
+			</File>
+			<File
+				RelativePath=".\mpeg4ip.h"
+				>
+			</File>
+			<File
+				RelativePath=".\mpeg4ip_version.h"
+				>
+			</File>
+			<File
+				RelativePath="ocidescriptors.h"
+				>
+			</File>
+			<File
+				RelativePath="odcommands.h"
+				>
+			</File>
+			<File
+				RelativePath="qosqualifiers.h"
+				>
+			</File>
+			<File
+				RelativePath="rtphint.h"
+				>
+			</File>
+			<File
+				RelativePath=".\virtual_io.h"
+				>
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- a/common/mp4v2/mp4.cpp
+++ b/common/mp4v2/mp4.cpp
@@ -13,7 +13,7 @@
  * 
  * The Initial Developer of the Original Code is Cisco Systems Inc.
  * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001 - 2004.  All Rights Reserved.
+ * 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.
@@ -25,6 +25,7 @@
  *		Dave Mackie			[email protected]
  *		Alix Marchandise-Franquet	[email protected]
  *              Ximpo Group Ltd.                [email protected]
+ *              Bill May                        [email protected]
  */
 
 /* 
@@ -41,6 +42,25 @@
 	VERBOSE_ERROR(((MP4File*)hFile)->GetVerbosity(), e->Print());
 
 /* file operations */
+// benski>
+ extern "C" MP4FileHandle MP4ReadEx (const char* fileName,
+				     void *user, 
+				     struct Virtual_IO *virtual_IO, 
+				     u_int32_t verbosity)
+{
+  MP4File* pFile = NULL;
+  try {
+    pFile = new MP4File(verbosity);
+    
+    pFile->ReadEx(fileName, user, virtual_IO);
+    return (MP4FileHandle)pFile;
+  } catch (MP4Error* e) {
+    VERBOSE_ERROR(verbosity, e->Print());
+    delete e; 
+    delete pFile;
+    return MP4_INVALID_FILE_HANDLE;
+  }
+}
 
 extern "C" MP4FileHandle MP4Read(const char* fileName, u_int32_t verbosity)
 {
@@ -58,20 +78,30 @@
 	}
 }
 
-extern "C" MP4FileHandle MP4CreateEx(const char* fileName,
-		u_int32_t verbosity, u_int32_t  flags,
-		char* majorBrand, u_int32_t minorVersion,
-		char** supportedBrands, u_int32_t supportedBrandsCount)
+extern "C" MP4FileHandle MP4Create (const char* fileName,
+				    u_int32_t verbosity, 
+				    u_int32_t  flags)
 {
+  return MP4CreateEx(fileName, verbosity, flags);
+}
+
+extern "C" MP4FileHandle MP4CreateEx (const char* fileName,
+				      u_int32_t verbosity, 
+				      u_int32_t  flags,
+				      int add_ftyp,
+				      int add_iods,
+				      char* majorBrand, 
+				      u_int32_t minorVersion,
+				      char** supportedBrands, 
+				      u_int32_t supportedBrandsCount)
+{
 	MP4File* pFile = NULL;
 	try {
 		pFile = new MP4File(verbosity);
 		// LATER useExtensibleFormat, moov first, then mvex's
-		if (!majorBrand) {
-			pFile->Create(fileName, flags);
-		} else {
-			pFile->CreateEx(fileName, flags, majorBrand, minorVersion, supportedBrands, supportedBrandsCount);
-                }
+		pFile->Create(fileName, flags, add_ftyp, add_iods,
+			      majorBrand, minorVersion, 
+			      supportedBrands, supportedBrandsCount);
 		return (MP4FileHandle)pFile;
 	}
 	catch (MP4Error* e) {
@@ -82,13 +112,6 @@
 	}
 }
 
-extern "C" MP4FileHandle MP4Create(const char* fileName, 
-				   u_int32_t verbosity, 
-				   u_int32_t flags)
-{
-	return MP4CreateEx(fileName, verbosity, flags, NULL, 0, NULL, 0 );
-}
-
 extern "C" MP4FileHandle MP4Modify(const char* fileName, 
 	u_int32_t verbosity, u_int32_t flags)
 {
@@ -96,15 +119,16 @@
 	try {
 		pFile = new MP4File(verbosity);
 		// LATER useExtensibleFormat, moov first, then mvex's
-		pFile->Modify(fileName);
+		if (pFile->Modify(fileName))
 		return (MP4FileHandle)pFile;
 	}
 	catch (MP4Error* e) {
 		VERBOSE_ERROR(verbosity, e->Print());
 		delete e;
-		delete pFile;
-		return MP4_INVALID_FILE_HANDLE;
 	}
+
+	if (pFile) delete pFile;
+	return MP4_INVALID_FILE_HANDLE;
 }
 
 extern "C" bool MP4Optimize(const char* existingFileName, 
@@ -124,13 +148,13 @@
 	return false;
 }
 
-extern "C" bool MP4Close(MP4FileHandle hFile)
+extern "C" void MP4Close(MP4FileHandle hFile)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
 			((MP4File*)hFile)->Close();
 			delete (MP4File*)hFile;
-			return true;
+			return;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -137,7 +161,7 @@
 			delete e;
 		}
 	}
-	return false;
+	return ;
 }
 
 extern "C" bool MP4Dump(
@@ -175,12 +199,12 @@
 	return 0;
 }
 
-extern "C" bool MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity)
+extern "C" void MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
 			((MP4File*)hFile)->SetVerbosity(verbosity);
-			return true;
+			return;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -187,7 +211,7 @@
 			delete e;
 		}
 	}
-	return false;
+	return;
 }
 
 extern "C" MP4Duration MP4GetDuration(MP4FileHandle hFile)
@@ -291,7 +315,8 @@
 	return false;
 }
 
-extern "C" u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile)
+extern "C" u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile,
+					    MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
@@ -301,16 +326,43 @@
 			PRINT_ERROR(e);
 			delete e;
 		}
+		if (MP4_IS_VALID_TRACK_ID(trackId)) {
+		  uint8_t *foo;
+		  uint32_t bufsize;
+		  uint8_t type;
+		  // for mpeg4 video tracks, try to look for the VOSH header,
+		  // which has this info.
+		  type = MP4GetTrackEsdsObjectTypeId(hFile, trackId);
+		  if (type == MP4_MPEG4_VIDEO_TYPE) {
+		    if (MP4GetTrackESConfiguration(hFile, 
+						   trackId,
+						   &foo, 
+						   &bufsize)) {
+		      uint8_t *ptr = foo;
+		      while (bufsize > 0) {
+			if (htonl(*(uint32_t *)ptr) == 0x1b0) {
+			  uint8_t ret = ptr[4];
+			  free(foo);
+			  return ret;
+			}
+			ptr++;
+			bufsize--;
+		      }
+		      free(foo);
+		    }
+		  }
+		}
+		  
 	}
 	return 0;
 }
 
-extern "C" bool MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value)
+extern "C" void MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
 			((MP4File*)hFile)->SetVideoProfileLevel(value);
-			return true;
+			return ;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -317,7 +369,7 @@
 			delete e;
 		}
 	}
-	return false;
+	return ;
 }
 
 extern "C" u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile)
@@ -334,12 +386,11 @@
 	return 0;
 }
 
-extern "C" bool MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value)
+extern "C" void MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
 			((MP4File*)hFile)->SetAudioProfileLevel(value);
-			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -346,7 +397,6 @@
 			delete e;
 		}
 	}
-	return false;
 }
 
 extern "C" u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile)
@@ -380,12 +430,26 @@
 
 /* generic file properties */
 
-extern "C" u_int64_t MP4GetIntegerProperty(
-	MP4FileHandle hFile, const char* propName)
+extern "C" bool MP4HaveAtom (MP4FileHandle hFile, const char *atomName)
 {
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File *)hFile)->FindAtom(atomName) != NULL;
+    } catch (MP4Error *e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
+extern "C" bool MP4GetIntegerProperty(
+	MP4FileHandle hFile, const char* propName, u_int64_t *retvalue)
+{
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetIntegerProperty(propName);
+			*retvalue = ((MP4File*)hFile)->GetIntegerProperty(propName);
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -392,15 +456,16 @@
 			delete e;
 		}
 	}
-	return (u_int64_t)-1;
+	return false;
 }
 
-extern "C" float MP4GetFloatProperty(
-	MP4FileHandle hFile, const char* propName)
+extern "C" bool MP4GetFloatProperty(
+	MP4FileHandle hFile, const char* propName, float *retvalue)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetFloatProperty(propName);
+			*retvalue = ((MP4File*)hFile)->GetFloatProperty(propName);
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -407,15 +472,17 @@
 			delete e;
 		}
 	}
-	return NAN;
+	return false;
 }
 
-extern "C" const char* MP4GetStringProperty(
-	MP4FileHandle hFile, const char* propName)
+extern "C" bool MP4GetStringProperty(
+	MP4FileHandle hFile, const char* propName,
+	const char **retvalue)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetStringProperty(propName);
+			*retvalue =  ((MP4File*)hFile)->GetStringProperty(propName);
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -422,10 +489,10 @@
 			delete e;
 		}
 	}
-	return NULL;
+	return false;
 }
 
-extern "C" void MP4GetBytesProperty(
+extern "C" bool MP4GetBytesProperty(
 	MP4FileHandle hFile, const char* propName, 
 	u_int8_t** ppValue, u_int32_t* pValueSize)
 {
@@ -432,7 +499,7 @@
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
 			((MP4File*)hFile)->GetBytesProperty(propName, ppValue, pValueSize);
-			return;
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -441,7 +508,7 @@
 	}
 	*ppValue = NULL;
 	*pValueSize = 0;
-	return;
+	return false;
 }
 
 extern "C" bool MP4SetIntegerProperty(
@@ -588,22 +655,50 @@
 	return MP4_INVALID_TRACK_ID;
 }
 
+//
+// API to initialize ismacryp properties to sensible defaults.
+// if the input pointer is null then an ismacryp params is malloc'd.
+// caller must see to it that it is properly disposed of.
+//
+extern "C" mp4v2_ismacrypParams *MP4DefaultISMACrypParams(mp4v2_ismacrypParams *ptr)
+{
+    try
+    {
+        if (ptr == NULL) {
+            ptr = (mp4v2_ismacrypParams *)MP4Malloc(sizeof(mp4v2_ismacrypParams));
+        }
+        memset(ptr, 0, sizeof(*ptr));
+        return ptr;
+    }
+
+    catch (...) {
+      return MP4_INVALID_TRACK_ID;
+    }
+}
+
+
 extern "C" MP4TrackId MP4AddEncAudioTrack(MP4FileHandle hFile, 
 					  u_int32_t timeScale, 
 					  MP4Duration sampleDuration,
                                           mp4v2_ismacrypParams *icPp,
-					  u_int8_t audioType
-                                          )
+					  u_int8_t audioType)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->
-	AddEncAudioTrack(timeScale, sampleDuration, audioType,
-                         icPp->scheme_type, icPp->scheme_version, 
-                         icPp->key_ind_len, icPp->iv_len, 
-                         icPp->selective_enc, icPp->kms_uri);
-    }
-    catch (MP4Error* e) {
+      if (icPp == NULL) {
+	return ((MP4File*)hFile)->
+	  AddEncAudioTrack(timeScale, sampleDuration, audioType,
+			   0, 0, 
+			   0, 0, 
+			   false, NULL, false);
+      } else {
+	return ((MP4File*)hFile)->
+	  AddEncAudioTrack(timeScale, sampleDuration, audioType,
+			   icPp->scheme_type, icPp->scheme_version, 
+			   icPp->key_ind_len, icPp->iv_len, 
+			   icPp->selective_enc, icPp->kms_uri, true);
+      }
+    } catch (MP4Error* e) {
       PRINT_ERROR(e);
       delete e;
     }
@@ -682,19 +777,14 @@
 	}
 }
 
-
-extern "C" MP4TrackId MP4AddVideoTrack(
-	MP4FileHandle hFile, 
-	u_int32_t timeScale, 
-	MP4Duration sampleDuration,
-	u_int16_t width, 
-	u_int16_t height, 
-	u_int8_t videoType)
+extern "C" uint16_t MP4GetAmrModeSet(
+				     MP4FileHandle hFile,
+				     MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->AddVideoTrack(
-				timeScale, sampleDuration, width, height, videoType);
+		  return ((MP4File*)hFile)->
+				GetAmrModeSet(trackId);
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -701,9 +791,72 @@
 			delete e;
 		}
 	}
-	return MP4_INVALID_TRACK_ID;
+	return 0;
 }
 
+extern "C" MP4TrackId MP4AddHrefTrack (MP4FileHandle hFile,
+				       uint32_t timeScale,
+				       MP4Duration sampleDuration,
+				       const char *base_url)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      MP4File *pFile = (MP4File *)hFile;
+
+      return pFile->AddHrefTrack(timeScale, 
+				 sampleDuration,
+				 base_url);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" const char *MP4GetHrefTrackBaseUrl (MP4FileHandle hFile,
+					       MP4TrackId trackId)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->GetTrackStringProperty(trackId,
+						       "mdia.minf.stbl.stsd.href.burl.base_url");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return NULL;
+}
+
+extern "C" MP4TrackId MP4AddVideoTrack(
+	MP4FileHandle hFile, 
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration,
+	u_int16_t width, 
+	u_int16_t height, 
+	u_int8_t videoType)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      MP4File *pFile = (MP4File *)hFile;
+
+      return pFile->AddMP4VideoTrack(timeScale, 
+				     sampleDuration, 
+				     width, 
+				     height, 
+				     videoType);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return MP4_INVALID_TRACK_ID;
+}
+
 extern "C" MP4TrackId MP4AddEncVideoTrack(MP4FileHandle hFile, 
 					  u_int32_t timeScale, 
 					  MP4Duration sampleDuration,
@@ -710,16 +863,58 @@
 					  u_int16_t width, 
 					  u_int16_t height, 
                                           mp4v2_ismacrypParams *icPp,
-					  u_int8_t videoType )
+					  u_int8_t videoType,
+					  const char *oFormat)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->AddEncVideoTrack(timeScale, sampleDuration, 
-						 width, height, videoType,
-                                                 icPp->scheme_type, icPp->scheme_version, 
-                                                 icPp->key_ind_len, icPp->iv_len, 
-                                                 icPp->selective_enc, icPp->kms_uri);
+
+ 	  // test for valid ismacrypt session descriptor
+      if (icPp == NULL) {
+		return MP4_INVALID_TRACK_ID;
+      }
+      MP4File *pFile = (MP4File *)hFile;
+
+	return pFile->AddEncVideoTrack(timeScale, 
+			sampleDuration, 
+			width, 
+			height, 
+			videoType, 
+			icPp, 
+			oFormat);
+
+    } catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
     }
+  }
+  return MP4_INVALID_TRACK_ID;
+}
+
+
+extern "C" MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile, 
+					   u_int32_t timeScale, 
+					   MP4Duration sampleDuration,
+					   u_int16_t width, 
+					   u_int16_t height, 
+					   uint8_t AVCProfileIndication,
+					   uint8_t profile_compat,
+					   uint8_t AVCLevelIndication,
+					   uint8_t sampleLenFieldSizeMinusOne)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      MP4File *pFile = (MP4File *)hFile;
+
+      return pFile->AddH264VideoTrack(timeScale, 
+				      sampleDuration, 
+				      width, 
+				      height, 
+				      AVCProfileIndication,
+				      profile_compat,
+				      AVCLevelIndication,
+				      sampleLenFieldSizeMinusOne);
+    }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
       delete e;
@@ -727,6 +922,90 @@
   }
   return MP4_INVALID_TRACK_ID;
 }
+
+extern "C" MP4TrackId MP4AddEncH264VideoTrack(
+	MP4FileHandle hFile, 
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration,
+	u_int16_t width, 
+	u_int16_t height, 
+	MP4FileHandle srcFile, 
+	MP4TrackId srcTrackId, 
+    mp4v2_ismacrypParams *icPp
+)
+
+{
+  MP4Atom *srcAtom;
+  MP4File *pFile;
+
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+
+	pFile = (MP4File *)srcFile;
+	srcAtom = pFile->FindTrackAtom(srcTrackId, "mdia.minf.stbl.stsd.avc1.avcC");
+	if (srcAtom == NULL)
+		return MP4_INVALID_TRACK_ID;
+
+	pFile = (MP4File *)hFile;
+
+	return pFile->AddEncH264VideoTrack(timeScale, 
+			 sampleDuration, 
+			 width, 
+			 height, 
+			 srcAtom,
+			 icPp);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" void MP4AddH264SequenceParameterSet (MP4FileHandle hFile,
+						MP4TrackId trackId,
+						const uint8_t *pSequence,
+						uint16_t sequenceLen)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      MP4File *pFile = (MP4File *)hFile;
+
+      pFile->AddH264SequenceParameterSet(trackId,
+					 pSequence,
+					 sequenceLen);
+      return;
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+    return;
+}
+extern "C" void MP4AddH264PictureParameterSet (MP4FileHandle hFile,
+					       MP4TrackId trackId,
+					       const uint8_t *pPict,
+					       uint16_t pictLen)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      MP4File *pFile = (MP4File *)hFile;
+
+      pFile->AddH264PictureParameterSet(trackId,
+					pPict,
+					pictLen);
+      return;
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+    return;
+}
+
 extern "C" MP4TrackId MP4AddH263VideoTrack(
 		MP4FileHandle hFile,
 		u_int32_t timeScale,
@@ -821,130 +1100,238 @@
 	return MP4_INVALID_TRACK_ID;
 }
 
-extern "C" MP4TrackId MP4CloneTrack(
-	MP4FileHandle srcFile, 
-	MP4TrackId srcTrackId,
-	MP4FileHandle dstFile,
-	MP4TrackId dstHintTrackReferenceTrack)
+extern "C" MP4TrackId MP4AddTextTrack(
+	MP4FileHandle hFile, MP4TrackId refTrackId)
 {
-	MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
-
-	if (dstFile == NULL) {
-		dstFile = srcFile;
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			return ((MP4File*)hFile)->AddTextTrack(refTrackId);
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
 	}
+	return MP4_INVALID_TRACK_ID;
+}
 
-	const char* trackType = 
-		MP4GetTrackType(srcFile, srcTrackId);
-
-	if (!trackType) {
-		return dstTrackId;
+extern "C" MP4TrackId MP4AddChapterTextTrack(
+	MP4FileHandle hFile, MP4TrackId refTrackId)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			return ((MP4File*)hFile)->AddChapterTextTrack(refTrackId);
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
 	}
+	return MP4_INVALID_TRACK_ID;
+}
 
-	if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
-                MP4SetVideoProfileLevel(dstFile, 
-                                        MP4GetVideoProfileLevel(srcFile));
-		dstTrackId = MP4AddVideoTrack(
-			dstFile,
-			MP4GetTrackTimeScale(srcFile, srcTrackId),
-			MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
-			MP4GetTrackVideoWidth(srcFile, srcTrackId),
-			MP4GetTrackVideoHeight(srcFile, srcTrackId),
-			MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId));
 
-	} else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
-                MP4SetAudioProfileLevel(dstFile, 
-                                        MP4GetAudioProfileLevel(srcFile));
-		dstTrackId = MP4AddAudioTrack(
-			dstFile,
-			MP4GetTrackTimeScale(srcFile, srcTrackId),
-			MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
-			MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId));
+extern "C" MP4TrackId MP4CloneTrack (MP4FileHandle srcFile, 
+				     MP4TrackId srcTrackId,
+				     MP4FileHandle dstFile,
+				     MP4TrackId dstHintTrackReferenceTrack)
+{
+  MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
 
-	} else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
-		dstTrackId = MP4AddODTrack(dstFile);
+  if (dstFile == NULL) {
+    dstFile = srcFile;
+  }
 
-	} else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) {
-		dstTrackId = MP4AddSceneTrack(dstFile);
+  const char* trackType = 
+    MP4GetTrackType(srcFile, srcTrackId);
 
-	} else if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
-	  if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) {
-	    dstTrackId = MP4_INVALID_TRACK_ID;
-	  } else {
-		dstTrackId = MP4AddHintTrack(
-			dstFile,
-			dstHintTrackReferenceTrack);
-	  }
+  if (!trackType) {
+    return dstTrackId;
+  }
 
-	} else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) {
-		dstTrackId = MP4AddSystemsTrack(dstFile, trackType);
+  const char *media_data_name = 
+    MP4GetTrackMediaDataName(srcFile, srcTrackId);
+  if (media_data_name == NULL) return dstTrackId;
 
-	} else {
-		dstTrackId = MP4AddTrack(dstFile, trackType);
+  if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+    if (ATOMID(media_data_name) == ATOMID("mp4v")) {
+      MP4SetVideoProfileLevel(dstFile, 
+			      MP4GetVideoProfileLevel(srcFile));
+      dstTrackId = MP4AddVideoTrack(
+				    dstFile,
+				    MP4GetTrackTimeScale(srcFile, 
+							 srcTrackId),
+				    MP4GetTrackFixedSampleDuration(srcFile, 
+								   srcTrackId),
+				    MP4GetTrackVideoWidth(srcFile, 
+							  srcTrackId),
+				    MP4GetTrackVideoHeight(srcFile, 
+							   srcTrackId),
+				    MP4GetTrackEsdsObjectTypeId(srcFile, 
+								srcTrackId));
+    } else if (ATOMID(media_data_name) == ATOMID("avc1")) {
+      uint8_t AVCProfileIndication;
+      uint8_t profile_compat;
+      uint8_t AVCLevelIndication;
+      uint32_t sampleLenFieldSizeMinusOne;
+      uint64_t temp;
+      
+      if (MP4GetTrackH264ProfileLevel(srcFile, srcTrackId, 
+				      &AVCProfileIndication,
+				      &AVCLevelIndication) == false) {
+	return dstTrackId;
+      }
+      if (MP4GetTrackH264LengthSize(srcFile, srcTrackId, 
+				    &sampleLenFieldSizeMinusOne) == false) {
+	return dstTrackId;
+      }
+      sampleLenFieldSizeMinusOne--;
+      if (MP4GetTrackIntegerProperty(srcFile, srcTrackId, 
+				     "mdia.minf.stbl.stsd.*[0].avcC.profile_compatibility",
+				     &temp) == false) return dstTrackId;
+      profile_compat = temp & 0xff;
+      
+      dstTrackId = MP4AddH264VideoTrack(dstFile, 
+					MP4GetTrackTimeScale(srcFile, 
+							     srcTrackId),
+					MP4GetTrackFixedSampleDuration(srcFile, 
+								       srcTrackId),
+					MP4GetTrackVideoWidth(srcFile, 
+							      srcTrackId),
+					MP4GetTrackVideoHeight(srcFile, 
+							       srcTrackId),
+					AVCProfileIndication,
+					profile_compat,
+					AVCLevelIndication,
+					sampleLenFieldSizeMinusOne);
+        uint8_t **seqheader, **pictheader;
+	uint32_t *pictheadersize, *seqheadersize;
+	uint32_t ix;
+	MP4GetTrackH264SeqPictHeaders(srcFile, srcTrackId, 
+				      &seqheader, &seqheadersize,
+				      &pictheader, &pictheadersize);
+	for (ix = 0; seqheadersize[ix] != 0; ix++) {
+	  MP4AddH264SequenceParameterSet(dstFile, dstTrackId,
+					 seqheader[ix], seqheadersize[ix]);
+	  free(seqheader[ix]);
 	}
-
-	if (dstTrackId == MP4_INVALID_TRACK_ID) {
-		return dstTrackId;
+	free(seqheader);
+	free(seqheadersize);
+	for (ix = 0; pictheadersize[ix] != 0; ix++) {
+	  MP4AddH264PictureParameterSet(dstFile, dstTrackId,
+					pictheader[ix], pictheadersize[ix]);
+	  free(pictheader[ix]);
 	}
+	free(pictheader);
+	free(pictheadersize);
+    } else
+      return dstTrackId;
+  } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
+    if (ATOMID(media_data_name) != ATOMID("mp4a")) return dstTrackId;
+    MP4SetAudioProfileLevel(dstFile, 
+			    MP4GetAudioProfileLevel(srcFile));
+    dstTrackId = MP4AddAudioTrack(
+				  dstFile,
+				  MP4GetTrackTimeScale(srcFile, srcTrackId),
+				  MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
+				  MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId));
 
-	MP4SetTrackTimeScale(
-		dstFile, 
-		dstTrackId,
-		MP4GetTrackTimeScale(srcFile, srcTrackId));
+  } else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
+    dstTrackId = MP4AddODTrack(dstFile);
 
-	if (MP4_IS_AUDIO_TRACK_TYPE(trackType) 
-	    || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
-	// copy track ES configuration
-	u_int8_t* pConfig = NULL;
-	u_int32_t configSize = 0;
+  } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) {
+    dstTrackId = MP4AddSceneTrack(dstFile);
 
-	MP4GetTrackESConfiguration(
-		srcFile, 
-		srcTrackId,
-		&pConfig,
-		&configSize);
+  } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
+    if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) {
+      dstTrackId = MP4_INVALID_TRACK_ID;
+    } else {
+      dstTrackId = MP4AddHintTrack(
+				   dstFile,
+				   dstHintTrackReferenceTrack);
+    }
 
-	MP4SetTrackESConfiguration(
-		dstFile, 
-		dstTrackId,
-		pConfig,
-		configSize);
+  } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) {
+    dstTrackId = MP4AddSystemsTrack(dstFile, trackType);
 
-		free(pConfig);
-	}
+  } else {
+    dstTrackId = MP4AddTrack(dstFile, trackType);
+  }
 
-	if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
-		// probably not exactly what is wanted
-		// but caller can adjust later to fit their desires
+  if (dstTrackId == MP4_INVALID_TRACK_ID) {
+    return dstTrackId;
+  }
 
-		char* payloadName = NULL;
-		char *encodingParms = NULL;
-		u_int8_t payloadNumber;
-		u_int16_t maxPayloadSize;
+  MP4SetTrackTimeScale(
+		       dstFile, 
+		       dstTrackId,
+		       MP4GetTrackTimeScale(srcFile, srcTrackId));
 
-		MP4GetHintTrackRtpPayload(
-			srcFile,
-			srcTrackId,
-			&payloadName,
-			&payloadNumber,
-			&maxPayloadSize,
-			&encodingParms);
+  if (MP4_IS_AUDIO_TRACK_TYPE(trackType) 
+      || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+    // copy track ES configuration
+    u_int8_t* pConfig = NULL;
+    u_int32_t configSize = 0;
+    uint32_t verb = MP4GetVerbosity(srcFile);
+    MP4SetVerbosity(srcFile, verb & ~(MP4_DETAILS_ERROR));
+    bool haveEs = MP4GetTrackESConfiguration(srcFile, 
+					     srcTrackId,
+					     &pConfig,
+					     &configSize);
+    MP4SetVerbosity(srcFile, verb);
+    if (haveEs &&
+	pConfig != NULL && configSize != 0) {
+      if (!MP4SetTrackESConfiguration(
+				      dstFile, 
+				      dstTrackId,
+				      pConfig,
+				      configSize)) {
+	free(pConfig);
+	MP4DeleteTrack(dstFile, dstTrackId);
+	return MP4_INVALID_TRACK_ID;
+      }
+	    
+      free(pConfig);
+    }
+  }
 
-		MP4SetHintTrackRtpPayload(
-			dstFile,
-			dstTrackId,
-			payloadName,
-			&payloadNumber,
-			maxPayloadSize,
-			encodingParms);
+  if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
+    // probably not exactly what is wanted
+    // but caller can adjust later to fit their desires
+
+    char* payloadName = NULL;
+    char *encodingParms = NULL;
+    u_int8_t payloadNumber;
+    u_int16_t maxPayloadSize;
+
+    if (MP4GetHintTrackRtpPayload(
+			      srcFile,
+			      srcTrackId,
+			      &payloadName,
+			      &payloadNumber,
+			      &maxPayloadSize,
+			      &encodingParms)) {
+
+      if (MP4SetHintTrackRtpPayload(
+				    dstFile,
+				    dstTrackId,
+				    payloadName,
+				    &payloadNumber,
+				    maxPayloadSize,
+				    encodingParms) == false) {
+	MP4DeleteTrack(dstFile, dstTrackId);
+	return MP4_INVALID_TRACK_ID;
+      }
+    }
 #if 0
-		MP4SetHintTrackSdp(
-			dstFile,
-			dstTrackId,
-			MP4GetHintTrackSdp(srcFile, srcTrackId));
+    MP4SetHintTrackSdp(
+		       dstFile,
+		       dstTrackId,
+		       MP4GetHintTrackSdp(srcFile, srcTrackId));
 #endif
-	}
+  }
 
-	return dstTrackId;
+  return dstTrackId;
 }
 
 // Given a track, make an encrypted clone of it in the dest. file
@@ -955,6 +1342,8 @@
 					  MP4TrackId dstHintTrackReferenceTrack
                                           )
 {
+  const char *oFormat;
+
   MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
 
   if (dstFile == NULL) {
@@ -961,8 +1350,7 @@
     dstFile = srcFile;
   }
 
-  const char* trackType = 
-    MP4GetTrackType(srcFile, srcTrackId);
+  const char* trackType = MP4GetTrackType(srcFile, srcTrackId);
 
   if (!trackType) {
     return dstTrackId;
@@ -969,17 +1357,34 @@
   }
 
   if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+
+    // test source file format for avc1
+    oFormat = MP4GetTrackMediaDataName(srcFile, srcTrackId);
+    if (!strcasecmp(oFormat, "avc1"))
+    {
+        dstTrackId = MP4AddEncH264VideoTrack(dstFile,
+				MP4GetTrackTimeScale(srcFile, srcTrackId),
+				MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
+				MP4GetTrackVideoWidth(srcFile, srcTrackId),
+				MP4GetTrackVideoHeight(srcFile, srcTrackId),
+				srcFile, 
+				srcTrackId,
+				icPp
+                     );
+    }
+    else
+    {
     MP4SetVideoProfileLevel(dstFile, MP4GetVideoProfileLevel(srcFile));
     dstTrackId = MP4AddEncVideoTrack(dstFile,
 				     MP4GetTrackTimeScale(srcFile, srcTrackId),
-				     MP4GetTrackFixedSampleDuration(srcFile, 
-								    srcTrackId),
+				MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
 				     MP4GetTrackVideoWidth(srcFile, srcTrackId),
 				     MP4GetTrackVideoHeight(srcFile, srcTrackId),
                                      icPp,
-				     MP4GetTrackEsdsObjectTypeId(srcFile, 
-								 srcTrackId)
+				MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId),
+				oFormat
                                      );
+    }
 
   } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
     MP4SetAudioProfileLevel(dstFile, MP4GetAudioProfileLevel(srcFile));
@@ -1048,15 +1453,15 @@
     u_int8_t payloadNumber;
     u_int16_t maxPayloadSize;
 
-    MP4GetHintTrackRtpPayload(
-                               srcFile,
-			       srcTrackId,
-			       &payloadName,
-			       &payloadNumber,
-			       &maxPayloadSize,
-			       &encodingParms);
+    if (MP4GetHintTrackRtpPayload(
+				  srcFile,
+				  srcTrackId,
+				  &payloadName,
+				  &payloadNumber,
+				  &maxPayloadSize,
+				  &encodingParms)) {
 
-       MP4SetHintTrackRtpPayload(
+      (void)MP4SetHintTrackRtpPayload(
 		                 dstFile,
 			         dstTrackId,
 			         payloadName,
@@ -1063,6 +1468,7 @@
 			         &payloadNumber,
 			         maxPayloadSize,
 			         encodingParms);	
+    }
 #if 0
       MP4SetHintTrackSdp(
                          dstFile,
@@ -1073,6 +1479,7 @@
 
   return dstTrackId;
 }
+
 extern "C" MP4TrackId MP4CopyTrack(MP4FileHandle srcFile, 
 				   MP4TrackId srcTrackId,
 				   MP4FileHandle dstFile, 
@@ -1252,7 +1659,7 @@
   return dstTrackId;
 }
 
-extern "C" bool MP4DeleteTrack(
+extern "C" void MP4DeleteTrack(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId)
 {
@@ -1259,7 +1666,7 @@
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
 			((MP4File*)hFile)->DeleteTrack(trackId);
-			return true;
+			return ;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1266,7 +1673,7 @@
 			delete e;
 		}
 	}
-	return false;
+	return;
 }
 
 extern "C" u_int32_t MP4GetNumberOfTracks(
@@ -1335,13 +1742,12 @@
 	}
 	return NULL;
 }
-
-extern "C" MP4Duration MP4GetTrackDuration(
+extern "C" const char* MP4GetTrackMediaDataName(
 	MP4FileHandle hFile, MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetTrackDuration(trackId);
+			return ((MP4File*)hFile)->GetTrackMediaDataName(trackId);
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1348,15 +1754,18 @@
 			delete e;
 		}
 	}
-	return MP4_INVALID_DURATION;
+	return NULL;
 }
 
-extern "C" u_int32_t MP4GetTrackTimeScale(
-	MP4FileHandle hFile, MP4TrackId trackId)
+extern "C" bool MP4GetTrackMediaDataOriginalFormat(
+	MP4FileHandle hFile, MP4TrackId trackId, char *originalFormat,
+	u_int32_t buflen)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetTrackTimeScale(trackId);
+
+			return ((MP4File*)hFile)->GetTrackMediaDataOriginalFormat(trackId, 
+				originalFormat, buflen);
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1363,16 +1772,15 @@
 			delete e;
 		}
 	}
-	return 0;
+	return false;
 }
 
-extern "C" bool MP4SetTrackTimeScale(
-	MP4FileHandle hFile, MP4TrackId trackId, u_int32_t value)
+extern "C" MP4Duration MP4GetTrackDuration(
+	MP4FileHandle hFile, MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			((MP4File*)hFile)->SetTrackTimeScale(trackId, value);
-			return true;
+			return ((MP4File*)hFile)->GetTrackDuration(trackId);
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1379,19 +1787,15 @@
 			delete e;
 		}
 	}
-	return false;
+	return MP4_INVALID_DURATION;
 }
 
-
-// This function should not be used anymore  
-// use MP4GetTrackEsdsObjectTypeId instead 
-extern "C" u_int8_t MP4GetTrackAudioType(
-     MP4FileHandle hFile, MP4TrackId trackId)
+extern "C" u_int32_t MP4GetTrackTimeScale(
+	MP4FileHandle hFile, MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-		  
-		  return ((MP4File*)hFile)->GetTrackAudioType(trackId);
+			return ((MP4File*)hFile)->GetTrackTimeScale(trackId);
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1398,15 +1802,16 @@
 			delete e;
 		}
 	}
-	return MP4_INVALID_AUDIO_TYPE;
+	return 0;
 }
 
-extern "C" u_int8_t MP4GetTrackAudioMpeg4Type(
-	MP4FileHandle hFile, MP4TrackId trackId)
+extern "C" void MP4SetTrackTimeScale(
+	MP4FileHandle hFile, MP4TrackId trackId, u_int32_t value)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetTrackAudioMpeg4Type(trackId);
+			((MP4File*)hFile)->SetTrackTimeScale(trackId, value);
+			return;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1413,18 +1818,15 @@
 			delete e;
 		}
 	}
-	return MP4_MPEG4_INVALID_AUDIO_TYPE;
+	return;
 }
 
-
-// This function should not be used anymore  
-// use MP4GetTrackEsdsObjectTypeId instead 
-extern "C" u_int8_t MP4GetTrackVideoType(
+extern "C" u_int8_t MP4GetTrackAudioMpeg4Type(
 	MP4FileHandle hFile, MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetTrackVideoType(trackId);
+			return ((MP4File*)hFile)->GetTrackAudioMpeg4Type(trackId);
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1431,9 +1833,11 @@
 			delete e;
 		}
 	}
-	return MP4_INVALID_VIDEO_TYPE;
+	return MP4_MPEG4_INVALID_AUDIO_TYPE;
 }
 
+
+
 // Replacement to MP4GetTrackVideoType and MP4GetTrackAudioType
 // Basically does the same thing but with a more self-explanatory name
 extern "C" u_int8_t MP4GetTrackEsdsObjectTypeId(
@@ -1471,14 +1875,36 @@
 	MP4FileHandle hFile, MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+	  MP4File *pFile = (MP4File *)hFile;
 		try {
-			return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
+		  return pFile->GetTrackIntegerProperty(trackId,
 				"mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate");
 		}
 		catch (MP4Error* e) {
-			PRINT_ERROR(e);
+		  //PRINT_ERROR(e);  we don't really need to print this.
 			delete e;
 		}
+		// if we're here, we can't get the bitrate from above - 
+		// lets calculate it
+		try {
+		  MP4Duration trackDur;
+		  trackDur = MP4GetTrackDuration(hFile, trackId);
+		  uint64_t msDuration = 
+		    pFile->ConvertFromTrackDuration(trackId, trackDur, 
+						    MP4_MSECS_TIME_SCALE);
+		  if (msDuration == 0) return 0;
+
+		  MP4Track *pTrack = pFile->GetTrack(trackId);
+		  uint64_t bytes = pTrack->GetTotalOfSampleSizes();
+		  bytes *= TO_U64(8 * 1000);
+		  bytes /= msDuration;
+		  return (uint32_t)bytes;
+		}
+		catch (MP4Error* e) {
+		  PRINT_ERROR(e); // print this one.
+			delete e;
+		}
+		
 	}
 	return 0;
 }
@@ -1502,6 +1928,25 @@
 	*pConfigSize = 0;
 	return false;
 }
+extern "C" bool MP4GetTrackVideoMetadata(
+	MP4FileHandle hFile, MP4TrackId trackId, 
+	u_int8_t** ppConfig, u_int32_t* pConfigSize)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			((MP4File*)hFile)->GetTrackVideoMetadata(
+				trackId, ppConfig, pConfigSize);
+			return true;
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
+	}
+	*ppConfig = NULL;
+	*pConfigSize = 0;
+	return false;
+}
 
 extern "C" bool MP4SetTrackESConfiguration(
 	MP4FileHandle hFile, MP4TrackId trackId, 
@@ -1521,6 +1966,71 @@
 	return false;
 }
 
+extern "C" bool MP4GetTrackH264ProfileLevel (MP4FileHandle hFile, 
+					     MP4TrackId trackId,
+					     uint8_t *pProfile,
+					     uint8_t *pLevel)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      *pProfile = 
+	((MP4File *)hFile)->GetTrackIntegerProperty(trackId, 
+						    "mdia.minf.stbl.stsd.*[0].avcC.AVCProfileIndication");
+      *pLevel = 
+	((MP4File *)hFile)->GetTrackIntegerProperty(trackId, 
+						    "mdia.minf.stbl.stsd.*[0].avcC.AVCLevelIndication");
+
+      return true;
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+extern "C" void MP4GetTrackH264SeqPictHeaders (MP4FileHandle hFile, 
+					       MP4TrackId trackId,
+					       uint8_t ***pSeqHeader,
+					       uint32_t **pSeqHeaderSize,
+					       uint8_t ***pPictHeader,
+					       uint32_t **pPictHeaderSize)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      ((MP4File*)hFile)->GetTrackH264SeqPictHeaders(trackId, 
+						    pSeqHeader,
+						    pSeqHeaderSize,
+						    pPictHeader,
+						    pPictHeaderSize);
+      return;
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return;
+}
+extern "C" bool MP4GetTrackH264LengthSize (MP4FileHandle hFile, 
+					   MP4TrackId trackId,
+					   uint32_t *pLength)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      *pLength = 1 + 
+	((MP4File*) hFile)->GetTrackIntegerProperty(trackId, 
+						   "mdia.minf.stbl.stsd.*[0].avcC.lengthSizeMinusOne");
+      return true;
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+  
 extern "C" MP4SampleId MP4GetTrackNumberOfSamples(
 	MP4FileHandle hFile, MP4TrackId trackId)
 {
@@ -1568,7 +2078,7 @@
 	return 0;
 }
 
-extern "C" float MP4GetTrackVideoFrameRate(
+extern "C" double MP4GetTrackVideoFrameRate(
 	MP4FileHandle hFile, MP4TrackId trackId)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
@@ -1583,13 +2093,32 @@
 	return 0.0;
 }
 
+extern "C" int MP4GetTrackAudioChannels (MP4FileHandle hFile,
+					      MP4TrackId trackId)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			return ((MP4File*)hFile)->GetTrackAudioChannels(trackId);
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
+	}
+	return -1;
+}
+
 // returns true if the track is a media track encrypted according to ismacryp
 extern "C" bool MP4IsIsmaCrypMediaTrack(
 	MP4FileHandle hFile, MP4TrackId trackId)
 {
+  bool retval = false;
+  uint32_t verb = MP4GetVerbosity(hFile);
+  MP4SetVerbosity(hFile, verb & ~(MP4_DETAILS_ERROR));
+
         if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
                try {
-                       return ((MP4File*)hFile)->IsIsmaCrypMediaTrack(trackId); 
+		 retval = ((MP4File*)hFile)->IsIsmaCrypMediaTrack(trackId); 
 	       }
                catch (MP4Error* e) {
                        PRINT_ERROR(e);
@@ -1596,20 +2125,39 @@
                        delete e;
                }
         }
-        return false;
+	MP4SetVerbosity(hFile, verb);
+        return retval;
 }
 
 
 /* generic track properties */
 
-extern "C" u_int64_t MP4GetTrackIntegerProperty (
+extern "C" bool MP4HaveTrackAtom (MP4FileHandle hFile, 
+				  MP4TrackId trackId, 
+				  const char *atomName)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->FindTrackAtom(trackId, atomName) != NULL;
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+				  
+extern "C" bool MP4GetTrackIntegerProperty (
 	MP4FileHandle hFile, MP4TrackId trackId, 
-	const char* propName)
+	const char* propName,
+	u_int64_t *retvalue)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, 
+			*retvalue = ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, 
 				propName);
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1616,33 +2164,18 @@
 			delete e;
 		}
 	}
-	return (u_int64_t)-1;
-}
-extern "C" bool MP4HaveTrackIntegerProperty(
-	MP4FileHandle hFile, MP4TrackId trackId,
-	const char* propName)
-{
-  // The same as MP4GetTrackIntegerProperty but with no error reporting
-	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
-		try {
-			return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, 
-				propName) != (u_int64_t)-1;
-		}
-		catch (MP4Error* e) {
-			// No error reporting
-			delete e;
-		}
-	}
 	return false;
 }
 
-extern "C" float MP4GetTrackFloatProperty(
+extern "C" bool MP4GetTrackFloatProperty(
 	MP4FileHandle hFile, MP4TrackId trackId, 
-	const char* propName)
+	const char* propName,
+	float *retvalue)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetTrackFloatProperty(trackId, propName);
+			*retvalue = ((MP4File*)hFile)->GetTrackFloatProperty(trackId, propName);
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1649,16 +2182,18 @@
 			delete e;
 		}
 	}
-	return NAN;
+	return false;
 }
 
-extern "C" const char* MP4GetTrackStringProperty(
+extern "C" bool MP4GetTrackStringProperty(
 	MP4FileHandle hFile, MP4TrackId trackId, 
-	const char* propName)
+	const char* propName,
+	const char **retvalue)
 {
 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
 		try {
-			return ((MP4File*)hFile)->GetTrackStringProperty(trackId, propName);
+			*retvalue = ((MP4File*)hFile)->GetTrackStringProperty(trackId, propName);
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1665,10 +2200,10 @@
 			delete e;
 		}
 	}
-	return NULL;
+	return false;
 }
 
-extern "C" void MP4GetTrackBytesProperty(
+extern "C" bool MP4GetTrackBytesProperty(
 	MP4FileHandle hFile, MP4TrackId trackId, const char* propName, 
 	u_int8_t** ppValue, u_int32_t* pValueSize)
 {
@@ -1676,7 +2211,7 @@
 		try {
 			((MP4File*)hFile)->GetTrackBytesProperty(
 				trackId, propName, ppValue, pValueSize);
-			return;
+			return true;
 		}
 		catch (MP4Error* e) {
 			PRINT_ERROR(e);
@@ -1685,7 +2220,7 @@
 	}
 	*ppValue = NULL;
 	*pValueSize = 0;
-	return;
+	return false;
 }
 
 extern "C" bool MP4SetTrackIntegerProperty(
@@ -2684,11 +3219,14 @@
 	u_int32_t supportedBrandsCount,
 	bool deleteIodsAtom)
 {
-	MP4File* pFile = NULL;
+	MP4File* pFile;
+	pFile = NULL;
 
 	try {
 		pFile = new MP4File(verbosity);
+		pFile->Modify(fileName);
 		pFile->Make3GPCompliant(fileName, majorBrand, minorVersion, supportedBrands, supportedBrandsCount, deleteIodsAtom);
+		pFile->Close();
 		delete pFile;
 		return true;
 	}
@@ -2707,7 +3245,8 @@
 	u_int32_t verbosity,
 	bool addIsmaComplianceSdp)
 {
-	MP4File* pFile = NULL;
+	MP4File* pFile;
+	pFile = NULL;
 
 	try {
 		pFile = new MP4File(verbosity);
@@ -2762,7 +3301,7 @@
 
 		char* sdpIod = 
 			(char*)MP4Malloc(strlen(iodBase64) + 64);
-		sprintf(sdpIod,
+		snprintf(sdpIod, strlen(iodBase64) + 64, 
 			"a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042",
 			iodBase64);
 		MP4Free(iodBase64);
@@ -2775,7 +3314,6 @@
 		VERBOSE_ERROR(verbosity, e->Print());
 		delete e;
 	}
-	delete pFile;
 	return NULL;
 }
 
@@ -2840,7 +3378,7 @@
 			return ((MP4File*)hFile)->GetTrackNumberOfEdits(trackId);
 		}
 		catch (MP4Error* e) {
-			PRINT_ERROR(e);
+			//PRINT_ERROR(e);
 			delete e;
 		}
 	}
@@ -3062,7 +3600,7 @@
 
 /* iTunes meta data handling */
 extern "C" bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index,
-				      const char** ppName,
+				      char** ppName,
 				      u_int8_t** ppValue, u_int32_t* pValueSize)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
@@ -3097,7 +3635,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataName(value);
+      return ((MP4File*)hFile)->SetMetadataString("\251nam", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3112,7 +3650,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataName(value);
+      return ((MP4File*)hFile)->GetMetadataString("\251nam", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3122,12 +3660,26 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataName(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251nam");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+ 
 extern "C" bool MP4SetMetadataWriter(MP4FileHandle hFile,
 				     const char* value)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataWriter(value);
+      return ((MP4File*)hFile)->SetMetadataString("\251wrt", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3142,7 +3694,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataWriter(value);
+      return ((MP4File*)hFile)->GetMetadataString("\251wrt", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3152,12 +3704,26 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataWriter(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251wrt");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+ 
 extern "C" bool MP4SetMetadataAlbum(MP4FileHandle hFile,
 				    const char* value)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataAlbum(value);
+      return ((MP4File*)hFile)->SetMetadataString("\251alb", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3172,7 +3738,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataAlbum(value);
+      return ((MP4File*)hFile)->GetMetadataString("\251alb", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3181,13 +3747,27 @@
   }
   return false;
 }
- 
+
+extern "C" bool MP4DeleteMetadataAlbum(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251alb");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataArtist(MP4FileHandle hFile,
 				     const char* value)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataArtist(value);
+      return ((MP4File*)hFile)->SetMetadataString("\251ART", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3202,7 +3782,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataArtist(value);
+      return ((MP4File*)hFile)->GetMetadataString("\251ART", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3212,12 +3792,26 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataArtist(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251ART");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataTool(MP4FileHandle hFile,
 				   const char* value)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataTool(value);
+      return ((MP4File*)hFile)->SetMetadataString("\251too", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3232,7 +3826,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataTool(value);
+      return ((MP4File*)hFile)->GetMetadataString("\251too", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3242,12 +3836,26 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataTool(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251too");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataComment(MP4FileHandle hFile,
 				      const char* value)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataComment(value);
+      return ((MP4File*)hFile)->SetMetadataString("\251cmt", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3262,7 +3870,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataComment(value);
+      return ((MP4File*)hFile)->GetMetadataString("\251cmt", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3272,12 +3880,26 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataComment(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251cmt");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataYear(MP4FileHandle hFile,
 				   const char* value)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataYear(value);
+      return ((MP4File*)hFile)->SetMetadataString("\251day", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3292,7 +3914,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataYear(value);
+      return ((MP4File*)hFile)->GetMetadataString("\251day", value);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3302,6 +3924,20 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataYear(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251day");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataTrack(MP4FileHandle hFile,
 				    u_int16_t track, u_int16_t totalTracks)
 {
@@ -3332,6 +3968,20 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataTrack(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("trkn");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataDisk(MP4FileHandle hFile,
 				   u_int16_t disk, u_int16_t totalDisks)
 {
@@ -3362,6 +4012,20 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataDisk(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("disk");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
@@ -3390,6 +4054,62 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataGenre(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataGenre();
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
+extern "C" bool MP4SetMetadataGrouping(MP4FileHandle hFile, const char *grouping)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->SetMetadataString("\251grp", grouping);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+ 
+extern "C" bool MP4GetMetadataGrouping(MP4FileHandle hFile, char **grouping)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->GetMetadataString("\251grp", grouping);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+ 
+extern "C" bool MP4DeleteMetadataGrouping(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("\251grp");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
@@ -3418,11 +4138,25 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataTempo(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("tmpo");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataCompilation(cpl);
+      return ((MP4File*)hFile)->SetMetadataUint8("cpil", cpl & 0x1);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3436,7 +4170,7 @@
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataCompilation(cpl);
+      return ((MP4File*)hFile)->GetMetadataUint8("cpil", cpl);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3446,6 +4180,64 @@
   return false;
 }
  
+extern "C" bool MP4DeleteMetadataCompilation(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("cpil");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
+extern "C" bool MP4SetMetadataPartOfGaplessAlbum (MP4FileHandle hFile, 
+						  u_int8_t pgap)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->SetMetadataUint8("pgap", pgap & 0x1);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+ 
+extern "C" bool MP4GetMetadataPartOfGaplessAlbum (MP4FileHandle hFile, 
+						  u_int8_t* pgap)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->GetMetadataUint8("pgap", pgap);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+ 
+extern "C" bool MP4DeleteMetadataPartOfGaplessAlbum (MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("pgap");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
 extern "C" bool MP4SetMetadataCoverArt(MP4FileHandle hFile,
 				       u_int8_t *coverArt, u_int32_t size)
 {
@@ -3462,11 +4254,12 @@
 }
  
 extern "C" bool MP4GetMetadataCoverArt(MP4FileHandle hFile,
-				       u_int8_t **coverArt, u_int32_t* size)
+				       u_int8_t **coverArt, u_int32_t* size,
+				       uint32_t index)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataCoverArt(coverArt, size);
+      return ((MP4File*)hFile)->GetMetadataCoverArt(coverArt, size, index);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3475,13 +4268,12 @@
   }
   return false;
 }
- 
-extern "C" bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name,
-				       u_int8_t* pValue, u_int32_t valueSize)
+
+extern "C" u_int32_t MP4GetMetadataCoverArtCount(MP4FileHandle hFile)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->SetMetadataFreeForm(name, pValue, valueSize);
+      return ((MP4File*)hFile)->GetMetadataCoverArtCount();
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3489,14 +4281,89 @@
     }
   }
   return false;
+} 
+
+extern "C" bool MP4DeleteMetadataCoverArt(MP4FileHandle hFile)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataAtom("covr");
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
 }
+extern "C" bool MP4SetMetadataAlbumArtist (MP4FileHandle hFile,
+					   const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+   try {
+     return ((MP4File*)hFile)->SetMetadataString("aART", value);
+   }
+   catch (MP4Error* e) {
+     PRINT_ERROR(e);
+     delete e;
+   }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataAlbumArtist (MP4FileHandle hFile,
+					   char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+   try {
+     return ((MP4File*)hFile)->GetMetadataString("aART", value);
+   }
+   catch (MP4Error* e) {
+     PRINT_ERROR(e);
+     delete e;
+   }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataAlbumArtist (MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+   try {
+     return ((MP4File*)hFile)->DeleteMetadataAtom("aART");
+   }
+   catch (MP4Error* e) {
+     PRINT_ERROR(e);
+     delete e;
+   }
+ }
+ return false;
+} 
+
+extern "C" bool MP4SetMetadataFreeForm(MP4FileHandle hFile, 
+				       const char *name,
+				       const u_int8_t* pValue, 
+				       u_int32_t valueSize,
+							 const char *owner)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->SetMetadataFreeForm(name, pValue, valueSize, owner);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
  
-extern "C" bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name,
-				       u_int8_t** pValue, u_int32_t* valueSize)
+extern "C" bool MP4GetMetadataFreeForm(MP4FileHandle hFile, const char *name,
+				       u_int8_t** pValue, u_int32_t* valueSize, const char *owner)
 {
   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
     try {
-      return ((MP4File*)hFile)->GetMetadataFreeForm(name, pValue, valueSize);
+      return ((MP4File*)hFile)->GetMetadataFreeForm(name, pValue, valueSize, owner);
     }
     catch (MP4Error* e) {
       PRINT_ERROR(e);
@@ -3504,4 +4371,25 @@
     }
   }
   return false;
+}
+
+extern "C" bool MP4DeleteMetadataFreeForm(MP4FileHandle hFile, const char *name, const char *owner)
+{
+  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+    try {
+      return ((MP4File*)hFile)->DeleteMetadataFreeForm(name, owner);
+    }
+    catch (MP4Error* e) {
+      PRINT_ERROR(e);
+      delete e;
+    }
+  }
+  return false;
+}
+
+
+extern "C" void MP4Free (void *p)
+{
+  if (p != NULL)
+    free(p);
 }
--- a/common/mp4v2/mp4.h
+++ b/common/mp4v2/mp4.h
@@ -13,7 +13,7 @@
  * 
  * The Initial Developer of the Original Code is Cisco Systems Inc.
  * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001 - 2004.  All Rights Reserved.
+ * 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.
@@ -25,6 +25,7 @@
  *		Dave Mackie			[email protected]
  *		Alix Marchandise-Franquet	[email protected]
  *              Ximpo Group Ltd.                [email protected]
+ *              Bill May                        [email protected]
  */
 
 #ifndef __MP4_INCLUDED__
@@ -32,12 +33,12 @@
 
 /* include system and project specific headers */
 #include "mpeg4ip.h"
-
 #include <math.h>	/* to define float HUGE_VAL and/or NAN */
 #ifndef NAN
 #define NAN HUGE_VAL
 #endif
 
+#ifndef DEFAULT
 #ifdef __cplusplus
 /* exploit C++ ability of default values for function parameters */
 #define DEFAULT(x)	=x
@@ -44,6 +45,7 @@
 #else
 #define DEFAULT(x)
 #endif
+#endif
 
 /* MP4 API types */
 typedef void*		MP4FileHandle;
@@ -53,6 +55,26 @@
 typedef u_int64_t	MP4Duration;
 typedef u_int32_t	MP4EditId;
 
+typedef u_int64_t (*VIRTUALIO_GETFILELENGTH)(void *user); // return file length in bytes
+typedef int (*VIRTUALIO_SETPOSITION)(void *user, u_int64_t position); // return 0 on success
+typedef int (*VIRTUALIO_GETPOSITION)(void *user, u_int64_t *position); // fill position, return 0 on success
+typedef size_t (*VIRTUALIO_READ)(void *user, void *buffer, size_t size); // return number of bytes actually read
+typedef size_t (*VIRTUALIO_WRITE)(void *user, void *buffer, size_t size); // return number of bytes actually written
+typedef int (*VIRTUALIO_ENDOFFILE)(void *user); // return 1 if file hit EOF
+typedef int (*VIRTUALIO_CLOSE)(void *user); // return 0 on success
+
+typedef struct Virtual_IO
+{
+	VIRTUALIO_GETFILELENGTH	GetFileLength;
+	VIRTUALIO_SETPOSITION SetPosition;
+	VIRTUALIO_GETPOSITION GetPosition;
+	VIRTUALIO_READ Read;
+	VIRTUALIO_WRITE Write;
+	VIRTUALIO_ENDOFFILE EndOfFile;
+	VIRTUALIO_CLOSE Close;
+} Virtual_IO_t;
+
+
 /* Invalid values for API types */
 #define MP4_INVALID_FILE_HANDLE	((MP4FileHandle)NULL)
 #define MP4_INVALID_TRACK_ID	((MP4TrackId)0)
@@ -98,6 +120,8 @@
 #define MP4_AUDIO_TRACK_TYPE	"soun"
 #define MP4_VIDEO_TRACK_TYPE	"vide"
 #define MP4_HINT_TRACK_TYPE		"hint"
+#define MP4_CNTL_TRACK_TYPE     "cntl"
+#define MP4_TEXT_TRACK_TYPE		"text"
 /*
  * This second set of track types should be created 
  * via MP4AddSystemsTrack(type)
@@ -114,6 +138,9 @@
 #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))
 
@@ -155,6 +182,7 @@
 #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
@@ -163,6 +191,11 @@
 #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) \
@@ -174,7 +207,7 @@
 
 #define MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4Type) \
 	(((mpeg4Type) >= MP4_MPEG4_AAC_MAIN_AUDIO_TYPE \
-		&& (mpeg4Type) <= MP4_MPEG4_AAC_LTP_AUDIO_TYPE) \
+		&& (mpeg4Type) <= MP4_MPEG4_AAC_HE_AUDIO_TYPE) \
 	  || (mpeg4Type) == MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE \
           || (mpeg4Type) == 17)
 
@@ -196,7 +229,6 @@
 #define MP4_JPEG_VIDEO_TYPE				0x6C
 #define MP4_PRIVATE_VIDEO_TYPE			0xD0
 #define MP4_YUV12_VIDEO_TYPE			0xF0	/* a private definition */
-#define MP4_H264_VIDEO_TYPE				0xF1	/* a private definition */
 #define MP4_H263_VIDEO_TYPE				0xF2	/* a private definition */
 #define MP4_H261_VIDEO_TYPE				0xF3	/* a private definition */
 
@@ -288,15 +320,16 @@
 	const char* fileName, 
 	u_int32_t verbosity DEFAULT(0),
 	u_int32_t flags DEFAULT(0));
-
 MP4FileHandle MP4CreateEx(
-		const char* fileName,
-		u_int32_t verbosity DEFAULT(0),
-		u_int32_t flags  DEFAULT(0),
-		char* majorBrand DEFAULT(0),
-		u_int32_t minorVersion DEFAULT(0),
-		char** supportedBrands DEFAULT(0),
-		u_int32_t supportedBrandsCount DEFAULT(0));
+        const char *fileName,
+	u_int32_t verbosity DEFAULT(0),
+	u_int32_t flags DEFAULT(0),
+	int add_ftyp DEFAULT(1),
+	int add_iods DEFAULT(1),
+	char* majorBrand DEFAULT(0),
+	u_int32_t minorVersion DEFAULT(0),
+	char** supportedBrands DEFAULT(0),
+	u_int32_t supportedBrandsCount DEFAULT(0));
 
 MP4FileHandle MP4Modify(
 	const char* fileName, 
@@ -307,7 +340,13 @@
 	const char* fileName, 
 	u_int32_t verbosity DEFAULT(0));
 
-bool MP4Close(
+// benski>
+MP4FileHandle MP4ReadEx(const char* fileName,
+			void *user, 
+			Virtual_IO_t *virtual_IO,
+			u_int32_t verbosity DEFAULT(0));
+ 
+void MP4Close(
 	MP4FileHandle hFile);
 
 bool MP4Optimize(
@@ -334,7 +373,7 @@
 
 u_int32_t MP4GetVerbosity(MP4FileHandle hFile);
 
-bool MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity);
+void MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity);
 
 MP4Duration MP4GetDuration(MP4FileHandle hFile);
 
@@ -350,13 +389,14 @@
 
 bool MP4SetSceneProfileLevel(MP4FileHandle hFile, u_int8_t value);
 
-u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile);
+u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile,
+				 MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID));
 
-bool MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value);
+void MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value);
 
 u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile);
 
-bool MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value);
+void MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value);
 
 u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile);
 
@@ -363,24 +403,26 @@
 bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, u_int8_t value);
 
 /* generic file properties */
+bool MP4HaveAtom(MP4FileHandle hFile, 
+		 const char *atomName);
 
-u_int64_t MP4GetIntegerProperty(
+bool MP4GetIntegerProperty(
 	MP4FileHandle hFile, 
-	const char* propName);
+	const char* propName,
+	u_int64_t *retval );
 
-bool MP4HaveTrackIntegerProperty(
-	MP4FileHandle hFile, MP4TrackId trackId, 
-	const char* propName);
 
-float MP4GetFloatProperty(
+bool MP4GetFloatProperty(
 	MP4FileHandle hFile, 
-	const char* propName);
+	const char* propName,
+	float *retvalue);
 
-const char* MP4GetStringProperty(
+bool MP4GetStringProperty(
 	MP4FileHandle hFile, 
-	const char* propName);
+	const char* propName,
+	const char **retvalue);
 
-void MP4GetBytesProperty(
+bool MP4GetBytesProperty(
 	MP4FileHandle hFile, 
 	const char* propName,
 	u_int8_t** ppValue, 
@@ -431,9 +473,12 @@
   u_int8_t  key_ind_len;
   u_int8_t  iv_len;
   u_int8_t  selective_enc;
-  char      *kms_uri;
+  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_ismacrypParams *MP4DefaultISMACrypParams(mp4v2_ismacrypParams *ptr);
 
 MP4TrackId MP4AddEncAudioTrack(
 	MP4FileHandle hFile, 
@@ -441,6 +486,7 @@
 	MP4Duration sampleDuration,
         mp4v2_ismacrypParams *icPp,
 	u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE));
+
 MP4TrackId MP4AddAmrAudioTrack(
 		MP4FileHandle hFile,
 		u_int32_t timeScale,
@@ -459,11 +505,16 @@
 		MP4TrackId trackId,
 		u_int8_t decoderVersion);
 
-void MP4SetAmrModeSet(
-		MP4FileHandle hFile,
-		MP4TrackId trackId,
-		u_int16_t modeSet);
+void MP4SetAmrModeSet(MP4FileHandle hFile, MP4TrackId trakId, uint16_t modeSet);
+uint16_t MP4GetAmrModeSet(MP4FileHandle hFile, MP4TrackId trackId);
 
+MP4TrackId MP4AddHrefTrack(MP4FileHandle hFile, 
+			   uint32_t timeScale, 
+			   MP4Duration sampleDuration,
+			   const char *base_url DEFAULT(NULL));
+
+const char *MP4GetHrefTrackBaseUrl(MP4FileHandle hFile,
+				   MP4TrackId trackId);
 MP4TrackId MP4AddVideoTrack(
 	MP4FileHandle hFile, 
 	u_int32_t timeScale, 
@@ -479,8 +530,38 @@
 	u_int16_t width, 
 	u_int16_t height,
         mp4v2_ismacrypParams *icPp,
-	u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE));
+	u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE),
+	const char *oFormat DEFAULT(NULL));
 
+MP4TrackId MP4AddH264VideoTrack(
+				MP4FileHandle hFile,
+				u_int32_t timeScale, 
+				MP4Duration sampleDuration, 
+				u_int16_t width, 
+				u_int16_t height, 
+				uint8_t AVCProfileIndication,
+				uint8_t profile_compat,
+				uint8_t AVCLevelIndication,
+				uint8_t sampleLenFieldSizeMinusOne);
+
+MP4TrackId MP4AddEncH264VideoTrack(
+				MP4FileHandle dstFile,
+				u_int32_t timeScale, 
+				MP4Duration sampleDuration, 
+				u_int16_t width, 
+				u_int16_t height, 
+				MP4FileHandle srcFile,
+				MP4TrackId srcTrackId,
+				mp4v2_ismacrypParams *icPp);
+
+void MP4AddH264SequenceParameterSet(MP4FileHandle hFile,
+				    MP4TrackId trackId,
+				    const uint8_t *pSequence,
+				    uint16_t sequenceLen);
+void MP4AddH264PictureParameterSet(MP4FileHandle hFile,
+				   MP4TrackId trackId,
+				   const uint8_t *pPict,
+				   uint16_t pictLen);
 void MP4SetH263Vendor(
 		MP4FileHandle hFile,
 		MP4TrackId trackId,
@@ -512,6 +593,14 @@
 	MP4FileHandle hFile, 
 	MP4TrackId refTrackId);
 
+MP4TrackId MP4AddTextTrack(
+	MP4FileHandle hFile, 
+	MP4TrackId refTrackId);
+
+MP4TrackId MP4AddChapterTextTrack(
+	MP4FileHandle hFile, 
+	MP4TrackId refTrackId);
+
 MP4TrackId MP4CloneTrack(
 	MP4FileHandle srcFile, 
 	MP4TrackId srcTrackId,
@@ -544,7 +633,7 @@
 	bool applyEdits DEFAULT(false),
 	MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID));
 
-bool MP4DeleteTrack(
+void MP4DeleteTrack(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
 
@@ -567,10 +656,22 @@
 
 /* specific track properties */
 
+bool MP4HaveTrackAtom(MP4FileHandle hFile, 
+		      MP4TrackId trackId, 
+		      const char *atomname);
+
 const char* MP4GetTrackType(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
 
+const char *MP4GetTrackMediaDataName(MP4FileHandle hFile,
+				     MP4TrackId trackId);
+
+// MP4GetTrackMediaDataOriginalFormat is to be used to get the original
+// MediaDataName if a track has been encrypted.
+bool MP4GetTrackMediaDataOriginalFormat(MP4FileHandle hFile,
+	    MP4TrackId trackId, char *originalFormat, u_int32_t buflen);
+
 MP4Duration MP4GetTrackDuration(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
@@ -579,25 +680,15 @@
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
 
-bool MP4SetTrackTimeScale(
+void MP4SetTrackTimeScale(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId, 
 	u_int32_t value);
 
-// Should not be used, replace with MP4GetTrackEsdsObjectTypeId
-u_int8_t MP4GetTrackAudioType(
-	MP4FileHandle hFile, 
-	MP4TrackId trackId);
-
 u_int8_t MP4GetTrackAudioMpeg4Type(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
 
-// Should not be used, replace with MP4GetTrackEsdsObjectTypeId
-u_int8_t MP4GetTrackVideoType(
-	MP4FileHandle hFile, 
-	MP4TrackId trackId);
-
 u_int8_t MP4GetTrackEsdsObjectTypeId(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
@@ -611,6 +702,11 @@
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
 
+bool MP4GetTrackVideoMetadata(MP4FileHandle hFile,
+			      MP4TrackId trackId,
+			      uint8_t **ppConfig,
+			      uint32_t *pConfigSize);
+
 bool MP4GetTrackESConfiguration(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId, 
@@ -623,6 +719,20 @@
 	const u_int8_t* pConfig, 
 	u_int32_t configSize);
 
+/* h264 information routines */
+bool MP4GetTrackH264ProfileLevel(MP4FileHandle hFile,
+				 MP4TrackId trackId,
+				 uint8_t *pProfile,
+				 uint8_t *pLevel);
+void MP4GetTrackH264SeqPictHeaders(MP4FileHandle hFile,
+				   MP4TrackId trackId,
+				   uint8_t ***pSeqHeaders,
+				   uint32_t **pSeqHeaderSize,
+				   uint8_t ***pPictHeader,
+				   uint32_t **pPictHeaderSize);
+bool MP4GetTrackH264LengthSize(MP4FileHandle hFile,
+			       MP4TrackId trackId,
+			       uint32_t *pLength);
 MP4SampleId MP4GetTrackNumberOfSamples(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
@@ -635,10 +745,13 @@
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
 
-float MP4GetTrackVideoFrameRate(
+double MP4GetTrackVideoFrameRate(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId);
 
+int MP4GetTrackAudioChannels(MP4FileHandle hFile, 
+				  MP4TrackId trackId);
+
 bool MP4IsIsmaCrypMediaTrack(
         MP4FileHandle hFile,
         MP4TrackId trackId);
@@ -645,22 +758,29 @@
 
 /* generic track properties */
 
-u_int64_t MP4GetTrackIntegerProperty(
+bool MP4HaveTrackAtom(MP4FileHandle hFile, 
+		      MP4TrackId trackId, 
+		      const char *atomName);
+			
+bool MP4GetTrackIntegerProperty(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId, 
-	const char* propName);
+	const char* propName,
+	u_int64_t *retvalue);
 
-float MP4GetTrackFloatProperty(
+bool MP4GetTrackFloatProperty(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId, 
-	const char* propName);
+	const char* propName,
+	float *ret_value);
 
-const char* MP4GetTrackStringProperty(
+bool MP4GetTrackStringProperty(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId, 
-	const char* propName);
+	const char* propName,
+	const char **retvalue);
 
-void MP4GetTrackBytesProperty(
+bool MP4GetTrackBytesProperty(
 	MP4FileHandle hFile, 
 	MP4TrackId trackId, 
 	const char* propName,
@@ -1046,46 +1166,73 @@
 /* iTunes metadata handling */
 bool MP4MetadataDelete(MP4FileHandle hFile);
 bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index,
-			   const char** ppName,
-			   u_int8_t** ppValue, u_int32_t* pValueSize);
+			   char** ppName, // need to free memory
+			   u_int8_t** ppValue,  // need to free
+			   u_int32_t* pValueSize);
 bool MP4SetMetadataName(MP4FileHandle hFile, const char* value);
 bool MP4GetMetadataName(MP4FileHandle hFile, char** value);
+bool MP4DeleteMetadataName(MP4FileHandle hFile);
 bool MP4SetMetadataArtist(MP4FileHandle hFile, const char* value);
 bool MP4GetMetadataArtist(MP4FileHandle hFile, char** value);
+bool MP4DeleteMetadataArtist(MP4FileHandle hFile);
 bool MP4SetMetadataWriter(MP4FileHandle hFile, const char* value);
 bool MP4GetMetadataWriter(MP4FileHandle hFile, char** value);
+bool MP4DeleteMetadataWriter(MP4FileHandle hFile);
 bool MP4SetMetadataComment(MP4FileHandle hFile, const char* value);
 bool MP4GetMetadataComment(MP4FileHandle hFile, char** value);
+bool MP4DeleteMetadataComment(MP4FileHandle hFile);
 bool MP4SetMetadataTool(MP4FileHandle hFile, const char* value);
 bool MP4GetMetadataTool(MP4FileHandle hFile, char** value);
+bool MP4DeleteMetadataTool(MP4FileHandle hFile);
 bool MP4SetMetadataYear(MP4FileHandle hFile, const char* value);
 bool MP4GetMetadataYear(MP4FileHandle hFile, char** value);
+bool MP4DeleteMetadataYear(MP4FileHandle hFile);
 bool MP4SetMetadataAlbum(MP4FileHandle hFile, const char* value);
 bool MP4GetMetadataAlbum(MP4FileHandle hFile, char** value);
+bool MP4DeleteMetadataAlbum(MP4FileHandle hFile);
 bool MP4SetMetadataTrack(MP4FileHandle hFile,
 			 u_int16_t track, u_int16_t totalTracks);
 bool MP4GetMetadataTrack(MP4FileHandle hFile,
 			 u_int16_t* track, u_int16_t* totalTracks);
+bool MP4DeleteMetadataTrack(MP4FileHandle hFile);
 bool MP4SetMetadataDisk(MP4FileHandle hFile,
 			u_int16_t disk, u_int16_t totalDisks);
 bool MP4GetMetadataDisk(MP4FileHandle hFile,
 			u_int16_t* disk, u_int16_t* totalDisks);
+bool MP4DeleteMetadataDisk(MP4FileHandle hFile);
 bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre);
 bool MP4GetMetadataGenre(MP4FileHandle hFile, char **genre);
+bool MP4DeleteMetadataGenre(MP4FileHandle hFile);
+bool MP4SetMetadataGrouping(MP4FileHandle hFile, const char *grouping);
+bool MP4GetMetadataGrouping(MP4FileHandle hFile, char **grouping);
+bool MP4DeleteMetadataGrouping(MP4FileHandle hFile);
 bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo);
 bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo);
+bool MP4DeleteMetadataTempo(MP4FileHandle hFile);
 bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl);
 bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl);
+bool MP4DeleteMetadataCompilation(MP4FileHandle hFile);
+bool MP4SetMetadataPartOfGaplessAlbum(MP4FileHandle hFile, uint8_t pgap);
+bool MP4GetMetadataPartOfGaplessAlbum(MP4FileHandle hFile, uint8_t *pgap);
+bool MP4DeleteMetadataPartOfGaplessAlbum(MP4FileHandle hFile);
 bool MP4SetMetadataCoverArt(MP4FileHandle hFile,
 			    u_int8_t *coverArt, u_int32_t size);
 bool MP4GetMetadataCoverArt(MP4FileHandle hFile,
-			    u_int8_t **coverArt, u_int32_t* size);
-bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name,
-			    u_int8_t* pValue, u_int32_t valueSize);
-bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name,
-			    u_int8_t** pValue, u_int32_t* valueSize);
- 
+			    u_int8_t **coverArt, u_int32_t* size,
+			    uint32_t index DEFAULT(0));
+u_int32_t MP4GetMetadataCoverArtCount(MP4FileHandle hFile);
+bool MP4DeleteMetadataCoverArt(MP4FileHandle hFile);
+bool MP4SetMetadataAlbumArtist(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataAlbumArtist(MP4FileHandle hFile,    char** value);
+bool MP4DeleteMetadataAlbumArtist(MP4FileHandle hFile); 
 
+
+bool MP4SetMetadataFreeForm(MP4FileHandle hFile, const char *name,
+			    const u_int8_t* pValue, u_int32_t valueSize, const char *owner DEFAULT(NULL));
+bool MP4GetMetadataFreeForm(MP4FileHandle hFile, const char *name,
+			    u_int8_t** pValue, u_int32_t* valueSize, const char *owner DEFAULT(NULL));
+bool MP4DeleteMetadataFreeForm(MP4FileHandle hFile, const char *name, const char *owner DEFAULT(NULL));
+
 /* time conversion utilties */
 
 /* predefined values for timeScale parameter below */
@@ -1135,6 +1282,13 @@
 char* MP4BinaryToBase64(
 	const u_int8_t* pData, 
 	u_int32_t dataSize);
+
+uint8_t *Base64ToBinary(const char *pData, 
+			uint32_t decodeSize, 
+			uint32_t *pDataSize);
+void MP4Free(void *p);
+
+  void MP4SetLibFunc(lib_message_func_t libfunc);
 
 #ifdef __cplusplus
 }
--- a/common/mp4v2/mp4array.h
+++ b/common/mp4v2/mp4array.h
@@ -89,9 +89,11 @@
 			if (!ValidIndex(index)) { \
 				throw new MP4Error(ERANGE, "MP4Array::Delete"); \
 			} \
-			memmove(&m_elements[index], &m_elements[index + 1], \
-				(m_numElements - index) * sizeof(type)); \
 			m_numElements--; \
+			if (index < m_numElements) { \
+			  memmove(&m_elements[index], &m_elements[index + 1], \
+			   	  (m_numElements - index) * sizeof(type)); \
+			} \
 		} \
 		void Resize(MP4ArrayIndex newSize) { \
 			m_numElements = newSize; \
@@ -102,7 +104,7 @@
 		\
 		type& operator[](MP4ArrayIndex index) { \
 			if (!ValidIndex(index)) { \
-				throw new MP4Error(ERANGE, "MP4Array::[]"); \
+				throw new MP4Error(ERANGE, "index %u of %u", "MP4Array::[]", index, m_numElements); \
 			} \
 			return m_elements[index]; \
 		} \
--- a/common/mp4v2/mp4atom.cpp
+++ b/common/mp4v2/mp4atom.cpp
@@ -21,18 +21,18 @@
  * Portions created by Ximpo Group Ltd. are
  * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved.
  * 
+ *  Portions created by Adnecto d.o.o. are
+ *  Copyright (C) Adnecto d.o.o. 2005.  All Rights Reserved
+ *
  * Contributor(s): 
  *		Dave Mackie			[email protected]
  *		Alix Marchandise-Franquet	[email protected]
  *              Ximpo Group Ltd.                [email protected]
+ *              Danijel Kopcinovic              [email protected]
  */
 
 #include "mp4common.h"
 #include "atoms.h"
-#ifdef __MINGW32__
-/* We need isalnum() declaration */
-#include <ctype.h>
-#endif /* #ifdef __MINGW32__ */
 
 MP4AtomInfo::MP4AtomInfo(const char* name, bool mandatory, bool onlyOne) 
 {
@@ -77,55 +77,39 @@
     pAtom = new MP4RootAtom();
   } else {
     switch((uint8_t)type[0]) {
-    case 'b':
-      if (ATOMID(type) == ATOMID("bitr")) {
-	pAtom = new MP4BitrAtom();
+    case 'a':
+      if (ATOMID(type) == ATOMID("avc1")) {
+	pAtom = new MP4Avc1Atom();
+      } else if (ATOMID(type) == ATOMID("avcC")) {
+	pAtom = new MP4AvcCAtom();
+      } else if (ATOMID(type) == ATOMID("alis")) {
+	pAtom = new MP4UrlAtom("alis");
+      } else if (ATOMID(type) == ATOMID("alaw")) {
+	pAtom = new MP4SoundAtom(type);
+      } else if (ATOMID(type) == ATOMID("alac")) {
+	pAtom = new MP4SoundAtom(type);
       }
       break;
     case 'c':
-      if (ATOMID(type) == ATOMID("ctts")) {
-	pAtom = new MP4CttsAtom();
-      } else if (ATOMID(type) == ATOMID("co64")) {
-	pAtom = new MP4Co64Atom();
-      } else if (ATOMID(type) == ATOMID("cprt")) {
-	pAtom = new MP4CprtAtom();
-      } else if (ATOMID(type) == ATOMID("cpil")) { /* Apple iTunes */
-	pAtom = new MP4CpilAtom();
-      } else if (ATOMID(type) == ATOMID("covr")) { /* Apple iTunes */
-	pAtom = new MP4CovrAtom();
-      }
-      break;
+      if (ATOMID(type) == ATOMID("chap")) {
+	pAtom = new MP4TrefTypeAtom(type);
+	  }
+	  break;
     case 'd':
       if (ATOMID(type) == ATOMID("d263")) {
 	pAtom = new MP4D263Atom();
       } else if (ATOMID(type) == ATOMID("damr")) {
 	pAtom = new MP4DamrAtom();
-      } else if (ATOMID(type) == ATOMID("dinf")) {
-	pAtom = new MP4DinfAtom();
       } else if (ATOMID(type) == ATOMID("dref")) {
 	pAtom = new MP4DrefAtom();
       } else if (ATOMID(type) == ATOMID("dpnd")) {
 	pAtom = new MP4TrefTypeAtom(type);
-      } else if (ATOMID(type) == ATOMID("dmed")) {
-	pAtom = new MP4DmedAtom();
-      } else if (ATOMID(type) == ATOMID("dimm")) {
-	pAtom = new MP4DimmAtom();
-      } else if (ATOMID(type) == ATOMID("drep")) {
-	pAtom = new MP4DrepAtom();
-      } else if (ATOMID(type) == ATOMID("dmax")) {
-	pAtom = new MP4DmaxAtom();
       } else if (ATOMID(type) == ATOMID("data")) { /* Apple iTunes */
 	pAtom = new MP4DataAtom();
-      } else if (ATOMID(type) == ATOMID("disk")) { /* Apple iTunes */
-	pAtom = new MP4DiskAtom();
       }
       break;
     case 'e':
-      if (ATOMID(type) == ATOMID("esds")) {
-	pAtom = new MP4EsdsAtom();
-      } else if (ATOMID(type) == ATOMID("edts")) {
-	pAtom = new MP4EdtsAtom();
-      } else if (ATOMID(type) == ATOMID("elst")) {
+      if (ATOMID(type) == ATOMID("elst")) {
 	pAtom = new MP4ElstAtom();
       } else if (ATOMID(type) == ATOMID("enca")) {
 	pAtom = new MP4EncaAtom();
@@ -136,22 +120,18 @@
     case 'f':
       if (ATOMID(type) == ATOMID("free")) {
 	pAtom = new MP4FreeAtom();
-      } else if (ATOMID(type) == ATOMID("frma")) {
-	pAtom = new MP4FrmaAtom();
       } else if (ATOMID(type) == ATOMID("ftyp")) {
 	pAtom = new MP4FtypAtom();
       }
       break;
     case 'g':
-      if (ATOMID(type) == ATOMID("gnre")) { // Apple iTunes 
-	pAtom = new MP4GnreAtom();
+      if (ATOMID(type) == ATOMID("gmin")) {
+	pAtom = new MP4GminAtom();
       }
       break;
     case 'h':
       if (ATOMID(type) == ATOMID("hdlr")) {
 	pAtom = new MP4HdlrAtom();
-      } else if (ATOMID(type) == ATOMID("hmhd")) {
-	pAtom = new MP4HmhdAtom();
       } else if (ATOMID(type) == ATOMID("hint")) {
 	pAtom = new MP4TrefTypeAtom(type);
       } else if (ATOMID(type) == ATOMID("hnti")) {
@@ -158,75 +138,58 @@
 	pAtom = new MP4HntiAtom();
       } else if (ATOMID(type) == ATOMID("hinf")) {
 	pAtom = new MP4HinfAtom();
+      } else if (ATOMID(type) == ATOMID("h263")) {
+	pAtom = new MP4VideoAtom("h263");
+      } else if (ATOMID(type) == ATOMID("href")) {
+	pAtom = new MP4HrefAtom();
       }
       break;
     case 'i':
-      if (ATOMID(type) == ATOMID("iKMS")) {
-	pAtom = new MP4IKMSAtom();
-      } else if (ATOMID(type) == ATOMID("iSFM")) {
-	pAtom = new MP4ISFMAtom();
-      } else if (ATOMID(type) == ATOMID("iods")) {
-	pAtom = new MP4IodsAtom();
-      } else if (ATOMID(type) == ATOMID("ipir")) {
+      if (ATOMID(type) == ATOMID("ipir")) {
 	pAtom = new MP4TrefTypeAtom(type);
-      } else if (ATOMID(type) == ATOMID("ilst")) {
-	pAtom = new MP4IlstAtom();
+      } else if (ATOMID(type) == ATOMID("ima4")) {
+	pAtom = new MP4SoundAtom("ima4");
       }
       break;
+    case 'j':
+      if (ATOMID(type) == ATOMID("jpeg")) {
+	pAtom = new MP4VideoAtom("jpeg");
+      }
+      break;
     case 'm':
-      if (ATOMID(type) == ATOMID("mdia")) {
-	pAtom = new MP4MdiaAtom();
-      } else if (ATOMID(type) == ATOMID("minf")) {
-	pAtom = new MP4MinfAtom();
-      } else if (ATOMID(type) == ATOMID("mdhd")) {
+      if (ATOMID(type) == ATOMID("mdhd")) {
 	pAtom = new MP4MdhdAtom();
-      } else if (ATOMID(type) == ATOMID("mdat")) {
-	pAtom = new MP4MdatAtom();
-      } else if (ATOMID(type) == ATOMID("moov")) {
-	pAtom = new MP4MoovAtom();
       } else if (ATOMID(type) == ATOMID("mvhd")) {
 	pAtom = new MP4MvhdAtom();
+      } else if (ATOMID(type) == ATOMID("mdat")) {
+	pAtom = new MP4MdatAtom();
       } else if (ATOMID(type) == ATOMID("mpod")) {
 	pAtom = new MP4TrefTypeAtom(type);
       } else if (ATOMID(type) == ATOMID("mp4a")) {
-	pAtom = new MP4Mp4aAtom();
+	pAtom = new MP4SoundAtom("mp4a");
       } else if (ATOMID(type) == ATOMID("mp4s")) {
 	pAtom = new MP4Mp4sAtom();
       } else if (ATOMID(type) == ATOMID("mp4v")) {
 	pAtom = new MP4Mp4vAtom();
-      } else if (ATOMID(type) == ATOMID("moof")) {
-	pAtom = new MP4MoofAtom();
-      } else if (ATOMID(type) == ATOMID("mfhd")) {
-	pAtom = new MP4MfhdAtom();
-      } else if (ATOMID(type) == ATOMID("mvex")) {
-	pAtom = new MP4MvexAtom();
-      } else if (ATOMID(type) == ATOMID("maxr")) {
-	pAtom = new MP4MaxrAtom();
-      } else if (ATOMID(type) == ATOMID("meta")) { // iTunes
-	pAtom = new MP4MetaAtom();
       } else if (ATOMID(type) == ATOMID("mean")) { // iTunes
-	pAtom = new MP4MeanAtom();
+	pAtom = new MP4Meta1Atom(type);
       }
       break;
     case 'n':
-      if (ATOMID(type) == ATOMID("nmhd")) {
-	pAtom = new MP4NmhdAtom();
-      } else if (ATOMID(type) == ATOMID("nump")) {
-	pAtom = new MP4NumpAtom();
-      } else if (ATOMID(type) == ATOMID("name")) { // iTunes
-	pAtom = new MP4NameAtom();
+      if (ATOMID(type) == ATOMID("name")) { // iTunes
+	pAtom = new MP4Meta1Atom(type);
       }
       break;
-    case 'p':
-      if (ATOMID(type) == ATOMID("pmax")) {
-	pAtom = new MP4PmaxAtom();
-      } else if (ATOMID(type) == ATOMID("payt")) {
-	pAtom = new MP4PaytAtom();
+    case 'o':
+      if (ATOMID(type) == ATOMID("ohdr")) {
+	pAtom = new MP4OhdrAtom();
       }
       break;
     case 'r':
       if (ATOMID(type) == ATOMID("rtp ")) {
 	pAtom = new MP4RtpAtom();
+      } else if (ATOMID(type) == ATOMID("raw ")) {
+	pAtom = new MP4VideoAtom("raw ");
       }
       break;
     case 's':
@@ -233,77 +196,43 @@
       if (ATOMID(type) == ATOMID("s263"))  {
         pAtom = new MP4S263Atom();
       } else if (ATOMID(type) == ATOMID("samr")) {
-	pAtom = new MP4SamrAtom();
+	pAtom = new MP4AmrAtom("samr");
       } else if (ATOMID(type) == ATOMID("sawb")) {
-	pAtom = new MP4SawbAtom();
-      } else if (ATOMID(type) == ATOMID("schi")) {
-	pAtom = new MP4SchiAtom();
-      } else if (ATOMID(type) == ATOMID("schm")) {
-	pAtom = new MP4SchmAtom();
-      } else if (ATOMID(type) == ATOMID("sinf")) {
-	pAtom = new MP4SinfAtom();
+	pAtom = new MP4AmrAtom("sawb");
       } else if (ATOMID(type) == ATOMID("stbl")) {
 	pAtom = new MP4StblAtom();
       } else if (ATOMID(type) == ATOMID("stsd")) {
 	pAtom = new MP4StsdAtom();
-      } else if (ATOMID(type) == ATOMID("stts")) {
-	pAtom = new MP4SttsAtom();
       } else if (ATOMID(type) == ATOMID("stsz")) {
 	pAtom = new MP4StszAtom();
       } else if (ATOMID(type) == ATOMID("stsc")) {
 	pAtom = new MP4StscAtom();
-      } else if (ATOMID(type) == ATOMID("stco")) {
-	pAtom = new MP4StcoAtom();
-      } else if (ATOMID(type) == ATOMID("stss")) {
-	pAtom = new MP4StssAtom();
-      } else if (ATOMID(type) == ATOMID("stsh")) {
-	pAtom = new MP4StshAtom();
+      } else if (ATOMID(type) == ATOMID("stz2")) {
+	pAtom = new MP4Stz2Atom();
       } else if (ATOMID(type) == ATOMID("stdp")) {
 	pAtom = new MP4StdpAtom();
-      } else if (ATOMID(type) == ATOMID("smhd")) {
-	pAtom = new MP4SmhdAtom();
       } else if (ATOMID(type) == ATOMID("sdp ")) {
 	pAtom = new MP4SdpAtom();
-      } else if (ATOMID(type) == ATOMID("snro")) {
-	pAtom = new MP4SnroAtom();
       } else if (ATOMID(type) == ATOMID("sync")) {
 	pAtom = new MP4TrefTypeAtom(type);
       } else if (ATOMID(type) == ATOMID("skip")) {
 	pAtom = new MP4FreeAtom();
 	pAtom->SetType("skip");
+      } else if (ATOMID(type) == ATOMID("sowt")) {
+	pAtom = new MP4SoundAtom("sowt");
       }
       break;
     case 't':
-      if (ATOMID(type) == ATOMID("trak")) {
-	pAtom = new MP4TrakAtom();
+      if (ATOMID(type) == ATOMID("text")) {
+	pAtom = new MP4TextAtom();
       } else if (ATOMID(type) == ATOMID("tkhd")) {
 	pAtom = new MP4TkhdAtom();
-      } else if (ATOMID(type) == ATOMID("tref")) {
-	pAtom = new MP4TrefAtom();
-      } else if (ATOMID(type) == ATOMID("traf")) {
-	pAtom = new MP4TrafAtom();
       } else if (ATOMID(type) == ATOMID("tfhd")) {
 	pAtom = new MP4TfhdAtom();
-      } else if (ATOMID(type) == ATOMID("trex")) {
-	pAtom = new MP4TrexAtom();
       } else if (ATOMID(type) == ATOMID("trun")) {
 	pAtom = new MP4TrunAtom();
-      } else if (ATOMID(type) == ATOMID("tmin")) {
-	pAtom = new MP4TminAtom();
-      } else if (ATOMID(type) == ATOMID("tmax")) {
-	pAtom = new MP4TmaxAtom();
-      } else if (ATOMID(type) == ATOMID("trpy")) {
-	pAtom = new MP4TrpyAtom();
-      } else if (ATOMID(type) == ATOMID("tpyl")) {
-	pAtom = new MP4TpylAtom();
-      } else if (ATOMID(type) == ATOMID("tims")) {
-	pAtom = new MP4TimsAtom();
-      } else if (ATOMID(type) == ATOMID("tsro")) {
-	pAtom = new MP4TsroAtom();
-      } else if (ATOMID(type) == ATOMID("trkn")) { // iTunes
-	pAtom = new MP4TrknAtom();
-      } else if (ATOMID(type) == ATOMID("tmpo")) { // iTunes
-	pAtom = new MP4TmpoAtom();
+      } else if (ATOMID(type) == ATOMID("twos")) {
+	pAtom = new MP4SoundAtom("twos");
       }
       break;
     case 'u':
@@ -313,6 +242,8 @@
 	pAtom = new MP4UrlAtom();
       } else if (ATOMID(type) == ATOMID("urn ")) {
 	pAtom = new MP4UrnAtom();
+      } else if (ATOMID(type) == ATOMID("ulaw")) {
+	pAtom = new MP4SoundAtom("ulaw");
       }
       break;
     case 'v':
@@ -320,41 +251,38 @@
 	pAtom = new MP4VmhdAtom();
       }
       break;
-    case 0251: { // copyright symbol 
-static const char name[5]={0251,'n', 'a', 'm', '\0'};
-static const char art[5]={0251,'A', 'R', 'T', '\0'};
-static const char wrt[5]={0251,'w', 'r', 't', '\0'};
-static const char alb[5]={0251,'a', 'l', 'b', '\0'};
-static const char day[5]={0251,'d', 'a', 'y', '\0'};
-static const char too[5]={0251,'t', 'o', 'o', '\0'};
-static const char cmt[5]={0251,'c', 'm', 't', '\0'};
-      if (ATOMID(type) == ATOMID(name)) {
- 	pAtom = new MP4NamAtom();
-      } else if (ATOMID(type) == ATOMID(art)) { /* Apple iTunes */
- 	pAtom = new MP4ArtAtom();
-      } else if (ATOMID(type) == ATOMID(wrt)) { /* Apple iTunes */
- 	pAtom = new MP4WrtAtom();
-      } else if (ATOMID(type) == ATOMID(alb)) { /* Apple iTunes */
- 	pAtom = new MP4AlbAtom();
-      } else if (ATOMID(type) == ATOMID(day)) { /* Apple iTunes */
- 	pAtom = new MP4DayAtom();
-      } else if (ATOMID(type) == ATOMID(too)) { /* Apple iTunes */
- 	pAtom = new MP4TooAtom();
-      } else if (ATOMID(type) == ATOMID(cmt)) { /* Apple iTunes */
- 	pAtom = new MP4CmtAtom();
+    case 'y':
+      if (ATOMID(type) == ATOMID("yuv2")) {
+	pAtom = new MP4VideoAtom("yuv2");
       }
       break;
-    }
-    case '-':
-      if (ATOMID(type) == ATOMID("----")) { /* Apple iTunes */
- 	pAtom = new MP4DashAtom();
+    case 'S':
+      if (ATOMID(type) == ATOMID("SVQ3")) {
+	pAtom = new MP4VideoAtom("SVQ3");
+      } else if (ATOMID(type) == ATOMID("SMI ")) {
+	pAtom = new MP4SmiAtom();
       }
+      break;
+    case 0251:
+      static const char name[5]={0251,'n', 'a', 'm', '\0'};
+      static const char cmt[5]={0251,'c', 'm', 't', '\0'};
+      static const char cpy[5]={0251,'c', 'p', 'y', '\0'};
+      static const char des[5]={0251,'d', 'e', 's','\0'};
+      static const char prd[5]={0251, 'p', 'r', 'd', '\0'};
+      if (ATOMID(type) == ATOMID(name) ||
+	  ATOMID(type) == ATOMID(cmt) ||
+	  ATOMID(type) == ATOMID(cpy) ||
+	  ATOMID(type) == ATOMID(prd) ||
+	  ATOMID(type) == ATOMID(des)) {
+	pAtom = new MP4Meta2Atom(type);
+      }
+      break;
     }
   }
 
   if (pAtom == NULL) {
-    pAtom = new MP4Atom(type);
-    pAtom->SetUnknownType(true);
+    pAtom = new MP4StandardAtom(type);
+    // unknown type is set by StandardAtom type
   }
 
   ASSERT(pAtom);
@@ -410,6 +338,7 @@
 	if (dataSize == 1) {
 		dataSize = pFile->ReadUInt64(); 
 		hdrSize += 8;
+		pFile->Check64BitStatus(type);
 	}
 
 	// extended type
@@ -426,13 +355,29 @@
 	dataSize -= hdrSize;
 
 	VERBOSE_READ(pFile->GetVerbosity(), 
-		printf("ReadAtom: type = %s data-size = "U64" (0x"X64")\n", 
-			type, dataSize, dataSize));
+		printf("ReadAtom: type = \"%s\" data-size = "U64" (0x"X64") hdr %u\n", 
+		       type, dataSize, dataSize, hdrSize));
 
 	if (pos + hdrSize + dataSize > pParentAtom->GetEnd()) {
-		VERBOSE_READ(pFile->GetVerbosity(), 
-			printf("ReadAtom: invalid atom size, extends outside parent atom\n"));
+		VERBOSE_ERROR(pFile->GetVerbosity(), 
+			printf("ReadAtom: invalid atom size, extends outside parent atom - skipping to end of \"%s\" \"%s\" "U64" vs "U64"\n", 
+			       pParentAtom->GetType(), type,
+			       pos + hdrSize + dataSize, 
+			       pParentAtom->GetEnd()));
+		VERBOSE_READ(pFile->GetVerbosity(),
+			     printf("parent %s ("U64") pos "U64" hdr %d data "U64" sum "U64"\n",
+				    pParentAtom->GetType(),
+				    pParentAtom->GetEnd(),
+				    pos, 
+				    hdrSize, 
+				    dataSize,
+				    pos + hdrSize + dataSize));
+#if 0
 		throw new MP4Error("invalid atom size", "ReadAtom");
+#else
+		// skip to end of atom
+		dataSize = pParentAtom->GetEnd() - pos - hdrSize;
+#endif
 	}
 
 
@@ -578,7 +523,7 @@
 	u_int32_t atomIndex = 0;
 
 	// get the index if we have one, e.g. moov.trak[2].mdia...
-	MP4NameFirstIndex(name, &atomIndex);
+	(void)MP4NameFirstIndex(name, &atomIndex);
 
 	// need to get to the index'th child atom of the right type
 	for (u_int32_t i = 0; i < m_pChildAtoms.Size(); i++) {
@@ -612,7 +557,7 @@
 
 	// check if we have an index, e.g. trak[2].mdia...
 	u_int32_t atomIndex = 0;
-	MP4NameFirstIndex(name, &atomIndex);
+	(void)MP4NameFirstIndex(name, &atomIndex);
 
 	// need to get to the index'th child atom of the right type
 	for (i = 0; i < m_pChildAtoms.Size(); i++) {
@@ -660,11 +605,36 @@
 
 void MP4Atom::ReadChildAtoms()
 {
+  bool this_is_udta = ATOMID(m_type) == ATOMID("udta");
+
 	VERBOSE_READ(GetVerbosity(), 
 		printf("ReadChildAtoms: of %s\n", m_type[0] ? m_type : "root"));
-
-	// read any child atoms
-	while (m_pFile->GetPosition() < m_end) {
+	for (u_int64_t position = m_pFile->GetPosition();
+	     position < m_end;
+	     position = m_pFile->GetPosition()) {
+	  // make sure that we have enough to read at least 8 bytes
+	  // size and type.
+	  if (m_end - position < 2 * sizeof(uint32_t)) {
+	    // if we're reading udta, it's okay to have 4 bytes of 0
+	    if (this_is_udta &&
+		m_end - position == sizeof(uint32_t)) {
+	      u_int32_t mbz = m_pFile->ReadUInt32();
+	      if (mbz != 0) {
+		VERBOSE_WARNING(GetVerbosity(),
+				printf("Error: In udta atom, end value is not zero %x\n", 
+				       mbz));
+	      }
+	      continue;
+	    }
+	    // otherwise, output a warning, but don't care
+	    VERBOSE_WARNING(GetVerbosity(),
+			    printf("Error: In %s atom, extra "D64" bytes at end of atom\n", 
+				   m_type, (m_end - position)));
+	    for (uint64_t ix = 0; ix < m_end - position; ix++) {
+	      (void)m_pFile->ReadUInt8();
+	    }
+	    continue;
+	  }
 		MP4Atom* pChildAtom = MP4Atom::ReadAtom(m_pFile, this);
 
 		AddChildAtom(pChildAtom);
@@ -690,6 +660,7 @@
 						GetType(), pChildAtom->GetType()));
 			}
 		}
+
 	}
 
 	// if mandatory child atom doesn't exist, print warning
@@ -769,6 +740,10 @@
 {
 	m_end = m_pFile->GetPosition();
 	m_size = (m_end - m_start);
+  VERBOSE_WRITE(GetVerbosity(), 
+		printf("end: type %s "U64" "U64" size "U64"\n", m_type, 
+		       m_start, m_end,
+		       m_size));
 	//use64 = m_pFile->Use64Bits();
 	if (use64) {
 		m_pFile->SetPosition(m_start + 8);
@@ -880,6 +855,7 @@
 	if (m_type[0] != '\0') {
 		Indent(pFile, indent);
 		fprintf(pFile, "type %s\n", m_type);
+		fflush(pFile);
 	}
 
 	u_int32_t i;
--- a/common/mp4v2/mp4atom.h
+++ b/common/mp4v2/mp4atom.h
@@ -96,7 +96,7 @@
 	};
 	void SetType(const char* type) {
 		if (type && *type != '\0') {
-			ASSERT(strlen(type) == 4);
+		  // not needed ASSERT(strlen(type) == 4);
 			memcpy(m_type, type, 4);
 			m_type[4] = '\0';
 		} else {
@@ -162,6 +162,21 @@
 		return m_pProperties[index];
 	}
 
+	u_int32_t GetCount() {
+		return m_pProperties.Size();
+	}
+
+#if 0
+	void SetProperty(u_int32_t index, MP4Property *property) {
+		u_int64_t t;
+		if (index > m_pProperties.Size())
+			return;
+
+		t = property->Get(index);
+		m_pProperties[index]->Set(t, index);
+	}
+#endif
+
 	MP4Atom* FindAtom(const char* name);
 
 	MP4Atom* FindChildAtom(const char* name);
@@ -234,6 +249,11 @@
 
 inline u_int32_t ATOMID(const char* type) {
 	return STRTOINT32(type);
+}
+
+// inverse ATOMID - 32 bit id to string
+inline void IDATOM(u_int32_t type, char *s) {
+	INT32TOSTR(type, s);
 }
 
 #endif /* __MP4_ATOM_INCLUDED__ */
--- a/common/mp4v2/mp4common.h
+++ b/common/mp4v2/mp4common.h
@@ -46,5 +46,5 @@
 #include "odcommands.h"
 
 #include "rtphint.h"
-
+#include "virtual_io.h"
 #endif /* __MP4_COMMON_INCLUDED__ */
--- a/common/mp4v2/mp4file.cpp
+++ b/common/mp4v2/mp4file.cpp
@@ -13,7 +13,7 @@
  * 
  * The Initial Developer of the Original Code is Cisco Systems Inc.
  * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001 - 2004.  All Rights Reserved.
+ * 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.
@@ -25,6 +25,7 @@
  *		Dave Mackie		  [email protected]
  *              Alix Marchandise-Franquet [email protected]
  *              Ximpo Group Ltd.          [email protected]
+ *              Bill May                  [email protected]
  */
 
 #include "mp4common.h"
@@ -32,7 +33,11 @@
 MP4File::MP4File(u_int32_t verbosity)
 {
 	m_fileName = NULL;
+	#ifdef _WIN32
+	m_fileName_w = NULL;
+	#endif
 	m_pFile = NULL;
+	m_virtual_IO = NULL;
 	m_orgFileSize = 0;
 	m_fileSize = 0;
 	m_pRootAtom = NULL;
@@ -55,16 +60,31 @@
 	m_bufReadBits = 0;
 	m_numWriteBits = 0;
 	m_bufWriteBits = 0;
+	m_editName = NULL;
+#ifndef _WIN32
+	m_tempFileName[0] = '\0';
+#endif
+	m_trakName[0] = '\0';
 }
 
 MP4File::~MP4File()
 {
 	MP4Free(m_fileName);
+	#ifdef _WIN32
+	MP4Free(m_fileName_w);
+	#endif
+	if (m_pFile != NULL) {
+	  // not closed ?
+	  m_virtual_IO->Close(m_pFile);
+	  m_pFile = NULL;
+	}
 	delete m_pRootAtom;
 	for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
 		delete m_pTracks[i];
 	}
 	MP4Free(m_memoryBuffer);	// just in case
+	CHECK_AND_FREE(m_editName);
+	
 }
 
 void MP4File::Read(const char* fileName)
@@ -79,16 +99,46 @@
 	CacheProperties();
 }
 
-void MP4File::Create(const char* fileName, u_int32_t flags)
+#ifdef _WIN32
+void MP4File::Read(const wchar_t* fileName)
 {
-	        CreateEx( fileName, flags, NULL, 0, NULL, 0 );
+	m_fileName_w = MP4Stralloc(fileName);
+	m_mode = 'r';
+
+	Open(L"rb");
+
+	ReadFromFile();
+
+	CacheProperties();
 }
+#endif
 
-void MP4File::CreateEx(const char* fileName, u_int32_t flags, 
-		       char* majorBrand, u_int32_t minorVersion, 
-		       char** supportedBrands, u_int32_t supportedBrandsCount)
+// benski>
+void MP4File::ReadEx(const char *fileName, void *user, Virtual_IO *virtual_IO)
 {
 	m_fileName = MP4Stralloc(fileName);
+	m_mode = 'r';
+
+ 	m_pFile = user;
+	m_virtual_IO = virtual_IO;
+
+	ASSERT(m_pFile);
+	ASSERT(m_virtual_IO)
+	
+	m_orgFileSize = m_fileSize = m_virtual_IO->GetFileLength(m_pFile); 
+
+	ReadFromFile();
+
+	CacheProperties();
+}
+
+
+void MP4File::Create(const char* fileName, u_int32_t flags, 
+		     int add_ftyp, int add_iods, 
+		     char* majorBrand, u_int32_t minorVersion, 
+		     char** supportedBrands, u_int32_t supportedBrandsCount)
+{
+	m_fileName = MP4Stralloc(fileName);
 	m_mode = 'w';
 	m_createFlags = flags;
 
@@ -99,36 +149,53 @@
 	m_pRootAtom->SetFile(this);
 	m_pRootAtom->Generate();
 
-	if ((majorBrand != NULL) || (minorVersion != 0)) {
-		MakeFtypAtom(majorBrand, minorVersion, 
-			     supportedBrands, supportedBrandsCount);
+	if (add_ftyp != 0) {
+	  MakeFtypAtom(majorBrand, minorVersion, 
+		       supportedBrands, supportedBrandsCount);
 	}
 
 	CacheProperties();
 
 	// create mdat, and insert it after ftyp, and before moov
-	InsertChildAtom(m_pRootAtom, "mdat", 1);
+	(void)InsertChildAtom(m_pRootAtom, "mdat", 
+			      add_ftyp != 0 ? 1 : 0);
 
 	// start writing
 	m_pRootAtom->BeginWrite();
+	if (add_iods != 0) {
+	  (void)AddChildAtom("moov", "iods");
+	}
 }
 
 bool MP4File::Use64Bits (const char *atomName)
 {
-  if (!strcmp(atomName, "mdat") || !strcmp(atomName, "stbl")) {
+  uint32_t atomid = ATOMID(atomName);
+  if (atomid == ATOMID("mdat") || atomid == ATOMID("stbl")) {
     return (m_createFlags & MP4_CREATE_64BIT_DATA) == MP4_CREATE_64BIT_DATA;
-  }
-
-  if (!strcmp(atomName, "mvhd") || 
-      !strcmp(atomName, "tkhd") ||
-      !strcmp(atomName, "mdhd")) {
+  } 
+  if (atomid == ATOMID("mvhd") ||
+      atomid == ATOMID("tkhd") ||
+      atomid == ATOMID("mdhd")) {
     return (m_createFlags & MP4_CREATE_64BIT_TIME) == MP4_CREATE_64BIT_TIME;
   }
   return false;
 }
 
+void MP4File::Check64BitStatus (const char *atomName)
+{
+  uint32_t atomid = ATOMID(atomName);
+
+  if (atomid == ATOMID("mdat") || atomid == ATOMID("stbl")) {
+    m_createFlags |= MP4_CREATE_64BIT_DATA;
+  } else if (atomid == ATOMID("mvhd") ||
+	     atomid == ATOMID("tkhd") ||
+	     atomid == ATOMID("mdhd")) {
+    m_createFlags |= MP4_CREATE_64BIT_TIME;
+  }
+}
+
     
-void MP4File::Modify(const char* fileName)
+bool MP4File::Modify(const char* fileName)
 {
 	m_fileName = MP4Stralloc(fileName);
 	m_mode = 'r';
@@ -144,7 +211,8 @@
 
 	if (pMoovAtom == NULL) {
 		// there isn't one, odd but we can still proceed
-		pMoovAtom = AddChildAtom(m_pRootAtom, "moov");
+	  return false;
+	  //pMoovAtom = AddChildAtom(m_pRootAtom, "moov");
 	} else {
 		numAtoms = m_pRootAtom->GetNumberOfChildAtoms();
 
@@ -217,7 +285,8 @@
 	MP4Atom* pMdatAtom = InsertChildAtom(m_pRootAtom, "mdat", numAtoms - 1);
 
 	// start writing new mdat
-	pMdatAtom->BeginWrite();
+	pMdatAtom->BeginWrite(Use64Bits("mdat"));
+	return true;
 }
 
 void MP4File::Optimize(const char* orgFileName, const char* newFileName)
@@ -233,6 +302,9 @@
 
 	// now switch over to writing the new file
 	MP4Free(m_fileName);
+	#ifdef _WIN32
+	MP4Free(m_fileName_w);
+	#endif
 
 	// create a temporary file if necessary
 	if (newFileName == NULL) {
@@ -241,7 +313,8 @@
 		m_fileName = MP4Stralloc(newFileName);
 	}
 
-	FILE* pReadFile = m_pFile;
+	void* pReadFile = m_pFile;
+	Virtual_IO *pReadIO = m_virtual_IO;
 	m_pFile = NULL;
 	m_mode = 'w';
 
@@ -254,15 +327,15 @@
 	((MP4RootAtom*)m_pRootAtom)->BeginOptimalWrite();
 
 	// write data in optimal order
-	RewriteMdat(pReadFile, m_pFile);
+	RewriteMdat(pReadFile, m_pFile, pReadIO, m_virtual_IO);
 
 	// finish writing
 	((MP4RootAtom*)m_pRootAtom)->FinishOptimalWrite();
 
 	// cleanup
-	fclose(m_pFile);
+	m_virtual_IO->Close(m_pFile);
 	m_pFile = NULL;
-	fclose(pReadFile);
+	pReadIO->Close(pReadFile);
 
 	// move temporary file into place
 	if (newFileName == NULL) {
@@ -270,7 +343,8 @@
 	}
 }
 
-void MP4File::RewriteMdat(FILE* pReadFile, FILE* pWriteFile)
+void MP4File::RewriteMdat(void* pReadFile, void* pWriteFile,
+			  Virtual_IO *readIO, Virtual_IO *writeIO)
 {
 	u_int32_t numTracks = m_pTracks.Size();
 
@@ -323,6 +397,7 @@
 
 		// point into original mp4 file for read chunk call
 		m_pFile = pReadFile;
+		m_virtual_IO = readIO;
 		m_mode = 'r';
 
 		u_int8_t* pChunk;
@@ -333,6 +408,7 @@
 
 		// point back at the new mp4 file for write chunk
 		m_pFile = pWriteFile;
+		m_virtual_IO = writeIO;
 		m_mode = 'w';
 
 		m_pTracks[nextTrackIndex]->
@@ -352,6 +428,7 @@
 void MP4File::Open(const char* fmode)
 {
 	ASSERT(m_pFile == NULL);
+	FILE *openFile = NULL;
 
 #ifdef O_LARGEFILE
 	// UGH! fopen doesn't open a file in 64-bit mode, period.
@@ -374,25 +451,70 @@
 	fd = open(m_fileName, flags, 0666); 
 
 	if (fd >= 0) {
-		m_pFile = fdopen(fd, fmode);
+		openFile = fdopen(fd, fmode);
 	}
 #else
-	m_pFile = fopen(m_fileName, fmode);
+	openFile = fopen(m_fileName, fmode);
 #endif
+	m_pFile = openFile;
+
 	if (m_pFile == NULL) {
 		throw new MP4Error(errno, "failed", "MP4Open");
 	}
-
+	
+	m_virtual_IO = &FILE_virtual_IO;
 	if (m_mode == 'r') {
-		struct stat s;
-		if (fstat(fileno(m_pFile), &s) < 0) {
-			throw new MP4Error(errno, "stat failed", "MP4Open");
+	  m_orgFileSize = m_fileSize = m_virtual_IO->GetFileLength(m_pFile); // benski
+	} else {
+		m_orgFileSize = m_fileSize = 0;
+	}
+}
+
+#ifdef _WIN32
+void MP4File::Open(const wchar_t* fmode)
+{
+	ASSERT(m_pFile == NULL);
+	FILE *openFile = NULL;
+#ifdef O_LARGEFILE
+	// UGH! fopen doesn't open a file in 64-bit mode, period.
+	// So we need to use open() and then fdopen()
+	int fd;
+	int flags = O_LARGEFILE;
+
+	if (strchr(fmode, '+')) {
+		flags |= O_CREAT | O_RDWR;
+		if (fmode[0] == 'w') {
+			flags |= O_TRUNC;
 		}
-		m_orgFileSize = m_fileSize = s.st_size;
 	} else {
+		if (fmode[0] == 'w') {
+			flags |= O_CREAT | O_TRUNC | O_WRONLY;
+		} else {
+			flags |= O_RDONLY;
+		}
+	}
+	fd = _wopen(m_fileName_w, flags, 0666);
+
+	if (fd >= 0) {
+		openFile = _wfdopen(fd, fmode);
+	}
+#else
+	openFile = _wfopen(m_fileName_w, fmode);
+#endif
+	m_pFile = openFile;
+
+	if (m_pFile == NULL) {
+		throw new MP4Error(errno, "failed", "MP4Open");
+	}
+	
+	m_virtual_IO = &FILE_virtual_IO;
+	if (m_mode == 'r') {
+	  m_orgFileSize = m_fileSize = m_virtual_IO->GetFileLength(m_pFile); // benski
+	} else {
 		m_orgFileSize = m_fileSize = 0;
 	}
 }
+#endif
 
 void MP4File::ReadFromFile()
 {
@@ -434,13 +556,13 @@
 
 		// find track id property
 		MP4Integer32Property* pTrackIdProperty = NULL;
-		pTrakAtom->FindProperty(
+		(void)pTrakAtom->FindProperty(
 			"trak.tkhd.trackId",
 			(MP4Property**)&pTrackIdProperty);
 
 		// find track type property
 		MP4StringProperty* pTypeProperty = NULL;
-		pTrakAtom->FindProperty(
+		(void)pTrakAtom->FindProperty(
 			"trak.mdia.hdlr.handlerType",
 			(MP4Property**)&pTypeProperty);
 
@@ -504,7 +626,6 @@
 		ASSERT(m_pTracks[i]);
 		m_pTracks[i]->FinishWrite();
 	}
-
 	// ask root atom to write
 	m_pRootAtom->FinishWrite();
 
@@ -523,14 +644,12 @@
 	}
 }
 
-MP4Duration MP4File::UpdateDuration(MP4Duration duration)
+void MP4File::UpdateDuration(MP4Duration duration)
 {
 	MP4Duration currentDuration = GetDuration();
 	if (duration > currentDuration) {
 		SetDuration(duration);
-		return duration;
 	}
-	return currentDuration;
 }
 
 void MP4File::Dump(FILE* pDumpFile, bool dumpImplicits)
@@ -552,7 +671,7 @@
 		FinishWrite();
 	}
 
-	fclose(m_pFile);
+	m_virtual_IO->Close(m_pFile);
 	m_pFile = NULL;
 }
 
@@ -561,11 +680,11 @@
 	// there are so many attempts in libc to get this right
 	// that for portablity reasons, it's best just to roll our own
 #ifndef _WIN32
-	static char tempFileName[64];
 	u_int32_t i;
 	for (i = getpid(); i < 0xFFFFFFFF; i++) {
-		sprintf(tempFileName, "./tmp%u.mp4", i);
-		if (access(tempFileName, F_OK) != 0) {
+		snprintf(m_tempFileName, sizeof(m_tempFileName), 
+			 "./tmp%u.mp4", i);
+		if (access(m_tempFileName, F_OK) != 0) {
 			break;
 		}
 	}
@@ -573,14 +692,13 @@
 		throw new MP4Error("can't create temporary file", "TempFileName");
 	}
 #else
-	static char tempFileName[MAX_PATH + 3];
-	GetTempFileName(".", // dir. for temp. files 
-					"mp4",                // temp. filename prefix 
-					0,                    // create unique name 
-					tempFileName);        // buffer for name 
+	GetTempFileNameA(".", // dir. for temp. files 
+			"mp4",                // temp. filename prefix 
+			0,                    // create unique name 
+			m_tempFileName);        // buffer for name 
 #endif
 
-	return tempFileName;
+	return (char *)m_tempFileName;
 }
 
 void MP4File::Rename(const char* oldFileName, const char* newFileName)
@@ -872,13 +990,13 @@
 
 	// set track id
 	MP4Integer32Property* pInteger32Property = NULL;
-	pTrakAtom->FindProperty(
-		"trak.tkhd.trackId", (MP4Property**)&pInteger32Property);
+	(void)pTrakAtom->FindProperty("trak.tkhd.trackId", 
+				       (MP4Property**)&pInteger32Property);
 	ASSERT(pInteger32Property);
 	pInteger32Property->SetValue(trackId);
 
 	// set track type
-	const char* normType = MP4Track::NormalizeTrackType(type);
+	const char* normType = MP4NormalizeTrackType(type, m_verbosity);
 
 	// sanity check for user defined types
 	if (strlen(normType) > 4) {
@@ -888,15 +1006,15 @@
 	}
 
 	MP4StringProperty* pStringProperty = NULL;
-	pTrakAtom->FindProperty(
-		"trak.mdia.hdlr.handlerType", (MP4Property**)&pStringProperty);
+	(void)pTrakAtom->FindProperty("trak.mdia.hdlr.handlerType", 
+				      (MP4Property**)&pStringProperty);
 	ASSERT(pStringProperty);
 	pStringProperty->SetValue(normType);
 
 	// set track time scale
 	pInteger32Property = NULL;
-	pTrakAtom->FindProperty(
-		"trak.mdia.mdhd.timeScale", (MP4Property**)&pInteger32Property);
+	(void)pTrakAtom->FindProperty("trak.mdia.mdhd.timeScale", 
+				       (MP4Property**)&pInteger32Property);
 	ASSERT(pInteger32Property);
 	pInteger32Property->SetValue(timeScale ? timeScale : 1000);
 
@@ -924,8 +1042,8 @@
 void MP4File::AddTrackToIod(MP4TrackId trackId)
 {
 	MP4DescriptorProperty* pDescriptorProperty = NULL;
-	m_pRootAtom->FindProperty("moov.iods.esIds", 
-		(MP4Property**)&pDescriptorProperty);
+	(void)m_pRootAtom->FindProperty("moov.iods.esIds", 
+				  (MP4Property**)&pDescriptorProperty);
 	ASSERT(pDescriptorProperty);
 
 	MP4Descriptor* pDescriptor = 
@@ -933,8 +1051,8 @@
 	ASSERT(pDescriptor);
 
 	MP4Integer32Property* pIdProperty = NULL;
-	pDescriptor->FindProperty("id", 
-		(MP4Property**)&pIdProperty);
+	(void)pDescriptor->FindProperty("id", 
+					(MP4Property**)&pIdProperty);
 	ASSERT(pIdProperty);
 
 	pIdProperty->SetValue(trackId);
@@ -943,9 +1061,11 @@
  void MP4File::RemoveTrackFromIod(MP4TrackId trackId, bool shallHaveIods)
 {
 	MP4DescriptorProperty* pDescriptorProperty = NULL;
-	m_pRootAtom->FindProperty("moov.iods.esIds",
-		(MP4Property**)&pDescriptorProperty);
-
+	if (!m_pRootAtom->FindProperty("moov.iods.esIds",
+				       (MP4Property**)&pDescriptorProperty))
+	  return;
+#if 0
+	// we may not have iods
 	if (shallHaveIods) {
 		ASSERT(pDescriptorProperty);
 	} else {
@@ -953,17 +1073,23 @@
 			return;
 		}
 	}
+#else
+	if (pDescriptorProperty == NULL) {
+	  return;
+	}
+#endif
 
 	for (u_int32_t i = 0; i < pDescriptorProperty->GetCount(); i++) {
-		static char name[32];
+	  /* static */char name[32];
 		snprintf(name, sizeof(name), "esIds[%u].id", i);
 
 		MP4Integer32Property* pIdProperty = NULL;
-		pDescriptorProperty->FindProperty(name, 
+		(void)pDescriptorProperty->FindProperty(name, 
 			(MP4Property**)&pIdProperty);
-		ASSERT(pIdProperty);
+		// wmay ASSERT(pIdProperty);
 
-		if (pIdProperty->GetValue() == trackId) {
+		if (pIdProperty != NULL && 
+		    pIdProperty->GetValue() == trackId) {
 			pDescriptorProperty->DeleteDescriptor(i);
 			break;
 		}
@@ -994,11 +1120,11 @@
 	char propName[1024];
 
 	snprintf(propName, sizeof(propName), "%s.%s", trefName, "entryCount");
-	m_pRootAtom->FindProperty(propName, ppCountProperty);
+	(void)m_pRootAtom->FindProperty(propName, ppCountProperty);
 	ASSERT(*ppCountProperty);
 
 	snprintf(propName, sizeof(propName), "%s.%s", trefName, "entries.trackId");
-	m_pRootAtom->FindProperty(propName, ppTrackIdProperty);
+	(void)m_pRootAtom->FindProperty(propName, ppTrackIdProperty);
 	ASSERT(*ppTrackIdProperty);
 }
 
@@ -1057,8 +1183,8 @@
 	ASSERT(pDrefAtom);
 
 	MP4Integer32Property* pCountProperty = NULL;
-	pDrefAtom->FindProperty("dref.entryCount", 
-		(MP4Property**)&pCountProperty);
+	(void)pDrefAtom->FindProperty("dref.entryCount", 
+				(MP4Property**)&pCountProperty);
 	ASSERT(pCountProperty);
 	pCountProperty->IncrementValue();
 
@@ -1068,8 +1194,8 @@
 		pUrlAtom->SetFlags(pUrlAtom->GetFlags() & 0xFFFFFE);
 
 		MP4StringProperty* pUrlProperty = NULL;
-		pUrlAtom->FindProperty("url .location",
-			(MP4Property**)&pUrlProperty);
+		(void)pUrlAtom->FindProperty("url .location",
+					     (MP4Property**)&pUrlProperty);
 		ASSERT(pUrlProperty);
 		pUrlProperty->SetValue(url);
 	} else {
@@ -1079,15 +1205,15 @@
 
 MP4TrackId MP4File::AddSystemsTrack(const char* type)
 {
-	const char* normType = MP4Track::NormalizeTrackType(type); 
+	const char* normType = MP4NormalizeTrackType(type, m_verbosity); 
 
 	// TBD if user type, fix name to four chars, and warn
 
 	MP4TrackId trackId = AddTrack(type, MP4_MSECS_TIME_SCALE);
 
-	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0);
+	(void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0);
 
-	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4s");
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4s");
 
 	// stsd is a unique beast in that it has a count of the number 
 	// of child atoms that needs to be incremented after we add the mp4s atom
@@ -1132,7 +1258,7 @@
 
 	AddTrackToIod(m_odTrackId);
 
-	AddDescendantAtoms(MakeTrackName(m_odTrackId, NULL), "tref.mpod");
+	(void)AddDescendantAtoms(MakeTrackName(m_odTrackId, NULL), "tref.mpod");
 
 	return m_odTrackId;
 }
@@ -1147,22 +1273,6 @@
 	return trackId;
 }
 
-MP4Atom* MP4File::GetTrakDamrAtom(MP4TrackId trackId)
-{
-	MP4Atom* amrAtom;
-	u_int16_t trackIndex = FindTrackIndex(trackId);
-	MP4Track* pTrack = m_pTracks[trackIndex];
-	ASSERT(pTrack);
-	MP4Atom* pTrakAtom = pTrack->GetTrakAtom();
-	ASSERT(pTrakAtom);
-	if ((amrAtom = pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.sawb.damr"))) {
-		return amrAtom;
-	}
-	else if ((amrAtom = pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.samr.damr"))) {
-		return amrAtom;
-	}
-	return NULL;
-}
 // NULL terminated list of brands which require the IODS atom
 char *brandsWithIods[] = { "mp42",
                            "isom",
@@ -1174,12 +1284,12 @@
         MP4StringProperty *pMajorBrandProperty;
 	
 	MP4Atom* ftypAtom = m_pRootAtom->FindAtom("ftyp");
-	ASSERT(ftypAtom);
+	if (ftypAtom == NULL) return false;
 	
         // Check the major brand
-	ftypAtom->FindProperty(
-			"ftyp.majorBrand",
-			(MP4Property**)&pMajorBrandProperty);
+	(void)ftypAtom->FindProperty(
+				     "ftyp.majorBrand",
+				     (MP4Property**)&pMajorBrandProperty);
 	ASSERT(pMajorBrandProperty);
         for(u_int32_t j = 0 ; brandsWithIods[j] != NULL ; j++) {
                 if (!strcasecmp( ((MP4StringProperty*)pMajorBrandProperty)->GetValue(),
@@ -1189,7 +1299,7 @@
 
         // Check the compatible brands
 	MP4Integer32Property* pCompatibleBrandsCountProperty;
-	ftypAtom->FindProperty(
+        (void)ftypAtom->FindProperty(
 			"ftyp.compatibleBrandsCount",
 			(MP4Property**)&pCompatibleBrandsCountProperty);
 	ASSERT(pCompatibleBrandsCountProperty);
@@ -1197,7 +1307,7 @@
 	compatibleBrandsCount  = pCompatibleBrandsCountProperty->GetValue();
 	
 	MP4TableProperty* pCompatibleBrandsProperty;
-	ftypAtom->FindProperty(
+	(void)ftypAtom->FindProperty(
 			"ftyp.compatibleBrands",
 			(MP4Property**)&pCompatibleBrandsProperty);
 	
@@ -1218,23 +1328,9 @@
 		MP4TrackId trackId,
 		u_int32_t vendor)
 {
-	
-	MP4Atom* damrAtom = GetTrakDamrAtom(trackId);
-	
-	if (damrAtom == NULL)
-		return;
-	
-	MP4Integer32Property* pVendorProperty = NULL;
-	
-	damrAtom->FindProperty("damr.vendor",
-			(MP4Property**)&pVendorProperty,
-			NULL);
-	ASSERT(pVendorProperty);
-	
-	pVendorProperty->SetValue(vendor);
-	
-	damrAtom->Rewrite();
-	
+	SetTrackIntegerProperty(trackId, 
+				"mdia.minf.stbl.stsd.*.damr.vendor",
+				vendor);
 }
 
 void MP4File::SetAmrDecoderVersion(
@@ -1241,21 +1337,10 @@
 		MP4TrackId trackId,
 		u_int8_t decoderVersion)
 {
-	MP4Atom* damrAtom = GetTrakDamrAtom(trackId);
-	
-	if (damrAtom == NULL)
-		return;
-	
-	MP4Integer8Property* pDecoderVersionProperty;
-	
-	damrAtom->FindProperty("damr.decoderVersion",
-			(MP4Property**)&pDecoderVersionProperty,
-			NULL);
-	ASSERT(pDecoderVersionProperty);
-	
-	pDecoderVersionProperty->SetValue(decoderVersion);
-	
-	damrAtom->Rewrite();
+
+	SetTrackIntegerProperty(trackId, 
+				"mdia.minf.stbl.stsd.*.damr.decoderVersion",
+				decoderVersion);
 }
 
 void MP4File::SetAmrModeSet(
@@ -1262,23 +1347,15 @@
 		MP4TrackId trackId,
 		u_int16_t modeSet)
 {
-	MP4Atom* damrAtom = GetTrakDamrAtom(trackId);
-	
-	if (damrAtom == NULL)
-		return;
-	
-	MP4Integer16Property* pModeSetProperty;
-	
-	damrAtom->FindProperty("damr.modeSet",
-			(MP4Property**)&pModeSetProperty,
-			NULL);
-	ASSERT(pModeSetProperty);
-	
-	pModeSetProperty->SetValue(modeSet);
-	
-	damrAtom->Rewrite();
-	
+  SetTrackIntegerProperty(trackId, 
+			  "mdia.minf.stbl.stsd.*.damr.modeSet",
+			  modeSet);
 }
+uint16_t MP4File::GetAmrModeSet(MP4TrackId trackId)
+{
+  return GetTrackIntegerProperty(trackId, 
+				 "mdia.minf.stbl.stsd.*.damr.modeSet");
+}
 
 MP4TrackId MP4File::AddAmrAudioTrack(
 		        u_int32_t timeScale,
@@ -1296,9 +1373,9 @@
 	
 	SetTrackFloatProperty(trackId, "tkhd.volume", 1.0);
 	
-	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
+	(void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
 	
-	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), isAmrWB ? "sawb" : "samr");
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), isAmrWB ? "sawb" : "samr");
 	
 	// stsd is a unique beast in that it has a count of the number
 	// of child atoms that needs to be incremented after we add the mp4a atom
@@ -1308,36 +1385,23 @@
 			(MP4Property**)&pStsdCountProperty);
 	pStsdCountProperty->IncrementValue();
 	
-	if (isAmrWB) {
-		SetTrackIntegerProperty(trackId,
-			"mdia.minf.stbl.stsd.sawb.timeScale", timeScale);
+	SetTrackIntegerProperty(trackId,
+				"mdia.minf.stbl.stsd.*.timeScale", 
+				timeScale);
 	
 	SetTrackIntegerProperty(trackId,
-			"mdia.minf.stbl.stsd.sawb.damr.modeSet", modeSet);
+				"mdia.minf.stbl.stsd.*.damr.modeSet", 
+				modeSet);
 	
 	SetTrackIntegerProperty(trackId,
-			"mdia.minf.stbl.stsd.sawb.damr.modeChangePeriod", modeChangePeriod);
+				"mdia.minf.stbl.stsd.*.damr.modeChangePeriod", 
+				modeChangePeriod);
 	
 	SetTrackIntegerProperty(trackId,
-			"mdia.minf.stbl.stsd.sawb.damr.framesPerSample", framesPerSample);
+				"mdia.minf.stbl.stsd.*.damr.framesPerSample", 
+				framesPerSample);
 	
-	m_pTracks[FindTrackIndex(trackId)]->
-		SetFixedSampleDuration(fixedSampleDuration);
 	
-	} else {
-		SetTrackIntegerProperty(trackId,
-				"mdia.minf.stbl.stsd.samr.timeScale", timeScale);
-		
-		SetTrackIntegerProperty(trackId,
-				"mdia.minf.stbl.stsd.samr.damr.modeSet", modeSet);
-		
-		SetTrackIntegerProperty(trackId,
-				"mdia.minf.stbl.stsd.samr.damr.modeChangePeriod", modeChangePeriod);
-		
-		SetTrackIntegerProperty(trackId,
-				"mdia.minf.stbl.stsd.samr.damr.framesPerSample", framesPerSample);
-	}
-	
 	m_pTracks[FindTrackIndex(trackId)]->
 		SetFixedSampleDuration(fixedSampleDuration);
 
@@ -1355,9 +1419,9 @@
 
 	SetTrackFloatProperty(trackId, "tkhd.volume", 1.0);
 
-	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
+	(void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
 
-	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4a");
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4a");
 
 	// stsd is a unique beast in that it has a count of the number 
 	// of child atoms that needs to be incremented after we add the mp4a atom
@@ -1403,7 +1467,8 @@
                                      u_int8_t  key_ind_len,
                                      u_int8_t  iv_len,
                                      bool      selective_enc,
-                                     char      *kms_uri
+                                     const char *kms_uri,
+				     bool use_ismacryp
                                      )
 {
   u_int32_t original_fmt = 0;
@@ -1414,9 +1479,9 @@
 
   SetTrackFloatProperty(trackId, "tkhd.volume", 1.0);
 
-  InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
+  (void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
 
-  AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "enca");
+  (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "enca");
 
   // stsd is a unique beast in that it has a count of the number 
   // of child atoms that needs to be incremented after we add the enca atom
@@ -1428,38 +1493,50 @@
 
   /* set all the ismacryp-specific values */
   // original format is mp4a
-  original_fmt = ('m'<<24 | 'p'<<16 | '4'<<8 | 'a');
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.enca.sinf.frma.data-format", 
-			  original_fmt);
+  if (use_ismacryp) {
+    original_fmt = ATOMID("mp4a");
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.enca.sinf.frma.data-format", 
+			    original_fmt);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.enca.sinf.schm.scheme_type", 
-			  scheme_type);
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.enca.sinf"), 
+		 "schm");
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.enca.sinf"), 
+		 "schi");
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.enca.sinf.schi"), 
+		 "iKMS");
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.enca.sinf.schi"), 
+		 "iSFM");
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.enca.sinf.schm.scheme_type", 
+			    scheme_type);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.enca.sinf.schm.scheme_version", 
-			  scheme_version);
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.enca.sinf.schm.scheme_version", 
+			    scheme_version);
   
-  SetTrackStringProperty(trackId,
-			 "mdia.minf.stbl.stsd.enca.sinf.schi.iKMS.kms_URI", 
-			 kms_uri);
-  if (kms_uri != NULL) {
-    free(kms_uri);
-  }  
+    SetTrackStringProperty(trackId,
+			   "mdia.minf.stbl.stsd.enca.sinf.schi.iKMS.kms_URI", 
+			   kms_uri);
+    #if 0
+    if (kms_uri != NULL) {
+      free((void *)kms_uri);
+    }  
+    #endif
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.selective-encryption", 
-			  selective_enc);
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.selective-encryption", 
+			    selective_enc);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.key-indicator-length", 
-			  key_ind_len);
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.key-indicator-length", 
+			    key_ind_len);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.IV-length", 
-			  iv_len);
-  /* end ismacryp */
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.enca.sinf.schi.iSFM.IV-length", 
+			    iv_len);
+    /* end ismacryp */
+  }
 
   SetTrackIntegerProperty(trackId, 
 			  "mdia.minf.stbl.stsd.enca.timeScale", timeScale);
@@ -1489,12 +1566,54 @@
   return trackId;
 }
 
-MP4TrackId MP4File::AddVideoTrack(
+MP4TrackId MP4File::AddCntlTrackDefault (uint32_t timeScale,
+					 MP4Duration sampleDuration,
+					 const char *type)
+{
+  MP4TrackId trackId = AddTrack(MP4_CNTL_TRACK_TYPE, timeScale);
+
+  (void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "nmhd", 0);
+  (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), type);
+
+  // stsd is a unique beast in that it has a count of the number 
+  // of child atoms that needs to be incremented after we add the mp4v atom
+  MP4Integer32Property* pStsdCountProperty;
+  FindIntegerProperty(
+		      MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
+		      (MP4Property**)&pStsdCountProperty);
+  pStsdCountProperty->IncrementValue();
+  
+  SetTrackIntegerProperty(trackId, 
+			  "mdia.minf.stbl.stsz.sampleSize", sampleDuration);
+  
+  m_pTracks[FindTrackIndex(trackId)]->
+    SetFixedSampleDuration(sampleDuration);
+  
+  return trackId;
+}
+
+MP4TrackId MP4File::AddHrefTrack (uint32_t timeScale, 
+				  MP4Duration sampleDuration,
+				  const char *base_url)
+{
+  MP4TrackId trackId = AddCntlTrackDefault(timeScale, sampleDuration, "href");
+
+  if (base_url != NULL) {
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.href"), 
+		 "burl");
+    SetTrackStringProperty(trackId, "mdia.minf.stbl.stsd.href.burl.base_url",
+			   base_url);
+  }
+
+  return trackId;
+}
+		  
+MP4TrackId MP4File::AddVideoTrackDefault(
 	u_int32_t timeScale, 
 	MP4Duration sampleDuration, 
 	u_int16_t width, 
 	u_int16_t height, 
-	u_int8_t videoType)
+	const char *videoType)
 {
 	MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);
 
@@ -1503,9 +1622,9 @@
 	SetTrackFloatProperty(trackId, "tkhd.width", width);
 	SetTrackFloatProperty(trackId, "tkhd.height", height);
 
-	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
+	(void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
 
-	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "mp4v");
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), videoType);
 
 	// stsd is a unique beast in that it has a count of the number 
 	// of child atoms that needs to be incremented after we add the mp4v atom
@@ -1516,6 +1635,27 @@
 	pStsdCountProperty->IncrementValue();
 
 	SetTrackIntegerProperty(trackId, 
+		"mdia.minf.stbl.stsz.sampleSize", sampleDuration);
+
+	m_pTracks[FindTrackIndex(trackId)]->
+		SetFixedSampleDuration(sampleDuration);
+
+	return trackId;
+}
+MP4TrackId MP4File::AddMP4VideoTrack(
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration, 
+	u_int16_t width, 
+	u_int16_t height, 
+	u_int8_t videoType)
+{
+  MP4TrackId trackId = AddVideoTrackDefault(timeScale, 
+					    sampleDuration,
+					    width, 
+					    height,
+					    "mp4v");
+
+	SetTrackIntegerProperty(trackId, 
 		"mdia.minf.stbl.stsd.mp4v.width", width);
 	SetTrackIntegerProperty(trackId, 
 		"mdia.minf.stbl.stsd.mp4v.height", height);
@@ -1539,49 +1679,27 @@
 		"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.streamType", 
 		MP4VisualStreamType);
 
-	SetTrackIntegerProperty(trackId, 
-		"mdia.minf.stbl.stsz.sampleSize", sampleDuration);
-
-	m_pTracks[FindTrackIndex(trackId)]->
-		SetFixedSampleDuration(sampleDuration);
-
 	return trackId;
 }
 
+// ismacrypted
 MP4TrackId MP4File::AddEncVideoTrack(u_int32_t timeScale, 
 				     MP4Duration sampleDuration, 
 				     u_int16_t width, 
 				     u_int16_t height, 
 				     u_int8_t videoType,
-				     u_int32_t scheme_type,
-				     u_int16_t scheme_version, 
-				     u_int8_t key_ind_len,
-                                     u_int8_t iv_len,
-                                     bool selective_enc,
-                                     char *kms_uri
+				  	mp4v2_ismacrypParams *icPp,
+					const char *oFormat
                                      )
 {
   u_int32_t original_fmt = 0;
 
-  MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);
+  MP4TrackId trackId = AddVideoTrackDefault(timeScale, 
+					    sampleDuration,
+					    width,
+					    height,
+					    "encv");
 
-  AddTrackToOd(trackId);
-
-  SetTrackFloatProperty(trackId, "tkhd.width", width);
-  SetTrackFloatProperty(trackId, "tkhd.height", height);
-
-  InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
-
-  AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "encv");
-
-  // stsd is a unique beast in that it has a count of the number 
-  // of child atoms that needs to be incremented after we add the encv atom
-  MP4Integer32Property* pStsdCountProperty;
-  FindIntegerProperty(
-		      MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
-		      (MP4Property**)&pStsdCountProperty);
-  pStsdCountProperty->IncrementValue();
-
   SetTrackIntegerProperty(trackId, 
 			  "mdia.minf.stbl.stsd.encv.width", width);
   SetTrackIntegerProperty(trackId, 
@@ -1588,40 +1706,51 @@
 			  "mdia.minf.stbl.stsd.encv.height", height);
 
   /* set all the ismacryp-specific values */
-  // original format is mp4v
-  original_fmt = ('m'<<24 | 'p'<<16 | '4'<<8 | 'v');
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.encv.sinf.frma.data-format", 
-			  original_fmt);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_type", 
-			  scheme_type);
+    original_fmt = ATOMID(oFormat);
+	
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.encv.sinf.frma.data-format", 
+			    original_fmt);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_version", 
-			  scheme_version);
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf"), 
+		 "schm");
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf"), 
+		 "schi");
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi"), 
+		 "iKMS");
+    (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi"), 
+		 "iSFM");
+
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_type", 
+			    icPp->scheme_type);
+
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_version", 
+			    icPp->scheme_version);
   
-  SetTrackStringProperty(trackId,
-			 "mdia.minf.stbl.stsd.encv.sinf.schi.iKMS.kms_URI", 
-			 kms_uri);
-  if (kms_uri != NULL) {
-    free(kms_uri);
-  }  
+    SetTrackStringProperty(trackId,
+			   "mdia.minf.stbl.stsd.encv.sinf.schi.iKMS.kms_URI", 
+			   icPp->kms_uri);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.selective-encryption", 
-			  selective_enc);
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.selective-encryption", 
+			    icPp->selective_enc);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.key-indicator-length", 
-			  key_ind_len);
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.key-indicator-length", 
+			    icPp->key_ind_len);
 
-  SetTrackIntegerProperty(trackId,
-			  "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.IV-length", 
-			  iv_len);
-  /* end ismacryp */
+    SetTrackIntegerProperty(trackId,
+			    "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.IV-length", 
+			    icPp->iv_len);
 
+  #if 0
+  if (icPp->kms_uri != NULL) {
+    free(icPp->kms_uri);
+  }  
+  #endif
 
   SetTrackIntegerProperty(trackId, 
 			  "mdia.minf.stbl.stsd.encv.esds.ESID", 
@@ -1642,30 +1771,229 @@
 		"mdia.minf.stbl.stsd.encv.esds.decConfigDescr.streamType", 
 			  MP4VisualStreamType);
 
-  SetTrackIntegerProperty(trackId, 
-			  "mdia.minf.stbl.stsz.sampleSize", sampleDuration);
+  return trackId;
+}
 
-  m_pTracks[FindTrackIndex(trackId)]->
-    SetFixedSampleDuration(sampleDuration);
+MP4TrackId MP4File::AddH264VideoTrack(
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration, 
+	u_int16_t width, 
+	u_int16_t height, 
+	uint8_t AVCProfileIndication,
+	uint8_t profile_compat,
+	uint8_t AVCLevelIndication,
+	uint8_t sampleLenFieldSizeMinusOne)
+{
+  MP4TrackId trackId = AddVideoTrackDefault(timeScale, 
+					    sampleDuration,
+					    width, 
+					    height,
+					    "avc1");
 
-  return trackId;
+	SetTrackIntegerProperty(trackId, 
+		"mdia.minf.stbl.stsd.avc1.width", width);
+	SetTrackIntegerProperty(trackId, 
+		"mdia.minf.stbl.stsd.avc1.height", height);
+
+	//FIXME - check this 
+	// shouldn't need this
+	#if 0
+	AddChildAtom(MakeTrackName(trackId,
+				   "mdia.minf.stbl.stsd.avc1"),
+		     "avcC");
+        #endif
+	
+	SetTrackIntegerProperty(trackId,
+				"mdia.minf.stbl.stsd.avc1.avcC.AVCProfileIndication",
+				AVCProfileIndication);
+	SetTrackIntegerProperty(trackId,
+				"mdia.minf.stbl.stsd.avc1.avcC.profile_compatibility",
+				profile_compat);
+	SetTrackIntegerProperty(trackId,
+				"mdia.minf.stbl.stsd.avc1.avcC.AVCLevelIndication",
+				AVCLevelIndication);
+	SetTrackIntegerProperty(trackId,
+				"mdia.minf.stbl.stsd.avc1.avcC.lengthSizeMinusOne",
+				sampleLenFieldSizeMinusOne);
+	
+
+	return trackId;
 }
+
+MP4TrackId MP4File::AddEncH264VideoTrack(
+	u_int32_t timeScale, 
+	MP4Duration sampleDuration, 
+	u_int16_t width, 
+	u_int16_t height, 
+  	MP4Atom *srcAtom,
+        mp4v2_ismacrypParams *icPp)
+
+{
+
+  u_int32_t original_fmt = 0;
+  MP4Atom *avcCAtom;
+
+  MP4TrackId trackId = AddVideoTrackDefault(timeScale, 
+					    sampleDuration,
+					    width, 
+					    height,
+					    "encv");
+
+  SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.width", width);
+  SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.height", height);
+  
+  (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv"), "avcC");
+  
+  // create default values
+  avcCAtom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.avcC"));
+  
+  // export source atom 
+  ((MP4AvcCAtom *) srcAtom)->Clone((MP4AvcCAtom *)avcCAtom);
+  
+  /* set all the ismacryp-specific values */
+  
+  (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf"), "schm");
+  (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf"), "schi");
+  (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi"), "iKMS");
+  (void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi"), "iSFM");
+
+    // per ismacrypt E&A V1.1 section 9.1.2.1 'avc1' is renamed '264b'
+    // avc1 must not appear as a sample entry name or original format name
+    original_fmt = ATOMID("264b");
+    SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.sinf.frma.data-format", 
+			    original_fmt);
+
+    SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_type", 
+			    icPp->scheme_type);
+
+    SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.sinf.schm.scheme_version", 
+			    icPp->scheme_version);
+  
+    SetTrackStringProperty(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi.iKMS.kms_URI", 
+			   icPp->kms_uri);
+
+    SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.selective-encryption", 
+			    icPp->selective_enc);
+
+    SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.key-indicator-length", 
+			    icPp->key_ind_len);
+
+    SetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.encv.sinf.schi.iSFM.IV-length", 
+			    icPp->iv_len);
+
+
+	return trackId;
+}
+
+
+void MP4File::AddH264SequenceParameterSet (MP4TrackId trackId,
+					   const uint8_t *pSequence,
+					   uint16_t sequenceLen)
+{
+  const char *format;
+  MP4Atom *avcCAtom;
+
+  // get 4cc media format - can be avc1 or encv for ismacrypted track
+  format = GetTrackMediaDataName(trackId);
+
+  if (!strcasecmp(format, "avc1"))
+ 	 avcCAtom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.avc1.avcC"));
+  else if (!strcasecmp(format, "encv"))
+ 	 avcCAtom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.avcC"));
+  else 
+        // huh?  unknown track format 
+	return;
+
+
+  MP4BitfieldProperty *pCount;
+  MP4Integer16Property *pLength;
+  MP4BytesProperty *pUnit;
+  if ((avcCAtom->FindProperty("avcC.numOfSequenceParameterSets",
+			     (MP4Property **)&pCount) == false) ||
+      (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetLength",
+			      (MP4Property **)&pLength) == false) ||
+      (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetNALUnit",
+			      (MP4Property **)&pUnit) == false)) {
+    VERBOSE_ERROR(m_verbosity, WARNING("Could not find avcC properties"));
+    return;
+  }
+  uint32_t count = pCount->GetValue();
+  
+  if (count > 0) {
+    // see if we already exist
+    for (uint32_t index = 0; index < count; index++) {
+      if (pLength->GetValue(index) == sequenceLen) {
+	uint8_t *seq;
+	uint32_t seqlen;
+	pUnit->GetValue(&seq, &seqlen, index);
+	if (memcmp(seq, pSequence, sequenceLen) == 0) {
+	  free(seq);
+	  return;
+	}
+	free(seq);
+      }
+    }
+  }
+  pLength->AddValue(sequenceLen);
+  pUnit->AddValue(pSequence, sequenceLen);
+  pCount->IncrementValue();
+
+  return;
+}
+void MP4File::AddH264PictureParameterSet (MP4TrackId trackId,
+					  const uint8_t *pPict,
+					  uint16_t pictLen)
+{
+  MP4Atom *avcCAtom = 
+    FindAtom(MakeTrackName(trackId,
+			   "mdia.minf.stbl.stsd.avc1.avcC"));
+  MP4Integer8Property *pCount;
+  MP4Integer16Property *pLength;
+  MP4BytesProperty *pUnit;
+  if ((avcCAtom->FindProperty("avcC.numOfPictureParameterSets",
+			     (MP4Property **)&pCount) == false) ||
+      (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetLength",
+			      (MP4Property **)&pLength) == false) ||
+      (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetNALUnit",
+			      (MP4Property **)&pUnit) == false)) {
+    VERBOSE_ERROR(m_verbosity, 
+		  WARNING("Could not find avcC picture table properties"));
+    return;
+  }
+  uint32_t count = pCount->GetValue();
+  
+  if (count > 0) {
+    // see if we already exist
+    for (uint32_t index = 0; index < count; index++) {
+      if (pLength->GetValue(index) == pictLen) {
+	uint8_t *seq;
+	uint32_t seqlen;
+	pUnit->GetValue(&seq, &seqlen, index);
+	if (memcmp(seq, pPict, pictLen) == 0) {
+	  VERBOSE_WRITE(m_verbosity, 
+			fprintf(stderr, "picture matches %d\n", index));
+	  free(seq);
+	  return;
+	}
+	free(seq);
+      }
+    }
+  }
+  pLength->AddValue(pictLen);
+  pUnit->AddValue(pPict, pictLen);
+  pCount->IncrementValue();
+  VERBOSE_WRITE(m_verbosity, 
+		fprintf(stderr, "new picture added %d\n", pCount->GetValue()));
+
+  return;
+}
 void  MP4File::SetH263Vendor(
 		MP4TrackId trackId,
 		u_int32_t vendor)
 {
-	
-	MP4Atom* d263Atom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"));
-	
-	if (d263Atom == NULL)
-		return;
-
 	SetTrackIntegerProperty(trackId,
 			"mdia.minf.stbl.stsd.s263.d263.vendor",
 			vendor);
-
-	d263Atom->Rewrite();
-	
 }
 
 void MP4File::SetH263DecoderVersion(
@@ -1672,17 +2000,9 @@
 		MP4TrackId trackId,
 		u_int8_t decoderVersion)
 {
-	MP4Atom* d263Atom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"));
-	
-	if (d263Atom == NULL) {
-		return;
-	}
-	
 	SetTrackIntegerProperty(trackId,
 			"mdia.minf.stbl.stsd.s263.d263.decoderVersion",
 			decoderVersion);
-
-	d263Atom->Rewrite();
 }
 
 void MP4File::SetH263Bitrates(
@@ -1690,13 +2010,6 @@
 	u_int32_t avgBitrate,
 	u_int32_t maxBitrate)
 {
-	MP4Atom* bitrAtom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263.bitr"));
-
-	if (bitrAtom == NULL) {
-		VERBOSE_ERROR(m_verbosity, WARNING("Could not find bitr atom!"));
-		return;
-	}
-
 	SetTrackIntegerProperty(trackId, 
 			"mdia.minf.stbl.stsd.s263.d263.bitr.avgBitrate", 
 			avgBitrate);
@@ -1705,8 +2018,6 @@
 			"mdia.minf.stbl.stsd.s263.d263.bitr.maxBitrate",
 			maxBitrate);
 
-	bitrAtom->Rewrite();
-
 }
 
 MP4TrackId MP4File::AddH263VideoTrack(
@@ -1720,25 +2031,12 @@
 		u_int32_t maxBitrate)
 
 {
-	MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);
+  MP4TrackId trackId = AddVideoTrackDefault(timeScale, 
+					    sampleDuration,
+					    width,
+					    height,
+					    "s263");
 	
-	AddTrackToOd(trackId);
-	
-	SetTrackFloatProperty(trackId, "tkhd.width", width);
-	SetTrackFloatProperty(trackId, "tkhd.height", height);
-	
-	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
-	
-	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "s263");
-	
-	// stsd is a unique beast in that it has a count of the number
-	// of child atoms that needs to be incremented after we add the mp4v atom
-	MP4Integer32Property* pStsdCountProperty;
-	FindIntegerProperty(
-			MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
-			(MP4Property**)&pStsdCountProperty);
-	pStsdCountProperty->IncrementValue();
-	
 	SetTrackIntegerProperty(trackId,
 			"mdia.minf.stbl.stsd.s263.width", width);
 	SetTrackIntegerProperty(trackId,
@@ -1751,7 +2049,7 @@
 			"mdia.minf.stbl.stsd.s263.d263.h263Profile", h263Profile);
 
 	// Add the bitr atom
-	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"), 
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.s263.d263"), 
 			"bitr");
 
 	SetTrackIntegerProperty(trackId,
@@ -1764,9 +2062,6 @@
 	SetTrackIntegerProperty(trackId,
 			"mdia.minf.stbl.stsz.sampleSize", sampleDuration);
 	
-	m_pTracks[FindTrackIndex(trackId)]->
-		SetFixedSampleDuration(sampleDuration);
-	
 	return trackId;
 
 }
@@ -1774,14 +2069,14 @@
 MP4TrackId MP4File::AddHintTrack(MP4TrackId refTrackId)
 {
 	// validate reference track id
-	FindTrackIndex(refTrackId);
+  (void)FindTrackIndex(refTrackId);
 
 	MP4TrackId trackId = 
 		AddTrack(MP4_HINT_TRACK_TYPE, GetTrackTimeScale(refTrackId));
 
-	InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "hmhd", 0);
+	(void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "hmhd", 0);
 
-	AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "rtp ");
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "rtp ");
 
 	// stsd is a unique beast in that it has a count of the number 
 	// of child atoms that needs to be incremented after we add the rtp atom
@@ -1795,17 +2090,84 @@
 		"mdia.minf.stbl.stsd.rtp .tims.timeScale", 
 		GetTrackTimeScale(trackId));
 
-	AddDescendantAtoms(MakeTrackName(trackId, NULL), "tref.hint");
+	(void)AddDescendantAtoms(MakeTrackName(trackId, NULL), "tref.hint");
 
 	AddTrackReference(MakeTrackName(trackId, "tref.hint"), refTrackId);
 
-	AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hnti.sdp ");
+	(void)AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hnti.sdp ");
 
-	AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hinf");
+	(void)AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.hinf");
 
 	return trackId;
 }
 
+MP4TrackId MP4File::AddTextTrack(MP4TrackId refTrackId)
+{
+	// validate reference track id
+  (void)FindTrackIndex(refTrackId);
+
+	MP4TrackId trackId = 
+		AddTrack(MP4_TEXT_TRACK_TYPE, GetTrackTimeScale(refTrackId));
+
+	(void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "gmhd", 0);
+
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "text");
+
+	// stsd is a unique beast in that it has a count of the number 
+	// of child atoms that needs to be incremented after we add the text atom
+	MP4Integer32Property* pStsdCountProperty;
+	FindIntegerProperty(
+		MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
+		(MP4Property**)&pStsdCountProperty);
+	pStsdCountProperty->IncrementValue();
+
+	return trackId;
+}
+
+MP4TrackId MP4File::AddChapterTextTrack(MP4TrackId refTrackId)
+{
+	// validate reference track id
+	(void)FindTrackIndex(refTrackId);
+
+	MP4TrackId trackId = 
+		AddTrack(MP4_TEXT_TRACK_TYPE, GetTrackTimeScale(refTrackId));
+
+	(void)InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "gmhd", 0);
+
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "text");
+
+	// stsd is a unique beast in that it has a count of the number 
+	// of child atoms that needs to be incremented after we add the text atom
+	MP4Integer32Property* pStsdCountProperty;
+	FindIntegerProperty(
+		MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
+		(MP4Property**)&pStsdCountProperty);
+	pStsdCountProperty->IncrementValue();
+
+	// add a "text" atom to the generic media header
+	// this is different to the stsd "text" atom added above
+	// truth be told, it's not clear what this second "text" atom does,
+	// but all iTunes Store movies (with chapter markers) have it,
+	// as do all movies with chapter tracks made by hand in QuickTime Pro
+	(void)AddChildAtom(MakeTrackName(trackId, "mdia.minf.gmhd"), "text");
+
+	// disable the chapter text track
+	// it won't display anyway, as it has zero display size,
+	// but nonetheless it's good to disable it
+	// the track still operates as a chapter track when disabled
+    MP4Atom *pTkhdAtom = FindAtom(MakeTrackName(trackId, "tkhd"));
+	if (pTkhdAtom) {
+	   	pTkhdAtom->SetFlags(0xE);
+	}
+
+	// add a "chapter" track reference to our reference track,
+	// pointing to this new chapter track
+	(void)AddDescendantAtoms(MakeTrackName(refTrackId, NULL), "tref.chap");
+	AddTrackReference(MakeTrackName(refTrackId, "tref.chap"), trackId);
+
+	return trackId;
+}
+
 void MP4File::DeleteTrack(MP4TrackId trackId)
 {
 	ProtectWriteOperation("MP4DeleteTrack");
@@ -1844,7 +2206,7 @@
 	} 
 
 	u_int32_t typeSeen = 0;
-	const char* normType = MP4Track::NormalizeTrackType(type);
+	const char* normType = MP4NormalizeTrackType(type, m_verbosity);
 
 	for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
 		if (!strcmp(normType, m_pTracks[i]->GetType())) {
@@ -1874,7 +2236,7 @@
 	if (trackId <= 0xFFFF) {
 		// check that nextTrackid is correct
 		try {
-			FindTrackIndex(trackId);
+		  (void)FindTrackIndex(trackId);
 			// ERROR, this trackId is in use
 		}
 		catch (MP4Error* e) {
@@ -1888,7 +2250,7 @@
 	// we need to search for a track id
 	for (trackId = 1; trackId <= 0xFFFF; trackId++) {
 		try {
-			FindTrackIndex(trackId);
+		  (void)FindTrackIndex(trackId);
 			// KEEP LOOKING, this trackId is in use
 		}
 		catch (MP4Error* e) {
@@ -1911,7 +2273,7 @@
   } 
 
   u_int32_t typeSeen = 0;
-  const char* normType = MP4Track::NormalizeTrackType(type);
+  const char* normType = MP4NormalizeTrackType(type, m_verbosity);
 
   for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
     if (!strcmp(normType, m_pTracks[i]->GetType())) {
@@ -2053,17 +2415,21 @@
 {
 	u_int16_t trakIndex = FindTrakAtomIndex(trackId);
 
-	static char trakName[1024];
 	if (name == NULL || name[0] == '\0') {
-		snprintf(trakName, sizeof(trakName), 
+		snprintf(m_trakName, sizeof(m_trakName), 
 			"moov.trak[%u]", trakIndex);
 	} else {
-		snprintf(trakName, sizeof(trakName), 
+		snprintf(m_trakName, sizeof(m_trakName), 
 			"moov.trak[%u].%s", trakIndex, name);
 	}
-	return trakName;
+	return m_trakName;
 }
 
+MP4Atom *MP4File::FindTrackAtom (MP4TrackId trackId, const char *name)
+{
+  return FindAtom(MakeTrackName(trackId, name));
+}
+
 u_int64_t MP4File::GetTrackIntegerProperty(MP4TrackId trackId, const char* name)
 {
 	return GetIntegerProperty(MakeTrackName(trackId, name));
@@ -2192,7 +2558,7 @@
 
 void MP4File::SetSessionSdp(const char* sdpString)
 {
-	AddDescendantAtoms("moov", "udta.hnti.rtp ");
+  (void)AddDescendantAtoms("moov", "udta.hnti.rtp ");
 
 	SetStringProperty("moov.udta.hnti.rtp .sdpText", sdpString);
 }
@@ -2217,7 +2583,42 @@
 	MP4Free(newSdpString);
 }
 
+//
+// ismacrypt API - retrieve OriginalFormatBox 
+//
+// parameters are assumed to have been sanity tested in mp4.cpp
+// don't call this unless media data name is 'encv',
+// results may otherwise be unpredictable.
+//
+// input:
+// trackID - valid encv track ID for this file
+// buflen  - length of oFormat, minimum is 5 (4cc plus null terminator)
+//
+// output:
+// oFormat - buffer to return null terminated string containing 
+//           track original format
+// return:
+// 0       - original format returned OK
+// 1       - buffer length error or problem retrieving track property
+//
+//
+bool MP4File::GetTrackMediaDataOriginalFormat(MP4TrackId trackId, 
+	char *originalFormat, u_int32_t buflen)
+{
+  u_int32_t format;
 
+  if (buflen < 5)
+	return false;
+
+  format = GetTrackIntegerProperty(trackId,
+	        "mdia.minf.stbl.stsd.*.sinf.frma.data-format");
+
+  IDATOM(format, originalFormat);
+  return true;
+
+}
+	     
+
 // track level convenience functions
 
 MP4SampleId MP4File::GetTrackNumberOfSamples(MP4TrackId trackId)
@@ -2230,6 +2631,22 @@
 	return m_pTracks[FindTrackIndex(trackId)]->GetType();
 }
 
+const char *MP4File::GetTrackMediaDataName (MP4TrackId trackId)
+{
+  MP4Atom *pChild;
+  MP4Atom *pAtom = 
+    FindAtom(MakeTrackName(trackId, 
+			   "mdia.minf.stbl.stsd"));
+  if (pAtom->GetNumberOfChildAtoms() != 1) {
+    VERBOSE_ERROR(m_verbosity, 
+		  fprintf(stderr, "track %d has more than 1 child atoms in stsd\n", trackId));
+    return NULL;
+  }
+  pChild = pAtom->GetChildAtom(0);
+  return pChild->GetType();
+}
+	     
+
 u_int32_t MP4File::GetTrackTimeScale(MP4TrackId trackId)
 {
 	return m_pTracks[FindTrackIndex(trackId)]->GetTimeScale();
@@ -2248,18 +2665,17 @@
 	return GetTrackIntegerProperty(trackId, "mdia.mdhd.duration");
 }
 
-// now GetTrackEsdsObjectTypeId 
-u_int8_t MP4File::GetTrackAudioType(MP4TrackId trackId)
-{
-        return GetTrackIntegerProperty(trackId,
-                "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId");
-}
-
 u_int8_t MP4File::GetTrackEsdsObjectTypeId(MP4TrackId trackId)
 {
 	// changed mp4a to * to handle enca case
+  try {
 	return GetTrackIntegerProperty(trackId, 
 		"mdia.minf.stbl.stsd.*.esds.decConfigDescr.objectTypeId");
+  } catch (MP4Error *e) {
+    delete e;
+    return GetTrackIntegerProperty(trackId, 
+		"mdia.minf.stbl.stsd.*.*.esds.decConfigDescr.objectTypeId");
+  }
 }
 
 u_int8_t MP4File::GetTrackAudioMpeg4Type(MP4TrackId trackId)
@@ -2278,10 +2694,20 @@
 	GetTrackESConfiguration(trackId, &pEsConfig, &esConfigSize);
 
 	if (esConfigSize < 1) {
+	  free(pEsConfig);
 		return MP4_MPEG4_INVALID_AUDIO_TYPE;
 	}
 
-	u_int8_t mpeg4Type = (pEsConfig[0] >> 3);
+	u_int8_t mpeg4Type = ((pEsConfig[0] >> 3) & 0x1f);
+	// TTTT TXXX XXX  potentially 6 bits of extension.
+	if (mpeg4Type == 0x1f) {
+	  if (esConfigSize < 2) {
+	    free(pEsConfig);
+	    return MP4_MPEG4_INVALID_AUDIO_TYPE;
+	  }
+	  mpeg4Type = 32 + 
+	    (((pEsConfig[0] & 0x7) << 3) | ((pEsConfig[1] >> 5) & 0x7));
+	}
 
 	free(pEsConfig);
 
@@ -2288,12 +2714,6 @@
 	return mpeg4Type;
 }
 
-// replaced with GetTrackEsdsObjectTypeId
-u_int8_t MP4File::GetTrackVideoType(MP4TrackId trackId)
-{
-	return GetTrackIntegerProperty(trackId, 
-		"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId");
-}
 
 MP4Duration MP4File::GetTrackFixedSampleDuration(MP4TrackId trackId)
 {
@@ -2300,7 +2720,7 @@
 	return m_pTracks[FindTrackIndex(trackId)]->GetFixedSampleDuration();
 }
 
-float MP4File::GetTrackVideoFrameRate(MP4TrackId trackId)
+double MP4File::GetTrackVideoFrameRate(MP4TrackId trackId)
 {
 	MP4SampleId numSamples =
 		GetTrackNumberOfSamples(trackId);
@@ -2316,6 +2736,12 @@
 	return ((double)numSamples / UINT64_TO_DOUBLE(msDuration)) * MP4_MSECS_TIME_SCALE;
 }
 
+int MP4File::GetTrackAudioChannels (MP4TrackId trackId)
+{
+  return GetTrackIntegerProperty(trackId, 
+				 "mdia.minf.stbl.stsd.*[0].channels");
+}
+
 // true if media track encrypted according to ismacryp
 bool MP4File::IsIsmaCrypMediaTrack(MP4TrackId trackId)
 {
@@ -2331,21 +2757,35 @@
 void MP4File::GetTrackESConfiguration(MP4TrackId trackId, 
 	u_int8_t** ppConfig, u_int32_t* pConfigSize)
 {
+  try {
 	GetTrackBytesProperty(trackId, 
 		"mdia.minf.stbl.stsd.*[0].esds.decConfigDescr.decSpecificInfo[0].info",
 		ppConfig, pConfigSize);
+  } catch (MP4Error *e) {
+    delete e;
+	GetTrackBytesProperty(trackId, 
+		"mdia.minf.stbl.stsd.*[0].*.esds.decConfigDescr.decSpecificInfo[0].info",
+		ppConfig, pConfigSize);
+  }
 }
 
+void MP4File::GetTrackVideoMetadata(MP4TrackId trackId, 
+	u_int8_t** ppConfig, u_int32_t* pConfigSize)
+{
+	GetTrackBytesProperty(trackId, 
+		"mdia.minf.stbl.stsd.*[0].*.metadata",
+		ppConfig, pConfigSize);
+}
+
 void MP4File::SetTrackESConfiguration(MP4TrackId trackId, 
 	const u_int8_t* pConfig, u_int32_t configSize)
 {
 	// get a handle on the track decoder config descriptor 
 	MP4DescriptorProperty* pConfigDescrProperty = NULL;
-	FindProperty(MakeTrackName(trackId, 
-		"mdia.minf.stbl.stsd.*[0].esds.decConfigDescr.decSpecificInfo"),
-		(MP4Property**)&pConfigDescrProperty);
-
-	if (pConfigDescrProperty == NULL) {
+	if (FindProperty(MakeTrackName(trackId, 
+				       "mdia.minf.stbl.stsd.*[0].esds.decConfigDescr.decSpecificInfo"),
+			 (MP4Property**)&pConfigDescrProperty) == false ||
+	    pConfigDescrProperty == NULL) {
 		// probably trackId refers to a hint track
 		throw new MP4Error("no such property", "MP4SetTrackESConfiguration");
 	}
@@ -2352,8 +2792,8 @@
 
 	// lookup the property to store the configuration
 	MP4BytesProperty* pInfoProperty = NULL;
-	pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
-		(MP4Property**)&pInfoProperty);
+	(void)pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
+						  (MP4Property**)&pInfoProperty);
 
 	// configuration being set for the first time
 	if (pInfoProperty == NULL) {
@@ -2362,7 +2802,7 @@
 			pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag);
 		pConfigDescr->Generate();
 
-		pConfigDescrProperty->FindProperty(
+		(void)pConfigDescrProperty->FindProperty(
 			"decSpecificInfo[0].info",
 			(MP4Property**)&pInfoProperty);
 		ASSERT(pInfoProperty);
@@ -2372,6 +2812,96 @@
 	pInfoProperty->SetValue(pConfig, configSize);
 }
 
+
+void MP4File::GetTrackH264SeqPictHeaders (MP4TrackId trackId,
+					  uint8_t ***pppSeqHeader,
+					  uint32_t **ppSeqHeaderSize,
+					  uint8_t ***pppPictHeader,
+					  uint32_t **ppPictHeaderSize)
+{
+  uint32_t count;
+  const char *format;
+  MP4Atom *avcCAtom;
+
+  *pppSeqHeader = NULL; *pppPictHeader = NULL;
+  *ppSeqHeaderSize = NULL; *ppPictHeaderSize = NULL;
+
+  // get 4cc media format - can be avc1 or encv for ismacrypted track
+  format = GetTrackMediaDataName (trackId);
+
+  if (!strcasecmp(format, "avc1"))
+ 	 avcCAtom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.avc1.avcC"));
+  else if (!strcasecmp(format, "encv"))
+ 	 avcCAtom = FindAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd.encv.avcC"));
+  else 
+        // huh?  unknown track format 
+	return;
+
+  MP4BitfieldProperty *pSeqCount;
+  MP4IntegerProperty *pSeqLen, *pPictCount, *pPictLen;
+  MP4BytesProperty *pSeqVal, *pPictVal;
+
+  if ((avcCAtom->FindProperty("avcC.numOfSequenceParameterSets",
+			     (MP4Property **)&pSeqCount) == false) ||
+      (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetLength",
+			      (MP4Property **)&pSeqLen) == false) ||
+      (avcCAtom->FindProperty("avcC.sequenceEntries.sequenceParameterSetNALUnit",
+			      (MP4Property **)&pSeqVal) == false)) {
+    VERBOSE_ERROR(m_verbosity, WARNING("Could not find avcC properties"));
+    return ;
+  }
+  uint8_t **ppSeqHeader =
+    (uint8_t **)malloc((pSeqCount->GetValue() + 1) * sizeof(uint8_t *));
+  if (ppSeqHeader == NULL) return;
+  *pppSeqHeader = ppSeqHeader;
+
+  uint32_t *pSeqHeaderSize = 
+    (uint32_t *)malloc((pSeqCount->GetValue() + 1) * sizeof(uint32_t *));
+
+  if (pSeqHeaderSize == NULL) return;
+
+  *ppSeqHeaderSize = pSeqHeaderSize;
+  for (count = 0; count < pSeqCount->GetValue(); count++) {
+    pSeqVal->GetValue(&(ppSeqHeader[count]), &(pSeqHeaderSize[count]),
+		      count);
+  }
+  ppSeqHeader[count] = NULL;
+  pSeqHeaderSize[count] = 0;
+
+  if ((avcCAtom->FindProperty("avcC.numOfPictureParameterSets",
+			     (MP4Property **)&pPictCount) == false) ||
+      (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetLength",
+			      (MP4Property **)&pPictLen) == false) ||
+      (avcCAtom->FindProperty("avcC.pictureEntries.pictureParameterSetNALUnit",
+			      (MP4Property **)&pPictVal) == false)) {
+    VERBOSE_ERROR(m_verbosity, 
+		  WARNING("Could not find avcC picture table properties"));
+    return ;
+  }
+  uint8_t 
+  **ppPictHeader = 
+    (uint8_t **)malloc((pPictCount->GetValue() + 1) * sizeof(uint8_t *));
+  if (ppPictHeader == NULL) return;
+  uint32_t *pPictHeaderSize = 
+    (uint32_t *)malloc((pPictCount->GetValue() + 1)* sizeof(uint32_t *));
+  if (pPictHeaderSize == NULL) {
+    free(ppPictHeader);
+    return;
+  }
+  *pppPictHeader = ppPictHeader;
+  *ppPictHeaderSize = pPictHeaderSize;
+
+  for (count = 0; count < pPictCount->GetValue(); count++) {
+    pPictVal->GetValue(&(ppPictHeader[count]), &(pPictHeaderSize[count]),
+		       count);
+  }
+  ppPictHeader[count] = NULL;
+  pPictHeaderSize[count] = 0;
+  return ;
+}
+
+
+
 const char* MP4File::GetHintTrackSdp(MP4TrackId hintTrackId)
 {
 	return GetTrackStringProperty(hintTrackId, "udta.hnti.sdp .sdpText");
@@ -2386,7 +2916,7 @@
 			"MP4SetHintTrackSdp");
 	}
 
-	AddDescendantAtoms(
+	(void)AddDescendantAtoms(
 		MakeTrackName(hintTrackId, NULL), "udta.hnti.sdp ");
 
 	SetTrackStringProperty(hintTrackId, "udta.hnti.sdp .sdpText", sdpString);
@@ -2469,10 +2999,9 @@
 		MP4Atom* pTrakAtom = m_pTracks[i]->GetTrakAtom();
 
 		MP4Integer32Property* pPayloadProperty = NULL;
-		pTrakAtom->FindProperty("trak.udta.hinf.payt.payloadNumber",
-			(MP4Property**)&pPayloadProperty);
-
-		if (pPayloadProperty) {
+		if (pTrakAtom->FindProperty("trak.udta.hinf.payt.payloadNumber",
+			(MP4Property**)&pPayloadProperty) &&
+		    pPayloadProperty) {
 			usedPayloads.Add(pPayloadProperty->GetValue());
 		}
 	}
@@ -2772,11 +3301,14 @@
 {
 	char* trakName = MakeTrackName(trackId, NULL);
 
-	static char editName[1024];
-	snprintf(editName, sizeof(editName), 
+	if (m_editName == NULL) {
+	  m_editName = (char *)malloc(1024);
+	  if (m_editName == NULL) return NULL;
+	}
+	snprintf(m_editName, 1024,
 		"%s.edts.elst.entries[%u].%s", 
 		trakName, editId - 1, name);
-	return editName;
+	return m_editName;
 }
 
 MP4EditId MP4File::AddTrackEdit(
--- a/common/mp4v2/mp4file.h
+++ b/common/mp4v2/mp4file.h
@@ -13,7 +13,7 @@
  * 
  * The Initial Developer of the Original Code is Cisco Systems Inc.
  * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2001 - 2004.  All Rights Reserved.
+ * 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.
@@ -38,6 +38,7 @@
 class MP4BytesProperty;
 class MP4Descriptor;
 class MP4DescriptorProperty;
+struct Virtual_IO;
 
 class MP4File {
 public: /* equivalent to MP4 library API */
@@ -46,11 +47,16 @@
 
 	/* file operations */
 	void Read(const char* fileName);
-	void Create(const char* fileName, u_int32_t flags);
-	void CreateEx(const char* fileName, u_int32_t flags, char* majorBrand, 
-		      u_int32_t minorVersion, char** supportedBrands, 
-		      u_int32_t supportedBrandsCount);
-	void Modify(const char* fileName);
+	#ifdef _WIN32
+	void Read(const wchar_t* fileName);
+	#endif
+	void ReadEx(const char *fileName, void *user, Virtual_IO *virtual_IO); //benski>
+	void Create(const char* fileName, u_int32_t flags, 
+		    int add_ftyp = 1, int add_iods = 1,
+		    char* majorBrand = NULL, 
+		    u_int32_t minorVersion = 0, char** supportedBrands = NULL, 
+		    u_int32_t supportedBrandsCount = 0);
+	bool Modify(const char* fileName);
 	void Optimize(const char* orgFileName, 
 		const char* newFileName = NULL);
 	void Dump(FILE* pDumpFile = NULL, bool dumpImplicits = false);
@@ -66,7 +72,7 @@
 	}
 
 	bool Use64Bits(const char *atomName);
-
+	void Check64BitStatus(const char *atomName);
 	/* file properties */
 
 	u_int64_t GetIntegerProperty(const char* name);
@@ -122,7 +128,7 @@
 	u_int16_t FindTrakAtomIndex(MP4TrackId trackId);
 
 	/* track properties */
-
+	MP4Atom *FindTrackAtom(MP4TrackId trackId, const char *name);
 	u_int64_t GetTrackIntegerProperty(
 		MP4TrackId trackId, const char* name);
 	float GetTrackFloatProperty(
@@ -211,7 +217,8 @@
                 u_int8_t  key_ind_len,
                 u_int8_t  iv_len, 
                 bool      selective_enc,
-                char      *kms_uri);
+                const char  *kms_uri,
+		bool      use_ismacryp);
 
 	void SetAmrVendor(
 			MP4TrackId trackId,
@@ -224,6 +231,7 @@
 	void SetAmrModeSet(
 			MP4TrackId trackId,
 			u_int16_t modeSet);
+	uint16_t GetAmrModeSet(MP4TrackId trackId);
 
 	MP4TrackId AddAmrAudioTrack(
 			u_int32_t timeScale,
@@ -232,7 +240,11 @@
 			u_int8_t framesPerSample,
 			bool isAmrWB);
 
-	MP4TrackId AddVideoTrack(
+	MP4TrackId AddHrefTrack(uint32_t timeScale,
+				MP4Duration sampleDuration,
+				const char *base_url);
+
+	MP4TrackId AddMP4VideoTrack(
 		u_int32_t timeScale, 
 		MP4Duration sampleDuration,
 		u_int16_t width, 
@@ -245,12 +257,8 @@
 		u_int16_t width, 
 		u_int16_t height, 
 		u_int8_t  videoType,
-                u_int32_t scheme_type,
-                u_int16_t scheme_version,
-                u_int8_t  key_ind_len,
-                u_int8_t  iv_len,
-                bool      selective_enc,
-                char      *kms_uri);
+		mp4v2_ismacrypParams *icPp,
+		const char *oFormat);
 
 	void SetH263Vendor(
 			MP4TrackId trackId,
@@ -275,12 +283,42 @@
 			u_int32_t avgBitrate,
 			u_int32_t maxBitrate);
 
+	MP4TrackId AddH264VideoTrack(
+				     u_int32_t timeScale,
+				     MP4Duration sampleDuration,
+				     u_int16_t width,
+				     u_int16_t height,
+				     uint8_t AVCProfileIndication,
+				     uint8_t profile_compat,
+				     uint8_t AVCLevelIndication,
+				     uint8_t sampleLenFieldSizeMinusOne);
+
+	MP4TrackId AddEncH264VideoTrack(
+				     u_int32_t timeScale,
+				     MP4Duration sampleDuration,
+				     u_int16_t width,
+				     u_int16_t height,
+					MP4Atom *srcAtom,
+					mp4v2_ismacrypParams *icPp);
+
+	void AddH264SequenceParameterSet(MP4TrackId trackId,
+					 const uint8_t *pSequence,
+					 uint16_t sequenceLen);
+	void AddH264PictureParameterSet(MP4TrackId trackId,
+					const uint8_t *pPicture,
+					uint16_t pictureLen);
 	MP4TrackId AddHintTrack(MP4TrackId refTrackId);
 
+	MP4TrackId AddTextTrack(MP4TrackId refTrackId);
+	MP4TrackId AddChapterTextTrack(MP4TrackId refTrackId);
+
 	MP4SampleId GetTrackNumberOfSamples(MP4TrackId trackId);
 
 	const char* GetTrackType(MP4TrackId trackId);
 
+	const char *GetTrackMediaDataName(MP4TrackId trackId);
+	bool GetTrackMediaDataOriginalFormat(MP4TrackId trackId,
+		char *originalFormat, u_int32_t buflen);
 	MP4Duration GetTrackDuration(MP4TrackId trackId);
 
 	u_int32_t GetTrackTimeScale(MP4TrackId trackId);
@@ -289,19 +327,25 @@
 	// replacement to GetTrackAudioType and GetTrackVideoType	
 	u_int8_t GetTrackEsdsObjectTypeId(MP4TrackId trackId);
 
-	u_int8_t GetTrackAudioType(MP4TrackId trackId);
 	u_int8_t GetTrackAudioMpeg4Type(MP4TrackId trackId);
-	u_int8_t GetTrackVideoType(MP4TrackId trackId);
 
 	MP4Duration GetTrackFixedSampleDuration(MP4TrackId trackId);
 
-	float GetTrackVideoFrameRate(MP4TrackId trackId);
-
+	double GetTrackVideoFrameRate(MP4TrackId trackId);
+	
+	int GetTrackAudioChannels(MP4TrackId trackId);
 	void GetTrackESConfiguration(MP4TrackId trackId, 
 		u_int8_t** ppConfig, u_int32_t* pConfigSize);
 	void SetTrackESConfiguration(MP4TrackId trackId, 
 		const u_int8_t* pConfig, u_int32_t configSize);
 
+	void GetTrackVideoMetadata(MP4TrackId trackId, 
+		u_int8_t** ppConfig, u_int32_t* pConfigSize);
+	void GetTrackH264SeqPictHeaders(MP4TrackId trackId, 
+					uint8_t ***pSeqHeader,
+					uint32_t **pSeqHeaderSize,
+					uint8_t ***pPictHeader,
+					uint32_t **pPictHeaderSize);
 	const char* GetHintTrackSdp(MP4TrackId hintTrackId);
 	void SetHintTrackSdp(MP4TrackId hintTrackId, const char* sdpString);
 	void AppendHintTrackSdp(MP4TrackId hintTrackId, const char* sdpString);
@@ -507,48 +551,50 @@
 		MP4Duration* pDuration = NULL);
 
 	/* iTunes metadata handling */
+ protected:
 	bool CreateMetadataAtom(const char* name);
+ public:
+	// these are public to remove a lot of unnecessary routines
+	bool DeleteMetadataAtom(const char* name, bool try_udta = false);
+	bool GetMetadataString(const char *atom, char **value, bool try_udta = false);
+	bool SetMetadataString(const char *atom, const char *value);
 	bool MetadataDelete(void);
+
+	bool SetMetadataUint8(const char *atom, u_int8_t compilation);
+	bool GetMetadataUint8(const char *atom, u_int8_t* compilation);
 	
 	/* set metadata */
-	bool SetMetadataName(const char* value);
-	bool SetMetadataWriter(const char* value);
-	bool SetMetadataAlbum(const char* value);
-	bool SetMetadataArtist(const char* value);
-	bool SetMetadataTool(const char* value);
-	bool SetMetadataComment(const char* value);
-	bool SetMetadataYear(const char* value);
 	bool SetMetadataTrack(u_int16_t track, u_int16_t totalTracks);
 	bool SetMetadataDisk(u_int16_t disk, u_int16_t totalDisks);
 	bool SetMetadataGenre(const char *value);
 	bool SetMetadataTempo(u_int16_t tempo);
-	bool SetMetadataCompilation(u_int8_t compilation);
 	bool SetMetadataCoverArt(u_int8_t *coverArt, u_int32_t size);
-	bool SetMetadataFreeForm(char *name, 
-				 u_int8_t* pValue, 
-				 u_int32_t valueSize);
+	bool SetMetadataFreeForm(const char *name, 
+				 const u_int8_t* pValue, 
+				 u_int32_t valueSize,
+				 const char *owner = NULL);
  
 	/* get metadata */
 	bool GetMetadataByIndex(u_int32_t index,
-				const char** ppName,
-				u_int8_t** ppValue, 
+				char** ppName, // free memory when done
+				u_int8_t** ppValue,  // free memory when done
 				u_int32_t* pValueSize);
-	bool GetMetadataName(char** value);
-	bool GetMetadataWriter(char** value);
-	bool GetMetadataAlbum(char** value);
-	bool GetMetadataArtist(char** value);
-	bool GetMetadataTool(char** value);
-	bool GetMetadataComment(char** value);
-	bool GetMetadataYear(char** value);
 	bool GetMetadataTrack(u_int16_t* track, u_int16_t* totalTracks);
 	bool GetMetadataDisk(u_int16_t* disk, u_int16_t* totalDisks);
 	bool GetMetadataGenre(char **value);
 	bool GetMetadataTempo(u_int16_t* tempo);
-	bool GetMetadataCompilation(u_int8_t* compilation);
-	bool GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t* size);
-	bool GetMetadataFreeForm(char *name, 
+	bool GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t* size,
+				 uint32_t index = 0);
+	u_int32_t GetMetadataCoverArtCount(void);
+	bool GetMetadataFreeForm(const char *name, 
 				 u_int8_t** pValue, 
-				 u_int32_t* valueSize);
+				 u_int32_t* valueSize,
+				 const char *owner = NULL);
+
+	/* delete metadata */
+	bool DeleteMetadataGenre();
+	bool DeleteMetadataFreeForm(const char *name, const char *owner = NULL);
+
 	/* end of MP4 API */
 
 	/* "protected" interface to be used only by friends in library */
@@ -558,7 +604,7 @@
 
 	u_int64_t GetSize();
 
-	u_int32_t ReadBytes(
+	void ReadBytes(
 		u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile = NULL);
 	u_int64_t ReadUInt(u_int8_t size);
 	u_int8_t ReadUInt8();
@@ -576,11 +622,10 @@
 	void FlushReadBits();
 	u_int32_t ReadMpegLength();
 
-	u_int32_t PeekBytes(
+	void PeekBytes(
 		u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile = NULL);
 
 	void WriteBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile = NULL);
-	void WriteUInt(u_int64_t value, u_int8_t size);
 	void WriteUInt8(u_int8_t value);
 	void WriteUInt16(u_int16_t value);
 	void WriteUInt24(u_int32_t value);
@@ -608,7 +653,7 @@
 
 	MP4Track* GetTrack(MP4TrackId trackId);
 
-	MP4Duration UpdateDuration(MP4Duration duration);
+	void UpdateDuration(MP4Duration duration);
 
 	MP4Atom* FindAtom(const char* name);
 
@@ -640,13 +685,16 @@
 
 protected:
 	void Open(const char* fmode);
+	#ifdef _WIN32
+	void Open(const wchar_t* fmode);
+	#endif
 	void ReadFromFile();
 	void GenerateTracks();
 	void BeginWrite();
 	void FinishWrite();
 	void CacheProperties();
-	void RewriteMdat(FILE* pReadFile, FILE* pWriteFile);
-	MP4Atom* GetTrakDamrAtom(MP4TrackId trackId);
+	void RewriteMdat(void* pReadFile, void* pWriteFile,
+			 Virtual_IO *readIO, Virtual_IO *writeIO);
 	bool ShallHaveIods();
 
 	const char* TempFileName();
@@ -666,6 +714,16 @@
 	bool FindProperty(const char* name,
 		MP4Property** ppProperty, u_int32_t* pIndex = NULL);
 
+	MP4TrackId AddVideoTrackDefault(
+		u_int32_t timeScale, 
+		MP4Duration sampleDuration,
+		u_int16_t width, 
+		u_int16_t height, 
+		const char *videoType);
+	MP4TrackId AddCntlTrackDefault(
+		u_int32_t timeScale, 
+		MP4Duration sampleDuration,
+		const char *videoType);
 	void AddTrackToIod(MP4TrackId trackId);
 
 	void RemoveTrackFromIod(MP4TrackId trackId, bool shallHaveIods = true);
@@ -697,7 +755,7 @@
 		u_int8_t** ppBytes,
 		u_int64_t* pNumBytes);
 
-	MP4Descriptor* CreateESD(
+	void CreateESD(
 		MP4DescriptorProperty* pEsProperty,
 		u_int32_t esid,
 		u_int8_t objectType,
@@ -704,7 +762,7 @@
 		u_int8_t streamType,
 		u_int32_t bufferSize,
 		u_int32_t bitrate,
-		u_int8_t* pConfig,
+		const u_int8_t* pConfig,
 		u_int32_t configLength,
 		char* url);
 
@@ -735,7 +793,11 @@
 
 protected:
 	char*			m_fileName;
-	FILE*			m_pFile;
+	#ifdef _WIN32
+	wchar_t*    	m_fileName_w;
+	#endif
+	void*			m_pFile;
+	Virtual_IO             *m_virtual_IO;
 	u_int64_t		m_orgFileSize;
 	u_int64_t		m_fileSize;
 	MP4Atom*		m_pRootAtom;
@@ -762,6 +824,14 @@
 	u_int8_t	m_bufReadBits;
 	u_int8_t	m_numWriteBits;
 	u_int8_t	m_bufWriteBits;
+
+#ifndef _WIN32
+	char m_tempFileName[64];
+#else
+	char m_tempFileName[MAX_PATH + 3];
+#endif
+	char m_trakName[1024];
+	char *m_editName;
 };
 
 #endif /* __MP4_FILE_INCLUDED__ */
--- a/common/mp4v2/mp4file_io.cpp
+++ b/common/mp4v2/mp4file_io.cpp
@@ -28,16 +28,20 @@
 	if (m_memoryBuffer == NULL) {
 		if (pFile == NULL) {
 			ASSERT(m_pFile);
-			pFile = m_pFile;
+			u_int64_t fpos;
+			if (m_virtual_IO->GetPosition(m_pFile, &fpos) != 0) {
+				throw new MP4Error("getting position via Virtual I/O", "MP4GetPosition");
+			}
+			return fpos;
+		} else {
+			fpos_t fpos;
+			if (fgetpos(pFile, &fpos) < 0) { 
+				throw new MP4Error(errno, "MP4GetPosition");
+			}
+			uint64_t ret;
+			FPOS_TO_VAR(fpos, uint64_t, ret);
+			return ret;
 		}
-
-		fpos_t fpos;
-		if (fgetpos(pFile, &fpos) < 0) {
-			throw new MP4Error(errno, "MP4GetPosition");
-		}
-		uint64_t ret;
-		FPOS_TO_VAR(fpos, uint64_t, ret);
-		return ret;
 	} else {
 		return m_memoryBufferPosition;
 	}
@@ -48,14 +52,16 @@
 	if (m_memoryBuffer == NULL) {
 		if (pFile == NULL) {
 			ASSERT(m_pFile);
-			pFile = m_pFile;
+			if (m_virtual_IO->SetPosition(m_pFile, pos) != 0) {
+				throw new MP4Error("setting position via Virtual I/O", "MP4SetPosition");
+			}
+		}	else {
+			fpos_t fpos;
+			VAR_TO_FPOS(fpos, pos);
+			if (fsetpos(pFile, &fpos) < 0) { 
+				throw new MP4Error(errno, "MP4SetPosition");
+			}
 		}
-
-		fpos_t fpos;
-		VAR_TO_FPOS(fpos, pos);
-		if (fsetpos(pFile, &fpos) < 0) {
-			throw new MP4Error(errno, "MP4SetPosition");
-		}
 	} else {
 		if (pos >= m_memoryBufferSize) {
 		  //		  abort();
@@ -78,30 +84,32 @@
 	return m_fileSize;
 }
 
-u_int32_t MP4File::ReadBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile)
+void MP4File::ReadBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile)
 {
 	// handle degenerate cases
 	if (numBytes == 0) {
-		return 0;
+		return;
 	}
 
 	ASSERT(pBytes);
 	WARNING(m_numReadBits > 0);
 
-	if (pFile == NULL) {
-		pFile = m_pFile;
-	}
-	ASSERT(pFile);
-
 	if (m_memoryBuffer == NULL) {
-		if (fread(pBytes, 1, numBytes, pFile) != numBytes) {
-			if (feof(pFile)) {
-				throw new MP4Error(
-					"not enough bytes, reached end-of-file",
-					"MP4ReadBytes");
-			} else {
-				throw new MP4Error(errno, "MP4ReadBytes");
+		if (pFile == NULL) {
+			ASSERT(m_pFile);
+			if (m_virtual_IO->Read(m_pFile, pBytes, numBytes) != numBytes) {
+				throw new MP4Error("not enough bytes, reached end-of-file",		"MP4ReadBytes");
 			}
+		}	else {
+			if (fread(pBytes, 1, numBytes, pFile) != numBytes) { 
+				if (feof(pFile)) { 
+					throw new MP4Error(
+						"not enough bytes, reached end-of-file",
+						"MP4ReadBytes");
+				} else {
+					throw new MP4Error(errno, "MP4ReadBytes");
+				}
+			}
 		}
 	} else {
 		if (m_memoryBufferPosition + numBytes > m_memoryBufferSize) {
@@ -112,15 +120,14 @@
 		memcpy(pBytes, &m_memoryBuffer[m_memoryBufferPosition], numBytes);
 		m_memoryBufferPosition += numBytes;
 	}
-	return numBytes;
+	return;
 }
 
-u_int32_t MP4File::PeekBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile)
+void MP4File::PeekBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile)
 {
 	u_int64_t pos = GetPosition(pFile);
 	ReadBytes(pBytes, numBytes, pFile);
 	SetPosition(pos, pFile);
-	return numBytes;
 }
 
 void MP4File::EnableMemoryBuffer(u_int8_t* pBytes, u_int64_t numBytes) 
@@ -168,13 +175,15 @@
 	if (m_memoryBuffer == NULL) {
 		if (pFile == NULL) {
 			ASSERT(m_pFile);
-			pFile = m_pFile;
+			if (m_virtual_IO->Write(m_pFile, pBytes, numBytes) != numBytes) {
+				throw new MP4Error("error writing bytes via virtual I/O", "MP4WriteBytes");
+			}
+		} else {
+			u_int32_t rc = fwrite(pBytes, 1, numBytes, pFile); 
+			if (rc != numBytes) {
+				throw new MP4Error(errno, "MP4WriteBytes");
+			}
 		}
-
-		u_int32_t rc = fwrite(pBytes, 1, numBytes, pFile);
-		if (rc != numBytes) {
-			throw new MP4Error(errno, "MP4WriteBytes");
-		}
 	} else {
 		if (m_memoryBufferPosition + numBytes > m_memoryBufferSize) {
 			m_memoryBufferSize = 2 * (m_memoryBufferSize + numBytes);
@@ -205,6 +214,7 @@
 	}
 }
 
+#if 0
 void MP4File::WriteUInt(u_int64_t value, u_int8_t size)
 {
 	switch (size) {
@@ -222,6 +232,7 @@
 		ASSERT(false);
 	}
 }
+#endif
 
 u_int8_t MP4File::ReadUInt8()
 {
@@ -382,6 +393,8 @@
 	do {
 		if (length == alloced) {
 			data = (char*)MP4Realloc(data, alloced * 2);
+			if (data == NULL) return NULL;
+			alloced *= 2;
 		}
 		ReadBytes((u_int8_t*)&data[length], 1);
 		length++;
@@ -394,7 +407,7 @@
 void MP4File::WriteString(char* string)
 {
 	if (string == NULL) {
-		static u_int8_t zero = 0;
+		u_int8_t zero = 0;
 		WriteBytes(&zero, 1);
 	} else {
 		WriteBytes((u_int8_t*)string, strlen(string) + 1);
@@ -406,10 +419,15 @@
 	u_int32_t charLength;
 	if (allowExpandedCount) {
 		u_int8_t b;
+		uint ix = 0;
 		charLength = 0;
 		do {
 			b = ReadUInt8();
 			charLength += b;
+			ix++;
+			if (ix > 25) 
+			  throw new MP4Error(ERANGE, 
+					     "Counted string too long 25 * 255");
 		} while (b == 255);
 	} else {
 		charLength = ReadUInt8();
--- a/common/mp4v2/mp4info.cpp
+++ b/common/mp4v2/mp4info.cpp
@@ -36,7 +36,7 @@
 		"MPEG-4 AAC LC",
 		"MPEG-4 AAC SSR",
 		"MPEG-4 AAC LTP",
-		NULL,
+		"MPEG-4 AAC HE",
 		"MPEG-4 AAC Scalable",
 		"MPEG-4 TwinVQ",
 		"MPEG-4 CELP",
@@ -58,9 +58,20 @@
 		"MPEG-4 ER HVXC",
 		"MPEG-4 ER HILN",
 		"MPEG-4 ER Parametric",
+		"MPEG-4 SSC",
+		"MPEG-4 PS",
+		"MPEG-4 MPEG Surround",
+		NULL,
+		"MPEG-4 Layer-1",
+		"MPEG-4 Layer-2",
+		"MPEG-4 Layer-3",
+		"MPEG-4 DST",
+		"MPEG-4 Audio Lossless",
+		"MPEG-4 SLS",
+		"MPEG-4 SLS non-core", 
 	};
 
-	static u_int8_t mpegAudioTypes[] = {
+	static const u_int8_t mpegAudioTypes[] = {
 		MP4_MPEG2_AAC_MAIN_AUDIO_TYPE,	// 0x66
 		MP4_MPEG2_AAC_LC_AUDIO_TYPE,	// 0x67
 		MP4_MPEG2_AAC_SSR_AUDIO_TYPE,	// 0x68
@@ -88,61 +99,58 @@
 		"G.723.1",
 		"PCM16 (big endian)",
 	};
-	static u_int8_t numMpegAudioTypes =
+	u_int8_t numMpegAudioTypes =
 		sizeof(mpegAudioTypes) / sizeof(u_int8_t);
 
 	const char* typeName = "Unknown";
 	bool foundType = false;
-	u_int8_t type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
+	u_int8_t type = 0;
+	const char *media_data_name;
 
-	switch (type) {
-	case MP4_MPEG4_AUDIO_TYPE:  {
-	  u_int8_t* pAacConfig = NULL;
-	  u_int32_t aacConfigLength;
+	media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
 
-	  MP4GetTrackESConfiguration(mp4File,
-				     trackId,
-				     &pAacConfig,
-				     &aacConfigLength);
-
-	  if (pAacConfig != NULL && aacConfigLength >= 2) {
-	    type = (pAacConfig[0] >> 3) & 0x1f;
-	    if (type == 0 || type == 5 || type == 10 || type == 11 ||
-		type == 18 || type >= 28) {
-	      typeName = "MPEG-4 Unknown Profile";
-	    } else {
-	        typeName = mpeg4AudioNames[type - 1];
-		foundType = true;
-	    }
-	    free(pAacConfig);
-	  } else {
-	    typeName = "MPEG-4 (no GAConfig)";
-	    foundType = true;
-	  }
-	  break;
-	}
-	case MP4_INVALID_AUDIO_TYPE:
-	  // type not found
-	  // try with 3gpp codecs
-	  if (MP4HaveTrackIntegerProperty(mp4File, trackId, 
-					  "mdia.minf.stbl.stsd.samr.damr.vendor")) {
+	if (media_data_name == NULL) {
+	  typeName = "Unknown - no media data name";
+	} else if (strcasecmp(media_data_name, "samr") == 0) {
 	    typeName = "AMR";
 	    foundType = true;
-	  } else if (MP4HaveTrackIntegerProperty(mp4File, trackId, 
-						 "mdia.minf.stbl.stsd.sawb.damr.vendor")) {
+	} else if (strcasecmp(media_data_name, "sawb") == 0) {
 	    typeName = "AMR-WB";
 	    foundType = true;
-	  }
-	  break;
-	  // fall through
-	default:
-	  for (u_int8_t i = 0; i < numMpegAudioTypes; i++) {
-	    if (type == mpegAudioTypes[i]) {
-	      typeName = mpegAudioNames[i];
+	} else if (strcasecmp(media_data_name, "mp4a") == 0) {
+	    
+	  type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
+	  switch (type) {
+	  case MP4_INVALID_AUDIO_TYPE:
+	    typeName = "AAC from .mov";
+	    foundType = true;
+	    break;
+	  case MP4_MPEG4_AUDIO_TYPE:  {
+	
+	    type = MP4GetTrackAudioMpeg4Type(mp4File, trackId);
+	    if (type == MP4_MPEG4_INVALID_AUDIO_TYPE ||
+		type > NUM_ELEMENTS_IN_ARRAY(mpeg4AudioNames) || 
+		mpeg4AudioNames[type - 1] == NULL) {
+	      typeName = "MPEG-4 Unknown Profile";
+	    } else {
+	      typeName = mpeg4AudioNames[type - 1];
 	      foundType = true;
-	      break;
 	    }
+	    break;
 	  }
+	    // fall through
+	  default:
+	    for (u_int8_t i = 0; i < numMpegAudioTypes; i++) {
+	      if (type == mpegAudioTypes[i]) {
+		typeName = mpegAudioNames[i];
+		foundType = true;
+		break;
+	      }
+	    }
+	  }
+	} else {
+	  typeName = media_data_name;
+	  foundType = true;
 	}
 
 	u_int32_t timeScale =
@@ -162,7 +170,7 @@
 
 	// type duration avgBitrate samplingFrequency
 	if (foundType)
-	  sprintf(sInfo,
+	  snprintf(sInfo, 256, 
 		  "%u\taudio\t%s%s, %.3f secs, %u kbps, %u Hz\n",
 		  trackId,
 		  MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "",
@@ -171,7 +179,7 @@
 		  (avgBitRate + 500) / 1000,
 		  timeScale);
 	else
-	  sprintf(sInfo,
+	  snprintf(sInfo, 256,
 		  "%u\taudio\t%s%s(%u), %.3f secs, %u kbps, %u Hz\n",
 		  trackId,
 		  MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "",
@@ -183,7 +191,7 @@
 
 	return sInfo;
 }
-static struct {
+static const struct {
   uint8_t profile;
   const char *name;
 } VisualProfileToName[] = {
@@ -263,7 +271,7 @@
 	MP4TrackId trackId)
 {
 
-	static u_int8_t mpegVideoTypes[] = {
+	static const u_int8_t mpegVideoTypes[] = {
 		MP4_MPEG2_SIMPLE_VIDEO_TYPE,	// 0x60
 		MP4_MPEG2_MAIN_VIDEO_TYPE,		// 0x61
 		MP4_MPEG2_SNR_VIDEO_TYPE,		// 0x62
@@ -273,7 +281,6 @@
 		MP4_MPEG1_VIDEO_TYPE,			// 0x6A
 		MP4_JPEG_VIDEO_TYPE,			// 0x6C
 		MP4_YUV12_VIDEO_TYPE,
-		MP4_H264_VIDEO_TYPE,
 		MP4_H263_VIDEO_TYPE,
 		MP4_H261_VIDEO_TYPE,
 	};
@@ -287,41 +294,112 @@
 		"MPEG-1",
 		"JPEG",
 		"YUV12",
-		"H.264",
 		"H.263",
 		"H.261",
 	};
-	static u_int8_t numMpegVideoTypes =
+	u_int8_t numMpegVideoTypes =
 		sizeof(mpegVideoTypes) / sizeof(u_int8_t);
 	bool foundTypeName = false;
 	const char* typeName = "Unknown";
 
-	u_int8_t type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
-
-        if ( type == MP4_INVALID_VIDEO_TYPE ) {
-          // type not found
-          // try with 3gpp codecs
-          if (MP4HaveTrackIntegerProperty(mp4File, trackId, "mdia.minf.stbl.stsd.s263.d263.vendor")) {
-            type = MP4_H263_VIDEO_TYPE;
-          }
-        }
-
-	if (type == MP4_MPEG4_VIDEO_TYPE) {
-		type = MP4GetVideoProfileLevel(mp4File);
-		typeName = Mpeg4VisualProfileName(type);
-		if (typeName == NULL) {
-		  typeName = "MPEG-4 Unknown Profile";
-		} else {
-		  foundTypeName = true;
-		}
-	} else {
-	  for (u_int8_t i = 0; i < numMpegVideoTypes; i++) {
-	    if (type == mpegVideoTypes[i]) {
-	      typeName = mpegVideoNames[i];
-	      foundTypeName = true;
+	const char *media_data_name;
+	char originalFormat[8];
+	char  oformatbuffer[32];
+	originalFormat[0] = 0;
+	*oformatbuffer = 0;
+	uint8_t type = 0;
+	
+	media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
+	// encv 264b
+	if (strcasecmp(media_data_name, "encv") == 0) {
+	  if (MP4GetTrackMediaDataOriginalFormat(mp4File, 
+						 trackId, 
+						 originalFormat, 
+						 sizeof(originalFormat)) == false)
+	      media_data_name = NULL;
+	      
+	}
+  
+	char  typebuffer[80];
+	if (media_data_name == NULL) {
+	  typeName = "Unknown - no media data name";
+	  foundTypeName = true;
+	} else if ((strcasecmp(media_data_name, "avc1") == 0) ||
+	  	(strcasecmp(originalFormat, "264b") == 0)) {
+	  // avc
+	  uint8_t profile, level;
+	  char profileb[20], levelb[20];
+	  if (MP4GetTrackH264ProfileLevel(mp4File, trackId, 
+					  &profile, &level)) {
+	    if (profile == 66) {
+	      strcpy(profileb, "Baseline");
+	    } else if (profile == 77) {
+	      strcpy(profileb, "Main");
+	    } else if (profile == 88) {
+	      strcpy(profileb, "Extended");
+	    } else if (profile == 100) {
+	      strcpy(profileb, "High");
+	    } else if (profile == 110) {
+	      strcpy(profileb, "High 10");
+	    } else if (profile == 122) {
+	      strcpy(profileb, "High 4:2:2");
+	    } else if (profile == 144) {
+	      strcpy(profileb, "High 4:4:4");
+	    } else {
+	      snprintf(profileb, 20, "Unknown Profile %x", profile);
+	    } 
+	    switch (level) {
+	    case 10: case 20: case 30: case 40: case 50:
+	      snprintf(levelb, 20, "%u", level / 10);
 	      break;
+	    case 11: case 12: case 13:
+	    case 21: case 22:
+	    case 31: case 32:
+	    case 41: case 42:
+	    case 51:
+	      snprintf(levelb, 20, "%u.%u", level / 10, level % 10);
+	      break;
+	    default:
+	      snprintf(levelb, 20, "unknown level %x", level);
+	      break;
 	    }
+	    if (originalFormat != NULL && originalFormat[0] != '\0') 
+	      snprintf(oformatbuffer, 32, "(%s) ", originalFormat);
+	    snprintf(typebuffer, sizeof(typebuffer), "H264 %s%s@%s", 
+		    oformatbuffer, profileb, levelb);
+	    typeName = typebuffer;
+	  } else {
+	    typeName = "H.264 - profile/level error";
 	  }
+	  foundTypeName = true;
+	} else if (strcasecmp(media_data_name, "s263") == 0) {
+	  // 3gp h.263
+	  typeName = "H.263";
+	  foundTypeName = true;
+	} else if ((strcasecmp(media_data_name, "mp4v") == 0) ||
+		   (strcasecmp(media_data_name, "encv") == 0)) {
+	  // note encv might needs it's own field eventually.
+	  type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
+	  if (type == MP4_MPEG4_VIDEO_TYPE) {
+	    type = MP4GetVideoProfileLevel(mp4File, trackId);
+	    typeName = Mpeg4VisualProfileName(type);
+	    if (typeName == NULL) {
+	      typeName = "MPEG-4 Unknown Profile";
+	    } else {
+	      foundTypeName = true;
+	    }
+	  } else {
+	    for (u_int8_t i = 0; i < numMpegVideoTypes; i++) {
+	      if (type == mpegVideoTypes[i]) {
+		typeName = mpegVideoNames[i];
+		foundTypeName = true;
+		break;
+	      }
+	    }
+	  }
+	} else {
+	  typeName = media_data_name;
+	  foundTypeName = true; // we don't have a type value to display
 	}
 
 	MP4Duration trackDuration =
@@ -340,7 +418,7 @@
 
 	u_int16_t height = MP4GetTrackVideoHeight(mp4File, trackId);
 
-	float fps = MP4GetTrackVideoFrameRate(mp4File, trackId);
+	double fps = MP4GetTrackVideoFrameRate(mp4File, trackId);
 
 	char *sInfo = (char*)MP4Malloc(256);
 
@@ -347,7 +425,7 @@
 	// type duration avgBitrate frameSize frameRate
 	if (foundTypeName) {
 	  sprintf(sInfo,
-		  "%u\tvideo\t%s%s, %.3f secs, %u kbps, %ux%u @ %.2f fps\n",
+		  "%u\tvideo\t%s%s, %.3f secs, %u kbps, %ux%u @ %f fps\n",
 		  trackId,
 		  MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "encv - " : "",
 		  typeName,
@@ -359,7 +437,7 @@
 		  );
 	} else {
 	  sprintf(sInfo,
-		  "%u\tvideo\t%s(%u), %.3f secs, %u kbps, %ux%u @ %.2f fps\n",
+		  "%u\tvideo\t%s(%u), %.3f secs, %u kbps, %ux%u @ %f fps\n",
 		  trackId,
 		  typeName,
 		  type, 
@@ -373,7 +451,38 @@
 
 	return sInfo;
 }
+static char* PrintCntlInfo(
+	MP4FileHandle mp4File,
+	MP4TrackId trackId)
+{
+  const char *media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
+  const char *typeName = "Unknown";
 
+  if (media_data_name == NULL) {
+    typeName = "Unknown - no media data name";
+  } else if (strcasecmp(media_data_name, "href") == 0) {
+    typeName = "ISMA Href";
+  } else {
+    typeName = media_data_name;
+  }
+
+  MP4Duration trackDuration = 
+    MP4GetTrackDuration(mp4File, trackId);
+ 
+  double msDuration = 
+    UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId, 
+						 trackDuration, MP4_MSECS_TIME_SCALE));
+  char *sInfo = (char *)MP4Malloc(256);
+
+  snprintf(sInfo, 256,
+	   "%u\tcontrol\t%s, %.3f secs\n",
+	   trackId, 
+	   typeName,
+	   msDuration / 1000.0);
+  return sInfo;
+}
+
+	  
 static char* PrintHintInfo(
 	MP4FileHandle mp4File,
 	MP4TrackId trackId)
@@ -382,11 +491,12 @@
 		MP4GetHintTrackReferenceTrackId(mp4File, trackId);
 
 	char* payloadName = NULL;
-	MP4GetHintTrackRtpPayload(mp4File, trackId, &payloadName);
+	if (!MP4GetHintTrackRtpPayload(mp4File, trackId, &payloadName))
+	  return NULL;
 
 	char *sInfo = (char*)MP4Malloc(256);
 
-	sprintf(sInfo,
+	snprintf(sInfo, 256, 
 		"%u\thint\tPayload %s for track %u\n",
 		trackId,
 		payloadName,
@@ -405,6 +515,7 @@
 
 	const char* trackType =
 		MP4GetTrackType(mp4File, trackId);
+	if (trackType == NULL) return NULL;
 
 	if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) {
 		trackInfo = PrintAudioInfo(mp4File, trackId);
@@ -412,18 +523,20 @@
 		trackInfo = PrintVideoInfo(mp4File, trackId);
 	} else if (!strcmp(trackType, MP4_HINT_TRACK_TYPE)) {
 		trackInfo = PrintHintInfo(mp4File, trackId);
+	} else if (strcmp(trackType, MP4_CNTL_TRACK_TYPE) == 0) {
+	  trackInfo = PrintCntlInfo(mp4File, trackId);
 	} else {
 		trackInfo = (char*)MP4Malloc(256);
 		if (!strcmp(trackType, MP4_OD_TRACK_TYPE)) {
-			sprintf(trackInfo,
+		  snprintf(trackInfo, 256,
 				"%u\tod\tObject Descriptors\n",
 				trackId);
 		} else if (!strcmp(trackType, MP4_SCENE_TRACK_TYPE)) {
-			sprintf(trackInfo,
+		  snprintf(trackInfo, 256,
 				"%u\tscene\tBIFS\n",
 				trackId);
 		} else {
-			sprintf(trackInfo,
+		  snprintf(trackInfo, 256,
 					"%u\t%s\n",
 					trackId, trackType);
 		}
@@ -441,9 +554,11 @@
 	if (MP4_IS_VALID_FILE_HANDLE(mp4File)) {
 		try {
 			if (trackId == MP4_INVALID_TRACK_ID) {
-				info = (char*)MP4Calloc(4*1024);
+			  uint buflen = 4 * 1024;
+				info = (char*)MP4Calloc(buflen);
 
-				sprintf(info, "Track\tType\tInfo\n");
+				buflen -= snprintf(info, buflen,
+						"Track\tType\tInfo\n");
 
 				u_int32_t numTracks = MP4GetNumberOfTracks(mp4File);
 
@@ -450,7 +565,10 @@
 				for (u_int32_t i = 0; i < numTracks; i++) {
 					trackId = MP4FindTrackId(mp4File, i);
 					char* trackInfo = PrintTrackInfo(mp4File, trackId);
-					strcat(info, trackInfo);
+					strncat(info, trackInfo, buflen);
+					uint newlen = strlen(trackInfo);
+					if (newlen > buflen) buflen = 0;
+					else buflen -= newlen;
 					MP4Free(trackInfo);
 				}
 			} else {
--- a/common/mp4v2/mp4meta.cpp
+++ b/common/mp4v2/mp4meta.cpp
@@ -23,965 +23,958 @@
 
 /**
 
- The iTunes tagging seems to support any tag field name
- but there are some predefined fields, also known from the QuickTime format
+   The iTunes tagging seems to support any tag field name
+   but there are some predefined fields, also known from the QuickTime format
 
- predefined fields (the ones I know of until now):
- - �nam : Name of the song/movie (string)
- - �ART : Name of the artist/performer (string)
- - �wrt : Name of the writer (string)
- - �alb : Name of the album (string)
- - �day : Year (4 bytes, e.g. "2003") (string)
- - �too : Tool(s) used to create the file (string)
- - �cmt : Comment (string)
- - �gen : Custom genre (string)
- - trkn : Tracknumber (8 byte string)
-           16 bit: empty
-           16 bit: tracknumber
-           16 bit: total tracks on album
-           16 bit: empty
- - disk : Disknumber (8 byte string)
-           16 bit: empty
-           16 bit: disknumber
-           16 bit: total number of disks
-           16 bit: empty
- - gnre : Genre (16 bit genre) (ID3v1 index + 1)
- - cpil : Part of a compilation (1 byte, 1 or 0)
- - tmpo : Tempo in BPM (16 bit)
- - covr : Cover art (xx bytes binary data)
- - ---- : Free form metadata, can have any name and any data
+   predefined fields (the ones I know of until now):
+   - �nam : Name of the song/movie (string)
+   - �ART : Name of the artist/performer (string)
+   - aART : Album artist
+   - �wrt : Name of the writer (string)
+   - �alb : Name of the album (string)
+   - �day : Year (4 bytes, e.g. "2003") (string)
+   - �too : Tool(s) used to create the file (string)
+   - �cmt : Comment (string)
+   - �gen : Custom genre (string)
+   - �grp : Grouping (string)
+   - trkn : Tracknumber (8 byte string)
+   16 bit: empty
+   16 bit: tracknumber
+   16 bit: total tracks on album
+   16 bit: empty
+   - disk : Disknumber (8 byte string)
+   16 bit: empty
+   16 bit: disknumber
+   16 bit: total number of disks
+   16 bit: empty
+   - gnre : Genre (16 bit genre) (ID3v1 index + 1)
+   - cpil : Part of a compilation (1 byte, 1 or 0)
+   - tmpo : Tempo in BPM (16 bit)
+   - covr : Cover art (xx bytes binary data)
+   - ---- : Free form metadata, can have any name and any data
+   - pgap : gapless - 8 bit boolean
 
+   - apID : purchaser name.
+   - cprt : copyright
+   - purd : purchase date.
+
 **/
 
 #include "mp4common.h"
 
 bool MP4File::GetMetadataByIndex(u_int32_t index,
-                                 const char** ppName,
+                                 char** ppName,
                                  u_int8_t** ppValue, u_int32_t* pValueSize)
 {
-    char s[256];
+  char s[256];
 
-    sprintf(s, "moov.udta.meta.ilst.*[%u].data.metadata", index);
-    GetBytesProperty(s, ppValue, pValueSize);
+  snprintf(s, 256, "moov.udta.meta.ilst.*[%u].data.metadata", index);
+  GetBytesProperty(s, ppValue, pValueSize);
 
-    sprintf(s, "moov.udta.meta.ilst.*[%u]", index);
-    MP4Atom* pParent = m_pRootAtom->FindAtom(s);
-    *ppName = pParent->GetType();
+  snprintf(s, 256, "moov.udta.meta.ilst.*[%u]", index);
+  MP4Atom* pParent = m_pRootAtom->FindAtom(s);
+  if (pParent == NULL) return false;
 
-    /* check for free form tagfield */
-    if (memcmp(*ppName, "----", 4) == 0)
+  /* check for free form tagfield */
+  if (memcmp(*ppName, "----", 4) == 0)
     {
-        u_int8_t* pV;
-        u_int32_t VSize = 0;
-        char *pN;
+      u_int8_t* pV;
+      u_int32_t VSize = 0;
+      char *pN;
 
-        sprintf(s, "moov.udta.meta.ilst.*[%u].name.metadata", index);
-        GetBytesProperty(s, &pV, &VSize);
+      snprintf(s, 256, "moov.udta.meta.ilst.*[%u].name.metadata", index);
+      GetBytesProperty(s, &pV, &VSize);
 
-        pN = (char*)malloc((VSize+1)*sizeof(char));
-        memset(pN, 0, (VSize+1)*sizeof(char));
-        memcpy(pN, pV, VSize*sizeof(char));
+      pN = (char*)malloc((VSize+1)*sizeof(char));
+      if (pN != NULL) {
+	memset(pN, 0, (VSize+1)*sizeof(char));
+	memcpy(pN, pV, VSize*sizeof(char));
+      }
+      free(pV);
+      *ppName = pN;
+    } else {
+    *ppName = strdup(pParent->GetType());
+  }
 
-        *ppName = pN;
-    }
-
-    return true;
+  return true;
 }
 
 bool MP4File::CreateMetadataAtom(const char* name)
 {
-    char s[256];
-    char t[256];
+  char s[256];
+  char t[256];
 
-    sprintf(t, "udta.meta.ilst.%s.data", name);
-    sprintf(s, "moov.udta.meta.ilst.%s.data", name);
-    AddDescendantAtoms("moov", t);
-    MP4Atom *pMetaAtom = m_pRootAtom->FindAtom(s);
+  snprintf(t, 256, "udta.meta.ilst.%s.data", name);
+  snprintf(s, 256, "moov.udta.meta.ilst.%s.data", name);
+  (void)AddDescendantAtoms("moov", t);
+  MP4Atom *pMetaAtom = m_pRootAtom->FindAtom(s);
 
-    if (!pMetaAtom)
-        return false;
+  if (!pMetaAtom)
+    return false;
 
-    /* some fields need special flags set */
-    if ((uint8_t)name[0] == 0251)
+  /* some fields need special flags set */
+  if ((uint8_t)name[0] == 0251 || ATOMID(name) == ATOMID("aART"))
     {
-        pMetaAtom->SetFlags(0x1);
+      pMetaAtom->SetFlags(0x1);
     } else if ((memcmp(name, "cpil", 4) == 0) || (memcmp(name, "tmpo", 4) == 0)) {
-        pMetaAtom->SetFlags(0x15);
-    }
+    pMetaAtom->SetFlags(0x15);
+  }
 
-    MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr");
-    MP4StringProperty *pStringProperty = NULL;
-    MP4BytesProperty *pBytesProperty = NULL;
-    ASSERT(pHdlrAtom);
+  MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr");
+  MP4StringProperty *pStringProperty = NULL;
+  MP4BytesProperty *pBytesProperty = NULL;
+  ASSERT(pHdlrAtom);
 
-    pHdlrAtom->FindProperty(
-        "hdlr.handlerType", (MP4Property**)&pStringProperty);
-    ASSERT(pStringProperty);
-    pStringProperty->SetValue("mdir");
+  ASSERT(pHdlrAtom->FindProperty("hdlr.handlerType", 
+				 (MP4Property**)&pStringProperty));
+  ASSERT(pStringProperty);
+  pStringProperty->SetValue("mdir");
 
-    u_int8_t val[12];
-    memset(val, 0, 12*sizeof(u_int8_t));
-    val[0] = 0x61;
-    val[1] = 0x70;
-    val[2] = 0x70;
-    val[3] = 0x6c;
-    pHdlrAtom->FindProperty(
-        "hdlr.reserved2", (MP4Property**)&pBytesProperty);
-    ASSERT(pBytesProperty);
-    pBytesProperty->SetReadOnly(false);
-    pBytesProperty->SetValue(val, 12);
-    pBytesProperty->SetReadOnly(true);
+  u_int8_t val[12];
+  memset(val, 0, 12*sizeof(u_int8_t));
+  val[0] = 0x61;
+  val[1] = 0x70;
+  val[2] = 0x70;
+  val[3] = 0x6c;
+  ASSERT(pHdlrAtom->FindProperty("hdlr.reserved2", 
+				 (MP4Property**)&pBytesProperty));
+  ASSERT(pBytesProperty);
+  pBytesProperty->SetReadOnly(false);
+  pBytesProperty->SetValue(val, 12);
+  pBytesProperty->SetReadOnly(true);
 
-    return true;
+  return true;
 }
 
-bool MP4File::SetMetadataName(const char* value)
+bool MP4File::DeleteMetadataAtom(const char* name, bool try_udta)
 {
-    const char *s = "moov.udta.meta.ilst.\251nam.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  MP4Atom *pMetaAtom = NULL;
+  char s[256];
 
-    if (!pMetaAtom)
-    {
-        if (!CreateMetadataAtom("\251nam"))
-            return false;
+  snprintf(s, 256, "moov.udta.meta.ilst.%s", name);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
 
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-    }
-
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-
-    pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
-
-    return true;
-}
-
-bool MP4File::GetMetadataName(char** value)
-{
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.\251nam.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
-
-    if (valSize > 0)
-    {
-        *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-        memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-        memcpy(*value, val, valSize*sizeof(unsigned char));
-        return true;
-    } else {
-        *value = NULL;
-        return false;
-    }
-}
-
-bool MP4File::SetMetadataWriter(const char* value)
-{
-    const char *s = "moov.udta.meta.ilst.\251wrt.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
+  if (pMetaAtom == NULL && try_udta) {
+    snprintf(s, 256, "moov.udta.%s", name);
     pMetaAtom = m_pRootAtom->FindAtom(s);
-
-    if (!pMetaAtom)
+  }
+  /* if it exists, delete it */
+  if (pMetaAtom)
     {
-        if (!CreateMetadataAtom("\251wrt"))
-            return false;
+      MP4Atom *pParent = pMetaAtom->GetParentAtom();
 
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-    }
+      pParent->DeleteChildAtom(pMetaAtom);
 
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
+      delete pMetaAtom;
 
-    pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
-
-    return true;
-}
-
-bool MP4File::GetMetadataWriter(char** value)
-{
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.\251wrt.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
-
-    if (valSize > 0)
-    {
-        *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-        memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-        memcpy(*value, val, valSize*sizeof(unsigned char));
-        return true;
-    } else {
-        *value = NULL;
-        return false;
+      return true;
     }
-}
 
-bool MP4File::SetMetadataAlbum(const char* value)
-{
-    const char *s = "moov.udta.meta.ilst.\251alb.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-
-    if (!pMetaAtom)
-    {
-        if (!CreateMetadataAtom("\251alb"))
-            return false;
-
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-    }
-
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-
-    pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
-
-    return true;
+  return false;
 }
 
-bool MP4File::GetMetadataAlbum(char** value)
+bool MP4File::SetMetadataString (const char *atom, const char *value)
 {
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.\251alb.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+  char atomstring[40];
+  MP4Atom *pMetaAtom;
+  MP4BytesProperty *pMetadataProperty = NULL;
+  snprintf(atomstring, 40, "moov.udta.meta.ilst.%s.data", atom);
 
-    if (valSize > 0)
+  pMetaAtom = m_pRootAtom->FindAtom(atomstring);
+  
+  if (!pMetaAtom)
     {
-        *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-        memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-        memcpy(*value, val, valSize*sizeof(unsigned char));
-        return true;
-    } else {
-        *value = NULL;
-        return false;
+      if (!CreateMetadataAtom(atom))
+	return false;
+      
+      pMetaAtom = m_pRootAtom->FindAtom(atomstring);
+      if (pMetaAtom == NULL) return false;
     }
-}
 
-bool MP4File::SetMetadataArtist(const char* value)
-{
-    const char *s = "moov.udta.meta.ilst.\251ART.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-
-    if (!pMetaAtom)
-    {
-        if (!CreateMetadataAtom("\251ART"))
-            return false;
-
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-    }
-
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-
-    pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
-
-    return true;
+  ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
+  
+  pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
+  
+  return true;
 }
 
-bool MP4File::GetMetadataArtist(char** value)
+bool MP4File::GetMetadataString (const char *atom, char **value, bool try_udta)
 {
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.\251ART.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+  unsigned char *val = NULL;
+  u_int32_t valSize = 0;
+  char atomstring[60];
+  snprintf(atomstring, 60, "moov.udta.meta.ilst.%s.data.metadata", atom);
 
-    if (valSize > 0)
-    {
-        *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-        memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-        memcpy(*value, val, valSize*sizeof(unsigned char));
-        return true;
-    } else {
-        *value = NULL;
-        return false;
+  *value = NULL;
+  if (try_udta == false) {
+    GetBytesProperty(atomstring, (u_int8_t**)&val, &valSize);
+  } else {
+    bool got_it = false;
+    try {
+      GetBytesProperty(atomstring, (u_int8_t**)&val, &valSize);
+      got_it = true;
     }
-}
-
-bool MP4File::SetMetadataTool(const char* value)
-{
-    const char *s = "moov.udta.meta.ilst.\251too.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-
-    if (!pMetaAtom)
-    {
-        if (!CreateMetadataAtom("\251too"))
-            return false;
-
-        pMetaAtom = m_pRootAtom->FindAtom(s);
+    catch (MP4Error* e) {
+      delete e;
     }
-
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-
-    pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
-
-    return true;
-}
-
-bool MP4File::GetMetadataTool(char** value)
-{
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.\251too.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
-
-    if (valSize > 0)
-    {
-        *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-        memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-        memcpy(*value, val, valSize*sizeof(unsigned char));
-        return true;
-    } else {
-        *value = NULL;
-        return false;
+    if (got_it == false) {
+      snprintf(atomstring, 60, "moov.udta.%s.metadata", atom);
+      GetBytesProperty(atomstring, (u_int8_t**)&val, &valSize);
     }
-}
-
-bool MP4File::SetMetadataComment(const char* value)
-{
-    const char *s = "moov.udta.meta.ilst.\251cmt.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-
-    if (!pMetaAtom)
+  }
+  if (valSize > 0)
     {
-        if (!CreateMetadataAtom("\251cmt"))
-            return false;
-
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-    }
-
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-
-    pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
-
-    return true;
+      *value = (char*)malloc((valSize+1)*sizeof(char));
+      if (*value == NULL) {
+	free(val);
+	return false;
+      }
+      memcpy(*value, val, valSize*sizeof(unsigned char));
+      free(val);
+      (*value)[valSize] = '\0';
+      return true;
+    } 
+  return false;
 }
 
-bool MP4File::GetMetadataComment(char** value)
-{
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.\251cmt.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
-
-    if (valSize > 0)
-    {
-        *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-        memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-        memcpy(*value, val, valSize*sizeof(unsigned char));
-        return true;
-    } else {
-        *value = NULL;
-        return false;
-    }
-}
-
-bool MP4File::SetMetadataYear(const char* value)
-{
-    const char *s = "moov.udta.meta.ilst.\251day.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-
-    if (!pMetaAtom)
-    {
-        if (!CreateMetadataAtom("\251day"))
-            return false;
-
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-    }
-
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-
-    if (strlen(value) < 4)
-        return false;
-
-    pMetadataProperty->SetValue((u_int8_t*)value, 4);
-
-    return true;
-}
-
-bool MP4File::GetMetadataYear(char** value)
-{
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.\251day.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
-
-    if (valSize > 0)
-    {
-        *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-        memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-        memcpy(*value, val, valSize*sizeof(unsigned char));
-        return true;
-    } else {
-        *value = NULL;
-        return false;
-    }
-}
-
 bool MP4File::SetMetadataTrack(u_int16_t track, u_int16_t totalTracks)
 {
-    unsigned char t[9];
-    const char *s = "moov.udta.meta.ilst.trkn.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
+  unsigned char t[9];
+  const char *s = "moov.udta.meta.ilst.trkn.data";
+  MP4BytesProperty *pMetadataProperty = NULL;
+  MP4Atom *pMetaAtom = NULL;
     
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
 
-    if (!pMetaAtom)
+  if (!pMetaAtom)
     {
-        if (!CreateMetadataAtom("trkn"))
-            return false;
+      if (!CreateMetadataAtom("trkn"))
+	return false;
 
-        pMetaAtom = m_pRootAtom->FindAtom(s);
+      pMetaAtom = m_pRootAtom->FindAtom(s);
+      if (pMetaAtom == NULL) return false;
     }
 
-    memset(t, 0, 9*sizeof(unsigned char));
-    t[2] = (unsigned char)(track>>8)&0xFF;
-    t[3] = (unsigned char)(track)&0xFF;
-    t[4] = (unsigned char)(totalTracks>>8)&0xFF;
-    t[5] = (unsigned char)(totalTracks)&0xFF;
+  memset(t, 0, 9*sizeof(unsigned char));
+  t[2] = (unsigned char)(track>>8)&0xFF;
+  t[3] = (unsigned char)(track)&0xFF;
+  t[4] = (unsigned char)(totalTracks>>8)&0xFF;
+  t[5] = (unsigned char)(totalTracks)&0xFF;
 
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
+  ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
 
-    pMetadataProperty->SetValue((u_int8_t*)t, 8);
+  pMetadataProperty->SetValue((u_int8_t*)t, 8);
 
-    return true;
+  return true;
 }
 
 bool MP4File::GetMetadataTrack(u_int16_t* track, u_int16_t* totalTracks)
 {
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.trkn.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+  unsigned char *val = NULL;
+  u_int32_t valSize = 0;
+  const char *s = "moov.udta.meta.ilst.trkn.data.metadata";
 
-    *track = 0;
-    *totalTracks = 0;
+  *track = 0;
+  *totalTracks = 0;
 
-    if (valSize != 8)
-        return false;
+  GetBytesProperty(s, (u_int8_t**)&val, &valSize);
 
+  if (valSize == 8) {
     *track = (u_int16_t)(val[3]);
     *track += (u_int16_t)(val[2]<<8);
     *totalTracks = (u_int16_t)(val[5]);
     *totalTracks += (u_int16_t)(val[4]<<8);
-
+    CHECK_AND_FREE(val);
     return true;
+  } 
+  CHECK_AND_FREE(val);
+  return false;
 }
 
 bool MP4File::SetMetadataDisk(u_int16_t disk, u_int16_t totalDisks)
 {
-    unsigned char t[9];
-    const char *s = "moov.udta.meta.ilst.disk.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
+  unsigned char t[7];
+  const char *s = "moov.udta.meta.ilst.disk.data";
+  MP4BytesProperty *pMetadataProperty = NULL;
+  MP4Atom *pMetaAtom = NULL;
     
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
 
-    if (!pMetaAtom)
+  if (!pMetaAtom)
     {
-        if (!CreateMetadataAtom("disk"))
-            return false;
+      if (!CreateMetadataAtom("disk"))
+	return false;
 
-        pMetaAtom = m_pRootAtom->FindAtom(s);
+      pMetaAtom = m_pRootAtom->FindAtom(s);
+      if (pMetaAtom == NULL) return false;
     }
 
-    memset(t, 0, 9*sizeof(unsigned char));
-    t[2] = (unsigned char)(disk>>8)&0xFF;
-    t[3] = (unsigned char)(disk)&0xFF;
-    t[4] = (unsigned char)(totalDisks>>8)&0xFF;
-    t[5] = (unsigned char)(totalDisks)&0xFF;
+  memset(t, 0, 7*sizeof(unsigned char));
+  t[2] = (unsigned char)(disk>>8)&0xFF;
+  t[3] = (unsigned char)(disk)&0xFF;
+  t[4] = (unsigned char)(totalDisks>>8)&0xFF;
+  t[5] = (unsigned char)(totalDisks)&0xFF;
 
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
+  ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
 
-    pMetadataProperty->SetValue((u_int8_t*)t, 8);
+  pMetadataProperty->SetValue((u_int8_t*)t, 6);
 
-    return true;
+  return true;
 }
 
 bool MP4File::GetMetadataDisk(u_int16_t* disk, u_int16_t* totalDisks)
 {
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.disk.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+  unsigned char *val = NULL;
+  u_int32_t valSize = 0;
+  const char *s = "moov.udta.meta.ilst.disk.data.metadata";
 
-    *disk = 0;
-    *totalDisks = 0;
+  *disk = 0;
+  *totalDisks = 0;
 
-    if (valSize != 8)
-        return false;
+  GetBytesProperty(s, (u_int8_t**)&val, &valSize);
 
+  if (valSize == 6 || valSize == 8) {
     *disk = (u_int16_t)(val[3]);
     *disk += (u_int16_t)(val[2]<<8);
     *totalDisks = (u_int16_t)(val[5]);
     *totalDisks += (u_int16_t)(val[4]<<8);
-
+    free(val);
     return true;
+  }
+  CHECK_AND_FREE(val);
+  return true;
 }
 
 static const char* ID3v1GenreList[] = {
-    "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
-    "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
-    "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
-    "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
-    "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
-    "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
-    "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
-    "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
-    "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
-    "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
-    "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
-    "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
-    "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
-    "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
-    "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
-    "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
-    "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
-    "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
-    "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
-    "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
-    "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
-    "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
-    "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
-    "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
-    "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
-    "SynthPop",
+  "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
+  "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
+  "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
+  "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
+  "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
+  "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
+  "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
+  "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
+  "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
+  "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
+  "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
+  "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
+  "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
+  "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
+  "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
+  "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
+  "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
+  "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
+  "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
+  "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
+  "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
+  "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
+  "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
+  "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
+  "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
+  "SynthPop",
 };
 
-int GenreToString(char** GenreStr, const int genre)
+void GenreToString(char** GenreStr, const int genre)
 {
   if (genre > 0 && 
       genre <= (int)(sizeof(ID3v1GenreList)/sizeof(*ID3v1GenreList)))
     {
-        *GenreStr = (char*)malloc((strlen(ID3v1GenreList[genre-1])+1)*sizeof(char));
-        memset(*GenreStr, 0, (strlen(ID3v1GenreList[genre-1])+1)*sizeof(char));
-        strcpy(*GenreStr, ID3v1GenreList[genre-1]);
-        return 0;
-    } else {
-        *GenreStr = (char*)malloc(2*sizeof(char));
-        memset(*GenreStr, 0, 2*sizeof(char));
-        return 1;
-    }
+      uint len = strlen(ID3v1GenreList[genre-1])+1;
+      *GenreStr = (char*)malloc(len);
+      if (*GenreStr == NULL) return;
+      // no need for strncpy; enough was malloced
+      strcpy(*GenreStr, ID3v1GenreList[genre-1]);
+      return;
+    } 
+  *GenreStr = (char*)malloc(2*sizeof(char));
+  if (*GenreStr == NULL) return;
+  memset(*GenreStr, 0, 2*sizeof(char));
+  return;
 }
 
 int StringToGenre(const char* GenreStr)
 {
-    unsigned int i;
+  unsigned int i;
 
-    for (i = 0; i < sizeof(ID3v1GenreList)/sizeof(*ID3v1GenreList); i++)
+  for (i = 0; i < sizeof(ID3v1GenreList)/sizeof(*ID3v1GenreList); i++)
     {
-        if (strcasecmp(GenreStr, ID3v1GenreList[i]) == 0)
-            return i+1;
+      if (strcasecmp(GenreStr, ID3v1GenreList[i]) == 0)
+	return i+1;
     }
-    return 0;
+  return 0;
 }
 
 bool MP4File::SetMetadataGenre(const char* value)
 {
-    u_int16_t genreIndex = 0;
-    unsigned char t[3];
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
+  u_int16_t genreIndex = 0;
+  unsigned char t[3];
+  MP4BytesProperty *pMetadataProperty = NULL;
+  MP4Atom *pMetaAtom = NULL;
 
-    genreIndex = StringToGenre(value);
+  genreIndex = StringToGenre(value);
 
-    if (genreIndex != 0)
+  const char *s = "moov.udta.meta.ilst.gnre.data";
+  const char *sroot = "moov.udta.meta.ilst.gnre";
+  const char *s2 = "moov.udta.meta.ilst.\251gen.data";
+  const char *s2root = "moov.udta.meta.ilst.\251gen";
+  if (genreIndex != 0)
     {
-        const char *s = "moov.udta.meta.ilst.gnre.data";
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-
-        if (!pMetaAtom)
+      pMetaAtom = m_pRootAtom->FindAtom(s);
+      if (!pMetaAtom)
         {
-            if (!CreateMetadataAtom("gnre"))
-                return false;
+	  if (!CreateMetadataAtom("gnre"))
+	    return false;
 
-            pMetaAtom = m_pRootAtom->FindAtom(s);
+	  pMetaAtom = m_pRootAtom->FindAtom(s);
+	  if (pMetaAtom == NULL) return false;
         }
 
-        memset(t, 0, 3*sizeof(unsigned char));
-        t[0] = (unsigned char)(genreIndex>>8)&0xFF;
-        t[1] = (unsigned char)(genreIndex)&0xFF;
+      memset(t, 0, 3*sizeof(unsigned char));
+      t[0] = (unsigned char)(genreIndex>>8)&0xFF;
+      t[1] = (unsigned char)(genreIndex)&0xFF;
 
-        pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-        ASSERT(pMetadataProperty);
+      ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				     (MP4Property**)&pMetadataProperty));
+      ASSERT(pMetadataProperty);
 
-        pMetadataProperty->SetValue((u_int8_t*)t, 2);
+      pMetadataProperty->SetValue((u_int8_t*)t, 2);
+	
+      // remove other style of genre atom, if this one is added
+      pMetaAtom = m_pRootAtom->FindAtom(s2root);
+      if (pMetaAtom != NULL) {
+	MP4Atom *pParent = pMetaAtom->GetParentAtom();
+	if (pParent != NULL) {
+	  pParent->DeleteChildAtom(pMetaAtom);
+	  delete pMetaAtom;
+	}
+      }
+	  
 
-        return true;
+      (void)DeleteMetadataAtom( "\251gen" );
+
+      return true;
     } else {
-        const char *s2 = "moov.udta.meta.ilst.\251gen.data";
-        pMetaAtom = m_pRootAtom->FindAtom(s2);
+    pMetaAtom = m_pRootAtom->FindAtom(s2);
 
-        if (!pMetaAtom)
-        {
-            if (!CreateMetadataAtom("\251gen"))
-                return false;
+    if (!pMetaAtom)
+      {
+	if (!CreateMetadataAtom("\251gen"))
+	  return false;
 
-            pMetaAtom = m_pRootAtom->FindAtom(s2);
-        }
+	pMetaAtom = m_pRootAtom->FindAtom(s2);
+      }
 
-        pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-        ASSERT(pMetadataProperty);
+    ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				   (MP4Property**)&pMetadataProperty));
+    ASSERT(pMetadataProperty);
 
-        pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
+    pMetadataProperty->SetValue((u_int8_t*)value, strlen(value));
 
-        return true;
+    // remove other gnre atom if this one is entered
+    pMetaAtom = m_pRootAtom->FindAtom(sroot);
+    if (pMetaAtom != NULL) {
+      MP4Atom *pParent = pMetaAtom->GetParentAtom();
+      pParent->DeleteChildAtom(pMetaAtom);
+      delete pMetaAtom;
     }
+    return true;
+  }
 
-    return false;
+  return false;
 }
 
 bool MP4File::GetMetadataGenre(char** value)
 {
-    u_int16_t genreIndex = 0;
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *t = "moov.udta.meta.ilst.gnre";
-    const char *s = "moov.udta.meta.ilst.gnre.data.metadata";
+  u_int16_t genreIndex = 0;
+  unsigned char *val = NULL;
+  u_int32_t valSize = 0;
+  const char *t = "moov.udta.meta.ilst.gnre";
+  const char *s = "moov.udta.meta.ilst.gnre.data.metadata";
 
-    MP4Atom *gnre = FindAtom(t);
+  *value = NULL;
 
-    if (gnre)
+  MP4Atom *gnre = FindAtom(t);
+
+  if (gnre)
     {
-        GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+      GetBytesProperty(s, (u_int8_t**)&val, &valSize);
 
-        if (valSize != 2)
-            return false;
+      if (valSize != 2) {
+	CHECK_AND_FREE(val);
+	return false;
+      }
 
-        genreIndex = (u_int16_t)(val[1]);
-        genreIndex += (u_int16_t)(val[0]<<8);
+      genreIndex = (u_int16_t)(val[1]);
+      genreIndex += (u_int16_t)(val[0]<<8);
 
-        GenreToString(value, genreIndex);
+      GenreToString(value, genreIndex);
 
-        return true;
+      (void)DeleteMetadataAtom( "gnre" );
+      free(val);
+      return true;
     } else {
-        const char *s2 = "moov.udta.meta.ilst.\251gen.data.metadata";
+    const char *s2 = "moov.udta.meta.ilst.\251gen.data.metadata";
 
-        val = NULL;
-        valSize = 0;
+    val = NULL;
+    valSize = 0;
 
-        GetBytesProperty(s2, (u_int8_t**)&val, &valSize);
+    GetBytesProperty(s2, (u_int8_t**)&val, &valSize);
 
-        if (valSize > 0)
-        {
-            *value = (char*)malloc((valSize+1)*sizeof(unsigned char));
-            memset(*value, 0, (valSize+1)*sizeof(unsigned char));
-            memcpy(*value, val, valSize*sizeof(unsigned char));
-            return true;
-        } else {
-            *value = NULL;
-            return false;
-        }
+    if (valSize > 0)
+      {
+	*value = (char*)malloc((valSize+1)*sizeof(unsigned char));
+	if (*value != NULL) {
+	  memset(*value, 0, (valSize+1)*sizeof(unsigned char));
+	  memcpy(*value, val, valSize*sizeof(unsigned char));
+	}
+	free(val);
+	return true;
+      } else {
+      CHECK_AND_FREE(val);
     }
+  }
 
-    return false;
+  return false;
 }
 
+bool MP4File::DeleteMetadataGenre()
+{
+  bool val1 = DeleteMetadataAtom("\251gen");
+  bool val2 = DeleteMetadataAtom("gnre");
+  return val1 || val2;
+}
+
 bool MP4File::SetMetadataTempo(u_int16_t tempo)
 {
-    unsigned char t[3];
-    const char *s = "moov.udta.meta.ilst.tmpo.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
+  unsigned char t[3];
+  const char *s = "moov.udta.meta.ilst.tmpo.data";
+  MP4BytesProperty *pMetadataProperty = NULL;
+  MP4Atom *pMetaAtom = NULL;
     
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
 
-    if (!pMetaAtom)
+  if (!pMetaAtom)
     {
-        if (!CreateMetadataAtom("tmpo"))
-            return false;
+      if (!CreateMetadataAtom("tmpo"))
+	return false;
 
-        pMetaAtom = m_pRootAtom->FindAtom(s);
+      pMetaAtom = m_pRootAtom->FindAtom(s);
+      if (pMetaAtom == NULL) return false;
     }
 
-    memset(t, 0, 3*sizeof(unsigned char));
-    t[0] = (unsigned char)(tempo>>8)&0xFF;
-    t[1] = (unsigned char)(tempo)&0xFF;
+  memset(t, 0, 3*sizeof(unsigned char));
+  t[0] = (unsigned char)(tempo>>8)&0xFF;
+  t[1] = (unsigned char)(tempo)&0xFF;
 
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
+  ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
 
-    pMetadataProperty->SetValue((u_int8_t*)t, 2);
+  pMetadataProperty->SetValue((u_int8_t*)t, 2);
 
-    return true;
+  return true;
 }
 
 bool MP4File::GetMetadataTempo(u_int16_t* tempo)
 {
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.tmpo.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+  unsigned char *val = NULL;
+  u_int32_t valSize = 0;
+  const char *s = "moov.udta.meta.ilst.tmpo.data.metadata";
 
-    *tempo = 0;
+  *tempo = 0;
 
-    if (valSize != 2)
-        return false;
+  GetBytesProperty(s, (u_int8_t**)&val, &valSize);
 
-    *tempo = (u_int16_t)(val[1]);
-    *tempo += (u_int16_t)(val[0]<<8);
+  if (valSize != 2) {
+    CHECK_AND_FREE(val);
+    return false;
+  }
 
-    return true;
+  *tempo = (u_int16_t)(val[1]);
+  *tempo += (u_int16_t)(val[0]<<8);
+  free(val);
+  return true;
 }
-
-bool MP4File::SetMetadataCompilation(u_int8_t compilation)
+bool MP4File::SetMetadataUint8 (const char *atom, uint8_t value)
 {
-    const char *s = "moov.udta.meta.ilst.cpil.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
-    
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  char atompath[36];
+  MP4BytesProperty *pMetadataProperty = NULL;
+  MP4Atom *pMetaAtom = NULL;
 
-    if (!pMetaAtom)
-    {
-        if (!CreateMetadataAtom("cpil"))
-            return false;
+  snprintf(atompath, 36, "moov.udta.meta.ilst.%s.data", atom);
 
-        pMetaAtom = m_pRootAtom->FindAtom(s);
-    }
+  pMetaAtom = m_pRootAtom->FindAtom(atompath);
 
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
+  if (pMetaAtom == NULL) {
+    if (!CreateMetadataAtom(atom))
+      return false;
 
-    compilation &= 0x1;
-    pMetadataProperty->SetValue((u_int8_t*)&compilation, 1);
+    pMetaAtom = m_pRootAtom->FindAtom(atompath);
+    if (pMetaAtom == NULL) return false;
+  }
 
-    return true;
+  ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
+  
+  pMetadataProperty->SetValue(&value, 1);
+
+  return true;
 }
 
-bool MP4File::GetMetadataCompilation(u_int8_t* compilation)
+
+bool MP4File::GetMetadataUint8(const char *atom, u_int8_t* retvalue)
 {
-    unsigned char *val = NULL;
-    u_int32_t valSize = 0;
-    const char *s = "moov.udta.meta.ilst.cpil.data.metadata";
-    GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+  unsigned char *val = NULL;
+  u_int32_t valSize = 0;
+  char atompath[80];
+  snprintf(atompath, 80, "moov.udta.meta.ilst.%s.data.metadata", atom);
 
-    *compilation = 0;
+  *retvalue = 0;
 
-    if (valSize != 1)
-        return false;
+  GetBytesProperty(atompath, (u_int8_t**)&val, &valSize);
 
-    *compilation = (u_int16_t)(val[0]);
+  if (valSize != 1) {
+    CHECK_AND_FREE(val);
+    return false;
+  }
 
-    return true;
+  *retvalue = val[0];
+  free(val);
+  return true;
 }
 
 bool MP4File::SetMetadataCoverArt(u_int8_t *coverArt, u_int32_t size)
 {
-    const char *s = "moov.udta.meta.ilst.covr.data";
-    MP4BytesProperty *pMetadataProperty = NULL;
-    MP4Atom *pMetaAtom = NULL;
+  const char *s = "moov.udta.meta.ilst.covr.data";
+  MP4BytesProperty *pMetadataProperty = NULL;
+  MP4Atom *pMetaAtom = NULL;
     
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
 
-    if (!pMetaAtom)
+  if (!pMetaAtom)
     {
-        if (!CreateMetadataAtom("covr"))
-            return false;
+      if (!CreateMetadataAtom("covr"))
+	return false;
 
-        pMetaAtom = m_pRootAtom->FindAtom(s);
+      pMetaAtom = m_pRootAtom->FindAtom(s);
+      if (pMetaAtom == NULL) return false;
     }
 
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
+  ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
 
-    pMetadataProperty->SetValue(coverArt, size);
+  pMetadataProperty->SetValue(coverArt, size);
 
-    return true;
+  return true;
 }
 
-bool MP4File::GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t *size)
+bool MP4File::GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t *size,
+				  uint32_t index)
 {
-    const char *s = "moov.udta.meta.ilst.covr.data.metadata";
-    GetBytesProperty(s, coverArt, size);
+  char buffer[256];
+  if (size == NULL || coverArt == NULL) return false;
 
-    if (size == 0)
-        return false;
+  if (index > 0 && index > GetMetadataCoverArtCount()) return false;
 
-    return true;
+  snprintf(buffer, 256, "moov.udta.meta.ilst.covr.data[%d].metadata", index);
+
+  *coverArt = NULL;
+  *size = 0;
+
+  GetBytesProperty(buffer, coverArt, size);
+
+  if (size == 0)
+    return false;
+
+  return true;
 }
 
-bool MP4File::SetMetadataFreeForm(char *name, u_int8_t* pValue, u_int32_t valueSize)
+u_int32_t MP4File::GetMetadataCoverArtCount (void)
 {
-    MP4Atom *pMetaAtom = NULL;
-    MP4BytesProperty *pMetadataProperty = NULL;
-    char s[256];
-    int i = 0;
+  MP4Atom *pMetaAtom = m_pRootAtom->FindAtom("moov.udta.meta.ilst.covr");
+  if (!pMetaAtom)
+    return 0;
 
-    while (1)
-    {
-        MP4BytesProperty *pMetadataProperty;
+  return pMetaAtom->GetNumberOfChildAtoms();
+}
 
-        sprintf(s, "moov.udta.meta.ilst.----[%u].name", i);
+bool MP4File::SetMetadataFreeForm (const char *name, 
+				   const u_int8_t* pValue, 
+				   u_int32_t valueSize,
+				   const char *owner)
+{
+  MP4Atom *pMetaAtom = NULL;
+  MP4BytesProperty *pMetadataProperty = NULL;
+  char s[256];
+  int i = 0;
+  size_t nameLen = strlen(name);
+  size_t ownerLen = owner != NULL ? strlen(owner) : 0;
 
-        MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s);
+  while (1)
+    {
+      snprintf(s, 256, "moov.udta.meta.ilst.----[%u].name", i);
 
-        if (!pTagAtom)
-            break;
+      MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s);
 
-        pTagAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty);
-        if (pMetadataProperty)
-        {
-            u_int8_t* pV;
-            u_int32_t VSize = 0;
+      if (!pTagAtom)
+	break;
 
-            pMetadataProperty->GetValue(&pV, &VSize);
+      snprintf(s, 256, "moov.udta.meta.ilst.----[%u].mean", i);
 
-            if (VSize != 0)
-            {
-                if (memcmp(pV, name, VSize) == 0)
-                {
-                    sprintf(s, "moov.udta.meta.ilst.----[%u].data.metadata", i);
-                    SetBytesProperty(s, pValue, valueSize);
+      MP4Atom *pMeanAtom = m_pRootAtom->FindAtom(s);
 
-                    return true;
-                }
-            }
-        }
+      if (pTagAtom->FindProperty("name.metadata", 
+				 (MP4Property**)&pMetadataProperty) &&
+	  pMetadataProperty) {
+	u_int8_t* pV;
+	u_int32_t VSize = 0;
 
-        i++;
+	pMetadataProperty->GetValue(&pV, &VSize);
+
+	if (VSize == nameLen && memcmp(pV, name, VSize) == 0) {
+	  u_int8_t* pOwner=0;
+	  u_int32_t ownerSize = 0;
+	  
+	  if (pMeanAtom && 
+	      pMeanAtom->FindProperty("mean.metadata", 
+				      (MP4Property**)&pMetadataProperty) &&
+	      pMetadataProperty) {
+	    pMetadataProperty->GetValue(&pOwner, &ownerSize);
+	  }
+	  
+	  if (owner == NULL|| 
+	      (pOwner && 
+	       ownerLen == ownerSize && 
+	       memcmp(owner, pOwner, ownerSize))) {
+	    snprintf(s, 256, "moov.udta.meta.ilst.----[%u].data.metadata", i);
+	    SetBytesProperty(s, pValue, valueSize);
+	    CHECK_AND_FREE(pV);
+	    CHECK_AND_FREE(pOwner);
+	    
+	    return true;
+	  }
+	  CHECK_AND_FREE(pOwner);
+	}
+	CHECK_AND_FREE(pV);
+      }
+      
+      i++;
     }
 
-    /* doesn't exist yet, create it */
-    char t[256];
+  /* doesn't exist yet, create it */
+  char t[256];
 
-    sprintf(t, "udta.meta.ilst.----[%u]", i);
-    sprintf(s, "moov.udta.meta.ilst.----[%u].data", i);
-    AddDescendantAtoms("moov", t);
+  snprintf(t, 256, "udta.meta.ilst.----[%u]", i);
+  snprintf(s, 256, "moov.udta.meta.ilst.----[%u].data", i);
+  (void)AddDescendantAtoms("moov", t);
 
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
 
-    if (!pMetaAtom)
-        return false;
+  if (!pMetaAtom)
+    return false;
 
-    pMetaAtom->SetFlags(0x1);
+  pMetaAtom->SetFlags(0x1);
 
-    MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr");
-    MP4StringProperty *pStringProperty = NULL;
-    MP4BytesProperty *pBytesProperty = NULL;
-    ASSERT(pHdlrAtom);
+  MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr");
+  MP4StringProperty *pStringProperty = NULL;
+  MP4BytesProperty *pBytesProperty = NULL;
+  ASSERT(pHdlrAtom);
 
-    pHdlrAtom->FindProperty(
-        "hdlr.handlerType", (MP4Property**)&pStringProperty);
-    ASSERT(pStringProperty);
-    pStringProperty->SetValue("mdir");
+  ASSERT(pHdlrAtom->FindProperty("hdlr.handlerType", 
+				 (MP4Property**)&pStringProperty));
+  ASSERT(pStringProperty);
+  pStringProperty->SetValue("mdir");
 
-    u_int8_t val[12];
-    memset(val, 0, 12*sizeof(u_int8_t));
-    val[0] = 0x61;
-    val[1] = 0x70;
-    val[2] = 0x70;
-    val[3] = 0x6c;
-    pHdlrAtom->FindProperty(
-        "hdlr.reserved2", (MP4Property**)&pBytesProperty);
-    ASSERT(pBytesProperty);
-    pBytesProperty->SetReadOnly(false);
-    pBytesProperty->SetValue(val, 12);
-    pBytesProperty->SetReadOnly(true);
+  u_int8_t val[12];
+  memset(val, 0, 12*sizeof(u_int8_t));
+  val[0] = 0x61;
+  val[1] = 0x70;
+  val[2] = 0x70;
+  val[3] = 0x6c;
+  ASSERT(pHdlrAtom->FindProperty("hdlr.reserved2", 
+				 (MP4Property**)&pBytesProperty));
+  ASSERT(pBytesProperty);
+  pBytesProperty->SetReadOnly(false);
+  pBytesProperty->SetValue(val, 12);
+  pBytesProperty->SetReadOnly(true);
 
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-    pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-    pMetadataProperty->SetValue(pValue, valueSize);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
+  ASSERT(pMetaAtom);
+  ASSERT(pMetaAtom->FindProperty("data.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
+  pMetadataProperty->SetValue(pValue, valueSize);
 
-    sprintf(s, "moov.udta.meta.ilst.----[%u].name", i);
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-    pMetaAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-    pMetadataProperty->SetValue((u_int8_t*)name, strlen(name));
+  snprintf(s, 256, "moov.udta.meta.ilst.----[%u].name", i);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
+  ASSERT(pMetaAtom->FindProperty("name.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
+  pMetadataProperty->SetValue((const u_int8_t*)name, strlen(name));
 
-    sprintf(s, "moov.udta.meta.ilst.----[%u].mean", i);
-    pMetaAtom = m_pRootAtom->FindAtom(s);
-    pMetaAtom->FindProperty("mean.metadata", (MP4Property**)&pMetadataProperty);
-    ASSERT(pMetadataProperty);
-    pMetadataProperty->SetValue((u_int8_t*)"com.apple.iTunes", 16); /* ?? */
+  snprintf(s, 256, "moov.udta.meta.ilst.----[%u].mean", i);
+  pMetaAtom = m_pRootAtom->FindAtom(s);
+  ASSERT(pMetaAtom->FindProperty("mean.metadata", 
+				 (MP4Property**)&pMetadataProperty));
+  ASSERT(pMetadataProperty);
+  if (!owner || !*owner)
+    pMetadataProperty->SetValue((u_int8_t*)"com.apple.iTunes", 16); /* com.apple.iTunes is the default*/
+  else
+    pMetadataProperty->SetValue((const u_int8_t*)owner, strlen((const char *)owner));
 
-    return true;
+  return true;
 }
 
-bool MP4File::GetMetadataFreeForm(char *name, u_int8_t** ppValue, u_int32_t *pValueSize)
+bool MP4File::GetMetadataFreeForm(const char *name, 
+				  u_int8_t** ppValue, 
+				  u_int32_t *pValueSize,
+				  const char *owner)
 {
-    char s[256];
-    int i = 0;
+  char s[256];
+  int i = 0;
 
-    while (1)
+  *ppValue = NULL;
+  *pValueSize = 0;
+
+  size_t nameLen = strlen(name);
+  size_t ownerLen = owner?strlen(owner):0;
+
+  while (1)
     {
-        MP4BytesProperty *pMetadataProperty;
+      MP4BytesProperty *pMetadataProperty;
 
-        sprintf(s, "moov.udta.meta.ilst.----[%u].name", i);
+      snprintf(s, 256,"moov.udta.meta.ilst.----[%u].name", i);
+      MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s);
 
-        MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s);
+      snprintf(s, 256,"moov.udta.meta.ilst.----[%u].mean", i);
+      MP4Atom *pMeanAtom = m_pRootAtom->FindAtom(s);
 
-        if (!pTagAtom)
-            return false;
+      if (!pTagAtom)
+	return false;
 
-        pTagAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty);
-        if (pMetadataProperty)
-        {
-            u_int8_t* pV;
-            u_int32_t VSize = 0;
+      if (pTagAtom->FindProperty("name.metadata", 
+				 (MP4Property**)&pMetadataProperty) &&
+	  pMetadataProperty) {
+	u_int8_t* pV;
+	u_int32_t VSize = 0;
 
-            pMetadataProperty->GetValue(&pV, &VSize);
+	pMetadataProperty->GetValue(&pV, &VSize);
 
-            if (VSize != 0)
-            {
-                if (memcmp(pV, name, VSize) == 0)
-                {
-                    sprintf(s, "moov.udta.meta.ilst.----[%u].data.metadata", i);
-                    GetBytesProperty(s, ppValue, pValueSize);
+	if (VSize == nameLen && memcmp(pV, name, VSize) == 0) {
+	    u_int8_t* pOwner=0;
+	    u_int32_t ownerSize = 0;
 
-                    return true;
-                }
-            }
-        }
+	    if (pMeanAtom && pMeanAtom->FindProperty("mean.metadata", 
+						     (MP4Property**)&pMetadataProperty) &&
+		pMetadataProperty) {
+	      pMetadataProperty->GetValue(&pOwner, &ownerSize);
+	    }
+
+	    if (!owner || (pOwner && ownerLen == ownerSize && memcmp(owner, pOwner, ownerSize))) {
+	      snprintf(s, 256, "moov.udta.meta.ilst.----[%u].data.metadata", i);
+	      GetBytesProperty(s, ppValue, pValueSize);
+	      CHECK_AND_FREE(pV);
+	      CHECK_AND_FREE(pOwner);
+	      return true;	
+	    }
+	    CHECK_AND_FREE(pOwner);
+	}
+	CHECK_AND_FREE(pV);
+      }
+      
+      i++;
+    }
+}
 
-        i++;
+bool MP4File::DeleteMetadataFreeForm(const char *name, const char *owner)
+{
+  char s[256];
+  int i = 0;
+
+  size_t nameLen = strlen(name);
+  size_t ownerLen = owner?strlen(owner):0;
+
+  while (1)
+    {
+      MP4BytesProperty *pMetadataProperty;
+
+      snprintf(s, 256, "moov.udta.meta.ilst.----[%u].name", i);
+      MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s);
+
+      snprintf(s, 256,"moov.udta.meta.ilst.----[%u].mean", i);
+      MP4Atom *pMeanAtom = m_pRootAtom->FindAtom(s);
+
+
+      if (!pTagAtom)
+	return false;
+
+      if (pTagAtom->FindProperty("name.metadata", 
+				 (MP4Property**)&pMetadataProperty) &&
+	  pMetadataProperty) {
+	u_int8_t* pV;
+	u_int32_t VSize = 0;
+
+	pMetadataProperty->GetValue(&pV, &VSize);
+
+	if (VSize != 0)
+	  {
+	    if (VSize == nameLen && memcmp(pV, name, VSize) == 0)
+	      {
+		u_int8_t* pOwner=0;
+		u_int32_t ownerSize = 0;
+
+		if (pMeanAtom && pMeanAtom->FindProperty("mean.metadata", 
+							 (MP4Property**)&pMetadataProperty) &&
+		    pMetadataProperty) 
+		  {
+		    pMetadataProperty->GetValue(&pOwner, &ownerSize);
+		  }
+
+		if (!owner || (pOwner && ownerLen == ownerSize && memcmp(owner, pOwner, ownerSize)))
+		  {
+		    snprintf(s, 256, "----[%u]", i);
+		    CHECK_AND_FREE(pOwner);
+		    CHECK_AND_FREE(pV);
+		    return DeleteMetadataAtom(s);
+		  }
+		CHECK_AND_FREE(pOwner);
+
+	      }
+	  }
+	CHECK_AND_FREE(pV);
+      }
+
+      i++;
     }
 }
 
 bool MP4File::MetadataDelete()
 {
-    MP4Atom *pMetaAtom = NULL;
-    char s[256];
+  MP4Atom *pMetaAtom = NULL;
+  char s[256];
 
-    sprintf(s, "moov.udta.meta");
-    pMetaAtom = m_pRootAtom->FindAtom(s);
+  snprintf(s, 256, "moov.udta.meta");
+  pMetaAtom = m_pRootAtom->FindAtom(s);
 
-    /* if it exists, delete it */
-    if (pMetaAtom)
+  /* if it exists, delete it */
+  if (pMetaAtom)
     {
-        MP4Atom *pParent = pMetaAtom->GetParentAtom();
+      MP4Atom *pParent = pMetaAtom->GetParentAtom();
 
-        pParent->DeleteChildAtom(pMetaAtom);
+      pParent->DeleteChildAtom(pMetaAtom);
 
-        delete pMetaAtom;
+      delete pMetaAtom;
 
-        return true;
+      return true;
     }
 
-    return false;
+  return false;
 }
--- a/common/mp4v2/mp4property.cpp
+++ b/common/mp4v2/mp4property.cpp
@@ -150,8 +150,13 @@
 		return;
 	}
 	Indent(pFile, indent);
-	fprintf(pFile, "%s = %u (0x%02x)\n", 
-		m_name, m_values[index], m_values[index]);
+	if (index != 0) 
+	  fprintf(pFile, "%s[%u] = %u (0x%02x)\n", 
+		  m_name, index, m_values[index], m_values[index]);
+	else
+	  fprintf(pFile, "%s = %u (0x%02x)\n", 
+		  m_name, m_values[index], m_values[index]);
+	fflush(pFile);
 }
 
 void MP4Integer16Property::Dump(FILE* pFile, u_int8_t indent,
@@ -161,8 +166,13 @@
 		return;
 	}
 	Indent(pFile, indent);
-	fprintf(pFile, "%s = %u (0x%04x)\n", 
-		m_name, m_values[index], m_values[index]);
+	if (index != 0) 
+	  fprintf(pFile, "%s[%u] = %u (0x%04x)\n", 
+		  m_name, index, m_values[index], m_values[index]);
+	else
+	  fprintf(pFile, "%s = %u (0x%04x)\n", 
+		  m_name, m_values[index], m_values[index]);
+	fflush(pFile);
 }
 
 void MP4Integer24Property::Dump(FILE* pFile, u_int8_t indent,
@@ -172,8 +182,13 @@
 		return;
 	}
 	Indent(pFile, indent);
-	fprintf(pFile, "%s = %u (0x%06x)\n", 
-		m_name, m_values[index], m_values[index]);
+	if (index != 0) 
+	  fprintf(pFile, "%s[%u] = %u (0x%06x)\n", 
+		  m_name, index, m_values[index], m_values[index]);
+	else
+	  fprintf(pFile, "%s = %u (0x%06x)\n", 
+		  m_name, m_values[index], m_values[index]);
+	fflush(pFile);
 }
 
 void MP4Integer32Property::Dump(FILE* pFile, u_int8_t indent,
@@ -183,8 +198,13 @@
 		return;
 	}
 	Indent(pFile, indent);
-	fprintf(pFile, "%s = %u (0x%08x)\n", 
+	if (index != 0) 
+	  fprintf(pFile, "%s[%u] = %u (0x%08x)\n", 
+		  m_name, index, m_values[index], m_values[index]);
+	else
+	  fprintf(pFile, "%s = %u (0x%08x)\n", 
 		m_name, m_values[index], m_values[index]);
+	fflush(pFile);
 }
 
 void MP4Integer64Property::Dump(FILE* pFile, u_int8_t indent,
@@ -194,9 +214,14 @@
 		return;
 	}
 	Indent(pFile, indent);
-	fprintf(pFile, 
-		"%s = "U64" (0x%016"X64F")\n", 
-		m_name, m_values[index], m_values[index]);
+	if (index != 0) 
+	  fprintf(pFile, "%s[%u] = "U64" (0x%016"X64F")\n", 
+		  m_name, index, m_values[index], m_values[index]);
+	else
+	  fprintf(pFile, 
+		  "%s = "U64" (0x%016"X64F")\n", 
+		  m_name, m_values[index], m_values[index]);
+	fflush(pFile);
 }
 
 // MP4BitfieldProperty
@@ -229,9 +254,15 @@
 	if (hexWidth == 0 || (m_numBits % 4)) {
 		hexWidth++;
 	}
+	if (index != 0) 
 	fprintf(pFile, 
-		"%s = "U64" (0x%0*"X64F") <%u bits>\n", 
-		m_name, m_values[index], (int)hexWidth, m_values[index], m_numBits);
+		"%s[%u] = "U64" (0x%0*"X64F") <%u bits>\n", 
+		m_name, index, m_values[index], (int)hexWidth, m_values[index], m_numBits);
+	else 
+	  fprintf(pFile, 
+		  "%s = "U64" (0x%0*"X64F") <%u bits>\n", 
+		  m_name, m_values[index], (int)hexWidth, m_values[index], m_numBits);
+	fflush(pFile);
 }
 
 // MP4Float32Property
@@ -271,8 +302,13 @@
 		return;
 	}
 	Indent(pFile, indent);
-	fprintf(pFile, "%s = %f\n", 
-		m_name, m_values[index]);
+	if (index != 0) 
+  	  fprintf(pFile, "%s[%u] = %f\n", 
+		  m_name, index, m_values[index]);
+	else
+ 	  fprintf(pFile, "%s = %f\n", 
+		  m_name, m_values[index]);
+	fflush(pFile);
 }
 
 // MP4StringProperty
@@ -369,11 +405,17 @@
 		return;
 	}
 	Indent(pFile, indent);
+	char indexd[32];
+	if (index != 0) {
+	  snprintf(indexd, 32, "[%u]", index);
+	} else indexd[0] = '\0';
+
 	if (m_useUnicode) {
-		fprintf(pFile, "%s = %ls\n", m_name, (wchar_t*)m_values[index]);
+	  fprintf(pFile, "%s%s = %ls\n", m_name, indexd, (wchar_t*)m_values[index]);
 	} else {
-		fprintf(pFile, "%s = %s\n", m_name, m_values[index]);
+	  fprintf(pFile, "%s%s = %s\n", m_name, indexd, m_values[index]);
 	}
+	fflush(pFile);
 }
 
 // MP4BytesProperty
@@ -418,8 +460,12 @@
 	}
 	if (m_fixedValueSize) {
 		if (valueSize > m_fixedValueSize) {
-			throw new MP4Error("value size exceeds fixed value size",
-				"MP4BytesProperty::SetValue");
+			throw new MP4Error("%s.%s value size %d exceeds fixed value size %d",
+					   "MP4BytesProperty::SetValue",
+					   GetParentAtom()->GetType(),
+					   GetName(),
+					   valueSize, 
+					   m_fixedValueSize);
 		}
 		if (m_values[index] == NULL) {
 			m_values[index] = (u_int8_t*)MP4Calloc(m_fixedValueSize);
@@ -487,7 +533,9 @@
 		return;
 	}
 	Indent(pFile, indent);
-	fprintf(pFile, "%s = <%u bytes> ", m_name, m_valueSizes[index]);
+	fputs(m_name, pFile);
+	if (index != 0) fprintf(pFile, "[%u]", index);
+	fprintf(pFile, " = <%u bytes> ", m_valueSizes[index]);
 	for (u_int32_t i = 0; i < m_valueSizes[index]; i++) {
 		if ((i % 16) == 0 && m_valueSizes[index] > 16) {
 			fprintf(pFile, "\n");
@@ -496,15 +544,14 @@
 		fprintf(pFile, "%02x ", m_values[index][i]);
 	}
 	fprintf(pFile, "\n");
+	fflush(pFile);
 }
 
 // MP4TableProperty
 
-MP4TableProperty::MP4TableProperty(char* name, MP4Property* pCountProperty)
+MP4TableProperty::MP4TableProperty(char* name, MP4IntegerProperty* pCountProperty)
 	: MP4Property(name) 
 {
-	ASSERT(pCountProperty->GetType() == Integer8Property
-		|| pCountProperty->GetType() == Integer32Property);
 	m_pCountProperty = pCountProperty;
 	m_pCountProperty->SetReadOnly();
 }
@@ -629,8 +676,15 @@
 
 	u_int32_t numEntries = GetCount();
 
-	ASSERT(m_pProperties[0]->GetCount() == numEntries);
+	if (m_pProperties[0]->GetCount() != numEntries) {
+	  fprintf(stderr, "%s %s \"%s\"table entries %u doesn't match count %u\n", 
+		  GetParentAtom() != NULL ? GetParentAtom()->GetType() : "", 
+		  GetName(), m_pProperties[0]->GetName(),
+		  m_pProperties[0]->GetCount(), numEntries);
 
+	  ASSERT(m_pProperties[0]->GetCount() == numEntries);
+	}
+
 	for (u_int32_t i = 0; i < numEntries; i++) {
 		WriteEntry(pFile, i);
 	}
@@ -858,7 +912,10 @@
 
 	if (m_name) {
 		Indent(pFile, indent);
-		fprintf(pFile, "%s\n", m_name);
+		if (index != 0) 
+		  fprintf(pFile, "%s[%u]\n", m_name, index);
+		else
+		  fprintf(pFile, "%s\n", m_name);
 		indent++;
 	}
 
--- a/common/mp4v2/mp4property.h
+++ b/common/mp4v2/mp4property.h
@@ -301,7 +301,7 @@
 
 	void SetValue(const char* value, u_int32_t index = 0);
 
-	void AddValue(char* value) {
+	void AddValue(const char* value) {
 		u_int32_t count = GetCount();
 		SetCount(count + 1); 
 		SetValue(value, count);
@@ -387,7 +387,7 @@
 	void SetValue(const u_int8_t* pValue, u_int32_t valueSize, 
 		u_int32_t index = 0);
 
-	void AddValue(u_int8_t* pValue, u_int32_t valueSize) {
+	void AddValue(const u_int8_t* pValue, u_int32_t valueSize) {
 		u_int32_t count = GetCount();
 		SetCount(count + 1); 
 		SetValue(pValue, valueSize, count);
@@ -419,7 +419,7 @@
 
 class MP4TableProperty : public MP4Property {
 public:
-	MP4TableProperty(char* name, MP4Property* pCountProperty);
+	MP4TableProperty(char* name, MP4IntegerProperty* pCountProperty);
 
 	~MP4TableProperty();
 
@@ -440,19 +440,11 @@
 		return m_pProperties[index];
 	}
 
-	u_int32_t GetCount() {
-		if (m_pCountProperty->GetType() == Integer8Property) {
-			return ((MP4Integer8Property*)m_pCountProperty)->GetValue();
-		} else {
-			return ((MP4Integer32Property*)m_pCountProperty)->GetValue();
-		} 
+	virtual u_int32_t GetCount() {
+	  return m_pCountProperty->GetValue();
 	}
-	void SetCount(u_int32_t count) {
-		if (m_pCountProperty->GetType() == Integer8Property) {
-			((MP4Integer8Property*)m_pCountProperty)->SetValue(count);
-		} else {
-			((MP4Integer32Property*)m_pCountProperty)->SetValue(count);
-		} 
+	virtual void SetCount(u_int32_t count) {
+	  m_pCountProperty->SetValue(count);
 	}
 
 	void Read(MP4File* pFile, u_int32_t index = 0);
@@ -471,7 +463,7 @@
 		MP4Property** ppProperty, u_int32_t* pIndex);
 
 protected:
-	MP4Property*		m_pCountProperty;
+	MP4IntegerProperty*	m_pCountProperty;
 	MP4PropertyArray	m_pProperties;
 };
 
--- a/common/mp4v2/mp4track.cpp
+++ b/common/mp4v2/mp4track.cpp
@@ -52,10 +52,15 @@
 	m_chunkSamples = 0;
 	m_chunkDuration = 0;
 
+	// m_bytesPerSample should be set to 1, except for the
+	// quicktime audio constant bit rate samples, which have non-1 values
+	m_bytesPerSample = 1;
 	m_samplesPerChunk = 0;
 	m_durationPerChunk = 0;
 	m_isAmr = AMR_UNINITIALIZED;
 	m_curMode = 0;
+	
+	m_cachedSttsSid = MP4_INVALID_SAMPLE_ID;
 
 	bool success = true;
 
@@ -97,17 +102,37 @@
 
 	// get handles on sample size information
 
-	success &= m_pTrakAtom->FindProperty(
-		"trak.mdia.minf.stbl.stsz.sampleSize",
-		(MP4Property**)&m_pStszFixedSampleSizeProperty);
+
+	m_pStszFixedSampleSizeProperty = NULL;
+	bool have_stsz = 
+	  m_pTrakAtom->FindProperty("trak.mdia.minf.stbl.stsz.sampleSize",
+				    (MP4Property**)&m_pStszFixedSampleSizeProperty);
 	
-	success &= m_pTrakAtom->FindProperty(
+	if (have_stsz) {
+	  success &= m_pTrakAtom->FindProperty(
 		"trak.mdia.minf.stbl.stsz.sampleCount",
 		(MP4Property**)&m_pStszSampleCountProperty);
 
-	success &= m_pTrakAtom->FindProperty(
-		"trak.mdia.minf.stbl.stsz.entries.sampleSize",
+	  success &= m_pTrakAtom->FindProperty(
+		"trak.mdia.minf.stbl.stsz.entries.entrySize",
 		(MP4Property**)&m_pStszSampleSizeProperty);
+	  m_stsz_sample_bits = 32;
+	} else {
+	  success &= m_pTrakAtom->FindProperty(
+		"trak.mdia.minf.stbl.stz2.sampleCount",
+		(MP4Property**)&m_pStszSampleCountProperty);
+	  success &= m_pTrakAtom->FindProperty(
+		"trak.mdia.minf.stbl.stz2.entries.entrySize",
+		(MP4Property**)&m_pStszSampleSizeProperty);
+	  MP4Integer8Property *stz2_field_size;
+	  if (m_pTrakAtom->FindProperty(
+					"trak.mdia.minf.stbl.stz2.fieldSize",
+					(MP4Property **)&stz2_field_size)) {
+	    m_stsz_sample_bits = stz2_field_size->GetValue();
+	    m_have_stz2_4bit_sample = false;
+	  } else success = false;
+	}
+	  
 
 	// get handles on information needed to map sample id's to file offsets
 
@@ -199,12 +224,13 @@
 	}
 
 	// edit list
-	InitEditListProperties();
+	(void)InitEditListProperties();
 
 	// was everything found?
 	if (!success) {
 		throw new MP4Error("invalid track", "MP4Track::MP4Track");
 	}
+	CalculateBytesPerSample();
 }
 
 MP4Track::~MP4Track()
@@ -220,7 +246,8 @@
 
 void MP4Track::SetType(const char* type) 
 {
-	m_pTypeProperty->SetValue(NormalizeTrackType(type));
+	m_pTypeProperty->SetValue(MP4NormalizeTrackType(type,
+							m_pFile->GetVerbosity()));
 }
 
 void MP4Track::ReadSample(
@@ -368,7 +395,7 @@
 	if (m_isAmr == AMR_UNINITIALIZED ) {
 		// figure out if this is an AMR audio track
 		if (m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.samr") ||
-				m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.sawb")) {
+		    m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd.sawb")) {
 			m_isAmr = AMR_TRUE;
 			m_curMode = (pBytes[0] >> 3) & 0x000F;
 		} else {
@@ -396,6 +423,7 @@
 	// append sample bytes to chunk buffer
 	m_pChunkBuffer = (u_int8_t*)MP4Realloc(m_pChunkBuffer, 
 		m_chunkBufferSize + numBytes);
+	if (m_pChunkBuffer == NULL) return;
 	memcpy(&m_pChunkBuffer[m_chunkBufferSize], pBytes, numBytes);
 	m_chunkBufferSize += numBytes;
 	m_chunkSamples++;
@@ -409,8 +437,7 @@
 
 	UpdateSyncSamples(m_writeSampleId, isSyncSample);
 
-	if ((m_isAmr == AMR_FALSE) &&
-		IsChunkFull(m_writeSampleId)) {
+	if (IsChunkFull(m_writeSampleId)) {
 		WriteChunkBuffer();
 		m_curMode = curMode;
 	}
@@ -457,6 +484,14 @@
 	// write out any remaining samples in chunk buffer
 	WriteChunkBuffer();
 
+	if (m_pStszFixedSampleSizeProperty == NULL &&
+	    m_stsz_sample_bits == 4) {
+	  if (m_have_stz2_4bit_sample) {
+	    ((MP4Integer8Property *)m_pStszSampleSizeProperty)->AddValue(m_stz2_4bit_sample_value);
+	    m_pStszSampleSizeProperty->IncrementValue();
+	  }
+	}
+
 	// record buffer size and bitrates
 	MP4BitfieldProperty* pBufferSizeProperty;
 
@@ -498,23 +533,36 @@
 
 u_int32_t MP4Track::GetSampleSize(MP4SampleId sampleId)
 {
+  if (m_pStszFixedSampleSizeProperty != NULL) {
 	u_int32_t fixedSampleSize = 
 		m_pStszFixedSampleSizeProperty->GetValue(); 
 
 	if (fixedSampleSize != 0) {
-		return fixedSampleSize;
+	  return fixedSampleSize * m_bytesPerSample;
 	}
-	return m_pStszSampleSizeProperty->GetValue(sampleId - 1);
+  }
+  // will have to check for 4 bit sample size here
+  if (m_stsz_sample_bits == 4) {
+    uint8_t value = m_pStszSampleSizeProperty->GetValue((sampleId - 1) / 2);
+    if ((sampleId - 1) / 2 == 0) {
+      value >>= 4;
+    } else value &= 0xf;
+    return m_bytesPerSample * value;
+  }
+  return m_bytesPerSample * 
+    m_pStszSampleSizeProperty->GetValue(sampleId - 1);
 }
 
 u_int32_t MP4Track::GetMaxSampleSize()
 {
+  if (m_pStszFixedSampleSizeProperty != NULL) {
 	u_int32_t fixedSampleSize = 
 		m_pStszFixedSampleSizeProperty->GetValue(); 
 
 	if (fixedSampleSize != 0) {
-		return fixedSampleSize;
+		return fixedSampleSize * m_bytesPerSample;
 	}
+  }
 
 	u_int32_t maxSampleSize = 0;
 	u_int32_t numSamples = m_pStszSampleSizeProperty->GetCount();
@@ -525,18 +573,24 @@
 			maxSampleSize = sampleSize;
 		}
 	}
-	return maxSampleSize;
+	return maxSampleSize * m_bytesPerSample;
 }
 
 u_int64_t MP4Track::GetTotalOfSampleSizes()
 {
+  uint64_t retval;
+  if (m_pStszFixedSampleSizeProperty != NULL) {
 	u_int32_t fixedSampleSize = 
 		m_pStszFixedSampleSizeProperty->GetValue(); 
 
 	// if fixed sample size, just need to multiply by number of samples
 	if (fixedSampleSize != 0) {
-		return fixedSampleSize * GetNumberOfSamples();
+	  retval = m_bytesPerSample;
+	  retval *= fixedSampleSize;
+	  retval *= GetNumberOfSamples();
+	  return retval;
 	}
+  }
 
 	// else non-fixed sample size, sum them
 	u_int64_t totalSampleSizes = 0;
@@ -546,46 +600,105 @@
 			m_pStszSampleSizeProperty->GetValue(sid - 1);
 		totalSampleSizes += sampleSize;
 	}
-	return totalSampleSizes;
+	return totalSampleSizes * m_bytesPerSample;
 }
 
+void MP4Track::SampleSizePropertyAddValue (uint32_t size)
+{
+  // this has to deal with different sample size values
+  switch (m_pStszSampleSizeProperty->GetType()) {
+  case Integer32Property:
+    ((MP4Integer32Property *)m_pStszSampleSizeProperty)->AddValue(size);
+    break;
+  case Integer16Property:
+    ((MP4Integer16Property *)m_pStszSampleSizeProperty)->AddValue(size);
+    break;
+  case Integer8Property:
+    if (m_stsz_sample_bits == 4) {
+      if (m_have_stz2_4bit_sample == false) {
+	m_have_stz2_4bit_sample = true;
+	m_stz2_4bit_sample_value = size << 4;
+	return;
+      } else {
+	m_have_stz2_4bit_sample = false;
+	size &= 0xf;
+	size |= m_stz2_4bit_sample_value;
+      }
+    }
+    ((MP4Integer8Property *)m_pStszSampleSizeProperty)->AddValue(size);
+    break;
+  default: break;
+  }
+
+
+  //  m_pStszSampleSizeProperty->IncrementValue();
+}
+
 void MP4Track::UpdateSampleSizes(MP4SampleId sampleId, u_int32_t numBytes)
 {
+  if (m_bytesPerSample > 1) {
+    if ((numBytes % m_bytesPerSample) != 0) {
+      // error
+      VERBOSE_ERROR(m_pFile->GetVerbosity(), 
+		    printf("UpdateSampleSize: numBytes %u not divisible by bytesPerSample %u sampleId %u\n", 
+			   numBytes, m_bytesPerSample, sampleId);
+		    );
+    }
+    numBytes /= m_bytesPerSample;
+  }
 	// for first sample
-	if (sampleId == 1) {
-		if (numBytes > 0) {
-			// presume sample size is fixed
-			m_pStszFixedSampleSizeProperty->SetValue(numBytes); 
-		} else {
-			// special case of first sample is zero bytes in length
-			// leave m_pStszFixedSampleSizeProperty at 0
-			// start recording variable sample sizes
-			m_pStszSampleSizeProperty->AddValue(0);
-		}
-
+	// wmay - if we are adding, we want to make sure that
+	// we don't inadvertently set up the fixed size again.
+	// so, we check the number of samples
+	if (sampleId == 1 && GetNumberOfSamples() == 0) {
+	  if (m_pStszFixedSampleSizeProperty == NULL ||
+	      numBytes == 0) {
+	    // special case of first sample is zero bytes in length
+	    // leave m_pStszFixedSampleSizeProperty at 0
+	    // start recording variable sample sizes
+	    if (m_pStszFixedSampleSizeProperty != NULL)
+	      m_pStszFixedSampleSizeProperty->SetValue(0); 
+	    SampleSizePropertyAddValue(0);
+	  } else {
+	    // presume sample size is fixed
+	    m_pStszFixedSampleSizeProperty->SetValue(numBytes); 
+	  }
 	} else { // sampleId > 1
-		u_int32_t fixedSampleSize = 
-			m_pStszFixedSampleSizeProperty->GetValue(); 
 
-		if (fixedSampleSize == 0 || numBytes != fixedSampleSize) {
-			// sample size is not fixed
+	  u_int32_t fixedSampleSize = 0;
+	  if (m_pStszFixedSampleSizeProperty != NULL) {
+	    fixedSampleSize = m_pStszFixedSampleSizeProperty->GetValue(); 
+	  }
 
-			if (fixedSampleSize) {
-				// need to clear fixed sample size
-				m_pStszFixedSampleSizeProperty->SetValue(0); 
-
-				// and create sizes for all previous samples
-				for (MP4SampleId sid = 1; sid < sampleId; sid++) {
-					m_pStszSampleSizeProperty->AddValue(fixedSampleSize);
-				}
-			}
-
-			// add size value for this sample
-			m_pStszSampleSizeProperty->AddValue(numBytes);
-		}
+	  // if we don't have a fixed size, or the current sample size
+	  // doesn't match our sample size, we need to write the current
+	  // sample size into the table
+	  if (fixedSampleSize == 0 || numBytes != fixedSampleSize) {
+	    if (fixedSampleSize != 0) {
+	      // fixed size was set; we need to clear fixed sample size
+	      m_pStszFixedSampleSizeProperty->SetValue(0); 
+	      
+	      // and create sizes for all previous samples
+	      // use GetNumberOfSamples due to needing the total number
+	      // not just the appended part of the file
+	      uint32_t samples = GetNumberOfSamples();
+	      for (MP4SampleId sid = 1; sid <= samples; sid++) {
+		SampleSizePropertyAddValue(fixedSampleSize);
+	      }
+	    }
+	    // add size value for this sample
+	    SampleSizePropertyAddValue(numBytes);
+	  }
 	}
-
+	// either way, we increment the number of samples.
 	m_pStszSampleCountProperty->IncrementValue();
+#if 0
+	printf("track %u sample id %u bytes %u fixed %u count %u prop %u\n", 
+	       m_trackId, sampleId, numBytes,
+	       m_pStszFixedSampleSizeProperty->GetValue(),
+	       m_pStszSampleSizeProperty->GetCount(),
+	       m_pStszSampleCountProperty->GetValue());
+#endif
 }
 
 u_int32_t MP4Track::GetAvgBitrate()
@@ -594,14 +707,13 @@
 		return 0;
 	}
 
-	u_int64_t durationSecs =
-		MP4ConvertTime(GetDuration(), GetTimeScale(), MP4_SECS_TIME_SCALE);
-
-	if (GetDuration() % GetTimeScale() != 0) {
-		durationSecs++;
-	}
-
-	return (GetTotalOfSampleSizes() * 8) / durationSecs;
+	double calc = UINT64_TO_DOUBLE(GetTotalOfSampleSizes());
+	// this is a bit better - we use the whole duration
+	calc *= 8.0;
+	calc *= GetTimeScale();
+	calc /=	UINT64_TO_DOUBLE(GetDuration());
+	// we might want to think about rounding to the next 100 or 1000
+	return (uint32_t) ceil(calc);
 }
 
 u_int32_t MP4Track::GetMaxBitrate()
@@ -610,34 +722,50 @@
 	MP4SampleId numSamples = GetNumberOfSamples();
 	u_int32_t maxBytesPerSec = 0;
 	u_int32_t bytesThisSec = 0;
-	MP4Timestamp thisSec = 0;
+	MP4Timestamp thisSecStart = 0;
+	MP4Timestamp lastSampleTime = 0;
+	uint32_t lastSampleSize = 0;
 
+	MP4SampleId thisSecStartSid = 1;
 	for (MP4SampleId sid = 1; sid <= numSamples; sid++) {
-		u_int32_t sampleSize;
-		MP4Timestamp sampleTime;
+	  uint32_t sampleSize;
+	  MP4Timestamp sampleTime;
 
-		sampleSize = GetSampleSize(sid);
+	  sampleSize = GetSampleSize(sid);
+	  GetSampleTimes(sid, &sampleTime, NULL);
+	  
+	  if (sampleTime < thisSecStart + timeScale) {
+	    bytesThisSec += sampleSize;
+	    lastSampleSize = sampleSize;
+	    lastSampleTime = sampleTime;
+	  } else {
+	    // we've already written the last sample and sampleSize.
+	    // this means that we've probably overflowed the last second
+	    // calculate the time we've overflowed
+	    MP4Duration overflow_dur = 
+	      (thisSecStart + timeScale) - lastSampleTime;
+	    // calculate the duration of the last sample
+	    MP4Duration lastSampleDur = sampleTime - lastSampleTime;
+	    uint32_t overflow_bytes;
+	    // now, calculate the number of bytes we overflowed.  Round up.
+	    overflow_bytes = 
+	      ((lastSampleSize * overflow_dur) + (lastSampleDur - 1)) / lastSampleDur;
 
-		GetSampleTimes(sid, &sampleTime, NULL);
+	    if (bytesThisSec - overflow_bytes > maxBytesPerSec) {
+	      maxBytesPerSec = bytesThisSec - overflow_bytes;
+	    }
 
-		// sample counts for current second
-		if (sampleTime < thisSec + timeScale) {
-			bytesThisSec += sampleSize;
-		} else { // sample is in a future second
-			if (bytesThisSec > maxBytesPerSec) {
-				maxBytesPerSec = bytesThisSec;
-			}
-
-			thisSec = sampleTime - (sampleTime % timeScale);
-			bytesThisSec = sampleSize;
-		}
+	    // now adjust the values for this sample.  Remove the bytes
+	    // from the first sample in this time frame
+	    lastSampleTime = sampleTime;
+	    lastSampleSize = sampleSize;
+	    bytesThisSec += sampleSize;
+	    bytesThisSec -= GetSampleSize(thisSecStartSid);
+	    thisSecStartSid++;
+	    GetSampleTimes(thisSecStartSid, &thisSecStart, NULL);
+	  }
 	}
 
-	// last second (or partial second) 
-	if (bytesThisSec > maxBytesPerSec) {
-		maxBytesPerSec = bytesThisSec;
-	}
-
 	return maxBytesPerSec * 8;
 }
 
@@ -687,11 +815,11 @@
 	ASSERT(pStsdEntryAtom);
 
 	MP4Integer16Property* pDrefIndexProperty = NULL;
-	pStsdEntryAtom->FindProperty(
-		"*.dataReferenceIndex",
-		(MP4Property**)&pDrefIndexProperty);
+	if (!pStsdEntryAtom->FindProperty(
+					 "*.dataReferenceIndex",
+					 (MP4Property**)&pDrefIndexProperty) ||
 	
-	if (pDrefIndexProperty == NULL) {
+	    pDrefIndexProperty == NULL) {
 		throw new MP4Error("invalid stsd entry", "GetSampleFile");
 	}
 
@@ -712,9 +840,9 @@
 		pFile = NULL;	// self-contained
 	} else {
 		MP4StringProperty* pLocationProperty = NULL;
-		pUrlAtom->FindProperty(
-			"*.location", 
-			(MP4Property**)&pLocationProperty);
+		ASSERT(pUrlAtom->FindProperty(
+					      "*.location", 
+					      (MP4Property**)&pLocationProperty));
 		ASSERT(pLocationProperty);
 
 		const char* url = pLocationProperty->GetValue();
@@ -756,6 +884,9 @@
 	u_int32_t stscIndex =
 		GetSampleStscIndex(sampleId);
 
+	// firstChunk is the chunk index of the first chunk with 
+	// samplesPerChunk samples in the chunk.  There may be multiples -
+	// ie: several chunks with the same number of samples per chunk.
 	u_int32_t firstChunk = 
 		m_pStscFirstChunkProperty->GetValue(stscIndex);
 
@@ -765,9 +896,12 @@
 	u_int32_t samplesPerChunk = 
 		m_pStscSamplesPerChunkProperty->GetValue(stscIndex);
 
+	// chunkId tells which is the absolute chunk number that this sample
+	// is stored in.
 	MP4ChunkId chunkId = firstChunk +
 		((sampleId - firstSample) / samplesPerChunk);
 
+	// chunkOffset is the file offset (absolute) for the start of the chunk
 	u_int64_t chunkOffset = m_pChunkOffsetProperty->GetValue(chunkId - 1);
 
 	MP4SampleId firstSampleInChunk = 
@@ -827,16 +961,16 @@
 	return m_pSttsSampleDeltaProperty->GetValue(0);
 }
 
-bool MP4Track::SetFixedSampleDuration(MP4Duration duration)
+void MP4Track::SetFixedSampleDuration(MP4Duration duration)
 {
 	u_int32_t numStts = m_pSttsCountProperty->GetValue();
 
 	// setting this is only allowed before samples have been written
 	if (numStts != 0) {
-		return false;
+		return;
 	}
 	m_fixedSampleDuration = duration;
-	return true;
+	return;
 }
 
 void MP4Track::GetSampleTimes(MP4SampleId sampleId,
@@ -843,10 +977,20 @@
 	MP4Timestamp* pStartTime, MP4Duration* pDuration)
 {
 	u_int32_t numStts = m_pSttsCountProperty->GetValue();
-	MP4SampleId sid = 1;
-	MP4Duration elapsed = 0;
+	MP4SampleId sid;
+	MP4Duration elapsed;
+	
+	
+	if (m_cachedSttsSid != MP4_INVALID_SAMPLE_ID && sampleId >= m_cachedSttsSid) {
+		sid	  = m_cachedSttsSid;
+		elapsed	  = m_cachedSttsElapsed;
+	} else {
+		m_cachedSttsIndex = 0;
+		sid	  = 1;
+		elapsed	  = 0;
+	}
 
-	for (u_int32_t sttsIndex = 0; sttsIndex < numStts; sttsIndex++) {
+	for (u_int32_t sttsIndex = m_cachedSttsIndex; sttsIndex < numStts; sttsIndex++) {
 		u_int32_t sampleCount = 
 			m_pSttsSampleCountProperty->GetValue(sttsIndex);
 		u_int32_t sampleDelta = 
@@ -861,6 +1005,11 @@
 			if (pDuration) {
 				*pDuration = sampleDelta;
 			}
+
+			m_cachedSttsIndex = sttsIndex;
+			m_cachedSttsSid = sid;
+			m_cachedSttsElapsed = elapsed;
+
 			return;
 		}
 		sid += sampleCount;
@@ -987,17 +1136,17 @@
 		MP4Atom* pCttsAtom = AddAtom("trak.mdia.minf.stbl", "ctts");
 
 		// and get handles on the properties
-		pCttsAtom->FindProperty(
+		ASSERT(pCttsAtom->FindProperty(
 			"ctts.entryCount",
-			(MP4Property**)&m_pCttsCountProperty);
+			(MP4Property**)&m_pCttsCountProperty));
 
-		pCttsAtom->FindProperty(
+		ASSERT(pCttsAtom->FindProperty(
 			"ctts.entries.sampleCount",
-			(MP4Property**)&m_pCttsSampleCountProperty);
+			(MP4Property**)&m_pCttsSampleCountProperty));
 
-		pCttsAtom->FindProperty(
+		ASSERT(pCttsAtom->FindProperty(
 			"ctts.entries.sampleOffset",
-			(MP4Property**)&m_pCttsSampleOffsetProperty);
+			(MP4Property**)&m_pCttsSampleOffsetProperty));
 
 		// if this is not the first sample
 		if (sampleId > 1) {
@@ -1132,8 +1281,11 @@
 	}
 
 	u_int32_t numStss = m_pStssCountProperty->GetValue();
+	u_int32_t stssLIndex = 0;
+	u_int32_t stssRIndex = numStss - 1;
 	
-	for (u_int32_t stssIndex = 0; stssIndex < numStss; stssIndex++) {
+	while (stssRIndex >= stssLIndex){
+		u_int32_t stssIndex = (stssRIndex + stssLIndex) >> 1;
 		MP4SampleId syncSampleId = 
 			m_pStssSampleProperty->GetValue(stssIndex);
 
@@ -1140,8 +1292,11 @@
 		if (sampleId == syncSampleId) {
 			return true;
 		} 
-		if (sampleId < syncSampleId) {
-			break;
+
+		if (sampleId > syncSampleId) {
+			stssLIndex = stssIndex + 1;
+		} else {
+			stssRIndex = stssIndex - 1;
 		}
 	}
 
@@ -1174,34 +1329,35 @@
 
 void MP4Track::UpdateSyncSamples(MP4SampleId sampleId, bool isSyncSample)
 {
-	if (isSyncSample) {
-		// if stss atom exists, add entry
-		if (m_pStssCountProperty) {
-			m_pStssSampleProperty->AddValue(sampleId);
-			m_pStssCountProperty->IncrementValue();
-		} // else nothing to do (yet)
+  if (isSyncSample) {
+    // if stss atom exists, add entry
+    if (m_pStssCountProperty) {
+      m_pStssSampleProperty->AddValue(sampleId);
+      m_pStssCountProperty->IncrementValue();
+    } // else nothing to do (yet)
 
-	} else { // !isSyncSample
-		// if stss atom doesn't exist, create one
-		if (m_pStssCountProperty == NULL) {
+  } else { // !isSyncSample
+    // if stss atom doesn't exist, create one
+    if (m_pStssCountProperty == NULL) {
 
-			MP4Atom* pStssAtom = AddAtom("trak.mdia.minf.stbl", "stss");
+      MP4Atom* pStssAtom = AddAtom("trak.mdia.minf.stbl", "stss");
 
-			pStssAtom->FindProperty(
-				"stss.entryCount",
-				(MP4Property**)&m_pStssCountProperty);
+      ASSERT(pStssAtom->FindProperty(
+			      "stss.entryCount",
+			      (MP4Property**)&m_pStssCountProperty));
+		  
+      ASSERT(pStssAtom->FindProperty(
+			      "stss.entries.sampleNumber",
+			      (MP4Property**)&m_pStssSampleProperty));
 
-			pStssAtom->FindProperty(
-				"stss.entries.sampleNumber",
-				(MP4Property**)&m_pStssSampleProperty);
-
-			// set values for all samples that came before this one
-			for (MP4SampleId sid = 1; sid < sampleId; sid++) {
-				m_pStssSampleProperty->AddValue(sid);
-				m_pStssCountProperty->IncrementValue();
-			}
-		} // else nothing to do
-	}
+      // set values for all samples that came before this one
+      uint32_t samples = GetNumberOfSamples();
+      for (MP4SampleId sid = 1; sid < samples; sid++) {
+	m_pStssSampleProperty->AddValue(sid);
+	m_pStssCountProperty->IncrementValue();
+      }
+    } // else nothing to do
+  }
 }
 
 MP4Atom* MP4Track::AddAtom(char* parentName, char* childName)
@@ -1379,87 +1535,51 @@
 
 // map track type name aliases to official names
 
-const char* MP4Track::NormalizeTrackType(const char* type)
-{
-	if (!strcasecmp(type, "vide")
-	  || !strcasecmp(type, "video")
-	  || !strcasecmp(type, "mp4v")
-	  || !strcasecmp(type, "s263")	// 3GPP H.263
-	  || !strcasecmp(type, "encv")) {
-		return MP4_VIDEO_TRACK_TYPE;
-	}
 
-	if (!strcasecmp(type, "soun")
-	  || !strcasecmp(type, "sound")
-	  || !strcasecmp(type, "audio")
-	  || !strcasecmp(type, "enca") 
-	  || !strcasecmp(type, "samr")	// 3GPP AMR 
-	  || !strcasecmp(type, "sawb")	// 3GPP AMR/WB
-	  || !strcasecmp(type, "mp4a")) {
-		return MP4_AUDIO_TRACK_TYPE;
-	}
-
-	if (!strcasecmp(type, "sdsm")
-	  || !strcasecmp(type, "scene")
-	  || !strcasecmp(type, "bifs")) {
-		return MP4_SCENE_TRACK_TYPE;
-	}
-
-	if (!strcasecmp(type, "odsm")
-	  || !strcasecmp(type, "od")) {
-		return MP4_OD_TRACK_TYPE;
-	}
-
-	return type;
-}
-
 bool MP4Track::InitEditListProperties()
 {
-	m_pElstCountProperty = NULL;
-	m_pElstMediaTimeProperty = NULL;
-	m_pElstDurationProperty = NULL;
-	m_pElstRateProperty = NULL;
-	m_pElstReservedProperty = NULL;
+  m_pElstCountProperty = NULL;
+  m_pElstMediaTimeProperty = NULL;
+  m_pElstDurationProperty = NULL;
+  m_pElstRateProperty = NULL;
+  m_pElstReservedProperty = NULL;
 
-	MP4Atom* pElstAtom =
-		m_pTrakAtom->FindAtom("trak.edts.elst");
+  MP4Atom* pElstAtom =
+    m_pTrakAtom->FindAtom("trak.edts.elst");
 
-	if (!pElstAtom) {
-		return false;
-	}
+  if (!pElstAtom) {
+    return false;
+  }
 
-	pElstAtom->FindProperty(
-		"elst.entryCount",
-		(MP4Property**)&m_pElstCountProperty);
+  (void)pElstAtom->FindProperty(
+				"elst.entryCount",
+				(MP4Property**)&m_pElstCountProperty);
+  (void)pElstAtom->FindProperty(
+				"elst.entries.mediaTime",
+				(MP4Property**)&m_pElstMediaTimeProperty);
+  (void)pElstAtom->FindProperty(
+				"elst.entries.segmentDuration",
+				(MP4Property**)&m_pElstDurationProperty);
+  (void)pElstAtom->FindProperty(
+				"elst.entries.mediaRate",
+				(MP4Property**)&m_pElstRateProperty);
 
-	pElstAtom->FindProperty(
-		"elst.entries.mediaTime",
-		(MP4Property**)&m_pElstMediaTimeProperty);
+  (void)pElstAtom->FindProperty(
+				"elst.entries.reserved",
+				(MP4Property**)&m_pElstReservedProperty);
 
-	pElstAtom->FindProperty(
-		"elst.entries.segmentDuration",
-		(MP4Property**)&m_pElstDurationProperty);
-
-	pElstAtom->FindProperty(
-		"elst.entries.mediaRate",
-		(MP4Property**)&m_pElstRateProperty);
-
-	pElstAtom->FindProperty(
-		"elst.entries.reserved",
-		(MP4Property**)&m_pElstReservedProperty);
-
-	return m_pElstCountProperty
-		&& m_pElstMediaTimeProperty
-		&& m_pElstDurationProperty
-		&& m_pElstRateProperty
-		&& m_pElstReservedProperty;
+  return m_pElstCountProperty
+    && m_pElstMediaTimeProperty
+    && m_pElstDurationProperty
+    && m_pElstRateProperty
+    && m_pElstReservedProperty;
 }
 
 MP4EditId MP4Track::AddEdit(MP4EditId editId)
 {
 	if (!m_pElstCountProperty) {
-		m_pFile->AddDescendantAtoms(m_pTrakAtom, "edts.elst");
-		InitEditListProperties();
+	  (void)m_pFile->AddDescendantAtoms(m_pTrakAtom, "edts.elst");
+	  if (InitEditListProperties() == false) return MP4_INVALID_EDIT_ID;
 	}
 
 	if (editId == MP4_INVALID_EDIT_ID) {
@@ -1668,3 +1788,23 @@
 	return sampleId;
 }
 
+void MP4Track::CalculateBytesPerSample ()
+{
+  MP4Atom *pMedia = m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd");
+  MP4Atom *pMediaData;
+  const char *media_data_name;
+  if (pMedia == NULL) return;
+
+  if (pMedia->GetNumberOfChildAtoms() != 1) return;
+  
+  pMediaData = pMedia->GetChildAtom(0);
+  media_data_name = pMediaData->GetType();
+  if ((ATOMID(media_data_name) == ATOMID("twos")) ||
+      (ATOMID(media_data_name) == ATOMID("sowt"))) {
+    MP4IntegerProperty *chan, *sampleSize;
+    chan = (MP4IntegerProperty *)pMediaData->GetProperty(4);
+    sampleSize = (MP4IntegerProperty *)pMediaData->GetProperty(5);
+    m_bytesPerSample = chan->GetValue() * (sampleSize->GetValue() / 8);
+  }
+}
+  
--- a/common/mp4v2/mp4track.h
+++ b/common/mp4v2/mp4track.h
@@ -93,7 +93,7 @@
 	u_int32_t	GetMaxBitrate();	// in bps
 
 	MP4Duration GetFixedSampleDuration();
-	bool		SetFixedSampleDuration(MP4Duration duration);
+	void		SetFixedSampleDuration(MP4Duration duration);
 
 	void		GetSampleTimes(MP4SampleId sampleId,
 					MP4Timestamp* pStartTime, MP4Duration* pDuration);
@@ -125,8 +125,6 @@
 		MP4Timestamp* pStartTime = NULL, 
 		MP4Duration* pDuration = NULL);
 
-	static const char* NormalizeTrackType(const char* type);
-
 	// special operation for use during hint track packet assembly
 	void ReadSampleFragment(
 		MP4SampleId sampleId,
@@ -179,6 +177,7 @@
 
 	void WriteChunkBuffer();
 
+	void CalculateBytesPerSample();
 protected:
 	MP4File*	m_pFile;
 	MP4Atom* 	m_pTrakAtom;		// moov.trak[]
@@ -205,6 +204,8 @@
 	u_int32_t 	m_samplesPerChunk;
 	MP4Duration m_durationPerChunk;
 
+	u_int32_t       m_bytesPerSample;
+
 	// controls for AMR chunking
 	int		m_isAmr;
 	u_int8_t	m_curMode;
@@ -217,7 +218,12 @@
 
 	MP4Integer32Property* m_pStszFixedSampleSizeProperty;
 	MP4Integer32Property* m_pStszSampleCountProperty;
-	MP4Integer32Property* m_pStszSampleSizeProperty;
+	
+	void SampleSizePropertyAddValue(uint32_t bytes);
+	uint8_t m_stsz_sample_bits;
+	bool m_have_stz2_4bit_sample;
+	uint8_t m_stz2_4bit_sample_value;
+	MP4IntegerProperty* m_pStszSampleSizeProperty;
 
 	MP4Integer32Property* m_pStscCountProperty;
 	MP4Integer32Property* m_pStscFirstChunkProperty;
@@ -231,6 +237,11 @@
 	MP4Integer32Property* m_pSttsCountProperty;
 	MP4Integer32Property* m_pSttsSampleCountProperty;
 	MP4Integer32Property* m_pSttsSampleDeltaProperty;
+
+	// for improve sequental timestamp index access
+	u_int32_t	m_cachedSttsIndex;
+	MP4SampleId	m_cachedSttsSid;
+	MP4Timestamp	m_cachedSttsElapsed;
 
 	MP4Integer32Property* m_pCttsCountProperty;
 	MP4Integer32Property* m_pCttsSampleCountProperty;
--- a/common/mp4v2/mp4util.cpp
+++ b/common/mp4v2/mp4util.cpp
@@ -13,20 +13,30 @@
  * 
  * 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.
+ * Copyright (C) Cisco Systems Inc. 2001-2005.  All Rights Reserved.
  * 
  * Contributor(s): 
  *		Dave Mackie		[email protected]
+ *              Bill May                [email protected]
  */
 
 #include "mp4common.h"
-#ifdef __MINGW32__
-/* We need tolower() declaration */
-#include <ctype.h>
-#endif /* #ifdef __MINGW32__ */
 
+static lib_message_func_t libfunc = NULL;
+extern "C"   void MP4SetLibFunc(lib_message_func_t libf)
+{
+  libfunc = libf;
+}
+
 void MP4Error::Print(FILE* pFile)
 {
+  if (libfunc != NULL) {
+    (libfunc)(LOG_ERR, "MP4ERROR", "%s:%s:%s",
+	      m_where == NULL ? "" : m_where, 
+	      m_errstring == NULL ? "" : m_errstring,
+	      m_errno ? strerror(m_errno) : "");
+    return;
+  } 
 	fprintf(pFile, "MP4ERROR: ");
 	if (m_where) {
 		fprintf(pFile, "%s", m_where);
@@ -153,12 +163,12 @@
 	if (dataSize) {
 		ASSERT(pData);
 	}
+	uint size = 2 * dataSize + 1;
+	char* s = (char*)MP4Calloc(size);
 
-	char* s = (char*)MP4Calloc((2 * dataSize) + 1);
-
 	u_int32_t i, j;
 	for (i = 0, j = 0; i < dataSize; i++) {
-		sprintf(&s[j], "%02x", pData[i]);
+		size -= snprintf(&s[j], size, "%02x", pData[i]);
 		j += 2;
 	}
 
@@ -167,11 +177,9 @@
 
 char* MP4ToBase64(const u_int8_t* pData, u_int32_t dataSize)
 {
-	if (dataSize) {
-		ASSERT(pData);
-	}
+  if (pData == NULL || dataSize == 0) return NULL;
 
-	static char encoding[64] = {
+	static const char encoding[64] = {
 		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
 		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
 		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
@@ -181,6 +189,7 @@
 	char* s = (char*)MP4Calloc((((dataSize + 2) * 4) / 3) + 1);
 
 	const u_int8_t* src = pData;
+	if (pData == NULL) return NULL;
 	char* dest = s;
 	u_int32_t numGroups = dataSize / 3;
 
@@ -203,10 +212,77 @@
 		*dest++ = encoding[((src[1] & 0x0F) << 2)];
 		*dest++ = '=';
 	}
-
+	*dest = '\0';
 	return s;	/* N.B. caller is responsible for free'ing s */
 }
 
+static bool convertBase64 (const char data, uint8_t *value)
+{
+  static const uint8_t decodingarr64[128] = {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+    0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+    0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+    0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+    0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+    0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
+  };
+  uint8_t index = (uint8_t)data;
+  if ((index & 0x80) != 0) return false;
+
+  if (decodingarr64[index] == 0xff) return false;
+  *value = decodingarr64[index];
+  return true;
+}
+
+uint8_t *Base64ToBinary (const char *pData, uint32_t decodeSize, uint32_t *pDataSize)
+{
+  uint8_t *ret;
+  uint32_t size, ix, groups;
+  if (pData == NULL ||  decodeSize == 0 || pDataSize == NULL) 
+    return NULL;
+
+ if ((decodeSize % 4) != 0) {
+    // must be multiples of 4 characters
+    return NULL;
+  }
+  size = (decodeSize * 3) / 4;
+  groups = decodeSize / 4;
+  ret = (uint8_t *)MP4Calloc(size);
+  if (ret == NULL) return NULL;
+  for (ix = 0; ix < groups; ix++) {
+    uint8_t value[4];
+    for (uint8_t jx = 0; jx < 4; jx++) {
+      if (pData[jx] == '=') {
+	if (ix != (groups - 1)) {
+	  free(ret);
+	  return NULL;
+	}
+	size--;
+	value[jx] = 0;
+      } else if (convertBase64(pData[jx], &value[jx]) == false) {
+	free(ret);
+	return NULL;
+      }
+    }
+    ret[(ix * 3)] = value[0] << 2 | ((value[1] >> 4) & 0x3);
+    ret[(ix * 3) + 1] = (value[1] << 4) | (value[2] >> 2 & 0xf);
+    ret[(ix * 3) + 2] = ((value[2] & 0x3) << 6) | value[3];
+    pData += 4;
+  }
+  *pDataSize = size;
+  return ret;
+}
+
 // log2 of value, rounded up
 static u_int8_t ilog2(u_int64_t value)
 {
@@ -228,6 +304,8 @@
 		throw new MP4Error("division by zero", "MP4ConvertTime");
 	}
 
+	if (oldTimeScale == newTimeScale) return t;
+
 	// check if we can safely use integer operations
 	if (ilog2(t) + ilog2(newTimeScale) <= 64) {
 		return (t * newTimeScale) / oldTimeScale;
@@ -234,9 +312,51 @@
 	}
 
 	// final resort is to use floating point
-	double d = ((double)newTimeScale / (double)oldTimeScale) + 0.5;
+	double d = (double)newTimeScale;
 	d *= UINT64_TO_DOUBLE(t);
+	d /= (double)oldTimeScale;	
+	d += 0.5; // round up.
 
 	return (u_int64_t)d;
 }
 
+const char* MP4NormalizeTrackType (const char* type,
+				   uint32_t verbosity)
+{
+	if (!strcasecmp(type, "vide")
+	  || !strcasecmp(type, "video")
+	  || !strcasecmp(type, "mp4v")
+	  || !strcasecmp(type, "avc1")
+	  || !strcasecmp(type, "s263")	// 3GPP H.263
+	  || !strcasecmp(type, "encv")) {
+		return MP4_VIDEO_TRACK_TYPE;
+	}
+
+	if (!strcasecmp(type, "soun")
+	  || !strcasecmp(type, "sound")
+	  || !strcasecmp(type, "audio")
+	  || !strcasecmp(type, "enca") 
+	  || !strcasecmp(type, "samr")	// 3GPP AMR 
+	  || !strcasecmp(type, "sawb")	// 3GPP AMR/WB
+	  || !strcasecmp(type, "mp4a")) {
+		return MP4_AUDIO_TRACK_TYPE;
+	}
+
+	if (!strcasecmp(type, "sdsm")
+	  || !strcasecmp(type, "scene")
+	  || !strcasecmp(type, "bifs")) {
+		return MP4_SCENE_TRACK_TYPE;
+	}
+
+	if (!strcasecmp(type, "odsm")
+	  || !strcasecmp(type, "od")) {
+		return MP4_OD_TRACK_TYPE;
+	}
+	if (strcasecmp(type, "cntl") == 0) {
+	  return MP4_CNTL_TRACK_TYPE;
+	}
+	VERBOSE_WARNING(verbosity,
+			printf("Attempt to normalize %s did not match\n",
+			       type));
+	return type;
+}
--- a/common/mp4v2/mp4util.h
+++ b/common/mp4v2/mp4util.h
@@ -24,19 +24,11 @@
 #include <assert.h>
 
 #ifndef ASSERT
-#ifdef NDEBUG
-#define ASSERT(expr)
-#else
 #define ASSERT(expr) \
 	if (!(expr)) { \
-		fflush(stdout); \
-		assert((expr)); \
+		throw new MP4Error("assert failure", __STRING((expr))); \
 	}
 #endif
-#endif
-#ifdef NDEBUG
-#define WARNING(expr)
-#else
 #define WARNING(expr) \
 	if (expr) { \
 		fflush(stdout); \
@@ -43,7 +35,6 @@
 		fprintf(stderr, "Warning (%s) in %s at line %u\n", \
 			__STRING(expr), __FILE__, __LINE__); \
 	}
-#endif
 
 #define VERBOSE(exprverbosity, verbosity, expr)	\
 	if (((exprverbosity) & (verbosity)) == (exprverbosity)) { expr; }
@@ -172,6 +163,7 @@
 	FILE* pFile = stdout, u_int8_t indent = 0);
 
 inline void* MP4Malloc(size_t size) {
+  if (size == 0) return NULL;
 	void* p = malloc(size);
 	if (p == NULL && size > 0) {
 		throw new MP4Error(errno);
@@ -180,6 +172,7 @@
 }
 
 inline void* MP4Calloc(size_t size) {
+  if (size == 0) return NULL;
 	return memset(MP4Malloc(size), 0, size);
 }
 
@@ -189,6 +182,14 @@
 	return s2;
 }
 
+#ifdef _WIN32
+inline wchar_t* MP4Stralloc(const wchar_t* s1) {
+	wchar_t* s2 = (wchar_t*)MP4Malloc((wcslen(s1) + 1)*sizeof(wchar_t));
+	wcscpy(s2, s1);
+	return s2;
+}
+#endif
+
 inline void* MP4Realloc(void* p, u_int32_t newSize) {
 	// workaround library bug
 	if (p == NULL && newSize == 0) {
@@ -201,17 +202,13 @@
 	return p;
 }
 
-inline void MP4Free(void* p) {
-	free(p);
-}
-
 inline u_int32_t STRTOINT32(const char* s) {
-	return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+  return ntohl(*(uint32_t *)s);
 }
 
 inline void INT32TOSTR(u_int32_t i, char* s) {
-	s[0] = ((i >> 24) & 0xFF); s[1] = ((i >> 16) & 0xFF); 
-	s[2] = ((i >> 8) & 0xFF); s[3] = (i & 0xFF); s[4] = 0;
+  *(uint32_t *)s = htonl(i);
+  s[4] = 0;
 }
 
 inline MP4Timestamp MP4GetAbsTimestamp() {
@@ -238,5 +235,8 @@
 char* MP4ToBase16(const u_int8_t* pData, u_int32_t dataSize);
 
 char* MP4ToBase64(const u_int8_t* pData, u_int32_t dataSize);
+
+const char* MP4NormalizeTrackType(const char* type,
+				  uint32_t verbosity);
 
 #endif /* __MP4_UTIL_INCLUDED__ */
--- a/common/mp4v2/mpeg4ip.h
+++ b/common/mp4v2/mpeg4ip.h
@@ -13,10 +13,11 @@
  * 
  * The Initial Developer of the Original Code is Cisco Systems Inc.
  * Portions created by Cisco Systems Inc. are
- * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
+ * Copyright (C) Cisco Systems Inc. 2000-2005.  All Rights Reserved.
  * 
  * Contributor(s): 
  *		Dave Mackie		[email protected]
+ *              Bill May                [email protected]
  */
 
 #ifndef __MPEG4IP_INCLUDED__
@@ -25,123 +26,41 @@
 /* project wide applicable stuff here */
 
 
-#ifdef _WIN32
-#define HAVE_IN_PORT_T
-#define HAVE_SOCKLEN_T
-#define NEED_SDL_VIDEO_IN_MAIN_THREAD
+#ifndef _WIN32
+#ifdef PACKAGE_BUGREPORT
+#define TEMP_PACKAGE_BUGREPORT PACKAGE_BUGREPORT
+#define TEMP_PACKAGE_NAME PACKAGE_NAME
+#define TEMP_PACKAGE_STRING PACKAGE_STRING
+#define TEMP_PACKAGE_TARNAME PACKAGE_TARNAME
+#define TEMP_PACKAGE_VERSION PACKAGE_VERSION
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#include <mpeg4ip_config.h>
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#define PACKAGE_BUGREPORT TEMP_PACKAGE_BUGREPORT
+#define PACKAGE_NAME TEMP_PACKAGE_NAME
+#define PACKAGE_STRING TEMP_PACKAGE_STRING
+#define PACKAGE_TARNAME TEMP_PACKAGE_TARNAME
+#define PACKAGE_VERSION TEMP_PACKAGE_VERSION
 #else
-#undef PACKAGE
-#undef VERSION
 #include <mpeg4ip_config.h>
-#undef PACKAGE
-#undef VERSION
-// so these don't propogate
 #endif
+#endif
 
 // the mpeg4ip_package and mpeg4ip_version are always in this
 // file 
 #include "mpeg4ip_version.h"
 
-
-
-
 #ifdef _WIN32
-
-#define _WIN32_WINNT 0x0400
-#define _WINSOCKAPI_
-#include <windows.h>
-#include <winsock2.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-#include <limits.h>
-
-typedef unsigned __int64 uint64_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int64 u_int64_t;
-typedef unsigned __int32 u_int32_t;
-typedef unsigned __int16 u_int16_t;
-typedef unsigned __int8 u_int8_t;
-typedef __int64 int64_t;
-typedef __int32 int32_t;
-typedef __int16 int16_t;
-typedef __int8  int8_t;
-typedef unsigned short in_port_t;
-typedef int socklen_t;
-#ifndef __MINGW32__
-/* Let's avoid some boring conflicting declarations */
-typedef int ssize_t;
-#endif /* #ifndef __MINGW32__ */
-#define snprintf _snprintf
-#define strncasecmp _strnicmp
-#define strcasecmp _stricmp
-
-#include <io.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#define write _write
-#define lseek _lseek
-#define close _close
-#define open _open
-#define access _access
-#define vsnprintf _vsnprintf
-#define F_OK 0
-#define OPEN_RDWR (_O_RDWR | _O_BINARY)
-#define OPEN_CREAT (_O_CREAT | _O_BINARY)
-#define OPEN_RDONLY (_O_RDONLY | _O_BINARY)
-#define srandom srand
-#define random rand
-
-#define IOSBINARY ios::binary
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-int gettimeofday(struct timeval *t, void *);
-#ifdef __cplusplus
-}
-#endif
-
-#define PATH_MAX MAX_PATH
-#define MAX_UINT64 -1
-#define D64F "I64d"
-#define U64F  "I64u"
-#define X64F "I64x"
-
-#define TO_D64(a) (a##I64)
-#define TO_U64(a) (a##UI64)
-
-#define LOG_EMERG 0
-#define LOG_ALERT 1
-#define LOG_CRIT 2
-#define LOG_ERR 3
-#define LOG_WARNING 4
-#define LOG_NOTICE 5
-#define LOG_INFO 6
-#define LOG_DEBUG 7
-
-#ifdef __MINGW32__
-#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)(fpos)
-#define VAR_TO_FPOS(fpos, var) (fpos) = (var)
-#elif     !__STDC__ && _INTEGRAL_MAX_BITS >= 64
-#define VAR_TO_FPOS(fpos, var) (fpos) = (var)
-#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)(_FPOSOFF(fpos))
-#else
-#define VAR_TO_FPOS(fpos, var) (fpos).lopart = ((var) & UINT_MAX); (fpos).hipart = ((var) >> 32)
-#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)((uint64_t)((fpos).hipart ) << 32 | (fpos).lopart)
-#endif /* #ifdef __MINGW32__ */
-
-
-#define __STRING(expr) #expr
-
-#define FOPEN_READ_BINARY "rb"
-#define FOPEN_WRITE_BINARY "wb"
-
-#define UINT64_TO_DOUBLE(a) ((double)((int64_t)(a)))
+#include "mpeg4ip_win32.h"
+#include "mpeg4ip_version.h"
 #else /* UNIX */
 /*****************************************************************************
  *   UNIX LIKE DEFINES BELOW THIS POINT
@@ -201,6 +120,14 @@
 #endif
 #include <sys/param.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+char *strcasestr(const char *haystack, const char *needle);
+#ifdef __cplusplus
+}
+#endif
+
 #define OPEN_RDWR O_RDWR
 #define OPEN_CREAT O_CREAT 
 #define OPEN_RDONLY O_RDONLY
@@ -214,7 +141,7 @@
 #define U64F  "lu"
 #define X64F "lx"
 
-#define TO_D64(a) (a##LD)
+#define TO_D64(a) (a##L)
 #define TO_U64(a) (a##LU)
 #else
 #define MAX_UINT64 -1LLU
@@ -222,7 +149,7 @@
 #define U64F  "llu"
 #define X64F "llx"
 
-#define TO_D64(a) (a##LLD)
+#define TO_D64(a) (a##LL)
 #define TO_U64(a) (a##LLU)
 #endif
 
@@ -343,9 +270,29 @@
 #endif
 
 #ifndef __cplusplus
+
 #ifndef bool
-typedef unsigned char 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
 
 #ifndef ROUND
@@ -369,6 +316,26 @@
 
 #ifndef UINT64_MAX
 # define UINT64_MAX TO_U64(0xffffffffffffffff)
+#endif
+
+typedef enum audio_format_t {
+  AUDIO_FMT_U8 = 0,
+  AUDIO_FMT_S8,
+  AUDIO_FMT_U16LSB,
+  AUDIO_FMT_S16LSB,
+  AUDIO_FMT_U16MSB,
+  AUDIO_FMT_S16MSB,
+  AUDIO_FMT_U16,
+  AUDIO_FMT_S16,
+  AUDIO_FMT_FLOAT,
+  AUDIO_FMT_HW_AC3,
+} audio_format_t;
+
+#ifndef HAVE_STRUCT_IOVEC
+struct iovec {
+  void *iov_base;
+  unsigned int iov_len;
+};
 #endif
 
 #endif /* __MPEG4IP_INCLUDED__ */
--- a/common/mp4v2/mpeg4ip_version.h
+++ b/common/mp4v2/mpeg4ip_version.h
@@ -1,2 +1,6 @@
 #define MPEG4IP_PACKAGE "mpeg4ip"
-#define MPEG4IP_VERSION "1.1.3"
+#define MPEG4IP_VERSION "1.6.1"
+#define MPEG4IP_MAJOR_VERSION 0x1
+#define MPEG4IP_MINOR_VERSION 0x6
+#define MPEG4IP_CVS_VERSION 0x1
+#define MPEG4IP_HEX_VERSION ((MPEG4IP_MAJOR_VERSION << 16) | (MPEG4IP_MINOR_VERSION << 8) | MPEG4IP_CVS_VERSION)
--- /dev/null
+++ b/common/mp4v2/mpeg4ip_win32.h
@@ -1,0 +1,178 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2005.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Bill May [email protected]
+ */
+/* windows defines */
+#ifndef __MPEG4IP_WIN32_H__
+#define __MPEG4IP_WIN32_H__
+#define HAVE_IN_PORT_T
+#define HAVE_SOCKLEN_T
+#define NEED_SDL_VIDEO_IN_MAIN_THREAD
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#define _WINSOCKAPI_
+#define _INTEGRAL_MAX_BITS 64
+#ifndef __GNUC__
+#define _CRT_SECURE_NO_DEPRECATE 1
+#ifndef _WIN32
+#define _WIN32
+#endif
+#endif
+#include <windows.h>
+#include <winsock2.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <limits.h>
+
+#ifndef inline
+#define inline __inline
+#endif
+typedef unsigned __int64 uint64_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int64 u_int64_t;
+typedef unsigned __int32 u_int32_t;
+typedef unsigned __int16 u_int16_t;
+typedef unsigned __int8 u_int8_t;
+typedef signed __int64 int64_t;
+typedef signed __int32 int32_t;
+typedef signed __int16 int16_t;
+typedef signed __int8  int8_t;
+typedef unsigned short in_port_t;
+typedef int socklen_t;
+typedef int ssize_t;
+typedef unsigned int uint;
+static inline int snprintf(char *buffer, size_t count,
+			  const char *format, ...) {
+  va_list ap;
+  int ret;
+  va_start(ap, format);
+  ret = vsnprintf_s(buffer, count, _TRUNCATE, format, ap);
+  va_end(ap);
+  if (ret == -1) {
+    if (errno == EINVAL) return -1;
+    return (int)count;
+  }
+  return ret;
+}
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+#define localtime_r(a,b) localtime_s(b,a)
+#define printf printf_s
+#define fprintf fprintf_s
+
+#include <io.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef __GNUC__
+#define read _read
+#define write _write
+#define lseek _lseek
+#define close _close
+#define open _open
+#define access _access
+#define vsnprintf _vsnprintf
+#define stat _stati64
+#define fstat _fstati64
+#define fileno _fileno
+#define strdup _strdup
+#endif
+#define F_OK 0
+#define OPEN_RDWR (_O_RDWR | _O_BINARY)
+#define OPEN_CREAT (_O_CREAT | _O_BINARY)
+#define OPEN_RDONLY (_O_RDONLY | _O_BINARY)
+#define srandom srand
+#define random rand
+
+#define IOSBINARY ios::binary
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int gettimeofday(struct timeval *t, void *);
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX MAX_PATH
+#endif
+#define MAX_UINT64 -1
+
+#define D64F "I64d"
+#define U64F  "I64u"
+#define X64F "I64x"
+
+#define TO_D64(a) (a##I64)
+#define TO_U64(a) (a##UI64)
+
+#define LOG_EMERG 0
+#define LOG_ALERT 1
+#define LOG_CRIT 2
+#define LOG_ERR 3
+#define LOG_WARNING 4
+#define LOG_NOTICE 5
+#define LOG_INFO 6
+#define LOG_DEBUG 7
+
+#if     defined (__GNUC__) || (!__STDC__ && _INTEGRAL_MAX_BITS >= 64)
+#define VAR_TO_FPOS(fpos, var) (fpos) = (var)
+#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)(fpos)
+#else
+#define VAR_TO_FPOS(fpos, var) (fpos).lopart = ((var) & UINT_MAX); (fpos).hipart = ((var) >> 32)
+#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)((uint64_t)((fpos).hipart ) << 32 | (fpos).lopart)
+#endif
+
+#define __STRING(expr) #expr
+
+#define FOPEN_READ_BINARY "rb"
+#define FOPEN_WRITE_BINARY "wb"
+
+#define UINT64_TO_DOUBLE(a) ((double)((int64_t)(a)))
+#ifdef __cplusplus
+extern "C" {
+#endif
+char *strcasestr(const char *haystack, const char *needle);
+#ifdef __cplusplus
+}
+#endif
+
+
+#define SIZEOF_BOOL 1
+
+#ifndef __GNUC__
+#ifndef _SS_PAD1SIZE
+struct sockaddr_storage {
+	unsigned short ss_family;
+	uint32_t ss_align;
+	char __ss_padding[128 - 2 * sizeof(uint32_t)];
+};
+#endif
+#pragma warning(disable : 4244)
+#pragma warning(disable: 4996)
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+#define HAVE_INET_PTON 1
+#define HAVE_INET_NTOP 1
+#endif
+#endif
--- a/common/mp4v2/qosqualifiers.cpp
+++ b/common/mp4v2/qosqualifiers.cpp
@@ -20,7 +20,51 @@
  */
 
 #include "mp4common.h"
+#if 1
+MP4QosDescriptorBase::MP4QosDescriptorBase (u_int8_t tag)
+  : MP4Descriptor(tag)
+{
+  switch (tag) {
+  case MP4QosDescrTag:
+	AddProperty( /* 0 */
+		new MP4Integer8Property("predefined"));
+	AddProperty( /* 1 */
+		new MP4QosQualifierProperty("qualifiers",
+					    MP4QosTagsStart, 
+					    MP4QosTagsEnd, Optional, Many));
+	break;
+  case MP4MaxDelayQosTag:
+	AddProperty( /* 0 */
+		new MP4Integer32Property("maxDelay"));
+	break;
+  case MP4PrefMaxDelayQosTag:
+	AddProperty( /* 0 */
+		new MP4Integer32Property("prefMaxDelay"));
+	break;
+  case MP4LossProbQosTag:
+	AddProperty( /* 0 */
+		new MP4Float32Property("lossProb"));
+	break;
+  case MP4MaxGapLossQosTag:
+	AddProperty( /* 0 */
+		new MP4Integer32Property("maxGapLoss"));
+	break;
+  case MP4MaxAUSizeQosTag:
+	AddProperty( /* 0 */
+		new MP4Integer32Property("maxAUSize"));
+	break;
+  case MP4AvgAUSizeQosTag:
+	AddProperty( /* 0 */
+		    new MP4Integer32Property("avgAUSize"));
+	break;
+  case MP4MaxAURateQosTag:
+	AddProperty( /* 0 */
+		new MP4Integer32Property("maxAURate"));
+	break;
+  }
+}
 
+#else
 MP4QosDescriptor::MP4QosDescriptor()
 	: MP4Descriptor(MP4QosDescrTag)
 {
@@ -79,9 +123,9 @@
 	AddProperty( /* 0 */
 		new MP4Integer32Property("maxAURate"));
 }
-
+#endif
 MP4UnknownQosQualifier::MP4UnknownQosQualifier()
-	: MP4QosQualifier()
+	: MP4Descriptor()
 {
 	AddProperty( /* 0 */
 		new MP4BytesProperty("data"));
@@ -100,8 +144,8 @@
 MP4Descriptor* MP4QosQualifierProperty::CreateDescriptor(u_int8_t tag) 
 {
 	MP4Descriptor* pDescriptor = NULL;
-
 	switch (tag) {
+#if 0
 	case MP4MaxDelayQosTag:
 		pDescriptor = new MP4MaxDelayQosQualifier();
 		break;
@@ -123,6 +167,17 @@
 	case MP4MaxAURateQosTag:
 		pDescriptor = new MP4MaxAURateQosQualifier();
 		break;
+#else
+	case MP4MaxDelayQosTag:
+	case MP4PrefMaxDelayQosTag:
+	case MP4LossProbQosTag:
+	case MP4MaxGapLossQosTag:
+	case MP4MaxAUSizeQosTag:
+	case MP4AvgAUSizeQosTag:
+	case MP4MaxAURateQosTag:
+	  pDescriptor = new MP4QosDescriptorBase(tag);
+	  break;
+#endif
 	default:
 		pDescriptor = new MP4UnknownQosQualifier();
 		pDescriptor->SetTag(tag);
--- a/common/mp4v2/qosqualifiers.h
+++ b/common/mp4v2/qosqualifiers.h
@@ -24,6 +24,7 @@
 
 const u_int8_t MP4QosDescrTag			 	= 0x0C; 
 
+#if 0
 class MP4QosDescriptor : public MP4Descriptor {
 public:
 	MP4QosDescriptor();
@@ -30,6 +31,7 @@
 };
 
 typedef MP4Descriptor MP4QosQualifier;
+#endif
 
 const u_int8_t MP4QosTagsStart				= 0x01; 
 const u_int8_t MP4MaxDelayQosTag			= 0x01; 
@@ -41,6 +43,7 @@
 const u_int8_t MP4MaxAURateQosTag			= 0x43; 
 const u_int8_t MP4QosTagsEnd				= 0xFF; 
 
+#if 0
 class MP4MaxDelayQosQualifier : public MP4QosQualifier {
 public:
 	MP4MaxDelayQosQualifier();
@@ -75,8 +78,14 @@
 public:
 	MP4MaxAURateQosQualifier();
 };
+#else
+class MP4QosDescriptorBase : public MP4Descriptor {
+ public:
+  MP4QosDescriptorBase(uint8_t tag);
+};
 
-class MP4UnknownQosQualifier : public MP4QosQualifier {
+#endif
+class MP4UnknownQosQualifier : public MP4Descriptor {
 public:
 	MP4UnknownQosQualifier();
 	void Read(MP4File* pFile);
--- a/common/mp4v2/rtphint.cpp
+++ b/common/mp4v2/rtphint.cpp
@@ -73,7 +73,7 @@
 {
 	if (m_pRefTrack == NULL) {
 		MP4Integer32Property* pRefTrackIdProperty = NULL;
-		m_pTrakAtom->FindProperty(
+		(void)m_pTrakAtom->FindProperty(
 			"trak.tref.hint.entries[0].trackId",
 			(MP4Property**)&pRefTrackIdProperty);
 		ASSERT(pRefTrackIdProperty);
@@ -85,12 +85,12 @@
 void MP4RtpHintTrack::InitRtpStart() 
 {
 	struct timeval tv;
-	gettimeofday(&tv, NULL);
+	(void)gettimeofday(&tv, NULL);
 	srandom((tv.tv_usec << 12) | (tv.tv_sec & 0xFFF));
 
 	ASSERT(m_pTrakAtom);
 
-	m_pTrakAtom->FindProperty(
+	(void)m_pTrakAtom->FindProperty(
 		"trak.udta.hnti.rtp .snro.offset",
 		(MP4Property**)&m_pSnroProperty);
 
@@ -100,7 +100,7 @@
 		m_rtpSequenceStart = random();
 	}
 
-	m_pTrakAtom->FindProperty(
+	(void)m_pTrakAtom->FindProperty(
 		"trak.udta.hnti.rtp .tsro.offset",
 		(MP4Property**)&m_pTsroProperty);
 
@@ -274,7 +274,7 @@
 
 		ASSERT(pTsroAtom);
 
-		pTsroAtom->FindProperty("offset",
+		(void)pTsroAtom->FindProperty("offset",
 			(MP4Property**)&m_pTsroProperty);
 
 		ASSERT(m_pTsroProperty);
@@ -289,19 +289,19 @@
 	ASSERT(m_pTrakAtom);
 
 	if (m_pRtpMapProperty == NULL) {
-		m_pTrakAtom->FindProperty(
+	  (void)m_pTrakAtom->FindProperty(
 			"trak.udta.hinf.payt.rtpMap",
 			(MP4Property**)&m_pRtpMapProperty);
 	}
 
 	if (m_pPayloadNumberProperty == NULL) {
-		m_pTrakAtom->FindProperty(
+	  (void)m_pTrakAtom->FindProperty(
 			"trak.udta.hinf.payt.payloadNumber",
 			(MP4Property**)&m_pPayloadNumberProperty);
 	}
 
 	if (m_pMaxPacketSizeProperty == NULL) {
-		m_pTrakAtom->FindProperty(
+	  (void)m_pTrakAtom->FindProperty(
 			"trak.mdia.minf.stbl.stsd.rtp .maxPacketSize",
 			(MP4Property**)&m_pMaxPacketSizeProperty);
 	}
@@ -314,7 +314,7 @@
 	char **ppEncodingParams)
 {
   const char* pRtpMap;
-  char* pSlash;
+  const char* pSlash;
   u_int32_t length;
 	InitPayload();
 
@@ -325,7 +325,7 @@
 	    *ppEncodingParams = NULL;
 		if (m_pRtpMapProperty) {
 			pRtpMap = m_pRtpMapProperty->GetValue();
-			pSlash = strchr((char*)pRtpMap, '/');
+			pSlash = strchr(pRtpMap, '/');
 
 			if (pSlash) {
 				length = pSlash - pRtpMap;
@@ -395,7 +395,7 @@
 	}
 
 	char* rtpMapBuf = (char*)MP4Malloc(len);
-	sprintf(rtpMapBuf, "%s/%u%c%s", 
+	snprintf(rtpMapBuf, len, "%s/%u%c%s", 
 		payloadName, 
 		GetTimeScale(),
 		encoding_parms != NULL ? '/' : '\0',
@@ -415,31 +415,34 @@
 		sdpMediaType = "audio";
 	} else if (!strcmp(m_pRefTrack->GetType(), MP4_VIDEO_TRACK_TYPE)) {
 		sdpMediaType = "video";
+	} else if (!strcmp(m_pRefTrack->GetType(), MP4_CNTL_TRACK_TYPE)) {
+	  sdpMediaType = "control";
 	} else {
 		sdpMediaType = "application";
 	}
 
-	char* sdpBuf = (char*)MP4Malloc(
-		strlen(sdpMediaType) + strlen(rtpMapBuf) + 256);
+	uint32_t maxlen = 
+	  strlen(sdpMediaType) + strlen(rtpMapBuf) + 256;
+	char* sdpBuf = (char*)MP4Malloc(maxlen);
 	uint32_t buflen;
-	buflen = sprintf(sdpBuf, 
+	buflen = snprintf(sdpBuf, maxlen,
 			 "m=%s 0 RTP/AVP %u\015\012"
 			 "a=control:trackID=%u\015\012",
 			 sdpMediaType, payloadNumber,
 			 m_trackId);
 	if (include_rtp_map) {
-	  buflen += sprintf(sdpBuf + buflen, 
+	  buflen += snprintf(sdpBuf + buflen, maxlen - buflen, 
 			    "a=rtpmap:%u %s\015\012",
 			    payloadNumber, rtpMapBuf);
 	}
 	if (include_mpeg4_esid) {
-	  sprintf(sdpBuf + buflen, 
+	  snprintf(sdpBuf + buflen, maxlen - buflen,
 		  "a=mpeg4-esid:%u\015\012",
 		  m_pRefTrack->GetId());
 	}
 
 	MP4StringProperty* pSdpProperty = NULL;
-	m_pTrakAtom->FindProperty("trak.udta.hnti.sdp .sdpText",
+	(void)m_pTrakAtom->FindProperty("trak.udta.hnti.sdp .sdpText",
 		(MP4Property**)&pSdpProperty);
 	ASSERT(pSdpProperty);
 	pSdpProperty->SetValue(sdpBuf);
@@ -673,26 +676,26 @@
 
 	ASSERT(pHinfAtom);
 
-	pHinfAtom->FindProperty("hinf.trpy.bytes", (MP4Property**)&m_pTrpy); 
-	pHinfAtom->FindProperty("hinf.nump.packets", (MP4Property**)&m_pNump); 
-	pHinfAtom->FindProperty("hinf.tpyl.bytes", (MP4Property**)&m_pTpyl); 
-	pHinfAtom->FindProperty("hinf.maxr.bytes", (MP4Property**)&m_pMaxr); 
-	pHinfAtom->FindProperty("hinf.dmed.bytes", (MP4Property**)&m_pDmed); 
-	pHinfAtom->FindProperty("hinf.dimm.bytes", (MP4Property**)&m_pDimm); 
-	pHinfAtom->FindProperty("hinf.pmax.bytes", (MP4Property**)&m_pPmax); 
-	pHinfAtom->FindProperty("hinf.dmax.milliSecs", (MP4Property**)&m_pDmax); 
+	(void)pHinfAtom->FindProperty("hinf.trpy.bytes", (MP4Property**)&m_pTrpy); 
+	(void)pHinfAtom->FindProperty("hinf.nump.packets", (MP4Property**)&m_pNump); 
+	(void)pHinfAtom->FindProperty("hinf.tpyl.bytes", (MP4Property**)&m_pTpyl); 
+	(void)pHinfAtom->FindProperty("hinf.maxr.bytes", (MP4Property**)&m_pMaxr); 
+	(void)pHinfAtom->FindProperty("hinf.dmed.bytes", (MP4Property**)&m_pDmed); 
+	(void)pHinfAtom->FindProperty("hinf.dimm.bytes", (MP4Property**)&m_pDimm); 
+	(void)pHinfAtom->FindProperty("hinf.pmax.bytes", (MP4Property**)&m_pPmax); 
+	(void)pHinfAtom->FindProperty("hinf.dmax.milliSecs", (MP4Property**)&m_pDmax); 
 
 	MP4Atom* pHmhdAtom = m_pTrakAtom->FindAtom("trak.mdia.minf.hmhd");
 
 	ASSERT(pHmhdAtom);
 
-	pHmhdAtom->FindProperty("hmhd.maxPduSize", (MP4Property**)&m_pMaxPdu); 
-	pHmhdAtom->FindProperty("hmhd.avgPduSize", (MP4Property**)&m_pAvgPdu); 
-	pHmhdAtom->FindProperty("hmhd.maxBitRate", (MP4Property**)&m_pMaxBitRate); 
-	pHmhdAtom->FindProperty("hmhd.avgBitRate", (MP4Property**)&m_pAvgBitRate); 
+	(void)pHmhdAtom->FindProperty("hmhd.maxPduSize", (MP4Property**)&m_pMaxPdu); 
+	(void)pHmhdAtom->FindProperty("hmhd.avgPduSize", (MP4Property**)&m_pAvgPdu); 
+	(void)pHmhdAtom->FindProperty("hmhd.maxBitRate", (MP4Property**)&m_pMaxBitRate); 
+	(void)pHmhdAtom->FindProperty("hmhd.avgBitRate", (MP4Property**)&m_pAvgBitRate); 
 
 	MP4Integer32Property* pMaxrPeriod = NULL;
-	pHinfAtom->FindProperty("hinf.maxr.granularity",
+	(void)pHinfAtom->FindProperty("hinf.maxr.granularity",
 		 (MP4Property**)&pMaxrPeriod); 
 	if (pMaxrPeriod) {
 		pMaxrPeriod->SetValue(1000);	// 1 second
@@ -1093,7 +1096,7 @@
 		ASSERT(pTrakAtom);
 
 		MP4Integer32Property* pTrackIdProperty = NULL;
-		pTrakAtom->FindProperty(
+		(void)pTrakAtom->FindProperty(
 			"trak.tref.hint.entries",
 			(MP4Property**)&pTrackIdProperty);
 		ASSERT(pTrackIdProperty);
@@ -1317,7 +1320,7 @@
 		pSampleTrack->GetTrakAtom();
 
 	char sdName[64];
-	sprintf(sdName, "trak.mdia.minf.stbl.stsd.*[%u]", sampleDescrIndex);
+	snprintf(sdName, 64, "trak.mdia.minf.stbl.stsd.*[%u]", sampleDescrIndex);
 
 	MP4Atom* pSdAtom =
 		pTrakAtom->FindAtom(sdName);
--- /dev/null
+++ b/common/mp4v2/virtual_io.cpp
@@ -1,0 +1,92 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001 - 2005.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Ben Allison			benski at nullsoft.com
+ *
+ * Virtual I/O support, for file support other than fopen/fread/fwrite
+ */
+
+#include "mp4common.h"
+#include "virtual_io.h"
+
+/* --------- Virtual IO for FILE * --------- */
+
+u_int64_t FILE_GetFileLength(void *user)
+{
+	FILE *fp = (FILE *)user;
+	struct stat s;
+	if (fstat(fileno(fp), &s) < 0) { 
+		throw new MP4Error(errno, "stat failed", "MP4Open");
+	}
+	return s.st_size;
+}
+
+int FILE_SetPosition(void *user, u_int64_t position)
+{
+	FILE *fp = (FILE *)user;
+	fpos_t fpos;
+	VAR_TO_FPOS(fpos, position);
+	return fsetpos(fp, &fpos);
+}
+
+int FILE_GetPosition(void *user, u_int64_t *position)
+{
+	FILE *fp = (FILE *)user;
+	fpos_t fpos;
+	if (fgetpos(fp, &fpos) < 0) { 
+		throw new MP4Error(errno, "MP4GetPosition");
+	}
+	
+	FPOS_TO_VAR(fpos, u_int64_t, *position);
+	return 0;
+}
+
+size_t FILE_Read(void *user, void *buffer, size_t size)
+{
+	FILE *fp = (FILE *)user;
+	return fread(buffer, 1, size, fp);
+}
+
+size_t FILE_Write(void *user, void *buffer, size_t size)
+{
+	FILE *fp = (FILE *)user;
+	return fwrite(buffer, 1, size, fp); 
+}
+
+int FILE_EndOfFile(void *user)
+{
+	FILE *fp = (FILE *)user;
+	return feof(fp);
+}
+
+int FILE_Close(void *user)
+{
+	FILE *fp = (FILE *)user;
+	return fclose(fp);
+}
+
+Virtual_IO FILE_virtual_IO =
+{
+	FILE_GetFileLength,
+		FILE_SetPosition,
+		FILE_GetPosition,
+		FILE_Read,
+		FILE_Write,
+		FILE_EndOfFile,
+		FILE_Close,
+};
--- /dev/null
+++ b/common/mp4v2/virtual_io.h
@@ -1,0 +1,31 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ * 
+ * The Original Code is MPEG4IP.
+ * 
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001 - 2005.  All Rights Reserved.
+ * 
+ * Contributor(s): 
+ *		Ben Allison			benski at nullsoft.com
+ *
+ * Virtual I/O support, for file support other than fopen/fread/fwrite
+ */
+
+#ifndef __VIRTUAL_IO_INCLUDED__
+#define __VIRTUAL_IO_INCLUDED__
+
+#include "mpeg4ip.h"
+
+extern Virtual_IO FILE_virtual_IO;
+
+#endif
--- a/faac.dsw
+++ /dev/null
@@ -1,134 +1,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "FAAD"=.\plugins\cooledit\FAAD.DSP - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name libfaac
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name libfaad
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "faac"=.\frontend\faac.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name libfaac
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name libsndfile
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "faacgui"=.\frontend\faacgui.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name libfaac
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name libsndfile
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "libfaac"=.\libfaac\libfaac.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "libfaac_dll"=.\libfaac\libfaac_dll.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "libfaad"=..\faad\libfaad\libfaad.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "libsndfile"=.\common\libsndfile\Win32\libsndfile.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "out_FAAC"=.\plugins\winamp\out_FAAC.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name libfaac
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
--- a/frontend/faac.dsp
+++ /dev/null
@@ -1,123 +1,0 @@
-# Microsoft Developer Studio Project File - Name="faac" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=faac - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "faac.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "faac.mak" CFG="faac - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "faac - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "faac - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=xicl6.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "faac - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /O1 /I "../include" /I "../common/libsndfile/src" /I "../common/getopt" /I "../common/mp4v2" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD BASE RSC /l 0x413 /d "NDEBUG"
-# ADD RSC /l 0x413 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=xilink6.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /machine:I386
-# SUBTRACT LINK32 /profile /debug /nodefaultlib
-
-!ELSEIF  "$(CFG)" == "faac - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../include" /I "../common/libsndfile/src" /I "../common/getopt" /I "../common/mp4v2" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x413 /d "_DEBUG"
-# ADD RSC /l 0x413 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=xilink6.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "faac - Win32 Release"
-# Name "faac - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\input.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\main.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE="E:\Program Files\Microsoft Visual Studio\VC98\Include\BASETSD.H"
-# End Source File
-# Begin Source File
-
-SOURCE=..\include\faac.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\common\getopt\getopt.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\common\libsndfile\src\sndfile.h
-# End Source File
-# Begin Source File
-
-SOURCE="E:\Program Files\Microsoft Visual Studio\VC98\Include\sndfile.h"
-# End Source File
-# End Group
-# End Target
-# End Project
--- a/frontend/faac.dsw
+++ /dev/null
@@ -1,62 +1,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "faac"=.\faac.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name libfaac
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name libsndfile
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name libmp4v2_st
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "libfaac"=..\LIBFAAC\libfaac.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "libmp4v2_st"=..\common\mp4v2\libmp4v2_st60.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
--- a/frontend/faacgui.dsp
+++ /dev/null
@@ -1,140 +1,0 @@
-# Microsoft Developer Studio Project File - Name="faacgui" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=faacgui - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "faacgui.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "faacgui.mak" CFG="faacgui - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "faacgui - Win32 Release" (based on "Win32 (x86) Application")
-!MESSAGE "faacgui - Win32 Debug" (based on "Win32 (x86) Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "faacgui - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "faacgui___Win32_Release"
-# PROP BASE Intermediate_Dir "faacgui___Win32_Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "ReleaseGUI"
-# PROP Intermediate_Dir "ReleaseGUI"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../common/libsndfile/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x413 /d "NDEBUG"
-# ADD RSC /l 0x413 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
-# SUBTRACT LINK32 /profile /nodefaultlib
-
-!ELSEIF  "$(CFG)" == "faacgui - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "faacgui___Win32_Debug"
-# PROP BASE Intermediate_Dir "faacgui___Win32_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "DebugGUI"
-# PROP Intermediate_Dir "DebugGUI"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../include" /I "../common/libsndfile/src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x413 /d "_DEBUG"
-# ADD RSC /l 0x413 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "faacgui - Win32 Release"
-# Name "faacgui - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\input.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\maingui.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE="E:\Program Files\Microsoft Visual Studio\VC98\Include\BASETSD.H"
-# End Source File
-# Begin Source File
-
-SOURCE=..\include\faac.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\include\faaccfg.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\input.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\resource.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\common\libsndfile\src\sndfile.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# Begin Source File
-
-SOURCE=.\faacgui.rc
-# End Source File
-# End Group
-# End Target
-# End Project
--- a/frontend/faacgui.dsw
+++ /dev/null
@@ -1,47 +1,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "faacgui"=.\faacgui.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-    Begin Project Dependency
-    Project_Dep_Name libfaac
-    End Project Dependency
-    Begin Project Dependency
-    Project_Dep_Name libsndfile
-    End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "libfaac"=..\libfaac\libfaac.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
--- a/libfaac/libfaac.dsp
+++ /dev/null
@@ -1,208 +1,0 @@
-# Microsoft Developer Studio Project File - Name="libfaac" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=libfaac - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "libfaac.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "libfaac.mak" CFG="libfaac - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "libfaac - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "libfaac - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=xicl6.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "libfaac - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Target_Dir ""
-F90=df.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /G6 /MD /W3 /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x413 /d "NDEBUG"
-# ADD RSC /l 0x413 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF  "$(CFG)" == "libfaac - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Target_Dir ""
-F90=df.exe
-MTL=midl.exe
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x413 /d "_DEBUG"
-# ADD RSC /l 0x413 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF 
-
-# Begin Target
-
-# Name "libfaac - Win32 Release"
-# Name "libfaac - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\aacquant.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\backpred.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\bitstream.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\channels.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\fft.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\filtbank.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\frame.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\huffman.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\ltp.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\midside.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\psychkni.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\tns.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\util.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\aacquant.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\backpred.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\bitstream.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\channels.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\coder.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\fft.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\filtbank.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\frame.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\huffman.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\hufftab.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\joint.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ltp.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\psych.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\tns.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\util.h
-# End Source File
-# End Group
-# End Target
-# End Project
--- a/libfaac/libfaac_dll.dsp
+++ /dev/null
@@ -1,223 +1,0 @@
-# Microsoft Developer Studio Project File - Name="libfaac_dll" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=libfaac_dll - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "libfaac_dll.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "libfaac_dll.mak" CFG="libfaac_dll - Win32 Debug"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "libfaac_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "libfaac_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "libfaac_dll - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "ReleaseDLL"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBFAAC_DLL_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBFAAC_DLL_EXPORTS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x407 /d "NDEBUG"
-# ADD RSC /l 0x407 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 /nologo /dll /machine:I386 /out:"ReleaseDLL/libfaac.dll"
-
-!ELSEIF  "$(CFG)" == "libfaac_dll - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "libfaac_dll___Win32_Debug"
-# PROP BASE Intermediate_Dir "libfaac_dll___Win32_Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "DebugDLL"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBFAAC_DLL_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBFAAC_DLL_EXPORTS" /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x407 /d "_DEBUG"
-# ADD RSC /l 0x407 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /dll /debug /machine:I386 /out:"DebugDLL/libfaac.dll" /pdbtype:sept
-
-!ENDIF 
-
-# Begin Target
-
-# Name "libfaac_dll - Win32 Release"
-# Name "libfaac_dll - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\aacquant.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\backpred.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\bitstream.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\channels.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\fft.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\filtbank.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\frame.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\huffman.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\ltp.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\midside.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\psychkni.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\tns.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\util.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\aacquant.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\backpred.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\bitstream.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\channels.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\coder.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\faac\include\faaccfg.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\fft.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\filtbank.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\frame.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\huffman.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\hufftab.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\ltp.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\midside.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\psych.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\tns.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\util.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\version.h
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\libfaac.def
-# End Source File
-# End Target
-# End Project
--- a/libfaac/libfaac_dll.dsw
+++ /dev/null
@@ -1,29 +1,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "libfaac_dll"=.\libfaac_dll.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-