shithub: aacdec

Download patch

ref: b3b26efdbae258ed54d186bbfd0a4375128b2db1
parent: 4443c0c223baa34eeab013604a33e37cfeeaf519
author: menno <menno>
date: Sun Dec 29 05:46:50 EST 2002

Added mp4 tagging support (also to foo_mp4)

--- /dev/null
+++ b/common/mp4v2/atom_tag4.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. 2001.  All Rights Reserved.
+ *
+ * Contributor(s):
+ *      M. Bakker     menno@audiocoding.com
+ */
+
+#include "mp4common.h"
+
+MP4Tag4Atom::MP4Tag4Atom()
+    : MP4Atom("TAG4")
+{
+    AddVersionAndFlags();
+
+    MP4Integer32Property* pCount =
+        new MP4Integer32Property("entryCount");
+    AddProperty(pCount);
+
+    MP4TableProperty* pTable = new
+        MP4TableProperty("entries", pCount);
+    AddProperty(pTable);
+
+    pTable->AddProperty(
+        new MP4StringProperty("name"));
+    pTable->AddProperty(
+        new MP4StringProperty("value"));
+}
--- a/common/mp4v2/atoms.h
+++ b/common/mp4v2/atoms.h
@@ -443,4 +443,9 @@
 	void Write();
 };
 
+class MP4Tag4Atom : public MP4Atom {
+public:
+	MP4Tag4Atom();
+};
+
 #endif /* __MP4_ATOMS_INCLUDED__ */
--- a/common/mp4v2/libmp4v2_cb.dsp
+++ b/common/mp4v2/libmp4v2_cb.dsp
@@ -287,6 +287,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\atom_tag4.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\atom_tfhd.cpp
 # End Source File
 # Begin Source File
--- a/common/mp4v2/libmp4v2_cb.vcproj
+++ b/common/mp4v2/libmp4v2_cb.vcproj
@@ -33,7 +33,8 @@
 				ProgramDataBaseFileName=".\CB_Release/"
 				WarningLevel="3"
 				SuppressStartupBanner="TRUE"
-				CompileAs="0">
+				CompileAs="0"
+				AdditionalOptions="&lt;?ICLPrjArgs?&gt; /Qvc7 /Qlocation,link,&quot;E:\Program Files\Microsoft Visual Studio .NET\Vc7\Bin&quot; /c  /I &quot;.\\&quot; /nologo /W3 /O2 /Ob1 /Oy /D &quot;NDEBUG&quot; /D &quot;WIN32&quot; /D &quot;_WINDOWS&quot; /D &quot;USE_FILE_CALLBACKS&quot; /GF /FD /EHsc /MT /GS /Gy /YX&quot;StdAfx.h&quot; /Fp&quot;.\CB_Release/libmp4v2_cb.pch&quot; /Fo&quot;.\CB_Release/&quot; /Fd&quot;.\CB_Release/&quot; /Gd &lt;?/ICLPrjArgs?&gt; &lt;?IVCSpawnPrjArgs?&gt; #$UseNonIntelTool #$BinPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Bin;E:\Program Files\Common Files\Intel\Shared Files\IA32\Bin;E:\Program Files\Microsoft Visual Studio .NET\Common7\IDE&quot; #$LibPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Lib;E:\Program Files\Common Files\Intel\Shared Files\IA32\Lib&quot; #$IncPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Include&quot; &lt;?/IVCSpawnPrjArgs?&gt;">
 				<IntelOptions
 					Optimization="2"
 					InlineFuncExpansion="1"
@@ -42,7 +43,8 @@
 					RuntimeLibrary="0"
 					BufferSecurityCheck="1"
 					FunctionLevelLinking="1"
-					AllOptions="/c  /I &quot;.\\&quot; /nologo /W3 /O2 /Ob1 /Oy /D &quot;NDEBUG&quot; /D &quot;WIN32&quot; /D &quot;_WINDOWS&quot; /D &quot;USE_FILE_CALLBACKS&quot; /GF /FD /EHsc /MT /GS /Gy /YX&quot;StdAfx.h&quot; /Fp&quot;.\CB_Release/libmp4v2_cb.pch&quot; /Fo&quot;.\CB_Release/&quot; /Fd&quot;.\CB_Release/&quot; /Gd"/>
+					AllOptions="/c  /I &quot;.\\&quot; /nologo /W3 /O2 /Ob1 /Oy /D &quot;NDEBUG&quot; /D &quot;WIN32&quot; /D &quot;_WINDOWS&quot; /D &quot;USE_FILE_CALLBACKS&quot; /GF /FD /EHsc /MT /GS /Gy /YX&quot;StdAfx.h&quot; /Fp&quot;.\CB_Release/libmp4v2_cb.pch&quot; /Fo&quot;.\CB_Release/&quot; /Fd&quot;.\CB_Release/&quot; /Gd"
+					MSOriginalAdditionalOptions=""/>
 			</Tool>
 			<Tool
 				Name="VCCustomBuildTool"/>
@@ -49,9 +51,11 @@
 			<Tool
 				Name="VCLibrarianTool"
 				OutputFile=".\CB_Release\libmp4v2_cb.lib"
-				SuppressStartupBanner="TRUE">
+				SuppressStartupBanner="TRUE"
+				AdditionalOptions="&lt;?ICLPrjArgs?&gt; /OUT:&quot;.\CB_Release\libmp4v2_cb.lib&quot; /NOLOGO &lt;?/ICLPrjArgs?&gt; &lt;?IVCSpawnPrjArgs?&gt; #$UseNonIntelTool #$BinPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Bin;E:\Program Files\Common Files\Intel\Shared Files\IA32\Bin;E:\Program Files\Microsoft Visual Studio .NET\Common7\IDE&quot; #$LibPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Lib;E:\Program Files\Common Files\Intel\Shared Files\IA32\Lib&quot; #$IncPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Include&quot; &lt;?/IVCSpawnPrjArgs?&gt;">
 				<IntelOptions
-					AllOptions="/OUT:&quot;.\CB_Release\libmp4v2_cb.lib&quot; /NOLOGO"/>
+					AllOptions="/OUT:&quot;.\CB_Release\libmp4v2_cb.lib&quot; /NOLOGO"
+					MSOriginalAdditionalOptions=""/>
 			</Tool>
 			<Tool
 				Name="VCMIDLTool"/>
@@ -92,13 +96,15 @@
 				WarningLevel="3"
 				SuppressStartupBanner="TRUE"
 				DebugInformationFormat="4"
-				CompileAs="0">
+				CompileAs="0"
+				AdditionalOptions="&lt;?ICLPrjArgs?&gt; /Qvc7 /Qlocation,link,&quot;E:\Program Files\Microsoft Visual Studio .NET\Vc7\Bin&quot; /c  /I &quot;.\\&quot; /ZI /nologo /W3 /Od /D &quot;_DEBUG&quot; /D &quot;WIN32&quot; /D &quot;_WINDOWS&quot; /D &quot;USE_FILE_CALLBACKS&quot; /Gm /EHsc /RTC1 /MDd /YX&quot;StdAfx.h&quot; /Fp&quot;.\CB_Debug/libmp4v2_cb.pch&quot; /Fo&quot;.\CB_Debug/&quot; /Fd&quot;.\CB_Debug/&quot; /Gd &lt;?/ICLPrjArgs?&gt; &lt;?IVCSpawnPrjArgs?&gt; #$UseIntelTool #$BinPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Bin;E:\Program Files\Common Files\Intel\Shared Files\IA32\Bin;E:\Program Files\Microsoft Visual Studio .NET\Common7\IDE&quot; #$LibPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Lib;E:\Program Files\Common Files\Intel\Shared Files\IA32\Lib&quot; #$IncPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Include&quot; &lt;?/IVCSpawnPrjArgs?&gt;">
 				<IntelOptions
 					Optimization="0"
 					MinimalRebuild="1"
 					BasicRuntimeChecks="3"
 					RuntimeLibrary="3"
-					AllOptions="/c  /I &quot;.\\&quot; /ZI /nologo /W3 /Od /D &quot;_DEBUG&quot; /D &quot;WIN32&quot; /D &quot;_WINDOWS&quot; /D &quot;USE_FILE_CALLBACKS&quot; /Gm /EHsc /RTC1 /MDd /YX&quot;StdAfx.h&quot; /Fp&quot;.\CB_Debug/libmp4v2_cb.pch&quot; /Fo&quot;.\CB_Debug/&quot; /Fd&quot;.\CB_Debug/&quot; /Gd"/>
+					AllOptions="/c  /I &quot;.\\&quot; /ZI /nologo /W3 /Od /D &quot;_DEBUG&quot; /D &quot;WIN32&quot; /D &quot;_WINDOWS&quot; /D &quot;USE_FILE_CALLBACKS&quot; /Gm /EHsc /RTC1 /MDd /YX&quot;StdAfx.h&quot; /Fp&quot;.\CB_Debug/libmp4v2_cb.pch&quot; /Fo&quot;.\CB_Debug/&quot; /Fd&quot;.\CB_Debug/&quot; /Gd"
+					MSOriginalAdditionalOptions=""/>
 			</Tool>
 			<Tool
 				Name="VCCustomBuildTool"/>
@@ -105,9 +111,11 @@
 			<Tool
 				Name="VCLibrarianTool"
 				OutputFile=".\CB_Debug\libmp4v2_cb.lib"
-				SuppressStartupBanner="TRUE">
+				SuppressStartupBanner="TRUE"
+				AdditionalOptions="&lt;?ICLPrjArgs?&gt; /OUT:&quot;.\CB_Debug\libmp4v2_cb.lib&quot; /NOLOGO &lt;?/ICLPrjArgs?&gt; &lt;?IVCSpawnPrjArgs?&gt; #$UseIntelTool #$BinPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Bin;E:\Program Files\Common Files\Intel\Shared Files\IA32\Bin;E:\Program Files\Microsoft Visual Studio .NET\Common7\IDE&quot; #$LibPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Lib;E:\Program Files\Common Files\Intel\Shared Files\IA32\Lib&quot; #$IncPath:&quot;E:\Program Files\Intel\Compiler70\IA32\Include&quot; &lt;?/IVCSpawnPrjArgs?&gt;">
 				<IntelOptions
-					AllOptions="/OUT:&quot;.\CB_Debug\libmp4v2_cb.lib&quot; /NOLOGO"/>
+					AllOptions="/OUT:&quot;.\CB_Debug\libmp4v2_cb.lib&quot; /NOLOGO"
+					MSOriginalAdditionalOptions=""/>
 			</Tool>
 			<Tool
 				Name="VCMIDLTool"/>
@@ -229,6 +237,8 @@
 				RelativePath=".\atom_stsz.cpp"/>
 			<File
 				RelativePath=".\atom_stts.cpp"/>
+			<File
+				RelativePath="atom_tag4.cpp"/>
 			<File
 				RelativePath=".\atom_tfhd.cpp"/>
 			<File
--- a/common/mp4v2/libmp4v2_st60.dsp
+++ b/common/mp4v2/libmp4v2_st60.dsp
@@ -287,6 +287,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=.\atom_tag4.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\atom_tfhd.cpp
 # End Source File
 # Begin Source File
--- a/common/mp4v2/libmp4v2_st60.vcproj
+++ b/common/mp4v2/libmp4v2_st60.vcproj
@@ -33,8 +33,7 @@
 				ProgramDataBaseFileName=".\ST_Release/"
 				WarningLevel="3"
 				SuppressStartupBanner="TRUE"
-				CompileAs="0"
-				AdditionalOptions="">
+				CompileAs="0">
 				<IntelOptions
 					Optimization="2"
 					InlineFuncExpansion="1"
@@ -43,8 +42,7 @@
 					RuntimeLibrary="0"
 					BufferSecurityCheck="1"
 					FunctionLevelLinking="1"
-					AllOptions="/c  /I &quot;.\\&quot; /nologo /W3 /O2 /Ob1 /Oy /D &quot;WIN32&quot; /D &quot;NDEBUG&quot; /D &quot;_WINDOWS&quot; /GF /FD /EHsc /MT /GS /Gy /YX&quot;StdAfx.h&quot; /Fp&quot;.\ST_Release/libmp4v2_st60.pch&quot; /Fo&quot;.\ST_Release/&quot; /Fd&quot;.\ST_Release/&quot; /Gd"
-					MSOriginalAdditionalOptions=""/>
+					AllOptions="/c  /I &quot;.\\&quot; /nologo /W3 /O2 /Ob1 /Oy /D &quot;WIN32&quot; /D &quot;NDEBUG&quot; /D &quot;_WINDOWS&quot; /GF /FD /EHsc /MT /GS /Gy /YX&quot;StdAfx.h&quot; /Fp&quot;.\ST_Release/libmp4v2_st60.pch&quot; /Fo&quot;.\ST_Release/&quot; /Fd&quot;.\ST_Release/&quot; /Gd"/>
 			</Tool>
 			<Tool
 				Name="VCCustomBuildTool"/>
@@ -51,11 +49,9 @@
 			<Tool
 				Name="VCLibrarianTool"
 				OutputFile=".\ST_Release\libmp4v2_st60.lib"
-				SuppressStartupBanner="TRUE"
-				AdditionalOptions="">
+				SuppressStartupBanner="TRUE">
 				<IntelOptions
-					AllOptions="/OUT:&quot;.\ST_Release\libmp4v2_st60.lib&quot; /NOLOGO"
-					MSOriginalAdditionalOptions=""/>
+					AllOptions="/OUT:&quot;.\ST_Release\libmp4v2_st60.lib&quot; /NOLOGO"/>
 			</Tool>
 			<Tool
 				Name="VCMIDLTool"/>
@@ -94,15 +90,13 @@
 				WarningLevel="3"
 				SuppressStartupBanner="TRUE"
 				DebugInformationFormat="1"
-				CompileAs="0"
-				AdditionalOptions="">
+				CompileAs="0">
 				<IntelOptions
 					Optimization="0"
 					MinimalRebuild="1"
 					BasicRuntimeChecks="3"
 					RuntimeLibrary="1"
-					AllOptions="/c  /I &quot;.\\&quot; /Z7 /nologo /W3 /Od /D &quot;WIN32&quot; /D &quot;_DEBUG&quot; /D &quot;_WINDOWS&quot; /Gm /EHsc /RTC1 /MTd /YX&quot;StdAfx.h&quot; /Fp&quot;.\ST_Debug/libmp4v2_st60.pch&quot; /Fo&quot;.\ST_Debug/&quot; /Fd&quot;.\ST_Debug/&quot; /Gd"
-					MSOriginalAdditionalOptions=""/>
+					AllOptions="/c  /I &quot;.\\&quot; /Z7 /nologo /W3 /Od /D &quot;WIN32&quot; /D &quot;_DEBUG&quot; /D &quot;_WINDOWS&quot; /Gm /EHsc /RTC1 /MTd /YX&quot;StdAfx.h&quot; /Fp&quot;.\ST_Debug/libmp4v2_st60.pch&quot; /Fo&quot;.\ST_Debug/&quot; /Fd&quot;.\ST_Debug/&quot; /Gd"/>
 			</Tool>
 			<Tool
 				Name="VCCustomBuildTool"/>
@@ -109,11 +103,9 @@
 			<Tool
 				Name="VCLibrarianTool"
 				OutputFile=".\ST_Debug\libmp4v2_st60.lib"
-				SuppressStartupBanner="TRUE"
-				AdditionalOptions="">
+				SuppressStartupBanner="TRUE">
 				<IntelOptions
-					AllOptions="/OUT:&quot;.\ST_Debug\libmp4v2_st60.lib&quot; /NOLOGO"
-					MSOriginalAdditionalOptions=""/>
+					AllOptions="/OUT:&quot;.\ST_Debug\libmp4v2_st60.lib&quot; /NOLOGO"/>
 			</Tool>
 			<Tool
 				Name="VCMIDLTool"/>
@@ -236,6 +228,8 @@
 				RelativePath=".\atom_stsz.cpp"/>
 			<File
 				RelativePath=".\atom_stts.cpp"/>
+			<File
+				RelativePath="atom_tag4.cpp"/>
 			<File
 				RelativePath=".\atom_tfhd.cpp"/>
 			<File
--- a/common/mp4v2/mp4.cpp
+++ b/common/mp4v2/mp4.cpp
@@ -86,6 +86,39 @@
 		return MP4_INVALID_FILE_HANDLE;
 	}
 }
+
+extern "C" MP4FileHandle MP4ModifyCb(const char* fileName, 
+	u_int32_t verbosity, bool useExtensibleFormat,
+    MP4OpenCallback MP4fopen, MP4CloseCallback MP4fclose,
+    MP4ReadCallback MP4fread, MP4WriteCallback MP4fwrite,
+    MP4SetposCallback MP4fsetpos, MP4GetposCallback MP4fgetpos,
+    MP4FilesizeCallback MP4filesize, void *userData)
+{
+	MP4File* pFile = NULL;
+	try {
+		pFile = new MP4File(verbosity);
+
+        // Set user data and callbacks
+        pFile->m_userData = userData;
+        pFile->m_MP4fopen = MP4fopen;
+        pFile->m_MP4fclose = MP4fclose;
+        pFile->m_MP4fread = MP4fread;
+        pFile->m_MP4fwrite = MP4fwrite;
+        pFile->m_MP4fsetpos = MP4fsetpos;
+        pFile->m_MP4fgetpos = MP4fgetpos;
+        pFile->m_MP4filesize = MP4filesize;
+
+		// LATER useExtensibleFormat, moov first, then mvex's
+		pFile->Modify(fileName);
+		return (MP4FileHandle)pFile;
+	}
+	catch (MP4Error* e) {
+		VERBOSE_ERROR(verbosity, e->Print());
+		delete e;
+		delete pFile;
+		return MP4_INVALID_FILE_HANDLE;
+	}
+}
 #endif
 
 extern "C" MP4FileHandle MP4Create(const char* fileName, 
@@ -2482,5 +2515,98 @@
 		}
 	}
 	return NULL;
+}
+
+/* tagging functions */
+
+extern "C" void MP4TagCreate(MP4FileHandle hFile, MP4TrackId trackId)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			((MP4File*)hFile)->TagCreate(trackId);
+            return;
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
+	}
+}
+
+extern "C" void MP4TagDelete(MP4FileHandle hFile, MP4TrackId trackId)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			((MP4File*)hFile)->TagDelete(trackId);
+            return;
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
+	}
+}
+
+extern "C" void MP4TagAddEntry(MP4FileHandle hFile, MP4TrackId trackId,
+                               const char *name, const char *value)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			((MP4File*)hFile)->TagAddEntry(trackId, name, value);
+            return;
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
+	}
+}
+
+#if 0
+extern "C" void MP4TagDeleteEntry(MP4FileHandle hFile, MP4TrackId trackId,
+                                  u_int32_t index)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			((MP4File*)hFile)->TagDeleteEntry(trackId, index);
+            return;
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
+	}
+}
+#endif
+
+extern "C" u_int32_t MP4TagGetNumEntries(MP4FileHandle hFile, MP4TrackId trackId)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			return ((MP4File*)hFile)->TagGetNumEntries(trackId);
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+            return 0;
+		}
+	}
+}
+
+extern "C" void MP4TagGetEntry(MP4FileHandle hFile, MP4TrackId trackId,
+                               u_int32_t index, const char **name,
+                               const char **value)
+{
+	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+		try {
+			((MP4File*)hFile)->TagGetEntry(trackId, index,
+                name, value);
+            return;
+		}
+		catch (MP4Error* e) {
+			PRINT_ERROR(e);
+			delete e;
+		}
+	}
 }
 
--- a/common/mp4v2/mp4.h
+++ b/common/mp4v2/mp4.h
@@ -246,6 +246,13 @@
                         MP4FilesizeCallback MP4filesize,
                         void *userData);
 
+MP4FileHandle MP4ModifyCb(const char* fileName, 
+	u_int32_t verbosity, bool useExtensibleFormat,
+    MP4OpenCallback MP4fopen, MP4CloseCallback MP4fclose,
+    MP4ReadCallback MP4fread, MP4WriteCallback MP4fwrite,
+    MP4SetposCallback MP4fsetpos, MP4GetposCallback MP4fgetpos,
+    MP4FilesizeCallback MP4filesize, void *userData);
+
 bool MP4Close(
 	MP4FileHandle hFile);
 
@@ -899,6 +906,18 @@
 char* MP4BinaryToBase64(
 	const u_int8_t* pData, 
 	u_int32_t dataSize);
+
+void MP4TagCreate(MP4FileHandle hFile, MP4TrackId trackId);
+void MP4TagDelete(MP4FileHandle hFile, MP4TrackId trackId);
+void MP4TagAddEntry(MP4FileHandle hFile, MP4TrackId trackId,
+                    const char *name, const char *value);
+#if 0
+void MP4TagDeleteEntry(MP4FileHandle hFile, MP4TrackId trackId,
+                       u_int32_t index);
+#endif
+u_int32_t MP4TagGetNumEntries(MP4FileHandle hFile, MP4TrackId trackId);
+void MP4TagGetEntry(MP4FileHandle hFile, MP4TrackId trackId,
+                    u_int32_t index, const char **name, const char **value);
 
 #ifdef __cplusplus
 }
--- a/common/mp4v2/mp4atom.cpp
+++ b/common/mp4v2/mp4atom.cpp
@@ -225,6 +225,8 @@
 			pAtom = new MP4RtpAtom();
 		} else if (ATOMID(type) == ATOMID("vmhd")) {
 			pAtom = new MP4VmhdAtom();
+		} else if (ATOMID(type) == ATOMID("TAG4")) {
+			pAtom = new MP4Tag4Atom();
 		}
 	}
 
--- a/common/mp4v2/mp4file.cpp
+++ b/common/mp4v2/mp4file.cpp
@@ -2312,3 +2312,132 @@
 		when, pStartTime, pDuration);
 }
 
+
+/* Code for handling mp4 tagging */
+
+void MP4File::TagCreate(MP4TrackId trackId)
+{
+    if (trackId == NULL)
+        AddDescendantAtoms("moov", "udta.TAG4");
+    else
+        AddDescendantAtoms(MakeTrackName(trackId, NULL), "udta.TAG4");
+}
+
+void MP4File::TagDelete(MP4TrackId trackId)
+{
+    MP4Atom *pUdtaAtom = NULL;
+    MP4Atom *pTagAtom = NULL;
+
+    if (trackId == NULL)
+    {
+        pUdtaAtom = m_pRootAtom->FindAtom("moov.udta");
+        pTagAtom = m_pRootAtom->FindAtom("moov.udta.TAG4");
+    } else {
+        pUdtaAtom = m_pRootAtom->FindAtom(MakeTrackName(trackId, "udta"));
+        pTagAtom = m_pRootAtom->FindAtom(MakeTrackName(trackId, "udta.TAG4"));
+    }
+
+    pUdtaAtom->DeleteChildAtom(pTagAtom);
+
+    delete pTagAtom;
+}
+
+void MP4File::TagAddEntry(MP4TrackId trackId,
+                          const char *name, const char *value)
+{
+    MP4StringProperty *pNameProperty = NULL;
+    MP4StringProperty *pValueProperty = NULL;
+    MP4Integer32Property *pCountProperty = NULL;
+    MP4Atom *pTagAtom = NULL;
+
+    if (trackId == NULL)
+        pTagAtom = m_pRootAtom->FindAtom("moov.udta.TAG4");
+    else
+        pTagAtom = m_pRootAtom->FindAtom(MakeTrackName(trackId, "udta.TAG4"));
+
+    pTagAtom->FindProperty("TAG4.entryCount",
+        (MP4Property**)&pCountProperty);
+    ASSERT(pCountProperty);
+
+    pTagAtom->FindProperty("TAG4.entries.name",
+        (MP4Property**)&pNameProperty);
+    ASSERT(pNameProperty);
+
+    pNameProperty->AddValue((char*)name);
+
+    pTagAtom->FindProperty("TAG4.entries.value",
+        (MP4Property**)&pValueProperty);
+    ASSERT(pValueProperty);
+
+    pValueProperty->AddValue((char*)value);
+
+    pCountProperty->IncrementValue();
+}
+
+#if 0
+void MP4File::TagDeleteEntry(MP4TrackId trackId, u_int32_t index)
+{
+    MP4TableProperty *pEntryProperty = NULL;
+    MP4Integer32Property *pCountProperty = NULL;
+    MP4Atom *pTagAtom = NULL;
+
+    if (trackId == NULL)
+        pTagAtom = m_pRootAtom->FindAtom("moov.udta.TAG4");
+    else
+        pTagAtom = m_pRootAtom->FindAtom(MakeTrackName(trackId, "udta.TAG4"));
+
+    pTagAtom->FindProperty("TAG4.entryCount",
+        (MP4Property**)&pCountProperty);
+    ASSERT(pCountProperty);
+
+    pTagAtom->FindProperty("TAG4.entries",
+        (MP4Property**)&pEntryProperty);
+    ASSERT(pEntryProperty);
+
+    pEntryProperty->DeleteEntry(index);
+
+    pCountProperty->IncrementValue(-1);
+}
+#endif
+
+u_int32_t MP4File::TagGetNumEntries(MP4TrackId trackId)
+{
+    MP4Integer32Property *pCountProperty = NULL;
+    MP4Atom *pTagAtom = NULL;
+
+    if (trackId == NULL)
+        pTagAtom = m_pRootAtom->FindAtom("moov.udta.TAG4");
+    else
+        pTagAtom = m_pRootAtom->FindAtom(MakeTrackName(trackId, "udta.TAG4"));
+
+    if (pTagAtom)
+    {
+        pTagAtom->FindProperty("TAG4.entryCount",
+            (MP4Property**)&pCountProperty);
+        if (pCountProperty)
+        {
+            return pCountProperty->GetValue();
+        }
+    }
+
+    return 0;
+}
+
+void MP4File::TagGetEntry(MP4TrackId trackId, u_int32_t index,
+                          const char **name, const char **value)
+{
+    char s[256];
+
+    if (trackId == NULL)
+    {
+        sprintf(s, "moov.udta.TAG4.entries[%u].name", index);		
+        *name = GetStringProperty(s);
+        sprintf(s, "moov.udta.TAG4.entries[%u].value", index);
+        *value = GetStringProperty(s);
+    } else {
+        sprintf(s, "udta.TAG4.entries[%u].name", index);		
+        *name = GetTrackStringProperty(trackId, s);
+        sprintf(s, "udta.TAG4.entries[%u].value", index);
+        *value = GetTrackStringProperty(trackId, s);
+    }
+}
--- a/common/mp4v2/mp4file.h
+++ b/common/mp4v2/mp4file.h
@@ -422,6 +422,16 @@
 		MP4Timestamp* pStartTime = NULL,
 		MP4Duration* pDuration = NULL);
 
+    /* tagging */
+    void TagCreate(MP4TrackId trackId);
+    void TagDelete(MP4TrackId trackId);
+    void TagAddEntry(MP4TrackId trackId,
+        const char *name, const char *value);
+    void TagDeleteEntry(MP4TrackId trackId, u_int32_t index);
+    u_int32_t TagGetNumEntries(MP4TrackId trackId);
+    void TagGetEntry(MP4TrackId trackId, u_int32_t index,
+        const char **name, const char **value);
+
 	/* end of MP4 API */
 
 	/* "protected" interface to be used only by friends in library */
--- a/common/mp4v2/mp4property.cpp
+++ b/common/mp4v2/mp4property.cpp
@@ -584,6 +584,37 @@
 	return false;
 }
 
+void MP4TableProperty::DeleteEntry(u_int32_t index)
+{
+    u_int32_t numProperties = m_pProperties.Size();
+
+	for (u_int32_t i = 0; i < numProperties; i++) {
+        switch (m_pProperties[i]->GetType()) {
+        case Integer8Property:
+            ((MP4Integer8Property*)m_pProperties[i])->DeleteValue(index);
+            break;
+        case Integer16Property:
+            ((MP4Integer16Property*)m_pProperties[i])->DeleteValue(index);
+            break;
+        case Integer24Property:
+            ((MP4Integer24Property*)m_pProperties[i])->DeleteValue(index);
+            break;
+        case Integer32Property:
+            ((MP4Integer32Property*)m_pProperties[i])->DeleteValue(index);
+            break;
+        case Integer64Property:
+            ((MP4Integer64Property*)m_pProperties[i])->DeleteValue(index);
+            break;
+        case StringProperty:
+            ((MP4StringProperty*)m_pProperties[i])->DeleteValue(index);
+            break;
+        default:
+            ASSERT(FALSE);
+            break;
+        }
+    }
+}
+
 void MP4TableProperty::Read(MP4File* pFile, u_int32_t index)
 {
 	ASSERT(index == 0);
--- a/common/mp4v2/mp4property.h
+++ b/common/mp4v2/mp4property.h
@@ -307,6 +307,10 @@
 		SetValue(value, count);
 	}
 
+    void DeleteValue(u_int32_t index) {
+        m_values.Delete(index);
+    }
+
 	bool IsCountedFormat() {
 		return m_useCountedFormat;
 	}
@@ -460,6 +464,8 @@
 
 	bool FindProperty(const char* name,
 		MP4Property** ppProperty, u_int32_t* pIndex = NULL);
+
+    void DeleteEntry(u_int32_t index);
 
 protected:
 	virtual void ReadEntry(MP4File* pFile, u_int32_t index);
--- a/plugins/foo_mp4/foo_mp4.cpp
+++ b/plugins/foo_mp4/foo_mp4.cpp
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: foo_mp4.cpp,v 1.7 2002/12/27 23:06:37 menno Exp $
+** $Id: foo_mp4.cpp,v 1.8 2002/12/29 10:46:50 menno Exp $
 **/
 
 #include <mp4.h>
@@ -49,11 +49,6 @@
         config->outputFormat = FAAD_FMT_FLOAT;
         faacDecSetConfiguration(hDecoder, config);
 
-//        char filename[_MAX_PATH];
-//        int len = (wcslen(info->get_file_path())+1)*2;
-//        WideCharToMultiByte(CP_ACP,0,info->get_file_path(),-1,filename,len,0,0);
-
-//        hFile = MP4Read(filename, 0);
         hFile = MP4ReadCb("blablabla", 0, open_cb, close_cb, read_cb, write_cb,
             setpos_cb, getpos_cb, filesize_cb, (void*)m_reader);
         if (hFile == MP4_INVALID_FILE_HANDLE) return 0;
@@ -85,6 +80,8 @@
         info->info_set_int("channels", (__int64)channels);
         info->info_set_int("samplerate", (__int64)m_samplerate);
 
+        ReadMP4Tag(info);
+
         return 1;
     }
 
@@ -140,7 +137,27 @@
 
     virtual int set_info(reader *r,const file_info * info)
     {
-        return 0;
+        m_reader = r;
+
+        hFile = MP4ModifyCb("blablabla", 0, 0, open_cb, close_cb, read_cb, write_cb,
+            setpos_cb, getpos_cb, filesize_cb, (void*)m_reader);
+        if (hFile == MP4_INVALID_FILE_HANDLE) return 0;
+
+        track = GetAACTrack(hFile);
+        if (track < 1) return 0;
+
+        MP4TagDelete(hFile, track);
+        MP4TagCreate(hFile, track);
+
+        int numItems = info->meta_get_count();
+        for (int i = 0; i < numItems; i++)
+        {
+            const char *n = info->meta_enum_name(i);
+            const char *v = info->meta_enum_value(i);
+            MP4TagAddEntry(hFile, track, n, v);
+        }
+
+        return 1;
     }
 
     virtual int seek(double seconds)
@@ -161,13 +178,27 @@
 
     MP4FileHandle hFile;
     MP4SampleId sampleId, numSamples;
-    int track;
+    MP4TrackId track;
 
     unsigned __int32 m_samplerate;
 
     faacDecHandle hDecoder;
 
+    int ReadMP4Tag(file_info *info)
+    {
+        int numItems = MP4TagGetNumEntries(hFile, track);
 
+        for (int i = 0; i < numItems; i++)
+        {
+            const char *n = NULL, *v = NULL;
+
+            MP4TagGetEntry(hFile, track, i, &n, &v);
+            info->meta_add(n, v);
+        }
+
+        return 1;
+    }
+
     int GetAACTrack(MP4FileHandle infile)
     {
         /* find AAC track */
@@ -228,7 +259,8 @@
     static unsigned __int32 write_cb(void *pBuffer, unsigned int nBytesToWrite,
         void *userData)
     {
-        return 0;
+        reader *r = (reader*)userData;
+        return r->write(pBuffer, nBytesToWrite);
     }
 
     static __int64 getpos_cb(void *userData)
--- a/plugins/foo_mp4/foo_mp4.sln
+++ b/plugins/foo_mp4/foo_mp4.sln
@@ -1,13 +1,13 @@
 Microsoft Visual Studio Solution File, Format Version 7.00
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foo_mp4", "foo_mp4.vcproj", "{5CEB23D7-5BDB-4D77-978A-D5B8572843FF}"
+Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "foo_mp4", "foo_mp4.vcproj", "{5CEB23D7-5BDB-4D77-978A-D5B8572843FF}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "foobar2000_SDK", "foobar2000\SDK\foobar2000_SDK.vcproj", "{409102E1-0B45-41CD-A3F8-C37371520D9B}"
+Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "foobar2000_SDK", "foobar2000\SDK\foobar2000_SDK.vcproj", "{409102E1-0B45-41CD-A3F8-C37371520D9B}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfaad", "..\..\libfaad\libfaad.vcproj", "{AB39547E-6CAC-4E25-8BC4-C97EFC144800}"
+Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "libfaad", "..\..\libfaad\libfaad.vcproj", "{AB39547E-6CAC-4E25-8BC4-C97EFC144800}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pfc_unicode", "pfc\pfc_unicode.vcproj", "{5C9C90BE-0FEA-4C67-9A4C-C2513C2E27C4}"
+Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "pfc_unicode", "pfc\pfc_unicode.vcproj", "{5C9C90BE-0FEA-4C67-9A4C-C2513C2E27C4}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmp4v2_cb", "..\..\common\mp4v2\libmp4v2_cb.vcproj", "{FAEB6203-052A-4073-AC1C-9CF6FB5B40CC}"
+Project("{EAF909A5-FA59-4C3D-9431-0FCC20D5BCF9}") = "libmp4v2_cb", "..\..\common\mp4v2\libmp4v2_cb.vcproj", "{FAEB6203-052A-4073-AC1C-9CF6FB5B40CC}"
 EndProject
 Global
 	GlobalSection(SolutionConfiguration) = preSolution