ref: 0ab055fe640979fa9161ae5ddea6160e2340fd16
parent: 0b2ef5faeb07dbc043cc925da4177b69b2146c84
author: menno <menno>
date: Sun Jun 29 17:41:00 EDT 2003
iTunes tagging support
--- /dev/null
+++ b/common/mp4v2/atom_enca.cpp
@@ -1,0 +1,61 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
+ */
+
+#include "mp4common.h"
+
+MP4EncaAtom::MP4EncaAtom()
+ : MP4Atom("enca")
+{
+ AddReserved("reserved1", 6); /* 0 */
+
+ AddProperty( /* 1 */
+ new MP4Integer16Property("dataReferenceIndex"));
+
+ AddReserved("reserved2", 16); /* 2 */
+
+ AddProperty( /* 3 */
+ new MP4Integer16Property("timeScale"));
+
+ AddReserved("reserved3", 2); /* 4 */
+
+ ExpectChildAtom("esds", Required, OnlyOne);
+ ExpectChildAtom("sinf", Required, OnlyOne);
+}
+
+void MP4EncaAtom::Generate()
+{
+ MP4Atom::Generate();
+
+ ((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+ // property reserved2 has non-zero fixed values
+ static u_int8_t reserved2[16] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00,
+ };
+ m_pProperties[2]->SetReadOnly(false);
+ ((MP4BytesProperty*)m_pProperties[2])->
+ SetValue(reserved2, sizeof(reserved2));
+ m_pProperties[2]->SetReadOnly(true);
+}
--- /dev/null
+++ b/common/mp4v2/atom_encv.cpp
@@ -1,0 +1,80 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
+ */
+
+#include "mp4common.h"
+
+MP4EncvAtom::MP4EncvAtom()
+ : MP4Atom("encv")
+{
+ AddReserved("reserved1", 6); /* 0 */
+
+ AddProperty( /* 1 */
+ new MP4Integer16Property("dataReferenceIndex"));
+
+ AddReserved("reserved2", 16); /* 2 */
+
+ AddProperty( /* 3 */
+ new MP4Integer16Property("width"));
+ AddProperty( /* 4 */
+ new MP4Integer16Property("height"));
+
+ AddReserved("reserved3", 14); /* 5 */
+
+ MP4StringProperty* pProp =
+ new MP4StringProperty("compressorName");
+ pProp->SetFixedLength(32);
+ pProp->SetValue("");
+ AddProperty(pProp); /* 6 */
+ AddReserved("reserved4", 4); /* 7 */
+
+ ExpectChildAtom("esds", Required, OnlyOne);
+ ExpectChildAtom("sinf", Required, OnlyOne);
+}
+
+void MP4EncvAtom::Generate()
+{
+ MP4Atom::Generate();
+
+ ((MP4Integer16Property*)m_pProperties[1])->SetValue(1);
+
+ // property reserved3 has non-zero fixed values
+ static u_int8_t reserved3[14] = {
+ 0x00, 0x48, 0x00, 0x00,
+ 0x00, 0x48, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01,
+ };
+ m_pProperties[5]->SetReadOnly(false);
+ ((MP4BytesProperty*)m_pProperties[5])->
+ SetValue(reserved3, sizeof(reserved3));
+ m_pProperties[5]->SetReadOnly(true);
+
+ // property reserved4 has non-zero fixed values
+ static u_int8_t reserved4[4] = {
+ 0x00, 0x18, 0xFF, 0xFF,
+ };
+ m_pProperties[7]->SetReadOnly(false);
+ ((MP4BytesProperty*)m_pProperties[7])->
+ SetValue(reserved4, sizeof(reserved4));
+ m_pProperties[7]->SetReadOnly(true);
+}
+
--- /dev/null
+++ b/common/mp4v2/atom_frma.cpp
@@ -1,0 +1,32 @@
+/*
+ * 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"));
+}
--- a/common/mp4v2/atom_ftyp.cpp
+++ b/common/mp4v2/atom_ftyp.cpp
@@ -49,12 +49,14 @@
{
MP4Atom::Generate();
- ((MP4StringProperty*)m_pProperties[0])->SetValue("isom");
+ ((MP4StringProperty*)m_pProperties[0])->SetValue("mp42");
MP4StringProperty* pBrandProperty = (MP4StringProperty*)
((MP4TableProperty*)m_pProperties[3])->GetProperty(0);
ASSERT(pBrandProperty);
- pBrandProperty->AddValue("mp41");
+ pBrandProperty->AddValue("mp42");
+ pBrandProperty->AddValue("isom");
+ ((MP4Integer32Property*)m_pProperties[2])->IncrementValue();
((MP4Integer32Property*)m_pProperties[2])->IncrementValue();
}
--- /dev/null
+++ b/common/mp4v2/atom_iKMS.cpp
@@ -1,0 +1,34 @@
+/*
+ * 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 */
+}
--- /dev/null
+++ b/common/mp4v2/atom_iSFM.cpp
@@ -1,0 +1,38 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 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"));
+}
--- /dev/null
+++ b/common/mp4v2/atom_meta.cpp
@@ -1,0 +1,183 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
+ *
+ * Contributor(s):
+ * M. Bakker mbakker at nero.com
+ *
+ * Apple iTunes META data
+ */
+
+#include "mp4common.h"
+
+MP4MetaAtom::MP4MetaAtom()
+ : MP4Atom("meta")
+{
+ AddVersionAndFlags(); /* 0, 1 */
+
+ ExpectChildAtom("hdlr", Required, OnlyOne);
+ ExpectChildAtom("ilst", Required, OnlyOne);
+}
+
+MP4MeanAtom::MP4MeanAtom()
+ : MP4Atom("mean")
+{
+ AddVersionAndFlags(); /* 0, 1 */
+
+ AddProperty(
+ new MP4BytesProperty("metadata")); /* 2 */
+}
+
+void MP4MeanAtom::Read()
+{
+ // calculate size of the metadata from the atom size
+ ((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 4);
+
+ MP4Atom::Read();
+}
+
+MP4NameAtom::MP4NameAtom()
+ : MP4Atom("name")
+{
+ AddVersionAndFlags(); /* 0, 1 */
+
+ AddProperty(
+ new MP4BytesProperty("metadata")); /* 2 */
+}
+
+void MP4NameAtom::Read()
+{
+ // calculate size of the metadata from the atom size
+ ((MP4BytesProperty*)m_pProperties[2])->SetValueSize(m_size - 4);
+
+ MP4Atom::Read();
+}
+
+MP4DataAtom::MP4DataAtom()
+ : MP4Atom("data")
+{
+ AddVersionAndFlags(); /* 0, 1 */
+ AddReserved("reserved2", 4); /* 2 */
+
+ AddProperty(
+ new MP4BytesProperty("metadata")); /* 3 */
+}
+
+void MP4DataAtom::Read()
+{
+ // calculate size of the metadata from the atom size
+ ((MP4BytesProperty*)m_pProperties[3])->SetValueSize(m_size - 8);
+
+ MP4Atom::Read();
+}
+
+MP4IlstAtom::MP4IlstAtom()
+ : MP4Atom("ilst")
+{
+ ExpectChildAtom("�nam", Optional, OnlyOne); /* name */
+ ExpectChildAtom("�ART", Optional, OnlyOne); /* artist */
+ ExpectChildAtom("�wrt", Optional, OnlyOne); /* writer */
+ ExpectChildAtom("�alb", Optional, OnlyOne); /* album */
+ ExpectChildAtom("�day", Optional, OnlyOne); /* date */
+ ExpectChildAtom("�too", Optional, OnlyOne); /* tool */
+ ExpectChildAtom("�cmt", Optional, OnlyOne); /* comment */
+ ExpectChildAtom("trkn", Optional, OnlyOne); /* tracknumber */
+ ExpectChildAtom("disk", Optional, OnlyOne); /* disknumber */
+ ExpectChildAtom("gnre", Optional, OnlyOne); /* genre */
+ ExpectChildAtom("cpil", Optional, OnlyOne); /* compilation */
+ ExpectChildAtom("tmpo", Optional, OnlyOne); /* BPM */
+ ExpectChildAtom("----", Optional, Many); /* ---- free form */
+}
+
+MP4DashAtom::MP4DashAtom()
+ : MP4Atom("----")
+{
+ ExpectChildAtom("mean", Required, OnlyOne);
+ ExpectChildAtom("name", Required, OnlyOne);
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4NamAtom::MP4NamAtom()
+ : MP4Atom("�nam")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4ArtAtom::MP4ArtAtom()
+ : MP4Atom("�ART")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4WrtAtom::MP4WrtAtom()
+ : MP4Atom("�wrt")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4AlbAtom::MP4AlbAtom()
+ : MP4Atom("�alb")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4CmtAtom::MP4CmtAtom()
+ : MP4Atom("�cmt")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4TrknAtom::MP4TrknAtom()
+ : MP4Atom("trkn")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4DiskAtom::MP4DiskAtom()
+ : MP4Atom("disk")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4DayAtom::MP4DayAtom()
+ : MP4Atom("�day")
+{
+ ExpectChildAtom("data", Required, OnlyOne);
+}
+
+MP4TooAtom::MP4TooAtom()
+ : MP4Atom("�too")
+{
+ 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);
+}
--- /dev/null
+++ b/common/mp4v2/atom_schi.cpp
@@ -1,0 +1,34 @@
+/*
+ * 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")
+{
+ AddVersionAndFlags();
+ // 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);
+}
--- /dev/null
+++ b/common/mp4v2/atom_schm.cpp
@@ -1,0 +1,35 @@
+/*
+ * 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
+}
--- /dev/null
+++ b/common/mp4v2/atom_sinf.cpp
@@ -1,0 +1,34 @@
+/*
+ * 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")
+{
+ AddVersionAndFlags();
+ ExpectChildAtom("frma", Required, OnlyOne);
+ ExpectChildAtom("schm", Required, OnlyOne);
+ ExpectChildAtom("schi", Required, OnlyOne);
+}
--- a/common/mp4v2/atom_stsd.cpp
+++ b/common/mp4v2/atom_stsd.cpp
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#include "mp4common.h"
@@ -32,8 +33,10 @@
AddProperty(pCount);
ExpectChildAtom("mp4a", Optional, Many);
+ ExpectChildAtom("enca", Optional, Many);
ExpectChildAtom("mp4s", Optional, Many);
ExpectChildAtom("mp4v", Optional, Many);
+ ExpectChildAtom("encv", Optional, Many);
ExpectChildAtom("rtp ", Optional, Many);
}
--- a/common/mp4v2/atom_tag4.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.
- *
- * Contributor(s):
- * M. Bakker [email protected]
- */
-
-#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/atom_udta.cpp
+++ b/common/mp4v2/atom_udta.cpp
@@ -26,6 +26,7 @@
{
ExpectChildAtom("cprt", Optional, Many);
ExpectChildAtom("hnti", Optional, OnlyOne);
+ ExpectChildAtom("meta", Optional, OnlyOne);
}
void MP4UdtaAtom::Read()
--- a/common/mp4v2/atoms.h
+++ b/common/mp4v2/atoms.h
@@ -443,9 +443,141 @@
void Write();
};
-class MP4Tag4Atom : public MP4Atom {
+// ismacrypt
+class MP4EncaAtom : public MP4Atom {
public:
- MP4Tag4Atom();
+ MP4EncaAtom();
+ void Generate();
+};
+
+class MP4EncvAtom : public MP4Atom {
+public:
+ MP4EncvAtom();
+ 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 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 MP4DiskAtom : public MP4Atom {
+public:
+ MP4DiskAtom();
};
#endif /* __MP4_ATOMS_INCLUDED__ */
--- a/common/mp4v2/descriptors.cpp
+++ b/common/mp4v2/descriptors.cpp
@@ -367,6 +367,13 @@
// UseTimestampsFlag = 1
((MP4BitfieldProperty*)m_pProperties[6])->SetValue(1);
}
+ } else {
+#if 1
+ for (i = 1; i <= 18; i++) {
+ m_pProperties[i]->SetImplicit(false);
+ }
+ ((MP4BitfieldProperty*)m_pProperties[18])->SetValue(3);
+#endif
}
bool durationFlag =
--- a/common/mp4v2/descriptors.h
+++ b/common/mp4v2/descriptors.h
@@ -92,7 +92,7 @@
MP4SLConfigDescriptor();
void Generate();
void Read(MP4File* pFile);
-protected:
+ protected:
void Mutate();
};
--- a/common/mp4v2/isma.cpp
+++ b/common/mp4v2/isma.cpp
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#include "mp4common.h"
@@ -201,6 +202,8 @@
pEsProperty->SetTags(MP4ESDescrTag);
MP4IntegerProperty* pSetProperty;
+ MP4IntegerProperty* pSceneESID;
+ MP4IntegerProperty* pOdESID;
// OD
MP4Descriptor* pOdEsd =
@@ -208,9 +211,11 @@
pOdEsd->Generate();
pOdEsd->FindProperty("ESID",
- (MP4Property**)&pSetProperty);
- pSetProperty->SetValue(m_odTrackId);
+ (MP4Property**)&pOdESID);
+ // we set the OD ESID to a non-zero unique value
+ pOdESID->SetValue(m_odTrackId);
+
pOdEsd->FindProperty("URLFlag",
(MP4Property**)&pSetProperty);
pSetProperty->SetValue(1);
@@ -280,8 +285,9 @@
pSceneEsd->Generate();
pSceneEsd->FindProperty("ESID",
- (MP4Property**)&pSetProperty);
- pSetProperty->SetValue(sceneTrackId);
+ (MP4Property**)&pSceneESID);
+ // we set the Scene ESID to a non-zero unique value
+ pSceneESID->SetValue(sceneTrackId);
pSceneEsd->FindProperty("URLFlag",
(MP4Property**)&pSetProperty);
@@ -346,6 +352,8 @@
// now carefully replace esd properties before destroying
pOdEsd->SetProperty(8, pOrgOdEsdProperty);
pSceneEsd->SetProperty(8, pOrgSceneEsdProperty);
+ pSceneESID->SetValue(0); // restore 0 value
+ pOdESID->SetValue(0);
delete pIod;
@@ -477,7 +485,7 @@
delete pVideoEsdProperty;
VERBOSE_ISMA(GetVerbosity(),
- printf("OD data =\n"); MP4HexDump(pBytes, numBytes));
+ printf("OD data = %llu bytes\n", numBytes); MP4HexDump(pBytes, numBytes));
char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);
@@ -672,32 +680,37 @@
u_int64_t* pNumBytes)
{
MP4DescriptorProperty* pAudioEsd = NULL;
- MP4Integer8Property* pAudioSLConfig = NULL;
+ MP4Integer8Property* pAudioSLConfigPredef = NULL;
MP4BitfieldProperty* pAudioAccessUnitEndFlag = NULL;
int oldAudioUnitEndFlagValue = 0;
MP4DescriptorProperty* pVideoEsd = NULL;
- MP4Integer8Property* pVideoSLConfig = NULL;
+ MP4Integer8Property* pVideoSLConfigPredef = NULL;
MP4BitfieldProperty* pVideoAccessUnitEndFlag = NULL;
int oldVideoUnitEndFlagValue = 0;
+ MP4IntegerProperty* pAudioEsdId = NULL;
+ MP4IntegerProperty* pVideoEsdId = NULL;
if (audioTrackId != MP4_INVALID_TRACK_ID) {
+ // changed mp4a to * to handle enca case
MP4Atom* pEsdsAtom =
FindAtom(MakeTrackName(audioTrackId,
- "mdia.minf.stbl.stsd.mp4a.esds"));
+ "mdia.minf.stbl.stsd.*.esds"));
ASSERT(pEsdsAtom);
pAudioEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
+ // ESID is 0 for file, stream needs to be non-ze
+ pAudioEsd->FindProperty("ESID",
+ (MP4Property**)&pAudioEsdId);
+ ASSERT(pAudioEsdId);
+ pAudioEsdId->SetValue(audioTrackId);
+
// SL config needs to change from 2 (file) to 1 (null)
pAudioEsd->FindProperty("slConfigDescr.predefined",
- (MP4Property**)&pAudioSLConfig);
- ASSERT(pAudioSLConfig);
-#if 0
- // changed 12/05/02 wmay
- pAudioSLConfig->SetValue(1);
-#else
- pAudioSLConfig->SetValue(0);
-#endif
+ (MP4Property**)&pAudioSLConfigPredef);
+ ASSERT(pAudioSLConfigPredef);
+ pAudioSLConfigPredef->SetValue(0);
+
pAudioEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
(MP4Property **)&pAudioAccessUnitEndFlag);
oldAudioUnitEndFlagValue =
@@ -706,23 +719,25 @@
}
if (videoTrackId != MP4_INVALID_TRACK_ID) {
+ // changed mp4v to * to handle encv case
MP4Atom* pEsdsAtom =
FindAtom(MakeTrackName(videoTrackId,
- "mdia.minf.stbl.stsd.mp4v.esds"));
+ "mdia.minf.stbl.stsd.*.esds"));
ASSERT(pEsdsAtom);
pVideoEsd = (MP4DescriptorProperty*)(pEsdsAtom->GetProperty(2));
+ pVideoEsd->FindProperty("ESID",
+ (MP4Property**)&pVideoEsdId);
+ ASSERT(pVideoEsdId);
+ pVideoEsdId->SetValue(videoTrackId);
+
// SL config needs to change from 2 (file) to 1 (null)
pVideoEsd->FindProperty("slConfigDescr.predefined",
- (MP4Property**)&pVideoSLConfig);
- ASSERT(pVideoSLConfig);
-#if 0
- pVideoSLConfig->SetValue(1);
- // changed 12/05/02 wmay
-#else
- pVideoSLConfig->SetValue(0);
-#endif
+ (MP4Property**)&pVideoSLConfigPredef);
+ ASSERT(pVideoSLConfigPredef);
+ pVideoSLConfigPredef->SetValue(0);
+
pVideoEsd->FindProperty("slConfigDescr.useAccessUnitEndFlag",
(MP4Property **)&pVideoAccessUnitEndFlag);
oldVideoUnitEndFlagValue =
@@ -732,16 +747,24 @@
CreateIsmaODUpdateCommandForStream(
pAudioEsd, pVideoEsd, ppBytes, pNumBytes);
-
+ VERBOSE_ISMA(GetVerbosity(),
+ printf("After CreateImsaODUpdateCommandForStream len %llu =\n", *pNumBytes); MP4HexDump(*ppBytes, *pNumBytes));
// return SL config values to 2 (file)
- if (pAudioSLConfig) {
- pAudioSLConfig->SetValue(2);
+ // return ESID values to 0
+ if (pAudioSLConfigPredef) {
+ pAudioSLConfigPredef->SetValue(2);
}
+ if (pAudioEsdId) {
+ pAudioEsdId->SetValue(0);
+ }
if (pAudioAccessUnitEndFlag) {
pAudioAccessUnitEndFlag->SetValue(oldAudioUnitEndFlagValue );
}
- if (pVideoSLConfig) {
- pVideoSLConfig->SetValue(2);
+ if (pVideoEsdId) {
+ pVideoEsdId->SetValue(0);
+ }
+ if (pVideoSLConfigPredef) {
+ pVideoSLConfigPredef->SetValue(2);
}
if (pVideoAccessUnitEndFlag) {
pVideoAccessUnitEndFlag->SetValue(oldVideoUnitEndFlagValue );
--- a/common/mp4v2/libmp4v2_cb.dsp
+++ b/common/mp4v2/libmp4v2_cb.dsp
@@ -41,6 +41,7 @@
# PROP Intermediate_Dir "CB_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 ".\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_FILE_CALLBACKS" /YX /FD /c
# ADD BASE RSC /l 0x413 /d "NDEBUG"
@@ -65,6 +66,7 @@
# PROP Intermediate_Dir "CB_Debug"
# PROP Target_Dir ""
MTL=midl.exe
+F90=df.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_FILE_CALLBACKS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x413 /d "_DEBUG"
@@ -131,6 +133,14 @@
# 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
@@ -139,6 +149,10 @@
# 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
@@ -159,10 +173,18 @@
# 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
@@ -179,6 +201,10 @@
# 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
@@ -239,10 +265,22 @@
# 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
@@ -287,10 +325,6 @@
# 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
@@ -396,6 +430,10 @@
# Begin Source File
SOURCE=.\mp4info.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mp4meta.cpp
# End Source File
# Begin Source File
--- a/common/mp4v2/libmp4v2_st60.dsp
+++ b/common/mp4v2/libmp4v2_st60.dsp
@@ -131,6 +131,14 @@
# 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
@@ -139,6 +147,10 @@
# 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
@@ -159,10 +171,18 @@
# 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
@@ -179,6 +199,10 @@
# 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
@@ -239,10 +263,22 @@
# 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
@@ -287,10 +323,6 @@
# 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
@@ -392,6 +424,10 @@
# Begin Source File
SOURCE=.\mp4file_io.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mp4meta.cpp
# End Source File
# Begin Source File
--- a/common/mp4v2/mp4.cpp
+++ b/common/mp4v2/mp4.cpp
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
/*
@@ -638,6 +639,24 @@
return MP4_INVALID_TRACK_ID;
}
+extern "C" MP4TrackId MP4AddEncAudioTrack(MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int8_t audioType)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ AddEncAudioTrack(timeScale, sampleDuration, audioType);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
extern "C" MP4TrackId MP4AddVideoTrack(
MP4FileHandle hFile,
u_int32_t timeScale,
@@ -659,6 +678,26 @@
return MP4_INVALID_TRACK_ID;
}
+extern "C" MP4TrackId MP4AddEncVideoTrack(MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ u_int8_t videoType)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddEncVideoTrack(timeScale, sampleDuration,
+ width, height, videoType);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
extern "C" MP4TrackId MP4AddHintTrack(
MP4FileHandle hFile, MP4TrackId refTrackId)
{
@@ -693,6 +732,8 @@
}
if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+ MP4SetVideoProfileLevel(dstFile,
+ MP4GetVideoProfileLevel(srcFile));
dstTrackId = MP4AddVideoTrack(
dstFile,
MP4GetTrackTimeScale(srcFile, srcTrackId),
@@ -699,14 +740,16 @@
MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
MP4GetTrackVideoWidth(srcFile, srcTrackId),
MP4GetTrackVideoHeight(srcFile, srcTrackId),
- MP4GetTrackVideoType(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),
- MP4GetTrackAudioType(srcFile, srcTrackId));
+ MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId));
} else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
dstTrackId = MP4AddODTrack(dstFile);
@@ -735,6 +778,8 @@
dstTrackId,
MP4GetTrackTimeScale(srcFile, srcTrackId));
+ if (MP4_IS_AUDIO_TRACK_TYPE(trackType)
+ || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
// copy track ES configuration
u_int8_t* pConfig = NULL;
u_int32_t configSize = 0;
@@ -752,6 +797,7 @@
configSize);
free(pConfig);
+ }
if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
// probably not exactly what is wanted
@@ -787,91 +833,259 @@
return dstTrackId;
}
-extern "C" MP4TrackId MP4CopyTrack(
- MP4FileHandle srcFile,
- MP4TrackId srcTrackId,
- MP4FileHandle dstFile,
- bool applyEdits)
+// Given a track, make an encrypted clone of it in the dest. file
+extern "C" MP4TrackId MP4EncAndCloneTrack(MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile)
{
- bool copySamples = true; // LATER allow false => reference samples
+ MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
- MP4TrackId dstTrackId =
- MP4CloneTrack(srcFile, srcTrackId, dstFile);
+ if (dstFile == NULL) {
+ dstFile = srcFile;
+ }
- if (dstTrackId == MP4_INVALID_TRACK_ID) {
- return dstTrackId;
- }
+ const char* trackType =
+ MP4GetTrackType(srcFile, srcTrackId);
- bool viaEdits =
- applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId);
+ if (!trackType) {
+ return dstTrackId;
+ }
- MP4SampleId sampleId = 0;
- MP4SampleId numSamples =
- MP4GetTrackNumberOfSamples(srcFile, srcTrackId);
+ if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+ MP4SetVideoProfileLevel(dstFile, MP4GetVideoProfileLevel(srcFile));
+ dstTrackId = MP4AddEncVideoTrack(dstFile,
+ MP4GetTrackTimeScale(srcFile, srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile,
+ srcTrackId),
+ MP4GetTrackVideoWidth(srcFile, srcTrackId),
+ MP4GetTrackVideoHeight(srcFile, srcTrackId),
+ MP4GetTrackEsdsObjectTypeId(srcFile,
+ srcTrackId));
- MP4Timestamp when = 0;
- MP4Duration editsDuration =
- MP4GetTrackEditTotalDuration(srcFile, srcTrackId);
+ } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
+ MP4SetAudioProfileLevel(dstFile, MP4GetAudioProfileLevel(srcFile));
+ dstTrackId = MP4AddEncAudioTrack(dstFile,
+ MP4GetTrackTimeScale(srcFile, srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile,
+ srcTrackId),
+ MP4GetTrackEsdsObjectTypeId(srcFile,
+ srcTrackId));
- while (true) {
- MP4Duration sampleDuration = MP4_INVALID_DURATION;
+ } else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddODTrack(dstFile);
- if (viaEdits) {
- sampleId = MP4GetSampleIdFromEditTime(
- srcFile,
- srcTrackId,
- when,
- NULL,
- &sampleDuration);
+ } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddSceneTrack(dstFile);
+
+ } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddHintTrack(dstFile,
+ MP4GetHintTrackReferenceTrackId(srcFile,
+ srcTrackId));
- // in theory, this shouldn't happen
- if (sampleId == MP4_INVALID_SAMPLE_ID) {
- MP4DeleteTrack(dstFile, dstTrackId);
- return MP4_INVALID_TRACK_ID;
- }
+ } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddSystemsTrack(dstFile, trackType);
+
+ } else {
+ dstTrackId = MP4AddTrack(dstFile, trackType);
+ }
- when += sampleDuration;
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ return dstTrackId;
+ }
- if (when >= editsDuration) {
- break;
- }
- } else {
- sampleId++;
- if (sampleId > numSamples) {
- break;
- }
- }
+ MP4SetTrackTimeScale(dstFile,
+ dstTrackId,
+ MP4GetTrackTimeScale(srcFile, srcTrackId));
- bool rc = false;
+ if (MP4_IS_AUDIO_TRACK_TYPE(trackType)
+ || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+ // copy track ES configuration
+ u_int8_t* pConfig = NULL;
+ u_int32_t configSize = 0;
+ if (MP4GetTrackESConfiguration(srcFile, srcTrackId,
+ &pConfig, &configSize)) {
+
+ if (pConfig != NULL) {
+ MP4SetTrackESConfiguration(dstFile, dstTrackId,
+ pConfig, configSize);
+ }
+ }
+ if (pConfig != NULL)
+ free(pConfig);
+ }
- if (copySamples) {
- rc = MP4CopySample(
- srcFile,
- srcTrackId,
- sampleId,
- dstFile,
- dstTrackId,
- sampleDuration);
+ return dstTrackId;
+}
- } else {
- rc = MP4ReferenceSample(
- srcFile,
- srcTrackId,
- sampleId,
- dstFile,
- dstTrackId,
- sampleDuration);
- }
+extern "C" MP4TrackId MP4CopyTrack(MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile,
+ bool applyEdits)
+{
+ bool copySamples = true; // LATER allow false => reference samples
- if (!rc) {
- MP4DeleteTrack(dstFile, dstTrackId);
- return MP4_INVALID_TRACK_ID;
- }
- }
+ MP4TrackId dstTrackId =
+ MP4CloneTrack(srcFile, srcTrackId, dstFile);
- return dstTrackId;
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ return dstTrackId;
+ }
+
+ bool viaEdits =
+ applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId);
+
+ MP4SampleId sampleId = 0;
+ MP4SampleId numSamples =
+ MP4GetTrackNumberOfSamples(srcFile, srcTrackId);
+
+ MP4Timestamp when = 0;
+ MP4Duration editsDuration =
+ MP4GetTrackEditTotalDuration(srcFile, srcTrackId);
+
+ while (true) {
+ MP4Duration sampleDuration = MP4_INVALID_DURATION;
+
+ if (viaEdits) {
+ sampleId = MP4GetSampleIdFromEditTime(
+ srcFile,
+ srcTrackId,
+ when,
+ NULL,
+ &sampleDuration);
+
+ // in theory, this shouldn't happen
+ if (sampleId == MP4_INVALID_SAMPLE_ID) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+
+ when += sampleDuration;
+
+ if (when >= editsDuration) {
+ break;
+ }
+ } else {
+ sampleId++;
+ if (sampleId > numSamples) {
+ break;
+ }
+ }
+
+ bool rc = false;
+
+ if (copySamples) {
+ rc = MP4CopySample(
+ srcFile,
+ srcTrackId,
+ sampleId,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+
+ } else {
+ rc = MP4ReferenceSample(
+ srcFile,
+ srcTrackId,
+ sampleId,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+ }
+
+ if (!rc) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+ }
+
+ return dstTrackId;
}
+
+// Given a source track in a source file, make an encrypted copy of
+// the track in the destination file, including sample encryption
+extern "C" MP4TrackId MP4EncAndCopyTrack(MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile,
+ bool applyEdits)
+{
+ bool copySamples = true; // LATER allow false => reference samples
+
+ MP4TrackId dstTrackId =
+ MP4EncAndCloneTrack(srcFile, srcTrackId, dstFile);
+
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ return dstTrackId;
+ }
+
+ bool viaEdits =
+ applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId);
+
+ MP4SampleId sampleId = 0;
+ MP4SampleId numSamples =
+ MP4GetTrackNumberOfSamples(srcFile, srcTrackId);
+
+ MP4Timestamp when = 0;
+ MP4Duration editsDuration =
+ MP4GetTrackEditTotalDuration(srcFile, srcTrackId);
+
+ while (true) {
+ MP4Duration sampleDuration = MP4_INVALID_DURATION;
+
+ if (viaEdits) {
+ sampleId = MP4GetSampleIdFromEditTime(srcFile,
+ srcTrackId,
+ when,
+ NULL,
+ &sampleDuration);
+
+ // in theory, this shouldn't happen
+ if (sampleId == MP4_INVALID_SAMPLE_ID) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+
+ when += sampleDuration;
+
+ if (when >= editsDuration) {
+ break;
+ }
+ } else {
+ sampleId++;
+ if (sampleId > numSamples) {
+ break;
+ }
+ }
+
+ bool rc = false;
+
+ if (copySamples) {
+ // will need to encrypt the sample here
+ rc = MP4CopySample(srcFile,
+ srcTrackId,
+ sampleId,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+
+ } else {
+ rc = MP4ReferenceSample(srcFile,
+ srcTrackId,
+ sampleId,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+ }
+
+ if (!rc) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+ }
+
+ return dstTrackId;
+}
+
extern "C" bool MP4DeleteTrack(
MP4FileHandle hFile,
MP4TrackId trackId)
@@ -1002,12 +1216,16 @@
return false;
}
+
+// This function should not be used anymore
+// use MP4GetTrackEsdsObjectTypeId instead
extern "C" u_int8_t MP4GetTrackAudioType(
- MP4FileHandle hFile, MP4TrackId trackId)
+ MP4FileHandle hFile, MP4TrackId trackId)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- return ((MP4File*)hFile)->GetTrackAudioType(trackId);
+
+ return ((MP4File*)hFile)->GetTrackAudioType(trackId);
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -1033,6 +1251,8 @@
}
+// This function should not be used anymore
+// use MP4GetTrackEsdsObjectTypeId instead
extern "C" u_int8_t MP4GetTrackVideoType(
MP4FileHandle hFile, MP4TrackId trackId)
{
@@ -1048,6 +1268,24 @@
return MP4_INVALID_VIDEO_TYPE;
}
+// Replacement to MP4GetTrackVideoType and MP4GetTrackAudioType
+// Basically does the same thing but with a more self-explanatory name
+extern "C" u_int8_t MP4GetTrackEsdsObjectTypeId(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+
+ return ((MP4File*)hFile)->GetTrackEsdsObjectTypeId(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_AUDIO_TYPE;
+}
+
extern "C" MP4Duration MP4GetTrackFixedSampleDuration(
MP4FileHandle hFile, MP4TrackId trackId)
{
@@ -1079,7 +1317,7 @@
return 0;
}
-extern "C" void MP4GetTrackESConfiguration(
+extern "C" bool MP4GetTrackESConfiguration(
MP4FileHandle hFile, MP4TrackId trackId,
u_int8_t** ppConfig, u_int32_t* pConfigSize)
{
@@ -1087,7 +1325,7 @@
try {
((MP4File*)hFile)->GetTrackESConfiguration(
trackId, ppConfig, pConfigSize);
- return;
+ return true;
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -1096,7 +1334,7 @@
}
*ppConfig = NULL;
*pConfigSize = 0;
- return;
+ return false;
}
extern "C" bool MP4SetTrackESConfiguration(
@@ -1137,8 +1375,8 @@
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
- "mdia.minf.stbl.stsd.mp4v.width");
+ return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.*.width");
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -1154,7 +1392,7 @@
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
- "mdia.minf.stbl.stsd.mp4v.height");
+ "mdia.minf.stbl.stsd.*.height");
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -1400,7 +1638,7 @@
extern "C" bool MP4WriteSample(
MP4FileHandle hFile,
MP4TrackId trackId,
- u_int8_t* pBytes,
+ const u_int8_t* pBytes,
u_int32_t numBytes,
MP4Duration duration,
MP4Duration renderingOffset,
@@ -1765,12 +2003,15 @@
const char* pPayloadName,
u_int8_t* pPayloadNumber,
u_int16_t maxPayloadSize,
- const char *encode_params)
+ const char *encode_params,
+ bool include_rtp_map,
+ bool include_mpeg4_esid)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
((MP4File*)hFile)->SetHintTrackRtpPayload(
- hintTrackId, pPayloadName, pPayloadNumber, maxPayloadSize, encode_params);
+ hintTrackId, pPayloadName, pPayloadNumber, maxPayloadSize, encode_params,
+ include_rtp_map, include_mpeg4_esid);
return true;
}
catch (MP4Error* e) {
@@ -2517,13 +2758,16 @@
return NULL;
}
-/* tagging functions */
-extern "C" bool MP4TagDelete(MP4FileHandle hFile, MP4TrackId trackId)
+/* iTunes meta data handling */
+extern "C" bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index,
+ const char** ppName,
+ u_int8_t** ppValue, u_int32_t* pValueSize)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- return ((MP4File*)hFile)->TagDelete(trackId);
+ return ((MP4File*)hFile)->GetMetadataByIndex(
+ index, ppName, ppValue, pValueSize);
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -2530,14 +2774,14 @@
delete e;
}
}
+ return false;
}
-extern "C" bool MP4TagAddEntry(MP4FileHandle hFile, MP4TrackId trackId,
- const char *name, const char *value)
+extern "C" bool MP4MetadataDelete(MP4FileHandle hFile)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- return ((MP4File*)hFile)->TagAddEntry(trackId, name, value);
+ return ((MP4File*)hFile)->MetadataDelete();
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -2544,16 +2788,15 @@
delete e;
}
}
+ return false;
}
-#if 0
-extern "C" void MP4TagDeleteEntry(MP4FileHandle hFile, MP4TrackId trackId,
- u_int32_t index)
+extern "C" bool MP4SetMetadataName(MP4FileHandle hFile,
+ const char* value)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- ((MP4File*)hFile)->TagDeleteEntry(trackId, index);
- return;
+ return ((MP4File*)hFile)->SetMetadataName(value);
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -2560,32 +2803,30 @@
delete e;
}
}
+ return false;
}
-#endif
-extern "C" u_int32_t MP4TagGetNumEntries(MP4FileHandle hFile, MP4TrackId trackId)
+extern "C" bool MP4GetMetadataName(MP4FileHandle hFile,
+ char** value)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- return ((MP4File*)hFile)->TagGetNumEntries(trackId);
+ return ((MP4File*)hFile)->GetMetadataName(value);
}
catch (MP4Error* e) {
PRINT_ERROR(e);
delete e;
- return 0;
}
}
+ return false;
}
-extern "C" void MP4TagGetEntry(MP4FileHandle hFile, MP4TrackId trackId,
- u_int32_t index, const char **name,
- const char **value)
+extern "C" bool MP4SetMetadataWriter(MP4FileHandle hFile,
+ const char* value)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- ((MP4File*)hFile)->TagGetEntry(trackId, index,
- name, value);
- return;
+ return ((MP4File*)hFile)->SetMetadataWriter(value);
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -2592,14 +2833,15 @@
delete e;
}
}
+ return false;
}
-extern "C" bool MP4TagGetEntryByName(MP4FileHandle hFile, MP4TrackId trackId,
- char *name, const char **value)
+extern "C" bool MP4GetMetadataWriter(MP4FileHandle hFile,
+ char** value)
{
if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
try {
- return ((MP4File*)hFile)->TagGetEntryByName(trackId, name, value);
+ return ((MP4File*)hFile)->GetMetadataWriter(value);
}
catch (MP4Error* e) {
PRINT_ERROR(e);
@@ -2606,4 +2848,359 @@
delete e;
}
}
+ return false;
+}
+
+extern "C" bool MP4SetMetadataAlbum(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataAlbum(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataAlbum(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataAlbum(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataArtist(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataArtist(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataArtist(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataArtist(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataTool(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataTool(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataTool(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataTool(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataComment(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataComment(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataComment(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataComment(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataYear(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataYear(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataYear(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataYear(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataTrack(MP4FileHandle hFile,
+ u_int16_t track, u_int16_t totalTracks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataTrack(track, totalTracks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataTrack(MP4FileHandle hFile,
+ u_int16_t* track, u_int16_t* totalTracks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataTrack(track, totalTracks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataDisk(MP4FileHandle hFile,
+ u_int16_t disk, u_int16_t totalDisks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataDisk(disk, totalDisks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataDisk(MP4FileHandle hFile,
+ u_int16_t* disk, u_int16_t* totalDisks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataDisk(disk, totalDisks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataGenre(MP4FileHandle hFile, u_int16_t genre)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataGenre(genre);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataGenre(MP4FileHandle hFile, u_int16_t* genre)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataGenre(genre);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataTempo(tempo);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataTempo(tempo);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataCompilation(cpl);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataCompilation(cpl);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataCoverArt(MP4FileHandle hFile,
+ u_int8_t *coverArt, u_int32_t size)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataCoverArt(coverArt, size);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataCoverArt(MP4FileHandle hFile,
+ u_int8_t **coverArt, u_int32_t* size)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataCoverArt(coverArt, size);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name,
+ u_int8_t* pValue, u_int32_t valueSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataFreeForm(name, pValue, valueSize);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name,
+ u_int8_t** pValue, u_int32_t* valueSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataFreeForm(name, pValue, valueSize);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
}
--- a/common/mp4v2/mp4.h
+++ b/common/mp4v2/mp4.h
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#ifndef __MP4_INCLUDED__
@@ -167,7 +168,8 @@
#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_SCALABLE_AUDIO_TYPE)
+ || (mpeg4Type) == MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE \
+ || (mpeg4Type) == 17)
#define MP4_IS_AAC_AUDIO_TYPE(type) \
(MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \
@@ -206,15 +208,6 @@
/* MP4 API declarations */
-typedef u_int32_t (*MP4OpenCallback)(const char *pName, const char *mode, void *userData);
-typedef void (*MP4CloseCallback)(void *userData);
-typedef u_int32_t (*MP4ReadCallback)(void *pBuffer, unsigned int nBytesToRead, void *userData);
-typedef u_int32_t (*MP4WriteCallback)(void *pBuffer, unsigned int nBytesToWrite, void *userData);
-typedef int32_t (*MP4SetposCallback)(u_int32_t pos, void *userData);
-typedef int64_t (*MP4GetposCallback)(void *userData);
-typedef int64_t (*MP4FilesizeCallback)(void *userData);
-
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -236,23 +229,6 @@
const char* fileName,
u_int32_t verbosity DEFAULT(0));
-MP4FileHandle MP4ReadCb(u_int32_t verbosity,
- MP4OpenCallback MP4fopen,
- MP4CloseCallback MP4fclose,
- MP4ReadCallback MP4fread,
- MP4WriteCallback MP4fwrite,
- MP4SetposCallback MP4fsetpos,
- MP4GetposCallback MP4fgetpos,
- MP4FilesizeCallback MP4filesize,
- void *userData);
-
-MP4FileHandle MP4ModifyCb(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);
@@ -367,6 +343,12 @@
MP4Duration sampleDuration,
u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE));
+MP4TrackId MP4AddEncAudioTrack(
+ MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE));
+
MP4TrackId MP4AddVideoTrack(
MP4FileHandle hFile,
u_int32_t timeScale,
@@ -375,6 +357,14 @@
u_int16_t height,
u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE));
+MP4TrackId MP4AddEncVideoTrack(
+ MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE));
+
MP4TrackId MP4AddHintTrack(
MP4FileHandle hFile,
MP4TrackId refTrackId);
@@ -384,6 +374,11 @@
MP4TrackId srcTrackId,
MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE));
+MP4TrackId MP4EncAndCloneTrack(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE));
+
MP4TrackId MP4CopyTrack(
MP4FileHandle srcFile,
MP4TrackId srcTrackId,
@@ -390,6 +385,12 @@
MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
bool applyEdits DEFAULT(false));
+MP4TrackId MP4EncAndCopyTrack(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE),
+ bool applyEdits DEFAULT(false));
+
bool MP4DeleteTrack(
MP4FileHandle hFile,
MP4TrackId trackId);
@@ -430,6 +431,7 @@
MP4TrackId trackId,
u_int32_t value);
+// Should not be used, replace with MP4GetTrackEsdsObjectTypeId
u_int8_t MP4GetTrackAudioType(
MP4FileHandle hFile,
MP4TrackId trackId);
@@ -438,10 +440,15 @@
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);
+
/* returns MP4_INVALID_DURATION if track samples do not have a fixed duration */
MP4Duration MP4GetTrackFixedSampleDuration(
MP4FileHandle hFile,
@@ -451,7 +458,7 @@
MP4FileHandle hFile,
MP4TrackId trackId);
-void MP4GetTrackESConfiguration(
+bool MP4GetTrackESConfiguration(
MP4FileHandle hFile,
MP4TrackId trackId,
u_int8_t** ppConfig,
@@ -562,7 +569,7 @@
bool MP4WriteSample(
MP4FileHandle hFile,
MP4TrackId trackId,
- u_int8_t* pBytes,
+ const u_int8_t* pBytes,
u_int32_t numBytes,
MP4Duration duration DEFAULT(MP4_INVALID_DURATION),
MP4Duration renderingOffset DEFAULT(0),
@@ -644,7 +651,9 @@
const char* pPayloadName,
u_int8_t* pPayloadNumber,
u_int16_t maxPayloadSize DEFAULT(0),
- const char *encode_params DEFAULT(NULL));
+ const char *encode_params DEFAULT(NULL),
+ bool include_rtp_map DEFAULT(true),
+ bool include_mpeg4_esid DEFAULT(true));
const char* MP4GetSessionSdp(
MP4FileHandle hFile);
@@ -907,18 +916,73 @@
const u_int8_t* pData,
u_int32_t dataSize);
-bool MP4TagDelete(MP4FileHandle hFile, MP4TrackId trackId);
-bool 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);
-bool MP4TagGetEntryByName(MP4FileHandle hFile, MP4TrackId trackId,
- char *name, const char **value);
+/* iTunes metadata handling */
+bool MP4MetadataDelete(MP4FileHandle hFile);
+bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index,
+ const char** ppName,
+ u_int8_t** ppValue, u_int32_t* pValueSize);
+bool MP4SetMetadataName(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataName(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataArtist(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataArtist(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataWriter(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataWriter(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataComment(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataComment(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataTool(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataTool(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataYear(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataYear(MP4FileHandle hFile, char** value);
+bool MP4SetMetadataAlbum(MP4FileHandle hFile, const char* value);
+bool MP4GetMetadataAlbum(MP4FileHandle hFile, char** value);
+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 MP4SetMetadataDisk(MP4FileHandle hFile,
+ u_int16_t disk, u_int16_t totalDisks);
+bool MP4GetMetadataDisk(MP4FileHandle hFile,
+ u_int16_t* disk, u_int16_t* totalDisks);
+bool MP4SetMetadataGenre(MP4FileHandle hFile, u_int16_t genre);
+bool MP4GetMetadataGenre(MP4FileHandle hFile, u_int16_t* genre);
+bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo);
+bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo);
+bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl);
+bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl);
+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);
+
+//#ifdef USE_FILE_CALLBACKS
+typedef u_int32_t (*MP4OpenCallback)(const char *pName, const char *mode, void *userData);
+typedef void (*MP4CloseCallback)(void *userData);
+typedef u_int32_t (*MP4ReadCallback)(void *pBuffer, unsigned int nBytesToRead, void *userData);
+typedef u_int32_t (*MP4WriteCallback)(void *pBuffer, unsigned int nBytesToWrite, void *userData);
+typedef int32_t (*MP4SetposCallback)(u_int32_t pos, void *userData);
+typedef int64_t (*MP4GetposCallback)(void *userData);
+typedef int64_t (*MP4FilesizeCallback)(void *userData);
+
+MP4FileHandle MP4ReadCb(u_int32_t verbosity,
+ MP4OpenCallback MP4fopen,
+ MP4CloseCallback MP4fclose,
+ MP4ReadCallback MP4fread,
+ MP4WriteCallback MP4fwrite,
+ MP4SetposCallback MP4fsetpos,
+ MP4GetposCallback MP4fgetpos,
+ MP4FilesizeCallback MP4filesize,
+ void *userData);
+MP4FileHandle MP4ModifyCb(int32_t verbosity,
+ bool useExtensibleFormat,
+ MP4OpenCallback MP4fopen, MP4CloseCallback MP4fclose,
+ MP4ReadCallback MP4fread, MP4WriteCallback MP4fwrite,
+ MP4SetposCallback MP4fsetpos, MP4GetposCallback MP4fgetpos,
+ MP4FilesizeCallback MP4filesize, void *userData);
+//#endif
#ifdef __cplusplus
}
--- a/common/mp4v2/mp4atom.cpp
+++ b/common/mp4v2/mp4atom.cpp
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#include "mp4common.h"
@@ -59,184 +60,269 @@
MP4Atom* MP4Atom::CreateAtom(const char* type)
{
- MP4Atom* pAtom = NULL;
+ MP4Atom* pAtom = NULL;
- if (type == NULL) {
- pAtom = new MP4RootAtom();
- } else if (type[0] == '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 (type[0] == 'd') {
- 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 (type[0] == 'e') {
- if (ATOMID(type) == ATOMID("esds")) {
- pAtom = new MP4EsdsAtom();
- } else if (ATOMID(type) == ATOMID("edts")) {
- pAtom = new MP4EdtsAtom();
- } else if (ATOMID(type) == ATOMID("elst")) {
- pAtom = new MP4ElstAtom();
- }
- } else if (type[0] == '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")) {
- pAtom = new MP4HntiAtom();
- } else if (ATOMID(type) == ATOMID("hinf")) {
- pAtom = new MP4HinfAtom();
- }
- } else if (type[0] == 'm') {
- if (ATOMID(type) == ATOMID("mdia")) {
- pAtom = new MP4MdiaAtom();
- } else if (ATOMID(type) == ATOMID("minf")) {
- pAtom = new MP4MinfAtom();
- } else 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("mpod")) {
- pAtom = new MP4TrefTypeAtom(type);
- } else if (ATOMID(type) == ATOMID("mp4a")) {
- pAtom = new MP4Mp4aAtom();
- } else if (ATOMID(type) == ATOMID("mp4s")) {
- pAtom = new MP4Mp4sAtom();
- } else if (ATOMID(type) == ATOMID("mp4v")) {
- pAtom = new MP4Mp4vAtom();
- } else if (ATOMID(type) == ATOMID("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 (type[0] == 's') {
- 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("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 (type[0] == 't') {
- if (ATOMID(type) == ATOMID("trak")) {
- pAtom = new MP4TrakAtom();
- } 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 (type[0] == 'u') {
- if (ATOMID(type) == ATOMID("udta")) {
- pAtom = new MP4UdtaAtom();
- } else if (ATOMID(type) == ATOMID("url ")) {
- pAtom = new MP4UrlAtom();
- } else if (ATOMID(type) == ATOMID("urn ")) {
- pAtom = new MP4UrnAtom();
- }
- } else {
- if (ATOMID(type) == ATOMID("free")) {
- pAtom = new MP4FreeAtom();
- } else if (ATOMID(type) == ATOMID("ftyp")) {
- pAtom = new MP4FtypAtom();
- } else if (ATOMID(type) == ATOMID("iods")) {
- pAtom = new MP4IodsAtom();
- } else if (ATOMID(type) == ATOMID("ipir")) {
- pAtom = new MP4TrefTypeAtom(type);
- } else if (ATOMID(type) == ATOMID("nmhd")) {
- pAtom = new MP4NmhdAtom();
- } else if (ATOMID(type) == ATOMID("nump")) {
- pAtom = new MP4NumpAtom();
- } else if (ATOMID(type) == ATOMID("pmax")) {
- pAtom = new MP4PmaxAtom();
- } else if (ATOMID(type) == ATOMID("payt")) {
- pAtom = new MP4PaytAtom();
- } else if (ATOMID(type) == ATOMID("rtp ")) {
- pAtom = new MP4RtpAtom();
- } else if (ATOMID(type) == ATOMID("vmhd")) {
- pAtom = new MP4VmhdAtom();
- } else if (ATOMID(type) == ATOMID("TAG4")) {
- pAtom = new MP4Tag4Atom();
- }
- }
+ if (type == NULL) {
+ pAtom = new MP4RootAtom();
+ } else {
+ switch(type[0]) {
+ 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();
+ }
+ break;
+ case 'd':
+ 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")) {
+ pAtom = new MP4ElstAtom();
+ } else if (ATOMID(type) == ATOMID("enca")) {
+ pAtom = new MP4EncaAtom();
+ } else if (ATOMID(type) == ATOMID("encv")) {
+ pAtom = new MP4EncvAtom();
+ }
+ break;
+ case 'f':
+ if (ATOMID(type) == ATOMID("free")) {
+ pAtom = new MP4FreeAtom();
+ } else if (ATOMID(type) == ATOMID("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();
+ }
+ 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")) {
+ pAtom = new MP4HntiAtom();
+ } else if (ATOMID(type) == ATOMID("hinf")) {
+ pAtom = new MP4HinfAtom();
+ }
+ 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")) {
+ pAtom = new MP4TrefTypeAtom(type);
+ } else if (ATOMID(type) == ATOMID("ilst")) { /* Apple iTunes */
+ pAtom = new MP4IlstAtom();
+ }
+ 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")) {
+ 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("mpod")) {
+ pAtom = new MP4TrefTypeAtom(type);
+ } else if (ATOMID(type) == ATOMID("mp4a")) {
+ pAtom = new MP4Mp4aAtom();
+ } else if (ATOMID(type) == ATOMID("mp4s")) {
+ pAtom = new MP4Mp4sAtom();
+ } else if (ATOMID(type) == ATOMID("mp4v")) {
+ pAtom = new MP4Mp4vAtom();
+ } else if (ATOMID(type) == ATOMID("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")) { /* Apple iTunes */
+ pAtom = new MP4MetaAtom();
+ } else if (ATOMID(type) == ATOMID("mean")) { /* Apple iTunes */
+ pAtom = new MP4MeanAtom();
+ }
+ 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")) {
+ pAtom = new MP4NameAtom();
+ }
+ break;
+ case 'p':
+ if (ATOMID(type) == ATOMID("pmax")) {
+ pAtom = new MP4PmaxAtom();
+ } else if (ATOMID(type) == ATOMID("payt")) {
+ pAtom = new MP4PaytAtom();
+ }
+ break;
+ case 'r':
+ if (ATOMID(type) == ATOMID("rtp ")) {
+ pAtom = new MP4RtpAtom();
+ }
+ break;
+ case 's':
+ 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();
+ } 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("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");
+ }
+ break;
+ case 't':
+ if (ATOMID(type) == ATOMID("trak")) {
+ pAtom = new MP4TrakAtom();
+ } 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")) { /* Apple iTunes */
+ pAtom = new MP4TrknAtom();
+ } else if (ATOMID(type) == ATOMID("tmpo")) { /* Apple iTunes */
+ pAtom = new MP4TmpoAtom();
+ }
+ break;
+ case 'u':
+ if (ATOMID(type) == ATOMID("udta")) {
+ pAtom = new MP4UdtaAtom();
+ } else if (ATOMID(type) == ATOMID("url ")) {
+ pAtom = new MP4UrlAtom();
+ } else if (ATOMID(type) == ATOMID("urn ")) {
+ pAtom = new MP4UrnAtom();
+ }
+ break;
+ case 'v':
+ if (ATOMID(type) == ATOMID("vmhd")) {
+ pAtom = new MP4VmhdAtom();
+ }
+ break;
+ case '�':
+ if (ATOMID(type) == ATOMID("�nam")) {
+ 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();
+ }
+ break;
+ case '-':
+ if (ATOMID(type) == ATOMID("----")) { /* Apple iTunes */
+ pAtom = new MP4DashAtom();
+ }
+ }
+ }
- if (pAtom == NULL) {
- pAtom = new MP4Atom(type);
- pAtom->SetUnknownType(true);
- }
+ if (pAtom == NULL) {
+ pAtom = new MP4Atom(type);
+ pAtom->SetUnknownType(true);
+ }
- ASSERT(pAtom);
- return pAtom;
+ ASSERT(pAtom);
+ return pAtom;
}
// generate a skeletal self
@@ -613,6 +699,7 @@
void MP4Atom::BeginWrite(bool use64)
{
m_start = m_pFile->GetPosition();
+ //use64 = m_pFile->Use64Bits();
if (use64) {
m_pFile->WriteUInt32(1);
} else {
@@ -631,6 +718,7 @@
{
m_end = m_pFile->GetPosition();
m_size = (m_end - m_start);
+ //use64 = m_pFile->Use64Bits();
if (use64) {
m_pFile->SetPosition(m_start + 8);
m_pFile->WriteUInt64(m_size);
--- a/common/mp4v2/mp4file.cpp
+++ b/common/mp4v2/mp4file.cpp
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#include "mp4common.h"
@@ -547,8 +548,8 @@
}
#ifndef USE_FILE_CALLBACKS
- fclose(m_pFile);
- m_pFile = NULL;
+ fclose(m_pFile);
+ m_pFile = NULL;
#else
m_MP4fclose(this);
#endif
@@ -1089,7 +1090,15 @@
pStsdCountProperty->IncrementValue();
SetTrackIntegerProperty(trackId,
- "mdia.minf.stbl.stsd.mp4s.esds.ESID", trackId);
+ "mdia.minf.stbl.stsd.mp4s.esds.ESID",
+#if 0
+ // note - for a file, these values need to
+ // be 0 - wmay - 04/16/2003
+ trackId
+#else
+ 0
+#endif
+ );
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId",
@@ -1157,7 +1166,15 @@
"mdia.minf.stbl.stsd.mp4a.timeScale", timeScale);
SetTrackIntegerProperty(trackId,
- "mdia.minf.stbl.stsd.mp4a.esds.ESID", trackId);
+ "mdia.minf.stbl.stsd.mp4a.esds.ESID",
+#if 0
+ // note - for a file, these values need to
+ // be 0 - wmay - 04/16/2003
+ trackId
+#else
+ 0
+#endif
+ );
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId",
@@ -1173,6 +1190,56 @@
return trackId;
}
+MP4TrackId MP4File::AddEncAudioTrack(u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int8_t audioType)
+{
+ MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale);
+
+ AddTrackToOd(trackId);
+
+ SetTrackFloatProperty(trackId, "tkhd.volume", 1.0);
+
+ InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "smhd", 0);
+
+ AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "enca");
+
+ // stsd is a unique beast in that it has a count of the number
+ // of child atoms that needs to be incremented after we add the enca atom
+ MP4Integer32Property* pStsdCountProperty;
+ FindIntegerProperty(
+ MakeTrackName(trackId, "mdia.minf.stbl.stsd.entryCount"),
+ (MP4Property**)&pStsdCountProperty);
+ pStsdCountProperty->IncrementValue();
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.enca.timeScale", timeScale);
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.enca.esds.ESID",
+#if 0
+ // note - for a file, these values need to
+ // be 0 - wmay - 04/16/2003
+ trackId
+#else
+ 0
+#endif
+ );
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.enca.esds.decConfigDescr.objectTypeId",
+ audioType);
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.enca.esds.decConfigDescr.streamType",
+ MP4AudioStreamType);
+
+ m_pTracks[FindTrackIndex(trackId)]->
+ SetFixedSampleDuration(sampleDuration);
+
+ return trackId;
+}
+
MP4TrackId MP4File::AddVideoTrack(
u_int32_t timeScale,
MP4Duration sampleDuration,
@@ -1205,7 +1272,15 @@
"mdia.minf.stbl.stsd.mp4v.height", height);
SetTrackIntegerProperty(trackId,
- "mdia.minf.stbl.stsd.mp4v.esds.ESID", trackId);
+ "mdia.minf.stbl.stsd.mp4v.esds.ESID",
+#if 0
+ // note - for a file, these values need to
+ // be 0 - wmay - 04/16/2003
+ trackId
+#else
+ 0
+#endif
+ );
SetTrackIntegerProperty(trackId,
"mdia.minf.stbl.stsd.mp4v.esds.decConfigDescr.objectTypeId",
@@ -1224,6 +1299,64 @@
return trackId;
}
+MP4TrackId MP4File::AddEncVideoTrack(u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ u_int8_t videoType)
+{
+ MP4TrackId trackId = AddTrack(MP4_VIDEO_TRACK_TYPE, timeScale);
+
+ AddTrackToOd(trackId);
+
+ SetTrackFloatProperty(trackId, "tkhd.width", width);
+ SetTrackFloatProperty(trackId, "tkhd.height", height);
+
+ InsertChildAtom(MakeTrackName(trackId, "mdia.minf"), "vmhd", 0);
+
+ AddChildAtom(MakeTrackName(trackId, "mdia.minf.stbl.stsd"), "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,
+ "mdia.minf.stbl.stsd.encv.height", height);
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.encv.esds.ESID",
+#if 0
+ // note - for a file, these values need to
+ // be 0 - wmay - 04/16/2003
+ trackId
+#else
+ 0
+#endif
+ );
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.encv.esds.decConfigDescr.objectTypeId",
+ videoType);
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.encv.esds.decConfigDescr.streamType",
+ MP4VisualStreamType);
+
+ SetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsz.sampleSize", sampleDuration);
+
+ m_pTracks[FindTrackIndex(trackId)]->
+ SetFixedSampleDuration(sampleDuration);
+
+ return trackId;
+}
+
MP4TrackId MP4File::AddHintTrack(MP4TrackId refTrackId)
{
// validate reference track id
@@ -1303,11 +1436,11 @@
if (!strcmp(normType, m_pTracks[i]->GetType())) {
if (subType) {
if (normType == MP4_AUDIO_TRACK_TYPE) {
- if (subType != GetTrackAudioType(m_pTracks[i]->GetId())) {
+ if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
} else if (normType == MP4_VIDEO_TRACK_TYPE) {
- if (subType != GetTrackVideoType(m_pTracks[i]->GetId())) {
+ if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
}
@@ -1356,43 +1489,43 @@
return MP4_INVALID_TRACK_ID; // to keep MSVC happy
}
-MP4TrackId MP4File::FindTrackId(
- u_int16_t trackIndex, const char* type, u_int8_t subType)
+MP4TrackId MP4File::FindTrackId(u_int16_t trackIndex,
+ const char* type, u_int8_t subType)
{
- if (type == NULL) {
- return m_pTracks[trackIndex]->GetId();
- }
+ if (type == NULL) {
+ return m_pTracks[trackIndex]->GetId();
+ }
- u_int32_t typeSeen = 0;
- const char* normType = MP4Track::NormalizeTrackType(type);
+ u_int32_t typeSeen = 0;
+ const char* normType = MP4Track::NormalizeTrackType(type);
- for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
- if (!strcmp(normType, m_pTracks[i]->GetType())) {
- if (subType) {
- if (normType == MP4_AUDIO_TRACK_TYPE) {
- if (subType != GetTrackAudioType(m_pTracks[i]->GetId())) {
- continue;
- }
- } else if (normType == MP4_VIDEO_TRACK_TYPE) {
- if (subType != GetTrackVideoType(m_pTracks[i]->GetId())) {
- continue;
- }
- }
- // else unknown subtype, ignore it
- }
+ for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
+ if (!strcmp(normType, m_pTracks[i]->GetType())) {
+ if (subType) {
+ if (normType == MP4_AUDIO_TRACK_TYPE) {
+ if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
+ continue;
+ }
+ } else if (normType == MP4_VIDEO_TRACK_TYPE) {
+ if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
+ continue;
+ }
+ }
+ // else unknown subtype, ignore it
+ }
- if (trackIndex == typeSeen) {
- return m_pTracks[i]->GetId();
- }
+ if (trackIndex == typeSeen) {
+ return m_pTracks[i]->GetId();
+ }
- typeSeen++;
- }
- }
+ typeSeen++;
+ }
+ }
- throw new MP4Error("Track index doesn't exist - track %d type %s",
- "FindTrackId",
- trackIndex, type);
- return MP4_INVALID_TRACK_ID; // satisfy MS compiler
+ throw new MP4Error("Track index doesn't exist - track %d type %s",
+ "FindTrackId",
+ trackIndex, type);
+ return MP4_INVALID_TRACK_ID; // satisfy MS compiler
}
u_int16_t MP4File::FindTrackIndex(MP4TrackId trackId)
@@ -1480,7 +1613,7 @@
}
void MP4File::WriteSample(MP4TrackId trackId,
- u_int8_t* pBytes, u_int32_t numBytes,
+ const u_int8_t* pBytes, u_int32_t numBytes,
MP4Duration duration, MP4Duration renderingOffset, bool isSyncSample)
{
ProtectWriteOperation("MP4WriteSample");
@@ -1701,16 +1834,24 @@
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
return GetTrackIntegerProperty(trackId,
- "mdia.minf.stbl.stsd.mp4a.esds.decConfigDescr.objectTypeId");
+ "mdia.minf.stbl.stsd.*.esds.decConfigDescr.objectTypeId");
}
u_int8_t MP4File::GetTrackAudioMpeg4Type(MP4TrackId trackId)
{
// verify that track is an MPEG-4 audio track
- if (GetTrackAudioType(trackId) != MP4_MPEG4_AUDIO_TYPE) {
+ if (GetTrackEsdsObjectTypeId(trackId) != MP4_MPEG4_AUDIO_TYPE) {
return MP4_MPEG4_INVALID_AUDIO_TYPE;
}
@@ -1733,6 +1874,7 @@
return mpeg4Type;
}
+// replaced with GetTrackEsdsObjectTypeId
u_int8_t MP4File::GetTrackVideoType(MP4TrackId trackId)
{
return GetTrackIntegerProperty(trackId,
@@ -1748,11 +1890,7 @@
{
MP4SampleId numSamples =
GetTrackNumberOfSamples(trackId);
-#ifdef _WIN32
- int64_t
-#else
u_int64_t
-#endif
msDuration =
ConvertFromTrackDuration(trackId,
GetTrackDuration(trackId), MP4_MSECS_TIME_SCALE);
@@ -1761,7 +1899,7 @@
return 0.0;
}
- return ((double)numSamples / (double)msDuration) * MP4_MSECS_TIME_SCALE;
+ return ((double)numSamples / UINT64_TO_DOUBLE(msDuration)) * MP4_MSECS_TIME_SCALE;
}
void MP4File::GetTrackESConfiguration(MP4TrackId trackId,
@@ -1869,7 +2007,9 @@
void MP4File::SetHintTrackRtpPayload(MP4TrackId hintTrackId,
const char* payloadName, u_int8_t* pPayloadNumber, u_int16_t maxPayloadSize,
- const char *encoding_params)
+ const char *encoding_params,
+ bool include_rtp_map,
+ bool include_mpeg4_esid)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
@@ -1889,7 +2029,8 @@
}
((MP4RtpHintTrack*)pTrack)->SetPayload(
- payloadName, payloadNumber, maxPayloadSize, encoding_params);
+ payloadName, payloadNumber, maxPayloadSize, encoding_params,
+ include_rtp_map, include_mpeg4_esid);
}
u_int8_t MP4File::AllocRtpPayloadNumber()
@@ -2140,7 +2281,7 @@
MP4Timestamp timeStamp,
u_int32_t timeScale)
{
- return MP4ConvertTime((u_int64_t)timeStamp,
+ return MP4ConvertTime(timeStamp,
GetTrackTimeScale(trackId), timeScale);
}
@@ -2312,187 +2453,3 @@
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");
-}
-
-bool 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"));
- }
- /* there is no tag */
- if (!pUdtaAtom || !pTagAtom)
- return false;
-
- pUdtaAtom->DeleteChildAtom(pTagAtom);
-
- delete pTagAtom;
-
- return true;
-}
-
-bool 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"));
- if (!pTagAtom)
- {
- TagCreate(trackId);
- 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);
-
- {
- char name2[128];
- if (strlen(name) > 126)
- {
- memcpy(name2, name, 127);
- name2[127] = '\0';
- pNameProperty->AddValue((char*)name2);
- } else {
- pNameProperty->AddValue((char*)name);
- }
- }
-
- pTagAtom->FindProperty("TAG4.entries.value",
- (MP4Property**)&pValueProperty);
- ASSERT(pValueProperty);
-
- {
- char value2[128];
- if (strlen(value) > 126)
- {
- memcpy(value2, value, 127);
- value2[127] = '\0';
- pValueProperty->AddValue((char*)value2);
- } else {
- pValueProperty->AddValue((char*)value);
- }
- }
-
- pCountProperty->IncrementValue();
-
- return true;
-}
-
-#if 0 // not working
-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);
- }
-}
-
-bool MP4File::TagGetEntryByName(MP4TrackId trackId, char *name,
- const char **value)
-{
- int numEntries = TagGetNumEntries(trackId);
-
- for (int i = 0; i < numEntries; i++)
- {
- const char *n = NULL, *v = NULL;
- TagGetEntry(trackId, i, &n, &v);
-
- if (!strcmp(n, name))
- {
- *value = v;
- return true;
- }
- }
-
- return false;
-}
--- a/common/mp4v2/mp4file.h
+++ b/common/mp4v2/mp4file.h
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#ifndef __MP4_FILE_INCLUDED__
@@ -31,6 +32,7 @@
class MP4Descriptor;
class MP4DescriptorProperty;
+
#ifdef USE_FILE_CALLBACKS
typedef u_int32_t (*MP4OpenCallback)(const char *pName, const char *mode, void *userData);
typedef void (*MP4CloseCallback)(void *userData);
@@ -180,7 +182,7 @@
void WriteSample(
MP4TrackId trackId,
- u_int8_t* pBytes,
+ const u_int8_t* pBytes,
u_int32_t numBytes,
MP4Duration duration = 0,
MP4Duration renderingOffset = 0,
@@ -204,6 +206,11 @@
MP4Duration sampleDuration,
u_int8_t audioType);
+ MP4TrackId AddEncAudioTrack( // ismacrypt
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int8_t audioType);
+
MP4TrackId AddVideoTrack(
u_int32_t timeScale,
MP4Duration sampleDuration,
@@ -210,6 +217,13 @@
u_int16_t width,
u_int16_t height,
u_int8_t videoType);
+
+ MP4TrackId AddEncVideoTrack( // ismacrypt
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ u_int8_t videoType);
MP4TrackId AddHintTrack(MP4TrackId refTrackId);
@@ -222,6 +236,9 @@
u_int32_t GetTrackTimeScale(MP4TrackId trackId);
void SetTrackTimeScale(MP4TrackId trackId, u_int32_t value);
+ // replacement to GetTrackAudioType and GetTrackVideoType
+ u_int8_t GetTrackEsdsObjectTypeId(MP4TrackId trackId);
+
u_int8_t GetTrackAudioType(MP4TrackId trackId);
u_int8_t GetTrackAudioMpeg4Type(MP4TrackId trackId);
u_int8_t GetTrackVideoType(MP4TrackId trackId);
@@ -295,7 +312,9 @@
const char* payloadName,
u_int8_t* pPayloadNumber,
u_int16_t maxPayloadSize,
- const char *encoding_params);
+ const char *encoding_params,
+ bool include_rtp_map,
+ bool include_mpeg4_esid);
MP4TrackId GetHintTrackReferenceTrackId(
MP4TrackId hintTrackId);
@@ -422,16 +441,45 @@
MP4Timestamp* pStartTime = NULL,
MP4Duration* pDuration = NULL);
- /* tagging */
- void TagCreate(MP4TrackId trackId);
- bool TagDelete(MP4TrackId trackId);
- bool TagAddEntry(MP4TrackId trackId,
- const char *name, const char *value);
- u_int32_t TagGetNumEntries(MP4TrackId trackId);
- void TagGetEntry(MP4TrackId trackId, u_int32_t index,
- const char **name, const char **value);
- bool TagGetEntryByName(MP4TrackId trackId, char *name,
- const char **value);
+ /* iTunes metadata handling */
+ bool CreateMetadataAtom(const char* name);
+ bool MetadataDelete();
+
+ /* 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(u_int16_t genreIndex);
+ bool SetMetadataTempo(u_int16_t tempo);
+ bool SetMetadataCompilation(u_int8_t compilation);
+ bool SetMetadataCoverArt(u_int8_t *coverArt, u_int32_t size);
+ bool SetMetadataFreeForm(char *name, u_int8_t* pValue, u_int32_t valueSize);
+
+ /* get metadata */
+ bool GetMetadataByIndex(u_int32_t index,
+ const char** ppName,
+ u_int8_t** ppValue, u_int32_t* pValueSize);
+ bool GetMetadataName(char** value);
+ bool GetMetadataWriter(char** value);
+ bool GetMetadataAlbum(char** value);
+ bool GetMetadataArtist(char** value);
+ bool GetMetadataTool(char** value);
+ bool GetMetadataComment(char** value);
+ bool GetMetadataYear(char** value);
+ bool GetMetadataTrack(u_int16_t* track, u_int16_t* totalTracks);
+ bool GetMetadataDisk(u_int16_t* disk, u_int16_t* totalDisks);
+ bool GetMetadataGenre(u_int16_t* genreIndex);
+ bool GetMetadataTempo(u_int16_t* tempo);
+ bool GetMetadataCompilation(u_int8_t* compilation);
+ bool GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t* size);
+ bool GetMetadataFreeForm(char *name, u_int8_t** pValue, u_int32_t* valueSize);
+
/* end of MP4 API */
--- a/common/mp4v2/mp4file_io.cpp
+++ b/common/mp4v2/mp4file_io.cpp
@@ -34,14 +34,13 @@
u_int64_t MP4File::GetPosition(FILE* pFile)
{
if (m_memoryBuffer == NULL) {
- int64_t pos;
#ifndef USE_FILE_CALLBACKS
+ fpos_t fpos;
if (pFile == NULL) {
ASSERT(m_pFile);
pFile = m_pFile;
}
- fpos_t fpos;
if (fgetpos(pFile, &fpos) < 0) {
throw new MP4Error(errno, "MP4GetPosition");
}
@@ -48,6 +47,7 @@
return FPOS_TO_UINT64(fpos);
#else
+ u_int64_t pos;
if ((pos = m_MP4fgetpos(m_userData)) < 0) {
throw new MP4Error(errno, "MP4GetPosition");
}
@@ -199,6 +199,7 @@
ASSERT(m_pFile);
pFile = m_pFile;
}
+
u_int32_t rc = fwrite(pBytes, 1, numBytes, pFile);
#else
u_int32_t rc = m_MP4fwrite(pBytes, numBytes, m_userData);
@@ -474,7 +475,7 @@
WriteUInt8(charLength);
} else {
if (charLength > 255) {
- throw new MP4Error(ERANGE, "MP4WriteCountedString");
+ throw new MP4Error(ERANGE, "Length is %d", "MP4WriteCountedString", charLength);
}
WriteUInt8(charLength);
}
--- a/common/mp4v2/mp4info.cpp
+++ b/common/mp4v2/mp4info.cpp
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001-2002. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#include "mp4common.h"
@@ -63,7 +64,7 @@
"MPEG-2 (MP3)",
"MPEG-1 (MP3)",
"PCM16 (little endian)",
- "OGG VORBIS",
+ "Vorbis",
"G.711 aLaw",
"G.711 uLaw",
"G.723.1",
@@ -73,7 +74,7 @@
sizeof(mpegAudioTypes) / sizeof(u_int8_t);
u_int8_t type =
- MP4GetTrackAudioType(mp4File, trackId);
+ MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
const char* typeName = "Unknown";
if (type == MP4_MPEG4_AUDIO_TYPE) {
@@ -99,11 +100,8 @@
MP4GetTrackDuration(mp4File, trackId);
double msDuration =
-#ifdef _WIN32
- (int64_t)
-#endif
- MP4ConvertFromTrackDuration(mp4File, trackId,
- trackDuration, MP4_MSECS_TIME_SCALE);
+ UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId,
+ trackDuration, MP4_MSECS_TIME_SCALE));
u_int32_t avgBitRate =
MP4GetTrackBitRate(mp4File, trackId);
@@ -178,7 +176,7 @@
sizeof(mpegVideoTypes) / sizeof(u_int8_t);
u_int8_t type =
- MP4GetTrackVideoType(mp4File, trackId);
+ MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
const char* typeName = "Unknown";
if (type == MP4_MPEG4_VIDEO_TYPE) {
@@ -201,11 +199,8 @@
MP4GetTrackDuration(mp4File, trackId);
double msDuration =
-#ifdef _WIN32
- (int64_t)
-#endif
- MP4ConvertFromTrackDuration(mp4File, trackId,
- trackDuration, MP4_MSECS_TIME_SCALE);
+ UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId,
+ trackDuration, MP4_MSECS_TIME_SCALE));
u_int32_t avgBitRate =
MP4GetTrackBitRate(mp4File, trackId);
@@ -267,8 +262,6 @@
const char* trackType =
MP4GetTrackType(mp4File, trackId);
- if (trackType) {
-
if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) {
trackInfo = PrintAudioInfo(mp4File, trackId);
} else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) {
@@ -291,8 +284,6 @@
trackId, trackType);
}
}
-
- }
return trackInfo;
}
--- /dev/null
+++ b/common/mp4v2/mp4meta.cpp
@@ -1,0 +1,876 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
+ *
+ * Contributor(s):
+ * M. Bakker mbakker at nero.com
+ *
+ * Apple iTunes Metadata handling
+ */
+
+/**
+
+ The iTunes tagging seems to support any tag field name
+ but there are some predefined fields, also known from the QuickTime format
+
+ predefined fields (the ones I know of until now):
+ - �nam : Name of the song/movie (string)
+ - �ART : Name of the artist/performer (string)
+ - �wrt : Name of the writer (string)
+ - �alb : Name of the album (string)
+ - �day : Year (4 bytes, e.g. "2003") (string)
+ - �too : Tool(s) used to create the file (string)
+ - �cmt : Comment (string)
+ - 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)
+ - cpil : Part of a compilation (1 byte, 1 or 0)
+ - tmpo : Tempo in BPM (16 bit)
+ - covr : Cover art (xx bytes binary data)
+ - ---- : Free form metadata, can have any name and any data
+
+**/
+
+#include "mp4common.h"
+
+bool MP4File::GetMetadataByIndex(u_int32_t index,
+ const char** ppName,
+ u_int8_t** ppValue, u_int32_t* pValueSize)
+{
+ char s[256];
+
+ sprintf(s, "moov.udta.meta.ilst.*[%u].data.metadata", index);
+ GetBytesProperty(s, ppValue, pValueSize);
+
+ sprintf(s, "moov.udta.meta.ilst.*[%u]", index);
+ MP4Atom* pParent = m_pRootAtom->FindAtom(s);
+ *ppName = pParent->GetType();
+
+ /* check for free form tagfield */
+ if (memcmp(*ppName, "----", 4) == 0)
+ {
+ u_int8_t* pV;
+ u_int32_t VSize = 0;
+ char *pN;
+
+ sprintf(s, "moov.udta.meta.ilst.*[%u].name.metadata", index);
+ GetBytesProperty(s, &pV, &VSize);
+
+ pN = (char*)malloc((VSize+1)*sizeof(char));
+ memset(pN, 0, (VSize+1)*sizeof(char));
+ memcpy(pN, pV, VSize*sizeof(char));
+
+ *ppName = pN;
+ }
+
+ return true;
+}
+
+bool MP4File::CreateMetadataAtom(const char* name)
+{
+ char s[256];
+ char t[256];
+
+ sprintf(t, "udta.meta.ilst.%s.data", name);
+ sprintf(s, "moov.udta.meta.ilst.%s.data", name);
+ AddDescendantAtoms("moov", t);
+ MP4Atom *pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ return false;
+
+ /* some fields need special flags set */
+ if (name[0] == '�')
+ {
+ pMetaAtom->SetFlags(0x1);
+ } else if ((memcmp(name, "cpil", 4) == 0) || (memcmp(name, "tmpo", 4) == 0)) {
+ pMetaAtom->SetFlags(0xF);
+ }
+
+ MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr");
+ MP4StringProperty *pStringProperty = NULL;
+ MP4BytesProperty *pBytesProperty = NULL;
+ ASSERT(pHdlrAtom);
+
+ pHdlrAtom->FindProperty(
+ "hdlr.handlerType", (MP4Property**)&pStringProperty);
+ ASSERT(pStringProperty);
+ pStringProperty->SetValue("mdir");
+
+ u_int8_t val[12];
+ memset(val, 0, 12*sizeof(u_int8_t));
+ val[0] = 0x61;
+ val[1] = 0x70;
+ val[2] = 0x70;
+ val[3] = 0x6c;
+ pHdlrAtom->FindProperty(
+ "hdlr.reserved2", (MP4Property**)&pBytesProperty);
+ ASSERT(pBytesProperty);
+ pBytesProperty->SetReadOnly(false);
+ pBytesProperty->SetValue(val, 12);
+ pBytesProperty->SetReadOnly(true);
+
+ return true;
+}
+
+bool MP4File::SetMetadataName(const char* value)
+{
+ const char *s = "moov.udta.meta.ilst.�nam.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("�nam"))
+ 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;
+}
+
+bool MP4File::GetMetadataName(char** value)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.�nam.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.�wrt.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("�wrt"))
+ 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;
+}
+
+bool MP4File::GetMetadataWriter(char** value)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.�wrt.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::SetMetadataAlbum(const char* value)
+{
+ const char *s = "moov.udta.meta.ilst.�alb.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("�alb"))
+ 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;
+}
+
+bool MP4File::GetMetadataAlbum(char** value)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.�alb.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::SetMetadataArtist(const char* value)
+{
+ const char *s = "moov.udta.meta.ilst.�ART.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("�ART"))
+ 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;
+}
+
+bool MP4File::GetMetadataArtist(char** value)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.�ART.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::SetMetadataTool(const char* value)
+{
+ const char *s = "moov.udta.meta.ilst.�too.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("�too"))
+ 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;
+}
+
+bool MP4File::GetMetadataTool(char** value)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.�too.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::SetMetadataComment(const char* value)
+{
+ const char *s = "moov.udta.meta.ilst.�cmt.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("�cmt"))
+ 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;
+}
+
+bool MP4File::GetMetadataComment(char** value)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.�cmt.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.�day.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("�day"))
+ 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.�day.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;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("trkn"))
+ return false;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ }
+
+ memset(t, 0, 9*sizeof(unsigned char));
+ t[2] = (unsigned char)(track>>8)&0xFF;
+ t[3] = (unsigned char)(track)&0xFF;
+ t[4] = (unsigned char)(totalTracks>>8)&0xFF;
+ t[5] = (unsigned char)(totalTracks)&0xFF;
+
+ pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+
+ pMetadataProperty->SetValue((u_int8_t*)t, 8);
+
+ return true;
+}
+
+bool MP4File::GetMetadataTrack(u_int16_t* track, u_int16_t* totalTracks)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.trkn.data.metadata";
+ GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+
+ *track = 0;
+ *totalTracks = 0;
+
+ if (valSize != 8)
+ return false;
+
+ *track = (u_int16_t)(val[3]);
+ *track += (u_int16_t)(val[2]<<8);
+ *totalTracks = (u_int16_t)(val[5]);
+ *totalTracks += (u_int16_t)(val[4]<<8);
+
+ return true;
+}
+
+bool MP4File::SetMetadataDisk(u_int16_t disk, u_int16_t totalDisks)
+{
+ unsigned char t[9];
+ const char *s = "moov.udta.meta.ilst.disk.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("disk"))
+ return false;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ }
+
+ memset(t, 0, 9*sizeof(unsigned char));
+ t[2] = (unsigned char)(disk>>8)&0xFF;
+ t[3] = (unsigned char)(disk)&0xFF;
+ t[4] = (unsigned char)(totalDisks>>8)&0xFF;
+ t[5] = (unsigned char)(totalDisks)&0xFF;
+
+ pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+
+ pMetadataProperty->SetValue((u_int8_t*)t, 8);
+
+ return true;
+}
+
+bool MP4File::GetMetadataDisk(u_int16_t* disk, u_int16_t* totalDisks)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.disk.data.metadata";
+ GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+
+ *disk = 0;
+ *totalDisks = 0;
+
+ if (valSize != 8)
+ return false;
+
+ *disk = (u_int16_t)(val[3]);
+ *disk += (u_int16_t)(val[2]<<8);
+ *totalDisks = (u_int16_t)(val[5]);
+ *totalDisks += (u_int16_t)(val[4]<<8);
+
+ return true;
+}
+
+bool MP4File::SetMetadataGenre(u_int16_t genreIndex)
+{
+ unsigned char t[3];
+ const char *s = "moov.udta.meta.ilst.gnre.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("gnre"))
+ return false;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ }
+
+ memset(t, 0, 3*sizeof(unsigned char));
+ t[0] = (unsigned char)(genreIndex>>8)&0xFF;
+ t[1] = (unsigned char)(genreIndex)&0xFF;
+
+ pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+
+ pMetadataProperty->SetValue((u_int8_t*)t, 2);
+
+ return true;
+}
+
+bool MP4File::GetMetadataGenre(u_int16_t* genreIndex)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.gnre.data.metadata";
+ GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+
+ *genreIndex = 0;
+
+ if (valSize != 2)
+ return false;
+
+ *genreIndex = (u_int16_t)(val[1]);
+ *genreIndex += (u_int16_t)(val[0]<<8);
+
+ return true;
+}
+
+bool MP4File::SetMetadataTempo(u_int16_t tempo)
+{
+ unsigned char t[3];
+ const char *s = "moov.udta.meta.ilst.tmpo.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("tmpo"))
+ return false;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ }
+
+ memset(t, 0, 3*sizeof(unsigned char));
+ t[0] = (unsigned char)(tempo>>8)&0xFF;
+ t[1] = (unsigned char)(tempo)&0xFF;
+
+ pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+
+ pMetadataProperty->SetValue((u_int8_t*)t, 2);
+
+ return true;
+}
+
+bool MP4File::GetMetadataTempo(u_int16_t* tempo)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.tmpo.data.metadata";
+ GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+
+ *tempo = 0;
+
+ if (valSize != 2)
+ return false;
+
+ *tempo = (u_int16_t)(val[1]);
+ *tempo += (u_int16_t)(val[0]<<8);
+
+ return true;
+}
+
+bool MP4File::SetMetadataCompilation(u_int8_t compilation)
+{
+ const char *s = "moov.udta.meta.ilst.cpil.data";
+ MP4BytesProperty *pMetadataProperty = NULL;
+ MP4Atom *pMetaAtom = NULL;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("cpil"))
+ return false;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ }
+
+ pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+
+ compilation &= 0x1;
+ pMetadataProperty->SetValue((u_int8_t*)&compilation, 1);
+
+ return true;
+}
+
+bool MP4File::GetMetadataCompilation(u_int8_t* compilation)
+{
+ unsigned char *val = NULL;
+ u_int32_t valSize = 0;
+ const char *s = "moov.udta.meta.ilst.cpil.data.metadata";
+ GetBytesProperty(s, (u_int8_t**)&val, &valSize);
+
+ *compilation = 0;
+
+ if (valSize != 1)
+ return false;
+
+ *compilation = (u_int16_t)(val[0]);
+
+ 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;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ {
+ if (!CreateMetadataAtom("covr"))
+ return false;
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ }
+
+ pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+
+ pMetadataProperty->SetValue(coverArt, size);
+
+ return true;
+}
+
+bool MP4File::GetMetadataCoverArt(u_int8_t **coverArt, u_int32_t *size)
+{
+ const char *s = "moov.udta.meta.ilst.covr.data.metadata";
+ GetBytesProperty(s, coverArt, size);
+
+ if (size == 0)
+ return false;
+
+ return true;
+}
+
+bool MP4File::SetMetadataFreeForm(char *name, u_int8_t* pValue, u_int32_t valueSize)
+{
+ MP4Atom *pMetaAtom = NULL;
+ MP4BytesProperty *pMetadataProperty = NULL;
+ char s[256];
+ int i = 0;
+ bool nameExists = false;
+
+ while (1)
+ {
+ MP4BytesProperty *pMetadataProperty;
+
+ sprintf(s, "moov.udta.meta.ilst.----[%u].name", i);
+
+ MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pTagAtom)
+ break;
+
+ pTagAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty);
+ if (pMetadataProperty)
+ {
+ u_int8_t* pV;
+ u_int32_t VSize = 0;
+
+ pMetadataProperty->GetValue(&pV, &VSize);
+
+ if (VSize != 0)
+ {
+ if (memcmp(pV, name, VSize) == 0)
+ {
+ sprintf(s, "moov.udta.meta.ilst.----[%u].data.metadata", i);
+ SetBytesProperty(s, pValue, valueSize);
+
+ return true;
+ }
+ }
+ }
+
+ i++;
+ }
+
+ /* doesn't exist yet, create it */
+ char t[256];
+
+ sprintf(t, "udta.meta.ilst.----[%u]", i);
+ sprintf(s, "moov.udta.meta.ilst.----[%u].data", i);
+ AddDescendantAtoms("moov", t);
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pMetaAtom)
+ return false;
+
+ pMetaAtom->SetFlags(0x1);
+
+ MP4Atom *pHdlrAtom = m_pRootAtom->FindAtom("moov.udta.meta.hdlr");
+ MP4StringProperty *pStringProperty = NULL;
+ MP4BytesProperty *pBytesProperty = NULL;
+ ASSERT(pHdlrAtom);
+
+ pHdlrAtom->FindProperty(
+ "hdlr.handlerType", (MP4Property**)&pStringProperty);
+ ASSERT(pStringProperty);
+ pStringProperty->SetValue("mdir");
+
+ u_int8_t val[12];
+ memset(val, 0, 12*sizeof(u_int8_t));
+ val[0] = 0x61;
+ val[1] = 0x70;
+ val[2] = 0x70;
+ val[3] = 0x6c;
+ pHdlrAtom->FindProperty(
+ "hdlr.reserved2", (MP4Property**)&pBytesProperty);
+ ASSERT(pBytesProperty);
+ pBytesProperty->SetReadOnly(false);
+ pBytesProperty->SetValue(val, 12);
+ pBytesProperty->SetReadOnly(true);
+
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ pMetaAtom->FindProperty("data.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+ pMetadataProperty->SetValue(pValue, valueSize);
+
+ sprintf(s, "moov.udta.meta.ilst.----[%u].name", i);
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ pMetaAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+ pMetadataProperty->SetValue((u_int8_t*)name, strlen(name));
+
+ sprintf(s, "moov.udta.meta.ilst.----[%u].mean", i);
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+ pMetaAtom->FindProperty("mean.metadata", (MP4Property**)&pMetadataProperty);
+ ASSERT(pMetadataProperty);
+ pMetadataProperty->SetValue((u_int8_t*)"com.apple.iTunes", 16); /* ?? */
+
+ return true;
+}
+
+bool MP4File::GetMetadataFreeForm(char *name, u_int8_t** ppValue, u_int32_t *pValueSize)
+{
+ char s[256];
+ int i = 0;
+
+ while (1)
+ {
+ MP4BytesProperty *pMetadataProperty;
+
+ sprintf(s, "moov.udta.meta.ilst.----[%u].name", i);
+
+ MP4Atom *pTagAtom = m_pRootAtom->FindAtom(s);
+
+ if (!pTagAtom)
+ return false;
+
+ pTagAtom->FindProperty("name.metadata", (MP4Property**)&pMetadataProperty);
+ if (pMetadataProperty)
+ {
+ u_int8_t* pV;
+ u_int32_t VSize = 0;
+
+ pMetadataProperty->GetValue(&pV, &VSize);
+
+ if (VSize != 0)
+ {
+ if (memcmp(pV, name, VSize) == 0)
+ {
+ sprintf(s, "moov.udta.meta.ilst.----[%u].data.metadata", i);
+ GetBytesProperty(s, ppValue, pValueSize);
+
+ return true;
+ }
+ }
+ }
+
+ i++;
+ }
+}
+
+bool MP4File::MetadataDelete()
+{
+ MP4Atom *pMetaAtom = NULL;
+ char s[256];
+
+ sprintf(s, "moov.udta.meta");
+ pMetaAtom = m_pRootAtom->FindAtom(s);
+
+ /* if it exists, delete it */
+ if (pMetaAtom)
+ {
+ MP4Atom *pParent = pMetaAtom->GetParentAtom();
+
+ pParent->DeleteChildAtom(pMetaAtom);
+
+ delete pMetaAtom;
+
+ return true;
+ }
+
+ return false;
+}
--- a/common/mp4v2/mp4property.cpp
+++ b/common/mp4v2/mp4property.cpp
@@ -584,37 +584,6 @@
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,10 +307,6 @@
SetValue(value, count);
}
- void DeleteValue(u_int32_t index) {
- m_values.Delete(index);
- }
-
bool IsCountedFormat() {
return m_useCountedFormat;
}
@@ -464,8 +460,6 @@
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/common/mp4v2/mp4track.cpp
+++ b/common/mp4v2/mp4track.cpp
@@ -16,7 +16,8 @@
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
- * Dave Mackie [email protected]
+ * Dave Mackie [email protected]
+ * Alix Marchandise-Franquet [email protected]
*/
#include "mp4common.h"
@@ -335,7 +336,7 @@
}
void MP4Track::WriteSample(
- u_int8_t* pBytes,
+ const u_int8_t* pBytes,
u_int32_t numBytes,
MP4Duration duration,
MP4Duration renderingOffset,
@@ -823,7 +824,9 @@
if (sampleId <= sid + sampleCount - 1) {
if (pStartTime) {
- *pStartTime = elapsed + ((sampleId - sid) * sampleDelta);
+ *pStartTime = (sampleId - sid);
+ *pStartTime *= sampleDelta;
+ *pStartTime += elapsed;
}
if (pDuration) {
*pDuration = sampleDelta;
@@ -1350,7 +1353,8 @@
{
if (!strcasecmp(type, "vide")
|| !strcasecmp(type, "video")
- || !strcasecmp(type, "mp4v")) {
+ || !strcasecmp(type, "mp4v")
+ || !strcasecmp(type, "encv")) {
return MP4_VIDEO_TRACK_TYPE;
}
@@ -1357,6 +1361,7 @@
if (!strcasecmp(type, "soun")
|| !strcasecmp(type, "sound")
|| !strcasecmp(type, "audio")
+ || !strcasecmp(type, "enca") // ismacrypt
|| !strcasecmp(type, "mp4a")) {
return MP4_AUDIO_TRACK_TYPE;
}
--- a/common/mp4v2/mp4track.h
+++ b/common/mp4v2/mp4track.h
@@ -68,7 +68,7 @@
bool* pIsSyncSample = NULL);
void WriteSample(
- u_int8_t* pBytes,
+ const u_int8_t* pBytes,
u_int32_t numBytes,
MP4Duration duration = 0,
MP4Duration renderingOffset = 0,
--- a/common/mp4v2/mp4util.cpp
+++ b/common/mp4v2/mp4util.cpp
@@ -231,11 +231,7 @@
// final resort is to use floating point
double d = ((double)newTimeScale / (double)oldTimeScale) + 0.5;
-#ifdef _WINDOWS
- d *= (double)(int64_t)t;
-#else
- d *= (double)t;
-#endif
+ d *= UINT64_TO_DOUBLE(t);
return (u_int64_t)d;
}
--- a/common/mp4v2/mp4util.h
+++ b/common/mp4v2/mp4util.h
@@ -210,7 +210,11 @@
inline MP4Timestamp MP4GetAbsTimestamp() {
struct timeval tv;
gettimeofday(&tv, NULL);
- return tv.tv_sec + 209606400; // MP4 start date is 1/1/1904
+ MP4Timestamp ret;
+ ret = tv.tv_sec;
+ ret += 2082844800;
+ return ret; // MP4 start date is 1/1/1904
+ // 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
}
u_int64_t MP4ConvertTime(u_int64_t t,
--- a/common/mp4v2/rtphint.cpp
+++ b/common/mp4v2/rtphint.cpp
@@ -370,7 +370,9 @@
const char* payloadName,
u_int8_t payloadNumber,
u_int16_t maxPayloadSize,
- const char *encoding_parms)
+ const char *encoding_parms,
+ bool include_rtp_map,
+ bool include_mpeg4_esid)
{
InitRefTrack();
InitPayload();
@@ -416,15 +418,22 @@
char* sdpBuf = (char*)MP4Malloc(
strlen(sdpMediaType) + strlen(rtpMapBuf) + 256);
- sprintf(sdpBuf,
- "m=%s 0 RTP/AVP %u\015\012"
- "a=rtpmap:%u %s\015\012"
- "a=control:trackID=%u\015\012"
- "a=mpeg4-esid:%u\015\012",
- sdpMediaType, payloadNumber,
- payloadNumber, rtpMapBuf,
- m_trackId,
- m_pRefTrack->GetId());
+ uint32_t buflen;
+ buflen = sprintf(sdpBuf,
+ "m=%s 0 RTP/AVP %u\015\012"
+ "a=control:trackID=%u\015\012",
+ sdpMediaType, payloadNumber,
+ m_trackId);
+ if (include_rtp_map) {
+ buflen += sprintf(sdpBuf + buflen,
+ "a=rtpmap:%u %s\015\012",
+ payloadNumber, rtpMapBuf);
+ }
+ if (include_mpeg4_esid) {
+ sprintf(sdpBuf + buflen,
+ "a=mpeg4-esid:%u\015\012",
+ m_pRefTrack->GetId());
+ }
MP4StringProperty* pSdpProperty = NULL;
m_pTrakAtom->FindProperty("trak.udta.hnti.sdp .sdpText",
--- a/common/mp4v2/rtphint.h
+++ b/common/mp4v2/rtphint.h
@@ -259,7 +259,9 @@
const char* payloadName,
u_int8_t payloadNumber,
u_int16_t maxPayloadSize,
- const char *encoding_parms);
+ const char *encoding_parms,
+ bool add_rtpmap,
+ bool add_mpeg4_esid);
void ReadHint(
MP4SampleId hintSampleId,
--- a/common/mp4v2/systems.h
+++ b/common/mp4v2/systems.h
@@ -27,6 +27,7 @@
#define HAVE_IN_PORT_T
#define HAVE_SOCKLEN_T
#include <win32_ver.h>
+#define NEED_SDL_VIDEO_IN_MAIN_THREAD
#else
#undef PACKAGE
#undef VERSION
@@ -35,10 +36,13 @@
+
#ifdef WIN32
#define _WIN32_WINNT 0x0400
+#define _WINSOCKAPI_
#include <windows.h>
+#include <winsock2.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
@@ -58,7 +62,7 @@
typedef __int16 int16_t;
typedef __int8 int8_t;
typedef unsigned short in_port_t;
-typedef unsigned int socklen_t;
+typedef int socklen_t;
typedef int ssize_t;
#define snprintf _snprintf
#define strncasecmp _strnicmp
@@ -96,6 +100,7 @@
#define LLD "%I64d"
#define LLU "%I64u"
#define LLX "%I64x"
+#define LLX16 "%016I64x"
#define M_LLU 1000i64
#define C_LLU 100i64
#define I_LLU 1i64
@@ -122,8 +127,26 @@
#define FOPEN_READ_BINARY "rb"
#define FOPEN_WRITE_BINARY "wb"
+#define UINT64_TO_DOUBLE(a) ((double)((int64_t)(a)))
#else /* UNIX */
+/*****************************************************************************
+ * UNIX LIKE DEFINES BELOW THIS POINT
+ *****************************************************************************/
+#ifdef sun
+#include <sys/feature_tests.h>
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#else
+#if _FILE_OFFSET_BITS < 64
+#error File offset bits is already set to non-64 value
+#endif
+#endif
+
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
@@ -150,7 +173,16 @@
#include <ctype.h>
#include <netdb.h>
#include <sys/stat.h>
+#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
#include <sys/param.h>
#define OPEN_RDWR O_RDWR
@@ -163,6 +195,7 @@
#define LLD "%lld"
#define LLU "%llu"
#define LLX "%llx"
+#define LLX16 "%016llx"
#define M_LLU 1000LLU
#define C_LLU 100LLU
#define I_LLU 1LLU
@@ -176,8 +209,12 @@
#define FOPEN_READ_BINARY "r"
#define FOPEN_WRITE_BINARY "w"
+#define UINT64_TO_DOUBLE(a) ((double)(a))
#endif /* define unix */
+/*****************************************************************************
+ * Generic type includes used in the whole package *
+ *****************************************************************************/
#include <stdarg.h>
typedef void (*error_msg_func_t)(int loglevel,
const char *lib,
@@ -228,7 +265,10 @@
#define MALLOC_STRUCTURE(a) ((a *)malloc(sizeof(a)))
-#define CHECK_AND_FREE(a) if ((a) != NULL) { free((a)); (a) = NULL;}
+#define CHECK_AND_FREE(a) if ((a) != NULL) { free((void *)(a)); (a) = NULL;}
+
+#define NUM_ELEMENTS_IN_ARRAY(name) ((sizeof((name))) / (sizeof(*(name))))
+
#ifndef HAVE_GLIB_H
typedef char gchar;
typedef unsigned char guchar;
@@ -264,7 +304,6 @@
#ifndef FALSE
#define FALSE 0
#endif
-
#endif /* __SYSTEMS_H__ */
--- a/common/mp4v2/win32_ver.h
+++ b/common/mp4v2/win32_ver.h
@@ -1,2 +1,2 @@
#define PACKAGE "mpeg4ip"
-#define VERSION "0.9.7.2"
+#define VERSION "0.9.8.6"
--- 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.34 2003/06/25 19:18:35 menno Exp $
+** $Id: foo_mp4.cpp,v 1.35 2003/06/29 21:41:00 menno Exp $
**/
#include <mp4.h>
@@ -44,7 +44,7 @@
#endif
DECLARE_COMPONENT_VERSION ("MPEG-4 AAC decoder",
- "$Revision: 1.34 $",
+ "$Revision: 1.35 $",
"Based on FAAD2 v" FAAD2_VERSION "\nCopyright (C) 2002-2003 http://www.audiocoding.com" );
class input_mp4 : public input
@@ -209,6 +209,7 @@
virtual int set_info(reader *r,const file_info * info)
{
+#if 0
m_reader = r;
hFile = MP4ModifyCb(0, 0, open_cb, close_cb, read_cb, write_cb,
@@ -257,6 +258,82 @@
/* end */
return 1;
+#else
+ m_reader = r;
+
+ hFile = MP4ModifyCb(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;
+
+ MP4MetadataDelete(hFile);
+
+ /* replay gain writing */
+ const char *p = NULL;
+
+ p = info->info_get("REPLAYGAIN_TRACK_PEAK");
+ if (p)
+ MP4SetMetadataFreeForm(hFile, "REPLAYGAIN_TRACK_PEAK", (unsigned __int8*)p, strlen(p));
+ p = info->info_get("REPLAYGAIN_TRACK_GAIN");
+ if (p)
+ MP4SetMetadataFreeForm(hFile, "REPLAYGAIN_TRACK_GAIN", (unsigned __int8*)p, strlen(p));
+ p = info->info_get("REPLAYGAIN_ALBUM_PEAK");
+ if (p)
+ MP4SetMetadataFreeForm(hFile, "REPLAYGAIN_ALBUM_PEAK", (unsigned __int8*)p, strlen(p));
+ p = info->info_get("REPLAYGAIN_ALBUM_GAIN");
+ if (p)
+ MP4SetMetadataFreeForm(hFile, "REPLAYGAIN_ALBUM_GAIN", (unsigned __int8*)p, strlen(p));
+
+ int numItems = info->meta_get_count();
+ if (numItems > 0)
+ {
+ for (int i = 0; i < numItems; i++)
+ {
+ char *pName = (char*)info->meta_enum_name(i);
+ const char *val = info->meta_enum_value(i);
+
+ if (strcmp(pName, "TITLE") == 0)
+ {
+ MP4SetMetadataName(hFile, val);
+ } else if (strcmp(pName, "ARTIST") == 0) {
+ MP4SetMetadataArtist(hFile, val);
+ } else if (strcmp(pName, "WRITER") == 0) {
+ MP4SetMetadataWriter(hFile, val);
+ } else if (strcmp(pName, "ALBUM") == 0) {
+ MP4SetMetadataAlbum(hFile, val);
+ } else if (strcmp(pName, "YEAR") == 0) {
+ MP4SetMetadataYear(hFile, val);
+ } else if (strcmp(pName, "TOOL") == 0) {
+ MP4SetMetadataTool(hFile, val);
+ } else if (strcmp(pName, "COMMENT") == 0) {
+ MP4SetMetadataComment(hFile, val);
+ } else if (strcmp(pName, "GENRE") == 0) {
+ unsigned __int16 genre = 0;
+ MP4SetMetadataGenre(hFile, genre);
+ } else if (strcmp(pName, "TRACKNUMBER") == 0) {
+ unsigned __int16 trkn = 0, tot = 0;
+ sscanf(val, "%d", &trkn);
+ MP4SetMetadataTrack(hFile, trkn, tot);
+ } else if (strcmp(pName, "DISKNUMBER") == 0) {
+ unsigned __int16 disk = 0, tot = 0;
+ sscanf(val, "%d", &disk);
+ MP4SetMetadataDisk(hFile, disk, tot);
+ } else if (strcmp(pName, "COMPILATION") == 0) {
+ unsigned __int8 cpil = 0;
+ sscanf(val, "%d", &cpil);
+ MP4SetMetadataCompilation(hFile, cpil);
+ } else if (strcmp(pName, "TEMPO") == 0) {
+ unsigned __int16 tempo = 0;
+ sscanf(val, "%d", &tempo);
+ MP4SetMetadataTempo(hFile, tempo);
+ } else {
+ MP4SetMetadataFreeForm(hFile, pName, (unsigned __int8*)val, strlen(val));
+ }
+ }
+ }
+
+ /* end */
+ return 1;
+#endif
}
virtual int seek(double seconds)
@@ -288,32 +365,96 @@
int ReadMP4Tag(file_info *info)
{
- int numItems = MP4TagGetNumEntries(hFile, track);
+ unsigned __int32 valueSize = 0;
+ unsigned __int8* pValue;
+ char* pName;
+ int i = 0;
- for (int i = 0; i < numItems; i++)
- {
- float f = 0.0;
- const char *n = NULL, *v = NULL;
+ do {
+ valueSize = 0;
- MP4TagGetEntry(hFile, track, i, &n, &v);
+ MP4GetMetadataByIndex(hFile, i, (const char**)&pName, &pValue, &valueSize);
- if (!strcmp(n, "REPLAYGAIN_TRACK_PEAK"))
+ if (valueSize > 0)
{
- sscanf(v, "%f", &f);
- info->info_set_replaygain_track_peak((double)f);
- } else if (!strcmp(n, "REPLAYGAIN_TRACK_GAIN")) {
- sscanf(v, "%f", &f);
- info->info_set_replaygain_track_gain((double)f);
- } else if (!strcmp(n, "REPLAYGAIN_ALBUM_PEAK")) {
- sscanf(v, "%f", &f);
- info->info_set_replaygain_album_peak((double)f);
- } else if (!strcmp(n, "REPLAYGAIN_ALBUM_GAIN")) {
- sscanf(v, "%f", &f);
- info->info_set_replaygain_album_gain((double)f);
- } else {
- info->meta_add(n, v);
+ char* val = (char*)malloc((valueSize+1)*sizeof(char));
+ memset(val, 0, (valueSize+1)*sizeof(char));
+ memcpy(val, pValue, valueSize*sizeof(char));
+
+ if (pName[0] == '�')
+ {
+ if (memcmp(pName, "�nam", 4) == 0)
+ {
+ info->meta_add("TITLE", val);
+ } else if (memcmp(pName, "�ART", 4) == 0) {
+ info->meta_add("ARTIST", val);
+ } else if (memcmp(pName, "�wrt", 4) == 0) {
+ info->meta_add("WRITER", val);
+ } else if (memcmp(pName, "�alb", 4) == 0) {
+ info->meta_add("ALBUM", val);
+ } else if (memcmp(pName, "�day", 4) == 0) {
+ info->meta_add("YEAR", val);
+ } else if (memcmp(pName, "�too", 4) == 0) {
+ info->meta_add("TOOL", val);
+ } else if (memcmp(pName, "�cmt", 4) == 0) {
+ info->meta_add("COMMENT", val);
+ } else {
+ info->meta_add(pName, val);
+ }
+ } else if (memcmp(pName, "gnre", 4) == 0) {
+ unsigned __int16 genre = 0;
+ char t[200];
+ MP4GetMetadataGenre(hFile, &genre);
+ wsprintf(t, "%d", genre);
+ info->meta_add("GENRE", t);
+ } else if (memcmp(pName, "trkn", 4) == 0) {
+ unsigned __int16 trkn = 0, tot = 0;
+ char t[200];
+ MP4GetMetadataTrack(hFile, &trkn, &tot);
+ wsprintf(t, "%d", trkn);
+ info->meta_add("TRACKNUMBER", t);
+ } else if (memcmp(pName, "disk", 4) == 0) {
+ unsigned __int16 disk = 0, tot = 0;
+ char t[200];
+ MP4GetMetadataDisk(hFile, &disk, &tot);
+ wsprintf(t, "%d", disk);
+ info->meta_add("DISKNUMBER", t);
+ } else if (memcmp(pName, "cpil", 4) == 0) {
+ unsigned __int8 cpil = 0;
+ char t[200];
+ MP4GetMetadataCompilation(hFile, &cpil);
+ wsprintf(t, "%d", cpil);
+ info->meta_add("COMPILATION", t);
+ } else if (memcmp(pName, "tmpo", 4) == 0) {
+ unsigned __int16 tempo = 0;
+ char t[200];
+ MP4GetMetadataTempo(hFile, &tempo);
+ wsprintf(t, "%d BPM", tempo);
+ info->meta_add("TEMPO", t);
+ } else {
+ float f = 0;
+ if (!strcmp(pName, "REPLAYGAIN_TRACK_PEAK"))
+ {
+ sscanf(val, "%f", &f);
+ info->info_set_replaygain_track_peak((double)f);
+ } else if (!strcmp(pName, "REPLAYGAIN_TRACK_GAIN")) {
+ sscanf(val, "%f", &f);
+ info->info_set_replaygain_track_gain((double)f);
+ } else if (!strcmp(pName, "REPLAYGAIN_ALBUM_PEAK")) {
+ sscanf(val, "%f", &f);
+ info->info_set_replaygain_album_peak((double)f);
+ } else if (!strcmp(pName, "REPLAYGAIN_ALBUM_GAIN")) {
+ sscanf(val, "%f", &f);
+ info->info_set_replaygain_album_gain((double)f);
+ } else {
+ info->meta_add(pName, val);
+ }
+ }
}
- }
+
+ i++;
+
+ } while (valueSize > 0);
return 1;
}