Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclsid2 <clsid2@users.sourceforge.net>2010-05-21 21:31:06 +0400
committerclsid2 <clsid2@users.sourceforge.net>2010-05-21 21:31:06 +0400
commitf04f37111f5e42ecc3ba3259a71064c8cf2d28ee (patch)
tree5c83d827187fd1998d880a2ee194901ae47e62b4 /src/filters/parser/MP4Splitter/AP4
parent55c5894d725662a782bd7aeacfa3b7fd32d9f2f2 (diff)
Updated Bento4 to version 1.2.3-387
git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@1917 10f7b99b-c216-0410-bff0-8a66a9350fd8
Diffstat (limited to 'src/filters/parser/MP4Splitter/AP4')
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.cpp81
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.h1
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Config/Ap4Config.h282
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Array.h466
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.cpp4
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.h8
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.cpp1568
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.h13
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.cpp752
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.h194
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.cpp554
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.h204
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.cpp1684
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.h404
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Command.cpp6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Config.h142
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4CttsAtom.cpp422
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DataBuffer.cpp414
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DecoderConfigDescriptor.cpp6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Descriptor.cpp6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4EsDescriptor.cpp12
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Expandable.cpp6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4File.cpp296
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.cpp5
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.h2
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Ipmp.cpp8
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.cpp1018
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.h300
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4List.h980
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.cpp1980
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.h407
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.cpp186
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.h134
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MoovAtom.cpp148
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Movie.cpp474
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ObjectDescriptor.cpp12
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OhdrAtom.h7
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.cpp2267
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.h659
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.cpp10
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.h4
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.cpp996
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.h474
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.cpp2670
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.h959
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Results.h152
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.cpp17
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.h341
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.cpp1236
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.h4
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleEntry.cpp6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.cpp423
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.h3
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StscAtom.h6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StsdAtom.cpp444
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StszAtom.h6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SttsAtom.h6
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.cpp456
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.h288
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.cpp348
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.h198
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.cpp5
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.h2
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.cpp10
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.h4
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.cpp486
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.h190
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Types.h4
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.cpp532
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.h424
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.cpp396
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.h194
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Version.h86
-rw-r--r--src/filters/parser/MP4Splitter/AP4/Source/MetaData/Ap4MetaData.cpp3472
74 files changed, 15658 insertions, 15306 deletions
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.cpp
index a054f0c97..7083f5db6 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.cpp
@@ -122,6 +122,45 @@ AP4_Mp4AudioDecoderConfig::ParseAudioObjectType(AP4_Mp4AudioDsiParser& parser, A
}
/*----------------------------------------------------------------------
+| AP4_Mp4AudioDecoderConfig::ParseExtension
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_Mp4AudioDecoderConfig::ParseExtension(AP4_Mp4AudioDsiParser& parser)
+{
+ if (parser.BitsLeft() < 16) return AP4_ERROR_INVALID_FORMAT;
+ unsigned int sync_extension_type = parser.ReadBits(11);
+ if (sync_extension_type == 0x2b7) {
+ AP4_Result result = ParseAudioObjectType(parser, m_Extension.m_ObjectType);
+ if (AP4_FAILED(result)) return result;
+ if (m_Extension.m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR) {
+ m_Extension.m_SbrPresent = (parser.ReadBits(1) == 1);
+ if (m_Extension.m_SbrPresent) {
+ result = ParseSamplingFrequency(parser,
+ m_Extension.m_SamplingFrequencyIndex,
+ m_Extension.m_SamplingFrequency);
+ if (AP4_FAILED(result)) return result;
+ if (parser.BitsLeft() >= 12) {
+ sync_extension_type = parser.ReadBits(11);
+ if (sync_extension_type == 0x548) {
+ m_Extension.m_PsPresent = (parser.ReadBits(1) == 1);
+ }
+ }
+ }
+ } else if (m_Extension.m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC) {
+ m_Extension.m_SbrPresent = (parser.ReadBits(1) == 1);
+ if (m_Extension.m_SbrPresent) {
+ result = ParseSamplingFrequency(parser,
+ m_Extension.m_SamplingFrequencyIndex,
+ m_Extension.m_SamplingFrequency);
+ if (AP4_FAILED(result)) return result;
+ }
+ parser.ReadBits(4); // extensionChannelConfiguration
+ }
+ }
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
| AP4_Mp4AudioDecoderConfig::ParseGASpecificInfo
+---------------------------------------------------------------------*/
AP4_Result
@@ -137,11 +176,34 @@ AP4_Mp4AudioDecoderConfig::ParseGASpecificInfo(AP4_Mp4AudioDsiParser& parser)
m_CoreCoderDelay = 0;
}
if (parser.BitsLeft() < 1) return AP4_ERROR_INVALID_FORMAT;
- parser.ReadBits(1); /* extensionFlag */
+ unsigned int extensionFlag = parser.ReadBits(1);
if (m_ChannelConfiguration == CHANNEL_CONFIG_NONE) {
/*program_config_element (); */
+ return AP4_ERROR_NOT_SUPPORTED;
}
-
+ if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SCALABLE ||
+ m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_SCALABLE) {
+ if (parser.BitsLeft() < 3) return AP4_ERROR_INVALID_FORMAT;
+ parser.ReadBits(3); // layerNr
+ }
+ if (extensionFlag) {
+ if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC) {
+ if (parser.BitsLeft() < 16) return AP4_ERROR_INVALID_FORMAT;
+ parser.ReadBits(16); // numOfSubFrame (5); layer_length (11)
+ }
+ if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LC ||
+ m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_SCALABLE ||
+ m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LD) {
+ if (parser.BitsLeft() < 3) return AP4_ERROR_INVALID_FORMAT;
+ parser.ReadBits(3); // aacSectionDataResilienceFlag (1)
+ // aacScalefactorDataResilienceFlag (1)
+ // aacSpectralDataResilienceFlag (1)
+ }
+ if (parser.BitsLeft() < 1) return AP4_ERROR_INVALID_FORMAT;
+ unsigned int extensionFlag3 = parser.ReadBits(1);
+ if (extensionFlag3) return AP4_ERROR_NOT_SUPPORTED;
+ }
+
return AP4_SUCCESS;
}
@@ -218,6 +280,10 @@ AP4_Mp4AudioDecoderConfig::Parse(const unsigned char* data,
if (AP4_FAILED(result)) return result;
result = ParseAudioObjectType(bits, m_ObjectType);
if (AP4_FAILED(result)) return result;
+ if (m_ObjectType == AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC) {
+ if (bits.BitsLeft() < 4) return AP4_ERROR_INVALID_FORMAT;
+ bits.ReadBits(4); // extensionChannelConfiguration (4)
+ }
} else {
m_Extension.m_ObjectType = 0;
m_Extension.m_SamplingFrequency = 0;
@@ -240,6 +306,17 @@ AP4_Mp4AudioDecoderConfig::Parse(const unsigned char* data,
case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_TWINVQ:
case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC:
result = ParseGASpecificInfo(bits);
+ if (result == AP4_SUCCESS) {
+ if (m_Extension.m_ObjectType != AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR &&
+ bits.BitsLeft() >= 16) {
+ result = ParseExtension(bits);
+ }
+ }
+ if (result == AP4_ERROR_NOT_SUPPORTED) {
+ // not a fatal error
+ result = AP4_SUCCESS;
+ }
+ if (result != AP4_SUCCESS) return result;
break;
default:
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.h b/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.h
index eeb629069..f6e754b89 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Codecs/Ap4Mp4AudioInfo.h
@@ -98,6 +98,7 @@ private:
AP4_Result ParseSamplingFrequency(AP4_Mp4AudioDsiParser& parser,
unsigned int& sampling_frequency_index,
unsigned int& sampling_frequency);
+ AP4_Result ParseExtension(AP4_Mp4AudioDsiParser& parser);
};
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Config/Ap4Config.h b/src/filters/parser/MP4Splitter/AP4/Source/Config/Ap4Config.h
index b93154a10..5c786a58f 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Config/Ap4Config.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Config/Ap4Config.h
@@ -1,140 +1,142 @@
-/*****************************************************************
-|
-| AP4 - Target Platform and Compiler Configuration
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-/**
- * @file
- * @brief Platform Configuration
- */
-#ifndef _AP4_CONFIG_H_
-#define _AP4_CONFIG_H_
-
-/*----------------------------------------------------------------------
-| defaults
-+---------------------------------------------------------------------*/
-#define AP4_CONFIG_HAVE_STDIO_H
-#define AP4_CONFIG_HAVE_ASSERT_H
-#define AP4_CONFIG_HAVE_STRING_H
-#define AP4_CONFIG_HAVE_SNPRINTF
-#define AP4_CONFIG_HAVE_VSNPRINTF
-#define AP4_CONFIG_HAVE_INT64
-
-/*----------------------------------------------------------------------
-| byte order
-+---------------------------------------------------------------------*/
-// define AP4_PLATFORM_BYTE_ORDER to one of these two choices
-#define AP4_PLATFORM_BYTE_ORDER_BIG_ENDIAN 0
-#define AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN 1
-
-#if !defined(AP4_PLATFORM_BYTE_ORDER)
-#if defined(__ppc__)
-#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_BIG_ENDIAN
-#else
-#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
-#endif
-#endif
-
-/*----------------------------------------------------------------------
-| standard C++ runtime
-+---------------------------------------------------------------------*/
-#define APT_CONFIG_HAVE_NEW_H
-
-/*----------------------------------------------------------------------
-| platform specifics
-+---------------------------------------------------------------------*/
-
-/* Microsoft Platforms */
-#if defined(_MSC_VER)
-#define AP4_CONFIG_INT64_TYPE __int64
-#if (_MSC_VER >= 1400) && !defined(_WIN32_WCE)
-#define AP4_CONFIG_HAVE_FOPEN_S
-#define AP4_snprintf(s,c,f,...) _snprintf_s(s,c,_TRUNCATE,f,__VA_ARGS__)
-#define AP4_vsnprintf(s,c,f,a) _vsnprintf_s(s,c,_TRUNCATE,f,a)
-#define fileno _fileno
-#define AP4_fseek _fseeki64
-#define AP4_ftell _ftelli64
-#else
-#define AP4_snprintf _snprintf
-#define AP4_vsnprintf _vsnprintf
-#endif
-#if defined(_WIN32_WCE)
-#define AP4_fseek fseek
-#define AP4_ftell ftell
-#endif
-#if defined(_DEBUG)
-#define _CRTDBG_MAP_ALLOC
-#endif
-#endif
-
-/* Cygwin */
-#if defined(__CYGWIN__)
-#define AP4_fseek fseek
-#define AP4_ftell ftell
-#endif
-
-/* Symbian */
-#if defined(__SYMBIAN32__)
-#undef APT_CONFIG_HAVE_NEW_H
-#include "e32std.h"
-/**
- * Define the Platform byte order here
- * for Symbian.
- */
-#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
-#define AP4_fseek fseek
-#define AP4_ftell ftell
-#define explicit
-#endif
-
-/* Android */
-#if defined(ANDROID)
-#define AP4_CONFIG_NO_RTTI
-#define AP4_CONFIG_NO_EXCEPTIONS
-#endif
-
-/*----------------------------------------------------------------------
-| defaults
-+---------------------------------------------------------------------*/
-#if !defined(AP4_CONFIG_INT64_TYPE)
-#define AP4_CONFIG_INT64_TYPE long long
-#endif
-
-#if !defined(AP4_fseek)
-#define AP4_fseek fseeko
-#endif
-#if !defined(AP4_ftell)
-#define AP4_ftell ftello
-#endif
-
-/* some compilers (ex: MSVC 8) deprecate those, so we rename them */
-#if !defined(AP4_snprintf)
-#define AP4_snprintf snprintf
-#endif
-#if !defined(AP4_vsnprintf)
-#define AP4_vsnprintf vsnprintf
-#endif
-
-#endif // _AP4_CONFIG_H_
+/*****************************************************************
+|
+| AP4 - Target Platform and Compiler Configuration
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+/**
+ * @file
+ * @brief Platform Configuration
+ */
+#ifndef _AP4_CONFIG_H_
+#define _AP4_CONFIG_H_
+
+/*----------------------------------------------------------------------
+| defaults
++---------------------------------------------------------------------*/
+#define AP4_CONFIG_HAVE_STDIO_H
+#define AP4_CONFIG_HAVE_ASSERT_H
+#define AP4_CONFIG_HAVE_STRING_H
+#define AP4_CONFIG_HAVE_SNPRINTF
+#define AP4_CONFIG_HAVE_VSNPRINTF
+#define AP4_CONFIG_HAVE_INT64
+
+/*----------------------------------------------------------------------
+| byte order
++---------------------------------------------------------------------*/
+// define AP4_PLATFORM_BYTE_ORDER to one of these two choices
+#define AP4_PLATFORM_BYTE_ORDER_BIG_ENDIAN 0
+#define AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN 1
+
+#if !defined(AP4_PLATFORM_BYTE_ORDER)
+#if defined(__ppc__)
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_BIG_ENDIAN
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
+#else /* MPC custom */
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
+#endif
+#endif
+
+/*----------------------------------------------------------------------
+| standard C++ runtime
++---------------------------------------------------------------------*/
+#define APT_CONFIG_HAVE_NEW_H
+
+/*----------------------------------------------------------------------
+| platform specifics
++---------------------------------------------------------------------*/
+
+/* Microsoft Platforms */
+#if defined(_MSC_VER)
+#define AP4_CONFIG_INT64_TYPE __int64
+#if (_MSC_VER >= 1400) && !defined(_WIN32_WCE)
+#define AP4_CONFIG_HAVE_FOPEN_S
+#define AP4_snprintf(s,c,f,...) _snprintf_s(s,c,_TRUNCATE,f,__VA_ARGS__)
+#define AP4_vsnprintf(s,c,f,a) _vsnprintf_s(s,c,_TRUNCATE,f,a)
+#define fileno _fileno
+#define AP4_fseek _fseeki64
+#define AP4_ftell _ftelli64
+#else
+#define AP4_snprintf _snprintf
+#define AP4_vsnprintf _vsnprintf
+#endif
+#if defined(_WIN32_WCE)
+#define AP4_fseek fseek
+#define AP4_ftell ftell
+#endif
+#if defined(_DEBUG)
+#define _CRTDBG_MAP_ALLOC
+#endif
+#endif
+
+/* Cygwin */
+#if defined(__CYGWIN__)
+#define AP4_fseek fseek
+#define AP4_ftell ftell
+#endif
+
+/* Symbian */
+#if defined(__SYMBIAN32__)
+#undef APT_CONFIG_HAVE_NEW_H
+#include "e32std.h"
+/**
+ * Define the Platform byte order here
+ * for Symbian.
+ */
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
+#define AP4_fseek fseek
+#define AP4_ftell ftell
+#define explicit
+#endif
+
+/* Android */
+#if defined(ANDROID)
+#define AP4_CONFIG_NO_RTTI
+#define AP4_CONFIG_NO_EXCEPTIONS
+#endif
+
+/*----------------------------------------------------------------------
+| defaults
++---------------------------------------------------------------------*/
+#if !defined(AP4_CONFIG_INT64_TYPE)
+#define AP4_CONFIG_INT64_TYPE long long
+#endif
+
+#if !defined(AP4_fseek)
+#define AP4_fseek fseeko
+#endif
+#if !defined(AP4_ftell)
+#define AP4_ftell ftello
+#endif
+
+/* some compilers (ex: MSVC 8) deprecate those, so we rename them */
+#if !defined(AP4_snprintf)
+#define AP4_snprintf snprintf
+#endif
+#if !defined(AP4_vsnprintf)
+#define AP4_vsnprintf vsnprintf
+#endif
+
+#endif // _AP4_CONFIG_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Array.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Array.h
index b62bac22c..dd52cf38c 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Array.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Array.h
@@ -1,233 +1,233 @@
-/*****************************************************************
-|
-| AP4 - Arrays
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-/**
- * @file
- * @brief Arrays
- */
-
-#ifndef _AP4_ARRAY_H_
-#define _AP4_ARRAY_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Config.h"
-#if defined(APT_CONFIG_HAVE_NEW_H)
-#include <new>
-#endif
-#include "Ap4Types.h"
-#include "Ap4Results.h"
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const int AP4_ARRAY_INITIAL_COUNT = 64;
-
-/*----------------------------------------------------------------------
-| AP4_Array
-+---------------------------------------------------------------------*/
-template <typename T>
-class AP4_Array
-{
-public:
- // methods
- AP4_Array(): m_AllocatedCount(0), m_ItemCount(0), m_Items(0) {}
- AP4_Array(const T* items, AP4_Size count);
- virtual ~AP4_Array();
- AP4_Cardinal ItemCount() const { return m_ItemCount; }
- AP4_Result Append(const T& item);
- AP4_Result RemoveLast();
- T& operator[](unsigned long idx) { return m_Items[idx]; }
- const T& operator[](unsigned long idx) const { return m_Items[idx]; }
- AP4_Result Clear();
- AP4_Result EnsureCapacity(AP4_Cardinal count);
- AP4_Result SetItemCount(AP4_Cardinal item_count);
-
-protected:
- // members
- AP4_Cardinal m_AllocatedCount;
- AP4_Cardinal m_ItemCount;
- T* m_Items;
-};
-
-/*----------------------------------------------------------------------
-| AP4_Array<T>::AP4_Array<T>
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Array<T>::AP4_Array(const T* items, AP4_Size count) :
- m_AllocatedCount(count),
- m_ItemCount(count),
- m_Items((T*)::operator new(count*sizeof(T)))
-{
- for (unsigned int i=0; i<count; i++) {
- new ((void*)&m_Items[i]) T(items[i]);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_Array<T>::~AP4_Array<T>
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Array<T>::~AP4_Array()
-{
- Clear();
- ::operator delete((void*)m_Items);
-}
-
-/*----------------------------------------------------------------------
-| NPT_Array<T>::Clear
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_Array<T>::Clear()
-{
- // destroy all items
- for (AP4_Ordinal i=0; i<m_ItemCount; i++) {
- m_Items[i].~T();
- }
-
- m_ItemCount = 0;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Array<T>::EnsureCapacity
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_Array<T>::EnsureCapacity(AP4_Cardinal count)
-{
- // check if we already have enough
- if (count <= m_AllocatedCount) return AP4_SUCCESS;
-
- // (re)allocate the items
- T* new_items = (T*) ::operator new (count*sizeof(T));
- if (new_items == NULL) {
- return AP4_ERROR_OUT_OF_MEMORY;
- }
- if (m_ItemCount && m_Items) {
- for (unsigned int i=0; i<m_ItemCount; i++) {
- new ((void*)&new_items[i]) T(m_Items[i]);
- m_Items[i].~T();
- }
- ::operator delete((void*)m_Items);
- }
- m_Items = new_items;
- m_AllocatedCount = count;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Array<T>::SetItemCount
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_Array<T>::SetItemCount(AP4_Cardinal item_count)
-{
- // shortcut
- if (item_count == m_ItemCount) return AP4_SUCCESS;
-
- // check for a reduction in the number of items
- if (item_count < m_ItemCount) {
- // destruct the items that are no longer needed
- for (unsigned int i=item_count; i<m_ItemCount; i++) {
- m_Items[i].~T();
- }
- m_ItemCount = item_count;
- return AP4_SUCCESS;
- }
-
- // grow the list
- AP4_Result result = EnsureCapacity(item_count);
- if (AP4_FAILED(result)) return result;
-
- // construct the new items
- for (unsigned int i=m_ItemCount; i<item_count; i++) {
- new ((void*)&m_Items[i]) T();
- }
- m_ItemCount = item_count;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Array<T>::RemoveLast
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_Array<T>::RemoveLast()
-{
- if (m_ItemCount) {
- m_Items[--m_ItemCount].~T();
- return AP4_SUCCESS;
- } else {
- return AP4_ERROR_OUT_OF_RANGE;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_Array<T>::Append
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_Array<T>::Append(const T& item)
-{
- // ensure that we have enough space
- if (m_AllocatedCount < m_ItemCount+1) {
- // try double the size, with a minimum
- unsigned long new_count = m_AllocatedCount?2*m_AllocatedCount:AP4_ARRAY_INITIAL_COUNT;
-
- // if that's still not enough, just ask for what we need
- if (new_count < m_ItemCount+1) new_count = m_ItemCount+1;
-
- // reserve the space
- AP4_Result result = EnsureCapacity(new_count);
- if (result != AP4_SUCCESS) return result;
- }
-
- // store the item
- new ((void*)&m_Items[m_ItemCount++]) T(item);
-
- return AP4_SUCCESS;
-}
-
-#endif // _AP4_ARRAY_H_
-
-
-
-
-
-
-
-
-
-
-
-
-
+/*****************************************************************
+|
+| AP4 - Arrays
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+/**
+ * @file
+ * @brief Arrays
+ */
+
+#ifndef _AP4_ARRAY_H_
+#define _AP4_ARRAY_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Config.h"
+#if defined(APT_CONFIG_HAVE_NEW_H)
+#include <new>
+#endif
+#include "Ap4Types.h"
+#include "Ap4Results.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int AP4_ARRAY_INITIAL_COUNT = 64;
+
+/*----------------------------------------------------------------------
+| AP4_Array
++---------------------------------------------------------------------*/
+template <typename T>
+class AP4_Array
+{
+public:
+ // methods
+ AP4_Array(): m_AllocatedCount(0), m_ItemCount(0), m_Items(0) {}
+ AP4_Array(const T* items, AP4_Size count);
+ virtual ~AP4_Array();
+ AP4_Cardinal ItemCount() const { return m_ItemCount; }
+ AP4_Result Append(const T& item);
+ AP4_Result RemoveLast();
+ T& operator[](unsigned long idx) { return m_Items[idx]; }
+ const T& operator[](unsigned long idx) const { return m_Items[idx]; }
+ AP4_Result Clear();
+ AP4_Result EnsureCapacity(AP4_Cardinal count);
+ AP4_Result SetItemCount(AP4_Cardinal item_count);
+
+protected:
+ // members
+ AP4_Cardinal m_AllocatedCount;
+ AP4_Cardinal m_ItemCount;
+ T* m_Items;
+};
+
+/*----------------------------------------------------------------------
+| AP4_Array<T>::AP4_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Array<T>::AP4_Array(const T* items, AP4_Size count) :
+ m_AllocatedCount(count),
+ m_ItemCount(count),
+ m_Items((T*)::operator new(count*sizeof(T)))
+{
+ for (unsigned int i=0; i<count; i++) {
+ new ((void*)&m_Items[i]) T(items[i]);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_Array<T>::~AP4_Array<T>
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Array<T>::~AP4_Array()
+{
+ Clear();
+ ::operator delete((void*)m_Items);
+}
+
+/*----------------------------------------------------------------------
+| NPT_Array<T>::Clear
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_Array<T>::Clear()
+{
+ // destroy all items
+ for (AP4_Ordinal i=0; i<m_ItemCount; i++) {
+ m_Items[i].~T();
+ }
+
+ m_ItemCount = 0;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Array<T>::EnsureCapacity
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_Array<T>::EnsureCapacity(AP4_Cardinal count)
+{
+ // check if we already have enough
+ if (count <= m_AllocatedCount) return AP4_SUCCESS;
+
+ // (re)allocate the items
+ T* new_items = (T*) ::operator new (count*sizeof(T));
+ if (new_items == NULL) {
+ return AP4_ERROR_OUT_OF_MEMORY;
+ }
+ if (m_ItemCount && m_Items) {
+ for (unsigned int i=0; i<m_ItemCount; i++) {
+ new ((void*)&new_items[i]) T(m_Items[i]);
+ m_Items[i].~T();
+ }
+ ::operator delete((void*)m_Items);
+ }
+ m_Items = new_items;
+ m_AllocatedCount = count;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Array<T>::SetItemCount
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_Array<T>::SetItemCount(AP4_Cardinal item_count)
+{
+ // shortcut
+ if (item_count == m_ItemCount) return AP4_SUCCESS;
+
+ // check for a reduction in the number of items
+ if (item_count < m_ItemCount) {
+ // destruct the items that are no longer needed
+ for (unsigned int i=item_count; i<m_ItemCount; i++) {
+ m_Items[i].~T();
+ }
+ m_ItemCount = item_count;
+ return AP4_SUCCESS;
+ }
+
+ // grow the list
+ AP4_Result result = EnsureCapacity(item_count);
+ if (AP4_FAILED(result)) return result;
+
+ // construct the new items
+ for (unsigned int i=m_ItemCount; i<item_count; i++) {
+ new ((void*)&m_Items[i]) T();
+ }
+ m_ItemCount = item_count;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Array<T>::RemoveLast
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_Array<T>::RemoveLast()
+{
+ if (m_ItemCount) {
+ m_Items[--m_ItemCount].~T();
+ return AP4_SUCCESS;
+ } else {
+ return AP4_ERROR_OUT_OF_RANGE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_Array<T>::Append
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_Array<T>::Append(const T& item)
+{
+ // ensure that we have enough space
+ if (m_AllocatedCount < m_ItemCount+1) {
+ // try double the size, with a minimum
+ unsigned long new_count = m_AllocatedCount?2*m_AllocatedCount:AP4_ARRAY_INITIAL_COUNT;
+
+ // if that's still not enough, just ask for what we need
+ if (new_count < m_ItemCount+1) new_count = m_ItemCount+1;
+
+ // reserve the space
+ AP4_Result result = EnsureCapacity(new_count);
+ if (result != AP4_SUCCESS) return result;
+ }
+
+ // store the item
+ new ((void*)&m_Items[m_ItemCount++]) T(item);
+
+ return AP4_SUCCESS;
+}
+
+#endif // _AP4_ARRAY_H_
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.cpp
index a9bd81e6b..0110cb3e3 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.cpp
@@ -297,8 +297,8 @@ AP4_Atom::InspectHeader(AP4_AtomInspector& inspector)
}
}
AP4_FormatString(header, sizeof(header),
- "size=%ld+%lld%s",
- GetHeaderSize(),
+ "size=%d+%lld%s",
+ (int)GetHeaderSize(),
GetSize()-GetHeaderSize(),
extra);
inspector.StartElement(name, header);
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.h
index 7301821a3..e755cfeae 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Atom.h
@@ -462,10 +462,10 @@ const AP4_Atom::Type AP4_ATOM_TYPE_QDMC = AP4_ATOM_TYPE('Q','D','M','C');
const AP4_Atom::Type AP4_ATOM_TYPE_QDM2 = AP4_ATOM_TYPE('Q','D','M','2');
const AP4_Atom::Type AP4_ATOM_TYPE_TWOS = AP4_ATOM_TYPE('t','w','o','s');
const AP4_Atom::Type AP4_ATOM_TYPE_SOWT = AP4_ATOM_TYPE('s','o','w','t');
-
-const AP4_Atom::Type AP4_ATOM_TYPE_CMOV = AP4_ATOM_TYPE('c','m','o','v');
-const AP4_Atom::Type AP4_ATOM_TYPE_DCOM = AP4_ATOM_TYPE('d','c','o','m');
-const AP4_Atom::Type AP4_ATOM_TYPE_CMVD = AP4_ATOM_TYPE('c','m','v','d');
+
+const AP4_Atom::Type AP4_ATOM_TYPE_CMOV = AP4_ATOM_TYPE('c','m','o','v');
+const AP4_Atom::Type AP4_ATOM_TYPE_DCOM = AP4_ATOM_TYPE('d','c','o','m');
+const AP4_Atom::Type AP4_ATOM_TYPE_CMVD = AP4_ATOM_TYPE('c','m','v','d');
// <== End patch MPC
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.cpp
index 04158c4aa..cd276eaf4 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.cpp
@@ -1,774 +1,794 @@
-/*****************************************************************
-|
-| AP4 - Atom Factory
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4Utils.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4SampleEntry.h"
-#include "Ap4UuidAtom.h"
-#include "Ap4IsmaCryp.h"
-#include "Ap4UrlAtom.h"
-#include "Ap4MoovAtom.h"
-#include "Ap4MvhdAtom.h"
-#include "Ap4MehdAtom.h"
-#include "Ap4MfhdAtom.h"
-#include "Ap4TfhdAtom.h"
-#include "Ap4TrunAtom.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4HdlrAtom.h"
-#include "Ap4DrefAtom.h"
-#include "Ap4TkhdAtom.h"
-#include "Ap4TrexAtom.h"
-#include "Ap4TfhdAtom.h"
-#include "Ap4MdhdAtom.h"
-#include "Ap4StsdAtom.h"
-#include "Ap4StscAtom.h"
-#include "Ap4StcoAtom.h"
-#include "Ap4Co64Atom.h"
-#include "Ap4StszAtom.h"
-#include "Ap4IodsAtom.h"
-#include "Ap4EsdsAtom.h"
-#include "Ap4SttsAtom.h"
-#include "Ap4CttsAtom.h"
-#include "Ap4StssAtom.h"
-#include "Ap4FtypAtom.h"
-#include "Ap4VmhdAtom.h"
-#include "Ap4SmhdAtom.h"
-#include "Ap4NmhdAtom.h"
-#include "Ap4HmhdAtom.h"
-#include "Ap4ElstAtom.h"
-#include "Ap4SchmAtom.h"
-#include "Ap4FrmaAtom.h"
-#include "Ap4TimsAtom.h"
-#include "Ap4RtpAtom.h"
-#include "Ap4SdpAtom.h"
-#include "Ap4IkmsAtom.h"
-#include "Ap4IsfmAtom.h"
-#include "Ap4IsltAtom.h"
-#include "Ap4OdheAtom.h"
-#include "Ap4OhdrAtom.h"
-#include "Ap4OddaAtom.h"
-#include "Ap4TrefTypeAtom.h"
-#include "Ap4MetaData.h"
-#include "Ap4IproAtom.h"
-#include "Ap4OdafAtom.h"
-#include "Ap4GrpiAtom.h"
-#include "Ap4AvccAtom.h"
-#include "Ap4Marlin.h"
-#include "Ap48bdlAtom.h"
-#include "Ap4Piff.h"
-#include "Ap4TfraAtom.h"
-#include "Ap4MfroAtom.h"
-
-// ==> Start patch MPC
-#include "Ap4ChplAtom.h"
-#include "Ap4FtabAtom.h"
-#include "Ap4DcomAtom.h"
-#include "AP4CmvdAtom.h"
-// <== End patch MPC
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::~AP4_AtomFactory
-+---------------------------------------------------------------------*/
-AP4_AtomFactory::~AP4_AtomFactory()
-{
- m_TypeHandlers.DeleteReferences();
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::AddTypeHandler
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomFactory::AddTypeHandler(TypeHandler* handler)
-{
- return m_TypeHandlers.Add(handler);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::RemoveTypeHandler
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomFactory::RemoveTypeHandler(TypeHandler* handler)
-{
- return m_TypeHandlers.Remove(handler);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::CreateAtomFromStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
- AP4_Atom*& atom)
-{
- AP4_LargeSize stream_size = 0;
- AP4_Position stream_position = 0;
- AP4_LargeSize bytes_available = (AP4_LargeSize)(-1);
- if (AP4_SUCCEEDED(stream.GetSize(stream_size)) &&
- stream_size != 0 &&
- AP4_SUCCEEDED(stream.Tell(stream_position)) &&
- stream_position <= stream_size) {
- bytes_available = stream_size-stream_position;
- }
- return CreateAtomFromStream(stream, bytes_available, atom);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::CreateAtomFromStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
- AP4_LargeSize& bytes_available,
- AP4_Atom*& atom)
-{
- AP4_Result result;
-
- // NULL by default
- atom = NULL;
-
- // check that there are enough bytes for at least a header
- if (bytes_available < 8) return AP4_ERROR_EOS;
-
- // remember current stream offset
- AP4_Position start;
- stream.Tell(start);
-
- // read atom size
- AP4_UI32 size_32;
- result = stream.ReadUI32(size_32);
- if (AP4_FAILED(result)) {
- stream.Seek(start);
- return result;
- }
- AP4_UI64 size = size_32;
-
- // read atom type
- AP4_Atom::Type type;
- result = stream.ReadUI32(type);
- if (AP4_FAILED(result)) {
- stream.Seek(start);
- return result;
- }
-
- // handle special size values
- bool atom_is_large = false;
- bool force_64 = false;
- if (size == 0) {
- // atom extends to end of file
- AP4_LargeSize stream_size = 0;
- stream.GetSize(stream_size);
- if (stream_size >= start) {
- size = stream_size - start;
- }
- } else if (size == 1) {
- // 64-bit size
- atom_is_large = true;
- if (bytes_available < 16) {
- stream.Seek(start);
- return AP4_ERROR_INVALID_FORMAT;
- }
- stream.ReadUI64(size);
- if (size <= 0xFFFFFFFF) {
- force_64 = true;
- }
- }
-
- // check the size
- if ((size > 0 && size < 8) || size > bytes_available) {
- stream.Seek(start);
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // create the atom
- if (GetContext() == AP4_ATOM_TYPE_STSD) {
- // sample entry
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- switch (type) {
- case AP4_ATOM_TYPE_MP4A:
- atom = new AP4_Mp4aSampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_MP4V:
- atom = new AP4_Mp4vSampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_MP4S:
- atom = new AP4_Mp4sSampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_ENCA:
- atom = new AP4_EncaSampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_ENCV:
- atom = new AP4_EncvSampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_DRMS:
- atom = new AP4_DrmsSampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_DRMI:
- atom = new AP4_DrmiSampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_AVC1:
- atom = new AP4_Avc1SampleEntry(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_ALAC:
- // ==> Start patch MPC
-// case AP4_ATOM_TYPE_AC_3:
- // <== End patch MPC
- case AP4_ATOM_TYPE_EC_3:
- atom = new AP4_AudioSampleEntry(type, size_32, stream, *this);
- break;
-
- // ==> Start patch MPC
- case AP4_ATOM_TYPE_TEXT:
- atom = new AP4_TextSampleEntry((unsigned long)size, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_TX3G:
- atom = new AP4_Tx3gSampleEntry((unsigned long)size, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_FTAB:
- atom = new AP4_FtabAtom((unsigned long)size, stream);
- break;
-
- case AP4_ATOM_TYPE_CHPL:
- atom = new AP4_ChplAtom((unsigned long)size, stream);
- break;
-
- case AP4_ATOM_TYPE_CVID:
- case AP4_ATOM_TYPE_SVQ1:
- case AP4_ATOM_TYPE_SVQ2:
- case AP4_ATOM_TYPE_SVQ3:
- case AP4_ATOM_TYPE_H263:
- case AP4_ATOM_TYPE_S263:
- atom = new AP4_VisualSampleEntry(type, (unsigned long)size, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_SAMR:
- case AP4_ATOM_TYPE__MP3:
- case AP4_ATOM_TYPE_IMA4:
- case AP4_ATOM_TYPE_QDMC:
- case AP4_ATOM_TYPE_QDM2:
- case AP4_ATOM_TYPE_TWOS:
- case AP4_ATOM_TYPE_SOWT:
- atom = new AP4_AudioSampleEntry(type, (unsigned long)size, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_AC_3: // AC3-in-MP4 from ISO Standard
- case AP4_ATOM_TYPE_SAC3: // AC3-in-MP4 from Nero Stuff >.<
- atom = new AP4_AC3SampleEntry(type, (unsigned long)size, stream, *this);
- break;
- // <== End patch MPC
-
- case AP4_ATOM_TYPE_RTP_:
- atom = new AP4_RtpHintSampleEntry(size_32, stream, *this);
- break;
-
- default:
- {
- // try all the external type handlers
- AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
- while (handler_item) {
- TypeHandler* handler = handler_item->GetData();
- if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
- break;
- }
- handler_item = handler_item->GetNext();
- }
-
- // no custom handler, create a generic entry
- atom = new AP4_UnknownSampleEntry(type, (AP4_Size)size, stream);
- }
- break;
- }
- } else {
- // regular atom
- switch (type) {
- case AP4_ATOM_TYPE_MOOV:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_MoovAtom::Create(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_MVHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_MvhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_MEHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_MehdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_MFHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_MfhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_TRAK:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TrakAtom::Create(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_TREX:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TrexAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_HDLR:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_HdlrAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_TKHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TkhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_TFHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TfhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_TRUN:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TrunAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_TFRA:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TfraAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_MFRO:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_MfroAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_MDHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_MdhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_STSD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_StsdAtom::Create(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_STSC:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_StscAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_STCO:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_StcoAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_CO64:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_Co64Atom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_STSZ:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_StszAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_STTS:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_SttsAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_CTTS:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_CttsAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_STSS:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_StssAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_IODS:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_IodsAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_ESDS:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_EsdsAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_AVCC:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_AvccAtom::Create(size_32, stream);
- break;
-
- #if !defined(AP4_CONFIG_MINI_BUILD)
- case AP4_ATOM_TYPE_UUID: {
- AP4_UI08 uuid[16];
- result = stream.Read(uuid, 16);
- if (AP4_FAILED(result)) return result;
-
- if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_TRACK_ENCRYPTION_ATOM, 16) == 0) {
- atom = AP4_PiffTrackEncryptionAtom::Create((AP4_Size)size, stream);
- } else if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_SAMPLE_ENCRYPTION_ATOM, 16) == 0) {
- atom = AP4_PiffSampleEncryptionAtom::Create((AP4_Size)size, stream);
- } else {
- atom = new AP4_UnknownUuidAtom(size, uuid, stream);
- }
- break;
- }
-
- case AP4_ATOM_TYPE_8ID_:
- atom = new AP4_NullTerminatedStringAtom(type, size, stream);
- break;
-
- case AP4_ATOM_TYPE_8BDL:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_8bdlAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_DREF:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_DrefAtom::Create(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_URL:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_UrlAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_ELST:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_ElstAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_VMHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_VmhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_SMHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_SmhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_NMHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_NmhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_HMHD:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_HmhdAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_FRMA:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_FrmaAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_SCHM:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_SchmAtom::Create(size_32, &m_ContextStack, stream);
- break;
-
- case AP4_ATOM_TYPE_FTYP:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_FtypAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_TIMS:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TimsAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_SDP_:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_SdpAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_IKMS:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_IkmsAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_ISFM:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_IsfmAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_ISLT:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_IsltAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_ODHE:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_OdheAtom::Create(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_OHDR:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_OhdrAtom::Create(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_ODDA:
- atom = AP4_OddaAtom::Create(size, stream);
- break;
-
- case AP4_ATOM_TYPE_ODAF:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_OdafAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_GRPI:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_GrpiAtom::Create(size_32, stream);
- break;
-
- case AP4_ATOM_TYPE_IPRO:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_IproAtom::Create(size_32, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_RTP_:
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_RtpAtom::Create(size_32, stream);
- break;
-
- // track ref types
- case AP4_ATOM_TYPE_HINT:
- case AP4_ATOM_TYPE_CDSC:
- case AP4_ATOM_TYPE_SYNC:
- case AP4_ATOM_TYPE_MPOD:
- case AP4_ATOM_TYPE_DPND:
- case AP4_ATOM_TYPE_IPIR:
- case AP4_ATOM_TYPE_ALIS:
- case AP4_ATOM_TYPE_CHAP:
- if (GetContext() == AP4_ATOM_TYPE_TREF) {
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_TrefTypeAtom::Create(type, size_32, stream);
- }
- break;
-
- #endif // AP4_CONFIG_MINI_BUILD
-
- // container atoms
- case AP4_ATOM_TYPE_MOOF:
- case AP4_ATOM_TYPE_MVEX:
- case AP4_ATOM_TYPE_TRAF:
- case AP4_ATOM_TYPE_TREF:
- case AP4_ATOM_TYPE_MFRA:
- case AP4_ATOM_TYPE_HNTI:
- case AP4_ATOM_TYPE_STBL:
- case AP4_ATOM_TYPE_MDIA:
- case AP4_ATOM_TYPE_DINF:
- case AP4_ATOM_TYPE_MINF:
- case AP4_ATOM_TYPE_SCHI:
- case AP4_ATOM_TYPE_SINF:
- case AP4_ATOM_TYPE_UDTA:
- case AP4_ATOM_TYPE_ILST:
- case AP4_ATOM_TYPE_EDTS:
- case AP4_ATOM_TYPE_MDRI:
- case AP4_ATOM_TYPE_WAVE:
-
- // ==> Start patch MPC
- case AP4_ATOM_TYPE_ART:
- case AP4_ATOM_TYPE_WRT:
- case AP4_ATOM_TYPE_ALB:
- case AP4_ATOM_TYPE_DAY:
- case AP4_ATOM_TYPE_TOO:
- case AP4_ATOM_TYPE_CMT:
- case AP4_ATOM_TYPE_GEN:
- case AP4_ATOM_TYPE_CMOV:
- // <== End patch MPC
-
- if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
- atom = AP4_ContainerAtom::Create(type, size, false, force_64, stream, *this);
- break;
-
- // full container atoms
- case AP4_ATOM_TYPE_META:
- case AP4_ATOM_TYPE_ODRM:
- case AP4_ATOM_TYPE_ODKM:
- atom = AP4_ContainerAtom::Create(type, size, true, force_64, stream, *this);
- break;
-
- case AP4_ATOM_TYPE_FREE:
- case AP4_ATOM_TYPE_WIDE:
- case AP4_ATOM_TYPE_MDAT:
- // generic atoms
- break;
-
- // ==> Start patch MPC
- case AP4_ATOM_TYPE_DCOM:
- atom = AP4_DcomAtom::Create((unsigned long)size, stream);
- break;
- case AP4_ATOM_TYPE_CMVD:
- atom = AP4_CmvdAtom::Create((unsigned long)size, stream, *this);
- break;
- // <== End patch MPC
-
- default:
- // try all the external type handlers
- {
- AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
- while (handler_item) {
- TypeHandler* handler = handler_item->GetData();
- if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
- break;
- }
- handler_item = handler_item->GetNext();
- }
-
- break;
- }
- }
- }
-
- // if we failed to create an atom, use a generic version
- if (atom == NULL) {
- unsigned int payload_offset = 8;
- if (atom_is_large) payload_offset += 8;
- stream.Seek(start+payload_offset);
- atom = new AP4_UnknownAtom(type, size, stream);
- }
-
- // special case: if the atom is poorly encoded and has a 64-bit
- // size header but an actual size that fits on 32-bit, adjust the
- // object to reflect that.
- if (force_64) {
- atom->SetSize32(1);
- atom->SetSize64(size);
- }
-
- // adjust the available size
- bytes_available -= size;
-
- // skip to the end of the atom
- result = stream.Seek(start+size);
- if (AP4_FAILED(result)) {
- delete atom;
- atom = NULL;
- return result;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::CreateAtomsFromStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomFactory::CreateAtomsFromStream(AP4_ByteStream& stream,
- AP4_AtomParent& atoms)
-{
- AP4_LargeSize stream_size = 0;
- AP4_Position stream_position = 0;
- AP4_LargeSize bytes_available = (AP4_LargeSize)(-1);
- if (AP4_SUCCEEDED(stream.GetSize(stream_size)) &&
- stream_size != 0 &&
- AP4_SUCCEEDED(stream.Tell(stream_position)) &&
- stream_position <= stream_size) {
- bytes_available = stream_size-stream_position;
- }
- return CreateAtomsFromStream(stream, bytes_available, atoms);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::CreateAtomsFromStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomFactory::CreateAtomsFromStream(AP4_ByteStream& stream,
- AP4_LargeSize bytes_available,
- AP4_AtomParent& atoms)
-{
- AP4_Result result;
- do {
- AP4_Atom* atom = NULL;
- result = CreateAtomFromStream(stream, bytes_available, atom);
- if (AP4_SUCCEEDED(result) && atom != NULL) {
- atoms.AddChild(atom);
- }
- } while (AP4_SUCCEEDED(result));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::PushContext
-+---------------------------------------------------------------------*/
-void
-AP4_AtomFactory::PushContext(AP4_Atom::Type context)
-{
- m_ContextStack.Append(context);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::PopContext
-+---------------------------------------------------------------------*/
-void
-AP4_AtomFactory::PopContext()
-{
- m_ContextStack.RemoveLast();
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomFactory::GetContext
-+---------------------------------------------------------------------*/
-AP4_Atom::Type
-AP4_AtomFactory::GetContext(AP4_Ordinal depth)
-{
- AP4_Ordinal available = m_ContextStack.ItemCount();
- if (depth >= available) return 0;
- return m_ContextStack[available-depth-1];
-}
-
-/*----------------------------------------------------------------------
-| AP4_DefaultAtomFactory::Instance
-+---------------------------------------------------------------------*/
-AP4_DefaultAtomFactory AP4_DefaultAtomFactory::Instance;
-
-/*----------------------------------------------------------------------
-| AP4_DefaultAtomFactory::Instance
-+---------------------------------------------------------------------*/
-AP4_DefaultAtomFactory::AP4_DefaultAtomFactory()
-{
- // register built-in type handlers
- AddTypeHandler(new AP4_MetaDataAtomTypeHandler(this));
-}
+/*****************************************************************
+|
+| AP4 - Atom Factory
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4Utils.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4SampleEntry.h"
+#include "Ap4UuidAtom.h"
+#include "Ap4IsmaCryp.h"
+#include "Ap4UrlAtom.h"
+#include "Ap4MoovAtom.h"
+#include "Ap4MvhdAtom.h"
+#include "Ap4MehdAtom.h"
+#include "Ap4MfhdAtom.h"
+#include "Ap4TfhdAtom.h"
+#include "Ap4TrunAtom.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4HdlrAtom.h"
+#include "Ap4DrefAtom.h"
+#include "Ap4TkhdAtom.h"
+#include "Ap4TrexAtom.h"
+#include "Ap4TfhdAtom.h"
+#include "Ap4MdhdAtom.h"
+#include "Ap4StsdAtom.h"
+#include "Ap4StscAtom.h"
+#include "Ap4StcoAtom.h"
+#include "Ap4Co64Atom.h"
+#include "Ap4StszAtom.h"
+#include "Ap4IodsAtom.h"
+#include "Ap4EsdsAtom.h"
+#include "Ap4SttsAtom.h"
+#include "Ap4CttsAtom.h"
+#include "Ap4StssAtom.h"
+#include "Ap4FtypAtom.h"
+#include "Ap4VmhdAtom.h"
+#include "Ap4SmhdAtom.h"
+#include "Ap4NmhdAtom.h"
+#include "Ap4HmhdAtom.h"
+#include "Ap4ElstAtom.h"
+#include "Ap4SchmAtom.h"
+#include "Ap4FrmaAtom.h"
+#include "Ap4TimsAtom.h"
+#include "Ap4RtpAtom.h"
+#include "Ap4SdpAtom.h"
+#include "Ap4IkmsAtom.h"
+#include "Ap4IsfmAtom.h"
+#include "Ap4IsltAtom.h"
+#include "Ap4OdheAtom.h"
+#include "Ap4OhdrAtom.h"
+#include "Ap4OddaAtom.h"
+#include "Ap4TrefTypeAtom.h"
+#include "Ap4MetaData.h"
+#include "Ap4IproAtom.h"
+#include "Ap4OdafAtom.h"
+#include "Ap4GrpiAtom.h"
+#include "Ap4AvccAtom.h"
+#include "Ap4Marlin.h"
+#include "Ap48bdlAtom.h"
+#include "Ap4Piff.h"
+#include "Ap4TfraAtom.h"
+#include "Ap4MfroAtom.h"
+
+// ==> Start patch MPC
+#include "Ap4ChplAtom.h"
+#include "Ap4FtabAtom.h"
+#include "Ap4DcomAtom.h"
+#include "AP4CmvdAtom.h"
+// <== End patch MPC
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::~AP4_AtomFactory
++---------------------------------------------------------------------*/
+AP4_AtomFactory::~AP4_AtomFactory()
+{
+ m_TypeHandlers.DeleteReferences();
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::AddTypeHandler
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomFactory::AddTypeHandler(TypeHandler* handler)
+{
+ return m_TypeHandlers.Add(handler);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::RemoveTypeHandler
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomFactory::RemoveTypeHandler(TypeHandler* handler)
+{
+ return m_TypeHandlers.Remove(handler);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::CreateAtomFromStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
+ AP4_Atom*& atom)
+{
+ AP4_LargeSize stream_size = 0;
+ AP4_Position stream_position = 0;
+ AP4_LargeSize bytes_available = (AP4_LargeSize)(-1);
+ if (AP4_SUCCEEDED(stream.GetSize(stream_size)) &&
+ stream_size != 0 &&
+ AP4_SUCCEEDED(stream.Tell(stream_position)) &&
+ stream_position <= stream_size) {
+ bytes_available = stream_size-stream_position;
+ }
+ return CreateAtomFromStream(stream, bytes_available, atom);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::CreateAtomFromStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
+ AP4_LargeSize& bytes_available,
+ AP4_Atom*& atom)
+{
+ AP4_Result result;
+
+ // NULL by default
+ atom = NULL;
+
+ // check that there are enough bytes for at least a header
+ if (bytes_available < 8) return AP4_ERROR_EOS;
+
+ // remember current stream offset
+ AP4_Position start;
+ stream.Tell(start);
+
+ // read atom size
+ AP4_UI32 size_32;
+ result = stream.ReadUI32(size_32);
+ if (AP4_FAILED(result)) {
+ stream.Seek(start);
+ return result;
+ }
+ AP4_UI64 size = size_32;
+
+ // read atom type
+ AP4_Atom::Type type;
+ result = stream.ReadUI32(type);
+ if (AP4_FAILED(result)) {
+ stream.Seek(start);
+ return result;
+ }
+
+ // handle special size values
+ bool atom_is_large = false;
+ bool force_64 = false;
+ if (size == 0) {
+ // atom extends to end of file
+ AP4_LargeSize stream_size = 0;
+ stream.GetSize(stream_size);
+ if (stream_size >= start) {
+ size = stream_size - start;
+ }
+ } else if (size == 1) {
+ // 64-bit size
+ atom_is_large = true;
+ if (bytes_available < 16) {
+ stream.Seek(start);
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+ stream.ReadUI64(size);
+ if (size <= 0xFFFFFFFF) {
+ force_64 = true;
+ }
+ }
+
+ // check the size
+ if ((size > 0 && size < 8) || size > bytes_available) {
+ stream.Seek(start);
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // create the atom
+ result = CreateAtomFromStream(stream, type, size_32, size, atom);
+ if (AP4_FAILED(result)) return result;
+
+ // if we failed to create an atom, use a generic version
+ if (atom == NULL) {
+ unsigned int payload_offset = 8;
+ if (atom_is_large) payload_offset += 8;
+ stream.Seek(start+payload_offset);
+ atom = new AP4_UnknownAtom(type, size, stream);
+ }
+
+ // special case: if the atom is poorly encoded and has a 64-bit
+ // size header but an actual size that fits on 32-bit, adjust the
+ // object to reflect that.
+ if (force_64) {
+ atom->SetSize32(1);
+ atom->SetSize64(size);
+ }
+
+ // adjust the available size
+ bytes_available -= size;
+
+ // skip to the end of the atom
+ result = stream.Seek(start+size);
+ if (AP4_FAILED(result)) {
+ delete atom;
+ atom = NULL;
+ return result;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::CreateAtomFromStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
+ AP4_UI32 type,
+ AP4_UI32 size_32,
+ AP4_UI64 size_64,
+ AP4_Atom*& atom)
+{
+ AP4_Result result;
+ bool atom_is_large = (size_32 == 1);
+ bool force_64 = (size_32==1 && ((size_64>>32) == 0));
+
+ // create the atom
+ if (GetContext() == AP4_ATOM_TYPE_STSD) {
+ // sample entry
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ switch (type) {
+ case AP4_ATOM_TYPE_MP4A:
+ atom = new AP4_Mp4aSampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_MP4V:
+ atom = new AP4_Mp4vSampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_MP4S:
+ atom = new AP4_Mp4sSampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_ENCA:
+ atom = new AP4_EncaSampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_ENCV:
+ atom = new AP4_EncvSampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_DRMS:
+ atom = new AP4_DrmsSampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_DRMI:
+ atom = new AP4_DrmiSampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_AVC1:
+ atom = new AP4_Avc1SampleEntry(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_ALAC:
+ // ==> Start patch MPC
+// case AP4_ATOM_TYPE_AC_3:
+ // <== End patch MPC
+ case AP4_ATOM_TYPE_EC_3:
+ atom = new AP4_AudioSampleEntry(type, size_32, stream, *this);
+ break;
+
+ // ==> Start patch MPC
+ case AP4_ATOM_TYPE_TEXT:
+ atom = new AP4_TextSampleEntry(size_64, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_TX3G:
+ atom = new AP4_Tx3gSampleEntry(size_64, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_FTAB:
+ atom = new AP4_FtabAtom(size_64, stream);
+ break;
+
+ case AP4_ATOM_TYPE_CHPL:
+ atom = new AP4_ChplAtom(size_64, stream);
+ break;
+
+ case AP4_ATOM_TYPE_CVID:
+ case AP4_ATOM_TYPE_SVQ1:
+ case AP4_ATOM_TYPE_SVQ2:
+ case AP4_ATOM_TYPE_SVQ3:
+ case AP4_ATOM_TYPE_H263:
+ case AP4_ATOM_TYPE_S263:
+ atom = new AP4_VisualSampleEntry(type, size_64, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_SAMR:
+ case AP4_ATOM_TYPE__MP3:
+ case AP4_ATOM_TYPE_IMA4:
+ case AP4_ATOM_TYPE_QDMC:
+ case AP4_ATOM_TYPE_QDM2:
+ case AP4_ATOM_TYPE_TWOS:
+ case AP4_ATOM_TYPE_SOWT:
+ atom = new AP4_AudioSampleEntry(type, size_64, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_AC_3: // AC3-in-MP4 from ISO Standard
+ case AP4_ATOM_TYPE_SAC3: // AC3-in-MP4 from Nero Stuff >.<
+ atom = new AP4_AC3SampleEntry(type, size_64, stream, *this);
+ break;
+ // <== End patch MPC
+
+ case AP4_ATOM_TYPE_RTP_:
+ atom = new AP4_RtpHintSampleEntry(size_32, stream, *this);
+ break;
+
+ default: {
+ // try all the external type handlers
+ AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
+ while (handler_item) {
+ TypeHandler* handler = handler_item->GetData();
+ if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
+ break;
+ }
+ handler_item = handler_item->GetNext();
+ }
+
+ // no custom handler, create a generic entry
+ atom = new AP4_UnknownSampleEntry(type, (AP4_UI32)size_64, stream);
+
+ break;
+ }
+ }
+ } else {
+ // regular atom
+ switch (type) {
+ case AP4_ATOM_TYPE_MOOV:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_MoovAtom::Create(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_MVHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_MvhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_MEHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_MehdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_MFHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_MfhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_TRAK:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TrakAtom::Create(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_TREX:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TrexAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_HDLR:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_HdlrAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_TKHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TkhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_TFHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TfhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_TRUN:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TrunAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_TFRA:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TfraAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_MFRO:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_MfroAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_MDHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_MdhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_STSD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_StsdAtom::Create(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_STSC:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_StscAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_STCO:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_StcoAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_CO64:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_Co64Atom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_STSZ:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_StszAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_STTS:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_SttsAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_CTTS:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_CttsAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_STSS:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_StssAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_IODS:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_IodsAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_ESDS:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_EsdsAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_AVCC:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_AvccAtom::Create(size_32, stream);
+ break;
+
+ #if !defined(AP4_CONFIG_MINI_BUILD)
+ case AP4_ATOM_TYPE_UUID: {
+ AP4_UI08 uuid[16];
+ result = stream.Read(uuid, 16);
+ if (AP4_FAILED(result)) return result;
+
+ if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_TRACK_ENCRYPTION_ATOM, 16) == 0) {
+ atom = AP4_PiffTrackEncryptionAtom::Create((AP4_UI32)size_64, stream);
+ } else if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_SAMPLE_ENCRYPTION_ATOM, 16) == 0) {
+ atom = AP4_PiffSampleEncryptionAtom::Create((AP4_UI32)size_64, stream);
+ } else {
+ atom = new AP4_UnknownUuidAtom(size_64, uuid, stream);
+ }
+ break;
+ }
+
+ case AP4_ATOM_TYPE_8ID_:
+ atom = new AP4_NullTerminatedStringAtom(type, size_64, stream);
+ break;
+
+ case AP4_ATOM_TYPE_8BDL:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_8bdlAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_DREF:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_DrefAtom::Create(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_URL:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_UrlAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_ELST:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_ElstAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_VMHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_VmhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_SMHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_SmhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_NMHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_NmhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_HMHD:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_HmhdAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_FRMA:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_FrmaAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_SCHM:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_SchmAtom::Create(size_32, &m_ContextStack, stream);
+ break;
+
+ case AP4_ATOM_TYPE_FTYP:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_FtypAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_TIMS:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TimsAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_SDP_:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_SdpAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_IKMS:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_IkmsAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_ISFM:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_IsfmAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_ISLT:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_IsltAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_ODHE:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_OdheAtom::Create(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_OHDR:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_OhdrAtom::Create(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_ODDA:
+ atom = AP4_OddaAtom::Create(size_64, stream);
+ break;
+
+ case AP4_ATOM_TYPE_ODAF:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_OdafAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_GRPI:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_GrpiAtom::Create(size_32, stream);
+ break;
+
+ case AP4_ATOM_TYPE_IPRO:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_IproAtom::Create(size_32, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_RTP_:
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_RtpAtom::Create(size_32, stream);
+ break;
+
+ // track ref types
+ case AP4_ATOM_TYPE_HINT:
+ case AP4_ATOM_TYPE_CDSC:
+ case AP4_ATOM_TYPE_SYNC:
+ case AP4_ATOM_TYPE_MPOD:
+ case AP4_ATOM_TYPE_DPND:
+ case AP4_ATOM_TYPE_IPIR:
+ case AP4_ATOM_TYPE_ALIS:
+ case AP4_ATOM_TYPE_CHAP:
+ if (GetContext() == AP4_ATOM_TYPE_TREF) {
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_TrefTypeAtom::Create(type, size_32, stream);
+ }
+ break;
+
+ #endif // AP4_CONFIG_MINI_BUILD
+
+ // container atoms
+ case AP4_ATOM_TYPE_MOOF:
+ case AP4_ATOM_TYPE_MVEX:
+ case AP4_ATOM_TYPE_TRAF:
+ case AP4_ATOM_TYPE_TREF:
+ case AP4_ATOM_TYPE_MFRA:
+ case AP4_ATOM_TYPE_HNTI:
+ case AP4_ATOM_TYPE_STBL:
+ case AP4_ATOM_TYPE_MDIA:
+ case AP4_ATOM_TYPE_DINF:
+ case AP4_ATOM_TYPE_MINF:
+ case AP4_ATOM_TYPE_SCHI:
+ case AP4_ATOM_TYPE_SINF:
+ case AP4_ATOM_TYPE_UDTA:
+ case AP4_ATOM_TYPE_ILST:
+ case AP4_ATOM_TYPE_EDTS:
+ case AP4_ATOM_TYPE_MDRI:
+ case AP4_ATOM_TYPE_WAVE:
+
+ // ==> Start patch MPC
+ case AP4_ATOM_TYPE_ART:
+ case AP4_ATOM_TYPE_WRT:
+ case AP4_ATOM_TYPE_ALB:
+ case AP4_ATOM_TYPE_DAY:
+ case AP4_ATOM_TYPE_TOO:
+ case AP4_ATOM_TYPE_CMT:
+ case AP4_ATOM_TYPE_GEN:
+ case AP4_ATOM_TYPE_CMOV:
+ // <== End patch MPC
+
+ if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
+ atom = AP4_ContainerAtom::Create(type, size_64, false, force_64, stream, *this);
+ break;
+
+ // full container atoms
+ case AP4_ATOM_TYPE_META:
+ case AP4_ATOM_TYPE_ODRM:
+ case AP4_ATOM_TYPE_ODKM:
+ atom = AP4_ContainerAtom::Create(type, size_64, true, force_64, stream, *this);
+ break;
+
+ case AP4_ATOM_TYPE_FREE:
+ case AP4_ATOM_TYPE_WIDE:
+ case AP4_ATOM_TYPE_MDAT:
+ // generic atoms
+ break;
+
+ // ==> Start patch MPC
+ case AP4_ATOM_TYPE_DCOM:
+ atom = AP4_DcomAtom::Create(size_64, stream);
+ break;
+ case AP4_ATOM_TYPE_CMVD:
+ atom = AP4_CmvdAtom::Create(size_64, stream, *this);
+ break;
+ // <== End patch MPC
+
+ default: {
+ // try all the external type handlers
+ AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
+ while (handler_item) {
+ TypeHandler* handler = handler_item->GetData();
+ if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
+ break;
+ }
+ handler_item = handler_item->GetNext();
+ }
+
+ break;
+ }
+ }
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::CreateAtomsFromStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomFactory::CreateAtomsFromStream(AP4_ByteStream& stream,
+ AP4_AtomParent& atoms)
+{
+ AP4_LargeSize stream_size = 0;
+ AP4_Position stream_position = 0;
+ AP4_LargeSize bytes_available = (AP4_LargeSize)(-1);
+ if (AP4_SUCCEEDED(stream.GetSize(stream_size)) &&
+ stream_size != 0 &&
+ AP4_SUCCEEDED(stream.Tell(stream_position)) &&
+ stream_position <= stream_size) {
+ bytes_available = stream_size-stream_position;
+ }
+ return CreateAtomsFromStream(stream, bytes_available, atoms);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::CreateAtomsFromStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomFactory::CreateAtomsFromStream(AP4_ByteStream& stream,
+ AP4_LargeSize bytes_available,
+ AP4_AtomParent& atoms)
+{
+ AP4_Result result;
+ do {
+ AP4_Atom* atom = NULL;
+ result = CreateAtomFromStream(stream, bytes_available, atom);
+ if (AP4_SUCCEEDED(result) && atom != NULL) {
+ atoms.AddChild(atom);
+ }
+ } while (AP4_SUCCEEDED(result));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::PushContext
++---------------------------------------------------------------------*/
+void
+AP4_AtomFactory::PushContext(AP4_Atom::Type context)
+{
+ m_ContextStack.Append(context);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::PopContext
++---------------------------------------------------------------------*/
+void
+AP4_AtomFactory::PopContext()
+{
+ m_ContextStack.RemoveLast();
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomFactory::GetContext
++---------------------------------------------------------------------*/
+AP4_Atom::Type
+AP4_AtomFactory::GetContext(AP4_Ordinal depth)
+{
+ AP4_Ordinal available = m_ContextStack.ItemCount();
+ if (depth >= available) return 0;
+ return m_ContextStack[available-depth-1];
+}
+
+/*----------------------------------------------------------------------
+| AP4_DefaultAtomFactory::Instance
++---------------------------------------------------------------------*/
+AP4_DefaultAtomFactory AP4_DefaultAtomFactory::Instance;
+
+/*----------------------------------------------------------------------
+| AP4_DefaultAtomFactory::Instance
++---------------------------------------------------------------------*/
+AP4_DefaultAtomFactory::AP4_DefaultAtomFactory()
+{
+ // register built-in type handlers
+ AddTypeHandler(new AP4_MetaDataAtomTypeHandler(this));
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.h
index 3c7486a7c..1e55c5bc7 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomFactory.h
@@ -61,14 +61,19 @@ class AP4_AtomFactory {
AP4_AtomFactory() {}
// destructor
- ~AP4_AtomFactory();
+ virtual ~AP4_AtomFactory();
// methods
AP4_Result AddTypeHandler(TypeHandler* handler);
AP4_Result RemoveTypeHandler(TypeHandler* handler);
- AP4_Result CreateAtomFromStream(AP4_ByteStream& stream,
- AP4_LargeSize& bytes_available,
- AP4_Atom*& atom);
+ AP4_Result CreateAtomFromStream(AP4_ByteStream& stream,
+ AP4_LargeSize& bytes_available,
+ AP4_Atom*& atom);
+ virtual AP4_Result CreateAtomFromStream(AP4_ByteStream& stream,
+ AP4_UI32 type,
+ AP4_UI32 size_32,
+ AP4_UI64 size_64,
+ AP4_Atom*& atom);
AP4_Result CreateAtomFromStream(AP4_ByteStream& stream,
AP4_Atom*& atom);
AP4_Result CreateAtomsFromStream(AP4_ByteStream& stream,
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.cpp
index 732ca2ef2..b4570be17 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.cpp
@@ -1,373 +1,379 @@
-/*****************************************************************
-|
-| AP4 - Atom Based Sample Tables
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This atom is part of AP4 (MP4 Audio Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the atom COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4AtomSampleTable.h"
-#include "Ap4ByteStream.h"
-#include "Ap4StsdAtom.h"
-#include "Ap4StscAtom.h"
-#include "Ap4StcoAtom.h"
-#include "Ap4Co64Atom.h"
-#include "Ap4StszAtom.h"
-#include "Ap4SttsAtom.h"
-#include "Ap4CttsAtom.h"
-#include "Ap4StssAtom.h"
-#include "Ap4Sample.h"
-#include "Ap4Atom.h"
-
-// ==> Start patch MPC
-#include "Ap4SampleEntry.h"
-// <== End patch MPC
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::AP4_AtomSampleTable
-+---------------------------------------------------------------------*/
-AP4_AtomSampleTable::AP4_AtomSampleTable(AP4_ContainerAtom* stbl,
- AP4_ByteStream& sample_stream) :
- m_SampleStream(sample_stream)
-{
- m_StscAtom = AP4_DYNAMIC_CAST(AP4_StscAtom, stbl->GetChild(AP4_ATOM_TYPE_STSC));
- m_StcoAtom = AP4_DYNAMIC_CAST(AP4_StcoAtom, stbl->GetChild(AP4_ATOM_TYPE_STCO));
- m_StszAtom = AP4_DYNAMIC_CAST(AP4_StszAtom, stbl->GetChild(AP4_ATOM_TYPE_STSZ));
- m_CttsAtom = AP4_DYNAMIC_CAST(AP4_CttsAtom, stbl->GetChild(AP4_ATOM_TYPE_CTTS));
- m_SttsAtom = AP4_DYNAMIC_CAST(AP4_SttsAtom, stbl->GetChild(AP4_ATOM_TYPE_STTS));
- m_StssAtom = AP4_DYNAMIC_CAST(AP4_StssAtom, stbl->GetChild(AP4_ATOM_TYPE_STSS));
- m_StsdAtom = AP4_DYNAMIC_CAST(AP4_StsdAtom, stbl->GetChild(AP4_ATOM_TYPE_STSD));
- m_Co64Atom = AP4_DYNAMIC_CAST(AP4_Co64Atom, stbl->GetChild(AP4_ATOM_TYPE_CO64));
-
- // keep a reference to the sample stream
- m_SampleStream.AddReference();
-
- // ==> Start patch MPC
- if(m_StsdAtom && m_StszAtom && m_StscAtom && m_SttsAtom
- && m_StszAtom->m_SampleSize == 1)
- {
- // fix mov files
- for(AP4_List<AP4_Atom>::Item* item = m_StsdAtom->GetChildren().FirstItem();
- item;
- item = item->GetNext())
- {
- AP4_Atom* atom = item->GetData();
-
- if(AP4_AudioSampleEntry* ase = dynamic_cast<AP4_AudioSampleEntry*>(atom))
- {
- AP4_UI32 SamplesPerPacket = ase->GetSamplesPerPacket();
- AP4_UI32 BytesPerFrame = ase->GetBytesPerFrame();
-
- if(SamplesPerPacket > 0 && BytesPerFrame > 0)
- {
- for(int i = 0, j = m_StscAtom->m_Entries.ItemCount(); i < j; i++)
- {
- AP4_StscTableEntry& e = m_StscAtom->m_Entries[i];
- AP4_ASSERT(e.m_SamplesPerChunk % SamplesPerPacket == 0);
- e.m_SamplesPerChunk = e.m_SamplesPerChunk / SamplesPerPacket;
- e.m_FirstSample = (e.m_FirstSample-1) / SamplesPerPacket + 1;
- }
-
- AP4_ASSERT(m_StszAtom->m_SampleCount % SamplesPerPacket == 0);
- m_StszAtom->m_SampleCount = m_StszAtom->m_SampleCount / SamplesPerPacket;
- m_StszAtom->m_SampleSize = BytesPerFrame;
-
- AP4_ASSERT(m_SttsAtom->m_Entries.ItemCount() == 1);
- m_SttsAtom->m_Entries[0].m_SampleCount = m_StszAtom->m_SampleCount;
- m_SttsAtom->m_Entries[0].m_SampleDuration = SamplesPerPacket;
- }
- }
- }
- }
- // <== End patch MPC
-
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::~AP4_AtomSampleTable
-+---------------------------------------------------------------------*/
-AP4_AtomSampleTable::~AP4_AtomSampleTable()
-{
- m_SampleStream.Release();
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomSampleTable::GetSample(AP4_Ordinal index,
- AP4_Sample& sample)
-{
- AP4_Result result;
-
- // check that we have a chunk offset table
- if (m_StcoAtom == NULL && m_Co64Atom == NULL) {
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // MP4 uses 1-based indexes internally, so adjust by one
- index++;
-
- // find out in which chunk this sample is located
- AP4_Ordinal chunk, skip, desc;
- result = m_StscAtom->GetChunkForSample(index, chunk, skip, desc);
- if (AP4_FAILED(result)) return result;
-
- // check that the result is within bounds
- if (skip > index) return AP4_ERROR_INTERNAL;
-
- // get the atom offset for this chunk
- AP4_UI64 offset;
- if (m_StcoAtom) {
- AP4_UI32 offset_32;
- result = m_StcoAtom->GetChunkOffset(chunk, offset_32);
- offset = offset_32;
- } else {
- result = m_Co64Atom->GetChunkOffset(chunk, offset);
- }
- if (AP4_FAILED(result)) return result;
-
- // compute the additional offset inside the chunk
- for (unsigned int i = index-skip; i < index; i++) {
- AP4_Size size;
- result = m_StszAtom->GetSampleSize(i, size);
- if (AP4_FAILED(result)) return result;
- offset += size;
- }
-
- // set the description index
- sample.SetDescriptionIndex(desc-1); // adjust for 0-based indexes
-
- // set the dts and cts
- AP4_UI32 cts_offset = 0;
- AP4_UI64 dts = 0;
- AP4_UI32 duration = 0;
- result = m_SttsAtom->GetDts(index, dts, &duration);
- if (AP4_FAILED(result)) return result;
- sample.SetDuration(duration);
- sample.SetDts(dts);
- if (m_CttsAtom == NULL) {
- sample.SetCts(dts);
- } else {
- result = m_CttsAtom->GetCtsOffset(index, cts_offset);
- if (AP4_FAILED(result)) return result;
- sample.SetCtsDelta(cts_offset);
- }
-
- // set the size
- AP4_Size sample_size;
- result = m_StszAtom->GetSampleSize(index, sample_size);
- if (AP4_FAILED(result)) return result;
- sample.SetSize(sample_size);
-
- // set the sync flag
- if (m_StssAtom == NULL) {
- sample.SetSync(true);
- } else {
- sample.SetSync(m_StssAtom->IsSampleSync(index));
- }
-
- // set the offset
- sample.SetOffset(offset);
-
- // set the data stream
- sample.SetDataStream(m_SampleStream);
-
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetSampleCount
-+---------------------------------------------------------------------*/
-AP4_Cardinal
-AP4_AtomSampleTable::GetSampleCount()
-{
- return m_StszAtom ? m_StszAtom->GetSampleCount() : 0;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetSampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_AtomSampleTable::GetSampleDescription(AP4_Ordinal index)
-{
- return m_StsdAtom ? m_StsdAtom->GetSampleDescription(index) : NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetSampleDescriptionCount
-+---------------------------------------------------------------------*/
-AP4_Cardinal
-AP4_AtomSampleTable::GetSampleDescriptionCount()
-{
- return m_StsdAtom ? m_StsdAtom->GetSampleDescriptionCount() : 0;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetSampleChunkPosition
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomSampleTable::GetSampleChunkPosition(AP4_Ordinal sample_index,
- AP4_Ordinal& chunk_index,
- AP4_Ordinal& position_in_chunk)
-{
- // default values
- chunk_index = 0;
- position_in_chunk = 0;
-
- AP4_Ordinal sample_description_index;
- return GetChunkForSample(sample_index,
- chunk_index,
- position_in_chunk,
- sample_description_index);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetChunkForSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomSampleTable::GetChunkForSample(AP4_Ordinal sample_index,
- AP4_Ordinal& chunk_index,
- AP4_Ordinal& position_in_chunk,
- AP4_Ordinal& sample_description_index)
-{
- // default values
- chunk_index = 0;
- position_in_chunk = 0;
- sample_description_index = 0;
-
- // check that we an stsc atom
- if (m_StscAtom == NULL) return AP4_ERROR_INVALID_STATE;
-
- // get the chunk info from the stsc atom
- AP4_Ordinal chunk = 0;
- AP4_Result result = m_StscAtom->GetChunkForSample(sample_index+1, // the atom API is 1-based
- chunk,
- position_in_chunk,
- sample_description_index);
- if (AP4_FAILED(result)) return result;
- if (chunk == 0) return AP4_ERROR_INTERNAL;
-
- // the atom sample and chunk indexes are 1-based, so we need to translate
- chunk_index = chunk-1;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetChunkOffset
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomSampleTable::GetChunkOffset(AP4_Ordinal chunk_index,
- AP4_Position& offset)
-{
- if (m_StcoAtom) {
- AP4_UI32 offset_32;
- AP4_Result result = m_StcoAtom->GetChunkOffset(chunk_index+1, offset_32);
- if (AP4_SUCCEEDED(result)) {
- offset = offset_32;
- } else {
- offset = 0;
- }
- return result;
- } else if (m_Co64Atom) {
- return m_Co64Atom->GetChunkOffset(chunk_index+1, offset);
- } else {
- offset = 0;
- return AP4_FAILURE;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::SetChunkOffset
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomSampleTable::SetChunkOffset(AP4_Ordinal chunk_index,
- AP4_Position offset)
-{
- if (m_StcoAtom) {
- if ((offset >> 32) != 0) return AP4_ERROR_OUT_OF_RANGE;
- return m_StcoAtom->SetChunkOffset(chunk_index+1, (AP4_UI32)offset);
- } else if (m_Co64Atom) {
- return m_Co64Atom->SetChunkOffset(chunk_index+1, offset);
- } else {
- return AP4_FAILURE;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::SetSampleSize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomSampleTable::SetSampleSize(AP4_Ordinal sample_index, AP4_Size size)
-{
- return m_StszAtom ? m_StszAtom->SetSampleSize(sample_index+1, size) : AP4_FAILURE;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetSampleIndexForTimeStamp
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomSampleTable::GetSampleIndexForTimeStamp(AP4_UI64 ts,
- AP4_Ordinal& sample_index)
-{
- return m_SttsAtom ? m_SttsAtom->GetSampleIndexForTimeStamp(ts, sample_index)
- : AP4_FAILURE;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable::GetNearestSyncSampleIndex
-+---------------------------------------------------------------------*/
-AP4_Ordinal
-AP4_AtomSampleTable::GetNearestSyncSampleIndex(AP4_Ordinal sample_index, bool before)
-{
- // if we don't have an stss table, all samples match
- if (m_StssAtom == NULL) return sample_index;
-
- sample_index += 1; // the table is 1-based
- AP4_Cardinal entry_count = m_StssAtom->GetEntries().ItemCount();
- if (before) {
- AP4_Ordinal cursor = 0;
- for (unsigned int i=0; i<entry_count; i++) {
- if (m_StssAtom->GetEntries()[i] >= sample_index) return cursor;
- if (m_StssAtom->GetEntries()[i]) cursor = m_StssAtom->GetEntries()[i]-1;
- }
-
- // not found?
- return cursor;
- } else {
- for (unsigned int i=0; i<entry_count; i++) {
- if (m_StssAtom->GetEntries()[i] >= sample_index) {
- return m_StssAtom->GetEntries()[i]?m_StssAtom->GetEntries()[i]-1:sample_index-1;
- }
- }
-
- // not found?
- return GetSampleCount();
- }
-}
-
+/*****************************************************************
+|
+| AP4 - Atom Based Sample Tables
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This atom is part of AP4 (MP4 Audio Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the atom COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4AtomSampleTable.h"
+#include "Ap4ByteStream.h"
+#include "Ap4StsdAtom.h"
+#include "Ap4StscAtom.h"
+#include "Ap4StcoAtom.h"
+#include "Ap4Co64Atom.h"
+#include "Ap4StszAtom.h"
+#include "Ap4SttsAtom.h"
+#include "Ap4CttsAtom.h"
+#include "Ap4StssAtom.h"
+#include "Ap4Sample.h"
+#include "Ap4Atom.h"
+
+// ==> Start patch MPC
+#include "Ap4SampleEntry.h"
+// <== End patch MPC
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_AtomSampleTable)
+
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::AP4_AtomSampleTable
++---------------------------------------------------------------------*/
+AP4_AtomSampleTable::AP4_AtomSampleTable(AP4_ContainerAtom* stbl,
+ AP4_ByteStream& sample_stream) :
+ m_SampleStream(sample_stream)
+{
+ m_StscAtom = AP4_DYNAMIC_CAST(AP4_StscAtom, stbl->GetChild(AP4_ATOM_TYPE_STSC));
+ m_StcoAtom = AP4_DYNAMIC_CAST(AP4_StcoAtom, stbl->GetChild(AP4_ATOM_TYPE_STCO));
+ m_StszAtom = AP4_DYNAMIC_CAST(AP4_StszAtom, stbl->GetChild(AP4_ATOM_TYPE_STSZ));
+ m_CttsAtom = AP4_DYNAMIC_CAST(AP4_CttsAtom, stbl->GetChild(AP4_ATOM_TYPE_CTTS));
+ m_SttsAtom = AP4_DYNAMIC_CAST(AP4_SttsAtom, stbl->GetChild(AP4_ATOM_TYPE_STTS));
+ m_StssAtom = AP4_DYNAMIC_CAST(AP4_StssAtom, stbl->GetChild(AP4_ATOM_TYPE_STSS));
+ m_StsdAtom = AP4_DYNAMIC_CAST(AP4_StsdAtom, stbl->GetChild(AP4_ATOM_TYPE_STSD));
+ m_Co64Atom = AP4_DYNAMIC_CAST(AP4_Co64Atom, stbl->GetChild(AP4_ATOM_TYPE_CO64));
+
+ // keep a reference to the sample stream
+ m_SampleStream.AddReference();
+
+ // ==> Start patch MPC
+ if(m_StsdAtom && m_StszAtom && m_StscAtom && m_SttsAtom
+ && m_StszAtom->m_SampleSize == 1)
+ {
+ // fix mov files
+ for(AP4_List<AP4_Atom>::Item* item = m_StsdAtom->GetChildren().FirstItem();
+ item;
+ item = item->GetNext())
+ {
+ AP4_Atom* atom = item->GetData();
+
+ if(AP4_AudioSampleEntry* ase = dynamic_cast<AP4_AudioSampleEntry*>(atom))
+ {
+ AP4_UI32 SamplesPerPacket = ase->GetSamplesPerPacket();
+ AP4_UI32 BytesPerFrame = ase->GetBytesPerFrame();
+
+ if(SamplesPerPacket > 0 && BytesPerFrame > 0)
+ {
+ for(int i = 0, j = m_StscAtom->m_Entries.ItemCount(); i < j; i++)
+ {
+ AP4_StscTableEntry& e = m_StscAtom->m_Entries[i];
+ AP4_ASSERT(e.m_SamplesPerChunk % SamplesPerPacket == 0);
+ e.m_SamplesPerChunk = e.m_SamplesPerChunk / SamplesPerPacket;
+ e.m_FirstSample = (e.m_FirstSample-1) / SamplesPerPacket + 1;
+ }
+
+ AP4_ASSERT(m_StszAtom->m_SampleCount % SamplesPerPacket == 0);
+ m_StszAtom->m_SampleCount = m_StszAtom->m_SampleCount / SamplesPerPacket;
+ m_StszAtom->m_SampleSize = BytesPerFrame;
+
+ AP4_ASSERT(m_SttsAtom->m_Entries.ItemCount() == 1);
+ m_SttsAtom->m_Entries[0].m_SampleCount = m_StszAtom->m_SampleCount;
+ m_SttsAtom->m_Entries[0].m_SampleDuration = SamplesPerPacket;
+ }
+ }
+ }
+ }
+ // <== End patch MPC
+
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::~AP4_AtomSampleTable
++---------------------------------------------------------------------*/
+AP4_AtomSampleTable::~AP4_AtomSampleTable()
+{
+ m_SampleStream.Release();
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomSampleTable::GetSample(AP4_Ordinal index,
+ AP4_Sample& sample)
+{
+ AP4_Result result;
+
+ // check that we have a chunk offset table
+ if (m_StcoAtom == NULL && m_Co64Atom == NULL) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // MP4 uses 1-based indexes internally, so adjust by one
+ index++;
+
+ // find out in which chunk this sample is located
+ AP4_Ordinal chunk, skip, desc;
+ result = m_StscAtom->GetChunkForSample(index, chunk, skip, desc);
+ if (AP4_FAILED(result)) return result;
+
+ // check that the result is within bounds
+ if (skip > index) return AP4_ERROR_INTERNAL;
+
+ // get the atom offset for this chunk
+ AP4_UI64 offset;
+ if (m_StcoAtom) {
+ AP4_UI32 offset_32;
+ result = m_StcoAtom->GetChunkOffset(chunk, offset_32);
+ offset = offset_32;
+ } else {
+ result = m_Co64Atom->GetChunkOffset(chunk, offset);
+ }
+ if (AP4_FAILED(result)) return result;
+
+ // compute the additional offset inside the chunk
+ for (unsigned int i = index-skip; i < index; i++) {
+ AP4_Size size;
+ result = m_StszAtom->GetSampleSize(i, size);
+ if (AP4_FAILED(result)) return result;
+ offset += size;
+ }
+
+ // set the description index
+ sample.SetDescriptionIndex(desc-1); // adjust for 0-based indexes
+
+ // set the dts and cts
+ AP4_UI32 cts_offset = 0;
+ AP4_UI64 dts = 0;
+ AP4_UI32 duration = 0;
+ result = m_SttsAtom->GetDts(index, dts, &duration);
+ if (AP4_FAILED(result)) return result;
+ sample.SetDuration(duration);
+ sample.SetDts(dts);
+ if (m_CttsAtom == NULL) {
+ sample.SetCts(dts);
+ } else {
+ result = m_CttsAtom->GetCtsOffset(index, cts_offset);
+ if (AP4_FAILED(result)) return result;
+ sample.SetCtsDelta(cts_offset);
+ }
+
+ // set the size
+ AP4_Size sample_size;
+ result = m_StszAtom->GetSampleSize(index, sample_size);
+ if (AP4_FAILED(result)) return result;
+ sample.SetSize(sample_size);
+
+ // set the sync flag
+ if (m_StssAtom == NULL) {
+ sample.SetSync(true);
+ } else {
+ sample.SetSync(m_StssAtom->IsSampleSync(index));
+ }
+
+ // set the offset
+ sample.SetOffset(offset);
+
+ // set the data stream
+ sample.SetDataStream(m_SampleStream);
+
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetSampleCount
++---------------------------------------------------------------------*/
+AP4_Cardinal
+AP4_AtomSampleTable::GetSampleCount()
+{
+ return m_StszAtom ? m_StszAtom->GetSampleCount() : 0;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetSampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_AtomSampleTable::GetSampleDescription(AP4_Ordinal index)
+{
+ return m_StsdAtom ? m_StsdAtom->GetSampleDescription(index) : NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetSampleDescriptionCount
++---------------------------------------------------------------------*/
+AP4_Cardinal
+AP4_AtomSampleTable::GetSampleDescriptionCount()
+{
+ return m_StsdAtom ? m_StsdAtom->GetSampleDescriptionCount() : 0;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetSampleChunkPosition
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomSampleTable::GetSampleChunkPosition(AP4_Ordinal sample_index,
+ AP4_Ordinal& chunk_index,
+ AP4_Ordinal& position_in_chunk)
+{
+ // default values
+ chunk_index = 0;
+ position_in_chunk = 0;
+
+ AP4_Ordinal sample_description_index;
+ return GetChunkForSample(sample_index,
+ chunk_index,
+ position_in_chunk,
+ sample_description_index);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetChunkForSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomSampleTable::GetChunkForSample(AP4_Ordinal sample_index,
+ AP4_Ordinal& chunk_index,
+ AP4_Ordinal& position_in_chunk,
+ AP4_Ordinal& sample_description_index)
+{
+ // default values
+ chunk_index = 0;
+ position_in_chunk = 0;
+ sample_description_index = 0;
+
+ // check that we an stsc atom
+ if (m_StscAtom == NULL) return AP4_ERROR_INVALID_STATE;
+
+ // get the chunk info from the stsc atom
+ AP4_Ordinal chunk = 0;
+ AP4_Result result = m_StscAtom->GetChunkForSample(sample_index+1, // the atom API is 1-based
+ chunk,
+ position_in_chunk,
+ sample_description_index);
+ if (AP4_FAILED(result)) return result;
+ if (chunk == 0) return AP4_ERROR_INTERNAL;
+
+ // the atom sample and chunk indexes are 1-based, so we need to translate
+ chunk_index = chunk-1;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetChunkOffset
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomSampleTable::GetChunkOffset(AP4_Ordinal chunk_index,
+ AP4_Position& offset)
+{
+ if (m_StcoAtom) {
+ AP4_UI32 offset_32;
+ AP4_Result result = m_StcoAtom->GetChunkOffset(chunk_index+1, offset_32);
+ if (AP4_SUCCEEDED(result)) {
+ offset = offset_32;
+ } else {
+ offset = 0;
+ }
+ return result;
+ } else if (m_Co64Atom) {
+ return m_Co64Atom->GetChunkOffset(chunk_index+1, offset);
+ } else {
+ offset = 0;
+ return AP4_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::SetChunkOffset
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomSampleTable::SetChunkOffset(AP4_Ordinal chunk_index,
+ AP4_Position offset)
+{
+ if (m_StcoAtom) {
+ if ((offset >> 32) != 0) return AP4_ERROR_OUT_OF_RANGE;
+ return m_StcoAtom->SetChunkOffset(chunk_index+1, (AP4_UI32)offset);
+ } else if (m_Co64Atom) {
+ return m_Co64Atom->SetChunkOffset(chunk_index+1, offset);
+ } else {
+ return AP4_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::SetSampleSize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomSampleTable::SetSampleSize(AP4_Ordinal sample_index, AP4_Size size)
+{
+ return m_StszAtom ? m_StszAtom->SetSampleSize(sample_index+1, size) : AP4_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetSampleIndexForTimeStamp
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomSampleTable::GetSampleIndexForTimeStamp(AP4_UI64 ts,
+ AP4_Ordinal& sample_index)
+{
+ return m_SttsAtom ? m_SttsAtom->GetSampleIndexForTimeStamp(ts, sample_index)
+ : AP4_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable::GetNearestSyncSampleIndex
++---------------------------------------------------------------------*/
+AP4_Ordinal
+AP4_AtomSampleTable::GetNearestSyncSampleIndex(AP4_Ordinal sample_index, bool before)
+{
+ // if we don't have an stss table, all samples match
+ if (m_StssAtom == NULL) return sample_index;
+
+ sample_index += 1; // the table is 1-based
+ AP4_Cardinal entry_count = m_StssAtom->GetEntries().ItemCount();
+ if (before) {
+ AP4_Ordinal cursor = 0;
+ for (unsigned int i=0; i<entry_count; i++) {
+ if (m_StssAtom->GetEntries()[i] >= sample_index) return cursor;
+ if (m_StssAtom->GetEntries()[i]) cursor = m_StssAtom->GetEntries()[i]-1;
+ }
+
+ // not found?
+ return cursor;
+ } else {
+ for (unsigned int i=0; i<entry_count; i++) {
+ if (m_StssAtom->GetEntries()[i] >= sample_index) {
+ return m_StssAtom->GetEntries()[i]?m_StssAtom->GetEntries()[i]-1:sample_index-1;
+ }
+ }
+
+ // not found?
+ return GetSampleCount();
+ }
+}
+
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.h
index aaecbf917..1eb348e00 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AtomSampleTable.h
@@ -1,96 +1,98 @@
-/*****************************************************************
-|
-| AP4 - Atom Based Sample Table
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This atom is part of AP4 (MP4 Audio Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the atom COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_ATOM_SAMPLE_TABLE_H_
-#define _AP4_ATOM_SAMPLE_TABLE_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4SampleTable.h"
-
-/*----------------------------------------------------------------------
-| forward declarations
-+---------------------------------------------------------------------*/
-class AP4_Atom;
-class AP4_ByteStream;
-class AP4_StscAtom;
-class AP4_StcoAtom;
-class AP4_StszAtom;
-class AP4_SttsAtom;
-class AP4_CttsAtom;
-class AP4_StssAtom;
-class AP4_StsdAtom;
-class AP4_Co64Atom;
-
-/*----------------------------------------------------------------------
-| AP4_AtomSampleTable
-+---------------------------------------------------------------------*/
-class AP4_AtomSampleTable : public AP4_SampleTable
-{
- public:
- // methods
- AP4_AtomSampleTable(AP4_ContainerAtom* stbl_atom,
- AP4_ByteStream& sample_stream);
- virtual ~AP4_AtomSampleTable();
-
- // AP4_SampleTable methods
- virtual AP4_Result GetSample(AP4_Ordinal sample_index, AP4_Sample& sample);
- virtual AP4_Cardinal GetSampleCount();
- virtual AP4_SampleDescription* GetSampleDescription(AP4_Ordinal sd_index);
- virtual AP4_Cardinal GetSampleDescriptionCount();
- virtual AP4_Result GetSampleChunkPosition(AP4_Ordinal sample_index,
- AP4_Ordinal& chunk_index,
- AP4_Ordinal& position_in_chunk);
- virtual AP4_Result GetSampleIndexForTimeStamp(AP4_UI64 ts, AP4_Ordinal& sample_index);
- virtual AP4_Ordinal GetNearestSyncSampleIndex(AP4_Ordinal index, bool before=true);
-
- // local methods
- virtual AP4_Result GetChunkForSample(AP4_Ordinal sample_index,
- AP4_Ordinal& chunk_index,
- AP4_Ordinal& position_in_chunk,
- AP4_Ordinal& sample_description_index);
- virtual AP4_Result GetChunkOffset(AP4_Ordinal chunk_index, AP4_Position& offset);
- virtual AP4_Result SetChunkOffset(AP4_Ordinal chunk_index, AP4_Position offset);
- virtual AP4_Result SetSampleSize(AP4_Ordinal sample_index, AP4_Size size);
-
-private:
- // members
- AP4_ByteStream& m_SampleStream;
- AP4_StscAtom* m_StscAtom;
- AP4_StcoAtom* m_StcoAtom;
- AP4_StszAtom* m_StszAtom;
- AP4_SttsAtom* m_SttsAtom;
- AP4_CttsAtom* m_CttsAtom;
- AP4_StsdAtom* m_StsdAtom;
- AP4_StssAtom* m_StssAtom;
- AP4_Co64Atom* m_Co64Atom;
-};
-
-#endif // _AP4_ATOM_SAMPLE_TABLE_H_
+/*****************************************************************
+|
+| AP4 - Atom Based Sample Table
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This atom is part of AP4 (MP4 Audio Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the atom COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_ATOM_SAMPLE_TABLE_H_
+#define _AP4_ATOM_SAMPLE_TABLE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4SampleTable.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class AP4_Atom;
+class AP4_ByteStream;
+class AP4_StscAtom;
+class AP4_StcoAtom;
+class AP4_StszAtom;
+class AP4_SttsAtom;
+class AP4_CttsAtom;
+class AP4_StssAtom;
+class AP4_StsdAtom;
+class AP4_Co64Atom;
+
+/*----------------------------------------------------------------------
+| AP4_AtomSampleTable
++---------------------------------------------------------------------*/
+class AP4_AtomSampleTable : public AP4_SampleTable
+{
+ public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_AtomSampleTable, AP4_SampleTable)
+
+ // methods
+ AP4_AtomSampleTable(AP4_ContainerAtom* stbl_atom,
+ AP4_ByteStream& sample_stream);
+ virtual ~AP4_AtomSampleTable();
+
+ // AP4_SampleTable methods
+ virtual AP4_Result GetSample(AP4_Ordinal sample_index, AP4_Sample& sample);
+ virtual AP4_Cardinal GetSampleCount();
+ virtual AP4_SampleDescription* GetSampleDescription(AP4_Ordinal sd_index);
+ virtual AP4_Cardinal GetSampleDescriptionCount();
+ virtual AP4_Result GetSampleChunkPosition(AP4_Ordinal sample_index,
+ AP4_Ordinal& chunk_index,
+ AP4_Ordinal& position_in_chunk);
+ virtual AP4_Result GetSampleIndexForTimeStamp(AP4_UI64 ts, AP4_Ordinal& sample_index);
+ virtual AP4_Ordinal GetNearestSyncSampleIndex(AP4_Ordinal index, bool before=true);
+
+ // local methods
+ virtual AP4_Result GetChunkForSample(AP4_Ordinal sample_index,
+ AP4_Ordinal& chunk_index,
+ AP4_Ordinal& position_in_chunk,
+ AP4_Ordinal& sample_description_index);
+ virtual AP4_Result GetChunkOffset(AP4_Ordinal chunk_index, AP4_Position& offset);
+ virtual AP4_Result SetChunkOffset(AP4_Ordinal chunk_index, AP4_Position offset);
+ virtual AP4_Result SetSampleSize(AP4_Ordinal sample_index, AP4_Size size);
+
+private:
+ // members
+ AP4_ByteStream& m_SampleStream;
+ AP4_StscAtom* m_StscAtom;
+ AP4_StcoAtom* m_StcoAtom;
+ AP4_StszAtom* m_StszAtom;
+ AP4_SttsAtom* m_SttsAtom;
+ AP4_CttsAtom* m_CttsAtom;
+ AP4_StsdAtom* m_StsdAtom;
+ AP4_StssAtom* m_StssAtom;
+ AP4_Co64Atom* m_Co64Atom;
+};
+
+#endif // _AP4_ATOM_SAMPLE_TABLE_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.cpp
index ac227203d..5802ae2da 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.cpp
@@ -1,277 +1,277 @@
-/*****************************************************************
-|
-| AP4 - avcC Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4AvccAtom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4Utils.h"
-#include "Ap4Types.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_AvccAtom)
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::GetProfileName
-+---------------------------------------------------------------------*/
-const char*
-AP4_AvccAtom::GetProfileName(AP4_UI08 profile)
-{
- switch (profile) {
- case AP4_AVC_PROFILE_BASELINE: return "Baseline";
- case AP4_AVC_PROFILE_MAIN: return "Main";
- case AP4_AVC_PROFILE_EXTENDED: return "Extended";
- case AP4_AVC_PROFILE_HIGH: return "High";
- case AP4_AVC_PROFILE_HIGH_10: return "High 10";
- case AP4_AVC_PROFILE_HIGH_422: return "High 4:2:2";
- case AP4_AVC_PROFILE_HIGH_444: return "High 4:4:4";
- }
-
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::Create
-+---------------------------------------------------------------------*/
-AP4_AvccAtom*
-AP4_AvccAtom::Create(AP4_Size size, AP4_ByteStream& stream)
-{
- // read the raw bytes in a buffer
- unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
- AP4_DataBuffer payload_data(payload_size);
- AP4_Result result = stream.Read(payload_data.UseData(), payload_size);
- if (AP4_FAILED(result)) return NULL;
-
- // check the version
- const AP4_UI08* payload = payload_data.GetData();
- if (payload[0] != 1) {
- return NULL;
- }
-
- // check the size
- if (payload_size < 6) return NULL;
- unsigned int num_seq_params = payload[5]&31;
- unsigned int cursor = 6;
- for (unsigned int i=0; i<num_seq_params; i++) {
- if (cursor+2 > payload_size) return NULL;
- cursor += 2+AP4_BytesToInt16BE(&payload[cursor]);
- if (cursor > payload_size) return NULL;
- }
- unsigned int num_pic_params = payload[cursor++];
- if (cursor > payload_size) return NULL;
- for (unsigned int i=0; i<num_pic_params; i++) {
- if (cursor+2 > payload_size) return NULL;
- cursor += 2+AP4_BytesToInt16BE(&payload[cursor]);
- if (cursor > payload_size) return NULL;
- }
- return new AP4_AvccAtom(size, payload);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::AP4_AvccAtom
-+---------------------------------------------------------------------*/
-AP4_AvccAtom::AP4_AvccAtom() :
- AP4_Atom(AP4_ATOM_TYPE_AVCC, AP4_ATOM_HEADER_SIZE),
- m_ConfigurationVersion(1),
- m_Profile(0),
- m_Level(0),
- m_ProfileCompatibility(0),
- m_NaluLengthSize(0)
-{
- UpdateRawBytes();
- m_Size32 += m_RawBytes.GetDataSize();
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::AP4_AvccAtom
-+---------------------------------------------------------------------*/
-AP4_AvccAtom::AP4_AvccAtom(const AP4_AvccAtom& other) :
- AP4_Atom(AP4_ATOM_TYPE_AVCC, other.m_Size32),
- m_ConfigurationVersion(other.m_ConfigurationVersion),
- m_Profile(other.m_Profile),
- m_Level(other.m_Level),
- m_ProfileCompatibility(other.m_ProfileCompatibility),
- m_NaluLengthSize(other.m_NaluLengthSize),
- m_RawBytes(other.m_RawBytes)
-{
- // deep copy of the parameters
- unsigned int i = 0;
- for (i=0; i<other.m_SequenceParameters.ItemCount(); i++) {
- m_SequenceParameters.Append(other.m_SequenceParameters[i]);
- }
- for (i=0; i<other.m_PictureParameters.ItemCount(); i++) {
- m_PictureParameters.Append(other.m_PictureParameters[i]);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::AP4_AvccAtom
-+---------------------------------------------------------------------*/
-AP4_AvccAtom::AP4_AvccAtom(AP4_UI32 size, const AP4_UI08* payload) :
- AP4_Atom(AP4_ATOM_TYPE_AVCC, size)
-{
- // make a copy of our configuration bytes
- unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
- m_RawBytes.SetData(payload, payload_size);
-
- // parse the payload
- m_ConfigurationVersion = payload[0];
- m_Profile = payload[1];
- m_ProfileCompatibility = payload[2];
- m_Level = payload[3];
- m_NaluLengthSize = 1+(payload[4]&3);
- AP4_UI08 num_seq_params = payload[5]&31;
- m_SequenceParameters.EnsureCapacity(num_seq_params);
- unsigned int cursor = 6;
- for (unsigned int i=0; i<num_seq_params; i++) {
- m_SequenceParameters.Append(AP4_DataBuffer());
- AP4_UI16 param_length = AP4_BytesToInt16BE(&payload[cursor]);
- m_SequenceParameters[i].SetData(&payload[cursor]+2, param_length);
- cursor += 2+param_length;
- }
- AP4_UI08 num_pic_params = payload[cursor++];
- m_PictureParameters.EnsureCapacity(num_pic_params);
- for (unsigned int i=0; i<num_pic_params; i++) {
- m_PictureParameters.Append(AP4_DataBuffer());
- AP4_UI16 param_length = AP4_BytesToInt16BE(&payload[cursor]);
- m_PictureParameters[i].SetData(&payload[cursor]+2, param_length);
- cursor += 2+param_length;
- }
-}
-
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::AP4_AvccAtom
-+---------------------------------------------------------------------*/
-AP4_AvccAtom::AP4_AvccAtom(AP4_UI08 profile,
- AP4_UI08 level,
- AP4_UI08 profile_compatibility,
- AP4_UI08 length_size,
- const AP4_Array<AP4_DataBuffer>& sequence_parameters,
- const AP4_Array<AP4_DataBuffer>& picture_parameters) :
- AP4_Atom(AP4_ATOM_TYPE_AVCC, AP4_ATOM_HEADER_SIZE),
- m_ConfigurationVersion(1),
- m_Profile(profile),
- m_Level(level),
- m_ProfileCompatibility(profile_compatibility),
- m_NaluLengthSize(length_size)
-{
- // deep copy of the parameters
- unsigned int i = 0;
- for (i=0; i<sequence_parameters.ItemCount(); i++) {
- m_SequenceParameters.Append(sequence_parameters[i]);
- }
- for (i=0; i<picture_parameters.ItemCount(); i++) {
- m_PictureParameters.Append(picture_parameters[i]);
- }
-
- // compute the raw bytes
- UpdateRawBytes();
-
- // update the size
- m_Size32 += m_RawBytes.GetDataSize();
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::UpdateRawBytes
-+---------------------------------------------------------------------*/
-void
-AP4_AvccAtom::UpdateRawBytes()
-{
- // compute the payload size
- unsigned int payload_size = 6;
- for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
- payload_size += 2+m_SequenceParameters[i].GetDataSize();
- }
- ++payload_size;
- for (unsigned int i=0; i<m_PictureParameters.ItemCount(); i++) {
- payload_size += 2+m_PictureParameters[i].GetDataSize();
- }
- m_RawBytes.SetDataSize(payload_size);
- AP4_UI08* payload = m_RawBytes.UseData();
-
- payload[0] = m_ConfigurationVersion;
- payload[1] = m_Profile;
- payload[2] = m_ProfileCompatibility;
- payload[3] = m_Level;
- payload[4] = 0xFC | (m_NaluLengthSize-1);
- payload[5] = 0xE0 | m_SequenceParameters.ItemCount();
- unsigned int cursor = 6;
- for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
- AP4_UI16 param_length = (AP4_UI16)m_SequenceParameters[i].GetDataSize();
- AP4_BytesFromUInt16BE(&payload[cursor], param_length);
- cursor += 2;
- AP4_CopyMemory(&payload[cursor], m_SequenceParameters[i].GetData(), param_length);
- cursor += param_length;
- }
- payload[cursor++] = m_PictureParameters.ItemCount();
- for (unsigned int i=0; i<m_PictureParameters.ItemCount(); i++) {
- AP4_UI16 param_length = (AP4_UI16)m_PictureParameters[i].GetDataSize();
- AP4_BytesFromUInt16BE(&payload[cursor], param_length);
- cursor += 2;
- AP4_CopyMemory(&payload[cursor], m_PictureParameters[i].GetData(), param_length);
- cursor += param_length;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AvccAtom::WriteFields(AP4_ByteStream& stream)
-{
- return stream.Write(m_RawBytes.GetData(), m_RawBytes.GetDataSize());
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AvccAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("Configuration Version", m_ConfigurationVersion);
- const char* profile_name = GetProfileName(m_Profile);
- if (profile_name) {
- inspector.AddField("Profile", profile_name);
- } else {
- inspector.AddField("Profile", m_Profile);
- }
- inspector.AddField("Profile Compatibility", m_ProfileCompatibility, AP4_AtomInspector::HINT_HEX);
- inspector.AddField("Level", m_Level);
- inspector.AddField("NALU Length Size", m_NaluLengthSize);
- for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
- inspector.AddField("Sequence Parameter", m_SequenceParameters[i].GetData(), m_SequenceParameters[i].GetDataSize());
- }
- for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
- inspector.AddField("Picture Parameter", m_PictureParameters[i].GetData(), m_PictureParameters[i].GetDataSize());
- }
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - avcC Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4AvccAtom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4Utils.h"
+#include "Ap4Types.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_AvccAtom)
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::GetProfileName
++---------------------------------------------------------------------*/
+const char*
+AP4_AvccAtom::GetProfileName(AP4_UI08 profile)
+{
+ switch (profile) {
+ case AP4_AVC_PROFILE_BASELINE: return "Baseline";
+ case AP4_AVC_PROFILE_MAIN: return "Main";
+ case AP4_AVC_PROFILE_EXTENDED: return "Extended";
+ case AP4_AVC_PROFILE_HIGH: return "High";
+ case AP4_AVC_PROFILE_HIGH_10: return "High 10";
+ case AP4_AVC_PROFILE_HIGH_422: return "High 4:2:2";
+ case AP4_AVC_PROFILE_HIGH_444: return "High 4:4:4";
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::Create
++---------------------------------------------------------------------*/
+AP4_AvccAtom*
+AP4_AvccAtom::Create(AP4_Size size, AP4_ByteStream& stream)
+{
+ // read the raw bytes in a buffer
+ unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
+ AP4_DataBuffer payload_data(payload_size);
+ AP4_Result result = stream.Read(payload_data.UseData(), payload_size);
+ if (AP4_FAILED(result)) return NULL;
+
+ // check the version
+ const AP4_UI08* payload = payload_data.GetData();
+ if (payload[0] != 1) {
+ return NULL;
+ }
+
+ // check the size
+ if (payload_size < 6) return NULL;
+ unsigned int num_seq_params = payload[5]&31;
+ unsigned int cursor = 6;
+ for (unsigned int i=0; i<num_seq_params; i++) {
+ if (cursor+2 > payload_size) return NULL;
+ cursor += 2+AP4_BytesToInt16BE(&payload[cursor]);
+ if (cursor > payload_size) return NULL;
+ }
+ unsigned int num_pic_params = payload[cursor++];
+ if (cursor > payload_size) return NULL;
+ for (unsigned int i=0; i<num_pic_params; i++) {
+ if (cursor+2 > payload_size) return NULL;
+ cursor += 2+AP4_BytesToInt16BE(&payload[cursor]);
+ if (cursor > payload_size) return NULL;
+ }
+ return new AP4_AvccAtom(size, payload);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::AP4_AvccAtom
++---------------------------------------------------------------------*/
+AP4_AvccAtom::AP4_AvccAtom() :
+ AP4_Atom(AP4_ATOM_TYPE_AVCC, AP4_ATOM_HEADER_SIZE),
+ m_ConfigurationVersion(1),
+ m_Profile(0),
+ m_Level(0),
+ m_ProfileCompatibility(0),
+ m_NaluLengthSize(0)
+{
+ UpdateRawBytes();
+ m_Size32 += m_RawBytes.GetDataSize();
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::AP4_AvccAtom
++---------------------------------------------------------------------*/
+AP4_AvccAtom::AP4_AvccAtom(const AP4_AvccAtom& other) :
+ AP4_Atom(AP4_ATOM_TYPE_AVCC, other.m_Size32),
+ m_ConfigurationVersion(other.m_ConfigurationVersion),
+ m_Profile(other.m_Profile),
+ m_Level(other.m_Level),
+ m_ProfileCompatibility(other.m_ProfileCompatibility),
+ m_NaluLengthSize(other.m_NaluLengthSize),
+ m_RawBytes(other.m_RawBytes)
+{
+ // deep copy of the parameters
+ unsigned int i = 0;
+ for (i=0; i<other.m_SequenceParameters.ItemCount(); i++) {
+ m_SequenceParameters.Append(other.m_SequenceParameters[i]);
+ }
+ for (i=0; i<other.m_PictureParameters.ItemCount(); i++) {
+ m_PictureParameters.Append(other.m_PictureParameters[i]);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::AP4_AvccAtom
++---------------------------------------------------------------------*/
+AP4_AvccAtom::AP4_AvccAtom(AP4_UI32 size, const AP4_UI08* payload) :
+ AP4_Atom(AP4_ATOM_TYPE_AVCC, size)
+{
+ // make a copy of our configuration bytes
+ unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE;
+ m_RawBytes.SetData(payload, payload_size);
+
+ // parse the payload
+ m_ConfigurationVersion = payload[0];
+ m_Profile = payload[1];
+ m_ProfileCompatibility = payload[2];
+ m_Level = payload[3];
+ m_NaluLengthSize = 1+(payload[4]&3);
+ AP4_UI08 num_seq_params = payload[5]&31;
+ m_SequenceParameters.EnsureCapacity(num_seq_params);
+ unsigned int cursor = 6;
+ for (unsigned int i=0; i<num_seq_params; i++) {
+ m_SequenceParameters.Append(AP4_DataBuffer());
+ AP4_UI16 param_length = AP4_BytesToInt16BE(&payload[cursor]);
+ m_SequenceParameters[i].SetData(&payload[cursor]+2, param_length);
+ cursor += 2+param_length;
+ }
+ AP4_UI08 num_pic_params = payload[cursor++];
+ m_PictureParameters.EnsureCapacity(num_pic_params);
+ for (unsigned int i=0; i<num_pic_params; i++) {
+ m_PictureParameters.Append(AP4_DataBuffer());
+ AP4_UI16 param_length = AP4_BytesToInt16BE(&payload[cursor]);
+ m_PictureParameters[i].SetData(&payload[cursor]+2, param_length);
+ cursor += 2+param_length;
+ }
+}
+
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::AP4_AvccAtom
++---------------------------------------------------------------------*/
+AP4_AvccAtom::AP4_AvccAtom(AP4_UI08 profile,
+ AP4_UI08 level,
+ AP4_UI08 profile_compatibility,
+ AP4_UI08 length_size,
+ const AP4_Array<AP4_DataBuffer>& sequence_parameters,
+ const AP4_Array<AP4_DataBuffer>& picture_parameters) :
+ AP4_Atom(AP4_ATOM_TYPE_AVCC, AP4_ATOM_HEADER_SIZE),
+ m_ConfigurationVersion(1),
+ m_Profile(profile),
+ m_Level(level),
+ m_ProfileCompatibility(profile_compatibility),
+ m_NaluLengthSize(length_size)
+{
+ // deep copy of the parameters
+ unsigned int i = 0;
+ for (i=0; i<sequence_parameters.ItemCount(); i++) {
+ m_SequenceParameters.Append(sequence_parameters[i]);
+ }
+ for (i=0; i<picture_parameters.ItemCount(); i++) {
+ m_PictureParameters.Append(picture_parameters[i]);
+ }
+
+ // compute the raw bytes
+ UpdateRawBytes();
+
+ // update the size
+ m_Size32 += m_RawBytes.GetDataSize();
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::UpdateRawBytes
++---------------------------------------------------------------------*/
+void
+AP4_AvccAtom::UpdateRawBytes()
+{
+ // compute the payload size
+ unsigned int payload_size = 6;
+ for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
+ payload_size += 2+m_SequenceParameters[i].GetDataSize();
+ }
+ ++payload_size;
+ for (unsigned int i=0; i<m_PictureParameters.ItemCount(); i++) {
+ payload_size += 2+m_PictureParameters[i].GetDataSize();
+ }
+ m_RawBytes.SetDataSize(payload_size);
+ AP4_UI08* payload = m_RawBytes.UseData();
+
+ payload[0] = m_ConfigurationVersion;
+ payload[1] = m_Profile;
+ payload[2] = m_ProfileCompatibility;
+ payload[3] = m_Level;
+ payload[4] = 0xFC | (m_NaluLengthSize-1);
+ payload[5] = 0xE0 | m_SequenceParameters.ItemCount();
+ unsigned int cursor = 6;
+ for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
+ AP4_UI16 param_length = (AP4_UI16)m_SequenceParameters[i].GetDataSize();
+ AP4_BytesFromUInt16BE(&payload[cursor], param_length);
+ cursor += 2;
+ AP4_CopyMemory(&payload[cursor], m_SequenceParameters[i].GetData(), param_length);
+ cursor += param_length;
+ }
+ payload[cursor++] = m_PictureParameters.ItemCount();
+ for (unsigned int i=0; i<m_PictureParameters.ItemCount(); i++) {
+ AP4_UI16 param_length = (AP4_UI16)m_PictureParameters[i].GetDataSize();
+ AP4_BytesFromUInt16BE(&payload[cursor], param_length);
+ cursor += 2;
+ AP4_CopyMemory(&payload[cursor], m_PictureParameters[i].GetData(), param_length);
+ cursor += param_length;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AvccAtom::WriteFields(AP4_ByteStream& stream)
+{
+ return stream.Write(m_RawBytes.GetData(), m_RawBytes.GetDataSize());
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AvccAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("Configuration Version", m_ConfigurationVersion);
+ const char* profile_name = GetProfileName(m_Profile);
+ if (profile_name) {
+ inspector.AddField("Profile", profile_name);
+ } else {
+ inspector.AddField("Profile", m_Profile);
+ }
+ inspector.AddField("Profile Compatibility", m_ProfileCompatibility, AP4_AtomInspector::HINT_HEX);
+ inspector.AddField("Level", m_Level);
+ inspector.AddField("NALU Length Size", m_NaluLengthSize);
+ for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
+ inspector.AddField("Sequence Parameter", m_SequenceParameters[i].GetData(), m_SequenceParameters[i].GetDataSize());
+ }
+ for (unsigned int i=0; i<m_SequenceParameters.ItemCount(); i++) {
+ inspector.AddField("Picture Parameter", m_PictureParameters[i].GetData(), m_PictureParameters[i].GetDataSize());
+ }
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.h
index b3b300853..6414f0c29 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4AvcCAtom.h
@@ -1,102 +1,102 @@
-/*****************************************************************
-|
-| AP4 - avcC Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-#ifndef _AP4_AVCC_ATOM_H_
-#define _AP4_AVCC_ATOM_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Atom.h"
-#include "Ap4Array.h"
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_UI08 AP4_AVC_PROFILE_BASELINE = 66;
-const AP4_UI08 AP4_AVC_PROFILE_MAIN = 77;
-const AP4_UI08 AP4_AVC_PROFILE_EXTENDED = 88;
-const AP4_UI08 AP4_AVC_PROFILE_HIGH = 100;
-const AP4_UI08 AP4_AVC_PROFILE_HIGH_10 = 110;
-const AP4_UI08 AP4_AVC_PROFILE_HIGH_422 = 122;
-const AP4_UI08 AP4_AVC_PROFILE_HIGH_444 = 144;
-
-
-/*----------------------------------------------------------------------
-| AP4_AvccAtom
-+---------------------------------------------------------------------*/
-class AP4_AvccAtom : public AP4_Atom
-{
-public:
- AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_AvccAtom, AP4_Atom)
-
- // class methods
- static AP4_AvccAtom* Create(AP4_Size size, AP4_ByteStream& stream);
- static const char* GetProfileName(AP4_UI08 profile);
-
- // constructors
- AP4_AvccAtom();
- AP4_AvccAtom(AP4_UI08 profile,
- AP4_UI08 level,
- AP4_UI08 profile_compatibility,
- AP4_UI08 length_size,
- const AP4_Array<AP4_DataBuffer>& sequence_parameters,
- const AP4_Array<AP4_DataBuffer>& picture_parameters);
- AP4_AvccAtom(const AP4_AvccAtom& other); // copy construtor
-
- // methods
- virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
- virtual AP4_Result WriteFields(AP4_ByteStream& stream);
-
- // accessors
- AP4_UI08 GetConfigurationVersion() const { return m_ConfigurationVersion; }
- AP4_UI08 GetProfile() const { return m_Profile; }
- AP4_UI08 GetLevel() const { return m_Level; }
- AP4_UI08 GetProfileCompatibility() const { return m_ProfileCompatibility; }
- AP4_UI08 GetNaluLengthSize() const { return m_NaluLengthSize; }
- AP4_Array<AP4_DataBuffer>& GetSequenceParameters() { return m_SequenceParameters; }
- AP4_Array<AP4_DataBuffer>& GetPictureParameters() { return m_PictureParameters; }
- const AP4_DataBuffer& GetRawBytes() const { return m_RawBytes; }
-
-private:
- // methods
- AP4_AvccAtom(AP4_UI32 size, const AP4_UI08* payload);
- void UpdateRawBytes();
-
- // members
- AP4_UI08 m_ConfigurationVersion;
- AP4_UI08 m_Profile;
- AP4_UI08 m_Level;
- AP4_UI08 m_ProfileCompatibility;
- AP4_UI08 m_NaluLengthSize;
- AP4_Array<AP4_DataBuffer> m_SequenceParameters;
- AP4_Array<AP4_DataBuffer> m_PictureParameters;
- AP4_DataBuffer m_RawBytes;
-};
-
-#endif // _AP4_AVCC_ATOM_H_
+/*****************************************************************
+|
+| AP4 - avcC Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+#ifndef _AP4_AVCC_ATOM_H_
+#define _AP4_AVCC_ATOM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Atom.h"
+#include "Ap4Array.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_UI08 AP4_AVC_PROFILE_BASELINE = 66;
+const AP4_UI08 AP4_AVC_PROFILE_MAIN = 77;
+const AP4_UI08 AP4_AVC_PROFILE_EXTENDED = 88;
+const AP4_UI08 AP4_AVC_PROFILE_HIGH = 100;
+const AP4_UI08 AP4_AVC_PROFILE_HIGH_10 = 110;
+const AP4_UI08 AP4_AVC_PROFILE_HIGH_422 = 122;
+const AP4_UI08 AP4_AVC_PROFILE_HIGH_444 = 144;
+
+
+/*----------------------------------------------------------------------
+| AP4_AvccAtom
++---------------------------------------------------------------------*/
+class AP4_AvccAtom : public AP4_Atom
+{
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_AvccAtom, AP4_Atom)
+
+ // class methods
+ static AP4_AvccAtom* Create(AP4_Size size, AP4_ByteStream& stream);
+ static const char* GetProfileName(AP4_UI08 profile);
+
+ // constructors
+ AP4_AvccAtom();
+ AP4_AvccAtom(AP4_UI08 profile,
+ AP4_UI08 level,
+ AP4_UI08 profile_compatibility,
+ AP4_UI08 length_size,
+ const AP4_Array<AP4_DataBuffer>& sequence_parameters,
+ const AP4_Array<AP4_DataBuffer>& picture_parameters);
+ AP4_AvccAtom(const AP4_AvccAtom& other); // copy construtor
+
+ // methods
+ virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
+ virtual AP4_Result WriteFields(AP4_ByteStream& stream);
+
+ // accessors
+ AP4_UI08 GetConfigurationVersion() const { return m_ConfigurationVersion; }
+ AP4_UI08 GetProfile() const { return m_Profile; }
+ AP4_UI08 GetLevel() const { return m_Level; }
+ AP4_UI08 GetProfileCompatibility() const { return m_ProfileCompatibility; }
+ AP4_UI08 GetNaluLengthSize() const { return m_NaluLengthSize; }
+ AP4_Array<AP4_DataBuffer>& GetSequenceParameters() { return m_SequenceParameters; }
+ AP4_Array<AP4_DataBuffer>& GetPictureParameters() { return m_PictureParameters; }
+ const AP4_DataBuffer& GetRawBytes() const { return m_RawBytes; }
+
+private:
+ // methods
+ AP4_AvccAtom(AP4_UI32 size, const AP4_UI08* payload);
+ void UpdateRawBytes();
+
+ // members
+ AP4_UI08 m_ConfigurationVersion;
+ AP4_UI08 m_Profile;
+ AP4_UI08 m_Level;
+ AP4_UI08 m_ProfileCompatibility;
+ AP4_UI08 m_NaluLengthSize;
+ AP4_Array<AP4_DataBuffer> m_SequenceParameters;
+ AP4_Array<AP4_DataBuffer> m_PictureParameters;
+ AP4_DataBuffer m_RawBytes;
+};
+
+#endif // _AP4_AVCC_ATOM_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.cpp
index e5c33d319..b9f1ea8cf 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.cpp
@@ -1,842 +1,842 @@
-/*****************************************************************
-|
-| AP4 - Byte Stream support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4ByteStream.h"
-#include "Ap4Utils.h"
-#include "Ap4Debug.h"
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const int AP4_BYTE_STREAM_COPY_BUFFER_SIZE = 65536;
-const int AP4_MEMORY_BYTE_STREAM_MAX_SIZE = 0x4000000; // 64 megs
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::Read
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::Read(void* buffer, AP4_Size bytes_to_read)
-{
- // shortcut
- if (bytes_to_read == 0) return AP4_SUCCESS;
-
- // read until failure
- AP4_Size bytes_read;
- while (bytes_to_read) {
- AP4_Result result = ReadPartial(buffer, bytes_to_read, bytes_read);
- if (AP4_FAILED(result)) return result;
- if (bytes_read == 0) return AP4_ERROR_INTERNAL;
- AP4_ASSERT(bytes_read <= bytes_to_read);
- bytes_to_read -= bytes_read;
- buffer = (void*)(((AP4_Byte*)buffer)+bytes_read);
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Stream::Write
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::Write(const void* buffer, AP4_Size bytes_to_write)
-{
- // shortcut
- if (bytes_to_write == 0) return AP4_SUCCESS;
-
- // write until failure
- AP4_Size bytes_written;
- while (bytes_to_write) {
- AP4_Result result = WritePartial(buffer, bytes_to_write, bytes_written);
- if (AP4_FAILED(result)) return result;
- if (bytes_written == 0) return AP4_ERROR_INTERNAL;
- AP4_ASSERT(bytes_written <= bytes_to_write);
- bytes_to_write -= bytes_written;
- buffer = (const void*)(((const AP4_Byte*)buffer)+bytes_written);
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::WriteString
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::WriteString(const char* buffer)
-{
- AP4_Size string_length = static_cast<AP4_Size>(strlen(buffer));
-
- // shortcut
- if ((buffer == NULL) || (string_length == 0)) return AP4_SUCCESS;
-
- // write the string
- return Write((const void*)buffer, string_length);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::WriteDouble
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::WriteDouble(double value)
-{
- unsigned char buffer[8];
-
- // convert value to bytes
- AP4_BytesFromDoubleBE(buffer, value);
-
- // write bytes to the stream
- return Write((void*)buffer, 8);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::WriteUI64
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::WriteUI64(AP4_UI64 value)
-{
- unsigned char buffer[8];
-
- // convert value to bytes
- AP4_BytesFromUInt64BE(buffer, value);
-
- // write bytes to the stream
- return Write((void*)buffer, 8);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::WriteUI32
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::WriteUI32(AP4_UI32 value)
-{
- unsigned char buffer[4];
-
- // convert value to bytes
- AP4_BytesFromUInt32BE(buffer, value);
-
- // write bytes to the stream
- return Write((void*)buffer, 4);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::WriteUI24
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::WriteUI24(AP4_UI32 value)
-{
- unsigned char buffer[3];
-
- // convert value to bytes
- AP4_BytesFromUInt24BE(buffer, value);
-
- // write bytes to the stream
- return Write((void*)buffer, 3);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::WriteUI16
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::WriteUI16(AP4_UI16 value)
-{
- unsigned char buffer[2];
-
- // convert value to bytes
- AP4_BytesFromUInt16BE(buffer, value);
-
- // write bytes to the stream
- return Write((void*)buffer, 2);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::WriteUI08
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::WriteUI08(AP4_UI08 value)
-{
- return Write((void*)&value, 1);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::ReadUI64
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::ReadUI64(AP4_UI64& value)
-{
- unsigned char buffer[8];
-
- // read bytes from the stream
- AP4_Result result;
- result = Read((void*)buffer, 8);
- if (AP4_FAILED(result)) {
- value = 0;
- return result;
- }
-
- // convert bytes to value
- value = AP4_BytesToUInt64BE(buffer);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::ReadDouble
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::ReadDouble(double& value)
-{
- unsigned char buffer[8];
-
- // read bytes from the stream
- AP4_Result result;
- result = Read((void*)buffer, 8);
- if (AP4_FAILED(result)) {
- value = 0;
- return result;
- }
-
- // convert bytes to value
- value = AP4_BytesToDoubleBE(buffer);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::ReadUI32
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::ReadUI32(AP4_UI32& value)
-{
- unsigned char buffer[4];
-
- // read bytes from the stream
- AP4_Result result;
- result = Read((void*)buffer, 4);
- if (AP4_FAILED(result)) {
- value = 0;
- return result;
- }
-
- // convert bytes to value
- value = AP4_BytesToUInt32BE(buffer);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::ReadUI24
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::ReadUI24(AP4_UI32& value)
-{
- unsigned char buffer[3];
-
- // read bytes from the stream
- AP4_Result result;
- result = Read((void*)buffer, 3);
- if (AP4_FAILED(result)) {
- value = 0;
- return result;
- }
-
- // convert bytes to value
- value = AP4_BytesToUInt24BE(buffer);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::ReadUI16
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::ReadUI16(AP4_UI16& value)
-{
- unsigned char buffer[2];
-
- // read bytes from the stream
- AP4_Result result;
- result = Read((void*)buffer, 2);
- if (AP4_FAILED(result)) {
- value = 0;
- return result;
- }
-
- // convert bytes to value
- value = AP4_BytesToUInt16BE(buffer);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::ReadUI08
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::ReadUI08(AP4_UI08& value)
-{
- unsigned char buffer[1];
-
- // read bytes from the stream
- AP4_Result result;
- result = Read((void*)buffer, 1);
- if (AP4_FAILED(result)) {
- value = 0;
- return result;
- }
-
- // convert bytes to value
- value = buffer[0];
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::ReadString
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::ReadString(char* buffer, AP4_Size size)
-{
- if (buffer == NULL || size == 0) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
-
- AP4_Size bytes_read = 0;
- while (bytes_read < size-1) {
- AP4_Result result;
- result = Read(&buffer[bytes_read], 1);
- if (AP4_FAILED(result)) {
- buffer[bytes_read] = '\0';
- return result;
- }
- if (buffer[bytes_read] == '\0') {
- // end of string
- return AP4_SUCCESS;
- }
- bytes_read++;
- }
-
- // the string was not null terminated, terminate it
- buffer[size-1] = '\0';
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream::CopyTo
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ByteStream::CopyTo(AP4_ByteStream& stream, AP4_LargeSize size)
-{
- unsigned char buffer[AP4_BYTE_STREAM_COPY_BUFFER_SIZE];
- while (size) {
- AP4_Size bytes_read;
- AP4_Size bytes_to_read;
- AP4_Result result;
-
- // decide how much to read
- if (size >= sizeof(buffer)) {
- bytes_to_read = sizeof(buffer);
- } else {
- bytes_to_read = (AP4_Size)size;
- }
-
- // read up to one buffer full
- result = ReadPartial(buffer, bytes_to_read, bytes_read);
- if (AP4_FAILED(result)) return result;
-
- // copy to destination
- if (bytes_read != 0) {
- result = stream.Write(buffer, bytes_read);
- if (AP4_FAILED(result)) return result;
- }
-
- // update the size
- size -= bytes_read;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SubStream::AP4_SubStream
-+---------------------------------------------------------------------*/
-AP4_SubStream::AP4_SubStream(AP4_ByteStream& container,
- AP4_Position offset,
- AP4_LargeSize size) :
- m_Container(container),
- m_Offset(offset),
- m_Size(size),
- m_Position(0),
- m_ReferenceCount(1)
-{
- m_Container.AddReference();
-}
-
-/*----------------------------------------------------------------------
-| AP4_SubStream::~AP4_SubStream
-+---------------------------------------------------------------------*/
-AP4_SubStream::~AP4_SubStream()
-{
- m_Container.Release();
-}
-
-/*----------------------------------------------------------------------
-| AP4_SubStream::ReadPartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SubStream::ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read)
-{
- // default values
- bytes_read = 0;
-
- // shortcut
- if (bytes_to_read == 0) {
- return AP4_SUCCESS;
- }
-
- // clamp to range
- if (m_Position+bytes_to_read > m_Size) {
- bytes_to_read = (AP4_Size)(m_Size - m_Position);
- }
-
- // check for end of substream
- if (bytes_to_read == 0) {
- return AP4_ERROR_EOS;
- }
-
- // seek inside container
- AP4_Result result;
- result = m_Container.Seek(m_Offset+m_Position);
- if (AP4_FAILED(result)) {
- return result;
- }
-
- // read from the container
- result = m_Container.ReadPartial(buffer, bytes_to_read, bytes_read);
- if (AP4_SUCCEEDED(result)) {
- m_Position += bytes_read;
- }
- return result;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SubStream::WritePartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SubStream::WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written)
-{
- // default values
- bytes_written = 0;
-
- // shortcut
- if (bytes_to_write == 0) {
- return AP4_SUCCESS;
- }
-
- // clamp to range
- if (m_Position+bytes_to_write > m_Size) {
- bytes_to_write = (AP4_Size)(m_Size - m_Position);
- }
-
- // check for en of substream
- if (bytes_to_write == 0) {
- return AP4_ERROR_EOS;
- }
-
- // seek inside container
- AP4_Result result;
- result = m_Container.Seek(m_Offset+m_Position);
- if (AP4_FAILED(result)) return result;
-
- // write to container
- result = m_Container.WritePartial(buffer, bytes_to_write, bytes_written);
- if (AP4_SUCCEEDED(result)) {
- m_Position += bytes_written;
- }
- return result;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SubStream::Seek
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SubStream::Seek(AP4_Position position)
-{
- if (position == m_Position) return AP4_SUCCESS;
- if (position > m_Size) return AP4_FAILURE;
- m_Position = position;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SubStream::AddReference
-+---------------------------------------------------------------------*/
-void
-AP4_SubStream::AddReference()
-{
- m_ReferenceCount++;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SubStream::Release
-+---------------------------------------------------------------------*/
-void
-AP4_SubStream::Release()
-{
- if (--m_ReferenceCount == 0) {
- delete this;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::AP4_MemoryByteStream
-+---------------------------------------------------------------------*/
-AP4_MemoryByteStream::AP4_MemoryByteStream(AP4_Size size) :
- m_BufferIsLocal(true),
- m_Position(0),
- m_ReferenceCount(1)
-{
- m_Buffer = new AP4_DataBuffer(size);
- AP4_SetMemory(m_Buffer->UseData(), 0, size);
- m_Buffer->SetDataSize(size);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::AP4_MemoryByteStream
-+---------------------------------------------------------------------*/
-AP4_MemoryByteStream::AP4_MemoryByteStream(const AP4_UI08* buffer, AP4_Size size) :
- m_BufferIsLocal(true),
- m_Position(0),
- m_ReferenceCount(1)
-{
- m_Buffer = new AP4_DataBuffer(buffer, size);
-}
-
-/*----------------------------------------------------------------------
- | AP4_MemoryByteStream::AP4_MemoryByteStream
- +---------------------------------------------------------------------*/
-AP4_MemoryByteStream::AP4_MemoryByteStream(AP4_DataBuffer& data_buffer) :
- m_BufferIsLocal(false),
- m_Position(0),
- m_ReferenceCount(1)
-{
- m_Buffer = &data_buffer;
-}
-
-/*----------------------------------------------------------------------
- | AP4_MemoryByteStream::~AP4_MemoryByteStream
- +---------------------------------------------------------------------*/
-AP4_MemoryByteStream::~AP4_MemoryByteStream()
-{
- if (m_BufferIsLocal) {
- delete m_Buffer;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::ReadPartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MemoryByteStream::ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read)
-{
- // default values
- bytes_read = 0;
-
- // shortcut
- if (bytes_to_read == 0) {
- return AP4_SUCCESS;
- }
-
- // clamp to range
- if (m_Position+bytes_to_read > m_Buffer->GetDataSize()) {
- bytes_to_read = (AP4_Size)(m_Buffer->GetDataSize() - m_Position);
- }
-
- // check for end of stream
- if (bytes_to_read == 0) {
- return AP4_ERROR_EOS;
- }
-
- // read from the memory
- AP4_CopyMemory(buffer, m_Buffer->GetData()+m_Position, bytes_to_read);
- m_Position += bytes_to_read;
-
- bytes_read = bytes_to_read;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::WritePartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MemoryByteStream::WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written)
-{
- // default values
- bytes_written = 0;
-
- // shortcut
- if (bytes_to_write == 0) {
- return AP4_SUCCESS;
- }
-
- // check that we don't exceed the max
- if (m_Position+bytes_to_write > (AP4_Position)AP4_MEMORY_BYTE_STREAM_MAX_SIZE) {
- return AP4_ERROR_OUT_OF_RANGE;
- }
-
- // reserve space in the buffer
- AP4_Result result = m_Buffer->Reserve((AP4_Size)(m_Position+bytes_to_write));
- if (AP4_SUCCEEDED(result)) {
- m_Buffer->SetDataSize((AP4_Size)(m_Position+bytes_to_write));
- } else {
- // failed to reserve, most likely caused by a buffer that has
- // external storage
- if (m_Position+bytes_to_write > m_Buffer->GetDataSize()) {
- bytes_to_write = (AP4_Size)(m_Buffer->GetDataSize() - m_Position);
- }
- }
-
- // check for en of stream
- if (bytes_to_write == 0) {
- return AP4_ERROR_EOS;
- }
-
- // write to memory
- AP4_CopyMemory((void*)(m_Buffer->UseData()+m_Position), buffer, bytes_to_write);
- m_Position += bytes_to_write;
-
- bytes_written = bytes_to_write;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::Seek
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MemoryByteStream::Seek(AP4_Position position)
-{
- if (position > m_Buffer->GetDataSize()) return AP4_FAILURE;
- m_Position = position;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::AddReference
-+---------------------------------------------------------------------*/
-void
-AP4_MemoryByteStream::AddReference()
-{
- m_ReferenceCount++;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::Release
-+---------------------------------------------------------------------*/
-void
-AP4_MemoryByteStream::Release()
-{
- if (--m_ReferenceCount == 0) {
- delete this;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream::AP4_BufferedInputStream
-+---------------------------------------------------------------------*/
-AP4_BufferedInputStream::AP4_BufferedInputStream(AP4_ByteStream& source,
- AP4_Size buffer_size,
- AP4_Size seek_as_read_threshold) :
- m_Buffer(buffer_size),
- m_BufferPosition(0),
- m_Source(source),
- m_SourcePosition(0),
- m_SeekAsReadThreshold(seek_as_read_threshold),
- m_ReferenceCount(1)
-{
- source.AddReference();
-}
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream::Refill
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_BufferedInputStream::Refill()
-{
- m_BufferPosition = 0;
- AP4_Size bytes_read = 0;
- AP4_Result result = m_Source.ReadPartial(m_Buffer.UseData(),
- m_Buffer.GetBufferSize(),
- bytes_read);
- if (AP4_FAILED(result)) {
- m_Buffer.SetDataSize(0);
- return result;
- }
- assert(bytes_read);
- m_Buffer.SetDataSize(bytes_read);
- m_SourcePosition += bytes_read;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream::ReadPartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_BufferedInputStream::ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read)
-{
- // check for shortcut
- if (bytes_to_read == 0) {
- bytes_read = 0;
- return AP4_SUCCESS;
- }
-
- // compute how much data is available in the buffer
- assert(m_BufferPosition <= m_Buffer.GetDataSize());
- AP4_Size available = m_Buffer.GetDataSize()-m_BufferPosition;
-
- // refill the buffer if it is empty
- if (available == 0) {
- AP4_Result result = Refill();
- if (AP4_FAILED(result)) {
- bytes_read = 0;
- return result;
- }
- assert(m_BufferPosition == 0);
- assert(m_Buffer.GetDataSize() != 0);
- available = m_Buffer.GetDataSize()-m_BufferPosition;
- }
-
- // clamp the number of bytes to read to what's available
- if (bytes_to_read > available) bytes_to_read = available;
- bytes_read = bytes_to_read;
-
- // copy the buffered data
- AP4_CopyMemory(buffer, m_Buffer.GetData()+m_BufferPosition, bytes_to_read);
- m_BufferPosition += bytes_to_read;
- assert(m_BufferPosition <= m_Buffer.GetDataSize());
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream::WritePartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_BufferedInputStream::WritePartial(const void* /*buffer*/,
- AP4_Size /*bytes_to_write*/,
- AP4_Size& /*bytes_written*/)
-{
- return AP4_ERROR_NOT_SUPPORTED;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream::Seek
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_BufferedInputStream::Seek(AP4_Position position)
-{
- assert(m_SourcePosition >= m_Buffer.GetDataSize());
- assert(m_BufferPosition <= m_Buffer.GetDataSize());
- if (position < m_SourcePosition-m_Buffer.GetDataSize() ||
- position > m_SourcePosition) {
- // out of buffer
- m_BufferPosition = 0;
- m_Buffer.SetDataSize(0);
-
- // seek in the source
- if (position > m_SourcePosition && (position-m_SourcePosition <= m_SeekAsReadThreshold)) {
- char* discard = new char[4096];
- AP4_Size to_skip = (AP4_Size)(position-m_SourcePosition);
- while (to_skip) {
- AP4_Size chunk = 4096;
- if (chunk > to_skip) chunk = to_skip;
- AP4_Result result = m_Source.Read(discard, chunk);
- if (AP4_FAILED(result)) {
- delete[] discard;
- return result;
- }
- m_SourcePosition += chunk;
- to_skip -= chunk;
- }
- delete[] discard;
- return AP4_SUCCESS;
- } else {
- m_SourcePosition = position;
- return m_Source.Seek(position);
- }
- }
-
- // compute the buffer position
- m_BufferPosition = (AP4_Size)(position-(m_SourcePosition-m_Buffer.GetDataSize()));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream::Tell
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_BufferedInputStream::Tell(AP4_Position& position)
-{
- assert(m_SourcePosition >= m_Buffer.GetDataSize());
- assert(m_BufferPosition <= m_Buffer.GetDataSize());
- position = m_SourcePosition-m_Buffer.GetDataSize()+m_BufferPosition;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream::AddReference
-+---------------------------------------------------------------------*/
-void
-AP4_BufferedInputStream::AddReference()
-{
- m_ReferenceCount++;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream::Release
-+---------------------------------------------------------------------*/
-void
-AP4_BufferedInputStream::Release()
-{
- if (--m_ReferenceCount == 0) {
- delete this;
- }
-}
+/*****************************************************************
+|
+| AP4 - Byte Stream support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4ByteStream.h"
+#include "Ap4Utils.h"
+#include "Ap4Debug.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int AP4_BYTE_STREAM_COPY_BUFFER_SIZE = 65536;
+const int AP4_MEMORY_BYTE_STREAM_MAX_SIZE = 0x4000000; // 64 megs
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::Read
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::Read(void* buffer, AP4_Size bytes_to_read)
+{
+ // shortcut
+ if (bytes_to_read == 0) return AP4_SUCCESS;
+
+ // read until failure
+ AP4_Size bytes_read;
+ while (bytes_to_read) {
+ AP4_Result result = ReadPartial(buffer, bytes_to_read, bytes_read);
+ if (AP4_FAILED(result)) return result;
+ if (bytes_read == 0) return AP4_ERROR_INTERNAL;
+ AP4_ASSERT(bytes_read <= bytes_to_read);
+ bytes_to_read -= bytes_read;
+ buffer = (void*)(((AP4_Byte*)buffer)+bytes_read);
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Stream::Write
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::Write(const void* buffer, AP4_Size bytes_to_write)
+{
+ // shortcut
+ if (bytes_to_write == 0) return AP4_SUCCESS;
+
+ // write until failure
+ AP4_Size bytes_written;
+ while (bytes_to_write) {
+ AP4_Result result = WritePartial(buffer, bytes_to_write, bytes_written);
+ if (AP4_FAILED(result)) return result;
+ if (bytes_written == 0) return AP4_ERROR_INTERNAL;
+ AP4_ASSERT(bytes_written <= bytes_to_write);
+ bytes_to_write -= bytes_written;
+ buffer = (const void*)(((const AP4_Byte*)buffer)+bytes_written);
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::WriteString
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::WriteString(const char* buffer)
+{
+ AP4_Size string_length = static_cast<AP4_Size>(strlen(buffer));
+
+ // shortcut
+ if ((buffer == NULL) || (string_length == 0)) return AP4_SUCCESS;
+
+ // write the string
+ return Write((const void*)buffer, string_length);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::WriteDouble
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::WriteDouble(double value)
+{
+ unsigned char buffer[8];
+
+ // convert value to bytes
+ AP4_BytesFromDoubleBE(buffer, value);
+
+ // write bytes to the stream
+ return Write((void*)buffer, 8);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::WriteUI64
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::WriteUI64(AP4_UI64 value)
+{
+ unsigned char buffer[8];
+
+ // convert value to bytes
+ AP4_BytesFromUInt64BE(buffer, value);
+
+ // write bytes to the stream
+ return Write((void*)buffer, 8);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::WriteUI32
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::WriteUI32(AP4_UI32 value)
+{
+ unsigned char buffer[4];
+
+ // convert value to bytes
+ AP4_BytesFromUInt32BE(buffer, value);
+
+ // write bytes to the stream
+ return Write((void*)buffer, 4);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::WriteUI24
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::WriteUI24(AP4_UI32 value)
+{
+ unsigned char buffer[3];
+
+ // convert value to bytes
+ AP4_BytesFromUInt24BE(buffer, value);
+
+ // write bytes to the stream
+ return Write((void*)buffer, 3);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::WriteUI16
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::WriteUI16(AP4_UI16 value)
+{
+ unsigned char buffer[2];
+
+ // convert value to bytes
+ AP4_BytesFromUInt16BE(buffer, value);
+
+ // write bytes to the stream
+ return Write((void*)buffer, 2);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::WriteUI08
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::WriteUI08(AP4_UI08 value)
+{
+ return Write((void*)&value, 1);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::ReadUI64
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::ReadUI64(AP4_UI64& value)
+{
+ unsigned char buffer[8];
+
+ // read bytes from the stream
+ AP4_Result result;
+ result = Read((void*)buffer, 8);
+ if (AP4_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = AP4_BytesToUInt64BE(buffer);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::ReadDouble
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::ReadDouble(double& value)
+{
+ unsigned char buffer[8];
+
+ // read bytes from the stream
+ AP4_Result result;
+ result = Read((void*)buffer, 8);
+ if (AP4_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = AP4_BytesToDoubleBE(buffer);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::ReadUI32
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::ReadUI32(AP4_UI32& value)
+{
+ unsigned char buffer[4];
+
+ // read bytes from the stream
+ AP4_Result result;
+ result = Read((void*)buffer, 4);
+ if (AP4_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = AP4_BytesToUInt32BE(buffer);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::ReadUI24
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::ReadUI24(AP4_UI32& value)
+{
+ unsigned char buffer[3];
+
+ // read bytes from the stream
+ AP4_Result result;
+ result = Read((void*)buffer, 3);
+ if (AP4_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = AP4_BytesToUInt24BE(buffer);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::ReadUI16
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::ReadUI16(AP4_UI16& value)
+{
+ unsigned char buffer[2];
+
+ // read bytes from the stream
+ AP4_Result result;
+ result = Read((void*)buffer, 2);
+ if (AP4_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = AP4_BytesToUInt16BE(buffer);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::ReadUI08
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::ReadUI08(AP4_UI08& value)
+{
+ unsigned char buffer[1];
+
+ // read bytes from the stream
+ AP4_Result result;
+ result = Read((void*)buffer, 1);
+ if (AP4_FAILED(result)) {
+ value = 0;
+ return result;
+ }
+
+ // convert bytes to value
+ value = buffer[0];
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::ReadString
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::ReadString(char* buffer, AP4_Size size)
+{
+ if (buffer == NULL || size == 0) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+
+ AP4_Size bytes_read = 0;
+ while (bytes_read < size-1) {
+ AP4_Result result;
+ result = Read(&buffer[bytes_read], 1);
+ if (AP4_FAILED(result)) {
+ buffer[bytes_read] = '\0';
+ return result;
+ }
+ if (buffer[bytes_read] == '\0') {
+ // end of string
+ return AP4_SUCCESS;
+ }
+ bytes_read++;
+ }
+
+ // the string was not null terminated, terminate it
+ buffer[size-1] = '\0';
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream::CopyTo
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ByteStream::CopyTo(AP4_ByteStream& stream, AP4_LargeSize size)
+{
+ unsigned char buffer[AP4_BYTE_STREAM_COPY_BUFFER_SIZE];
+ while (size) {
+ AP4_Size bytes_read;
+ AP4_Size bytes_to_read;
+ AP4_Result result;
+
+ // decide how much to read
+ if (size >= sizeof(buffer)) {
+ bytes_to_read = sizeof(buffer);
+ } else {
+ bytes_to_read = (AP4_Size)size;
+ }
+
+ // read up to one buffer full
+ result = ReadPartial(buffer, bytes_to_read, bytes_read);
+ if (AP4_FAILED(result)) return result;
+
+ // copy to destination
+ if (bytes_read != 0) {
+ result = stream.Write(buffer, bytes_read);
+ if (AP4_FAILED(result)) return result;
+ }
+
+ // update the size
+ size -= bytes_read;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SubStream::AP4_SubStream
++---------------------------------------------------------------------*/
+AP4_SubStream::AP4_SubStream(AP4_ByteStream& container,
+ AP4_Position offset,
+ AP4_LargeSize size) :
+ m_Container(container),
+ m_Offset(offset),
+ m_Size(size),
+ m_Position(0),
+ m_ReferenceCount(1)
+{
+ m_Container.AddReference();
+}
+
+/*----------------------------------------------------------------------
+| AP4_SubStream::~AP4_SubStream
++---------------------------------------------------------------------*/
+AP4_SubStream::~AP4_SubStream()
+{
+ m_Container.Release();
+}
+
+/*----------------------------------------------------------------------
+| AP4_SubStream::ReadPartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SubStream::ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read)
+{
+ // default values
+ bytes_read = 0;
+
+ // shortcut
+ if (bytes_to_read == 0) {
+ return AP4_SUCCESS;
+ }
+
+ // clamp to range
+ if (m_Position+bytes_to_read > m_Size) {
+ bytes_to_read = (AP4_Size)(m_Size - m_Position);
+ }
+
+ // check for end of substream
+ if (bytes_to_read == 0) {
+ return AP4_ERROR_EOS;
+ }
+
+ // seek inside container
+ AP4_Result result;
+ result = m_Container.Seek(m_Offset+m_Position);
+ if (AP4_FAILED(result)) {
+ return result;
+ }
+
+ // read from the container
+ result = m_Container.ReadPartial(buffer, bytes_to_read, bytes_read);
+ if (AP4_SUCCEEDED(result)) {
+ m_Position += bytes_read;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SubStream::WritePartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SubStream::WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written)
+{
+ // default values
+ bytes_written = 0;
+
+ // shortcut
+ if (bytes_to_write == 0) {
+ return AP4_SUCCESS;
+ }
+
+ // clamp to range
+ if (m_Position+bytes_to_write > m_Size) {
+ bytes_to_write = (AP4_Size)(m_Size - m_Position);
+ }
+
+ // check for en of substream
+ if (bytes_to_write == 0) {
+ return AP4_ERROR_EOS;
+ }
+
+ // seek inside container
+ AP4_Result result;
+ result = m_Container.Seek(m_Offset+m_Position);
+ if (AP4_FAILED(result)) return result;
+
+ // write to container
+ result = m_Container.WritePartial(buffer, bytes_to_write, bytes_written);
+ if (AP4_SUCCEEDED(result)) {
+ m_Position += bytes_written;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SubStream::Seek
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SubStream::Seek(AP4_Position position)
+{
+ if (position == m_Position) return AP4_SUCCESS;
+ if (position > m_Size) return AP4_FAILURE;
+ m_Position = position;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SubStream::AddReference
++---------------------------------------------------------------------*/
+void
+AP4_SubStream::AddReference()
+{
+ m_ReferenceCount++;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SubStream::Release
++---------------------------------------------------------------------*/
+void
+AP4_SubStream::Release()
+{
+ if (--m_ReferenceCount == 0) {
+ delete this;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::AP4_MemoryByteStream
++---------------------------------------------------------------------*/
+AP4_MemoryByteStream::AP4_MemoryByteStream(AP4_Size size) :
+ m_BufferIsLocal(true),
+ m_Position(0),
+ m_ReferenceCount(1)
+{
+ m_Buffer = new AP4_DataBuffer(size);
+ AP4_SetMemory(m_Buffer->UseData(), 0, size);
+ m_Buffer->SetDataSize(size);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::AP4_MemoryByteStream
++---------------------------------------------------------------------*/
+AP4_MemoryByteStream::AP4_MemoryByteStream(const AP4_UI08* buffer, AP4_Size size) :
+ m_BufferIsLocal(true),
+ m_Position(0),
+ m_ReferenceCount(1)
+{
+ m_Buffer = new AP4_DataBuffer(buffer, size);
+}
+
+/*----------------------------------------------------------------------
+ | AP4_MemoryByteStream::AP4_MemoryByteStream
+ +---------------------------------------------------------------------*/
+AP4_MemoryByteStream::AP4_MemoryByteStream(AP4_DataBuffer& data_buffer) :
+ m_BufferIsLocal(false),
+ m_Position(0),
+ m_ReferenceCount(1)
+{
+ m_Buffer = &data_buffer;
+}
+
+/*----------------------------------------------------------------------
+ | AP4_MemoryByteStream::~AP4_MemoryByteStream
+ +---------------------------------------------------------------------*/
+AP4_MemoryByteStream::~AP4_MemoryByteStream()
+{
+ if (m_BufferIsLocal) {
+ delete m_Buffer;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::ReadPartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MemoryByteStream::ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read)
+{
+ // default values
+ bytes_read = 0;
+
+ // shortcut
+ if (bytes_to_read == 0) {
+ return AP4_SUCCESS;
+ }
+
+ // clamp to range
+ if (m_Position+bytes_to_read > m_Buffer->GetDataSize()) {
+ bytes_to_read = (AP4_Size)(m_Buffer->GetDataSize() - m_Position);
+ }
+
+ // check for end of stream
+ if (bytes_to_read == 0) {
+ return AP4_ERROR_EOS;
+ }
+
+ // read from the memory
+ AP4_CopyMemory(buffer, m_Buffer->GetData()+m_Position, bytes_to_read);
+ m_Position += bytes_to_read;
+
+ bytes_read = bytes_to_read;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::WritePartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MemoryByteStream::WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written)
+{
+ // default values
+ bytes_written = 0;
+
+ // shortcut
+ if (bytes_to_write == 0) {
+ return AP4_SUCCESS;
+ }
+
+ // check that we don't exceed the max
+ if (m_Position+bytes_to_write > (AP4_Position)AP4_MEMORY_BYTE_STREAM_MAX_SIZE) {
+ return AP4_ERROR_OUT_OF_RANGE;
+ }
+
+ // reserve space in the buffer
+ AP4_Result result = m_Buffer->Reserve((AP4_Size)(m_Position+bytes_to_write));
+ if (AP4_SUCCEEDED(result)) {
+ m_Buffer->SetDataSize((AP4_Size)(m_Position+bytes_to_write));
+ } else {
+ // failed to reserve, most likely caused by a buffer that has
+ // external storage
+ if (m_Position+bytes_to_write > m_Buffer->GetDataSize()) {
+ bytes_to_write = (AP4_Size)(m_Buffer->GetDataSize() - m_Position);
+ }
+ }
+
+ // check for en of stream
+ if (bytes_to_write == 0) {
+ return AP4_ERROR_EOS;
+ }
+
+ // write to memory
+ AP4_CopyMemory((void*)(m_Buffer->UseData()+m_Position), buffer, bytes_to_write);
+ m_Position += bytes_to_write;
+
+ bytes_written = bytes_to_write;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::Seek
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MemoryByteStream::Seek(AP4_Position position)
+{
+ if (position > m_Buffer->GetDataSize()) return AP4_FAILURE;
+ m_Position = position;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::AddReference
++---------------------------------------------------------------------*/
+void
+AP4_MemoryByteStream::AddReference()
+{
+ m_ReferenceCount++;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::Release
++---------------------------------------------------------------------*/
+void
+AP4_MemoryByteStream::Release()
+{
+ if (--m_ReferenceCount == 0) {
+ delete this;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream::AP4_BufferedInputStream
++---------------------------------------------------------------------*/
+AP4_BufferedInputStream::AP4_BufferedInputStream(AP4_ByteStream& source,
+ AP4_Size buffer_size,
+ AP4_Size seek_as_read_threshold) :
+ m_Buffer(buffer_size),
+ m_BufferPosition(0),
+ m_Source(source),
+ m_SourcePosition(0),
+ m_SeekAsReadThreshold(seek_as_read_threshold),
+ m_ReferenceCount(1)
+{
+ source.AddReference();
+}
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream::Refill
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_BufferedInputStream::Refill()
+{
+ m_BufferPosition = 0;
+ AP4_Size bytes_read = 0;
+ AP4_Result result = m_Source.ReadPartial(m_Buffer.UseData(),
+ m_Buffer.GetBufferSize(),
+ bytes_read);
+ if (AP4_FAILED(result)) {
+ m_Buffer.SetDataSize(0);
+ return result;
+ }
+ assert(bytes_read);
+ m_Buffer.SetDataSize(bytes_read);
+ m_SourcePosition += bytes_read;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream::ReadPartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_BufferedInputStream::ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read)
+{
+ // check for shortcut
+ if (bytes_to_read == 0) {
+ bytes_read = 0;
+ return AP4_SUCCESS;
+ }
+
+ // compute how much data is available in the buffer
+ assert(m_BufferPosition <= m_Buffer.GetDataSize());
+ AP4_Size available = m_Buffer.GetDataSize()-m_BufferPosition;
+
+ // refill the buffer if it is empty
+ if (available == 0) {
+ AP4_Result result = Refill();
+ if (AP4_FAILED(result)) {
+ bytes_read = 0;
+ return result;
+ }
+ assert(m_BufferPosition == 0);
+ assert(m_Buffer.GetDataSize() != 0);
+ available = m_Buffer.GetDataSize()-m_BufferPosition;
+ }
+
+ // clamp the number of bytes to read to what's available
+ if (bytes_to_read > available) bytes_to_read = available;
+ bytes_read = bytes_to_read;
+
+ // copy the buffered data
+ AP4_CopyMemory(buffer, m_Buffer.GetData()+m_BufferPosition, bytes_to_read);
+ m_BufferPosition += bytes_to_read;
+ assert(m_BufferPosition <= m_Buffer.GetDataSize());
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream::WritePartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_BufferedInputStream::WritePartial(const void* /*buffer*/,
+ AP4_Size /*bytes_to_write*/,
+ AP4_Size& /*bytes_written*/)
+{
+ return AP4_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream::Seek
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_BufferedInputStream::Seek(AP4_Position position)
+{
+ assert(m_SourcePosition >= m_Buffer.GetDataSize());
+ assert(m_BufferPosition <= m_Buffer.GetDataSize());
+ if (position < m_SourcePosition-m_Buffer.GetDataSize() ||
+ position > m_SourcePosition) {
+ // out of buffer
+ m_BufferPosition = 0;
+ m_Buffer.SetDataSize(0);
+
+ // seek in the source
+ if (position > m_SourcePosition && (position-m_SourcePosition <= m_SeekAsReadThreshold)) {
+ char* discard = new char[4096];
+ AP4_Size to_skip = (AP4_Size)(position-m_SourcePosition);
+ while (to_skip) {
+ AP4_Size chunk = 4096;
+ if (chunk > to_skip) chunk = to_skip;
+ AP4_Result result = m_Source.Read(discard, chunk);
+ if (AP4_FAILED(result)) {
+ delete[] discard;
+ return result;
+ }
+ m_SourcePosition += chunk;
+ to_skip -= chunk;
+ }
+ delete[] discard;
+ return AP4_SUCCESS;
+ } else {
+ m_SourcePosition = position;
+ return m_Source.Seek(position);
+ }
+ }
+
+ // compute the buffer position
+ m_BufferPosition = (AP4_Size)(position-(m_SourcePosition-m_Buffer.GetDataSize()));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream::Tell
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_BufferedInputStream::Tell(AP4_Position& position)
+{
+ assert(m_SourcePosition >= m_Buffer.GetDataSize());
+ assert(m_BufferPosition <= m_Buffer.GetDataSize());
+ position = m_SourcePosition-m_Buffer.GetDataSize()+m_BufferPosition;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream::AddReference
++---------------------------------------------------------------------*/
+void
+AP4_BufferedInputStream::AddReference()
+{
+ m_ReferenceCount++;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream::Release
++---------------------------------------------------------------------*/
+void
+AP4_BufferedInputStream::Release()
+{
+ if (--m_ReferenceCount == 0) {
+ delete this;
+ }
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.h
index 3eaf2d803..4e2d271f7 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ByteStream.h
@@ -1,202 +1,202 @@
-/*****************************************************************
-|
-| AP4 - ByteStream Interface
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_BYTE_STREAM_H_
-#define _AP4_BYTE_STREAM_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4Interfaces.h"
-#include "Ap4Results.h"
-#include "Ap4DataBuffer.h"
-
-/*----------------------------------------------------------------------
-| AP4_ByteStream
-+---------------------------------------------------------------------*/
-class AP4_ByteStream : public AP4_Referenceable
-{
- public:
- // methods
- virtual AP4_Result ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read) = 0;
- AP4_Result Read(void* buffer, AP4_Size bytes_to_read);
- AP4_Result ReadDouble(double& value);
- AP4_Result ReadUI64(AP4_UI64& value);
- AP4_Result ReadUI32(AP4_UI32& value);
- AP4_Result ReadUI24(AP4_UI32& value);
- AP4_Result ReadUI16(AP4_UI16& value);
- AP4_Result ReadUI08(AP4_UI08& value);
- AP4_Result ReadString(char* buffer, AP4_Size size);
- virtual AP4_Result WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written) = 0;
- AP4_Result Write(const void* buffer, AP4_Size bytes_to_write);
- AP4_Result WriteString(const char* string_buffer);
- AP4_Result WriteDouble(double value);
- AP4_Result WriteUI64(AP4_UI64 value);
- AP4_Result WriteUI32(AP4_UI32 value);
- AP4_Result WriteUI24(AP4_UI32 value);
- AP4_Result WriteUI16(AP4_UI16 value);
- AP4_Result WriteUI08(AP4_UI08 value);
- virtual AP4_Result Seek(AP4_Position position) = 0;
- virtual AP4_Result Tell(AP4_Position& position) = 0;
- virtual AP4_Result GetSize(AP4_LargeSize& size) = 0;
- virtual AP4_Result CopyTo(AP4_ByteStream& stream, AP4_LargeSize size);
- virtual AP4_Result Flush() { return AP4_SUCCESS; }
-};
-
-/*----------------------------------------------------------------------
-| AP4_SubStream
-+---------------------------------------------------------------------*/
-class AP4_SubStream : public AP4_ByteStream
-{
- public:
- AP4_SubStream(AP4_ByteStream& container,
- AP4_Position position,
- AP4_LargeSize size);
-
- // AP4_ByteStream methods
- AP4_Result ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read);
- AP4_Result WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written);
- AP4_Result Seek(AP4_Position position);
- AP4_Result Tell(AP4_Position& position) {
- position = m_Position;
- return AP4_SUCCESS;
- }
- AP4_Result GetSize(AP4_LargeSize& size) {
- size = m_Size;
- return AP4_SUCCESS;
- }
-
- // AP4_Referenceable methods
- void AddReference();
- void Release();
-
- protected:
- virtual ~AP4_SubStream();
-
- private:
- AP4_ByteStream& m_Container;
- AP4_Position m_Offset;
- AP4_LargeSize m_Size;
- AP4_Position m_Position;
- AP4_Cardinal m_ReferenceCount;
-};
-
-/*----------------------------------------------------------------------
-| AP4_MemoryByteStream
-+---------------------------------------------------------------------*/
-class AP4_MemoryByteStream : public AP4_ByteStream
-{
-public:
- AP4_MemoryByteStream(AP4_Size size = 0); // filled with zeros
- AP4_MemoryByteStream(const AP4_UI08* buffer, AP4_Size size);
- AP4_MemoryByteStream(AP4_DataBuffer& data_buffer); // data is read/written from/to supplied buffer
-
- // AP4_ByteStream methods
- AP4_Result ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read);
- AP4_Result WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written);
- AP4_Result Seek(AP4_Position position);
- AP4_Result Tell(AP4_Position& position) {
- position = m_Position;
- return AP4_SUCCESS;
- }
- AP4_Result GetSize(AP4_LargeSize& size) {
- size = m_Buffer->GetDataSize();
- return AP4_SUCCESS;
- }
-
- // AP4_Referenceable methods
- void AddReference();
- void Release();
-
- // methods
- const AP4_UI08* GetData() { return m_Buffer->GetData(); }
- AP4_UI08* UseData() { return m_Buffer->UseData(); }
- AP4_Size GetDataSize() { return m_Buffer->GetDataSize(); }
-
-protected:
- virtual ~AP4_MemoryByteStream();
-
-private:
- AP4_DataBuffer* m_Buffer;
- bool m_BufferIsLocal;
- AP4_Position m_Position;
- AP4_Cardinal m_ReferenceCount;
-};
-
-/*----------------------------------------------------------------------
-| AP4_BufferedInputStream
-+---------------------------------------------------------------------*/
-class AP4_BufferedInputStream : public AP4_ByteStream
-{
-public:
- AP4_BufferedInputStream(AP4_ByteStream& source,
- AP4_Size buffer_size=4096,
- AP4_Size seek_as_read_threshold=1024*128);
-
- // AP4_ByteStream methods
- AP4_Result ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read);
- AP4_Result WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written);
- AP4_Result Seek(AP4_Position position);
- AP4_Result Tell(AP4_Position& position);
- AP4_Result GetSize(AP4_LargeSize& size) { return m_Source.GetSize(size); }
-
- // AP4_Referenceable methods
- void AddReference();
- void Release();
-
-protected:
- ~AP4_BufferedInputStream() { m_Source.Release(); }
- AP4_Result Refill();
-
-private:
- AP4_DataBuffer m_Buffer;
- AP4_Size m_BufferPosition;
- AP4_ByteStream& m_Source;
- AP4_Position m_SourcePosition;
- AP4_Size m_SeekAsReadThreshold;
- AP4_Cardinal m_ReferenceCount;
-};
-
-#endif // _AP4_BYTE_STREAM_H_
+/*****************************************************************
+|
+| AP4 - ByteStream Interface
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_BYTE_STREAM_H_
+#define _AP4_BYTE_STREAM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4Interfaces.h"
+#include "Ap4Results.h"
+#include "Ap4DataBuffer.h"
+
+/*----------------------------------------------------------------------
+| AP4_ByteStream
++---------------------------------------------------------------------*/
+class AP4_ByteStream : public AP4_Referenceable
+{
+ public:
+ // methods
+ virtual AP4_Result ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read) = 0;
+ AP4_Result Read(void* buffer, AP4_Size bytes_to_read);
+ AP4_Result ReadDouble(double& value);
+ AP4_Result ReadUI64(AP4_UI64& value);
+ AP4_Result ReadUI32(AP4_UI32& value);
+ AP4_Result ReadUI24(AP4_UI32& value);
+ AP4_Result ReadUI16(AP4_UI16& value);
+ AP4_Result ReadUI08(AP4_UI08& value);
+ AP4_Result ReadString(char* buffer, AP4_Size size);
+ virtual AP4_Result WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written) = 0;
+ AP4_Result Write(const void* buffer, AP4_Size bytes_to_write);
+ AP4_Result WriteString(const char* string_buffer);
+ AP4_Result WriteDouble(double value);
+ AP4_Result WriteUI64(AP4_UI64 value);
+ AP4_Result WriteUI32(AP4_UI32 value);
+ AP4_Result WriteUI24(AP4_UI32 value);
+ AP4_Result WriteUI16(AP4_UI16 value);
+ AP4_Result WriteUI08(AP4_UI08 value);
+ virtual AP4_Result Seek(AP4_Position position) = 0;
+ virtual AP4_Result Tell(AP4_Position& position) = 0;
+ virtual AP4_Result GetSize(AP4_LargeSize& size) = 0;
+ virtual AP4_Result CopyTo(AP4_ByteStream& stream, AP4_LargeSize size);
+ virtual AP4_Result Flush() { return AP4_SUCCESS; }
+};
+
+/*----------------------------------------------------------------------
+| AP4_SubStream
++---------------------------------------------------------------------*/
+class AP4_SubStream : public AP4_ByteStream
+{
+ public:
+ AP4_SubStream(AP4_ByteStream& container,
+ AP4_Position position,
+ AP4_LargeSize size);
+
+ // AP4_ByteStream methods
+ AP4_Result ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read);
+ AP4_Result WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written);
+ AP4_Result Seek(AP4_Position position);
+ AP4_Result Tell(AP4_Position& position) {
+ position = m_Position;
+ return AP4_SUCCESS;
+ }
+ AP4_Result GetSize(AP4_LargeSize& size) {
+ size = m_Size;
+ return AP4_SUCCESS;
+ }
+
+ // AP4_Referenceable methods
+ void AddReference();
+ void Release();
+
+ protected:
+ virtual ~AP4_SubStream();
+
+ private:
+ AP4_ByteStream& m_Container;
+ AP4_Position m_Offset;
+ AP4_LargeSize m_Size;
+ AP4_Position m_Position;
+ AP4_Cardinal m_ReferenceCount;
+};
+
+/*----------------------------------------------------------------------
+| AP4_MemoryByteStream
++---------------------------------------------------------------------*/
+class AP4_MemoryByteStream : public AP4_ByteStream
+{
+public:
+ AP4_MemoryByteStream(AP4_Size size = 0); // filled with zeros
+ AP4_MemoryByteStream(const AP4_UI08* buffer, AP4_Size size);
+ AP4_MemoryByteStream(AP4_DataBuffer& data_buffer); // data is read/written from/to supplied buffer
+
+ // AP4_ByteStream methods
+ AP4_Result ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read);
+ AP4_Result WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written);
+ AP4_Result Seek(AP4_Position position);
+ AP4_Result Tell(AP4_Position& position) {
+ position = m_Position;
+ return AP4_SUCCESS;
+ }
+ AP4_Result GetSize(AP4_LargeSize& size) {
+ size = m_Buffer->GetDataSize();
+ return AP4_SUCCESS;
+ }
+
+ // AP4_Referenceable methods
+ void AddReference();
+ void Release();
+
+ // methods
+ const AP4_UI08* GetData() { return m_Buffer->GetData(); }
+ AP4_UI08* UseData() { return m_Buffer->UseData(); }
+ AP4_Size GetDataSize() { return m_Buffer->GetDataSize(); }
+
+protected:
+ virtual ~AP4_MemoryByteStream();
+
+private:
+ AP4_DataBuffer* m_Buffer;
+ bool m_BufferIsLocal;
+ AP4_Position m_Position;
+ AP4_Cardinal m_ReferenceCount;
+};
+
+/*----------------------------------------------------------------------
+| AP4_BufferedInputStream
++---------------------------------------------------------------------*/
+class AP4_BufferedInputStream : public AP4_ByteStream
+{
+public:
+ AP4_BufferedInputStream(AP4_ByteStream& source,
+ AP4_Size buffer_size=4096,
+ AP4_Size seek_as_read_threshold=1024*128);
+
+ // AP4_ByteStream methods
+ AP4_Result ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read);
+ AP4_Result WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written);
+ AP4_Result Seek(AP4_Position position);
+ AP4_Result Tell(AP4_Position& position);
+ AP4_Result GetSize(AP4_LargeSize& size) { return m_Source.GetSize(size); }
+
+ // AP4_Referenceable methods
+ void AddReference();
+ void Release();
+
+protected:
+ ~AP4_BufferedInputStream() { m_Source.Release(); }
+ AP4_Result Refill();
+
+private:
+ AP4_DataBuffer m_Buffer;
+ AP4_Size m_BufferPosition;
+ AP4_ByteStream& m_Source;
+ AP4_Position m_SourcePosition;
+ AP4_Size m_SeekAsReadThreshold;
+ AP4_Cardinal m_ReferenceCount;
+};
+
+#endif // _AP4_BYTE_STREAM_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Command.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Command.cpp
index 1dc6958f5..0a2c395fa 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Command.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Command.cpp
@@ -47,9 +47,9 @@ AP4_Command::Inspect(AP4_AtomInspector& inspector)
char name[6];
AP4_FormatString(name, sizeof(name), "[Command:%02x]", m_ClassId);
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),
- m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),
+ (int)m_PayloadSize);
inspector.StartElement(name, info);
inspector.EndElement();
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Config.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Config.h
new file mode 100644
index 000000000..5c786a58f
--- /dev/null
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Config.h
@@ -0,0 +1,142 @@
+/*****************************************************************
+|
+| AP4 - Target Platform and Compiler Configuration
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+/**
+ * @file
+ * @brief Platform Configuration
+ */
+#ifndef _AP4_CONFIG_H_
+#define _AP4_CONFIG_H_
+
+/*----------------------------------------------------------------------
+| defaults
++---------------------------------------------------------------------*/
+#define AP4_CONFIG_HAVE_STDIO_H
+#define AP4_CONFIG_HAVE_ASSERT_H
+#define AP4_CONFIG_HAVE_STRING_H
+#define AP4_CONFIG_HAVE_SNPRINTF
+#define AP4_CONFIG_HAVE_VSNPRINTF
+#define AP4_CONFIG_HAVE_INT64
+
+/*----------------------------------------------------------------------
+| byte order
++---------------------------------------------------------------------*/
+// define AP4_PLATFORM_BYTE_ORDER to one of these two choices
+#define AP4_PLATFORM_BYTE_ORDER_BIG_ENDIAN 0
+#define AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN 1
+
+#if !defined(AP4_PLATFORM_BYTE_ORDER)
+#if defined(__ppc__)
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_BIG_ENDIAN
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
+#else /* MPC custom */
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
+#endif
+#endif
+
+/*----------------------------------------------------------------------
+| standard C++ runtime
++---------------------------------------------------------------------*/
+#define APT_CONFIG_HAVE_NEW_H
+
+/*----------------------------------------------------------------------
+| platform specifics
++---------------------------------------------------------------------*/
+
+/* Microsoft Platforms */
+#if defined(_MSC_VER)
+#define AP4_CONFIG_INT64_TYPE __int64
+#if (_MSC_VER >= 1400) && !defined(_WIN32_WCE)
+#define AP4_CONFIG_HAVE_FOPEN_S
+#define AP4_snprintf(s,c,f,...) _snprintf_s(s,c,_TRUNCATE,f,__VA_ARGS__)
+#define AP4_vsnprintf(s,c,f,a) _vsnprintf_s(s,c,_TRUNCATE,f,a)
+#define fileno _fileno
+#define AP4_fseek _fseeki64
+#define AP4_ftell _ftelli64
+#else
+#define AP4_snprintf _snprintf
+#define AP4_vsnprintf _vsnprintf
+#endif
+#if defined(_WIN32_WCE)
+#define AP4_fseek fseek
+#define AP4_ftell ftell
+#endif
+#if defined(_DEBUG)
+#define _CRTDBG_MAP_ALLOC
+#endif
+#endif
+
+/* Cygwin */
+#if defined(__CYGWIN__)
+#define AP4_fseek fseek
+#define AP4_ftell ftell
+#endif
+
+/* Symbian */
+#if defined(__SYMBIAN32__)
+#undef APT_CONFIG_HAVE_NEW_H
+#include "e32std.h"
+/**
+ * Define the Platform byte order here
+ * for Symbian.
+ */
+#define AP4_PLATFORM_BYTE_ORDER AP4_PLATFORM_BYTE_ORDER_LITTLE_ENDIAN
+#define AP4_fseek fseek
+#define AP4_ftell ftell
+#define explicit
+#endif
+
+/* Android */
+#if defined(ANDROID)
+#define AP4_CONFIG_NO_RTTI
+#define AP4_CONFIG_NO_EXCEPTIONS
+#endif
+
+/*----------------------------------------------------------------------
+| defaults
++---------------------------------------------------------------------*/
+#if !defined(AP4_CONFIG_INT64_TYPE)
+#define AP4_CONFIG_INT64_TYPE long long
+#endif
+
+#if !defined(AP4_fseek)
+#define AP4_fseek fseeko
+#endif
+#if !defined(AP4_ftell)
+#define AP4_ftell ftello
+#endif
+
+/* some compilers (ex: MSVC 8) deprecate those, so we rename them */
+#if !defined(AP4_snprintf)
+#define AP4_snprintf snprintf
+#endif
+#if !defined(AP4_vsnprintf)
+#define AP4_vsnprintf vsnprintf
+#endif
+
+#endif // _AP4_CONFIG_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4CttsAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4CttsAtom.cpp
index fc431825a..50c9ad414 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4CttsAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4CttsAtom.cpp
@@ -1,211 +1,211 @@
-/*****************************************************************
-|
-| AP4 - ctts Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4CttsAtom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4Utils.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_CttsAtom)
-
-/*----------------------------------------------------------------------
-| AP4_CttsAtom::Create
-+---------------------------------------------------------------------*/
-AP4_CttsAtom*
-AP4_CttsAtom::Create(AP4_UI32 size, AP4_ByteStream& stream)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version != 0) return NULL;
- return new AP4_CttsAtom(size, version, flags, stream);
-}
-
-/*----------------------------------------------------------------------
-| AP4_CttsAtom::AP4_CttsAtom
-+---------------------------------------------------------------------*/
-AP4_CttsAtom::AP4_CttsAtom() :
- AP4_Atom(AP4_ATOM_TYPE_CTTS, AP4_FULL_ATOM_HEADER_SIZE+4, 0, 0)
-{
- m_LookupCache.sample = 0;
- m_LookupCache.entry_index = 0;
-}
-
-/*----------------------------------------------------------------------
-| AP4_CttsAtom::AP4_CttsAtom
-+---------------------------------------------------------------------*/
-AP4_CttsAtom::AP4_CttsAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream) :
- AP4_Atom(AP4_ATOM_TYPE_CTTS, size, version, flags)
-{
- m_LookupCache.sample = 0;
- m_LookupCache.entry_index = 0;
-
- AP4_UI32 entry_count;
- stream.ReadUI32(entry_count);
- m_Entries.SetItemCount(entry_count);
- unsigned char* buffer = new unsigned char[entry_count*8];
- AP4_Result result = stream.Read(buffer, entry_count*8);
- if (AP4_FAILED(result)) {
- delete[] buffer;
- return;
- }
- //bool use_quicktime_format = false;
- //AP4_SI32 quicktime_min_offset = 0;
- for (unsigned i=0; i<entry_count; i++) {
- m_Entries[i].m_SampleCount = AP4_BytesToUInt32BE(&buffer[i*8 ]);
- AP4_UI32 offset = AP4_BytesToUInt32BE(&buffer[i*8+4]);
- //if (offset & 0x80000000) {
- // use_quicktime_format = true;
- // AP4_SI32 noffset = (AP4_SI32)offset;
- // if (noffset < quicktime_min_offset) quicktime_min_offset = noffset;
- //}
- m_Entries[i].m_SampleOffset = offset;
- }
- delete[] buffer;
-
- // in the quicktime format, the offsets can be positive or negative, so
- // we need to adjust for them here
- //if (use_quicktime_format) {
- // for (unsigned i=0; i<entry_count; i++) {
- // m_Entries[i].m_SampleOffset -= quicktime_min_offset;
- // }
- //}
-}
-
-/*----------------------------------------------------------------------
-| AP4_CttsAtom::AddEntry
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_CttsAtom::AddEntry(AP4_UI32 count, AP4_UI32 cts_offset)
-{
- m_Entries.Append(AP4_CttsTableEntry(count, cts_offset));
- m_Size32 += 8;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_CttsAtom::GetCtsOffset
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_CttsAtom::GetCtsOffset(AP4_Ordinal sample, AP4_UI32& cts_offset)
-{
- // default value
- cts_offset = 0;
-
- // sample indexes start at 1
- if (sample == 0) return AP4_ERROR_OUT_OF_RANGE;
-
- // check the lookup cache
- AP4_Ordinal lookup_start = 0;
- AP4_Ordinal sample_start = 0;
- if (sample >= m_LookupCache.sample) {
- // start from the cached entry
- lookup_start = m_LookupCache.entry_index;
- sample_start = m_LookupCache.sample;
- }
-
- for (AP4_Ordinal i = lookup_start; i < m_Entries.ItemCount(); i++) {
- AP4_CttsTableEntry& entry = m_Entries[i];
-
- // check if we have reached the sample
- if (sample <= sample_start+entry.m_SampleCount) {
- // we are within the sample range for the current entry
- cts_offset = entry.m_SampleOffset;
-
- // update the lookup cache
- m_LookupCache.entry_index = i;
- m_LookupCache.sample = sample_start;
-
- return AP4_SUCCESS;
- }
-
- // update the upper bound
- sample_start += entry.m_SampleCount;
- }
-
- // sample is greater than the number of samples
- return AP4_ERROR_OUT_OF_RANGE;
-}
-
-/*----------------------------------------------------------------------
-| AP4_CttsAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_CttsAtom::WriteFields(AP4_ByteStream& stream)
-{
- AP4_Result result;
-
- // write the entry count
- AP4_Cardinal entry_count = m_Entries.ItemCount();
- result = stream.WriteUI32(entry_count);
- if (AP4_FAILED(result)) return result;
-
- // write the entries
- for (AP4_Ordinal i=0; i<entry_count; i++) {
- // sample count
- result = stream.WriteUI32(m_Entries[i].m_SampleCount);
- if (AP4_FAILED(result)) return result;
-
- // time offset
- result = stream.WriteUI32(m_Entries[i].m_SampleOffset);
- if (AP4_FAILED(result)) return result;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_CttsAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_CttsAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("entry_count", m_Entries.ItemCount());
-
- if (inspector.GetVerbosity() >= 2) {
- char header[32];
- char value[64];
- for (AP4_Ordinal i=0; i<m_Entries.ItemCount(); i++) {
- AP4_FormatString(header, sizeof(header), "entry %8d", i);
- AP4_FormatString(value, sizeof(value), "count=%d, offset=%d",
- m_Entries[i].m_SampleCount,
- m_Entries[i].m_SampleOffset);
- inspector.AddField(header, value);
- }
- }
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - ctts Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4CttsAtom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4Utils.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_CttsAtom)
+
+/*----------------------------------------------------------------------
+| AP4_CttsAtom::Create
++---------------------------------------------------------------------*/
+AP4_CttsAtom*
+AP4_CttsAtom::Create(AP4_UI32 size, AP4_ByteStream& stream)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version != 0) return NULL;
+ return new AP4_CttsAtom(size, version, flags, stream);
+}
+
+/*----------------------------------------------------------------------
+| AP4_CttsAtom::AP4_CttsAtom
++---------------------------------------------------------------------*/
+AP4_CttsAtom::AP4_CttsAtom() :
+ AP4_Atom(AP4_ATOM_TYPE_CTTS, AP4_FULL_ATOM_HEADER_SIZE+4, 0, 0)
+{
+ m_LookupCache.sample = 0;
+ m_LookupCache.entry_index = 0;
+}
+
+/*----------------------------------------------------------------------
+| AP4_CttsAtom::AP4_CttsAtom
++---------------------------------------------------------------------*/
+AP4_CttsAtom::AP4_CttsAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream) :
+ AP4_Atom(AP4_ATOM_TYPE_CTTS, size, version, flags)
+{
+ m_LookupCache.sample = 0;
+ m_LookupCache.entry_index = 0;
+
+ AP4_UI32 entry_count;
+ stream.ReadUI32(entry_count);
+ m_Entries.SetItemCount(entry_count);
+ unsigned char* buffer = new unsigned char[entry_count*8];
+ AP4_Result result = stream.Read(buffer, entry_count*8);
+ if (AP4_FAILED(result)) {
+ delete[] buffer;
+ return;
+ }
+ //bool use_quicktime_format = false;
+ //AP4_SI32 quicktime_min_offset = 0;
+ for (unsigned i=0; i<entry_count; i++) {
+ m_Entries[i].m_SampleCount = AP4_BytesToUInt32BE(&buffer[i*8 ]);
+ AP4_UI32 offset = AP4_BytesToUInt32BE(&buffer[i*8+4]);
+ //if (offset & 0x80000000) {
+ // use_quicktime_format = true;
+ // AP4_SI32 noffset = (AP4_SI32)offset;
+ // if (noffset < quicktime_min_offset) quicktime_min_offset = noffset;
+ //}
+ m_Entries[i].m_SampleOffset = offset;
+ }
+ delete[] buffer;
+
+ // in the quicktime format, the offsets can be positive or negative, so
+ // we need to adjust for them here
+ //if (use_quicktime_format) {
+ // for (unsigned i=0; i<entry_count; i++) {
+ // m_Entries[i].m_SampleOffset -= quicktime_min_offset;
+ // }
+ //}
+}
+
+/*----------------------------------------------------------------------
+| AP4_CttsAtom::AddEntry
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_CttsAtom::AddEntry(AP4_UI32 count, AP4_UI32 cts_offset)
+{
+ m_Entries.Append(AP4_CttsTableEntry(count, cts_offset));
+ m_Size32 += 8;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_CttsAtom::GetCtsOffset
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_CttsAtom::GetCtsOffset(AP4_Ordinal sample, AP4_UI32& cts_offset)
+{
+ // default value
+ cts_offset = 0;
+
+ // sample indexes start at 1
+ if (sample == 0) return AP4_ERROR_OUT_OF_RANGE;
+
+ // check the lookup cache
+ AP4_Ordinal lookup_start = 0;
+ AP4_Ordinal sample_start = 0;
+ if (sample >= m_LookupCache.sample) {
+ // start from the cached entry
+ lookup_start = m_LookupCache.entry_index;
+ sample_start = m_LookupCache.sample;
+ }
+
+ for (AP4_Ordinal i = lookup_start; i < m_Entries.ItemCount(); i++) {
+ AP4_CttsTableEntry& entry = m_Entries[i];
+
+ // check if we have reached the sample
+ if (sample <= sample_start+entry.m_SampleCount) {
+ // we are within the sample range for the current entry
+ cts_offset = entry.m_SampleOffset;
+
+ // update the lookup cache
+ m_LookupCache.entry_index = i;
+ m_LookupCache.sample = sample_start;
+
+ return AP4_SUCCESS;
+ }
+
+ // update the upper bound
+ sample_start += entry.m_SampleCount;
+ }
+
+ // sample is greater than the number of samples
+ return AP4_ERROR_OUT_OF_RANGE;
+}
+
+/*----------------------------------------------------------------------
+| AP4_CttsAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_CttsAtom::WriteFields(AP4_ByteStream& stream)
+{
+ AP4_Result result;
+
+ // write the entry count
+ AP4_Cardinal entry_count = m_Entries.ItemCount();
+ result = stream.WriteUI32(entry_count);
+ if (AP4_FAILED(result)) return result;
+
+ // write the entries
+ for (AP4_Ordinal i=0; i<entry_count; i++) {
+ // sample count
+ result = stream.WriteUI32(m_Entries[i].m_SampleCount);
+ if (AP4_FAILED(result)) return result;
+
+ // time offset
+ result = stream.WriteUI32(m_Entries[i].m_SampleOffset);
+ if (AP4_FAILED(result)) return result;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_CttsAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_CttsAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("entry_count", m_Entries.ItemCount());
+
+ if (inspector.GetVerbosity() >= 2) {
+ char header[32];
+ char value[64];
+ for (AP4_Ordinal i=0; i<m_Entries.ItemCount(); i++) {
+ AP4_FormatString(header, sizeof(header), "entry %8d", i);
+ AP4_FormatString(value, sizeof(value), "count=%d, offset=%d",
+ m_Entries[i].m_SampleCount,
+ m_Entries[i].m_SampleOffset);
+ inspector.AddField(header, value);
+ }
+ }
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DataBuffer.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DataBuffer.cpp
index 5cd837d3c..d537cb430 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DataBuffer.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DataBuffer.cpp
@@ -1,207 +1,207 @@
-/*****************************************************************
-|
-| AP4 - Data Buffer
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4DataBuffer.h"
-#include "Ap4Utils.h"
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::AP4_DataBuffer
-+---------------------------------------------------------------------*/
-AP4_DataBuffer::AP4_DataBuffer() :
- m_BufferIsLocal(true),
- m_Buffer(NULL),
- m_BufferSize(0),
- m_DataSize(0)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::AP4_DataBuffer
-+---------------------------------------------------------------------*/
-AP4_DataBuffer::AP4_DataBuffer(AP4_Size buffer_size) :
- m_BufferIsLocal(true),
- m_Buffer(NULL),
- m_BufferSize(buffer_size),
- m_DataSize(0)
-{
- m_Buffer = new AP4_Byte[buffer_size];
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::AP4_DataBuffer
-+---------------------------------------------------------------------*/
-AP4_DataBuffer::AP4_DataBuffer(const void* data, AP4_Size data_size) :
- m_BufferIsLocal(true),
- m_Buffer(NULL),
- m_BufferSize(data_size),
- m_DataSize(data_size)
-{
- if (data && data_size) {
- m_Buffer = new AP4_Byte[data_size];
- AP4_CopyMemory(m_Buffer, data, data_size);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::AP4_DataBuffer
-+---------------------------------------------------------------------*/
-AP4_DataBuffer::AP4_DataBuffer(const AP4_DataBuffer& other) :
- m_BufferIsLocal(true),
- m_Buffer(NULL),
- m_BufferSize(other.m_DataSize),
- m_DataSize(other.m_DataSize)
-{
- m_Buffer = new AP4_Byte[m_BufferSize];
- AP4_CopyMemory(m_Buffer, other.m_Buffer, m_BufferSize);
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::~AP4_DataBuffer
-+---------------------------------------------------------------------*/
-AP4_DataBuffer::~AP4_DataBuffer()
-{
- if (m_BufferIsLocal) {
- delete[] m_Buffer;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::Reserve
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataBuffer::Reserve(AP4_Size size)
-{
- if (size <= m_BufferSize) return AP4_SUCCESS;
-
- // try doubling the buffer to accomodate for the new size
- AP4_Size new_size = m_BufferSize*2+1024;
- if (new_size < size) new_size = size;
- return SetBufferSize(new_size);
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::SetBuffer
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataBuffer::SetBuffer(AP4_Byte* buffer, AP4_Size buffer_size)
-{
- if (m_BufferIsLocal) {
- // destroy the local buffer
- delete[] m_Buffer;
- }
-
- // we're now using an external buffer
- m_BufferIsLocal = false;
- m_Buffer = buffer;
- m_BufferSize = buffer_size;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::SetBufferSize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataBuffer::SetBufferSize(AP4_Size buffer_size)
-{
- if (m_BufferIsLocal) {
- return ReallocateBuffer(buffer_size);
- } else {
- return AP4_FAILURE; // you cannot change the
- // buffer management mode
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::SetDataSize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataBuffer::SetDataSize(AP4_Size size)
-{
- if (size > m_BufferSize) {
- if (m_BufferIsLocal) {
- AP4_Result result = ReallocateBuffer(size);
- if (AP4_FAILED(result)) return result;
- } else {
- return AP4_FAILURE;
- }
- }
- m_DataSize = size;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::SetData
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataBuffer::SetData(const AP4_Byte* data, AP4_Size size)
-{
- if (size > m_BufferSize) {
- if (m_BufferIsLocal) {
- AP4_Result result = ReallocateBuffer(size);
- if (AP4_FAILED(result)) return result;
- } else {
- return AP4_FAILURE;
- }
- }
- AP4_CopyMemory(m_Buffer, data, size);
- m_DataSize = size;
-
- return AP4_SUCCESS;
-}
-
-
-/*----------------------------------------------------------------------
-| AP4_DataBuffer::ReallocateBuffer
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataBuffer::ReallocateBuffer(AP4_Size size)
-{
- // check that the existing data fits
- if (m_DataSize > size) return AP4_FAILURE;
-
- // allocate a new buffer
- AP4_Byte* new_buffer = new AP4_Byte[size];
-
- // copy the contents of the previous buffer ,is any
- if (m_Buffer && m_DataSize) {
- AP4_CopyMemory(new_buffer, m_Buffer, m_DataSize);
- }
-
- // destroy the previous buffer
- delete[] m_Buffer;
-
- // use the new buffer
- m_Buffer = new_buffer;
- m_BufferSize = size;
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - Data Buffer
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4DataBuffer.h"
+#include "Ap4Utils.h"
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::AP4_DataBuffer
++---------------------------------------------------------------------*/
+AP4_DataBuffer::AP4_DataBuffer() :
+ m_BufferIsLocal(true),
+ m_Buffer(NULL),
+ m_BufferSize(0),
+ m_DataSize(0)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::AP4_DataBuffer
++---------------------------------------------------------------------*/
+AP4_DataBuffer::AP4_DataBuffer(AP4_Size buffer_size) :
+ m_BufferIsLocal(true),
+ m_Buffer(NULL),
+ m_BufferSize(buffer_size),
+ m_DataSize(0)
+{
+ m_Buffer = new AP4_Byte[buffer_size];
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::AP4_DataBuffer
++---------------------------------------------------------------------*/
+AP4_DataBuffer::AP4_DataBuffer(const void* data, AP4_Size data_size) :
+ m_BufferIsLocal(true),
+ m_Buffer(NULL),
+ m_BufferSize(data_size),
+ m_DataSize(data_size)
+{
+ if (data && data_size) {
+ m_Buffer = new AP4_Byte[data_size];
+ AP4_CopyMemory(m_Buffer, data, data_size);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::AP4_DataBuffer
++---------------------------------------------------------------------*/
+AP4_DataBuffer::AP4_DataBuffer(const AP4_DataBuffer& other) :
+ m_BufferIsLocal(true),
+ m_Buffer(NULL),
+ m_BufferSize(other.m_DataSize),
+ m_DataSize(other.m_DataSize)
+{
+ m_Buffer = new AP4_Byte[m_BufferSize];
+ AP4_CopyMemory(m_Buffer, other.m_Buffer, m_BufferSize);
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::~AP4_DataBuffer
++---------------------------------------------------------------------*/
+AP4_DataBuffer::~AP4_DataBuffer()
+{
+ if (m_BufferIsLocal) {
+ delete[] m_Buffer;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::Reserve
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataBuffer::Reserve(AP4_Size size)
+{
+ if (size <= m_BufferSize) return AP4_SUCCESS;
+
+ // try doubling the buffer to accomodate for the new size
+ AP4_Size new_size = m_BufferSize*2+1024;
+ if (new_size < size) new_size = size;
+ return SetBufferSize(new_size);
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::SetBuffer
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataBuffer::SetBuffer(AP4_Byte* buffer, AP4_Size buffer_size)
+{
+ if (m_BufferIsLocal) {
+ // destroy the local buffer
+ delete[] m_Buffer;
+ }
+
+ // we're now using an external buffer
+ m_BufferIsLocal = false;
+ m_Buffer = buffer;
+ m_BufferSize = buffer_size;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::SetBufferSize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataBuffer::SetBufferSize(AP4_Size buffer_size)
+{
+ if (m_BufferIsLocal) {
+ return ReallocateBuffer(buffer_size);
+ } else {
+ return AP4_FAILURE; // you cannot change the
+ // buffer management mode
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::SetDataSize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataBuffer::SetDataSize(AP4_Size size)
+{
+ if (size > m_BufferSize) {
+ if (m_BufferIsLocal) {
+ AP4_Result result = ReallocateBuffer(size);
+ if (AP4_FAILED(result)) return result;
+ } else {
+ return AP4_FAILURE;
+ }
+ }
+ m_DataSize = size;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::SetData
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataBuffer::SetData(const AP4_Byte* data, AP4_Size size)
+{
+ if (size > m_BufferSize) {
+ if (m_BufferIsLocal) {
+ AP4_Result result = ReallocateBuffer(size);
+ if (AP4_FAILED(result)) return result;
+ } else {
+ return AP4_FAILURE;
+ }
+ }
+ AP4_CopyMemory(m_Buffer, data, size);
+ m_DataSize = size;
+
+ return AP4_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------
+| AP4_DataBuffer::ReallocateBuffer
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataBuffer::ReallocateBuffer(AP4_Size size)
+{
+ // check that the existing data fits
+ if (m_DataSize > size) return AP4_FAILURE;
+
+ // allocate a new buffer
+ AP4_Byte* new_buffer = new AP4_Byte[size];
+
+ // copy the contents of the previous buffer ,is any
+ if (m_Buffer && m_DataSize) {
+ AP4_CopyMemory(new_buffer, m_Buffer, m_DataSize);
+ }
+
+ // destroy the previous buffer
+ delete[] m_Buffer;
+
+ // use the new buffer
+ m_Buffer = new_buffer;
+ m_BufferSize = size;
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DecoderConfigDescriptor.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DecoderConfigDescriptor.cpp
index 45b348f2d..9f767c07d 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DecoderConfigDescriptor.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4DecoderConfigDescriptor.cpp
@@ -132,9 +132,9 @@ AP4_Result
AP4_DecoderConfigDescriptor::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),
- m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),
+ (int)m_PayloadSize);
inspector.StartElement("[DecoderConfig]", info);
inspector.AddField("stream_type", m_StreamType);
inspector.AddField("object_type", m_ObjectTypeIndication);
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Descriptor.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Descriptor.cpp
index 38fb28988..930025ec1 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Descriptor.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Descriptor.cpp
@@ -48,9 +48,9 @@ AP4_Descriptor::Inspect(AP4_AtomInspector& inspector)
char name[20];
AP4_FormatString(name, sizeof(name), "[Descriptor:%02x]", m_ClassId);
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),
- m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),
+ (int)m_PayloadSize);
inspector.StartElement(name, info);
inspector.EndElement();
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4EsDescriptor.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4EsDescriptor.cpp
index 065d6f513..909627ae0 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4EsDescriptor.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4EsDescriptor.cpp
@@ -166,8 +166,8 @@ AP4_Result
AP4_EsDescriptor::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
inspector.StartElement("[ESDescriptor]", info);
inspector.AddField("es_id", m_EsId);
inspector.AddField("stream_priority", m_StreamPriority);
@@ -250,8 +250,8 @@ AP4_Result
AP4_EsIdIncDescriptor::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
inspector.StartElement("[ES_ID_Inc]", info);
inspector.AddField("track_id", m_TrackId);
inspector.EndElement();
@@ -297,8 +297,8 @@ AP4_Result
AP4_EsIdRefDescriptor::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
inspector.StartElement("[ES_ID_Ref]", info);
inspector.AddField("ref_index", m_RefIndex);
inspector.EndElement();
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Expandable.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Expandable.cpp
index a0fa39601..a4c300ca8 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Expandable.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Expandable.cpp
@@ -116,9 +116,9 @@ AP4_Expandable::Inspect(AP4_AtomInspector& inspector)
char name[6];
AP4_FormatString(name, sizeof(name), "[#:%02x]", m_ClassId);
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),
- m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),
+ (int)m_PayloadSize);
inspector.StartElement(name, info);
inspector.EndElement();
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4File.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4File.cpp
index baedd893a..6f9296cce 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4File.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4File.cpp
@@ -1,148 +1,148 @@
-/*****************************************************************
-|
-| AP4 - File
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4File.h"
-#include "Ap4Atom.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4MoovAtom.h"
-#include "Ap4MvhdAtom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4Movie.h"
-#include "Ap4FtypAtom.h"
-#include "Ap4MetaData.h"
-
-/*----------------------------------------------------------------------
-| AP4_File::AP4_File
-+---------------------------------------------------------------------*/
-AP4_File::AP4_File(AP4_Movie* movie) :
- m_Movie(movie),
- m_FileType(NULL),
- m_MetaData(NULL),
- m_MoovIsBeforeMdat(true)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_File::AP4_File
-+---------------------------------------------------------------------*/
-AP4_File::AP4_File(AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory,
- bool moov_only) :
- m_Movie(NULL),
- m_FileType(NULL),
- m_MetaData(NULL),
- m_MoovIsBeforeMdat(true)
-{
- // parse top-level atoms
- AP4_Atom* atom;
- AP4_Position stream_position;
- bool keep_parsing = true;
- while (keep_parsing &&
- AP4_SUCCEEDED(stream.Tell(stream_position)) &&
- AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(stream, atom))) {
- AddChild(atom);
- switch (atom->GetType()) {
- case AP4_ATOM_TYPE_MOOV:
- m_Movie = new AP4_Movie(AP4_DYNAMIC_CAST(AP4_MoovAtom, atom), stream, false);
- if (moov_only) keep_parsing = false;
- break;
-
- case AP4_ATOM_TYPE_FTYP:
- m_FileType = AP4_DYNAMIC_CAST(AP4_FtypAtom, atom);
- break;
-
- case AP4_ATOM_TYPE_MDAT:
- // see if we are before the moov atom
- if (m_Movie == NULL) m_MoovIsBeforeMdat = false;
- break;
- }
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_File::~AP4_File
-+---------------------------------------------------------------------*/
-AP4_File::~AP4_File()
-{
- delete m_Movie;
- delete m_MetaData;
-}
-
-/*----------------------------------------------------------------------
-| AP4_File::Inspect
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_File::Inspect(AP4_AtomInspector& inspector)
-{
- // dump the moov atom first
- if (m_Movie) m_Movie->Inspect(inspector);
-
- // dump the other atoms
- m_Children.Apply(AP4_AtomListInspector(inspector));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_File::SetFileType
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_File::SetFileType(AP4_UI32 major_brand,
- AP4_UI32 minor_version,
- AP4_UI32* compatible_brands,
- AP4_Cardinal compatible_brand_count)
-{
- if (m_FileType) {
- RemoveChild(m_FileType);
- delete m_FileType;
- }
- m_FileType = new AP4_FtypAtom(major_brand,
- minor_version,
- compatible_brands,
- compatible_brand_count);
- AddChild(m_FileType, 0);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_File::GetMetaData
-+---------------------------------------------------------------------*/
-const AP4_MetaData*
-AP4_File::GetMetaData()
-{
- if (m_MetaData == NULL) {
- m_MetaData = new AP4_MetaData(this);
- }
-
- return m_MetaData;
-}
-
+/*****************************************************************
+|
+| AP4 - File
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4File.h"
+#include "Ap4Atom.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4MoovAtom.h"
+#include "Ap4MvhdAtom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4Movie.h"
+#include "Ap4FtypAtom.h"
+#include "Ap4MetaData.h"
+
+/*----------------------------------------------------------------------
+| AP4_File::AP4_File
++---------------------------------------------------------------------*/
+AP4_File::AP4_File(AP4_Movie* movie) :
+ m_Movie(movie),
+ m_FileType(NULL),
+ m_MetaData(NULL),
+ m_MoovIsBeforeMdat(true)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_File::AP4_File
++---------------------------------------------------------------------*/
+AP4_File::AP4_File(AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory,
+ bool moov_only) :
+ m_Movie(NULL),
+ m_FileType(NULL),
+ m_MetaData(NULL),
+ m_MoovIsBeforeMdat(true)
+{
+ // parse top-level atoms
+ AP4_Atom* atom;
+ AP4_Position stream_position;
+ bool keep_parsing = true;
+ while (keep_parsing &&
+ AP4_SUCCEEDED(stream.Tell(stream_position)) &&
+ AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(stream, atom))) {
+ AddChild(atom);
+ switch (atom->GetType()) {
+ case AP4_ATOM_TYPE_MOOV:
+ m_Movie = new AP4_Movie(AP4_DYNAMIC_CAST(AP4_MoovAtom, atom), stream, false);
+ if (moov_only) keep_parsing = false;
+ break;
+
+ case AP4_ATOM_TYPE_FTYP:
+ m_FileType = AP4_DYNAMIC_CAST(AP4_FtypAtom, atom);
+ break;
+
+ case AP4_ATOM_TYPE_MDAT:
+ // see if we are before the moov atom
+ if (m_Movie == NULL) m_MoovIsBeforeMdat = false;
+ break;
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_File::~AP4_File
++---------------------------------------------------------------------*/
+AP4_File::~AP4_File()
+{
+ delete m_Movie;
+ delete m_MetaData;
+}
+
+/*----------------------------------------------------------------------
+| AP4_File::Inspect
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_File::Inspect(AP4_AtomInspector& inspector)
+{
+ // dump the moov atom first
+ if (m_Movie) m_Movie->Inspect(inspector);
+
+ // dump the other atoms
+ m_Children.Apply(AP4_AtomListInspector(inspector));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_File::SetFileType
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_File::SetFileType(AP4_UI32 major_brand,
+ AP4_UI32 minor_version,
+ AP4_UI32* compatible_brands,
+ AP4_Cardinal compatible_brand_count)
+{
+ if (m_FileType) {
+ RemoveChild(m_FileType);
+ delete m_FileType;
+ }
+ m_FileType = new AP4_FtypAtom(major_brand,
+ minor_version,
+ compatible_brands,
+ compatible_brand_count);
+ AddChild(m_FileType, 0);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_File::GetMetaData
++---------------------------------------------------------------------*/
+const AP4_MetaData*
+AP4_File::GetMetaData()
+{
+ if (m_MetaData == NULL) {
+ m_MetaData = new AP4_MetaData(this);
+ }
+
+ return m_MetaData;
+}
+
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.cpp
index cfaef69b3..c396b6edd 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.cpp
@@ -34,6 +34,11 @@
#include "Ap4Utils.h"
/*----------------------------------------------------------------------
+| AP4_FrmaAtom Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_FrmaAtom)
+
+/*----------------------------------------------------------------------
| AP4_FrmaAtom::AP4_FrmaAtom
+---------------------------------------------------------------------*/
AP4_FrmaAtom::AP4_FrmaAtom(AP4_UI32 original_format) :
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.h
index c6ea77a08..ccc3148af 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4FrmaAtom.h
@@ -46,6 +46,8 @@ class AP4_ByteStream;
class AP4_FrmaAtom : public AP4_Atom
{
public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_FrmaAtom, AP4_Atom)
+
// class methods
static AP4_FrmaAtom* Create(AP4_Size size, AP4_ByteStream& stream) {
return new AP4_FrmaAtom(size, stream);
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Ipmp.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Ipmp.cpp
index c3e057ae1..32ffadd34 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Ipmp.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Ipmp.cpp
@@ -85,8 +85,8 @@ AP4_Result
AP4_IpmpDescriptorPointer::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
inspector.StartElement("[IPMP_DescriptorPointer]", info);
inspector.AddField("IPMP_DescriptorID", m_DescriptorId);
if (m_DescriptorId == 0xFF) {
@@ -201,8 +201,8 @@ AP4_Result
AP4_IpmpDescriptor::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
inspector.StartElement("[IPMP_Descriptor]", info);
inspector.AddField("IPMP_DescriptorID", m_DescriptorId);
inspector.AddField("IPMPS_Type", m_IpmpsType, AP4_AtomInspector::HINT_HEX);
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.cpp
index 569ca4951..b6f3f8a7d 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.cpp
@@ -1,509 +1,509 @@
-/*****************************************************************
-|
-| AP4 - ISMA E&A Support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4IsmaCryp.h"
-#include "Ap4SchmAtom.h"
-#include "Ap4StsdAtom.h"
-#include "Ap4Sample.h"
-#include "Ap4StreamCipher.h"
-#include "Ap4IsfmAtom.h"
-#include "Ap4FrmaAtom.h"
-#include "Ap4IkmsAtom.h"
-#include "Ap4IsfmAtom.h"
-#include "Ap4IsltAtom.h"
-#include "Ap4Utils.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4HdlrAtom.h"
-
-/*----------------------------------------------------------------------
-| AP4_IsmaCipher::CreateSampleDecrypter
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaCipher::CreateSampleDecrypter(AP4_ProtectedSampleDescription* sample_description,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_IsmaCipher*& decrypter)
-{
- // check parameters
- if (key == NULL || block_cipher_factory == NULL) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
- decrypter = NULL;
-
- // create the cipher
- AP4_BlockCipher* block_cipher = NULL;
- AP4_Result result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::ENCRYPT,
- key,
- key_size,
- block_cipher);
- if (AP4_FAILED(result)) return result;
-
- // get the scheme info atom
- AP4_ContainerAtom* schi = sample_description->GetSchemeInfo()->GetSchiAtom();
- if (schi == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // get the cipher params
- AP4_IsfmAtom* isfm = AP4_DYNAMIC_CAST(AP4_IsfmAtom, schi->FindChild("iSFM"));
- if (isfm == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // get the salt
- AP4_IsltAtom* salt = AP4_DYNAMIC_CAST(AP4_IsltAtom, schi->FindChild("iSLT"));
-
- // instantiate the decrypter
- decrypter = new AP4_IsmaCipher(block_cipher,
- salt?salt->GetSalt():NULL,
- isfm->GetIvLength(),
- isfm->GetKeyIndicatorLength(),
- isfm->GetSelectiveEncryption());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaCrypCipher::AP4_IsmaCipher
-+---------------------------------------------------------------------*/
-AP4_IsmaCipher::AP4_IsmaCipher(AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt,
- AP4_UI08 iv_length,
- AP4_UI08 key_indicator_length,
- bool selective_encryption) :
- m_IvLength(iv_length),
- m_KeyIndicatorLength(key_indicator_length),
- m_SelectiveEncryption(selective_encryption)
-{
- // NOTE: we do not handle key indicators yet, so there is only one key.
-
- // left-align the salt
- unsigned char salt_128[AP4_CIPHER_BLOCK_SIZE];
- unsigned int i=0;
- if (salt) {
- for (; i<8; i++) {
- salt_128[i] = salt[i];
- }
- }
- for (; i<AP4_CIPHER_BLOCK_SIZE; i++) {
- salt_128[i] = 0;
- }
-
- // create a cipher
- m_Cipher = new AP4_CtrStreamCipher(block_cipher, salt_128, iv_length);
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaCipher::~AP4_IsmaCipher
-+---------------------------------------------------------------------*/
-AP4_IsmaCipher::~AP4_IsmaCipher()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaCipher::GetDecryptedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_IsmaCipher::GetDecryptedSampleSize(AP4_Sample& sample)
-{
- AP4_Size isma_header_size = m_KeyIndicatorLength + m_IvLength;
- if (m_SelectiveEncryption) {
- ++isma_header_size;
- }
- return sample.GetSize()-isma_header_size;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaCipher::DecryptSampleData
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaCipher::DecryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- const AP4_UI08* /*iv*/)
-{
- bool is_encrypted = true;
- const AP4_UI08* in = data_in.GetData();
- AP4_Size in_size = data_in.GetDataSize();
- AP4_Size header_size;
-
- // default to 0 output
- data_out.SetDataSize(0);
-
- // check the selective encryption flag
- if (in_size < 1) return AP4_ERROR_INVALID_FORMAT;
- if (m_SelectiveEncryption) {
- is_encrypted = ((in[0]&0x80)!=0);
- in++;
- }
-
- // check the header size
- header_size = (m_SelectiveEncryption?1:0)+
- (is_encrypted?m_KeyIndicatorLength+m_IvLength:0);
- if (header_size > in_size) return AP4_ERROR_INVALID_FORMAT;
-
- // process the sample data
- AP4_Size payload_size = in_size-header_size;
- data_out.SetDataSize(payload_size);
- AP4_UI08* out = data_out.UseData();
- if (is_encrypted) {
- // get the IV
- const AP4_UI08* iv = in;
- in += m_IvLength;
-
- // get the key indicator (we only support up to 32 bits)
- unsigned int to_read = m_KeyIndicatorLength;
- while (to_read > 4) {
- // skip anything above 4 bytes
- to_read--;
- in++;
- }
- AP4_UI32 key_indicator = 0;
- while (to_read--) {
- key_indicator = (key_indicator<<8) | *in++;
- header_size++;
- }
- // we only support key indicator = 0 for now... (TODO)
- if (key_indicator != 0) {
- return AP4_ERROR_NOT_SUPPORTED;
- }
-
- m_Cipher->SetIV(iv);
- m_Cipher->ProcessBuffer(in, payload_size, out);
- } else {
- AP4_CopyMemory(out, in, payload_size);
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaCipher::EncryptSampleData
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaCipher::EncryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- AP4_UI32 iv)
-{
- // setup the buffers
- const unsigned char* in = data_in.GetData();
- data_out.SetDataSize(data_in.GetDataSize()+4);
- unsigned char* out = data_out.UseData();
-
- // IV on 4 bytes
- AP4_BytesFromUInt32BE(out, iv);
-
- // encrypt the payload
- m_Cipher->SetIV(out);
- AP4_Size data_size = data_in.GetDataSize();
- m_Cipher->ProcessBuffer(in, data_size, out+4);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackDecrypter::Create
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaTrackDecrypter::Create(const AP4_UI08* key,
- AP4_Size key_size,
- AP4_ProtectedSampleDescription* sample_description,
- AP4_SampleEntry* sample_entry,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_IsmaTrackDecrypter*& decrypter)
-{
- // instantiate the cipher
- AP4_IsmaCipher* cipher = NULL;
- decrypter = NULL;
- AP4_Result result = AP4_IsmaCipher::CreateSampleDecrypter(sample_description,
- key,
- key_size,
- block_cipher_factory,
- cipher);
- if (AP4_FAILED(result)) return result;
-
- // instanciate the object
- decrypter = new AP4_IsmaTrackDecrypter(cipher,
- sample_entry,
- sample_description->GetOriginalFormat());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackDecrypter::AP4_IsmaTrackDecrypter
-+---------------------------------------------------------------------*/
-AP4_IsmaTrackDecrypter::AP4_IsmaTrackDecrypter(AP4_IsmaCipher* cipher,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 original_format) :
- m_Cipher(cipher),
- m_SampleEntry(sample_entry),
- m_OriginalFormat(original_format)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackDecrypter::~AP4_IsmaTrackDecrypter
-+---------------------------------------------------------------------*/
-AP4_IsmaTrackDecrypter::~AP4_IsmaTrackDecrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackDecrypter::GetProcessedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_IsmaTrackDecrypter::GetProcessedSampleSize(AP4_Sample& sample)
-{
- return m_Cipher->GetDecryptedSampleSize(sample);
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackDecrypter::ProcessTrack
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaTrackDecrypter::ProcessTrack()
-{
- m_SampleEntry->SetType(m_OriginalFormat);
- m_SampleEntry->DeleteChild(AP4_ATOM_TYPE_SINF);
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaDecrypter::ProcessSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaTrackDecrypter::ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out)
-{
- return m_Cipher->DecryptSampleData(data_in, data_out);
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackEncrypter
-+---------------------------------------------------------------------*/
-class AP4_IsmaTrackEncrypter : public AP4_Processor::TrackHandler {
-public:
- // constructor
- AP4_IsmaTrackEncrypter(const char* kms_uri,
- AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 format);
- virtual ~AP4_IsmaTrackEncrypter();
-
- // methods
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
- virtual AP4_Result ProcessTrack();
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out);
-
-private:
- // members
- AP4_String m_KmsUri;
- AP4_IsmaCipher* m_Cipher;
- AP4_SampleEntry* m_SampleEntry;
- AP4_UI32 m_Format;
- AP4_UI32 m_Counter;
-};
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackEncrypter::AP4_IsmaTrackEncrypter
-+---------------------------------------------------------------------*/
-AP4_IsmaTrackEncrypter::AP4_IsmaTrackEncrypter(
- const char* kms_uri,
- AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 format) :
- m_KmsUri(kms_uri),
- m_SampleEntry(sample_entry),
- m_Format(format),
- m_Counter(0)
-{
- // instantiate the cipher (fixed params for now)
- m_Cipher = new AP4_IsmaCipher(block_cipher, salt, 4, 0, false);
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackEncrypter::~AP4_IsmaTrackEncrypter
-+---------------------------------------------------------------------*/
-AP4_IsmaTrackEncrypter::~AP4_IsmaTrackEncrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackEncrypter::GetProcessedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_IsmaTrackEncrypter::GetProcessedSampleSize(AP4_Sample& sample)
-{
- return sample.GetSize()+4; //fixed header size for now
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackEncrypter::ProcessTrack
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaTrackEncrypter::ProcessTrack()
-{
- // sinf container
- AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
-
- // original format
- AP4_FrmaAtom* frma = new AP4_FrmaAtom(m_SampleEntry->GetType());
-
- // scheme
- AP4_SchmAtom* schm = new AP4_SchmAtom(AP4_PROTECTION_SCHEME_TYPE_IAEC, 1);
-
- // scheme info
- AP4_ContainerAtom* schi = new AP4_ContainerAtom(AP4_ATOM_TYPE_SCHI);
- AP4_IkmsAtom* ikms = new AP4_IkmsAtom(m_KmsUri.GetChars());
- AP4_IsfmAtom* isfm = new AP4_IsfmAtom(m_Cipher->GetSelectiveEncryption(),
- m_Cipher->GetKeyIndicatorLength(),
- m_Cipher->GetIvLength());
- AP4_IsltAtom* islt = new AP4_IsltAtom(m_Cipher->GetCipher()->GetIV());
-
- // populate the schi container
- schi->AddChild(ikms);
- schi->AddChild(isfm);
- schi->AddChild(islt);
-
- // populate the sinf container
- sinf->AddChild(frma);
- sinf->AddChild(schm);
- sinf->AddChild(schi);
-
- // add the sinf atom to the sample description
- m_SampleEntry->AddChild(sinf);
-
- // change the atom type of the sample description
- m_SampleEntry->SetType(m_Format);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackEncrypter::ProcessSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IsmaTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out)
-{
- AP4_Result result = m_Cipher->EncryptSampleData(data_in, data_out, m_Counter);
- if (AP4_FAILED(result)) return result;
-
- m_Counter += (data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE-1)/AP4_CIPHER_BLOCK_SIZE;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaEncryptingProcessor::AP4_IsmaEncryptingProcessor
-+---------------------------------------------------------------------*/
-AP4_IsmaEncryptingProcessor::AP4_IsmaEncryptingProcessor(const char* kms_uri,
- AP4_BlockCipherFactory* block_cipher_factory) :
- m_KmsUri(kms_uri)
-{
- if (block_cipher_factory == NULL) {
- m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
- } else {
- m_BlockCipherFactory = block_cipher_factory;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_IsmaEncryptingProcessor:CreateTrackHandler
-+---------------------------------------------------------------------*/
-AP4_Processor::TrackHandler*
-AP4_IsmaEncryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
-{
- // find the stsd atom
- AP4_StsdAtom* stsd = AP4_DYNAMIC_CAST(AP4_StsdAtom, trak->FindChild("mdia/minf/stbl/stsd"));
-
- // avoid tracks with no stsd atom (should not happen)
- if (stsd == NULL) return NULL;
-
- // only look at the first sample description
- AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
- if (entry == NULL) return NULL;
-
- // create a handler for this track if we have a key for it and we know
- // how to map the type
- const AP4_UI08* key;
- const AP4_UI08* salt;
- AP4_UI32 format = 0;
- if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, salt))) {
- switch (entry->GetType()) {
- case AP4_ATOM_TYPE_MP4A:
- format = AP4_ATOM_TYPE_ENCA;
- break;
-
- case AP4_ATOM_TYPE_MP4V:
- case AP4_ATOM_TYPE_AVC1:
- format = AP4_ATOM_TYPE_ENCV;
- break;
-
- default: {
- // try to find if this is audio or video
- AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, trak->FindChild("mdia/hdlr"));
- if (hdlr) {
- switch (hdlr->GetHandlerType()) {
- case AP4_HANDLER_TYPE_SOUN:
- format = AP4_ATOM_TYPE_ENCA;
- break;
-
- case AP4_HANDLER_TYPE_VIDE:
- format = AP4_ATOM_TYPE_ENCV;
- break;
- }
- }
- break;
- }
- }
- if (format) {
- // create the block cipher
- AP4_BlockCipher* block_cipher = NULL;
- AP4_Result result = m_BlockCipherFactory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::ENCRYPT,
- key,
- AP4_CIPHER_BLOCK_SIZE,
- block_cipher);
- if (AP4_FAILED(result)) return NULL;
-
- // create the encrypter
- return new AP4_IsmaTrackEncrypter(m_KmsUri.GetChars(),
- block_cipher,
- salt,
- entry,
- format);
- }
- }
-
- return NULL;
-}
+/*****************************************************************
+|
+| AP4 - ISMA E&A Support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4IsmaCryp.h"
+#include "Ap4SchmAtom.h"
+#include "Ap4StsdAtom.h"
+#include "Ap4Sample.h"
+#include "Ap4StreamCipher.h"
+#include "Ap4IsfmAtom.h"
+#include "Ap4FrmaAtom.h"
+#include "Ap4IkmsAtom.h"
+#include "Ap4IsfmAtom.h"
+#include "Ap4IsltAtom.h"
+#include "Ap4Utils.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4HdlrAtom.h"
+
+/*----------------------------------------------------------------------
+| AP4_IsmaCipher::CreateSampleDecrypter
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaCipher::CreateSampleDecrypter(AP4_ProtectedSampleDescription* sample_description,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_IsmaCipher*& decrypter)
+{
+ // check parameters
+ if (key == NULL || block_cipher_factory == NULL) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+ decrypter = NULL;
+
+ // create the cipher
+ AP4_BlockCipher* block_cipher = NULL;
+ AP4_Result result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::ENCRYPT,
+ key,
+ key_size,
+ block_cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // get the scheme info atom
+ AP4_ContainerAtom* schi = sample_description->GetSchemeInfo()->GetSchiAtom();
+ if (schi == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // get the cipher params
+ AP4_IsfmAtom* isfm = AP4_DYNAMIC_CAST(AP4_IsfmAtom, schi->FindChild("iSFM"));
+ if (isfm == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // get the salt
+ AP4_IsltAtom* salt = AP4_DYNAMIC_CAST(AP4_IsltAtom, schi->FindChild("iSLT"));
+
+ // instantiate the decrypter
+ decrypter = new AP4_IsmaCipher(block_cipher,
+ salt?salt->GetSalt():NULL,
+ isfm->GetIvLength(),
+ isfm->GetKeyIndicatorLength(),
+ isfm->GetSelectiveEncryption());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaCrypCipher::AP4_IsmaCipher
++---------------------------------------------------------------------*/
+AP4_IsmaCipher::AP4_IsmaCipher(AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt,
+ AP4_UI08 iv_length,
+ AP4_UI08 key_indicator_length,
+ bool selective_encryption) :
+ m_IvLength(iv_length),
+ m_KeyIndicatorLength(key_indicator_length),
+ m_SelectiveEncryption(selective_encryption)
+{
+ // NOTE: we do not handle key indicators yet, so there is only one key.
+
+ // left-align the salt
+ unsigned char salt_128[AP4_CIPHER_BLOCK_SIZE];
+ unsigned int i=0;
+ if (salt) {
+ for (; i<8; i++) {
+ salt_128[i] = salt[i];
+ }
+ }
+ for (; i<AP4_CIPHER_BLOCK_SIZE; i++) {
+ salt_128[i] = 0;
+ }
+
+ // create a cipher
+ m_Cipher = new AP4_CtrStreamCipher(block_cipher, salt_128, iv_length);
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaCipher::~AP4_IsmaCipher
++---------------------------------------------------------------------*/
+AP4_IsmaCipher::~AP4_IsmaCipher()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaCipher::GetDecryptedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_IsmaCipher::GetDecryptedSampleSize(AP4_Sample& sample)
+{
+ AP4_Size isma_header_size = m_KeyIndicatorLength + m_IvLength;
+ if (m_SelectiveEncryption) {
+ ++isma_header_size;
+ }
+ return sample.GetSize()-isma_header_size;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaCipher::DecryptSampleData
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaCipher::DecryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ const AP4_UI08* /*iv*/)
+{
+ bool is_encrypted = true;
+ const AP4_UI08* in = data_in.GetData();
+ AP4_Size in_size = data_in.GetDataSize();
+ AP4_Size header_size;
+
+ // default to 0 output
+ data_out.SetDataSize(0);
+
+ // check the selective encryption flag
+ if (in_size < 1) return AP4_ERROR_INVALID_FORMAT;
+ if (m_SelectiveEncryption) {
+ is_encrypted = ((in[0]&0x80)!=0);
+ in++;
+ }
+
+ // check the header size
+ header_size = (m_SelectiveEncryption?1:0)+
+ (is_encrypted?m_KeyIndicatorLength+m_IvLength:0);
+ if (header_size > in_size) return AP4_ERROR_INVALID_FORMAT;
+
+ // process the sample data
+ AP4_Size payload_size = in_size-header_size;
+ data_out.SetDataSize(payload_size);
+ AP4_UI08* out = data_out.UseData();
+ if (is_encrypted) {
+ // get the IV
+ const AP4_UI08* iv = in;
+ in += m_IvLength;
+
+ // get the key indicator (we only support up to 32 bits)
+ unsigned int to_read = m_KeyIndicatorLength;
+ while (to_read > 4) {
+ // skip anything above 4 bytes
+ to_read--;
+ in++;
+ }
+ AP4_UI32 key_indicator = 0;
+ while (to_read--) {
+ key_indicator = (key_indicator<<8) | *in++;
+ header_size++;
+ }
+ // we only support key indicator = 0 for now... (TODO)
+ if (key_indicator != 0) {
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+
+ m_Cipher->SetIV(iv);
+ m_Cipher->ProcessBuffer(in, payload_size, out);
+ } else {
+ AP4_CopyMemory(out, in, payload_size);
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaCipher::EncryptSampleData
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaCipher::EncryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ AP4_UI32 iv)
+{
+ // setup the buffers
+ const unsigned char* in = data_in.GetData();
+ data_out.SetDataSize(data_in.GetDataSize()+4);
+ unsigned char* out = data_out.UseData();
+
+ // IV on 4 bytes
+ AP4_BytesFromUInt32BE(out, iv);
+
+ // encrypt the payload
+ m_Cipher->SetIV(out);
+ AP4_Size data_size = data_in.GetDataSize();
+ m_Cipher->ProcessBuffer(in, data_size, out+4);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackDecrypter::Create
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaTrackDecrypter::Create(const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_ProtectedSampleDescription* sample_description,
+ AP4_SampleEntry* sample_entry,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_IsmaTrackDecrypter*& decrypter)
+{
+ // instantiate the cipher
+ AP4_IsmaCipher* cipher = NULL;
+ decrypter = NULL;
+ AP4_Result result = AP4_IsmaCipher::CreateSampleDecrypter(sample_description,
+ key,
+ key_size,
+ block_cipher_factory,
+ cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // instanciate the object
+ decrypter = new AP4_IsmaTrackDecrypter(cipher,
+ sample_entry,
+ sample_description->GetOriginalFormat());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackDecrypter::AP4_IsmaTrackDecrypter
++---------------------------------------------------------------------*/
+AP4_IsmaTrackDecrypter::AP4_IsmaTrackDecrypter(AP4_IsmaCipher* cipher,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 original_format) :
+ m_Cipher(cipher),
+ m_SampleEntry(sample_entry),
+ m_OriginalFormat(original_format)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackDecrypter::~AP4_IsmaTrackDecrypter
++---------------------------------------------------------------------*/
+AP4_IsmaTrackDecrypter::~AP4_IsmaTrackDecrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackDecrypter::GetProcessedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_IsmaTrackDecrypter::GetProcessedSampleSize(AP4_Sample& sample)
+{
+ return m_Cipher->GetDecryptedSampleSize(sample);
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackDecrypter::ProcessTrack
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaTrackDecrypter::ProcessTrack()
+{
+ m_SampleEntry->SetType(m_OriginalFormat);
+ m_SampleEntry->DeleteChild(AP4_ATOM_TYPE_SINF);
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaDecrypter::ProcessSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaTrackDecrypter::ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out)
+{
+ return m_Cipher->DecryptSampleData(data_in, data_out);
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackEncrypter
++---------------------------------------------------------------------*/
+class AP4_IsmaTrackEncrypter : public AP4_Processor::TrackHandler {
+public:
+ // constructor
+ AP4_IsmaTrackEncrypter(const char* kms_uri,
+ AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 format);
+ virtual ~AP4_IsmaTrackEncrypter();
+
+ // methods
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
+ virtual AP4_Result ProcessTrack();
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out);
+
+private:
+ // members
+ AP4_String m_KmsUri;
+ AP4_IsmaCipher* m_Cipher;
+ AP4_SampleEntry* m_SampleEntry;
+ AP4_UI32 m_Format;
+ AP4_UI32 m_Counter;
+};
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackEncrypter::AP4_IsmaTrackEncrypter
++---------------------------------------------------------------------*/
+AP4_IsmaTrackEncrypter::AP4_IsmaTrackEncrypter(
+ const char* kms_uri,
+ AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 format) :
+ m_KmsUri(kms_uri),
+ m_SampleEntry(sample_entry),
+ m_Format(format),
+ m_Counter(0)
+{
+ // instantiate the cipher (fixed params for now)
+ m_Cipher = new AP4_IsmaCipher(block_cipher, salt, 4, 0, false);
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackEncrypter::~AP4_IsmaTrackEncrypter
++---------------------------------------------------------------------*/
+AP4_IsmaTrackEncrypter::~AP4_IsmaTrackEncrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackEncrypter::GetProcessedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_IsmaTrackEncrypter::GetProcessedSampleSize(AP4_Sample& sample)
+{
+ return sample.GetSize()+4; //fixed header size for now
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackEncrypter::ProcessTrack
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaTrackEncrypter::ProcessTrack()
+{
+ // sinf container
+ AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
+
+ // original format
+ AP4_FrmaAtom* frma = new AP4_FrmaAtom(m_SampleEntry->GetType());
+
+ // scheme
+ AP4_SchmAtom* schm = new AP4_SchmAtom(AP4_PROTECTION_SCHEME_TYPE_IAEC, 1);
+
+ // scheme info
+ AP4_ContainerAtom* schi = new AP4_ContainerAtom(AP4_ATOM_TYPE_SCHI);
+ AP4_IkmsAtom* ikms = new AP4_IkmsAtom(m_KmsUri.GetChars());
+ AP4_IsfmAtom* isfm = new AP4_IsfmAtom(m_Cipher->GetSelectiveEncryption(),
+ m_Cipher->GetKeyIndicatorLength(),
+ m_Cipher->GetIvLength());
+ AP4_IsltAtom* islt = new AP4_IsltAtom(m_Cipher->GetCipher()->GetIV());
+
+ // populate the schi container
+ schi->AddChild(ikms);
+ schi->AddChild(isfm);
+ schi->AddChild(islt);
+
+ // populate the sinf container
+ sinf->AddChild(frma);
+ sinf->AddChild(schm);
+ sinf->AddChild(schi);
+
+ // add the sinf atom to the sample description
+ m_SampleEntry->AddChild(sinf);
+
+ // change the atom type of the sample description
+ m_SampleEntry->SetType(m_Format);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackEncrypter::ProcessSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IsmaTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out)
+{
+ AP4_Result result = m_Cipher->EncryptSampleData(data_in, data_out, m_Counter);
+ if (AP4_FAILED(result)) return result;
+
+ m_Counter += (data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE-1)/AP4_CIPHER_BLOCK_SIZE;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaEncryptingProcessor::AP4_IsmaEncryptingProcessor
++---------------------------------------------------------------------*/
+AP4_IsmaEncryptingProcessor::AP4_IsmaEncryptingProcessor(const char* kms_uri,
+ AP4_BlockCipherFactory* block_cipher_factory) :
+ m_KmsUri(kms_uri)
+{
+ if (block_cipher_factory == NULL) {
+ m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
+ } else {
+ m_BlockCipherFactory = block_cipher_factory;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_IsmaEncryptingProcessor:CreateTrackHandler
++---------------------------------------------------------------------*/
+AP4_Processor::TrackHandler*
+AP4_IsmaEncryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
+{
+ // find the stsd atom
+ AP4_StsdAtom* stsd = AP4_DYNAMIC_CAST(AP4_StsdAtom, trak->FindChild("mdia/minf/stbl/stsd"));
+
+ // avoid tracks with no stsd atom (should not happen)
+ if (stsd == NULL) return NULL;
+
+ // only look at the first sample description
+ AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
+ if (entry == NULL) return NULL;
+
+ // create a handler for this track if we have a key for it and we know
+ // how to map the type
+ const AP4_UI08* key;
+ const AP4_UI08* salt;
+ AP4_UI32 format = 0;
+ if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, salt))) {
+ switch (entry->GetType()) {
+ case AP4_ATOM_TYPE_MP4A:
+ format = AP4_ATOM_TYPE_ENCA;
+ break;
+
+ case AP4_ATOM_TYPE_MP4V:
+ case AP4_ATOM_TYPE_AVC1:
+ format = AP4_ATOM_TYPE_ENCV;
+ break;
+
+ default: {
+ // try to find if this is audio or video
+ AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, trak->FindChild("mdia/hdlr"));
+ if (hdlr) {
+ switch (hdlr->GetHandlerType()) {
+ case AP4_HANDLER_TYPE_SOUN:
+ format = AP4_ATOM_TYPE_ENCA;
+ break;
+
+ case AP4_HANDLER_TYPE_VIDE:
+ format = AP4_ATOM_TYPE_ENCV;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if (format) {
+ // create the block cipher
+ AP4_BlockCipher* block_cipher = NULL;
+ AP4_Result result = m_BlockCipherFactory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::ENCRYPT,
+ key,
+ AP4_CIPHER_BLOCK_SIZE,
+ block_cipher);
+ if (AP4_FAILED(result)) return NULL;
+
+ // create the encrypter
+ return new AP4_IsmaTrackEncrypter(m_KmsUri.GetChars(),
+ block_cipher,
+ salt,
+ entry,
+ format);
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.h
index 34cde13d8..8b77186fd 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4IsmaCryp.h
@@ -1,150 +1,150 @@
-/*****************************************************************
-|
-| AP4 - ISMA E&A support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-#ifndef _AP4_ISMACRYP_H_
-#define _AP4_ISMACRYP_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4SampleEntry.h"
-#include "Ap4Atom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4SampleDescription.h"
-#include "Ap4Processor.h"
-#include "Ap4Protection.h"
-
-/*----------------------------------------------------------------------
-| class references
-+---------------------------------------------------------------------*/
-class AP4_CtrStreamCipher;
-class AP4_IsfmAtom;
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_IAEC = AP4_ATOM_TYPE('i','A','E','C');
-
-/*----------------------------------------------------------------------
-| AP4_IsmaCipher
-+---------------------------------------------------------------------*/
-class AP4_IsmaCipher : public AP4_SampleDecrypter
-{
-public:
- // factory
- static AP4_Result CreateSampleDecrypter(AP4_ProtectedSampleDescription* sample_description,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_IsmaCipher*& decrypter);
-
- // constructor and destructor
- AP4_IsmaCipher(AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt,
- AP4_UI08 iv_length,
- AP4_UI08 key_indicator_length,
- bool selective_encryption);
- ~AP4_IsmaCipher();
- AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- AP4_UI32 offset);
- AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- const AP4_UI08* iv = NULL);
- AP4_Size GetDecryptedSampleSize(AP4_Sample& sample);
- AP4_CtrStreamCipher* GetCipher() { return m_Cipher; }
- AP4_UI08 GetIvLength() { return m_IvLength; }
- AP4_UI08 GetKeyIndicatorLength() { return m_KeyIndicatorLength; }
- bool GetSelectiveEncryption(){ return m_SelectiveEncryption;}
-
-private:
- // members
- AP4_CtrStreamCipher* m_Cipher;
- AP4_UI08 m_IvLength;
- AP4_UI08 m_KeyIndicatorLength;
- bool m_SelectiveEncryption;
-};
-
-/*----------------------------------------------------------------------
-| AP4_IsmaTrackDecrypter
-+---------------------------------------------------------------------*/
-class AP4_IsmaTrackDecrypter : public AP4_Processor::TrackHandler {
-public:
- // construction
- static AP4_Result Create(const AP4_UI08* key,
- AP4_Size key_size,
- AP4_ProtectedSampleDescription* sample_description,
- AP4_SampleEntry* sample_entry,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_IsmaTrackDecrypter*& decrypter);
-
- virtual ~AP4_IsmaTrackDecrypter();
-
- // methods
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
- virtual AP4_Result ProcessTrack();
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out);
-
-private:
- // constructor
- AP4_IsmaTrackDecrypter(AP4_IsmaCipher* cipher,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 original_format);
-
- // members
- AP4_IsmaCipher* m_Cipher;
- AP4_SampleEntry* m_SampleEntry;
- AP4_UI32 m_OriginalFormat;
-};
-
-/*----------------------------------------------------------------------
-| AP4_IsmaEncryptingProcessor
-+---------------------------------------------------------------------*/
-class AP4_IsmaEncryptingProcessor : public AP4_Processor
-{
-public:
- // constructors and destructor
- AP4_IsmaEncryptingProcessor(const char* kms_uri,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
-
- // accessors
- AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
-
- // methods
- virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
-
-private:
- // members
- AP4_ProtectionKeyMap m_KeyMap;
- AP4_String m_KmsUri;
- AP4_BlockCipherFactory* m_BlockCipherFactory;
-};
-
-#endif // _AP4_ISMACRYP_H_
+/*****************************************************************
+|
+| AP4 - ISMA E&A support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+#ifndef _AP4_ISMACRYP_H_
+#define _AP4_ISMACRYP_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4SampleEntry.h"
+#include "Ap4Atom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4SampleDescription.h"
+#include "Ap4Processor.h"
+#include "Ap4Protection.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class AP4_CtrStreamCipher;
+class AP4_IsfmAtom;
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_IAEC = AP4_ATOM_TYPE('i','A','E','C');
+
+/*----------------------------------------------------------------------
+| AP4_IsmaCipher
++---------------------------------------------------------------------*/
+class AP4_IsmaCipher : public AP4_SampleDecrypter
+{
+public:
+ // factory
+ static AP4_Result CreateSampleDecrypter(AP4_ProtectedSampleDescription* sample_description,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_IsmaCipher*& decrypter);
+
+ // constructor and destructor
+ AP4_IsmaCipher(AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt,
+ AP4_UI08 iv_length,
+ AP4_UI08 key_indicator_length,
+ bool selective_encryption);
+ ~AP4_IsmaCipher();
+ AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ AP4_UI32 offset);
+ AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ const AP4_UI08* iv = NULL);
+ AP4_Size GetDecryptedSampleSize(AP4_Sample& sample);
+ AP4_CtrStreamCipher* GetCipher() { return m_Cipher; }
+ AP4_UI08 GetIvLength() { return m_IvLength; }
+ AP4_UI08 GetKeyIndicatorLength() { return m_KeyIndicatorLength; }
+ bool GetSelectiveEncryption(){ return m_SelectiveEncryption;}
+
+private:
+ // members
+ AP4_CtrStreamCipher* m_Cipher;
+ AP4_UI08 m_IvLength;
+ AP4_UI08 m_KeyIndicatorLength;
+ bool m_SelectiveEncryption;
+};
+
+/*----------------------------------------------------------------------
+| AP4_IsmaTrackDecrypter
++---------------------------------------------------------------------*/
+class AP4_IsmaTrackDecrypter : public AP4_Processor::TrackHandler {
+public:
+ // construction
+ static AP4_Result Create(const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_ProtectedSampleDescription* sample_description,
+ AP4_SampleEntry* sample_entry,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_IsmaTrackDecrypter*& decrypter);
+
+ virtual ~AP4_IsmaTrackDecrypter();
+
+ // methods
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
+ virtual AP4_Result ProcessTrack();
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out);
+
+private:
+ // constructor
+ AP4_IsmaTrackDecrypter(AP4_IsmaCipher* cipher,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 original_format);
+
+ // members
+ AP4_IsmaCipher* m_Cipher;
+ AP4_SampleEntry* m_SampleEntry;
+ AP4_UI32 m_OriginalFormat;
+};
+
+/*----------------------------------------------------------------------
+| AP4_IsmaEncryptingProcessor
++---------------------------------------------------------------------*/
+class AP4_IsmaEncryptingProcessor : public AP4_Processor
+{
+public:
+ // constructors and destructor
+ AP4_IsmaEncryptingProcessor(const char* kms_uri,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+
+ // accessors
+ AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
+
+ // methods
+ virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
+
+private:
+ // members
+ AP4_ProtectionKeyMap m_KeyMap;
+ AP4_String m_KmsUri;
+ AP4_BlockCipherFactory* m_BlockCipherFactory;
+};
+
+#endif // _AP4_ISMACRYP_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4List.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4List.h
index d6a28cc63..e58bde8ad 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4List.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4List.h
@@ -1,490 +1,490 @@
-/*****************************************************************
-|
-| AP4 - Lists
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_LIST_H_
-#define _AP4_LIST_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4Results.h"
-
-/*----------------------------------------------------------------------
-| forward references
-+---------------------------------------------------------------------*/
-template <typename T> class AP4_List;
-
-/*----------------------------------------------------------------------
-| AP4_List
-+---------------------------------------------------------------------*/
-template <typename T>
-class AP4_List
-{
-public:
- // types
- class Item
- {
- public:
- // types
- class Operator
- {
- public:
- // methods
- virtual ~Operator() {}
- virtual AP4_Result Action(T* data) const = 0;
- };
-
- class Finder
- {
- public:
- // methods
- virtual ~Finder() {}
- virtual AP4_Result Test(T* data) const = 0;
- };
-
- // methods
- Item(T* data) : m_Data(data), m_Next(0), m_Prev(0) {}
- ~Item() {}
- Item* GetNext() { return m_Next; }
- Item* GetPrev() { return m_Prev; }
- T* GetData() { return m_Data; }
-
- private:
- // members
- T* m_Data;
- Item* m_Next;
- Item* m_Prev;
-
- // friends
- friend class AP4_List;
- };
-
- // methods
- AP4_List<T>(): m_ItemCount(0), m_Head(0), m_Tail(0) {}
- virtual ~AP4_List<T>();
- AP4_Result Clear();
- AP4_Result Add(T* data);
- AP4_Result Add(Item* item);
- AP4_Result Remove(T* data);
- AP4_Result Insert(Item* where, T* data);
- AP4_Result Get(AP4_Ordinal idx, T*& data) const;
- AP4_Result PopHead(T*& data);
- AP4_Result Apply(const typename Item::Operator& op) const;
- AP4_Result ApplyUntilFailure(const typename Item::Operator& op) const;
- AP4_Result ApplyUntilSuccess(const typename Item::Operator& op) const ;
- AP4_Result ReverseApply(const typename Item::Operator& op) const;
- AP4_Result Find(const typename Item::Finder& finder, T*& data) const;
- AP4_Result ReverseFind(const typename Item::Finder& finder, T*& data) const;
- AP4_Result DeleteReferences();
- AP4_Cardinal ItemCount() const { return m_ItemCount; }
- Item* FirstItem() const { return m_Head; }
- Item* LastItem() const { return m_Tail; }
-
-protected:
- // members
- AP4_Cardinal m_ItemCount;
- Item* m_Head;
- Item* m_Tail;
-
-private:
- // these cannot be used
- AP4_List<T>(const AP4_List<T>&);
- AP4_List<T>& operator=(const AP4_List<T>&);
-};
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::~AP4_List<T>
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_List<T>::~AP4_List()
-{
- Clear();
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Clear
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::Clear()
-{
- Item* item = m_Head;
-
- while (item) {
- Item* next = item->m_Next;
- delete item;
- item = next;
- }
- m_ItemCount = 0;
- m_Head = m_Tail = NULL;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Add
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::Add(T* data)
-{
- return Add(new Item(data));
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Add
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_List<T>::Add(Item* item)
-{
- // add element at the tail
- if (m_Tail) {
- item->m_Prev = m_Tail;
- item->m_Next = NULL;
- m_Tail->m_Next = item;
- m_Tail = item;
- } else {
- m_Head = item;
- m_Tail = item;
- item->m_Next = NULL;
- item->m_Prev = NULL;
- }
-
- // one more item in the list now
- m_ItemCount++;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Remove
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_List<T>::Remove(T* data)
-{
- Item* item = m_Head;
-
- while (item) {
- if (item->m_Data == data) {
- // delete item
- if (item->m_Prev) {
- // item is not the head
- if (item->m_Next) {
- // item is not the tail
- item->m_Next->m_Prev = item->m_Prev;
- item->m_Prev->m_Next = item->m_Next;
- } else {
- // item is the tail
- m_Tail = item->m_Prev;
- m_Tail->m_Next = NULL;
- }
- } else {
- // item is the head
- m_Head = item->m_Next;
- if (m_Head) {
- // item is not the tail
- m_Head->m_Prev = NULL;
- } else {
- // item is also the tail
- m_Tail = NULL;
- }
- }
-
- // delete the item
- delete item;
-
- // one less item in the list now
- m_ItemCount--;
-
- return AP4_SUCCESS;
- }
- item = item->m_Next;
- }
-
- return AP4_ERROR_NO_SUCH_ITEM;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Insert
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_List<T>::Insert(Item* where, T* data)
-{
- Item* item = new Item(data);
-
- if (where == NULL) {
- // insert as the head
- if (m_Head) {
- // replace the current head
- item->m_Prev = NULL;
- item->m_Next = m_Head;
- m_Head->m_Prev = item;
- m_Head = item;
- } else {
- // this item becomes the head and tail
- m_Head = item;
- m_Tail = item;
- item->m_Next = NULL;
- item->m_Prev = NULL;
- }
- } else {
- // insert after the 'where' item
- if (where == m_Tail) {
- // add the item at the end
- return Add(item);
- } else {
- // update the links
- item->m_Prev = where;
- item->m_Next = where->m_Next;
- where->m_Next->m_Prev = item;
- where->m_Next = item;
- }
- }
-
- // one more item in the list now
- ++m_ItemCount;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Get
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_List<T>::Get(AP4_Ordinal idx, T*& data) const
-{
- Item* item = m_Head;
-
- if (idx < m_ItemCount) {
- while (idx--) item = item->m_Next;
- data = item->m_Data;
- return AP4_SUCCESS;
- } else {
- data = NULL;
- return AP4_ERROR_NO_SUCH_ITEM;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::PopHead
-+---------------------------------------------------------------------*/
-template <typename T>
-AP4_Result
-AP4_List<T>::PopHead(T*& data)
-{
- // check that we have at least one item
- if (m_Head == NULL) {
- return AP4_ERROR_LIST_EMPTY;
- }
-
- // remove the item and return it
- data = m_Head->m_Data;
- Item* head = m_Head;
- m_Head = m_Head->m_Next;
- if (m_Head) {
- m_Head->m_Prev = NULL;
- } else {
- m_Tail = NULL;
- }
-
- // delete item
- delete head;
-
- // one less item in the list now
- m_ItemCount--;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Apply
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::Apply(const typename Item::Operator& op) const
-{
- Item* item = m_Head;
-
- while (item) {
- op.Action(item->m_Data);
- item = item->m_Next;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::ApplyUntilFailure
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::ApplyUntilFailure(const typename Item::Operator& op) const
-{
- Item* item = m_Head;
-
- while (item) {
- AP4_Result result;
- result = op.Action(item->m_Data);
- if (result != AP4_SUCCESS) return result;
- item = item->m_Next;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::ApplyUntilSuccess
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::ApplyUntilSuccess(const typename Item::Operator& op) const
-{
- Item* item = m_Head;
-
- while (item) {
- AP4_Result result;
- result = op.Action(item->m_Data);
- if (result == AP4_SUCCESS) return AP4_SUCCESS;
- item = item->m_Next;
- }
-
- return AP4_FAILURE;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::ReverseApply
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::ReverseApply(const typename Item::Operator& op) const
-{
- Item* item = m_Tail;
-
- while (item) {
- if (op.Action(item->m_Data) != AP4_SUCCESS) {
- return AP4_ERROR_LIST_OPERATION_ABORTED;
- }
- item = item->m_Prev;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::Find
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::Find(const typename Item::Finder& finder, T*& data) const
-{
- Item* item = m_Head;
-
- while (item) {
- if (finder.Test(item->m_Data) == AP4_SUCCESS) {
- data = item->m_Data;
- return AP4_SUCCESS;
- }
- item = item->m_Next;
- }
-
- data = NULL;
- return AP4_ERROR_NO_SUCH_ITEM;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::ReverseFind
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::ReverseFind(const typename Item::Finder& finder, T*& data) const
-{
- Item* item = m_Tail;
-
- while (item) {
- if (finder.Test(item->m_Data) == AP4_SUCCESS) {
- data = item->m_Data;
- return AP4_SUCCESS;
- }
- item = item->m_Prev;
- }
-
- data = NULL;
- return AP4_ERROR_NO_SUCH_ITEM;
-}
-
-/*----------------------------------------------------------------------
-| AP4_List<T>::DeleteReferences
-+---------------------------------------------------------------------*/
-template <typename T>
-inline
-AP4_Result
-AP4_List<T>::DeleteReferences()
-{
- Item* item = m_Head;
-
- while (item) {
- Item* next = item->m_Next;
- delete item->m_Data;
- delete item;
- item = next;
- }
-
- // no more items
- m_Head = m_Tail = NULL;
- m_ItemCount = 0;
-
- return AP4_SUCCESS;
-}
-
-#endif // _AP4_LIST_H_
-
-
-
-
-
-
-
-
-
-
-
-
-
+/*****************************************************************
+|
+| AP4 - Lists
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_LIST_H_
+#define _AP4_LIST_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4Results.h"
+
+/*----------------------------------------------------------------------
+| forward references
++---------------------------------------------------------------------*/
+template <typename T> class AP4_List;
+
+/*----------------------------------------------------------------------
+| AP4_List
++---------------------------------------------------------------------*/
+template <typename T>
+class AP4_List
+{
+public:
+ // types
+ class Item
+ {
+ public:
+ // types
+ class Operator
+ {
+ public:
+ // methods
+ virtual ~Operator() {}
+ virtual AP4_Result Action(T* data) const = 0;
+ };
+
+ class Finder
+ {
+ public:
+ // methods
+ virtual ~Finder() {}
+ virtual AP4_Result Test(T* data) const = 0;
+ };
+
+ // methods
+ Item(T* data) : m_Data(data), m_Next(0), m_Prev(0) {}
+ ~Item() {}
+ Item* GetNext() { return m_Next; }
+ Item* GetPrev() { return m_Prev; }
+ T* GetData() { return m_Data; }
+
+ private:
+ // members
+ T* m_Data;
+ Item* m_Next;
+ Item* m_Prev;
+
+ // friends
+ friend class AP4_List;
+ };
+
+ // methods
+ AP4_List<T>(): m_ItemCount(0), m_Head(0), m_Tail(0) {}
+ virtual ~AP4_List<T>();
+ AP4_Result Clear();
+ AP4_Result Add(T* data);
+ AP4_Result Add(Item* item);
+ AP4_Result Remove(T* data);
+ AP4_Result Insert(Item* where, T* data);
+ AP4_Result Get(AP4_Ordinal idx, T*& data) const;
+ AP4_Result PopHead(T*& data);
+ AP4_Result Apply(const typename Item::Operator& op) const;
+ AP4_Result ApplyUntilFailure(const typename Item::Operator& op) const;
+ AP4_Result ApplyUntilSuccess(const typename Item::Operator& op) const ;
+ AP4_Result ReverseApply(const typename Item::Operator& op) const;
+ AP4_Result Find(const typename Item::Finder& finder, T*& data) const;
+ AP4_Result ReverseFind(const typename Item::Finder& finder, T*& data) const;
+ AP4_Result DeleteReferences();
+ AP4_Cardinal ItemCount() const { return m_ItemCount; }
+ Item* FirstItem() const { return m_Head; }
+ Item* LastItem() const { return m_Tail; }
+
+protected:
+ // members
+ AP4_Cardinal m_ItemCount;
+ Item* m_Head;
+ Item* m_Tail;
+
+private:
+ // these cannot be used
+ AP4_List<T>(const AP4_List<T>&);
+ AP4_List<T>& operator=(const AP4_List<T>&);
+};
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::~AP4_List<T>
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_List<T>::~AP4_List()
+{
+ Clear();
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Clear
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::Clear()
+{
+ Item* item = m_Head;
+
+ while (item) {
+ Item* next = item->m_Next;
+ delete item;
+ item = next;
+ }
+ m_ItemCount = 0;
+ m_Head = m_Tail = NULL;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::Add(T* data)
+{
+ return Add(new Item(data));
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Add
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_List<T>::Add(Item* item)
+{
+ // add element at the tail
+ if (m_Tail) {
+ item->m_Prev = m_Tail;
+ item->m_Next = NULL;
+ m_Tail->m_Next = item;
+ m_Tail = item;
+ } else {
+ m_Head = item;
+ m_Tail = item;
+ item->m_Next = NULL;
+ item->m_Prev = NULL;
+ }
+
+ // one more item in the list now
+ m_ItemCount++;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Remove
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_List<T>::Remove(T* data)
+{
+ Item* item = m_Head;
+
+ while (item) {
+ if (item->m_Data == data) {
+ // delete item
+ if (item->m_Prev) {
+ // item is not the head
+ if (item->m_Next) {
+ // item is not the tail
+ item->m_Next->m_Prev = item->m_Prev;
+ item->m_Prev->m_Next = item->m_Next;
+ } else {
+ // item is the tail
+ m_Tail = item->m_Prev;
+ m_Tail->m_Next = NULL;
+ }
+ } else {
+ // item is the head
+ m_Head = item->m_Next;
+ if (m_Head) {
+ // item is not the tail
+ m_Head->m_Prev = NULL;
+ } else {
+ // item is also the tail
+ m_Tail = NULL;
+ }
+ }
+
+ // delete the item
+ delete item;
+
+ // one less item in the list now
+ m_ItemCount--;
+
+ return AP4_SUCCESS;
+ }
+ item = item->m_Next;
+ }
+
+ return AP4_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Insert
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_List<T>::Insert(Item* where, T* data)
+{
+ Item* item = new Item(data);
+
+ if (where == NULL) {
+ // insert as the head
+ if (m_Head) {
+ // replace the current head
+ item->m_Prev = NULL;
+ item->m_Next = m_Head;
+ m_Head->m_Prev = item;
+ m_Head = item;
+ } else {
+ // this item becomes the head and tail
+ m_Head = item;
+ m_Tail = item;
+ item->m_Next = NULL;
+ item->m_Prev = NULL;
+ }
+ } else {
+ // insert after the 'where' item
+ if (where == m_Tail) {
+ // add the item at the end
+ return Add(item);
+ } else {
+ // update the links
+ item->m_Prev = where;
+ item->m_Next = where->m_Next;
+ where->m_Next->m_Prev = item;
+ where->m_Next = item;
+ }
+ }
+
+ // one more item in the list now
+ ++m_ItemCount;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Get
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_List<T>::Get(AP4_Ordinal idx, T*& data) const
+{
+ Item* item = m_Head;
+
+ if (idx < m_ItemCount) {
+ while (idx--) item = item->m_Next;
+ data = item->m_Data;
+ return AP4_SUCCESS;
+ } else {
+ data = NULL;
+ return AP4_ERROR_NO_SUCH_ITEM;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::PopHead
++---------------------------------------------------------------------*/
+template <typename T>
+AP4_Result
+AP4_List<T>::PopHead(T*& data)
+{
+ // check that we have at least one item
+ if (m_Head == NULL) {
+ return AP4_ERROR_LIST_EMPTY;
+ }
+
+ // remove the item and return it
+ data = m_Head->m_Data;
+ Item* head = m_Head;
+ m_Head = m_Head->m_Next;
+ if (m_Head) {
+ m_Head->m_Prev = NULL;
+ } else {
+ m_Tail = NULL;
+ }
+
+ // delete item
+ delete head;
+
+ // one less item in the list now
+ m_ItemCount--;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Apply
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::Apply(const typename Item::Operator& op) const
+{
+ Item* item = m_Head;
+
+ while (item) {
+ op.Action(item->m_Data);
+ item = item->m_Next;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::ApplyUntilFailure
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::ApplyUntilFailure(const typename Item::Operator& op) const
+{
+ Item* item = m_Head;
+
+ while (item) {
+ AP4_Result result;
+ result = op.Action(item->m_Data);
+ if (result != AP4_SUCCESS) return result;
+ item = item->m_Next;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::ApplyUntilSuccess
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::ApplyUntilSuccess(const typename Item::Operator& op) const
+{
+ Item* item = m_Head;
+
+ while (item) {
+ AP4_Result result;
+ result = op.Action(item->m_Data);
+ if (result == AP4_SUCCESS) return AP4_SUCCESS;
+ item = item->m_Next;
+ }
+
+ return AP4_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::ReverseApply
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::ReverseApply(const typename Item::Operator& op) const
+{
+ Item* item = m_Tail;
+
+ while (item) {
+ if (op.Action(item->m_Data) != AP4_SUCCESS) {
+ return AP4_ERROR_LIST_OPERATION_ABORTED;
+ }
+ item = item->m_Prev;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::Find
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::Find(const typename Item::Finder& finder, T*& data) const
+{
+ Item* item = m_Head;
+
+ while (item) {
+ if (finder.Test(item->m_Data) == AP4_SUCCESS) {
+ data = item->m_Data;
+ return AP4_SUCCESS;
+ }
+ item = item->m_Next;
+ }
+
+ data = NULL;
+ return AP4_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::ReverseFind
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::ReverseFind(const typename Item::Finder& finder, T*& data) const
+{
+ Item* item = m_Tail;
+
+ while (item) {
+ if (finder.Test(item->m_Data) == AP4_SUCCESS) {
+ data = item->m_Data;
+ return AP4_SUCCESS;
+ }
+ item = item->m_Prev;
+ }
+
+ data = NULL;
+ return AP4_ERROR_NO_SUCH_ITEM;
+}
+
+/*----------------------------------------------------------------------
+| AP4_List<T>::DeleteReferences
++---------------------------------------------------------------------*/
+template <typename T>
+inline
+AP4_Result
+AP4_List<T>::DeleteReferences()
+{
+ Item* item = m_Head;
+
+ while (item) {
+ Item* next = item->m_Next;
+ delete item->m_Data;
+ delete item;
+ item = next;
+ }
+
+ // no more items
+ m_Head = m_Tail = NULL;
+ m_ItemCount = 0;
+
+ return AP4_SUCCESS;
+}
+
+#endif // _AP4_LIST_H_
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.cpp
index c4464f5df..009550350 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.cpp
@@ -1,990 +1,990 @@
-/*****************************************************************
-|
-| AP4 - Marlin File Format Support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4SchmAtom.h"
-#include "Ap4StsdAtom.h"
-#include "Ap4Sample.h"
-#include "Ap4StreamCipher.h"
-#include "Ap4FrmaAtom.h"
-#include "Ap4Utils.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4FtypAtom.h"
-#include "Ap4IodsAtom.h"
-#include "Ap4MoovAtom.h"
-#include "Ap4Track.h"
-#include "Ap4DescriptorFactory.h"
-#include "Ap4CommandFactory.h"
-#include "Ap4Marlin.h"
-#include "Ap4FileByteStream.h"
-#include "Ap4Ipmp.h"
-#include "Ap4AesBlockCipher.h"
-#include "Ap4SyntheticSampleTable.h"
-#include "Ap4HdlrAtom.h"
-#include "Ap4Hmac.h"
-#include "Ap4KeyWrap.h"
-#include "Ap4ByteStream.h"
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpAtomTypeHandler
-+---------------------------------------------------------------------*/
-class AP4_MarlinIpmpAtomTypeHandler : public AP4_AtomFactory::TypeHandler
-{
-public:
- // constructor
- AP4_MarlinIpmpAtomTypeHandler(AP4_AtomFactory* atom_factory) :
- m_AtomFactory(atom_factory) {}
- virtual AP4_Result CreateAtom(AP4_Atom::Type type,
- AP4_UI32 size,
- AP4_ByteStream& stream,
- AP4_Atom::Type context,
- AP4_Atom*& atom);
-
-private:
- // members
- AP4_AtomFactory* m_AtomFactory;
-};
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpAtomFactory
-+---------------------------------------------------------------------*/
-class AP4_MarlinIpmpAtomFactory : public AP4_DefaultAtomFactory
-{
-public:
- // class members
- static AP4_MarlinIpmpAtomFactory Instance;
-
- // constructor
- AP4_MarlinIpmpAtomFactory() {
- AddTypeHandler(new AP4_MarlinIpmpAtomTypeHandler(this));
- }
-};
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpAtomFactory::Instance
-+---------------------------------------------------------------------*/
-AP4_MarlinIpmpAtomFactory AP4_MarlinIpmpAtomFactory::Instance;
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpAtomTypeHandler::CreateAtom
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpAtomTypeHandler::CreateAtom(AP4_Atom::Type type,
- AP4_UI32 size,
- AP4_ByteStream& stream,
- AP4_Atom::Type /*context*/,
- AP4_Atom*& atom)
-{
- switch (type) {
- case AP4_ATOM_TYPE_SATR:
- atom = AP4_ContainerAtom::Create(type, size, false, false, stream, *m_AtomFactory);
- break;
-
- case AP4_ATOM_TYPE_STYP:
- atom = new AP4_NullTerminatedStringAtom(type, size, stream);
- break;
-
- default:
- atom = NULL;
- }
-
- return atom ? AP4_SUCCESS : AP4_FAILURE;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpParser:Parse
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpParser::Parse(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- AP4_List<SinfEntry>& sinf_entries,
- bool remove_od_data)
-{
- // check the file type
- AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
- if (ftyp == NULL ||
- (ftyp->GetMajorBrand() != AP4_MARLIN_BRAND_MGSV && !ftyp->HasCompatibleBrand(AP4_MARLIN_BRAND_MGSV))) {
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // check the initial object descriptor and get the OD Track ID
- AP4_IodsAtom* iods = AP4_DYNAMIC_CAST(AP4_IodsAtom, top_level.FindChild("moov/iods"));
- AP4_UI32 od_track_id = 0;
- if (iods == NULL) return AP4_ERROR_INVALID_FORMAT;
- const AP4_ObjectDescriptor* od = iods->GetObjectDescriptor();
- if (od == NULL) return AP4_ERROR_INVALID_FORMAT;
- AP4_EsIdIncDescriptor* es_id_inc = AP4_DYNAMIC_CAST(AP4_EsIdIncDescriptor, od->FindSubDescriptor(AP4_DESCRIPTOR_TAG_ES_ID_INC));
- if (es_id_inc == NULL) return AP4_ERROR_INVALID_FORMAT;
- od_track_id = es_id_inc->GetTrackId();
-
- // find the track pointed to by the descriptor
- AP4_MoovAtom* moov = AP4_DYNAMIC_CAST(AP4_MoovAtom, top_level.GetChild(AP4_ATOM_TYPE_MOOV));
- if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
- AP4_TrakAtom* od_trak = NULL;
- for (AP4_List<AP4_TrakAtom>::Item* trak_item = moov->GetTrakAtoms().FirstItem();
- trak_item;
- trak_item = trak_item->GetNext()) {
- AP4_TrakAtom* trak = trak_item->GetData();
- if (trak) {
- if (trak->GetId() == od_track_id) {
- od_trak = trak;
- } else {
- sinf_entries.Add(new SinfEntry(trak->GetId(), NULL));
- }
- }
- }
-
- // check that we have found the OD track
- if (od_trak == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // look for the 'mpod' trak references
- AP4_TrefTypeAtom* track_references;
- track_references = AP4_DYNAMIC_CAST(AP4_TrefTypeAtom, od_trak->FindChild("tref/mpod"));
- if (track_references == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // create an AP4_Track object from the trak atom and check that it has samples
- AP4_Track* od_track = new AP4_Track(*od_trak, stream, 0);
- if (od_track->GetSampleCount() < 1) {
- delete od_track;
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // get the first sample (in this version, we only look at a single OD command)
- AP4_Sample od_sample;
- AP4_Result result = od_track->GetSample(0, od_sample);
- if (AP4_FAILED(result)) {
- delete od_track;
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // adapt the sample data into a byte stream for parsing
- AP4_DataBuffer sample_data;
- od_sample.ReadData(sample_data);
- AP4_MemoryByteStream* sample_stream = new AP4_MemoryByteStream(sample_data);
-
- // look for one ObjectDescriptorUpdate command and
- // one IPMP_DescriptorUpdate command
- AP4_DescriptorUpdateCommand* od_update = NULL;
- AP4_DescriptorUpdateCommand* ipmp_update = NULL;
- do {
- AP4_Command* command = NULL;
- result = AP4_CommandFactory::CreateCommandFromStream(*sample_stream, command);
- if (AP4_SUCCEEDED(result)) {
- // found a command in the sample, check the type
- switch (command->GetTag()) {
- case AP4_COMMAND_TAG_OBJECT_DESCRIPTOR_UPDATE:
- if (od_update == NULL) {
- od_update = AP4_DYNAMIC_CAST(AP4_DescriptorUpdateCommand, command);
- }
- break;
-
- case AP4_COMMAND_TAG_IPMP_DESCRIPTOR_UPDATE:
- if (ipmp_update == NULL) {
- ipmp_update = AP4_DYNAMIC_CAST(AP4_DescriptorUpdateCommand, command);
- }
- break;
-
- default:
- break;
- }
- }
- } while (AP4_SUCCEEDED(result));
- sample_stream->Release();
- sample_stream = NULL;
-
- // check that we have what we need
- if (od_update == NULL || ipmp_update == NULL) {
- delete od_track;
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // process all the object descriptors in the od update
- for (AP4_List<AP4_Descriptor>::Item* od_item = od_update->GetDescriptors().FirstItem();
- od_item;
- od_item = od_item->GetNext()) {
- od = AP4_DYNAMIC_CAST(AP4_ObjectDescriptor, od_item->GetData());
- if (od == NULL) continue;
-
- // find which track this od references
- AP4_EsIdRefDescriptor* es_id_ref;
- es_id_ref = AP4_DYNAMIC_CAST(AP4_EsIdRefDescriptor, od->FindSubDescriptor(AP4_DESCRIPTOR_TAG_ES_ID_REF));
- if (es_id_ref == NULL ||
- es_id_ref->GetRefIndex() > track_references->GetTrackIds().ItemCount() ||
- es_id_ref->GetRefIndex() == 0) {
- continue;
- }
- AP4_UI32 track_id = track_references->GetTrackIds()[es_id_ref->GetRefIndex()-1];
- SinfEntry* sinf_entry = NULL;
- for (AP4_List<SinfEntry>::Item* sinf_entry_item = sinf_entries.FirstItem();
- sinf_entry_item;
- sinf_entry_item = sinf_entry_item->GetNext()) {
- sinf_entry = sinf_entry_item->GetData();
- if (sinf_entry->m_TrackId == track_id) {
- break; // match
- } else {
- sinf_entry = NULL; // no match
- }
- }
- if (sinf_entry == NULL) continue; // no matching entry
- if (sinf_entry->m_Sinf != NULL) continue; // entry already populated
-
- // see what ipmp descriptor this od points to
- AP4_IpmpDescriptorPointer* ipmpd_pointer;
- ipmpd_pointer = AP4_DYNAMIC_CAST(AP4_IpmpDescriptorPointer, od->FindSubDescriptor(AP4_DESCRIPTOR_TAG_IPMP_DESCRIPTOR_POINTER));
- if (ipmpd_pointer == NULL) continue; // no pointer
-
- // find the ipmp descriptor referenced by the pointer
- AP4_IpmpDescriptor* ipmpd = NULL;
- for (AP4_List<AP4_Descriptor>::Item* ipmpd_item = ipmp_update->GetDescriptors().FirstItem();
- ipmpd_item;
- ipmpd_item = ipmpd_item->GetNext()) {
- // check that this descriptor is of the right type
- ipmpd = AP4_DYNAMIC_CAST(AP4_IpmpDescriptor, ipmpd_item->GetData());
- if (ipmpd == NULL || ipmpd->GetIpmpsType() != AP4_MARLIN_IPMPS_TYPE_MGSV) continue;
-
- // check the descriptor id
- if (ipmpd->GetDescriptorId() == ipmpd_pointer->GetDescriptorId()) {
- break; // match
- } else {
- ipmpd = NULL; // no match
- }
- }
- if (ipmpd == NULL) continue; // no matching entry
-
- // parse the ipmp data into one or more 'sinf' atoms, and keep the one with the
- // right type
- AP4_MemoryByteStream* data = new AP4_MemoryByteStream(ipmpd->GetData().GetData(),
- ipmpd->GetData().GetDataSize());
- AP4_LargeSize bytes_available = ipmpd->GetData().GetDataSize();
- do {
- AP4_Atom* atom = NULL;
-
- // setup the factory with a context so we can instantiate a 'schm'
- // atom with a slightly different format than the standard 'schm'
- AP4_AtomFactory* factory = &AP4_MarlinIpmpAtomFactory::Instance;
- factory->PushContext(AP4_ATOM_TYPE('m','r','l','n'));
-
- // parse the next atom in the stream
- result = factory->CreateAtomFromStream(*data, bytes_available, atom);
- factory->PopContext();
- if (AP4_FAILED(result) || atom == NULL) break;
-
- // check that what we have parsed is indeed an 'sinf' of the right type
- if (atom->GetType() == AP4_ATOM_TYPE_SINF) {
- AP4_ContainerAtom* sinf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
- AP4_SchmAtom* schm = AP4_DYNAMIC_CAST(AP4_SchmAtom, sinf->FindChild("schm"));
- if ((schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC &&
- schm->GetSchemeVersion() == 0x0100) ||
- (schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK &&
- schm->GetSchemeVersion() == 0x0100)) {
- // store the sinf in the entry for that track
- sinf_entry->m_Sinf = sinf;
- break;
- }
- }
- delete atom;
- } while (AP4_SUCCEEDED(result));
- data->Release();
- }
-
- // get rid of entries that have no SINF
- for (AP4_List<SinfEntry>::Item* sinf_entry_item = sinf_entries.FirstItem();
- sinf_entry_item;
- sinf_entry_item = sinf_entry_item->GetNext()) {
- SinfEntry* sinf_entry = sinf_entry_item->GetData();
- if (sinf_entry->m_Sinf == NULL) {
- sinf_entries.Remove(sinf_entry);
- sinf_entry_item = sinf_entries.FirstItem();
- continue;
- }
- }
-
- // remove the iods atom and the OD track if required
- if (remove_od_data) {
- od_trak->Detach();
- delete od_trak;
- iods->Detach();
- delete iods;
- }
-
- // cleanup
- delete od_track;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpDecryptingProcessor:AP4_MarlinIpmpDecryptingProcessor
-+---------------------------------------------------------------------*/
-AP4_MarlinIpmpDecryptingProcessor::AP4_MarlinIpmpDecryptingProcessor(
- const AP4_ProtectionKeyMap* key_map, /* = NULL */
- AP4_BlockCipherFactory* block_cipher_factory /* = NULL */){
- if (key_map) {
- // copy the keys
- m_KeyMap.SetKeys(*key_map);
- }
-
- if (block_cipher_factory == NULL) {
- m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
- } else {
- m_BlockCipherFactory = block_cipher_factory;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpDecryptingProcessor::~AP4_MarlinIpmpDecryptingProcessor
-+---------------------------------------------------------------------*/
-AP4_MarlinIpmpDecryptingProcessor::~AP4_MarlinIpmpDecryptingProcessor()
-{
- m_SinfEntries.DeleteReferences();
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpDecryptingProcessor:Initialize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpDecryptingProcessor::Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- ProgressListener* /*listener*/)
-{
- return AP4_MarlinIpmpParser::Parse(top_level, stream, m_SinfEntries, true);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpDecryptingProcessor:CreateTrackHandler
-+---------------------------------------------------------------------*/
-AP4_Processor::TrackHandler*
-AP4_MarlinIpmpDecryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
-{
- // look for this track in the list of entries
- AP4_MarlinIpmpParser::SinfEntry* sinf_entry = NULL;
- for (AP4_List<AP4_MarlinIpmpParser::SinfEntry>::Item* sinf_entry_item = m_SinfEntries.FirstItem();
- sinf_entry_item;
- sinf_entry_item = sinf_entry_item->GetNext()) {
- sinf_entry = sinf_entry_item->GetData();
- if (sinf_entry->m_TrackId == trak->GetId()) {
- break; // match
- } else {
- sinf_entry = NULL; // no match
- }
- }
- if (sinf_entry == NULL) return NULL; // no matching entry
- AP4_ContainerAtom* sinf = sinf_entry->m_Sinf;
-
- // check the scheme
- bool use_group_key;
- AP4_SchmAtom* schm = AP4_DYNAMIC_CAST(AP4_SchmAtom, sinf->GetChild(AP4_ATOM_TYPE_SCHM));
- if (schm == NULL) return NULL; // no schm
- if (schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC &&
- schm->GetSchemeVersion() == 0x0100) {
- use_group_key = false;
- } else if (schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK &&
- schm->GetSchemeVersion() == 0x0100) {
- use_group_key = true;
- } else {
- // unsupported scheme
- return NULL;
- }
-
- // find the key
- const AP4_UI08* key = NULL;
- AP4_DataBuffer unwrapped_key;
- if (use_group_key) {
- const AP4_UI08* group_key = m_KeyMap.GetKey(0);
- if (group_key == NULL) return NULL; // no group key
- AP4_ContainerAtom* schi = AP4_DYNAMIC_CAST(AP4_ContainerAtom, sinf->GetChild(AP4_ATOM_TYPE_SCHI));
- if (schi == NULL) return NULL; // no schi
- AP4_Atom* gkey = schi->GetChild(AP4_ATOM_TYPE_GKEY);
- if (gkey == NULL) return NULL; // no gkey
- AP4_MemoryByteStream* gkey_data = new AP4_MemoryByteStream();
- gkey->WriteFields(*gkey_data);
- AP4_AesKeyUnwrap(group_key, gkey_data->GetData(), gkey_data->GetDataSize(), unwrapped_key);
- key = unwrapped_key.GetData();
- gkey_data->Release();
- } else {
- key = m_KeyMap.GetKey(sinf_entry->m_TrackId);
- }
- if (key == NULL) return NULL;
-
- // create the decrypter
- AP4_MarlinIpmpTrackDecrypter* decrypter = NULL;
- AP4_Result result = AP4_MarlinIpmpTrackDecrypter::Create(*m_BlockCipherFactory,
- key, decrypter);
- if (AP4_FAILED(result)) return NULL;
-
- return decrypter;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackDecrypter::Create
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpTrackDecrypter::Create(AP4_BlockCipherFactory& cipher_factory,
- const AP4_UI08* key,
- AP4_MarlinIpmpTrackDecrypter*& decrypter)
-{
- // default value
- decrypter = NULL;
-
- // create a block cipher for the decrypter
- AP4_BlockCipher* block_cipher = NULL;
- AP4_Result result = cipher_factory.Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::DECRYPT,
- key,
- AP4_AES_BLOCK_SIZE,
- block_cipher);
- if (AP4_FAILED(result)) return result;
-
- // create a CBC cipher
- AP4_CbcStreamCipher* cbc_cipher = new AP4_CbcStreamCipher(block_cipher, AP4_StreamCipher::DECRYPT);
-
- // create the track decrypter
- decrypter = new AP4_MarlinIpmpTrackDecrypter(cbc_cipher);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackDecrypter::~AP4_MarlinIpmpTrackDecrypter
-+---------------------------------------------------------------------*/
-AP4_MarlinIpmpTrackDecrypter::~AP4_MarlinIpmpTrackDecrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackDecrypter:GetProcessedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_MarlinIpmpTrackDecrypter::GetProcessedSampleSize(AP4_Sample& sample)
-{
- // with CBC, we need to decrypt the last block to know what the padding was
- AP4_Size encrypted_size = sample.GetSize()-AP4_AES_BLOCK_SIZE;
- AP4_DataBuffer encrypted;
- AP4_DataBuffer decrypted;
- AP4_Size decrypted_size = AP4_CIPHER_BLOCK_SIZE;
- if (sample.GetSize() < 2*AP4_CIPHER_BLOCK_SIZE) {
- return 0;
- }
- AP4_Size offset = sample.GetSize()-2*AP4_CIPHER_BLOCK_SIZE;
- if (AP4_FAILED(sample.ReadData(encrypted, 2*AP4_CIPHER_BLOCK_SIZE, offset))) {
- return 0;
- }
- decrypted.Reserve(decrypted_size);
- m_Cipher->SetIV(encrypted.GetData());
- if (AP4_FAILED(m_Cipher->ProcessBuffer(encrypted.GetData()+AP4_CIPHER_BLOCK_SIZE,
- AP4_CIPHER_BLOCK_SIZE,
- decrypted.UseData(),
- &decrypted_size,
- true))) {
- return 0;
- }
- unsigned int padding_size = AP4_CIPHER_BLOCK_SIZE-decrypted_size;
- return encrypted_size-padding_size;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackDecrypter:ProcessSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpTrackDecrypter::ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out)
-{
- AP4_Result result;
-
- const AP4_UI08* in = data_in.GetData();
- AP4_Size in_size = data_in.GetDataSize();
-
- // default to 0 output
- data_out.SetDataSize(0);
-
- // check that we have at least the minimum size
- if (in_size < 2*AP4_AES_BLOCK_SIZE) return AP4_ERROR_INVALID_FORMAT;
-
- // process the sample data
- AP4_Size out_size = in_size-AP4_AES_BLOCK_SIZE; // worst case
- data_out.SetDataSize(out_size);
- AP4_UI08* out = data_out.UseData();
-
- // decrypt the data
- m_Cipher->SetIV(in);
- result = m_Cipher->ProcessBuffer(in+AP4_AES_BLOCK_SIZE,
- in_size-AP4_AES_BLOCK_SIZE,
- out,
- &out_size,
- true);
- if (AP4_FAILED(result)) return result;
-
- // update the payload size
- data_out.SetDataSize(out_size);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpEncryptingProcessor::AP4_MarlinIpmpEncryptingProcessor
-+---------------------------------------------------------------------*/
-AP4_MarlinIpmpEncryptingProcessor::AP4_MarlinIpmpEncryptingProcessor(
- bool use_group_key, /* = false */
- const AP4_ProtectionKeyMap* key_map, /* = NULL */
- AP4_BlockCipherFactory* block_cipher_factory /* = NULL */) :
- m_UseGroupKey(use_group_key)
-{
- if (key_map) {
- // copy the keys
- m_KeyMap.SetKeys(*key_map);
- }
-
- if (block_cipher_factory == NULL) {
- m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
- } else {
- m_BlockCipherFactory = block_cipher_factory;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpEncryptingProcessor::Initialize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpEncryptingProcessor::Initialize(
- AP4_AtomParent& top_level,
- AP4_ByteStream& /*stream*/,
- AP4_Processor::ProgressListener* /*listener = NULL*/)
-{
- // get the moov atom
- AP4_MoovAtom* moov = AP4_DYNAMIC_CAST(AP4_MoovAtom, top_level.GetChild(AP4_ATOM_TYPE_MOOV));
- if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // deal with the file type
- AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
- if (ftyp) {
- // remove the atom, it will be replaced with a new one
- top_level.RemoveChild(ftyp);
-
- // keep the existing brand and compatible brands
- AP4_Array<AP4_UI32> compatible_brands;
- compatible_brands.EnsureCapacity(ftyp->GetCompatibleBrands().ItemCount()+1);
- for (unsigned int i=0; i<ftyp->GetCompatibleBrands().ItemCount(); i++) {
- compatible_brands.Append(ftyp->GetCompatibleBrands()[i]);
- }
-
- // add the MGSV compatible brand if it is not already there
- if (!ftyp->HasCompatibleBrand(AP4_MARLIN_BRAND_MGSV)) {
- compatible_brands.Append(AP4_MARLIN_BRAND_MGSV);
- }
-
- // create a replacement for the major brand
- AP4_FtypAtom* new_ftyp = new AP4_FtypAtom(AP4_MARLIN_BRAND_MGSV,
- 0x13c078c, //AP4_MARLIN_BRAND_MGSV_MAJOR_VERSION,
- &compatible_brands[0],
- compatible_brands.ItemCount());
- delete ftyp;
- ftyp = new_ftyp;
- } else {
- AP4_UI32 isom = AP4_FTYP_BRAND_ISOM;
- ftyp = new AP4_FtypAtom(AP4_MARLIN_BRAND_MGSV, 0, &isom, 1);
- }
-
- // insert the ftyp atom as the first child
- top_level.AddChild(ftyp, 0);
-
- // create and 'mpod' track reference atom
- AP4_TrefTypeAtom* mpod = new AP4_TrefTypeAtom(AP4_ATOM_TYPE_MPOD);
-
- // look for an available track ID, starting at 1
- unsigned int od_track_id = 0;
- unsigned int od_track_position = 0;
- for (AP4_List<AP4_TrakAtom>::Item* trak_item = moov->GetTrakAtoms().FirstItem();
- trak_item;
- trak_item = trak_item->GetNext()) {
- AP4_TrakAtom* trak = trak_item->GetData();
- if (trak) {
- od_track_position++;
- if (trak->GetId() >= od_track_id) {
- od_track_id = trak->GetId()+1;
- }
-
- // if the track is encrypted, reference it in the mpod
- if (m_KeyMap.GetKey(trak->GetId())) {
- mpod->AddTrackId(trak->GetId());
- }
-
- //m_SinfEntries.Add(new SinfEntry(trak->GetId(), NULL));
- }
- }
-
- // check that there was at least one track in the file
- if (od_track_id == 0) return AP4_ERROR_INVALID_FORMAT;
-
- // create an initial object descriptor
- AP4_InitialObjectDescriptor* iod =
- // FIXME: get real values from the property map
- new AP4_InitialObjectDescriptor(AP4_DESCRIPTOR_TAG_MP4_IOD,
- 1022, // object descriptor id
- false,
- 0xFE, // OD profile level (0xFE = No OD profile specified)
- 0xFF, // scene profile level
- 0xFE, // audio profile level
- 0xFE, // visual profile level
- 0xFF); // graphics profile
-
- // create an ES_ID_Inc subdescriptor and add it to the initial object descriptor
- AP4_EsIdIncDescriptor* es_id_inc = new AP4_EsIdIncDescriptor(od_track_id);
- iod->AddSubDescriptor(es_id_inc);
-
- // create an iods atom to hold the initial object descriptor
- AP4_IodsAtom* iods = new AP4_IodsAtom(iod);
-
- // add the iods atom to the moov atom (try to put it just after mvhd)
- int iods_position = 0;
- int item_position = 0;
- for (AP4_List<AP4_Atom>::Item* moov_item = moov->GetChildren().FirstItem();
- moov_item;
- moov_item = moov_item->GetNext()) {
- ++item_position;
- if (moov_item->GetData()->GetType() == AP4_ATOM_TYPE_MVHD) {
- iods_position = item_position;
- break;
- }
- }
- AP4_Result result = moov->AddChild(iods, iods_position);
- if (AP4_FAILED(result)) {
- delete iods;
- return result;
- }
-
- // create a sample table for the OD track
- AP4_SyntheticSampleTable* od_sample_table = new AP4_SyntheticSampleTable();
-
- // create the sample description for the OD track
- AP4_MpegSystemSampleDescription* od_sample_description;
- od_sample_description = new AP4_MpegSystemSampleDescription(AP4_STREAM_TYPE_OD,
- AP4_OTI_MPEG4_SYSTEM,
- NULL,
- 32768, // buffer size
- 1024, // max bitrate
- 512); // avg bitrate
- od_sample_table->AddSampleDescription(od_sample_description, true);
-
- // create the OD descriptor update
- AP4_DescriptorUpdateCommand od_update(AP4_COMMAND_TAG_OBJECT_DESCRIPTOR_UPDATE);
- for (unsigned int i=0; i<mpod->GetTrackIds().ItemCount(); i++) {
- AP4_ObjectDescriptor* od = new AP4_ObjectDescriptor(AP4_DESCRIPTOR_TAG_MP4_OD, 256+i); // descriptor id = 256+i
- od->AddSubDescriptor(new AP4_EsIdRefDescriptor(i+1)); // index into mpod (1-based)
- od->AddSubDescriptor(new AP4_IpmpDescriptorPointer(i+1)); // descriptor id = i+1
- od_update.AddDescriptor(od);
- }
-
- // create the IPMP descriptor update
- AP4_DescriptorUpdateCommand ipmp_update(AP4_COMMAND_TAG_IPMP_DESCRIPTOR_UPDATE);
- for (unsigned int i=0; i<mpod->GetTrackIds().ItemCount(); i++) {
- // create the ipmp descriptor
- AP4_IpmpDescriptor* ipmp_descriptor = new AP4_IpmpDescriptor(i+1, AP4_MARLIN_IPMPS_TYPE_MGSV);
-
- // create the sinf container
- AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
-
- // add the scheme type atom
- sinf->AddChild(new AP4_SchmAtom(m_UseGroupKey?
- AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK:
- AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC,
- 0x0100, NULL, true));
-
- // create the 'schi' container
- AP4_ContainerAtom* schi = new AP4_ContainerAtom(AP4_ATOM_TYPE_SCHI);
-
- // add the content ID
- const char* content_id = m_PropertyMap.GetProperty(mpod->GetTrackIds()[i], "ContentId");
- if (content_id) {
- // add the content ID (8id_)
- schi->AddChild(new AP4_NullTerminatedStringAtom(AP4_ATOM_TYPE_8ID_, content_id));
- }
-
- // add the signed attributes, if any
- const char* signed_attributes = m_PropertyMap.GetProperty(mpod->GetTrackIds()[i], "SignedAttributes");
- if (signed_attributes) {
- // decode the hex-encoded data
- unsigned int size = (unsigned int)AP4_StringLength(signed_attributes)/2;
- AP4_DataBuffer attributes_atoms;
- attributes_atoms.SetDataSize(size);
- if (AP4_SUCCEEDED(AP4_ParseHex(signed_attributes, attributes_atoms.UseData(), size))) {
- // parse all the atoms encoded in the data and add them to the 'schi' container
- AP4_MemoryByteStream* mbs = new AP4_MemoryByteStream(attributes_atoms.GetData(),
- attributes_atoms.GetDataSize());
- do {
- AP4_Atom* atom = NULL;
- result = AP4_DefaultAtomFactory::Instance.CreateAtomFromStream(*mbs, atom);
- if (AP4_SUCCEEDED(result) && atom) {
- schi->AddChild(atom);
- }
- } while (AP4_SUCCEEDED(result));
- mbs->Release();
- }
- }
-
- // find what the track type is (necessary for the next step) and the key
- const AP4_UI08* key;
- unsigned int key_size = 0;
- AP4_Track::Type track_type = AP4_Track::TYPE_UNKNOWN;
- for (AP4_List<AP4_TrakAtom>::Item* trak_item = moov->GetTrakAtoms().FirstItem();
- trak_item;
- trak_item = trak_item->GetNext()) {
- AP4_TrakAtom* trak = trak_item->GetData();
- if (trak->GetId() == mpod->GetTrackIds()[i]) {
- // find the handler type
- AP4_Atom* sub = trak->FindChild("mdia/hdlr");
- if (sub) {
- AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, sub);
- if (hdlr) {
- AP4_UI32 type = hdlr->GetHandlerType();
- if (type == AP4_HANDLER_TYPE_SOUN) {
- track_type = AP4_Track::TYPE_AUDIO;
- } else if (type == AP4_HANDLER_TYPE_VIDE) {
- track_type = AP4_Track::TYPE_VIDEO;
- }
- }
- }
-
- // find the key
- const AP4_UI08* iv = NULL;
- if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, iv))) {
- key_size = 16;
- }
-
- break;
- }
- }
-
- // group key
- if (m_UseGroupKey) {
- // find the group key
- const AP4_UI08* iv = NULL;
- const AP4_UI08* group_key;
- if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(0, group_key, iv))) {
- AP4_DataBuffer wrapped_key;
- result = AP4_AesKeyWrap(group_key, key, key_size, wrapped_key);
- if (AP4_FAILED(result)) return result;
- AP4_UnknownAtom* gkey = new AP4_UnknownAtom(AP4_ATOM_TYPE_GKEY,
- wrapped_key.GetData(),
- wrapped_key.GetDataSize());
- schi->AddChild(gkey);
- }
- }
-
- // create and add the secure attributes (satr)
- if (track_type != AP4_Track::TYPE_UNKNOWN && key != NULL && key_size != 0) {
- AP4_ContainerAtom* satr = new AP4_ContainerAtom(AP4_ATOM_TYPE_SATR);
- switch (track_type) {
- case AP4_Track::TYPE_AUDIO:
- satr->AddChild(new AP4_NullTerminatedStringAtom(AP4_ATOM_TYPE_STYP, AP4_MARLIN_IPMP_STYP_AUDIO));
- break;
- case AP4_Track::TYPE_VIDEO:
- satr->AddChild(new AP4_NullTerminatedStringAtom(AP4_ATOM_TYPE_STYP, AP4_MARLIN_IPMP_STYP_VIDEO));
- break;
- default:
- break;
- }
-
- // compute the hmac
- AP4_MemoryByteStream* mbs = new AP4_MemoryByteStream();
- satr->Write(*mbs);
- AP4_Hmac* digester = NULL;
- AP4_Hmac::Create(AP4_Hmac::SHA256, key, key_size, digester);
- digester->Update(mbs->GetData(), mbs->GetDataSize());
- AP4_DataBuffer hmac_value;
- digester->Final(hmac_value);
- AP4_Atom* hmac = new AP4_UnknownAtom(AP4_ATOM_TYPE_HMAC, hmac_value.GetData(), hmac_value.GetDataSize());
-
- schi->AddChild(satr);
- schi->AddChild(hmac);
-
- mbs->Release();
- }
-
- sinf->AddChild(schi);
-
- // serialize the sinf atom to a buffer and set it as the ipmp data
- AP4_MemoryByteStream* sinf_data = new AP4_MemoryByteStream((AP4_Size)sinf->GetSize());
- sinf->Write(*sinf_data);
- ipmp_descriptor->SetData(sinf_data->GetData(), sinf_data->GetDataSize());
- sinf_data->Release();
-
- ipmp_update.AddDescriptor(ipmp_descriptor);
- }
-
- // add the sample with the descriptors and updates
- AP4_MemoryByteStream* sample_data = new AP4_MemoryByteStream();
- od_update.Write(*sample_data);
- ipmp_update.Write(*sample_data);
- od_sample_table->AddSample(*sample_data, 0, sample_data->GetDataSize(), 0, 0, 0, 0, true);
-
- // create the OD track
- AP4_TrakAtom* od_track = new AP4_TrakAtom(od_sample_table,
- AP4_HANDLER_TYPE_ODSM,
- "Bento4 Marlin OD Handler",
- od_track_id,
- 0, 0,
- 1, 1000, 1, 0, "und",
- 0, 0);
-
- // add an entry in the processor's stream table to indicate that the
- // media data for the OD track is not in the file stream, but in our
- // memory stream.
- m_ExternalTrackData.Add(new ExternalTrackData(od_track_id, sample_data));
- sample_data->Release();
-
- // add a tref track reference atom
- AP4_ContainerAtom* tref = new AP4_ContainerAtom(AP4_ATOM_TYPE_TREF);
- tref->AddChild(mpod);
- od_track->AddChild(tref, 1); // add after 'tkhd'
-
- // add the track to the moov atoms (just after the last track)
- moov->AddChild(od_track, od_track_position);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpEncryptingProcessor::CreateTrackHandler
-+---------------------------------------------------------------------*/
-AP4_Processor::TrackHandler*
-AP4_MarlinIpmpEncryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
-{
- // create a handler for this track if we have a key for it
- const AP4_UI08* key;
- const AP4_UI08* iv;
- if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, iv))) {
- // create the track handler
- AP4_MarlinIpmpTrackEncrypter* handler = NULL;
- AP4_Result result = AP4_MarlinIpmpTrackEncrypter::Create(*m_BlockCipherFactory, key, iv, handler);
- if (AP4_FAILED(result)) return NULL;
- return handler;
- }
-
- // not encrypted
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackEncrypter::Create
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpTrackEncrypter::Create(AP4_BlockCipherFactory& cipher_factory,
- const AP4_UI08* key,
- const AP4_UI08* iv,
- AP4_MarlinIpmpTrackEncrypter*& encrypter)
-{
- // default value
- encrypter = NULL;
-
- // create a block cipher
- AP4_BlockCipher* block_cipher = NULL;
- AP4_Result result = cipher_factory.Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::ENCRYPT,
- key,
- AP4_AES_BLOCK_SIZE,
- block_cipher);
- if (AP4_FAILED(result)) return result;
-
- // create a CBC cipher
- AP4_CbcStreamCipher* cbc_cipher = new AP4_CbcStreamCipher(block_cipher, AP4_StreamCipher::ENCRYPT);
-
- // create the track encrypter
- encrypter = new AP4_MarlinIpmpTrackEncrypter(cbc_cipher, iv);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackEncrypter::AP4_MarlinIpmpTrackEncrypter
-+---------------------------------------------------------------------*/
-AP4_MarlinIpmpTrackEncrypter::AP4_MarlinIpmpTrackEncrypter(AP4_StreamCipher* cipher,
- const AP4_UI08* iv) :
- m_Cipher(cipher)
-{
- // copy the IV
- AP4_CopyMemory(m_IV, iv, AP4_AES_BLOCK_SIZE);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackEncrypter::~AP4_MarlinIpmpTrackEncrypter
-+---------------------------------------------------------------------*/
-AP4_MarlinIpmpTrackEncrypter::~AP4_MarlinIpmpTrackEncrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackEncrypter:GetProcessedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_MarlinIpmpTrackEncrypter::GetProcessedSampleSize(AP4_Sample& sample)
-{
- return AP4_CIPHER_BLOCK_SIZE*(2+(sample.GetSize()/AP4_CIPHER_BLOCK_SIZE));
-}
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackEncrypter:ProcessSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MarlinIpmpTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out)
-{
- AP4_Result result;
-
- const AP4_UI08* in = data_in.GetData();
- AP4_Size in_size = data_in.GetDataSize();
-
- // default to 0 output
- data_out.SetDataSize(0);
-
- // process the sample data
- AP4_Size out_size = AP4_CIPHER_BLOCK_SIZE*(2+(in_size/AP4_CIPHER_BLOCK_SIZE));
- data_out.SetDataSize(out_size);
- AP4_UI08* out = data_out.UseData();
-
- // write the IV
- AP4_CopyMemory(out, m_IV, AP4_CIPHER_BLOCK_SIZE);
- out_size -= AP4_CIPHER_BLOCK_SIZE;
-
- // encrypt the data
- m_Cipher->SetIV(m_IV);
- result = m_Cipher->ProcessBuffer(in,
- in_size,
- out+AP4_AES_BLOCK_SIZE,
- &out_size,
- true);
- if (AP4_FAILED(result)) return result;
-
- // update the payload size
- data_out.SetDataSize(out_size+AP4_AES_BLOCK_SIZE);
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - Marlin File Format Support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4SchmAtom.h"
+#include "Ap4StsdAtom.h"
+#include "Ap4Sample.h"
+#include "Ap4StreamCipher.h"
+#include "Ap4FrmaAtom.h"
+#include "Ap4Utils.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4FtypAtom.h"
+#include "Ap4IodsAtom.h"
+#include "Ap4MoovAtom.h"
+#include "Ap4Track.h"
+#include "Ap4DescriptorFactory.h"
+#include "Ap4CommandFactory.h"
+#include "Ap4Marlin.h"
+#include "Ap4FileByteStream.h"
+#include "Ap4Ipmp.h"
+#include "Ap4AesBlockCipher.h"
+#include "Ap4SyntheticSampleTable.h"
+#include "Ap4HdlrAtom.h"
+#include "Ap4Hmac.h"
+#include "Ap4KeyWrap.h"
+#include "Ap4ByteStream.h"
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpAtomTypeHandler
++---------------------------------------------------------------------*/
+class AP4_MarlinIpmpAtomTypeHandler : public AP4_AtomFactory::TypeHandler
+{
+public:
+ // constructor
+ AP4_MarlinIpmpAtomTypeHandler(AP4_AtomFactory* atom_factory) :
+ m_AtomFactory(atom_factory) {}
+ virtual AP4_Result CreateAtom(AP4_Atom::Type type,
+ AP4_UI32 size,
+ AP4_ByteStream& stream,
+ AP4_Atom::Type context,
+ AP4_Atom*& atom);
+
+private:
+ // members
+ AP4_AtomFactory* m_AtomFactory;
+};
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpAtomFactory
++---------------------------------------------------------------------*/
+class AP4_MarlinIpmpAtomFactory : public AP4_DefaultAtomFactory
+{
+public:
+ // class members
+ static AP4_MarlinIpmpAtomFactory Instance;
+
+ // constructor
+ AP4_MarlinIpmpAtomFactory() {
+ AddTypeHandler(new AP4_MarlinIpmpAtomTypeHandler(this));
+ }
+};
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpAtomFactory::Instance
++---------------------------------------------------------------------*/
+AP4_MarlinIpmpAtomFactory AP4_MarlinIpmpAtomFactory::Instance;
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpAtomTypeHandler::CreateAtom
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpAtomTypeHandler::CreateAtom(AP4_Atom::Type type,
+ AP4_UI32 size,
+ AP4_ByteStream& stream,
+ AP4_Atom::Type /*context*/,
+ AP4_Atom*& atom)
+{
+ switch (type) {
+ case AP4_ATOM_TYPE_SATR:
+ atom = AP4_ContainerAtom::Create(type, size, false, false, stream, *m_AtomFactory);
+ break;
+
+ case AP4_ATOM_TYPE_STYP:
+ atom = new AP4_NullTerminatedStringAtom(type, size, stream);
+ break;
+
+ default:
+ atom = NULL;
+ }
+
+ return atom ? AP4_SUCCESS : AP4_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpParser:Parse
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpParser::Parse(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ AP4_List<SinfEntry>& sinf_entries,
+ bool remove_od_data)
+{
+ // check the file type
+ AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
+ if (ftyp == NULL ||
+ (ftyp->GetMajorBrand() != AP4_MARLIN_BRAND_MGSV && !ftyp->HasCompatibleBrand(AP4_MARLIN_BRAND_MGSV))) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // check the initial object descriptor and get the OD Track ID
+ AP4_IodsAtom* iods = AP4_DYNAMIC_CAST(AP4_IodsAtom, top_level.FindChild("moov/iods"));
+ AP4_UI32 od_track_id = 0;
+ if (iods == NULL) return AP4_ERROR_INVALID_FORMAT;
+ const AP4_ObjectDescriptor* od = iods->GetObjectDescriptor();
+ if (od == NULL) return AP4_ERROR_INVALID_FORMAT;
+ AP4_EsIdIncDescriptor* es_id_inc = AP4_DYNAMIC_CAST(AP4_EsIdIncDescriptor, od->FindSubDescriptor(AP4_DESCRIPTOR_TAG_ES_ID_INC));
+ if (es_id_inc == NULL) return AP4_ERROR_INVALID_FORMAT;
+ od_track_id = es_id_inc->GetTrackId();
+
+ // find the track pointed to by the descriptor
+ AP4_MoovAtom* moov = AP4_DYNAMIC_CAST(AP4_MoovAtom, top_level.GetChild(AP4_ATOM_TYPE_MOOV));
+ if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
+ AP4_TrakAtom* od_trak = NULL;
+ for (AP4_List<AP4_TrakAtom>::Item* trak_item = moov->GetTrakAtoms().FirstItem();
+ trak_item;
+ trak_item = trak_item->GetNext()) {
+ AP4_TrakAtom* trak = trak_item->GetData();
+ if (trak) {
+ if (trak->GetId() == od_track_id) {
+ od_trak = trak;
+ } else {
+ sinf_entries.Add(new SinfEntry(trak->GetId(), NULL));
+ }
+ }
+ }
+
+ // check that we have found the OD track
+ if (od_trak == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // look for the 'mpod' trak references
+ AP4_TrefTypeAtom* track_references;
+ track_references = AP4_DYNAMIC_CAST(AP4_TrefTypeAtom, od_trak->FindChild("tref/mpod"));
+ if (track_references == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // create an AP4_Track object from the trak atom and check that it has samples
+ AP4_Track* od_track = new AP4_Track(*od_trak, stream, 0);
+ if (od_track->GetSampleCount() < 1) {
+ delete od_track;
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // get the first sample (in this version, we only look at a single OD command)
+ AP4_Sample od_sample;
+ AP4_Result result = od_track->GetSample(0, od_sample);
+ if (AP4_FAILED(result)) {
+ delete od_track;
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // adapt the sample data into a byte stream for parsing
+ AP4_DataBuffer sample_data;
+ od_sample.ReadData(sample_data);
+ AP4_MemoryByteStream* sample_stream = new AP4_MemoryByteStream(sample_data);
+
+ // look for one ObjectDescriptorUpdate command and
+ // one IPMP_DescriptorUpdate command
+ AP4_DescriptorUpdateCommand* od_update = NULL;
+ AP4_DescriptorUpdateCommand* ipmp_update = NULL;
+ do {
+ AP4_Command* command = NULL;
+ result = AP4_CommandFactory::CreateCommandFromStream(*sample_stream, command);
+ if (AP4_SUCCEEDED(result)) {
+ // found a command in the sample, check the type
+ switch (command->GetTag()) {
+ case AP4_COMMAND_TAG_OBJECT_DESCRIPTOR_UPDATE:
+ if (od_update == NULL) {
+ od_update = AP4_DYNAMIC_CAST(AP4_DescriptorUpdateCommand, command);
+ }
+ break;
+
+ case AP4_COMMAND_TAG_IPMP_DESCRIPTOR_UPDATE:
+ if (ipmp_update == NULL) {
+ ipmp_update = AP4_DYNAMIC_CAST(AP4_DescriptorUpdateCommand, command);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ } while (AP4_SUCCEEDED(result));
+ sample_stream->Release();
+ sample_stream = NULL;
+
+ // check that we have what we need
+ if (od_update == NULL || ipmp_update == NULL) {
+ delete od_track;
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // process all the object descriptors in the od update
+ for (AP4_List<AP4_Descriptor>::Item* od_item = od_update->GetDescriptors().FirstItem();
+ od_item;
+ od_item = od_item->GetNext()) {
+ od = AP4_DYNAMIC_CAST(AP4_ObjectDescriptor, od_item->GetData());
+ if (od == NULL) continue;
+
+ // find which track this od references
+ AP4_EsIdRefDescriptor* es_id_ref;
+ es_id_ref = AP4_DYNAMIC_CAST(AP4_EsIdRefDescriptor, od->FindSubDescriptor(AP4_DESCRIPTOR_TAG_ES_ID_REF));
+ if (es_id_ref == NULL ||
+ es_id_ref->GetRefIndex() > track_references->GetTrackIds().ItemCount() ||
+ es_id_ref->GetRefIndex() == 0) {
+ continue;
+ }
+ AP4_UI32 track_id = track_references->GetTrackIds()[es_id_ref->GetRefIndex()-1];
+ SinfEntry* sinf_entry = NULL;
+ for (AP4_List<SinfEntry>::Item* sinf_entry_item = sinf_entries.FirstItem();
+ sinf_entry_item;
+ sinf_entry_item = sinf_entry_item->GetNext()) {
+ sinf_entry = sinf_entry_item->GetData();
+ if (sinf_entry->m_TrackId == track_id) {
+ break; // match
+ } else {
+ sinf_entry = NULL; // no match
+ }
+ }
+ if (sinf_entry == NULL) continue; // no matching entry
+ if (sinf_entry->m_Sinf != NULL) continue; // entry already populated
+
+ // see what ipmp descriptor this od points to
+ AP4_IpmpDescriptorPointer* ipmpd_pointer;
+ ipmpd_pointer = AP4_DYNAMIC_CAST(AP4_IpmpDescriptorPointer, od->FindSubDescriptor(AP4_DESCRIPTOR_TAG_IPMP_DESCRIPTOR_POINTER));
+ if (ipmpd_pointer == NULL) continue; // no pointer
+
+ // find the ipmp descriptor referenced by the pointer
+ AP4_IpmpDescriptor* ipmpd = NULL;
+ for (AP4_List<AP4_Descriptor>::Item* ipmpd_item = ipmp_update->GetDescriptors().FirstItem();
+ ipmpd_item;
+ ipmpd_item = ipmpd_item->GetNext()) {
+ // check that this descriptor is of the right type
+ ipmpd = AP4_DYNAMIC_CAST(AP4_IpmpDescriptor, ipmpd_item->GetData());
+ if (ipmpd == NULL || ipmpd->GetIpmpsType() != AP4_MARLIN_IPMPS_TYPE_MGSV) continue;
+
+ // check the descriptor id
+ if (ipmpd->GetDescriptorId() == ipmpd_pointer->GetDescriptorId()) {
+ break; // match
+ } else {
+ ipmpd = NULL; // no match
+ }
+ }
+ if (ipmpd == NULL) continue; // no matching entry
+
+ // parse the ipmp data into one or more 'sinf' atoms, and keep the one with the
+ // right type
+ AP4_MemoryByteStream* data = new AP4_MemoryByteStream(ipmpd->GetData().GetData(),
+ ipmpd->GetData().GetDataSize());
+ AP4_LargeSize bytes_available = ipmpd->GetData().GetDataSize();
+ do {
+ AP4_Atom* atom = NULL;
+
+ // setup the factory with a context so we can instantiate a 'schm'
+ // atom with a slightly different format than the standard 'schm'
+ AP4_AtomFactory* factory = &AP4_MarlinIpmpAtomFactory::Instance;
+ factory->PushContext(AP4_ATOM_TYPE('m','r','l','n'));
+
+ // parse the next atom in the stream
+ result = factory->CreateAtomFromStream(*data, bytes_available, atom);
+ factory->PopContext();
+ if (AP4_FAILED(result) || atom == NULL) break;
+
+ // check that what we have parsed is indeed an 'sinf' of the right type
+ if (atom->GetType() == AP4_ATOM_TYPE_SINF) {
+ AP4_ContainerAtom* sinf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
+ AP4_SchmAtom* schm = AP4_DYNAMIC_CAST(AP4_SchmAtom, sinf->FindChild("schm"));
+ if ((schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC &&
+ schm->GetSchemeVersion() == 0x0100) ||
+ (schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK &&
+ schm->GetSchemeVersion() == 0x0100)) {
+ // store the sinf in the entry for that track
+ sinf_entry->m_Sinf = sinf;
+ break;
+ }
+ }
+ delete atom;
+ } while (AP4_SUCCEEDED(result));
+ data->Release();
+ }
+
+ // get rid of entries that have no SINF
+ for (AP4_List<SinfEntry>::Item* sinf_entry_item = sinf_entries.FirstItem();
+ sinf_entry_item;
+ sinf_entry_item = sinf_entry_item->GetNext()) {
+ SinfEntry* sinf_entry = sinf_entry_item->GetData();
+ if (sinf_entry->m_Sinf == NULL) {
+ sinf_entries.Remove(sinf_entry);
+ sinf_entry_item = sinf_entries.FirstItem();
+ continue;
+ }
+ }
+
+ // remove the iods atom and the OD track if required
+ if (remove_od_data) {
+ od_trak->Detach();
+ delete od_trak;
+ iods->Detach();
+ delete iods;
+ }
+
+ // cleanup
+ delete od_track;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpDecryptingProcessor:AP4_MarlinIpmpDecryptingProcessor
++---------------------------------------------------------------------*/
+AP4_MarlinIpmpDecryptingProcessor::AP4_MarlinIpmpDecryptingProcessor(
+ const AP4_ProtectionKeyMap* key_map, /* = NULL */
+ AP4_BlockCipherFactory* block_cipher_factory /* = NULL */){
+ if (key_map) {
+ // copy the keys
+ m_KeyMap.SetKeys(*key_map);
+ }
+
+ if (block_cipher_factory == NULL) {
+ m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
+ } else {
+ m_BlockCipherFactory = block_cipher_factory;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpDecryptingProcessor::~AP4_MarlinIpmpDecryptingProcessor
++---------------------------------------------------------------------*/
+AP4_MarlinIpmpDecryptingProcessor::~AP4_MarlinIpmpDecryptingProcessor()
+{
+ m_SinfEntries.DeleteReferences();
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpDecryptingProcessor:Initialize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpDecryptingProcessor::Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ ProgressListener* /*listener*/)
+{
+ return AP4_MarlinIpmpParser::Parse(top_level, stream, m_SinfEntries, true);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpDecryptingProcessor:CreateTrackHandler
++---------------------------------------------------------------------*/
+AP4_Processor::TrackHandler*
+AP4_MarlinIpmpDecryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
+{
+ // look for this track in the list of entries
+ AP4_MarlinIpmpParser::SinfEntry* sinf_entry = NULL;
+ for (AP4_List<AP4_MarlinIpmpParser::SinfEntry>::Item* sinf_entry_item = m_SinfEntries.FirstItem();
+ sinf_entry_item;
+ sinf_entry_item = sinf_entry_item->GetNext()) {
+ sinf_entry = sinf_entry_item->GetData();
+ if (sinf_entry->m_TrackId == trak->GetId()) {
+ break; // match
+ } else {
+ sinf_entry = NULL; // no match
+ }
+ }
+ if (sinf_entry == NULL) return NULL; // no matching entry
+ AP4_ContainerAtom* sinf = sinf_entry->m_Sinf;
+
+ // check the scheme
+ bool use_group_key;
+ AP4_SchmAtom* schm = AP4_DYNAMIC_CAST(AP4_SchmAtom, sinf->GetChild(AP4_ATOM_TYPE_SCHM));
+ if (schm == NULL) return NULL; // no schm
+ if (schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC &&
+ schm->GetSchemeVersion() == 0x0100) {
+ use_group_key = false;
+ } else if (schm->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK &&
+ schm->GetSchemeVersion() == 0x0100) {
+ use_group_key = true;
+ } else {
+ // unsupported scheme
+ return NULL;
+ }
+
+ // find the key
+ const AP4_UI08* key = NULL;
+ AP4_DataBuffer unwrapped_key;
+ if (use_group_key) {
+ const AP4_UI08* group_key = m_KeyMap.GetKey(0);
+ if (group_key == NULL) return NULL; // no group key
+ AP4_ContainerAtom* schi = AP4_DYNAMIC_CAST(AP4_ContainerAtom, sinf->GetChild(AP4_ATOM_TYPE_SCHI));
+ if (schi == NULL) return NULL; // no schi
+ AP4_Atom* gkey = schi->GetChild(AP4_ATOM_TYPE_GKEY);
+ if (gkey == NULL) return NULL; // no gkey
+ AP4_MemoryByteStream* gkey_data = new AP4_MemoryByteStream();
+ gkey->WriteFields(*gkey_data);
+ AP4_AesKeyUnwrap(group_key, gkey_data->GetData(), gkey_data->GetDataSize(), unwrapped_key);
+ key = unwrapped_key.GetData();
+ gkey_data->Release();
+ } else {
+ key = m_KeyMap.GetKey(sinf_entry->m_TrackId);
+ }
+ if (key == NULL) return NULL;
+
+ // create the decrypter
+ AP4_MarlinIpmpTrackDecrypter* decrypter = NULL;
+ AP4_Result result = AP4_MarlinIpmpTrackDecrypter::Create(*m_BlockCipherFactory,
+ key, decrypter);
+ if (AP4_FAILED(result)) return NULL;
+
+ return decrypter;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackDecrypter::Create
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpTrackDecrypter::Create(AP4_BlockCipherFactory& cipher_factory,
+ const AP4_UI08* key,
+ AP4_MarlinIpmpTrackDecrypter*& decrypter)
+{
+ // default value
+ decrypter = NULL;
+
+ // create a block cipher for the decrypter
+ AP4_BlockCipher* block_cipher = NULL;
+ AP4_Result result = cipher_factory.Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::DECRYPT,
+ key,
+ AP4_AES_BLOCK_SIZE,
+ block_cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // create a CBC cipher
+ AP4_CbcStreamCipher* cbc_cipher = new AP4_CbcStreamCipher(block_cipher, AP4_StreamCipher::DECRYPT);
+
+ // create the track decrypter
+ decrypter = new AP4_MarlinIpmpTrackDecrypter(cbc_cipher);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackDecrypter::~AP4_MarlinIpmpTrackDecrypter
++---------------------------------------------------------------------*/
+AP4_MarlinIpmpTrackDecrypter::~AP4_MarlinIpmpTrackDecrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackDecrypter:GetProcessedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_MarlinIpmpTrackDecrypter::GetProcessedSampleSize(AP4_Sample& sample)
+{
+ // with CBC, we need to decrypt the last block to know what the padding was
+ AP4_Size encrypted_size = sample.GetSize()-AP4_AES_BLOCK_SIZE;
+ AP4_DataBuffer encrypted;
+ AP4_DataBuffer decrypted;
+ AP4_Size decrypted_size = AP4_CIPHER_BLOCK_SIZE;
+ if (sample.GetSize() < 2*AP4_CIPHER_BLOCK_SIZE) {
+ return 0;
+ }
+ AP4_Size offset = sample.GetSize()-2*AP4_CIPHER_BLOCK_SIZE;
+ if (AP4_FAILED(sample.ReadData(encrypted, 2*AP4_CIPHER_BLOCK_SIZE, offset))) {
+ return 0;
+ }
+ decrypted.Reserve(decrypted_size);
+ m_Cipher->SetIV(encrypted.GetData());
+ if (AP4_FAILED(m_Cipher->ProcessBuffer(encrypted.GetData()+AP4_CIPHER_BLOCK_SIZE,
+ AP4_CIPHER_BLOCK_SIZE,
+ decrypted.UseData(),
+ &decrypted_size,
+ true))) {
+ return 0;
+ }
+ unsigned int padding_size = AP4_CIPHER_BLOCK_SIZE-decrypted_size;
+ return encrypted_size-padding_size;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackDecrypter:ProcessSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpTrackDecrypter::ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out)
+{
+ AP4_Result result;
+
+ const AP4_UI08* in = data_in.GetData();
+ AP4_Size in_size = data_in.GetDataSize();
+
+ // default to 0 output
+ data_out.SetDataSize(0);
+
+ // check that we have at least the minimum size
+ if (in_size < 2*AP4_AES_BLOCK_SIZE) return AP4_ERROR_INVALID_FORMAT;
+
+ // process the sample data
+ AP4_Size out_size = in_size-AP4_AES_BLOCK_SIZE; // worst case
+ data_out.SetDataSize(out_size);
+ AP4_UI08* out = data_out.UseData();
+
+ // decrypt the data
+ m_Cipher->SetIV(in);
+ result = m_Cipher->ProcessBuffer(in+AP4_AES_BLOCK_SIZE,
+ in_size-AP4_AES_BLOCK_SIZE,
+ out,
+ &out_size,
+ true);
+ if (AP4_FAILED(result)) return result;
+
+ // update the payload size
+ data_out.SetDataSize(out_size);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpEncryptingProcessor::AP4_MarlinIpmpEncryptingProcessor
++---------------------------------------------------------------------*/
+AP4_MarlinIpmpEncryptingProcessor::AP4_MarlinIpmpEncryptingProcessor(
+ bool use_group_key, /* = false */
+ const AP4_ProtectionKeyMap* key_map, /* = NULL */
+ AP4_BlockCipherFactory* block_cipher_factory /* = NULL */) :
+ m_UseGroupKey(use_group_key)
+{
+ if (key_map) {
+ // copy the keys
+ m_KeyMap.SetKeys(*key_map);
+ }
+
+ if (block_cipher_factory == NULL) {
+ m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
+ } else {
+ m_BlockCipherFactory = block_cipher_factory;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpEncryptingProcessor::Initialize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpEncryptingProcessor::Initialize(
+ AP4_AtomParent& top_level,
+ AP4_ByteStream& /*stream*/,
+ AP4_Processor::ProgressListener* /*listener = NULL*/)
+{
+ // get the moov atom
+ AP4_MoovAtom* moov = AP4_DYNAMIC_CAST(AP4_MoovAtom, top_level.GetChild(AP4_ATOM_TYPE_MOOV));
+ if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // deal with the file type
+ AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
+ if (ftyp) {
+ // remove the atom, it will be replaced with a new one
+ top_level.RemoveChild(ftyp);
+
+ // keep the existing brand and compatible brands
+ AP4_Array<AP4_UI32> compatible_brands;
+ compatible_brands.EnsureCapacity(ftyp->GetCompatibleBrands().ItemCount()+1);
+ for (unsigned int i=0; i<ftyp->GetCompatibleBrands().ItemCount(); i++) {
+ compatible_brands.Append(ftyp->GetCompatibleBrands()[i]);
+ }
+
+ // add the MGSV compatible brand if it is not already there
+ if (!ftyp->HasCompatibleBrand(AP4_MARLIN_BRAND_MGSV)) {
+ compatible_brands.Append(AP4_MARLIN_BRAND_MGSV);
+ }
+
+ // create a replacement for the major brand
+ AP4_FtypAtom* new_ftyp = new AP4_FtypAtom(AP4_MARLIN_BRAND_MGSV,
+ 0x13c078c, //AP4_MARLIN_BRAND_MGSV_MAJOR_VERSION,
+ &compatible_brands[0],
+ compatible_brands.ItemCount());
+ delete ftyp;
+ ftyp = new_ftyp;
+ } else {
+ AP4_UI32 isom = AP4_FTYP_BRAND_ISOM;
+ ftyp = new AP4_FtypAtom(AP4_MARLIN_BRAND_MGSV, 0, &isom, 1);
+ }
+
+ // insert the ftyp atom as the first child
+ top_level.AddChild(ftyp, 0);
+
+ // create and 'mpod' track reference atom
+ AP4_TrefTypeAtom* mpod = new AP4_TrefTypeAtom(AP4_ATOM_TYPE_MPOD);
+
+ // look for an available track ID, starting at 1
+ unsigned int od_track_id = 0;
+ unsigned int od_track_position = 0;
+ for (AP4_List<AP4_TrakAtom>::Item* trak_item = moov->GetTrakAtoms().FirstItem();
+ trak_item;
+ trak_item = trak_item->GetNext()) {
+ AP4_TrakAtom* trak = trak_item->GetData();
+ if (trak) {
+ od_track_position++;
+ if (trak->GetId() >= od_track_id) {
+ od_track_id = trak->GetId()+1;
+ }
+
+ // if the track is encrypted, reference it in the mpod
+ if (m_KeyMap.GetKey(trak->GetId())) {
+ mpod->AddTrackId(trak->GetId());
+ }
+
+ //m_SinfEntries.Add(new SinfEntry(trak->GetId(), NULL));
+ }
+ }
+
+ // check that there was at least one track in the file
+ if (od_track_id == 0) return AP4_ERROR_INVALID_FORMAT;
+
+ // create an initial object descriptor
+ AP4_InitialObjectDescriptor* iod =
+ // FIXME: get real values from the property map
+ new AP4_InitialObjectDescriptor(AP4_DESCRIPTOR_TAG_MP4_IOD,
+ 1022, // object descriptor id
+ false,
+ 0xFE, // OD profile level (0xFE = No OD profile specified)
+ 0xFF, // scene profile level
+ 0xFE, // audio profile level
+ 0xFE, // visual profile level
+ 0xFF); // graphics profile
+
+ // create an ES_ID_Inc subdescriptor and add it to the initial object descriptor
+ AP4_EsIdIncDescriptor* es_id_inc = new AP4_EsIdIncDescriptor(od_track_id);
+ iod->AddSubDescriptor(es_id_inc);
+
+ // create an iods atom to hold the initial object descriptor
+ AP4_IodsAtom* iods = new AP4_IodsAtom(iod);
+
+ // add the iods atom to the moov atom (try to put it just after mvhd)
+ int iods_position = 0;
+ int item_position = 0;
+ for (AP4_List<AP4_Atom>::Item* moov_item = moov->GetChildren().FirstItem();
+ moov_item;
+ moov_item = moov_item->GetNext()) {
+ ++item_position;
+ if (moov_item->GetData()->GetType() == AP4_ATOM_TYPE_MVHD) {
+ iods_position = item_position;
+ break;
+ }
+ }
+ AP4_Result result = moov->AddChild(iods, iods_position);
+ if (AP4_FAILED(result)) {
+ delete iods;
+ return result;
+ }
+
+ // create a sample table for the OD track
+ AP4_SyntheticSampleTable* od_sample_table = new AP4_SyntheticSampleTable();
+
+ // create the sample description for the OD track
+ AP4_MpegSystemSampleDescription* od_sample_description;
+ od_sample_description = new AP4_MpegSystemSampleDescription(AP4_STREAM_TYPE_OD,
+ AP4_OTI_MPEG4_SYSTEM,
+ NULL,
+ 32768, // buffer size
+ 1024, // max bitrate
+ 512); // avg bitrate
+ od_sample_table->AddSampleDescription(od_sample_description, true);
+
+ // create the OD descriptor update
+ AP4_DescriptorUpdateCommand od_update(AP4_COMMAND_TAG_OBJECT_DESCRIPTOR_UPDATE);
+ for (unsigned int i=0; i<mpod->GetTrackIds().ItemCount(); i++) {
+ AP4_ObjectDescriptor* od = new AP4_ObjectDescriptor(AP4_DESCRIPTOR_TAG_MP4_OD, 256+i); // descriptor id = 256+i
+ od->AddSubDescriptor(new AP4_EsIdRefDescriptor(i+1)); // index into mpod (1-based)
+ od->AddSubDescriptor(new AP4_IpmpDescriptorPointer(i+1)); // descriptor id = i+1
+ od_update.AddDescriptor(od);
+ }
+
+ // create the IPMP descriptor update
+ AP4_DescriptorUpdateCommand ipmp_update(AP4_COMMAND_TAG_IPMP_DESCRIPTOR_UPDATE);
+ for (unsigned int i=0; i<mpod->GetTrackIds().ItemCount(); i++) {
+ // create the ipmp descriptor
+ AP4_IpmpDescriptor* ipmp_descriptor = new AP4_IpmpDescriptor(i+1, AP4_MARLIN_IPMPS_TYPE_MGSV);
+
+ // create the sinf container
+ AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
+
+ // add the scheme type atom
+ sinf->AddChild(new AP4_SchmAtom(m_UseGroupKey?
+ AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK:
+ AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC,
+ 0x0100, NULL, true));
+
+ // create the 'schi' container
+ AP4_ContainerAtom* schi = new AP4_ContainerAtom(AP4_ATOM_TYPE_SCHI);
+
+ // add the content ID
+ const char* content_id = m_PropertyMap.GetProperty(mpod->GetTrackIds()[i], "ContentId");
+ if (content_id) {
+ // add the content ID (8id_)
+ schi->AddChild(new AP4_NullTerminatedStringAtom(AP4_ATOM_TYPE_8ID_, content_id));
+ }
+
+ // add the signed attributes, if any
+ const char* signed_attributes = m_PropertyMap.GetProperty(mpod->GetTrackIds()[i], "SignedAttributes");
+ if (signed_attributes) {
+ // decode the hex-encoded data
+ unsigned int size = (unsigned int)AP4_StringLength(signed_attributes)/2;
+ AP4_DataBuffer attributes_atoms;
+ attributes_atoms.SetDataSize(size);
+ if (AP4_SUCCEEDED(AP4_ParseHex(signed_attributes, attributes_atoms.UseData(), size))) {
+ // parse all the atoms encoded in the data and add them to the 'schi' container
+ AP4_MemoryByteStream* mbs = new AP4_MemoryByteStream(attributes_atoms.GetData(),
+ attributes_atoms.GetDataSize());
+ do {
+ AP4_Atom* atom = NULL;
+ result = AP4_DefaultAtomFactory::Instance.CreateAtomFromStream(*mbs, atom);
+ if (AP4_SUCCEEDED(result) && atom) {
+ schi->AddChild(atom);
+ }
+ } while (AP4_SUCCEEDED(result));
+ mbs->Release();
+ }
+ }
+
+ // find what the track type is (necessary for the next step) and the key
+ const AP4_UI08* key;
+ unsigned int key_size = 0;
+ AP4_Track::Type track_type = AP4_Track::TYPE_UNKNOWN;
+ for (AP4_List<AP4_TrakAtom>::Item* trak_item = moov->GetTrakAtoms().FirstItem();
+ trak_item;
+ trak_item = trak_item->GetNext()) {
+ AP4_TrakAtom* trak = trak_item->GetData();
+ if (trak->GetId() == mpod->GetTrackIds()[i]) {
+ // find the handler type
+ AP4_Atom* sub = trak->FindChild("mdia/hdlr");
+ if (sub) {
+ AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, sub);
+ if (hdlr) {
+ AP4_UI32 type = hdlr->GetHandlerType();
+ if (type == AP4_HANDLER_TYPE_SOUN) {
+ track_type = AP4_Track::TYPE_AUDIO;
+ } else if (type == AP4_HANDLER_TYPE_VIDE) {
+ track_type = AP4_Track::TYPE_VIDEO;
+ }
+ }
+ }
+
+ // find the key
+ const AP4_UI08* iv = NULL;
+ if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, iv))) {
+ key_size = 16;
+ }
+
+ break;
+ }
+ }
+
+ // group key
+ if (m_UseGroupKey) {
+ // find the group key
+ const AP4_UI08* iv = NULL;
+ const AP4_UI08* group_key;
+ if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(0, group_key, iv))) {
+ AP4_DataBuffer wrapped_key;
+ result = AP4_AesKeyWrap(group_key, key, key_size, wrapped_key);
+ if (AP4_FAILED(result)) return result;
+ AP4_UnknownAtom* gkey = new AP4_UnknownAtom(AP4_ATOM_TYPE_GKEY,
+ wrapped_key.GetData(),
+ wrapped_key.GetDataSize());
+ schi->AddChild(gkey);
+ }
+ }
+
+ // create and add the secure attributes (satr)
+ if (track_type != AP4_Track::TYPE_UNKNOWN && key != NULL && key_size != 0) {
+ AP4_ContainerAtom* satr = new AP4_ContainerAtom(AP4_ATOM_TYPE_SATR);
+ switch (track_type) {
+ case AP4_Track::TYPE_AUDIO:
+ satr->AddChild(new AP4_NullTerminatedStringAtom(AP4_ATOM_TYPE_STYP, AP4_MARLIN_IPMP_STYP_AUDIO));
+ break;
+ case AP4_Track::TYPE_VIDEO:
+ satr->AddChild(new AP4_NullTerminatedStringAtom(AP4_ATOM_TYPE_STYP, AP4_MARLIN_IPMP_STYP_VIDEO));
+ break;
+ default:
+ break;
+ }
+
+ // compute the hmac
+ AP4_MemoryByteStream* mbs = new AP4_MemoryByteStream();
+ satr->Write(*mbs);
+ AP4_Hmac* digester = NULL;
+ AP4_Hmac::Create(AP4_Hmac::SHA256, key, key_size, digester);
+ digester->Update(mbs->GetData(), mbs->GetDataSize());
+ AP4_DataBuffer hmac_value;
+ digester->Final(hmac_value);
+ AP4_Atom* hmac = new AP4_UnknownAtom(AP4_ATOM_TYPE_HMAC, hmac_value.GetData(), hmac_value.GetDataSize());
+
+ schi->AddChild(satr);
+ schi->AddChild(hmac);
+
+ mbs->Release();
+ }
+
+ sinf->AddChild(schi);
+
+ // serialize the sinf atom to a buffer and set it as the ipmp data
+ AP4_MemoryByteStream* sinf_data = new AP4_MemoryByteStream((AP4_Size)sinf->GetSize());
+ sinf->Write(*sinf_data);
+ ipmp_descriptor->SetData(sinf_data->GetData(), sinf_data->GetDataSize());
+ sinf_data->Release();
+
+ ipmp_update.AddDescriptor(ipmp_descriptor);
+ }
+
+ // add the sample with the descriptors and updates
+ AP4_MemoryByteStream* sample_data = new AP4_MemoryByteStream();
+ od_update.Write(*sample_data);
+ ipmp_update.Write(*sample_data);
+ od_sample_table->AddSample(*sample_data, 0, sample_data->GetDataSize(), 0, 0, 0, 0, true);
+
+ // create the OD track
+ AP4_TrakAtom* od_track = new AP4_TrakAtom(od_sample_table,
+ AP4_HANDLER_TYPE_ODSM,
+ "Bento4 Marlin OD Handler",
+ od_track_id,
+ 0, 0,
+ 1, 1000, 1, 0, "und",
+ 0, 0);
+
+ // add an entry in the processor's stream table to indicate that the
+ // media data for the OD track is not in the file stream, but in our
+ // memory stream.
+ m_ExternalTrackData.Add(new ExternalTrackData(od_track_id, sample_data));
+ sample_data->Release();
+
+ // add a tref track reference atom
+ AP4_ContainerAtom* tref = new AP4_ContainerAtom(AP4_ATOM_TYPE_TREF);
+ tref->AddChild(mpod);
+ od_track->AddChild(tref, 1); // add after 'tkhd'
+
+ // add the track to the moov atoms (just after the last track)
+ moov->AddChild(od_track, od_track_position);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpEncryptingProcessor::CreateTrackHandler
++---------------------------------------------------------------------*/
+AP4_Processor::TrackHandler*
+AP4_MarlinIpmpEncryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
+{
+ // create a handler for this track if we have a key for it
+ const AP4_UI08* key;
+ const AP4_UI08* iv;
+ if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, iv))) {
+ // create the track handler
+ AP4_MarlinIpmpTrackEncrypter* handler = NULL;
+ AP4_Result result = AP4_MarlinIpmpTrackEncrypter::Create(*m_BlockCipherFactory, key, iv, handler);
+ if (AP4_FAILED(result)) return NULL;
+ return handler;
+ }
+
+ // not encrypted
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackEncrypter::Create
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpTrackEncrypter::Create(AP4_BlockCipherFactory& cipher_factory,
+ const AP4_UI08* key,
+ const AP4_UI08* iv,
+ AP4_MarlinIpmpTrackEncrypter*& encrypter)
+{
+ // default value
+ encrypter = NULL;
+
+ // create a block cipher
+ AP4_BlockCipher* block_cipher = NULL;
+ AP4_Result result = cipher_factory.Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::ENCRYPT,
+ key,
+ AP4_AES_BLOCK_SIZE,
+ block_cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // create a CBC cipher
+ AP4_CbcStreamCipher* cbc_cipher = new AP4_CbcStreamCipher(block_cipher, AP4_StreamCipher::ENCRYPT);
+
+ // create the track encrypter
+ encrypter = new AP4_MarlinIpmpTrackEncrypter(cbc_cipher, iv);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackEncrypter::AP4_MarlinIpmpTrackEncrypter
++---------------------------------------------------------------------*/
+AP4_MarlinIpmpTrackEncrypter::AP4_MarlinIpmpTrackEncrypter(AP4_StreamCipher* cipher,
+ const AP4_UI08* iv) :
+ m_Cipher(cipher)
+{
+ // copy the IV
+ AP4_CopyMemory(m_IV, iv, AP4_AES_BLOCK_SIZE);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackEncrypter::~AP4_MarlinIpmpTrackEncrypter
++---------------------------------------------------------------------*/
+AP4_MarlinIpmpTrackEncrypter::~AP4_MarlinIpmpTrackEncrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackEncrypter:GetProcessedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_MarlinIpmpTrackEncrypter::GetProcessedSampleSize(AP4_Sample& sample)
+{
+ return AP4_CIPHER_BLOCK_SIZE*(2+(sample.GetSize()/AP4_CIPHER_BLOCK_SIZE));
+}
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackEncrypter:ProcessSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MarlinIpmpTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out)
+{
+ AP4_Result result;
+
+ const AP4_UI08* in = data_in.GetData();
+ AP4_Size in_size = data_in.GetDataSize();
+
+ // default to 0 output
+ data_out.SetDataSize(0);
+
+ // process the sample data
+ AP4_Size out_size = AP4_CIPHER_BLOCK_SIZE*(2+(in_size/AP4_CIPHER_BLOCK_SIZE));
+ data_out.SetDataSize(out_size);
+ AP4_UI08* out = data_out.UseData();
+
+ // write the IV
+ AP4_CopyMemory(out, m_IV, AP4_CIPHER_BLOCK_SIZE);
+ out_size -= AP4_CIPHER_BLOCK_SIZE;
+
+ // encrypt the data
+ m_Cipher->SetIV(m_IV);
+ result = m_Cipher->ProcessBuffer(in,
+ in_size,
+ out+AP4_AES_BLOCK_SIZE,
+ &out_size,
+ true);
+ if (AP4_FAILED(result)) return result;
+
+ // update the payload size
+ data_out.SetDataSize(out_size+AP4_AES_BLOCK_SIZE);
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.h
index 7e1b428d6..30e67e476 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Marlin.h
@@ -1,203 +1,204 @@
-/*****************************************************************
-|
-| AP4 - Marlin File Format support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-#ifndef _AP4_MARLIN_H_
-#define _AP4_MARLIN_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4SampleEntry.h"
-#include "Ap4Atom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4SampleDescription.h"
-#include "Ap4Processor.h"
-#include "Ap4Protection.h"
-#include "Ap4TrefTypeAtom.h"
-#include "Ap4ObjectDescriptor.h"
-#include "Ap4Command.h"
-#include "Ap4UuidAtom.h"
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_UI32 AP4_MARLIN_BRAND_MGSV = AP4_ATOM_TYPE('M','G','S','V');
-const AP4_UI16 AP4_MARLIN_IPMPS_TYPE_MGSV = 0xA551;
-const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC = AP4_ATOM_TYPE('A','C','B','C');
-const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK = AP4_ATOM_TYPE('A','C','G','K');
-
-const AP4_Atom::Type AP4_ATOM_TYPE_SATR = AP4_ATOM_TYPE('s','a','t','r');
-const AP4_Atom::Type AP4_ATOM_TYPE_STYP = AP4_ATOM_TYPE('s','t','y','p');
-const AP4_Atom::Type AP4_ATOM_TYPE_HMAC = AP4_ATOM_TYPE('h','m','a','c');
-const AP4_Atom::Type AP4_ATOM_TYPE_GKEY = AP4_ATOM_TYPE('g','k','e','y');
-
-const char* const AP4_MARLIN_IPMP_STYP_VIDEO = "urn:marlin:organization:sne:content-type:video";
-const char* const AP4_MARLIN_IPMP_STYP_AUDIO = "urn:marlin:organization:sne:content-type:audio";
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpParser
-+---------------------------------------------------------------------*/
-class AP4_MarlinIpmpParser
-{
-public:
- // types
- struct SinfEntry {
- SinfEntry(AP4_UI32 track_id, AP4_ContainerAtom* sinf) :
- m_TrackId(track_id), m_Sinf(sinf) {}
- ~SinfEntry() { delete m_Sinf; }
- AP4_UI32 m_TrackId;
- AP4_ContainerAtom* m_Sinf;
- };
-
- // methods
- static AP4_Result Parse(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- AP4_List<SinfEntry>& sinf_entries,
- bool remove_od_data=false);
-
-private:
- AP4_MarlinIpmpParser() {} // this class can't be instantiated
-};
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpDecryptingProcessor
-+---------------------------------------------------------------------*/
-class AP4_MarlinIpmpDecryptingProcessor : public AP4_Processor
-{
-public:
- // constructor and destructor
- AP4_MarlinIpmpDecryptingProcessor(const AP4_ProtectionKeyMap* key_map = NULL,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
- ~AP4_MarlinIpmpDecryptingProcessor();
-
- // accessors
- AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
-
- // methods
- virtual AP4_Result Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- ProgressListener* listener);
- virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
-
-private:
-
- // members
- AP4_BlockCipherFactory* m_BlockCipherFactory;
- AP4_ProtectionKeyMap m_KeyMap;
- AP4_List<AP4_MarlinIpmpParser::SinfEntry> m_SinfEntries;
-};
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackDecrypter
-+---------------------------------------------------------------------*/
-class AP4_MarlinIpmpTrackDecrypter : public AP4_Processor::TrackHandler
-{
-public:
- // class methods
- static AP4_Result Create(AP4_BlockCipherFactory& cipher_factory,
- const AP4_UI08* key,
- AP4_MarlinIpmpTrackDecrypter*& decrypter);
-
- // destructor
- ~AP4_MarlinIpmpTrackDecrypter();
-
- // AP4_Processor::TrackHandler methods
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out);
-
-
-private:
- // constructor
- AP4_MarlinIpmpTrackDecrypter(AP4_StreamCipher* cipher) : m_Cipher(cipher) {}
-
- // members
- AP4_StreamCipher* m_Cipher;
-};
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpEncryptingProcessor
-+---------------------------------------------------------------------*/
-class AP4_MarlinIpmpEncryptingProcessor : public AP4_Processor
-{
-public:
- // constructor
- AP4_MarlinIpmpEncryptingProcessor(bool use_group_key = false,
- const AP4_ProtectionKeyMap* key_map = NULL,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
-
- // accessors
- AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
- AP4_TrackPropertyMap& GetPropertyMap() { return m_PropertyMap; }
-
- // AP4_Processor methods
- virtual AP4_Result Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- AP4_Processor::ProgressListener* listener = NULL);
- virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
-
-private:
- // members
- AP4_BlockCipherFactory* m_BlockCipherFactory;
- bool m_UseGroupKey;
- AP4_ProtectionKeyMap m_KeyMap;
- AP4_TrackPropertyMap m_PropertyMap;
-};
-
-/*----------------------------------------------------------------------
-| AP4_MarlinIpmpTrackEncrypter
-+---------------------------------------------------------------------*/
-class AP4_MarlinIpmpTrackEncrypter : public AP4_Processor::TrackHandler
-{
-public:
- // class methods
- static AP4_Result Create(AP4_BlockCipherFactory& cipher_factory,
- const AP4_UI08* key,
- const AP4_UI08* iv,
- AP4_MarlinIpmpTrackEncrypter*& encrypter);
-
- // destructor
- ~AP4_MarlinIpmpTrackEncrypter();
-
- // AP4_Processor::TrackHandler methods
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out);
-
-
-private:
- // constructor
- AP4_MarlinIpmpTrackEncrypter(AP4_StreamCipher* cipher, const AP4_UI08* iv);
-
- // members
- AP4_UI08 m_IV[16];
- AP4_StreamCipher* m_Cipher;
-};
-
-#endif // _AP4_MARLIN_H_
+/*****************************************************************
+|
+| AP4 - Marlin File Format support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+#ifndef _AP4_MARLIN_H_
+#define _AP4_MARLIN_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4SampleEntry.h"
+#include "Ap4Atom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4SampleDescription.h"
+#include "Ap4Processor.h"
+#include "Ap4Protection.h"
+#include "Ap4TrefTypeAtom.h"
+#include "Ap4ObjectDescriptor.h"
+#include "Ap4Command.h"
+#include "Ap4UuidAtom.h"
+#include "Ap4OmaDcf.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_UI32 AP4_MARLIN_BRAND_MGSV = AP4_ATOM_TYPE('M','G','S','V');
+const AP4_UI16 AP4_MARLIN_IPMPS_TYPE_MGSV = 0xA551;
+const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACBC = AP4_ATOM_TYPE('A','C','B','C');
+const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_MARLIN_ACGK = AP4_ATOM_TYPE('A','C','G','K');
+
+const AP4_Atom::Type AP4_ATOM_TYPE_SATR = AP4_ATOM_TYPE('s','a','t','r');
+const AP4_Atom::Type AP4_ATOM_TYPE_STYP = AP4_ATOM_TYPE('s','t','y','p');
+const AP4_Atom::Type AP4_ATOM_TYPE_HMAC = AP4_ATOM_TYPE('h','m','a','c');
+const AP4_Atom::Type AP4_ATOM_TYPE_GKEY = AP4_ATOM_TYPE('g','k','e','y');
+
+const char* const AP4_MARLIN_IPMP_STYP_VIDEO = "urn:marlin:organization:sne:content-type:video";
+const char* const AP4_MARLIN_IPMP_STYP_AUDIO = "urn:marlin:organization:sne:content-type:audio";
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpParser
++---------------------------------------------------------------------*/
+class AP4_MarlinIpmpParser
+{
+public:
+ // types
+ struct SinfEntry {
+ SinfEntry(AP4_UI32 track_id, AP4_ContainerAtom* sinf) :
+ m_TrackId(track_id), m_Sinf(sinf) {}
+ ~SinfEntry() { delete m_Sinf; }
+ AP4_UI32 m_TrackId;
+ AP4_ContainerAtom* m_Sinf;
+ };
+
+ // methods
+ static AP4_Result Parse(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ AP4_List<SinfEntry>& sinf_entries,
+ bool remove_od_data=false);
+
+private:
+ AP4_MarlinIpmpParser() {} // this class can't be instantiated
+};
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpDecryptingProcessor
++---------------------------------------------------------------------*/
+class AP4_MarlinIpmpDecryptingProcessor : public AP4_Processor
+{
+public:
+ // constructor and destructor
+ AP4_MarlinIpmpDecryptingProcessor(const AP4_ProtectionKeyMap* key_map = NULL,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+ ~AP4_MarlinIpmpDecryptingProcessor();
+
+ // accessors
+ AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
+
+ // methods
+ virtual AP4_Result Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ ProgressListener* listener);
+ virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
+
+private:
+
+ // members
+ AP4_BlockCipherFactory* m_BlockCipherFactory;
+ AP4_ProtectionKeyMap m_KeyMap;
+ AP4_List<AP4_MarlinIpmpParser::SinfEntry> m_SinfEntries;
+};
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackDecrypter
++---------------------------------------------------------------------*/
+class AP4_MarlinIpmpTrackDecrypter : public AP4_Processor::TrackHandler
+{
+public:
+ // class methods
+ static AP4_Result Create(AP4_BlockCipherFactory& cipher_factory,
+ const AP4_UI08* key,
+ AP4_MarlinIpmpTrackDecrypter*& decrypter);
+
+ // destructor
+ ~AP4_MarlinIpmpTrackDecrypter();
+
+ // AP4_Processor::TrackHandler methods
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out);
+
+
+private:
+ // constructor
+ AP4_MarlinIpmpTrackDecrypter(AP4_StreamCipher* cipher) : m_Cipher(cipher) {}
+
+ // members
+ AP4_StreamCipher* m_Cipher;
+};
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpEncryptingProcessor
++---------------------------------------------------------------------*/
+class AP4_MarlinIpmpEncryptingProcessor : public AP4_Processor
+{
+public:
+ // constructor
+ AP4_MarlinIpmpEncryptingProcessor(bool use_group_key = false,
+ const AP4_ProtectionKeyMap* key_map = NULL,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+
+ // accessors
+ AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
+ AP4_TrackPropertyMap& GetPropertyMap() { return m_PropertyMap; }
+
+ // AP4_Processor methods
+ virtual AP4_Result Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ AP4_Processor::ProgressListener* listener = NULL);
+ virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
+
+private:
+ // members
+ AP4_BlockCipherFactory* m_BlockCipherFactory;
+ bool m_UseGroupKey;
+ AP4_ProtectionKeyMap m_KeyMap;
+ AP4_TrackPropertyMap m_PropertyMap;
+};
+
+/*----------------------------------------------------------------------
+| AP4_MarlinIpmpTrackEncrypter
++---------------------------------------------------------------------*/
+class AP4_MarlinIpmpTrackEncrypter : public AP4_Processor::TrackHandler
+{
+public:
+ // class methods
+ static AP4_Result Create(AP4_BlockCipherFactory& cipher_factory,
+ const AP4_UI08* key,
+ const AP4_UI08* iv,
+ AP4_MarlinIpmpTrackEncrypter*& encrypter);
+
+ // destructor
+ ~AP4_MarlinIpmpTrackEncrypter();
+
+ // AP4_Processor::TrackHandler methods
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out);
+
+
+private:
+ // constructor
+ AP4_MarlinIpmpTrackEncrypter(AP4_StreamCipher* cipher, const AP4_UI08* iv);
+
+ // members
+ AP4_UI08 m_IV[16];
+ AP4_StreamCipher* m_Cipher;
+};
+
+#endif // _AP4_MARLIN_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.cpp
index 62294f74a..b15630eb9 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.cpp
@@ -1,93 +1,93 @@
-/*****************************************************************
-|
-| AP4 - mfhd Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4MfhdAtom.h"
-#include "Ap4Utils.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MfhdAtom)
-
-
-/*----------------------------------------------------------------------
-| AP4_MfhdAtom::Create
-+---------------------------------------------------------------------*/
-AP4_MfhdAtom*
-AP4_MfhdAtom::Create(AP4_Size size, AP4_ByteStream& stream)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version > 0) return NULL;
- return new AP4_MfhdAtom(size, version, flags, stream);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MfhdAtom::AP4_MfhdAtom
-+---------------------------------------------------------------------*/
-AP4_MfhdAtom::AP4_MfhdAtom(AP4_UI32 sequence_number) :
- AP4_Atom(AP4_ATOM_TYPE_MFHD, AP4_FULL_ATOM_HEADER_SIZE+4, 0, 0),
- m_SequenceNumber(sequence_number)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_MfhdAtom::AP4_MfhdAtom
-+---------------------------------------------------------------------*/
-AP4_MfhdAtom::AP4_MfhdAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream) :
- AP4_Atom(AP4_ATOM_TYPE_MFHD, size, version, flags)
-{
- stream.ReadUI32(m_SequenceNumber);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MfhdAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MfhdAtom::WriteFields(AP4_ByteStream& stream)
-{
- return stream.WriteUI32(m_SequenceNumber);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MfhdAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MfhdAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("sequence number", m_SequenceNumber);
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - mfhd Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4MfhdAtom.h"
+#include "Ap4Utils.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MfhdAtom)
+
+
+/*----------------------------------------------------------------------
+| AP4_MfhdAtom::Create
++---------------------------------------------------------------------*/
+AP4_MfhdAtom*
+AP4_MfhdAtom::Create(AP4_Size size, AP4_ByteStream& stream)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version > 0) return NULL;
+ return new AP4_MfhdAtom(size, version, flags, stream);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MfhdAtom::AP4_MfhdAtom
++---------------------------------------------------------------------*/
+AP4_MfhdAtom::AP4_MfhdAtom(AP4_UI32 sequence_number) :
+ AP4_Atom(AP4_ATOM_TYPE_MFHD, AP4_FULL_ATOM_HEADER_SIZE+4, 0, 0),
+ m_SequenceNumber(sequence_number)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_MfhdAtom::AP4_MfhdAtom
++---------------------------------------------------------------------*/
+AP4_MfhdAtom::AP4_MfhdAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream) :
+ AP4_Atom(AP4_ATOM_TYPE_MFHD, size, version, flags)
+{
+ stream.ReadUI32(m_SequenceNumber);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MfhdAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MfhdAtom::WriteFields(AP4_ByteStream& stream)
+{
+ return stream.WriteUI32(m_SequenceNumber);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MfhdAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MfhdAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("sequence number", m_SequenceNumber);
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.h
index ecdaacb0d..7c1e6c3c7 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MfhdAtom.h
@@ -1,67 +1,67 @@
-/*****************************************************************
-|
-| AP4 - mfhd Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_MFHD_ATOM_H_
-#define _AP4_MFHD_ATOM_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Atom.h"
-
-/*----------------------------------------------------------------------
-| AP4_MfhdAtom
-+---------------------------------------------------------------------*/
-class AP4_MfhdAtom : public AP4_Atom
-{
-public:
- AP4_IMPLEMENT_DYNAMIC_CAST(AP4_MfhdAtom)
-
- // class methods
- static AP4_MfhdAtom* Create(AP4_Size size, AP4_ByteStream& stream);
-
- // methods
- AP4_MfhdAtom(AP4_UI32 sequence_number);
- virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
- virtual AP4_Result WriteFields(AP4_ByteStream& stream);
-
- AP4_UI32 GetSequenceNumber() { return m_SequenceNumber; }
- void SetSequenceNumber(AP4_UI32 sequence_number) { m_SequenceNumber = sequence_number; }
-
-private:
- // methods
- AP4_MfhdAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream);
-
- // members
- AP4_UI32 m_SequenceNumber;
-};
-
-#endif // _AP4_MFHD_ATOM_H_
+/*****************************************************************
+|
+| AP4 - mfhd Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_MFHD_ATOM_H_
+#define _AP4_MFHD_ATOM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Atom.h"
+
+/*----------------------------------------------------------------------
+| AP4_MfhdAtom
++---------------------------------------------------------------------*/
+class AP4_MfhdAtom : public AP4_Atom
+{
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST(AP4_MfhdAtom)
+
+ // class methods
+ static AP4_MfhdAtom* Create(AP4_Size size, AP4_ByteStream& stream);
+
+ // methods
+ AP4_MfhdAtom(AP4_UI32 sequence_number);
+ virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
+ virtual AP4_Result WriteFields(AP4_ByteStream& stream);
+
+ AP4_UI32 GetSequenceNumber() { return m_SequenceNumber; }
+ void SetSequenceNumber(AP4_UI32 sequence_number) { m_SequenceNumber = sequence_number; }
+
+private:
+ // methods
+ AP4_MfhdAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream);
+
+ // members
+ AP4_UI32 m_SequenceNumber;
+};
+
+#endif // _AP4_MFHD_ATOM_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MoovAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MoovAtom.cpp
index a50080cf1..6a04d3ffc 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MoovAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4MoovAtom.cpp
@@ -88,80 +88,80 @@ AP4_MoovAtom::AP4_MoovAtom(AP4_UI32 size,
// ==> Start patch MPC
if(AP4_ContainerAtom* cmov = dynamic_cast<AP4_ContainerAtom*>(GetChild(AP4_ATOM_TYPE_CMOV)))
{
- AP4_DcomAtom* dcom = dynamic_cast<AP4_DcomAtom*>(cmov->GetChild(AP4_ATOM_TYPE_DCOM));
- AP4_CmvdAtom* cmvd = dynamic_cast<AP4_CmvdAtom*>(cmov->GetChild(AP4_ATOM_TYPE_CMVD));
- if(dcom && dcom->GetCompressorSubType() == AP4_ATOM_TYPE('z','l','i','b') && cmvd)
- {
- const AP4_DataBuffer& data = cmvd->GetDataBuffer();
-
- z_stream d_stream;
- d_stream.zalloc = (alloc_func)0;
- d_stream.zfree = (free_func)0;
- d_stream.opaque = (voidpf)0;
-
- int res;
-
- if(Z_OK == (res = inflateInit(&d_stream)))
- {
- d_stream.next_in = (Bytef*)data.GetData();
- d_stream.avail_in = data.GetDataSize();
-
- unsigned char* dst = NULL;
- int n = 0;
-
- do
- {
- dst = (unsigned char*)realloc(dst, ++n*1000);
- d_stream.next_out = &dst[(n-1)*1000];
- d_stream.avail_out = 1000;
-
- if(Z_OK != (res = inflate(&d_stream, Z_NO_FLUSH)) && Z_STREAM_END != res)
- {
- free(dst);
- dst = NULL;
- break;
- }
- }
- while(0 == d_stream.avail_out && 0 != d_stream.avail_in && Z_STREAM_END != res);
-
- inflateEnd(&d_stream);
-
- if(dst)
- {
- AP4_ByteStream* s = new AP4_MemoryByteStream(dst, d_stream.total_out);
- ReadChildren(atom_factory, *s, d_stream.total_out);
- s->Release();
- free(dst);
- }
-
- if(AP4_MoovAtom* moov = dynamic_cast<AP4_MoovAtom*>(GetChild(AP4_ATOM_TYPE_MOOV)))
- {
- AP4_List<AP4_Atom> Children;
-
- for(AP4_List<AP4_Atom>::Item* item = moov->GetChildren().FirstItem();
- item;
- item = item->GetNext())
- {
- Children.Add(item->GetData());
- }
-
- for(AP4_List<AP4_Atom>::Item* item = Children.FirstItem();
- item;
- item = item->GetNext())
- {
- AP4_Atom* atom = item->GetData();
- atom->Detach();
- atom->SetParent(this);
- m_Children.Add(atom);
- }
-
- moov->Detach();
- delete moov;
- }
- }
- }
- }
- // <== End patch MPC
+ AP4_DcomAtom* dcom = dynamic_cast<AP4_DcomAtom*>(cmov->GetChild(AP4_ATOM_TYPE_DCOM));
+ AP4_CmvdAtom* cmvd = dynamic_cast<AP4_CmvdAtom*>(cmov->GetChild(AP4_ATOM_TYPE_CMVD));
+ if(dcom && dcom->GetCompressorSubType() == AP4_ATOM_TYPE('z','l','i','b') && cmvd)
+ {
+ const AP4_DataBuffer& data = cmvd->GetDataBuffer();
+
+ z_stream d_stream;
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ int res;
+
+ if(Z_OK == (res = inflateInit(&d_stream)))
+ {
+ d_stream.next_in = (Bytef*)data.GetData();
+ d_stream.avail_in = data.GetDataSize();
+
+ unsigned char* dst = NULL;
+ int n = 0;
+
+ do
+ {
+ dst = (unsigned char*)realloc(dst, ++n*1000);
+ d_stream.next_out = &dst[(n-1)*1000];
+ d_stream.avail_out = 1000;
+
+ if(Z_OK != (res = inflate(&d_stream, Z_NO_FLUSH)) && Z_STREAM_END != res)
+ {
+ free(dst);
+ dst = NULL;
+ break;
+ }
+ }
+ while(0 == d_stream.avail_out && 0 != d_stream.avail_in && Z_STREAM_END != res);
+
+ inflateEnd(&d_stream);
+
+ if(dst)
+ {
+ AP4_ByteStream* s = new AP4_MemoryByteStream(dst, d_stream.total_out);
+ ReadChildren(atom_factory, *s, d_stream.total_out);
+ s->Release();
+ free(dst);
+ }
+
+ if(AP4_MoovAtom* moov = dynamic_cast<AP4_MoovAtom*>(GetChild(AP4_ATOM_TYPE_MOOV)))
+ {
+ AP4_List<AP4_Atom> Children;
+
+ for(AP4_List<AP4_Atom>::Item* item = moov->GetChildren().FirstItem();
+ item;
+ item = item->GetNext())
+ {
+ Children.Add(item->GetData());
+ }
+
+ for(AP4_List<AP4_Atom>::Item* item = Children.FirstItem();
+ item;
+ item = item->GetNext())
+ {
+ AP4_Atom* atom = item->GetData();
+ atom->Detach();
+ atom->SetParent(this);
+ m_Children.Add(atom);
+ }
+
+ moov->Detach();
+ delete moov;
+ }
+ }
+ }
+ }
+ // <== End patch MPC
// collect all trak atoms
m_Children.Apply(AP4_TrakAtomCollector(&m_TrakAtoms));
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Movie.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Movie.cpp
index 57c8c3c50..a76b2643f 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Movie.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Movie.cpp
@@ -1,237 +1,237 @@
-/*****************************************************************
-|
-| AP4 - Movie
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4File.h"
-#include "Ap4Atom.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4MoovAtom.h"
-#include "Ap4MvhdAtom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4Movie.h"
-#include "Ap4MetaData.h"
-
-/*----------------------------------------------------------------------
-| AP4_TrackFinderById
-+---------------------------------------------------------------------*/
-class AP4_TrackFinderById : public AP4_List<AP4_Track>::Item::Finder
-{
-public:
- AP4_TrackFinderById(AP4_UI32 track_id) : m_TrackId(track_id) {}
- AP4_Result Test(AP4_Track* track) const {
- return track->GetId() == m_TrackId ? AP4_SUCCESS : AP4_FAILURE;
- }
-private:
- AP4_UI32 m_TrackId;
-};
-
-/*----------------------------------------------------------------------
-| AP4_TrackFinderByType
-+---------------------------------------------------------------------*/
-class AP4_TrackFinderByType : public AP4_List<AP4_Track>::Item::Finder
-{
-public:
- AP4_TrackFinderByType(AP4_Track::Type type, AP4_Ordinal index = 0) :
- m_Type(type), m_Index(index) {}
- AP4_Result Test(AP4_Track* track) const {
- if (track->GetType() == m_Type && m_Index-- == 0) {
- return AP4_SUCCESS;
- } else {
- return AP4_FAILURE;
- }
- }
-private:
- AP4_Track::Type m_Type;
- mutable AP4_Ordinal m_Index;
-};
-
-/*----------------------------------------------------------------------
-| AP4_Movie::AP4_Movie
-+---------------------------------------------------------------------*/
-AP4_Movie::AP4_Movie(AP4_UI32 time_scale) :
- m_MoovAtomIsOwned(true)
-{
- m_MoovAtom = new AP4_MoovAtom();
- m_MvhdAtom = new AP4_MvhdAtom(0, 0,
- time_scale,
- 0,
- 0x00010000,
- 0x0100);
- m_MoovAtom->AddChild(m_MvhdAtom);
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::AP4_Moovie
-+---------------------------------------------------------------------*/
-AP4_Movie::AP4_Movie(AP4_MoovAtom* moov, AP4_ByteStream& sample_stream, bool transfer_moov_ownership) :
- m_MoovAtom(moov),
- m_MoovAtomIsOwned(transfer_moov_ownership)
-{
- // ignore null atoms
- if (moov == NULL) return;
-
- // get the time scale
- AP4_UI32 time_scale;
- m_MvhdAtom = AP4_DYNAMIC_CAST(AP4_MvhdAtom, moov->GetChild(AP4_ATOM_TYPE_MVHD));
- if (m_MvhdAtom) {
- time_scale = m_MvhdAtom->GetTimeScale();
- } else {
- time_scale = 0;
- }
-
- // get all tracks
- AP4_List<AP4_TrakAtom>* trak_atoms;
- trak_atoms = &moov->GetTrakAtoms();
- AP4_List<AP4_TrakAtom>::Item* item = trak_atoms->FirstItem();
- while (item) {
- AP4_Track* track = new AP4_Track(*item->GetData(),
- sample_stream,
- time_scale);
- m_Tracks.Add(track);
- item = item->GetNext();
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::~AP4_Movie
-+---------------------------------------------------------------------*/
-AP4_Movie::~AP4_Movie()
-{
- m_Tracks.DeleteReferences();
- if (m_MoovAtomIsOwned) delete m_MoovAtom;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::Inspect
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_Movie::Inspect(AP4_AtomInspector& inspector)
-{
- // dump the moov atom
- return m_MoovAtom->Inspect(inspector);
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::GetTrack
-+---------------------------------------------------------------------*/
-AP4_Track*
-AP4_Movie::GetTrack(AP4_UI32 track_id)
-{
- AP4_Track* track = NULL;
- if (AP4_SUCCEEDED(m_Tracks.Find(AP4_TrackFinderById(track_id), track))) {
- return track;
- } else {
- return NULL;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::GetTrack
-+---------------------------------------------------------------------*/
-AP4_Track*
-AP4_Movie::GetTrack(AP4_Track::Type track_type, AP4_Ordinal index)
-{
- AP4_Track* track = NULL;
- if (AP4_SUCCEEDED(m_Tracks.Find(AP4_TrackFinderByType(track_type, index), track))) {
- return track;
- } else {
- return NULL;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::AddTrack
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_Movie::AddTrack(AP4_Track* track)
-{
- // assign an ID to the track unless it already has one
- if (track->GetId() == 0) {
- track->SetId(m_Tracks.ItemCount()+1);
- }
-
- // if we don't have a time scale, use the one from the track
- if (m_MvhdAtom->GetTimeScale() == 0) {
- m_MvhdAtom->SetTimeScale(track->GetMediaTimeScale());
- }
-
- // adjust the parent time scale of the track
- track->SetMovieTimeScale(m_MvhdAtom->GetTimeScale());
-
- // update the movie duration
- if (m_MvhdAtom->GetDuration() < track->GetDuration()) {
- m_MvhdAtom->SetDuration(track->GetDuration());
- }
-
- // attach the track as a child
- track->Attach(m_MoovAtom);
- m_Tracks.Add(track);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::GetTimeScale
-+---------------------------------------------------------------------*/
-AP4_UI32
-AP4_Movie::GetTimeScale()
-{
- if (m_MvhdAtom) {
- return m_MvhdAtom->GetTimeScale();
- } else {
- return 0;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::GetDuration
-+---------------------------------------------------------------------*/
-AP4_UI64
-AP4_Movie::GetDuration()
-{
- if (m_MvhdAtom) {
- return m_MvhdAtom->GetDuration();
- } else {
- return 0;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_Movie::GetDurationMs
-+---------------------------------------------------------------------*/
-AP4_UI32
-AP4_Movie::GetDurationMs()
-{
- if (m_MvhdAtom) {
- return m_MvhdAtom->GetDurationMs();
- } else {
- return 0;
- }
-}
+/*****************************************************************
+|
+| AP4 - Movie
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4File.h"
+#include "Ap4Atom.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4MoovAtom.h"
+#include "Ap4MvhdAtom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4Movie.h"
+#include "Ap4MetaData.h"
+
+/*----------------------------------------------------------------------
+| AP4_TrackFinderById
++---------------------------------------------------------------------*/
+class AP4_TrackFinderById : public AP4_List<AP4_Track>::Item::Finder
+{
+public:
+ AP4_TrackFinderById(AP4_UI32 track_id) : m_TrackId(track_id) {}
+ AP4_Result Test(AP4_Track* track) const {
+ return track->GetId() == m_TrackId ? AP4_SUCCESS : AP4_FAILURE;
+ }
+private:
+ AP4_UI32 m_TrackId;
+};
+
+/*----------------------------------------------------------------------
+| AP4_TrackFinderByType
++---------------------------------------------------------------------*/
+class AP4_TrackFinderByType : public AP4_List<AP4_Track>::Item::Finder
+{
+public:
+ AP4_TrackFinderByType(AP4_Track::Type type, AP4_Ordinal index = 0) :
+ m_Type(type), m_Index(index) {}
+ AP4_Result Test(AP4_Track* track) const {
+ if (track->GetType() == m_Type && m_Index-- == 0) {
+ return AP4_SUCCESS;
+ } else {
+ return AP4_FAILURE;
+ }
+ }
+private:
+ AP4_Track::Type m_Type;
+ mutable AP4_Ordinal m_Index;
+};
+
+/*----------------------------------------------------------------------
+| AP4_Movie::AP4_Movie
++---------------------------------------------------------------------*/
+AP4_Movie::AP4_Movie(AP4_UI32 time_scale) :
+ m_MoovAtomIsOwned(true)
+{
+ m_MoovAtom = new AP4_MoovAtom();
+ m_MvhdAtom = new AP4_MvhdAtom(0, 0,
+ time_scale,
+ 0,
+ 0x00010000,
+ 0x0100);
+ m_MoovAtom->AddChild(m_MvhdAtom);
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::AP4_Moovie
++---------------------------------------------------------------------*/
+AP4_Movie::AP4_Movie(AP4_MoovAtom* moov, AP4_ByteStream& sample_stream, bool transfer_moov_ownership) :
+ m_MoovAtom(moov),
+ m_MoovAtomIsOwned(transfer_moov_ownership)
+{
+ // ignore null atoms
+ if (moov == NULL) return;
+
+ // get the time scale
+ AP4_UI32 time_scale;
+ m_MvhdAtom = AP4_DYNAMIC_CAST(AP4_MvhdAtom, moov->GetChild(AP4_ATOM_TYPE_MVHD));
+ if (m_MvhdAtom) {
+ time_scale = m_MvhdAtom->GetTimeScale();
+ } else {
+ time_scale = 0;
+ }
+
+ // get all tracks
+ AP4_List<AP4_TrakAtom>* trak_atoms;
+ trak_atoms = &moov->GetTrakAtoms();
+ AP4_List<AP4_TrakAtom>::Item* item = trak_atoms->FirstItem();
+ while (item) {
+ AP4_Track* track = new AP4_Track(*item->GetData(),
+ sample_stream,
+ time_scale);
+ m_Tracks.Add(track);
+ item = item->GetNext();
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::~AP4_Movie
++---------------------------------------------------------------------*/
+AP4_Movie::~AP4_Movie()
+{
+ m_Tracks.DeleteReferences();
+ if (m_MoovAtomIsOwned) delete m_MoovAtom;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::Inspect
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_Movie::Inspect(AP4_AtomInspector& inspector)
+{
+ // dump the moov atom
+ return m_MoovAtom->Inspect(inspector);
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::GetTrack
++---------------------------------------------------------------------*/
+AP4_Track*
+AP4_Movie::GetTrack(AP4_UI32 track_id)
+{
+ AP4_Track* track = NULL;
+ if (AP4_SUCCEEDED(m_Tracks.Find(AP4_TrackFinderById(track_id), track))) {
+ return track;
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::GetTrack
++---------------------------------------------------------------------*/
+AP4_Track*
+AP4_Movie::GetTrack(AP4_Track::Type track_type, AP4_Ordinal index)
+{
+ AP4_Track* track = NULL;
+ if (AP4_SUCCEEDED(m_Tracks.Find(AP4_TrackFinderByType(track_type, index), track))) {
+ return track;
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::AddTrack
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_Movie::AddTrack(AP4_Track* track)
+{
+ // assign an ID to the track unless it already has one
+ if (track->GetId() == 0) {
+ track->SetId(m_Tracks.ItemCount()+1);
+ }
+
+ // if we don't have a time scale, use the one from the track
+ if (m_MvhdAtom->GetTimeScale() == 0) {
+ m_MvhdAtom->SetTimeScale(track->GetMediaTimeScale());
+ }
+
+ // adjust the parent time scale of the track
+ track->SetMovieTimeScale(m_MvhdAtom->GetTimeScale());
+
+ // update the movie duration
+ if (m_MvhdAtom->GetDuration() < track->GetDuration()) {
+ m_MvhdAtom->SetDuration(track->GetDuration());
+ }
+
+ // attach the track as a child
+ track->Attach(m_MoovAtom);
+ m_Tracks.Add(track);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::GetTimeScale
++---------------------------------------------------------------------*/
+AP4_UI32
+AP4_Movie::GetTimeScale()
+{
+ if (m_MvhdAtom) {
+ return m_MvhdAtom->GetTimeScale();
+ } else {
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::GetDuration
++---------------------------------------------------------------------*/
+AP4_UI64
+AP4_Movie::GetDuration()
+{
+ if (m_MvhdAtom) {
+ return m_MvhdAtom->GetDuration();
+ } else {
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_Movie::GetDurationMs
++---------------------------------------------------------------------*/
+AP4_UI32
+AP4_Movie::GetDurationMs()
+{
+ if (m_MvhdAtom) {
+ return m_MvhdAtom->GetDurationMs();
+ } else {
+ return 0;
+ }
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ObjectDescriptor.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ObjectDescriptor.cpp
index 1b74261d9..dd5f471df 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ObjectDescriptor.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4ObjectDescriptor.cpp
@@ -155,8 +155,8 @@ AP4_Result
AP4_ObjectDescriptor::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
inspector.StartElement("[ObjectDescriptor]", info);
inspector.AddField("id", m_ObjectDescriptorId);
if (m_UrlFlag) {
@@ -305,8 +305,8 @@ AP4_Result
AP4_InitialObjectDescriptor::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
inspector.StartElement("[InitialObjectDescriptor]", info);
inspector.AddField("id", m_ObjectDescriptorId);
if (m_UrlFlag) {
@@ -387,8 +387,8 @@ AP4_Result
AP4_DescriptorUpdateCommand::Inspect(AP4_AtomInspector& inspector)
{
char info[64];
- AP4_FormatString(info, sizeof(info), "size=%ld+%ld",
- GetHeaderSize(),m_PayloadSize);
+ AP4_FormatString(info, sizeof(info), "size=%d+%d",
+ (int)GetHeaderSize(),(int)m_PayloadSize);
switch (GetTag()) {
case AP4_COMMAND_TAG_OBJECT_DESCRIPTOR_UPDATE:
inspector.StartElement("[ObjectDescriptorUpdate]", info);
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OhdrAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OhdrAtom.h
index afee7f5fb..974009d8c 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OhdrAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OhdrAtom.h
@@ -36,6 +36,7 @@
#include "Ap4Atom.h"
#include "Ap4ContainerAtom.h"
#include "Ap4String.h"
+#include "Ap4OmaDcf.h"
/*----------------------------------------------------------------------
| constants
@@ -50,10 +51,10 @@ const AP4_UI08 AP4_OMA_DCF_PADDING_SCHEME_RFC_2630 = 1;
/*----------------------------------------------------------------------
| AP4_OhdrAtom
+---------------------------------------------------------------------*/
-class AP4_OhdrAtom : public AP4_ContainerAtom
+class AP4_OhdrAtom : public AP4_ContainerAtom, public AP4_OmaDrmInfo
{
public:
- AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_OhdrAtom, AP4_ContainerAtom)
+ AP4_IMPLEMENT_DYNAMIC_CAST_D2(AP4_OhdrAtom, AP4_ContainerAtom, AP4_OmaDrmInfo)
// class methods
static AP4_OhdrAtom* Create(AP4_Size size,
@@ -80,6 +81,8 @@ public:
AP4_UI08 GetPaddingScheme() const { return m_PaddingScheme; }
void SetPaddingScheme(AP4_UI08 padding_scheme) { m_PaddingScheme = padding_scheme; }
AP4_UI64 GetPlaintextLength() const { return m_PlaintextLength; }
+
+ // AP4_OmaDrmInfo implementation
const AP4_String& GetContentId() const { return m_ContentId; }
const AP4_String& GetRightsIssuerUrl() const { return m_RightsIssuerUrl; }
const AP4_DataBuffer& GetTextualHeaders() const { return m_TextualHeaders; }
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.cpp
index a224ab14d..6ddb424a2 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.cpp
@@ -1,1131 +1,1136 @@
-/*****************************************************************
-|
-| AP4 - OMA DCF Support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4SchmAtom.h"
-#include "Ap4StsdAtom.h"
-#include "Ap4Sample.h"
-#include "Ap4StreamCipher.h"
-#include "Ap4IsfmAtom.h"
-#include "Ap4FrmaAtom.h"
-#include "Ap4IkmsAtom.h"
-#include "Ap4IsfmAtom.h"
-#include "Ap4IsltAtom.h"
-#include "Ap4Utils.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4OdafAtom.h"
-#include "Ap4OmaDcf.h"
-#include "Ap4OhdrAtom.h"
-#include "Ap4OddaAtom.h"
-#include "Ap4OdheAtom.h"
-#include "Ap4FtypAtom.h"
-#include "Ap4GrpiAtom.h"
-#include "Ap4HdlrAtom.h"
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfAtomDecrypter::DecryptAtoms
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfAtomDecrypter::DecryptAtoms(AP4_AtomParent& atoms,
- AP4_Processor::ProgressListener* /*listener*/,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ProtectionKeyMap& key_map)
-{
- unsigned int index = 1;
- for (AP4_List<AP4_Atom>::Item* item = atoms.GetChildren().FirstItem();
- item;
- item = item->GetNext()) {
- AP4_Atom* atom = item->GetData();
- if (atom->GetType() != AP4_ATOM_TYPE_ODRM) continue;
-
- // check that we have the key
- const AP4_UI08* key = key_map.GetKey(index++);
- if (key == NULL) return AP4_ERROR_INVALID_PARAMETERS;
-
- // check that we have all the atoms we need
- AP4_ContainerAtom* odrm = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
- if (odrm == NULL) continue; // not enough info
- AP4_OdheAtom* odhe = AP4_DYNAMIC_CAST(AP4_OdheAtom, odrm->GetChild(AP4_ATOM_TYPE_ODHE));
- if (odhe == NULL) continue; // not enough info
- AP4_OddaAtom* odda = AP4_DYNAMIC_CAST(AP4_OddaAtom, odrm->GetChild(AP4_ATOM_TYPE_ODDA));
- if (odda == NULL) continue; // not enough info
- AP4_OhdrAtom* ohdr = AP4_DYNAMIC_CAST(AP4_OhdrAtom, odhe->GetChild(AP4_ATOM_TYPE_OHDR));
- if (ohdr == NULL) continue; // not enough info
-
- // do nothing if the atom is not encrypted
- if (ohdr->GetEncryptionMethod() == AP4_OMA_DCF_ENCRYPTION_METHOD_NULL) {
- continue;
- }
-
- // create the byte stream
- AP4_ByteStream* cipher_stream = NULL;
- AP4_Result result = CreateDecryptingStream(*odrm,
- key,
- 16,
- block_cipher_factory,
- cipher_stream);
- if (AP4_SUCCEEDED(result)) {
- // replace the odda atom's payload with the decrypted stream
- odda->SetEncryptedPayload(*cipher_stream, ohdr->GetPlaintextLength());
- cipher_stream->Release();
-
- // the atom will now be in the clear
- ohdr->SetEncryptionMethod(AP4_OMA_DCF_ENCRYPTION_METHOD_NULL);
- ohdr->SetPaddingScheme(AP4_OMA_DCF_PADDING_SCHEME_NONE);
- }
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfAtomDecrypter::CreateDecryptingStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfAtomDecrypter::CreateDecryptingStream(
- AP4_ContainerAtom& odrm,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream)
-{
- // default return values
- stream = NULL;
-
- AP4_OdheAtom* odhe = AP4_DYNAMIC_CAST(AP4_OdheAtom, odrm.GetChild(AP4_ATOM_TYPE_ODHE));
- if (odhe == NULL) return AP4_ERROR_INVALID_FORMAT;
- AP4_OddaAtom* odda = AP4_DYNAMIC_CAST(AP4_OddaAtom, odrm.GetChild(AP4_ATOM_TYPE_ODDA));
- if (odda == NULL) return AP4_ERROR_INVALID_FORMAT;
- AP4_OhdrAtom* ohdr = AP4_DYNAMIC_CAST(AP4_OhdrAtom, odhe->GetChild(AP4_ATOM_TYPE_OHDR));
- if (ohdr == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // shortcut for non-encrypted files
- if (ohdr->GetEncryptionMethod() == AP4_OMA_DCF_ENCRYPTION_METHOD_NULL) {
- stream = &odda->GetEncryptedPayload();
- stream->AddReference();
- return AP4_SUCCESS;
- }
-
- // if this is part of a group, use the group key to obtain the content
- // key (note that the field called GroupKey in the spec is actually not
- // the group key but the content key encrypted with the group key...
- AP4_GrpiAtom* grpi = AP4_DYNAMIC_CAST(AP4_GrpiAtom, ohdr->GetChild(AP4_ATOM_TYPE_GRPI));
- AP4_UI08* key_buffer = NULL;
- if (grpi) {
- // sanity check on the encrypted key size
- if (grpi->GetGroupKey().GetDataSize() < 32) {
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // create a block cipher to decrypt the content key
- AP4_BlockCipher* block_cipher = NULL;
- AP4_Result result;
-
- // create a stream cipher from the block cipher
- AP4_StreamCipher* stream_cipher = NULL;
- switch (ohdr->GetEncryptionMethod()) {
- case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC:
- result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::DECRYPT,
- key,
- key_size,
- block_cipher);
- if (AP4_FAILED(result)) return result;
- stream_cipher = new AP4_CbcStreamCipher(block_cipher, AP4_CbcStreamCipher::DECRYPT);
- break;
-
- case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR:
- result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::ENCRYPT,
- key,
- key_size,
- block_cipher);
- if (AP4_FAILED(result)) return result;
- stream_cipher = new AP4_CtrStreamCipher(block_cipher, NULL, 16);
- break;
-
- default:
- return AP4_ERROR_NOT_SUPPORTED;
- }
-
- // set the IV
- stream_cipher->SetIV(grpi->GetGroupKey().GetData());
-
- // decrypt the content key
- AP4_Size key_buffer_size = grpi->GetGroupKey().GetDataSize(); // worst case
- key_buffer = new AP4_UI08[key_buffer_size];
- result = stream_cipher->ProcessBuffer(grpi->GetGroupKey().GetData()+16,
- grpi->GetGroupKey().GetDataSize()-16,
- key_buffer,
- &key_buffer_size,
- true);
- delete stream_cipher; // this will also delete the block cipher
- if (AP4_FAILED(result)) {
- delete[] key_buffer;
- return result;
- }
-
- // point to the new key value
- key = key_buffer;
- key_size = key_buffer_size;
- }
-
- AP4_OmaDcfCipherMode mode;
- switch (ohdr->GetEncryptionMethod()) {
- case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC:
- mode = AP4_OMA_DCF_CIPHER_MODE_CBC;
- break;
- case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR:
- mode = AP4_OMA_DCF_CIPHER_MODE_CTR;
- break;
- default:
- return AP4_ERROR_NOT_SUPPORTED;
- }
-
- AP4_Result result;
- result = CreateDecryptingStream(mode,
- odda->GetEncryptedPayload(),
- ohdr->GetPlaintextLength(),
- key, key_size,
- block_cipher_factory,
- stream);
-
- // cleanup
- delete[] key_buffer;
-
- return result;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfAtomDecrypter::CreateDecryptingStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfAtomDecrypter::CreateDecryptingStream(
- AP4_OmaDcfCipherMode mode,
- AP4_ByteStream& encrypted_stream,
- AP4_LargeSize cleartext_size,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream)
-{
- // default return value
- stream = NULL;
-
- // get the encrypted size (includes IV and padding)
- AP4_LargeSize encrypted_size = 0;
- AP4_Result result = encrypted_stream.GetSize(encrypted_size);
- if (AP4_FAILED(result)) return result;
-
- // check that the encrypted size is consistent with the cipher mode
- AP4_DecryptingStream::CipherMode cipher_mode;
- if (mode == AP4_OMA_DCF_CIPHER_MODE_CBC) {
- // we need at least 16 bytes of IV and 32 bytes of data+padding
- // we also need a multiple of the block size
- if (encrypted_size < 48 || ((encrypted_size % 16) != 0)) {
- return AP4_ERROR_INVALID_FORMAT;
- }
- cipher_mode = AP4_DecryptingStream::CIPHER_MODE_CBC;
- } else if (mode == AP4_OMA_DCF_CIPHER_MODE_CTR) {
- // we need at least 16 bytes of IV
- if (encrypted_size < 16) {
- return AP4_ERROR_INVALID_FORMAT;
- }
- cipher_mode = AP4_DecryptingStream::CIPHER_MODE_CTR;
- } else {
- return AP4_ERROR_NOT_SUPPORTED;
- }
-
- // read the IV
- AP4_UI08 iv[16];
- result = encrypted_stream.Seek(0);
- if (AP4_FAILED(result)) return result;
- result = encrypted_stream.Read(iv, 16);
- if (AP4_FAILED(result)) return result;
-
- // create a sub stream with just the encrypted payload without the IV
- AP4_ByteStream* sub_stream = new AP4_SubStream(encrypted_stream, 16, encrypted_size-16);
-
- // create the decrypting cipher
- result = AP4_DecryptingStream::Create(cipher_mode,
- *sub_stream,
- cleartext_size,
- iv,
- 16,
- key,
- key_size,
- block_cipher_factory,
- stream);
-
- // we don't keep our own reference to the sub stream
- sub_stream->Release();
-
- return result;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfSampleDecrypter::Create
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfSampleDecrypter::Create(AP4_ProtectedSampleDescription* sample_description,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_OmaDcfSampleDecrypter*& cipher)
-{
- // check the parameters
- if (key == NULL || block_cipher_factory == NULL) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
-
- // default return value
- cipher = NULL;
-
- // get the scheme info atom
- AP4_ContainerAtom* schi = sample_description->GetSchemeInfo()->GetSchiAtom();
- if (schi == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // get and check the cipher params
- // NOTE: we only support an IV Length less than or equal to the cipher block size,
- // and we don't know how to deal with a key indicator length != 0
- AP4_OdafAtom* odaf = AP4_DYNAMIC_CAST(AP4_OdafAtom, schi->FindChild("odkm/odaf"));
- if (odaf) {
- if (odaf->GetIvLength() > AP4_CIPHER_BLOCK_SIZE) return AP4_ERROR_INVALID_FORMAT;
- if (odaf->GetKeyIndicatorLength() != 0) return AP4_ERROR_INVALID_FORMAT;
- }
-
- // check the scheme details and create the cipher
- AP4_OhdrAtom* ohdr = AP4_DYNAMIC_CAST(AP4_OhdrAtom, schi->FindChild("odkm/ohdr"));
- if (ohdr == NULL) return AP4_ERROR_INVALID_FORMAT;
- AP4_UI08 encryption_method = ohdr->GetEncryptionMethod();
- if (encryption_method == AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC) {
- // in CBC mode, we only support IVs of the same size as the cipher block size
- if (odaf->GetIvLength() != AP4_CIPHER_BLOCK_SIZE) return AP4_ERROR_INVALID_FORMAT;
-
- // require RFC_2630 padding
- if (ohdr->GetPaddingScheme() != AP4_OMA_DCF_PADDING_SCHEME_RFC_2630) {
- return AP4_ERROR_NOT_SUPPORTED;
- }
-
- // create the block cipher
- AP4_BlockCipher* block_cipher = NULL;
- AP4_Result result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::DECRYPT,
- key,
- key_size,
- block_cipher);
- if (AP4_FAILED(result)) return result;
-
- // create the cipher
- cipher = new AP4_OmaDcfCbcSampleDecrypter(block_cipher,
- odaf->GetSelectiveEncryption());
- return AP4_SUCCESS;
- } else if (encryption_method == AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR) {
- // require NONE padding
- if (ohdr->GetPaddingScheme() != AP4_OMA_DCF_PADDING_SCHEME_NONE) {
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // create the block cipher
- AP4_BlockCipher* block_cipher = NULL;
- AP4_Result result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::ENCRYPT,
- key,
- key_size,
- block_cipher);
- if (AP4_FAILED(result)) return result;
-
- // create the cipher
- cipher = new AP4_OmaDcfCtrSampleDecrypter(block_cipher,
- odaf->GetIvLength(),
- odaf->GetSelectiveEncryption());
- return AP4_SUCCESS;
- } else {
- return AP4_ERROR_NOT_SUPPORTED;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleDecrypter::AP4_OmaDcfCtrSampleDecrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCtrSampleDecrypter::AP4_OmaDcfCtrSampleDecrypter(
- AP4_BlockCipher* block_cipher,
- AP4_Size iv_length,
- bool selective_encryption) :
- AP4_OmaDcfSampleDecrypter(iv_length, selective_encryption)
-{
- m_Cipher = new AP4_CtrStreamCipher(block_cipher, NULL, iv_length);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleDecrypter::~AP4_OmaDcfCtrSampleDecrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCtrSampleDecrypter::~AP4_OmaDcfCtrSampleDecrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleDecrypter::DecryptSampleData
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfCtrSampleDecrypter::DecryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- const AP4_UI08* /*iv*/)
-{
- bool is_encrypted = true;
- const unsigned char* in = data_in.GetData();
- AP4_Size in_size = data_in.GetDataSize();
-
- // default to 0 output
- AP4_CHECK(data_out.SetDataSize(0));
-
- // check the selective encryption flag
- if (m_SelectiveEncryption) {
- if (in_size < 1) return AP4_ERROR_INVALID_FORMAT;
- is_encrypted = ((in[0]&0x80)!=0);
- in++;
- }
-
- // check the size
- unsigned int header_size = (m_SelectiveEncryption?1:0)+(is_encrypted?m_IvLength:0);
- if (header_size > in_size) return AP4_ERROR_INVALID_FORMAT;
-
- // process the sample data
- AP4_Size payload_size = in_size-header_size;
- AP4_CHECK(data_out.Reserve(payload_size));
- unsigned char* out = data_out.UseData();
- if (is_encrypted) {
- // set the IV
- m_Cipher->SetIV(in);
- AP4_CHECK(m_Cipher->ProcessBuffer(in+m_IvLength,
- payload_size,
- out));
- } else {
- AP4_CopyMemory(out, in, payload_size);
- }
- AP4_CHECK(data_out.SetDataSize(payload_size));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleDecrypter::GetDecryptedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_OmaDcfCtrSampleDecrypter::GetDecryptedSampleSize(AP4_Sample& sample)
-{
- if (m_Cipher == NULL) return 0;
-
- // decide if this sample is encrypted or not
- bool is_encrypted;
- if (m_SelectiveEncryption) {
- // read the first byte to see if the sample is encrypted or not
- AP4_Byte h;
- AP4_DataBuffer peek_buffer;
- peek_buffer.SetBuffer(&h, 1);
- sample.ReadData(peek_buffer, 1);
- is_encrypted = ((h&0x80)!=0);
- } else {
- is_encrypted = true;
- }
-
- AP4_Size crypto_header_size = (m_SelectiveEncryption?1:0)+(is_encrypted?m_IvLength:0);
- return sample.GetSize()-crypto_header_size;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleDecrypter::AP4_OmaDcfCbcSampleDecrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCbcSampleDecrypter::AP4_OmaDcfCbcSampleDecrypter(
- AP4_BlockCipher* block_cipher,
- bool selective_encryption) :
- AP4_OmaDcfSampleDecrypter(AP4_CIPHER_BLOCK_SIZE, selective_encryption)
-{
- m_Cipher = new AP4_CbcStreamCipher(block_cipher, AP4_CbcStreamCipher::DECRYPT);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleDecrypter::~AP4_OmaDcfCbcSampleDecrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCbcSampleDecrypter::~AP4_OmaDcfCbcSampleDecrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDbcCbcSampleDecrypter::DecryptSampleData
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfCbcSampleDecrypter::DecryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- const AP4_UI08* /*iv*/)
-{
- bool is_encrypted = true;
- const unsigned char* in = data_in.GetData();
- AP4_Size in_size = data_in.GetDataSize();
- AP4_Size out_size;
-
- // default to 0 output
- AP4_CHECK(data_out.SetDataSize(0));
-
- // check the selective encryption flag
- if (m_SelectiveEncryption) {
- if (in_size < 1) return AP4_ERROR_INVALID_FORMAT;
- is_encrypted = ((in[0]&0x80)!=0);
- in++;
- }
-
- // check the size
- unsigned int header_size = (m_SelectiveEncryption?1:0)+(is_encrypted?m_IvLength:0);
- if (header_size > in_size) return AP4_ERROR_INVALID_FORMAT;
-
- // process the sample data
- unsigned int payload_size = in_size-header_size;
- data_out.Reserve(payload_size);
- unsigned char* out = data_out.UseData();
- if (is_encrypted) {
- // get the IV
- const AP4_UI08* iv = (const AP4_UI08*)in;
- in += AP4_CIPHER_BLOCK_SIZE;
-
- m_Cipher->SetIV(iv);
- out_size = payload_size;
- AP4_CHECK(m_Cipher->ProcessBuffer(in, payload_size, out, &out_size, true));
- } else {
- AP4_CopyMemory(out, in, payload_size);
- out_size = payload_size;
- }
-
- AP4_CHECK(data_out.SetDataSize(out_size));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleDecrypter::GetDecryptedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_OmaDcfCbcSampleDecrypter::GetDecryptedSampleSize(AP4_Sample& sample)
-{
- if (m_Cipher == NULL) return 0;
-
- // decide if this sample is encrypted or not
- bool is_encrypted;
- if (m_SelectiveEncryption) {
- // read the first byte to see if the sample is encrypted or not
- AP4_Byte h;
- AP4_DataBuffer peek_buffer;
- peek_buffer.SetBuffer(&h, 1);
- sample.ReadData(peek_buffer, 1);
- is_encrypted = ((h&0x80)!=0);
- } else {
- is_encrypted = true;
- }
-
- if (is_encrypted) {
- // with CBC, we need to decrypt the last block to know what the padding was
- AP4_Size crypto_header_size = (m_SelectiveEncryption?1:0)+m_IvLength;
- AP4_Size encrypted_size = sample.GetSize()-crypto_header_size;
- AP4_DataBuffer encrypted;
- AP4_DataBuffer decrypted;
- AP4_Size decrypted_size = AP4_CIPHER_BLOCK_SIZE;
- if (sample.GetSize() < crypto_header_size+AP4_CIPHER_BLOCK_SIZE) {
- return 0;
- }
- AP4_Size offset = sample.GetSize()-2*AP4_CIPHER_BLOCK_SIZE;
- if (AP4_FAILED(sample.ReadData(encrypted, 2*AP4_CIPHER_BLOCK_SIZE, offset))) {
- return 0;
- }
- decrypted.Reserve(decrypted_size);
- m_Cipher->SetIV(encrypted.GetData());
- if (AP4_FAILED(m_Cipher->ProcessBuffer(encrypted.GetData()+AP4_CIPHER_BLOCK_SIZE,
- AP4_CIPHER_BLOCK_SIZE,
- decrypted.UseData(),
- &decrypted_size,
- true))) {
- return 0;
- }
- unsigned int padding_size = AP4_CIPHER_BLOCK_SIZE-decrypted_size;
- return encrypted_size-padding_size;
- } else {
- return sample.GetSize()-(m_SelectiveEncryption?1:0);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfSampleEncrypter::AP4_OmaDcfSampleEncrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfSampleEncrypter::AP4_OmaDcfSampleEncrypter(const AP4_UI08* salt)
-{
- // left-align the salt
- unsigned int i=0;
- if (salt) {
- for (; i<8; i++) {
- m_Salt[i] = salt[i];
- }
- }
- for (; i<sizeof(m_Salt)/sizeof(m_Salt[0]); i++) {
- m_Salt[i] = 0;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleEncrypter::AP4_OmaDcfCtrSampleEncrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCtrSampleEncrypter::AP4_OmaDcfCtrSampleEncrypter(AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt) :
- AP4_OmaDcfSampleEncrypter(salt)
-{
- m_Cipher = new AP4_CtrStreamCipher(block_cipher, m_Salt, 8);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleEncrypter::~AP4_OmaDcfCtrSampleEncrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCtrSampleEncrypter::~AP4_OmaDcfCtrSampleEncrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleEncrypter::EncryptSampleData
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfCtrSampleEncrypter::EncryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- AP4_UI64 counter,
- bool /*skip_encryption*/)
-{
- // setup the buffers
- const unsigned char* in = data_in.GetData();
- AP4_CHECK(data_out.SetDataSize(data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE+1));
- unsigned char* out = data_out.UseData();
-
- // selective encryption flag
- *out++ = 0x80;
-
- // IV on 16 bytes: [SSSSSSSSXXXXXXXX]
- // where SSSSSSSS is the 64-bit salt and
- // XXXXXXXX is the 64-bit base counter
- AP4_CopyMemory(out, m_Salt, 8);
- AP4_BytesFromUInt64BE(&out[8], counter);
-
- // encrypt the payload
- AP4_Size data_size = data_in.GetDataSize();
- m_Cipher->SetIV(out+8);
- m_Cipher->ProcessBuffer(in, data_size, out+AP4_CIPHER_BLOCK_SIZE);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleEncrypter::GetEncryptedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_OmaDcfCtrSampleEncrypter::GetEncryptedSampleSize(AP4_Sample& sample)
-{
- return sample.GetSize()+AP4_CIPHER_BLOCK_SIZE+1;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleEncrypter::AP4_OmaDcfCbcSampleEncrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCbcSampleEncrypter::AP4_OmaDcfCbcSampleEncrypter(AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt) :
- AP4_OmaDcfSampleEncrypter(salt)
-{
- m_Cipher = new AP4_CbcStreamCipher(block_cipher, AP4_CbcStreamCipher::ENCRYPT);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleEncrypter::~AP4_OmaDcfCbcSampleEncrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfCbcSampleEncrypter::~AP4_OmaDcfCbcSampleEncrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleEncrypter::EncryptSampleData
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfCbcSampleEncrypter::EncryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- AP4_UI64 counter,
- bool /*skip_encryption*/)
-{
- // make sure there is enough space in the output buffer
- data_out.Reserve(data_in.GetDataSize()+2*AP4_CIPHER_BLOCK_SIZE+1);
-
- // setup the buffers
- AP4_Size out_size = data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE;
- unsigned char* out = data_out.UseData();
-
- // selective encryption flag
- *out++ = 0x80;
-
- // IV on 16 bytes: [SSSSSSSSXXXXXXXX]
- // where SSSSSSSS is the 64-bit salt and
- // XXXXXXXX is the 64-bit base counter
- AP4_CopyMemory(out, m_Salt, 8);
- AP4_BytesFromUInt64BE(&out[8], counter);
-
- // encrypt the payload
- m_Cipher->SetIV(out);
- m_Cipher->ProcessBuffer(data_in.GetData(),
- data_in.GetDataSize(),
- out+AP4_CIPHER_BLOCK_SIZE,
- &out_size,
- true);
- AP4_CHECK(data_out.SetDataSize(out_size+AP4_CIPHER_BLOCK_SIZE+1));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleEncrypter::GetEncryptedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_OmaDcfCbcSampleEncrypter::GetEncryptedSampleSize(AP4_Sample& sample)
-{
- AP4_Size sample_size = sample.GetSize();
- AP4_Size padding_size = AP4_CIPHER_BLOCK_SIZE-(sample_size%AP4_CIPHER_BLOCK_SIZE);
- return sample_size+padding_size+AP4_CIPHER_BLOCK_SIZE+1;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackDecrypter::Create
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfTrackDecrypter::Create(
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_ProtectedSampleDescription* sample_description,
- AP4_SampleEntry* sample_entry,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_OmaDcfTrackDecrypter*& decrypter)
-{
- // check and set defaults
- if (key == NULL) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
- if (block_cipher_factory == NULL) {
- block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
- }
- decrypter = NULL;
-
- // create the cipher
- AP4_OmaDcfSampleDecrypter* cipher = NULL;
- AP4_Result result = AP4_OmaDcfSampleDecrypter::Create(sample_description,
- key,
- key_size,
- block_cipher_factory,
- cipher);
- if (AP4_FAILED(result)) return result;
-
- // instantiate the object
- decrypter = new AP4_OmaDcfTrackDecrypter(cipher,
- sample_entry,
- sample_description->GetOriginalFormat());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackDecrypter::AP4_OmaDcfTrackDecrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfTrackDecrypter::AP4_OmaDcfTrackDecrypter(AP4_OmaDcfSampleDecrypter* cipher,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 original_format) :
- m_Cipher(cipher),
- m_SampleEntry(sample_entry),
- m_OriginalFormat(original_format)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackDecrypter::~AP4_OmaDcfTrackDecrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfTrackDecrypter::~AP4_OmaDcfTrackDecrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackDecrypter::GetProcessedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_OmaDcfTrackDecrypter::GetProcessedSampleSize(AP4_Sample& sample)
-{
- if (m_Cipher == NULL) return 0;
- return m_Cipher->GetDecryptedSampleSize(sample);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackDecrypter::ProcessTrack
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfTrackDecrypter::ProcessTrack()
-{
- m_SampleEntry->SetType(m_OriginalFormat);
- m_SampleEntry->DeleteChild(AP4_ATOM_TYPE_SINF);
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfDecrypter::ProcessSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfTrackDecrypter::ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out)
-{
- return m_Cipher->DecryptSampleData(data_in, data_out);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackEncrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfTrackEncrypter : public AP4_Processor::TrackHandler {
-public:
- // constructor
- AP4_OmaDcfTrackEncrypter(AP4_OmaDcfCipherMode cipher_mode,
- AP4_BlockCipher* block_cipher,
- const AP4_UI08* iv,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 format,
- const char* content_id,
- const char* rights_issuer_url,
- const AP4_Byte* textual_headers,
- AP4_Size textual_headers_size);
- virtual ~AP4_OmaDcfTrackEncrypter();
-
- // methods
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
- virtual AP4_Result ProcessTrack();
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out);
-
-private:
- // members
- AP4_OmaDcfSampleEncrypter* m_Cipher;
- AP4_UI08 m_CipherMode;
- AP4_UI08 m_CipherPadding;
- AP4_SampleEntry* m_SampleEntry;
- AP4_UI32 m_Format;
- AP4_String m_ContentId;
- AP4_String m_RightsIssuerUrl;
- AP4_DataBuffer m_TextualHeaders;
- AP4_UI64 m_Counter;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackEncrypter::AP4_OmaDcfTrackEncrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfTrackEncrypter::AP4_OmaDcfTrackEncrypter(
- AP4_OmaDcfCipherMode cipher_mode,
- AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 format,
- const char* content_id,
- const char* rights_issuer_url,
- const AP4_Byte* textual_headers,
- AP4_Size textual_headers_size) :
- m_SampleEntry(sample_entry),
- m_Format(format),
- m_ContentId(content_id),
- m_RightsIssuerUrl(rights_issuer_url),
- m_TextualHeaders(textual_headers, textual_headers_size),
- m_Counter(0)
-{
- // instantiate the cipher (fixed params for now)
- if (cipher_mode == AP4_OMA_DCF_CIPHER_MODE_CBC) {
- m_Cipher = new AP4_OmaDcfCbcSampleEncrypter(block_cipher, salt);
- m_CipherMode = AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC;
- m_CipherPadding = AP4_OMA_DCF_PADDING_SCHEME_RFC_2630;
- } else {
- m_Cipher = new AP4_OmaDcfCtrSampleEncrypter(block_cipher, salt);
- m_CipherMode = AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR;
- m_CipherPadding = AP4_OMA_DCF_PADDING_SCHEME_NONE;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackEncrypter::~AP4_OmaDcfTrackEncrypter
-+---------------------------------------------------------------------*/
-AP4_OmaDcfTrackEncrypter::~AP4_OmaDcfTrackEncrypter()
-{
- delete m_Cipher;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackEncrypter::GetProcessedSampleSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_OmaDcfTrackEncrypter::GetProcessedSampleSize(AP4_Sample& sample)
-{
- return m_Cipher->GetEncryptedSampleSize(sample);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackEncrypter::ProcessTrack
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfTrackEncrypter::ProcessTrack()
-{
- // sinf container
- AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
-
- // original format
- AP4_FrmaAtom* frma = new AP4_FrmaAtom(m_SampleEntry->GetType());
-
- // scheme info
- AP4_ContainerAtom* schi = new AP4_ContainerAtom(AP4_ATOM_TYPE_SCHI);
- AP4_OdafAtom* odaf = new AP4_OdafAtom(true, 0, AP4_CIPHER_BLOCK_SIZE);
- AP4_OhdrAtom* ohdr = new AP4_OhdrAtom(m_CipherMode,
- m_CipherPadding,
- 0,
- m_ContentId.GetChars(),
- m_RightsIssuerUrl.GetChars(),
- m_TextualHeaders.GetData(),
- m_TextualHeaders.GetDataSize());
- AP4_ContainerAtom* odkm = new AP4_ContainerAtom(AP4_ATOM_TYPE_ODKM, (AP4_UI32)0, (AP4_UI32)0);
- AP4_SchmAtom* schm = new AP4_SchmAtom(AP4_PROTECTION_SCHEME_TYPE_OMA,
- AP4_PROTECTION_SCHEME_VERSION_OMA_20);
- odkm->AddChild(odaf);
- odkm->AddChild(ohdr);
-
- // populate the schi container
- schi->AddChild(odkm);
-
- // populate the sinf container
- sinf->AddChild(frma);
- sinf->AddChild(schm);
- sinf->AddChild(schi);
-
- // add the sinf atom to the sample description
- m_SampleEntry->AddChild(sinf);
-
- // change the atom type of the sample description
- m_SampleEntry->SetType(m_Format);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackEncrypter::ProcessSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out)
-{
- AP4_Result result = m_Cipher->EncryptSampleData(data_in,
- data_out,
- m_Counter,
- false);
- if (AP4_FAILED(result)) return result;
-
- m_Counter += (data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE-1)/AP4_CIPHER_BLOCK_SIZE;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfDecryptingProcessor:AP4_OmaDcfDecryptingProcessor
-+---------------------------------------------------------------------*/
-AP4_OmaDcfDecryptingProcessor::AP4_OmaDcfDecryptingProcessor(
- const AP4_ProtectionKeyMap* key_map /* = NULL */,
- AP4_BlockCipherFactory* block_cipher_factory /* = NULL */)
-{
- if (key_map) {
- // copy the keys
- m_KeyMap.SetKeys(*key_map);
- }
-
- if (block_cipher_factory == NULL) {
- m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
- } else {
- m_BlockCipherFactory = block_cipher_factory;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfDecryptingProcessor:Initialize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfDecryptingProcessor::Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& /* stream */,
- ProgressListener* listener)
-{
- // decide which processor to instantiate based on the file type
- AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
- if (ftyp) {
- if (ftyp->GetMajorBrand() == AP4_OMA_DCF_BRAND_ODCF || ftyp->HasCompatibleBrand(AP4_OMA_DCF_BRAND_ODCF)) {
- return AP4_OmaDcfAtomDecrypter::DecryptAtoms(top_level, listener, m_BlockCipherFactory, m_KeyMap);
- } else {
- return AP4_ERROR_INVALID_FORMAT;
- }
- } else {
- return AP4_SUCCESS;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfEncryptingProcessor:AP4_OmaDcfEncryptingProcessor
-+---------------------------------------------------------------------*/
-AP4_OmaDcfEncryptingProcessor::AP4_OmaDcfEncryptingProcessor(AP4_OmaDcfCipherMode cipher_mode,
- AP4_BlockCipherFactory* block_cipher_factory) :
- m_CipherMode(cipher_mode)
-{
- if (block_cipher_factory == NULL) {
- m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
- } else {
- m_BlockCipherFactory = block_cipher_factory;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfEncryptingProcessor::Initialize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_OmaDcfEncryptingProcessor::Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& /*stream*/,
- AP4_Processor::ProgressListener* /*listener*/)
-{
- AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
- if (ftyp) {
- // remove the atom, it will be replaced with a new one
- top_level.RemoveChild(ftyp);
-
- // keep the existing brand and compatible brands
- AP4_Array<AP4_UI32> compatible_brands;
- compatible_brands.EnsureCapacity(ftyp->GetCompatibleBrands().ItemCount()+1);
- for (unsigned int i=0; i<ftyp->GetCompatibleBrands().ItemCount(); i++) {
- compatible_brands.Append(ftyp->GetCompatibleBrands()[i]);
- }
-
- // add the OMA compatible brand if it is not already there
- if (!ftyp->HasCompatibleBrand(AP4_OMA_DCF_BRAND_OPF2)) {
- compatible_brands.Append(AP4_OMA_DCF_BRAND_OPF2);
- }
-
- // create a replacement
- AP4_FtypAtom* new_ftyp = new AP4_FtypAtom(ftyp->GetMajorBrand(),
- ftyp->GetMinorVersion(),
- &compatible_brands[0],
- compatible_brands.ItemCount());
- delete ftyp;
- ftyp = new_ftyp;
- } else {
- AP4_UI32 opf2 = AP4_OMA_DCF_BRAND_OPF2;
- ftyp = new AP4_FtypAtom(AP4_FTYP_BRAND_ISOM, 0, &opf2, 1);
- }
-
- // insert the ftyp atom as the first child
- return top_level.AddChild(ftyp, 0);
-}
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfEncryptingProcessor:CreateTrackHandler
-+---------------------------------------------------------------------*/
-AP4_Processor::TrackHandler*
-AP4_OmaDcfEncryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
-{
- // find the stsd atom
- AP4_StsdAtom* stsd = AP4_DYNAMIC_CAST(AP4_StsdAtom, trak->FindChild("mdia/minf/stbl/stsd"));
-
- // avoid tracks with no stsd atom (should not happen)
- if (stsd == NULL) return NULL;
-
- // only look at the first sample description
- AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
- if (entry == NULL) return NULL;
-
- // create a handler for this track if we have a key for it and we know
- // how to map the type
- const AP4_UI08* key;
- const AP4_UI08* iv;
- AP4_UI32 format = 0;
- if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, iv))) {
- switch (entry->GetType()) {
- case AP4_ATOM_TYPE_MP4A:
- format = AP4_ATOM_TYPE_ENCA;
- break;
-
- case AP4_ATOM_TYPE_MP4V:
- case AP4_ATOM_TYPE_AVC1:
- format = AP4_ATOM_TYPE_ENCV;
- break;
-
- default: {
- // try to find if this is audio or video
- AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, trak->FindChild("mdia/hdlr"));
- if (hdlr) {
- switch (hdlr->GetHandlerType()) {
- case AP4_HANDLER_TYPE_SOUN:
- format = AP4_ATOM_TYPE_ENCA;
- break;
-
- case AP4_HANDLER_TYPE_VIDE:
- format = AP4_ATOM_TYPE_ENCV;
- break;
- }
- }
- break;
- }
- }
- if (format) {
- const char* content_id = m_PropertyMap.GetProperty(trak->GetId(), "ContentId");
- const char* rights_issuer_url = m_PropertyMap.GetProperty(trak->GetId(), "RightsIssuerUrl");
- AP4_DataBuffer textual_headers;
- AP4_Result result = m_PropertyMap.GetTextualHeaders(trak->GetId(), textual_headers);
- if (AP4_FAILED(result)) textual_headers.SetDataSize(0);
-
- // create the block cipher
- AP4_BlockCipher* block_cipher = NULL;
- result = m_BlockCipherFactory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::ENCRYPT,
- key,
- AP4_CIPHER_BLOCK_SIZE,
- block_cipher);
- if (AP4_FAILED(result)) return NULL;
- return new AP4_OmaDcfTrackEncrypter(m_CipherMode,
- block_cipher,
- iv,
- entry,
- format,
- content_id,
- rights_issuer_url,
- textual_headers.GetData(),
- textual_headers.GetDataSize());
- }
- }
-
- return NULL;
-}
+/*****************************************************************
+|
+| AP4 - OMA DCF Support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4SchmAtom.h"
+#include "Ap4StsdAtom.h"
+#include "Ap4Sample.h"
+#include "Ap4StreamCipher.h"
+#include "Ap4IsfmAtom.h"
+#include "Ap4FrmaAtom.h"
+#include "Ap4IkmsAtom.h"
+#include "Ap4IsfmAtom.h"
+#include "Ap4IsltAtom.h"
+#include "Ap4Utils.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4OdafAtom.h"
+#include "Ap4OmaDcf.h"
+#include "Ap4OhdrAtom.h"
+#include "Ap4OddaAtom.h"
+#include "Ap4OdheAtom.h"
+#include "Ap4FtypAtom.h"
+#include "Ap4GrpiAtom.h"
+#include "Ap4HdlrAtom.h"
+
+/*----------------------------------------------------------------------
+| AP4_OmaDrmInfo Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_OmaDrmInfo)
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfAtomDecrypter::DecryptAtoms
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfAtomDecrypter::DecryptAtoms(AP4_AtomParent& atoms,
+ AP4_Processor::ProgressListener* /*listener*/,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ProtectionKeyMap& key_map)
+{
+ unsigned int index = 1;
+ for (AP4_List<AP4_Atom>::Item* item = atoms.GetChildren().FirstItem();
+ item;
+ item = item->GetNext()) {
+ AP4_Atom* atom = item->GetData();
+ if (atom->GetType() != AP4_ATOM_TYPE_ODRM) continue;
+
+ // check that we have the key
+ const AP4_UI08* key = key_map.GetKey(index++);
+ if (key == NULL) return AP4_ERROR_INVALID_PARAMETERS;
+
+ // check that we have all the atoms we need
+ AP4_ContainerAtom* odrm = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
+ if (odrm == NULL) continue; // not enough info
+ AP4_OdheAtom* odhe = AP4_DYNAMIC_CAST(AP4_OdheAtom, odrm->GetChild(AP4_ATOM_TYPE_ODHE));
+ if (odhe == NULL) continue; // not enough info
+ AP4_OddaAtom* odda = AP4_DYNAMIC_CAST(AP4_OddaAtom, odrm->GetChild(AP4_ATOM_TYPE_ODDA));
+ if (odda == NULL) continue; // not enough info
+ AP4_OhdrAtom* ohdr = AP4_DYNAMIC_CAST(AP4_OhdrAtom, odhe->GetChild(AP4_ATOM_TYPE_OHDR));
+ if (ohdr == NULL) continue; // not enough info
+
+ // do nothing if the atom is not encrypted
+ if (ohdr->GetEncryptionMethod() == AP4_OMA_DCF_ENCRYPTION_METHOD_NULL) {
+ continue;
+ }
+
+ // create the byte stream
+ AP4_ByteStream* cipher_stream = NULL;
+ AP4_Result result = CreateDecryptingStream(*odrm,
+ key,
+ 16,
+ block_cipher_factory,
+ cipher_stream);
+ if (AP4_SUCCEEDED(result)) {
+ // replace the odda atom's payload with the decrypted stream
+ odda->SetEncryptedPayload(*cipher_stream, ohdr->GetPlaintextLength());
+ cipher_stream->Release();
+
+ // the atom will now be in the clear
+ ohdr->SetEncryptionMethod(AP4_OMA_DCF_ENCRYPTION_METHOD_NULL);
+ ohdr->SetPaddingScheme(AP4_OMA_DCF_PADDING_SCHEME_NONE);
+ }
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfAtomDecrypter::CreateDecryptingStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfAtomDecrypter::CreateDecryptingStream(
+ AP4_ContainerAtom& odrm,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream)
+{
+ // default return values
+ stream = NULL;
+
+ AP4_OdheAtom* odhe = AP4_DYNAMIC_CAST(AP4_OdheAtom, odrm.GetChild(AP4_ATOM_TYPE_ODHE));
+ if (odhe == NULL) return AP4_ERROR_INVALID_FORMAT;
+ AP4_OddaAtom* odda = AP4_DYNAMIC_CAST(AP4_OddaAtom, odrm.GetChild(AP4_ATOM_TYPE_ODDA));
+ if (odda == NULL) return AP4_ERROR_INVALID_FORMAT;
+ AP4_OhdrAtom* ohdr = AP4_DYNAMIC_CAST(AP4_OhdrAtom, odhe->GetChild(AP4_ATOM_TYPE_OHDR));
+ if (ohdr == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // shortcut for non-encrypted files
+ if (ohdr->GetEncryptionMethod() == AP4_OMA_DCF_ENCRYPTION_METHOD_NULL) {
+ stream = &odda->GetEncryptedPayload();
+ stream->AddReference();
+ return AP4_SUCCESS;
+ }
+
+ // if this is part of a group, use the group key to obtain the content
+ // key (note that the field called GroupKey in the spec is actually not
+ // the group key but the content key encrypted with the group key...
+ AP4_GrpiAtom* grpi = AP4_DYNAMIC_CAST(AP4_GrpiAtom, ohdr->GetChild(AP4_ATOM_TYPE_GRPI));
+ AP4_UI08* key_buffer = NULL;
+ if (grpi) {
+ // sanity check on the encrypted key size
+ if (grpi->GetGroupKey().GetDataSize() < 32) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // create a block cipher to decrypt the content key
+ AP4_BlockCipher* block_cipher = NULL;
+ AP4_Result result;
+
+ // create a stream cipher from the block cipher
+ AP4_StreamCipher* stream_cipher = NULL;
+ switch (ohdr->GetEncryptionMethod()) {
+ case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC:
+ result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::DECRYPT,
+ key,
+ key_size,
+ block_cipher);
+ if (AP4_FAILED(result)) return result;
+ stream_cipher = new AP4_CbcStreamCipher(block_cipher, AP4_CbcStreamCipher::DECRYPT);
+ break;
+
+ case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR:
+ result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::ENCRYPT,
+ key,
+ key_size,
+ block_cipher);
+ if (AP4_FAILED(result)) return result;
+ stream_cipher = new AP4_CtrStreamCipher(block_cipher, NULL, 16);
+ break;
+
+ default:
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+
+ // set the IV
+ stream_cipher->SetIV(grpi->GetGroupKey().GetData());
+
+ // decrypt the content key
+ AP4_Size key_buffer_size = grpi->GetGroupKey().GetDataSize(); // worst case
+ key_buffer = new AP4_UI08[key_buffer_size];
+ result = stream_cipher->ProcessBuffer(grpi->GetGroupKey().GetData()+16,
+ grpi->GetGroupKey().GetDataSize()-16,
+ key_buffer,
+ &key_buffer_size,
+ true);
+ delete stream_cipher; // this will also delete the block cipher
+ if (AP4_FAILED(result)) {
+ delete[] key_buffer;
+ return result;
+ }
+
+ // point to the new key value
+ key = key_buffer;
+ key_size = key_buffer_size;
+ }
+
+ AP4_OmaDcfCipherMode mode;
+ switch (ohdr->GetEncryptionMethod()) {
+ case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC:
+ mode = AP4_OMA_DCF_CIPHER_MODE_CBC;
+ break;
+ case AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR:
+ mode = AP4_OMA_DCF_CIPHER_MODE_CTR;
+ break;
+ default:
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+
+ AP4_Result result;
+ result = CreateDecryptingStream(mode,
+ odda->GetEncryptedPayload(),
+ ohdr->GetPlaintextLength(),
+ key, key_size,
+ block_cipher_factory,
+ stream);
+
+ // cleanup
+ delete[] key_buffer;
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfAtomDecrypter::CreateDecryptingStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfAtomDecrypter::CreateDecryptingStream(
+ AP4_OmaDcfCipherMode mode,
+ AP4_ByteStream& encrypted_stream,
+ AP4_LargeSize cleartext_size,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream)
+{
+ // default return value
+ stream = NULL;
+
+ // get the encrypted size (includes IV and padding)
+ AP4_LargeSize encrypted_size = 0;
+ AP4_Result result = encrypted_stream.GetSize(encrypted_size);
+ if (AP4_FAILED(result)) return result;
+
+ // check that the encrypted size is consistent with the cipher mode
+ AP4_DecryptingStream::CipherMode cipher_mode;
+ if (mode == AP4_OMA_DCF_CIPHER_MODE_CBC) {
+ // we need at least 16 bytes of IV and 32 bytes of data+padding
+ // we also need a multiple of the block size
+ if (encrypted_size < 48 || ((encrypted_size % 16) != 0)) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+ cipher_mode = AP4_DecryptingStream::CIPHER_MODE_CBC;
+ } else if (mode == AP4_OMA_DCF_CIPHER_MODE_CTR) {
+ // we need at least 16 bytes of IV
+ if (encrypted_size < 16) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+ cipher_mode = AP4_DecryptingStream::CIPHER_MODE_CTR;
+ } else {
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+
+ // read the IV
+ AP4_UI08 iv[16];
+ result = encrypted_stream.Seek(0);
+ if (AP4_FAILED(result)) return result;
+ result = encrypted_stream.Read(iv, 16);
+ if (AP4_FAILED(result)) return result;
+
+ // create a sub stream with just the encrypted payload without the IV
+ AP4_ByteStream* sub_stream = new AP4_SubStream(encrypted_stream, 16, encrypted_size-16);
+
+ // create the decrypting cipher
+ result = AP4_DecryptingStream::Create(cipher_mode,
+ *sub_stream,
+ cleartext_size,
+ iv,
+ 16,
+ key,
+ key_size,
+ block_cipher_factory,
+ stream);
+
+ // we don't keep our own reference to the sub stream
+ sub_stream->Release();
+
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfSampleDecrypter::Create
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfSampleDecrypter::Create(AP4_ProtectedSampleDescription* sample_description,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_OmaDcfSampleDecrypter*& cipher)
+{
+ // check the parameters
+ if (key == NULL || block_cipher_factory == NULL) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+
+ // default return value
+ cipher = NULL;
+
+ // get the scheme info atom
+ AP4_ContainerAtom* schi = sample_description->GetSchemeInfo()->GetSchiAtom();
+ if (schi == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // get and check the cipher params
+ // NOTE: we only support an IV Length less than or equal to the cipher block size,
+ // and we don't know how to deal with a key indicator length != 0
+ AP4_OdafAtom* odaf = AP4_DYNAMIC_CAST(AP4_OdafAtom, schi->FindChild("odkm/odaf"));
+ if (odaf) {
+ if (odaf->GetIvLength() > AP4_CIPHER_BLOCK_SIZE) return AP4_ERROR_INVALID_FORMAT;
+ if (odaf->GetKeyIndicatorLength() != 0) return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // check the scheme details and create the cipher
+ AP4_OhdrAtom* ohdr = AP4_DYNAMIC_CAST(AP4_OhdrAtom, schi->FindChild("odkm/ohdr"));
+ if (ohdr == NULL) return AP4_ERROR_INVALID_FORMAT;
+ AP4_UI08 encryption_method = ohdr->GetEncryptionMethod();
+ if (encryption_method == AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC) {
+ // in CBC mode, we only support IVs of the same size as the cipher block size
+ if (odaf->GetIvLength() != AP4_CIPHER_BLOCK_SIZE) return AP4_ERROR_INVALID_FORMAT;
+
+ // require RFC_2630 padding
+ if (ohdr->GetPaddingScheme() != AP4_OMA_DCF_PADDING_SCHEME_RFC_2630) {
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+
+ // create the block cipher
+ AP4_BlockCipher* block_cipher = NULL;
+ AP4_Result result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::DECRYPT,
+ key,
+ key_size,
+ block_cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // create the cipher
+ cipher = new AP4_OmaDcfCbcSampleDecrypter(block_cipher,
+ odaf->GetSelectiveEncryption());
+ return AP4_SUCCESS;
+ } else if (encryption_method == AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR) {
+ // require NONE padding
+ if (ohdr->GetPaddingScheme() != AP4_OMA_DCF_PADDING_SCHEME_NONE) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // create the block cipher
+ AP4_BlockCipher* block_cipher = NULL;
+ AP4_Result result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::ENCRYPT,
+ key,
+ key_size,
+ block_cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // create the cipher
+ cipher = new AP4_OmaDcfCtrSampleDecrypter(block_cipher,
+ odaf->GetIvLength(),
+ odaf->GetSelectiveEncryption());
+ return AP4_SUCCESS;
+ } else {
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleDecrypter::AP4_OmaDcfCtrSampleDecrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCtrSampleDecrypter::AP4_OmaDcfCtrSampleDecrypter(
+ AP4_BlockCipher* block_cipher,
+ AP4_Size iv_length,
+ bool selective_encryption) :
+ AP4_OmaDcfSampleDecrypter(iv_length, selective_encryption)
+{
+ m_Cipher = new AP4_CtrStreamCipher(block_cipher, NULL, iv_length);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleDecrypter::~AP4_OmaDcfCtrSampleDecrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCtrSampleDecrypter::~AP4_OmaDcfCtrSampleDecrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleDecrypter::DecryptSampleData
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfCtrSampleDecrypter::DecryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ const AP4_UI08* /*iv*/)
+{
+ bool is_encrypted = true;
+ const unsigned char* in = data_in.GetData();
+ AP4_Size in_size = data_in.GetDataSize();
+
+ // default to 0 output
+ AP4_CHECK(data_out.SetDataSize(0));
+
+ // check the selective encryption flag
+ if (m_SelectiveEncryption) {
+ if (in_size < 1) return AP4_ERROR_INVALID_FORMAT;
+ is_encrypted = ((in[0]&0x80)!=0);
+ in++;
+ }
+
+ // check the size
+ unsigned int header_size = (m_SelectiveEncryption?1:0)+(is_encrypted?m_IvLength:0);
+ if (header_size > in_size) return AP4_ERROR_INVALID_FORMAT;
+
+ // process the sample data
+ AP4_Size payload_size = in_size-header_size;
+ AP4_CHECK(data_out.Reserve(payload_size));
+ unsigned char* out = data_out.UseData();
+ if (is_encrypted) {
+ // set the IV
+ m_Cipher->SetIV(in);
+ AP4_CHECK(m_Cipher->ProcessBuffer(in+m_IvLength,
+ payload_size,
+ out));
+ } else {
+ AP4_CopyMemory(out, in, payload_size);
+ }
+ AP4_CHECK(data_out.SetDataSize(payload_size));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleDecrypter::GetDecryptedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_OmaDcfCtrSampleDecrypter::GetDecryptedSampleSize(AP4_Sample& sample)
+{
+ if (m_Cipher == NULL) return 0;
+
+ // decide if this sample is encrypted or not
+ bool is_encrypted;
+ if (m_SelectiveEncryption) {
+ // read the first byte to see if the sample is encrypted or not
+ AP4_Byte h;
+ AP4_DataBuffer peek_buffer;
+ peek_buffer.SetBuffer(&h, 1);
+ sample.ReadData(peek_buffer, 1);
+ is_encrypted = ((h&0x80)!=0);
+ } else {
+ is_encrypted = true;
+ }
+
+ AP4_Size crypto_header_size = (m_SelectiveEncryption?1:0)+(is_encrypted?m_IvLength:0);
+ return sample.GetSize()-crypto_header_size;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleDecrypter::AP4_OmaDcfCbcSampleDecrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCbcSampleDecrypter::AP4_OmaDcfCbcSampleDecrypter(
+ AP4_BlockCipher* block_cipher,
+ bool selective_encryption) :
+ AP4_OmaDcfSampleDecrypter(AP4_CIPHER_BLOCK_SIZE, selective_encryption)
+{
+ m_Cipher = new AP4_CbcStreamCipher(block_cipher, AP4_CbcStreamCipher::DECRYPT);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleDecrypter::~AP4_OmaDcfCbcSampleDecrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCbcSampleDecrypter::~AP4_OmaDcfCbcSampleDecrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDbcCbcSampleDecrypter::DecryptSampleData
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfCbcSampleDecrypter::DecryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ const AP4_UI08* /*iv*/)
+{
+ bool is_encrypted = true;
+ const unsigned char* in = data_in.GetData();
+ AP4_Size in_size = data_in.GetDataSize();
+ AP4_Size out_size;
+
+ // default to 0 output
+ AP4_CHECK(data_out.SetDataSize(0));
+
+ // check the selective encryption flag
+ if (m_SelectiveEncryption) {
+ if (in_size < 1) return AP4_ERROR_INVALID_FORMAT;
+ is_encrypted = ((in[0]&0x80)!=0);
+ in++;
+ }
+
+ // check the size
+ unsigned int header_size = (m_SelectiveEncryption?1:0)+(is_encrypted?m_IvLength:0);
+ if (header_size > in_size) return AP4_ERROR_INVALID_FORMAT;
+
+ // process the sample data
+ unsigned int payload_size = in_size-header_size;
+ data_out.Reserve(payload_size);
+ unsigned char* out = data_out.UseData();
+ if (is_encrypted) {
+ // get the IV
+ const AP4_UI08* iv = (const AP4_UI08*)in;
+ in += AP4_CIPHER_BLOCK_SIZE;
+
+ m_Cipher->SetIV(iv);
+ out_size = payload_size;
+ AP4_CHECK(m_Cipher->ProcessBuffer(in, payload_size, out, &out_size, true));
+ } else {
+ AP4_CopyMemory(out, in, payload_size);
+ out_size = payload_size;
+ }
+
+ AP4_CHECK(data_out.SetDataSize(out_size));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleDecrypter::GetDecryptedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_OmaDcfCbcSampleDecrypter::GetDecryptedSampleSize(AP4_Sample& sample)
+{
+ if (m_Cipher == NULL) return 0;
+
+ // decide if this sample is encrypted or not
+ bool is_encrypted;
+ if (m_SelectiveEncryption) {
+ // read the first byte to see if the sample is encrypted or not
+ AP4_Byte h;
+ AP4_DataBuffer peek_buffer;
+ peek_buffer.SetBuffer(&h, 1);
+ sample.ReadData(peek_buffer, 1);
+ is_encrypted = ((h&0x80)!=0);
+ } else {
+ is_encrypted = true;
+ }
+
+ if (is_encrypted) {
+ // with CBC, we need to decrypt the last block to know what the padding was
+ AP4_Size crypto_header_size = (m_SelectiveEncryption?1:0)+m_IvLength;
+ AP4_Size encrypted_size = sample.GetSize()-crypto_header_size;
+ AP4_DataBuffer encrypted;
+ AP4_DataBuffer decrypted;
+ AP4_Size decrypted_size = AP4_CIPHER_BLOCK_SIZE;
+ if (sample.GetSize() < crypto_header_size+AP4_CIPHER_BLOCK_SIZE) {
+ return 0;
+ }
+ AP4_Size offset = sample.GetSize()-2*AP4_CIPHER_BLOCK_SIZE;
+ if (AP4_FAILED(sample.ReadData(encrypted, 2*AP4_CIPHER_BLOCK_SIZE, offset))) {
+ return 0;
+ }
+ decrypted.Reserve(decrypted_size);
+ m_Cipher->SetIV(encrypted.GetData());
+ if (AP4_FAILED(m_Cipher->ProcessBuffer(encrypted.GetData()+AP4_CIPHER_BLOCK_SIZE,
+ AP4_CIPHER_BLOCK_SIZE,
+ decrypted.UseData(),
+ &decrypted_size,
+ true))) {
+ return 0;
+ }
+ unsigned int padding_size = AP4_CIPHER_BLOCK_SIZE-decrypted_size;
+ return encrypted_size-padding_size;
+ } else {
+ return sample.GetSize()-(m_SelectiveEncryption?1:0);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfSampleEncrypter::AP4_OmaDcfSampleEncrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfSampleEncrypter::AP4_OmaDcfSampleEncrypter(const AP4_UI08* salt)
+{
+ // left-align the salt
+ unsigned int i=0;
+ if (salt) {
+ for (; i<8; i++) {
+ m_Salt[i] = salt[i];
+ }
+ }
+ for (; i<sizeof(m_Salt)/sizeof(m_Salt[0]); i++) {
+ m_Salt[i] = 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleEncrypter::AP4_OmaDcfCtrSampleEncrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCtrSampleEncrypter::AP4_OmaDcfCtrSampleEncrypter(AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt) :
+ AP4_OmaDcfSampleEncrypter(salt)
+{
+ m_Cipher = new AP4_CtrStreamCipher(block_cipher, m_Salt, 8);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleEncrypter::~AP4_OmaDcfCtrSampleEncrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCtrSampleEncrypter::~AP4_OmaDcfCtrSampleEncrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleEncrypter::EncryptSampleData
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfCtrSampleEncrypter::EncryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ AP4_UI64 counter,
+ bool /*skip_encryption*/)
+{
+ // setup the buffers
+ const unsigned char* in = data_in.GetData();
+ AP4_CHECK(data_out.SetDataSize(data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE+1));
+ unsigned char* out = data_out.UseData();
+
+ // selective encryption flag
+ *out++ = 0x80;
+
+ // IV on 16 bytes: [SSSSSSSSXXXXXXXX]
+ // where SSSSSSSS is the 64-bit salt and
+ // XXXXXXXX is the 64-bit base counter
+ AP4_CopyMemory(out, m_Salt, 8);
+ AP4_BytesFromUInt64BE(&out[8], counter);
+
+ // encrypt the payload
+ AP4_Size data_size = data_in.GetDataSize();
+ m_Cipher->SetIV(out+8);
+ m_Cipher->ProcessBuffer(in, data_size, out+AP4_CIPHER_BLOCK_SIZE);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleEncrypter::GetEncryptedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_OmaDcfCtrSampleEncrypter::GetEncryptedSampleSize(AP4_Sample& sample)
+{
+ return sample.GetSize()+AP4_CIPHER_BLOCK_SIZE+1;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleEncrypter::AP4_OmaDcfCbcSampleEncrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCbcSampleEncrypter::AP4_OmaDcfCbcSampleEncrypter(AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt) :
+ AP4_OmaDcfSampleEncrypter(salt)
+{
+ m_Cipher = new AP4_CbcStreamCipher(block_cipher, AP4_CbcStreamCipher::ENCRYPT);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleEncrypter::~AP4_OmaDcfCbcSampleEncrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfCbcSampleEncrypter::~AP4_OmaDcfCbcSampleEncrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleEncrypter::EncryptSampleData
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfCbcSampleEncrypter::EncryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ AP4_UI64 counter,
+ bool /*skip_encryption*/)
+{
+ // make sure there is enough space in the output buffer
+ data_out.Reserve(data_in.GetDataSize()+2*AP4_CIPHER_BLOCK_SIZE+1);
+
+ // setup the buffers
+ AP4_Size out_size = data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE;
+ unsigned char* out = data_out.UseData();
+
+ // selective encryption flag
+ *out++ = 0x80;
+
+ // IV on 16 bytes: [SSSSSSSSXXXXXXXX]
+ // where SSSSSSSS is the 64-bit salt and
+ // XXXXXXXX is the 64-bit base counter
+ AP4_CopyMemory(out, m_Salt, 8);
+ AP4_BytesFromUInt64BE(&out[8], counter);
+
+ // encrypt the payload
+ m_Cipher->SetIV(out);
+ m_Cipher->ProcessBuffer(data_in.GetData(),
+ data_in.GetDataSize(),
+ out+AP4_CIPHER_BLOCK_SIZE,
+ &out_size,
+ true);
+ AP4_CHECK(data_out.SetDataSize(out_size+AP4_CIPHER_BLOCK_SIZE+1));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleEncrypter::GetEncryptedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_OmaDcfCbcSampleEncrypter::GetEncryptedSampleSize(AP4_Sample& sample)
+{
+ AP4_Size sample_size = sample.GetSize();
+ AP4_Size padding_size = AP4_CIPHER_BLOCK_SIZE-(sample_size%AP4_CIPHER_BLOCK_SIZE);
+ return sample_size+padding_size+AP4_CIPHER_BLOCK_SIZE+1;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackDecrypter::Create
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfTrackDecrypter::Create(
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_ProtectedSampleDescription* sample_description,
+ AP4_SampleEntry* sample_entry,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_OmaDcfTrackDecrypter*& decrypter)
+{
+ // check and set defaults
+ if (key == NULL) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+ if (block_cipher_factory == NULL) {
+ block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
+ }
+ decrypter = NULL;
+
+ // create the cipher
+ AP4_OmaDcfSampleDecrypter* cipher = NULL;
+ AP4_Result result = AP4_OmaDcfSampleDecrypter::Create(sample_description,
+ key,
+ key_size,
+ block_cipher_factory,
+ cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // instantiate the object
+ decrypter = new AP4_OmaDcfTrackDecrypter(cipher,
+ sample_entry,
+ sample_description->GetOriginalFormat());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackDecrypter::AP4_OmaDcfTrackDecrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfTrackDecrypter::AP4_OmaDcfTrackDecrypter(AP4_OmaDcfSampleDecrypter* cipher,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 original_format) :
+ m_Cipher(cipher),
+ m_SampleEntry(sample_entry),
+ m_OriginalFormat(original_format)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackDecrypter::~AP4_OmaDcfTrackDecrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfTrackDecrypter::~AP4_OmaDcfTrackDecrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackDecrypter::GetProcessedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_OmaDcfTrackDecrypter::GetProcessedSampleSize(AP4_Sample& sample)
+{
+ if (m_Cipher == NULL) return 0;
+ return m_Cipher->GetDecryptedSampleSize(sample);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackDecrypter::ProcessTrack
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfTrackDecrypter::ProcessTrack()
+{
+ m_SampleEntry->SetType(m_OriginalFormat);
+ m_SampleEntry->DeleteChild(AP4_ATOM_TYPE_SINF);
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfDecrypter::ProcessSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfTrackDecrypter::ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out)
+{
+ return m_Cipher->DecryptSampleData(data_in, data_out);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackEncrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfTrackEncrypter : public AP4_Processor::TrackHandler {
+public:
+ // constructor
+ AP4_OmaDcfTrackEncrypter(AP4_OmaDcfCipherMode cipher_mode,
+ AP4_BlockCipher* block_cipher,
+ const AP4_UI08* iv,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 format,
+ const char* content_id,
+ const char* rights_issuer_url,
+ const AP4_Byte* textual_headers,
+ AP4_Size textual_headers_size);
+ virtual ~AP4_OmaDcfTrackEncrypter();
+
+ // methods
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
+ virtual AP4_Result ProcessTrack();
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out);
+
+private:
+ // members
+ AP4_OmaDcfSampleEncrypter* m_Cipher;
+ AP4_UI08 m_CipherMode;
+ AP4_UI08 m_CipherPadding;
+ AP4_SampleEntry* m_SampleEntry;
+ AP4_UI32 m_Format;
+ AP4_String m_ContentId;
+ AP4_String m_RightsIssuerUrl;
+ AP4_DataBuffer m_TextualHeaders;
+ AP4_UI64 m_Counter;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackEncrypter::AP4_OmaDcfTrackEncrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfTrackEncrypter::AP4_OmaDcfTrackEncrypter(
+ AP4_OmaDcfCipherMode cipher_mode,
+ AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 format,
+ const char* content_id,
+ const char* rights_issuer_url,
+ const AP4_Byte* textual_headers,
+ AP4_Size textual_headers_size) :
+ m_SampleEntry(sample_entry),
+ m_Format(format),
+ m_ContentId(content_id),
+ m_RightsIssuerUrl(rights_issuer_url),
+ m_TextualHeaders(textual_headers, textual_headers_size),
+ m_Counter(0)
+{
+ // instantiate the cipher (fixed params for now)
+ if (cipher_mode == AP4_OMA_DCF_CIPHER_MODE_CBC) {
+ m_Cipher = new AP4_OmaDcfCbcSampleEncrypter(block_cipher, salt);
+ m_CipherMode = AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CBC;
+ m_CipherPadding = AP4_OMA_DCF_PADDING_SCHEME_RFC_2630;
+ } else {
+ m_Cipher = new AP4_OmaDcfCtrSampleEncrypter(block_cipher, salt);
+ m_CipherMode = AP4_OMA_DCF_ENCRYPTION_METHOD_AES_CTR;
+ m_CipherPadding = AP4_OMA_DCF_PADDING_SCHEME_NONE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackEncrypter::~AP4_OmaDcfTrackEncrypter
++---------------------------------------------------------------------*/
+AP4_OmaDcfTrackEncrypter::~AP4_OmaDcfTrackEncrypter()
+{
+ delete m_Cipher;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackEncrypter::GetProcessedSampleSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_OmaDcfTrackEncrypter::GetProcessedSampleSize(AP4_Sample& sample)
+{
+ return m_Cipher->GetEncryptedSampleSize(sample);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackEncrypter::ProcessTrack
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfTrackEncrypter::ProcessTrack()
+{
+ // sinf container
+ AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
+
+ // original format
+ AP4_FrmaAtom* frma = new AP4_FrmaAtom(m_SampleEntry->GetType());
+
+ // scheme info
+ AP4_ContainerAtom* schi = new AP4_ContainerAtom(AP4_ATOM_TYPE_SCHI);
+ AP4_OdafAtom* odaf = new AP4_OdafAtom(true, 0, AP4_CIPHER_BLOCK_SIZE);
+ AP4_OhdrAtom* ohdr = new AP4_OhdrAtom(m_CipherMode,
+ m_CipherPadding,
+ 0,
+ m_ContentId.GetChars(),
+ m_RightsIssuerUrl.GetChars(),
+ m_TextualHeaders.GetData(),
+ m_TextualHeaders.GetDataSize());
+ AP4_ContainerAtom* odkm = new AP4_ContainerAtom(AP4_ATOM_TYPE_ODKM, (AP4_UI32)0, (AP4_UI32)0);
+ AP4_SchmAtom* schm = new AP4_SchmAtom(AP4_PROTECTION_SCHEME_TYPE_OMA,
+ AP4_PROTECTION_SCHEME_VERSION_OMA_20);
+ odkm->AddChild(odaf);
+ odkm->AddChild(ohdr);
+
+ // populate the schi container
+ schi->AddChild(odkm);
+
+ // populate the sinf container
+ sinf->AddChild(frma);
+ sinf->AddChild(schm);
+ sinf->AddChild(schi);
+
+ // add the sinf atom to the sample description
+ m_SampleEntry->AddChild(sinf);
+
+ // change the atom type of the sample description
+ m_SampleEntry->SetType(m_Format);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackEncrypter::ProcessSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out)
+{
+ AP4_Result result = m_Cipher->EncryptSampleData(data_in,
+ data_out,
+ m_Counter,
+ false);
+ if (AP4_FAILED(result)) return result;
+
+ m_Counter += (data_in.GetDataSize()+AP4_CIPHER_BLOCK_SIZE-1)/AP4_CIPHER_BLOCK_SIZE;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfDecryptingProcessor:AP4_OmaDcfDecryptingProcessor
++---------------------------------------------------------------------*/
+AP4_OmaDcfDecryptingProcessor::AP4_OmaDcfDecryptingProcessor(
+ const AP4_ProtectionKeyMap* key_map /* = NULL */,
+ AP4_BlockCipherFactory* block_cipher_factory /* = NULL */)
+{
+ if (key_map) {
+ // copy the keys
+ m_KeyMap.SetKeys(*key_map);
+ }
+
+ if (block_cipher_factory == NULL) {
+ m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
+ } else {
+ m_BlockCipherFactory = block_cipher_factory;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfDecryptingProcessor:Initialize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfDecryptingProcessor::Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& /* stream */,
+ ProgressListener* listener)
+{
+ // decide which processor to instantiate based on the file type
+ AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
+ if (ftyp) {
+ if (ftyp->GetMajorBrand() == AP4_OMA_DCF_BRAND_ODCF || ftyp->HasCompatibleBrand(AP4_OMA_DCF_BRAND_ODCF)) {
+ return AP4_OmaDcfAtomDecrypter::DecryptAtoms(top_level, listener, m_BlockCipherFactory, m_KeyMap);
+ } else {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+ } else {
+ return AP4_SUCCESS;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfEncryptingProcessor:AP4_OmaDcfEncryptingProcessor
++---------------------------------------------------------------------*/
+AP4_OmaDcfEncryptingProcessor::AP4_OmaDcfEncryptingProcessor(AP4_OmaDcfCipherMode cipher_mode,
+ AP4_BlockCipherFactory* block_cipher_factory) :
+ m_CipherMode(cipher_mode)
+{
+ if (block_cipher_factory == NULL) {
+ m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
+ } else {
+ m_BlockCipherFactory = block_cipher_factory;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfEncryptingProcessor::Initialize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_OmaDcfEncryptingProcessor::Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& /*stream*/,
+ AP4_Processor::ProgressListener* /*listener*/)
+{
+ AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
+ if (ftyp) {
+ // remove the atom, it will be replaced with a new one
+ top_level.RemoveChild(ftyp);
+
+ // keep the existing brand and compatible brands
+ AP4_Array<AP4_UI32> compatible_brands;
+ compatible_brands.EnsureCapacity(ftyp->GetCompatibleBrands().ItemCount()+1);
+ for (unsigned int i=0; i<ftyp->GetCompatibleBrands().ItemCount(); i++) {
+ compatible_brands.Append(ftyp->GetCompatibleBrands()[i]);
+ }
+
+ // add the OMA compatible brand if it is not already there
+ if (!ftyp->HasCompatibleBrand(AP4_OMA_DCF_BRAND_OPF2)) {
+ compatible_brands.Append(AP4_OMA_DCF_BRAND_OPF2);
+ }
+
+ // create a replacement
+ AP4_FtypAtom* new_ftyp = new AP4_FtypAtom(ftyp->GetMajorBrand(),
+ ftyp->GetMinorVersion(),
+ &compatible_brands[0],
+ compatible_brands.ItemCount());
+ delete ftyp;
+ ftyp = new_ftyp;
+ } else {
+ AP4_UI32 opf2 = AP4_OMA_DCF_BRAND_OPF2;
+ ftyp = new AP4_FtypAtom(AP4_FTYP_BRAND_ISOM, 0, &opf2, 1);
+ }
+
+ // insert the ftyp atom as the first child
+ return top_level.AddChild(ftyp, 0);
+}
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfEncryptingProcessor:CreateTrackHandler
++---------------------------------------------------------------------*/
+AP4_Processor::TrackHandler*
+AP4_OmaDcfEncryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
+{
+ // find the stsd atom
+ AP4_StsdAtom* stsd = AP4_DYNAMIC_CAST(AP4_StsdAtom, trak->FindChild("mdia/minf/stbl/stsd"));
+
+ // avoid tracks with no stsd atom (should not happen)
+ if (stsd == NULL) return NULL;
+
+ // only look at the first sample description
+ AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
+ if (entry == NULL) return NULL;
+
+ // create a handler for this track if we have a key for it and we know
+ // how to map the type
+ const AP4_UI08* key;
+ const AP4_UI08* iv;
+ AP4_UI32 format = 0;
+ if (AP4_SUCCEEDED(m_KeyMap.GetKeyAndIv(trak->GetId(), key, iv))) {
+ switch (entry->GetType()) {
+ case AP4_ATOM_TYPE_MP4A:
+ format = AP4_ATOM_TYPE_ENCA;
+ break;
+
+ case AP4_ATOM_TYPE_MP4V:
+ case AP4_ATOM_TYPE_AVC1:
+ format = AP4_ATOM_TYPE_ENCV;
+ break;
+
+ default: {
+ // try to find if this is audio or video
+ AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, trak->FindChild("mdia/hdlr"));
+ if (hdlr) {
+ switch (hdlr->GetHandlerType()) {
+ case AP4_HANDLER_TYPE_SOUN:
+ format = AP4_ATOM_TYPE_ENCA;
+ break;
+
+ case AP4_HANDLER_TYPE_VIDE:
+ format = AP4_ATOM_TYPE_ENCV;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if (format) {
+ const char* content_id = m_PropertyMap.GetProperty(trak->GetId(), "ContentId");
+ const char* rights_issuer_url = m_PropertyMap.GetProperty(trak->GetId(), "RightsIssuerUrl");
+ AP4_DataBuffer textual_headers;
+ AP4_Result result = m_PropertyMap.GetTextualHeaders(trak->GetId(), textual_headers);
+ if (AP4_FAILED(result)) textual_headers.SetDataSize(0);
+
+ // create the block cipher
+ AP4_BlockCipher* block_cipher = NULL;
+ result = m_BlockCipherFactory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::ENCRYPT,
+ key,
+ AP4_CIPHER_BLOCK_SIZE,
+ block_cipher);
+ if (AP4_FAILED(result)) return NULL;
+ return new AP4_OmaDcfTrackEncrypter(m_CipherMode,
+ block_cipher,
+ iv,
+ entry,
+ format,
+ content_id,
+ rights_issuer_url,
+ textual_headers.GetData(),
+ textual_headers.GetDataSize());
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.h
index 806f6f0db..403866c16 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4OmaDcf.h
@@ -1,322 +1,337 @@
-/*****************************************************************
-|
-| AP4 - OMA DCF support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-#ifndef _AP4_OMA_DCF_H_
-#define _AP4_OMA_DCF_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4SampleEntry.h"
-#include "Ap4Atom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4SampleDescription.h"
-#include "Ap4Processor.h"
-#include "Ap4Protection.h"
-
-/*----------------------------------------------------------------------
-| class references
-+---------------------------------------------------------------------*/
-class AP4_OdafAtom;
-class AP4_StreamCipher;
-class AP4_CbcStreamCipher;
-class AP4_CtrStreamCipher;
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_OMA = AP4_ATOM_TYPE('o','d','k','m');
-const AP4_UI32 AP4_PROTECTION_SCHEME_VERSION_OMA_20 = 0x00000200;
-const AP4_UI32 AP4_OMA_DCF_BRAND_ODCF = AP4_ATOM_TYPE('o','d','c','f');
-const AP4_UI32 AP4_OMA_DCF_BRAND_OPF2 = AP4_ATOM_TYPE('o','p','f','2');
-
-typedef enum {
- AP4_OMA_DCF_CIPHER_MODE_CTR,
- AP4_OMA_DCF_CIPHER_MODE_CBC
-} AP4_OmaDcfCipherMode;
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfAtomDecrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfAtomDecrypter {
-public:
- // class methods
- static AP4_Result DecryptAtoms(AP4_AtomParent& atoms,
- AP4_Processor::ProgressListener* listener,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ProtectionKeyMap& key_map);
-
- // Returns a byte stream that will produce the decrypted data found
- // in the 'odda' child atom of an 'odrm' atom
- static AP4_Result CreateDecryptingStream(AP4_ContainerAtom& odrm_atom,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream);
-
- // Returns a byte stream that will produce the decrypted data from
- // an encrypted stream where the IV follows the encrypted bytes.
- // This method is normally not called directly: most callers will call
- // the stream factory that takes an 'odrm' atom as an input parameter
- static AP4_Result CreateDecryptingStream(AP4_OmaDcfCipherMode mode,
- AP4_ByteStream& encrypted_stream,
- AP4_LargeSize cleartext_size,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream);
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfSampleDecrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfSampleDecrypter : public AP4_SampleDecrypter
-{
-public:
- // factory
- static AP4_Result Create(AP4_ProtectedSampleDescription* sample_description,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_OmaDcfSampleDecrypter*& cipher);
-
- // constructor and destructor
- AP4_OmaDcfSampleDecrypter(AP4_Size iv_length,
- bool selective_encryption) :
- m_IvLength(iv_length),
- m_SelectiveEncryption(selective_encryption) {}
-
-protected:
- AP4_Size m_IvLength;
- AP4_Size m_KeyIndicatorLength;
- bool m_SelectiveEncryption;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleDecrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfCtrSampleDecrypter : public AP4_OmaDcfSampleDecrypter
-{
-public:
- // constructor and destructor
- AP4_OmaDcfCtrSampleDecrypter(AP4_BlockCipher* block_cipher,
- AP4_Size iv_length,
- bool selective_encryption);
- ~AP4_OmaDcfCtrSampleDecrypter();
-
- // methods
- virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- const AP4_UI08* iv = NULL);
- virtual AP4_Size GetDecryptedSampleSize(AP4_Sample& sample);
-
-private:
- // members
- AP4_CtrStreamCipher* m_Cipher;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleDecrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfCbcSampleDecrypter : public AP4_OmaDcfSampleDecrypter
-{
-public:
- // constructor and destructor
- AP4_OmaDcfCbcSampleDecrypter(AP4_BlockCipher* block_cipher,
- bool selective_encryption);
- ~AP4_OmaDcfCbcSampleDecrypter();
-
- // methods
- virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- const AP4_UI08* iv = NULL);
- virtual AP4_Size GetDecryptedSampleSize(AP4_Sample& sample);
-
-private:
- // members
- AP4_CbcStreamCipher* m_Cipher;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfTrackDecrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfTrackDecrypter : public AP4_Processor::TrackHandler {
-public:
- // constructor
- static AP4_Result Create(const AP4_UI08* key,
- AP4_Size key_size,
- AP4_ProtectedSampleDescription* sample_description,
- AP4_SampleEntry* sample_entry,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_OmaDcfTrackDecrypter*& decrypter);
- virtual ~AP4_OmaDcfTrackDecrypter();
-
- // methods
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
- virtual AP4_Result ProcessTrack();
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out);
-
-private:
- // constructor
- AP4_OmaDcfTrackDecrypter(AP4_OmaDcfSampleDecrypter* cipher,
- AP4_SampleEntry* sample_entry,
- AP4_UI32 original_format);
-
- // members
- AP4_OmaDcfSampleDecrypter* m_Cipher;
- AP4_SampleEntry* m_SampleEntry;
- AP4_UI32 m_OriginalFormat;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfSampleEncrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfSampleEncrypter
-{
-public:
- // constructor and destructor
- AP4_OmaDcfSampleEncrypter(const AP4_UI08* salt); // salt is only 8 bytes
- virtual ~AP4_OmaDcfSampleEncrypter() {}
-
- // methods
- virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- AP4_UI64 bso,
- bool skip_encryption) = 0;
- virtual AP4_Size GetEncryptedSampleSize(AP4_Sample& sample) = 0;
-
-protected:
- // members
- AP4_UI08 m_Salt[16];
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCtrSampleEncrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfCtrSampleEncrypter : public AP4_OmaDcfSampleEncrypter
-{
-public:
- // constructor and destructor
- AP4_OmaDcfCtrSampleEncrypter(AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt); // salt is only 8 bytes
- ~AP4_OmaDcfCtrSampleEncrypter();
-
- // methods
- virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- AP4_UI64 bso,
- bool skip_encryption);
- virtual AP4_Size GetEncryptedSampleSize(AP4_Sample& sample);
-
-private:
- // members
- AP4_CtrStreamCipher* m_Cipher;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfCbcSampleEncrypter
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfCbcSampleEncrypter : public AP4_OmaDcfSampleEncrypter
-{
-public:
- // constructor and destructor
- AP4_OmaDcfCbcSampleEncrypter(AP4_BlockCipher* block_cipher,
- const AP4_UI08* salt); // salt is only 8 bytes
- ~AP4_OmaDcfCbcSampleEncrypter();
-
- // methods
- virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- AP4_UI64 bso,
- bool skip_encryption);
- virtual AP4_Size GetEncryptedSampleSize(AP4_Sample& sample);
-
-private:
- // members
- AP4_CbcStreamCipher* m_Cipher;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfDecryptingProcessor
-+---------------------------------------------------------------------*/
-/**
- * Use for DCF only, not PDCF. For PDCF, use the
- * AP4_StandardDecryptingProcessor class
- */
-class AP4_OmaDcfDecryptingProcessor : public AP4_Processor
-{
-public:
- // constructor
- AP4_OmaDcfDecryptingProcessor(const AP4_ProtectionKeyMap* key_map = NULL,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
-
- // accessors
- AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
-
- // methods
- virtual AP4_Result Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- ProgressListener* listener);
-
-private:
- // members
- AP4_BlockCipherFactory* m_BlockCipherFactory;
- AP4_ProtectionKeyMap m_KeyMap;
-};
-
-/*----------------------------------------------------------------------
-| AP4_OmaDcfEncryptingProcessor
-+---------------------------------------------------------------------*/
-class AP4_OmaDcfEncryptingProcessor : public AP4_Processor
-{
-public:
- // constructor
- AP4_OmaDcfEncryptingProcessor(AP4_OmaDcfCipherMode cipher_mode,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
-
- // accessors
- AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
- AP4_TrackPropertyMap& GetPropertyMap() { return m_PropertyMap; }
-
- // AP4_Processor methods
- virtual AP4_Result Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- AP4_Processor::ProgressListener* listener = NULL);
- virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
-
-private:
- // members
- AP4_OmaDcfCipherMode m_CipherMode;
- AP4_BlockCipherFactory* m_BlockCipherFactory;
- AP4_ProtectionKeyMap m_KeyMap;
- AP4_TrackPropertyMap m_PropertyMap;
-};
-
-#endif // _AP4_OMA_DCF_H_
+/*****************************************************************
+|
+| AP4 - OMA DCF support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+#ifndef _AP4_OMA_DCF_H_
+#define _AP4_OMA_DCF_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4SampleEntry.h"
+#include "Ap4Atom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4SampleDescription.h"
+#include "Ap4Processor.h"
+#include "Ap4Protection.h"
+#include "Ap4DynamicCast.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class AP4_OdafAtom;
+class AP4_StreamCipher;
+class AP4_CbcStreamCipher;
+class AP4_CtrStreamCipher;
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_OMA = AP4_ATOM_TYPE('o','d','k','m');
+const AP4_UI32 AP4_PROTECTION_SCHEME_VERSION_OMA_20 = 0x00000200;
+const AP4_UI32 AP4_OMA_DCF_BRAND_ODCF = AP4_ATOM_TYPE('o','d','c','f');
+const AP4_UI32 AP4_OMA_DCF_BRAND_OPF2 = AP4_ATOM_TYPE('o','p','f','2');
+
+typedef enum {
+ AP4_OMA_DCF_CIPHER_MODE_CTR,
+ AP4_OMA_DCF_CIPHER_MODE_CBC
+} AP4_OmaDcfCipherMode;
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfAtomDecrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfAtomDecrypter {
+public:
+ // class methods
+ static AP4_Result DecryptAtoms(AP4_AtomParent& atoms,
+ AP4_Processor::ProgressListener* listener,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ProtectionKeyMap& key_map);
+
+ // Returns a byte stream that will produce the decrypted data found
+ // in the 'odda' child atom of an 'odrm' atom
+ static AP4_Result CreateDecryptingStream(AP4_ContainerAtom& odrm_atom,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream);
+
+ // Returns a byte stream that will produce the decrypted data from
+ // an encrypted stream where the IV follows the encrypted bytes.
+ // This method is normally not called directly: most callers will call
+ // the stream factory that takes an 'odrm' atom as an input parameter
+ static AP4_Result CreateDecryptingStream(AP4_OmaDcfCipherMode mode,
+ AP4_ByteStream& encrypted_stream,
+ AP4_LargeSize cleartext_size,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream);
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfSampleDecrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfSampleDecrypter : public AP4_SampleDecrypter
+{
+public:
+ // factory
+ static AP4_Result Create(AP4_ProtectedSampleDescription* sample_description,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_OmaDcfSampleDecrypter*& cipher);
+
+ // constructor and destructor
+ AP4_OmaDcfSampleDecrypter(AP4_Size iv_length,
+ bool selective_encryption) :
+ m_IvLength(iv_length),
+ m_SelectiveEncryption(selective_encryption) {}
+
+protected:
+ AP4_Size m_IvLength;
+ AP4_Size m_KeyIndicatorLength;
+ bool m_SelectiveEncryption;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleDecrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfCtrSampleDecrypter : public AP4_OmaDcfSampleDecrypter
+{
+public:
+ // constructor and destructor
+ AP4_OmaDcfCtrSampleDecrypter(AP4_BlockCipher* block_cipher,
+ AP4_Size iv_length,
+ bool selective_encryption);
+ ~AP4_OmaDcfCtrSampleDecrypter();
+
+ // methods
+ virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ const AP4_UI08* iv = NULL);
+ virtual AP4_Size GetDecryptedSampleSize(AP4_Sample& sample);
+
+private:
+ // members
+ AP4_CtrStreamCipher* m_Cipher;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleDecrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfCbcSampleDecrypter : public AP4_OmaDcfSampleDecrypter
+{
+public:
+ // constructor and destructor
+ AP4_OmaDcfCbcSampleDecrypter(AP4_BlockCipher* block_cipher,
+ bool selective_encryption);
+ ~AP4_OmaDcfCbcSampleDecrypter();
+
+ // methods
+ virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ const AP4_UI08* iv = NULL);
+ virtual AP4_Size GetDecryptedSampleSize(AP4_Sample& sample);
+
+private:
+ // members
+ AP4_CbcStreamCipher* m_Cipher;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfTrackDecrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfTrackDecrypter : public AP4_Processor::TrackHandler {
+public:
+ // constructor
+ static AP4_Result Create(const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_ProtectedSampleDescription* sample_description,
+ AP4_SampleEntry* sample_entry,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_OmaDcfTrackDecrypter*& decrypter);
+ virtual ~AP4_OmaDcfTrackDecrypter();
+
+ // methods
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample);
+ virtual AP4_Result ProcessTrack();
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out);
+
+private:
+ // constructor
+ AP4_OmaDcfTrackDecrypter(AP4_OmaDcfSampleDecrypter* cipher,
+ AP4_SampleEntry* sample_entry,
+ AP4_UI32 original_format);
+
+ // members
+ AP4_OmaDcfSampleDecrypter* m_Cipher;
+ AP4_SampleEntry* m_SampleEntry;
+ AP4_UI32 m_OriginalFormat;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfSampleEncrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfSampleEncrypter
+{
+public:
+ // constructor and destructor
+ AP4_OmaDcfSampleEncrypter(const AP4_UI08* salt); // salt is only 8 bytes
+ virtual ~AP4_OmaDcfSampleEncrypter() {}
+
+ // methods
+ virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ AP4_UI64 bso,
+ bool skip_encryption) = 0;
+ virtual AP4_Size GetEncryptedSampleSize(AP4_Sample& sample) = 0;
+
+protected:
+ // members
+ AP4_UI08 m_Salt[16];
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCtrSampleEncrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfCtrSampleEncrypter : public AP4_OmaDcfSampleEncrypter
+{
+public:
+ // constructor and destructor
+ AP4_OmaDcfCtrSampleEncrypter(AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt); // salt is only 8 bytes
+ ~AP4_OmaDcfCtrSampleEncrypter();
+
+ // methods
+ virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ AP4_UI64 bso,
+ bool skip_encryption);
+ virtual AP4_Size GetEncryptedSampleSize(AP4_Sample& sample);
+
+private:
+ // members
+ AP4_CtrStreamCipher* m_Cipher;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfCbcSampleEncrypter
++---------------------------------------------------------------------*/
+class AP4_OmaDcfCbcSampleEncrypter : public AP4_OmaDcfSampleEncrypter
+{
+public:
+ // constructor and destructor
+ AP4_OmaDcfCbcSampleEncrypter(AP4_BlockCipher* block_cipher,
+ const AP4_UI08* salt); // salt is only 8 bytes
+ ~AP4_OmaDcfCbcSampleEncrypter();
+
+ // methods
+ virtual AP4_Result EncryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ AP4_UI64 bso,
+ bool skip_encryption);
+ virtual AP4_Size GetEncryptedSampleSize(AP4_Sample& sample);
+
+private:
+ // members
+ AP4_CbcStreamCipher* m_Cipher;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfDecryptingProcessor
++---------------------------------------------------------------------*/
+/**
+ * Use for DCF only, not PDCF. For PDCF, use the
+ * AP4_StandardDecryptingProcessor class
+ */
+class AP4_OmaDcfDecryptingProcessor : public AP4_Processor
+{
+public:
+ // constructor
+ AP4_OmaDcfDecryptingProcessor(const AP4_ProtectionKeyMap* key_map = NULL,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+
+ // accessors
+ AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
+
+ // methods
+ virtual AP4_Result Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ ProgressListener* listener);
+
+private:
+ // members
+ AP4_BlockCipherFactory* m_BlockCipherFactory;
+ AP4_ProtectionKeyMap m_KeyMap;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDcfEncryptingProcessor
++---------------------------------------------------------------------*/
+class AP4_OmaDcfEncryptingProcessor : public AP4_Processor
+{
+public:
+ // constructor
+ AP4_OmaDcfEncryptingProcessor(AP4_OmaDcfCipherMode cipher_mode,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+
+ // accessors
+ AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
+ AP4_TrackPropertyMap& GetPropertyMap() { return m_PropertyMap; }
+
+ // AP4_Processor methods
+ virtual AP4_Result Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ AP4_Processor::ProgressListener* listener = NULL);
+ virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
+
+private:
+ // members
+ AP4_OmaDcfCipherMode m_CipherMode;
+ AP4_BlockCipherFactory* m_BlockCipherFactory;
+ AP4_ProtectionKeyMap m_KeyMap;
+ AP4_TrackPropertyMap m_PropertyMap;
+};
+
+/*----------------------------------------------------------------------
+| AP4_OmaDrmInfo
++---------------------------------------------------------------------*/
+class AP4_OmaDrmInfo
+{
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST(AP4_OmaDrmInfo)
+ virtual ~AP4_OmaDrmInfo() {}
+ virtual const AP4_String& GetContentId() const = 0;
+ virtual const AP4_String& GetRightsIssuerUrl() const = 0;
+ virtual const AP4_DataBuffer& GetTextualHeaders() const = 0;
+};
+
+
+#endif // _AP4_OMA_DCF_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.cpp
index f442658ff..988639c9f 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.cpp
@@ -903,6 +903,11 @@ AP4_PiffAvcCbcSampleDecrypter::DecryptSampleData(AP4_DataBuffer& data_in,
}
/*----------------------------------------------------------------------
+| AP4_PiffTrackEncryptionAtom Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_PiffTrackEncryptionAtom)
+
+/*----------------------------------------------------------------------
| AP4_PiffTrackEncryptionAtom::Create
+---------------------------------------------------------------------*/
AP4_PiffTrackEncryptionAtom*
@@ -976,6 +981,11 @@ AP4_PiffTrackEncryptionAtom::WriteFields(AP4_ByteStream& stream)
}
/*----------------------------------------------------------------------
+| AP4_PiffSampleEncryptionAtom Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_PiffSampleEncryptionAtom)
+
+/*----------------------------------------------------------------------
| AP4_PiffSampleEncryptionAtom::Create
+---------------------------------------------------------------------*/
AP4_PiffSampleEncryptionAtom*
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.h
index 73ad5659c..ac5e2ab10 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Piff.h
@@ -351,6 +351,8 @@ private:
class AP4_PiffTrackEncryptionAtom : public AP4_UuidAtom
{
public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_PiffTrackEncryptionAtom, AP4_UuidAtom)
+
// class methods
static AP4_PiffTrackEncryptionAtom* Create(AP4_Size size,
AP4_ByteStream& stream);
@@ -388,6 +390,8 @@ private:
class AP4_PiffSampleEncryptionAtom : public AP4_UuidAtom
{
public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_PiffSampleEncryptionAtom, AP4_UuidAtom)
+
// class methods
static AP4_PiffSampleEncryptionAtom* Create(AP4_Size size,
AP4_ByteStream& stream);
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.cpp
index 129989b1e..211a9a6eb 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.cpp
@@ -1,498 +1,498 @@
-/*****************************************************************
-|
-| AP4 - File Processor
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Processor.h"
-#include "Ap4AtomSampleTable.h"
-#include "Ap4MovieFragment.h"
-#include "Ap4FragmentSampleTable.h"
-#include "Ap4TfhdAtom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4Movie.h"
-#include "Ap4Array.h"
-#include "Ap4Sample.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4TfraAtom.h"
-#include "Ap4DataBuffer.h"
-#include "Ap4Debug.h"
-
-/*----------------------------------------------------------------------
-| types
-+---------------------------------------------------------------------*/
-struct AP4_SampleLocator {
- AP4_SampleLocator() :
- m_TrakIndex(0),
- m_SampleTable(NULL),
- m_SampleIndex(0),
- m_ChunkIndex(0) {}
- AP4_Ordinal m_TrakIndex;
- AP4_AtomSampleTable* m_SampleTable;
- AP4_Ordinal m_SampleIndex;
- AP4_Ordinal m_ChunkIndex;
- AP4_Sample m_Sample;
-};
-
-struct AP4_SampleCursor {
- AP4_SampleCursor() : m_EndReached(false) {}
- AP4_SampleLocator m_Locator;
- bool m_EndReached;
-};
-
-struct AP4_MoofLocator {
- AP4_MoofLocator(AP4_ContainerAtom* moof, AP4_UI64 offset) :
- m_Moof(moof),
- m_Offset(offset) {}
- AP4_ContainerAtom* m_Moof;
- AP4_UI64 m_Offset;
-};
-
-/*----------------------------------------------------------------------
-| AP4_Processor::ProcessFragments
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_Processor::ProcessFragments(AP4_MoovAtom* moov,
- AP4_List<AP4_MoofLocator>& moofs,
- AP4_ContainerAtom* mfra,
- AP4_ByteStream& input,
- AP4_ByteStream& output)
-{
- // FIXME: this only works for non-changing moofs
-
- for (AP4_List<AP4_MoofLocator>::Item* item = moofs.FirstItem();
- item;
- item = item->GetNext()) {
- AP4_MoofLocator* locator = item->GetData();
- AP4_ContainerAtom* moof = locator->m_Moof;
- AP4_UI64 moof_offset = locator->m_Offset;
- AP4_UI64 mdat_payload_offset = moof_offset+moof->GetSize()+8;
- AP4_MovieFragment* fragment = new AP4_MovieFragment(moof);
- AP4_Sample sample;
- AP4_DataBuffer sample_data_in;
- AP4_DataBuffer sample_data_out;
- AP4_Result result;
-
- // process all the traf atoms
- AP4_Array<AP4_Processor::FragmentHandler*> handlers;
- for (;AP4_Atom* atom = moof->GetChild(AP4_ATOM_TYPE_TRAF, handlers.ItemCount());) {
- AP4_ContainerAtom* traf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
- AP4_Processor::FragmentHandler* handler = CreateFragmentHandler(traf);
- if (handler) result = handler->ProcessFragment();
- handlers.Append(handler);
- }
-
- // write the moof
- AP4_UI64 moof_out_start = 0;
- output.Tell(moof_out_start);
- bool moof_has_changed = false;
- moof->Write(output);
-
- // process all track runs
- for (unsigned int i=0; i<handlers.ItemCount(); i++) {
- AP4_FragmentSampleTable* sample_table = NULL;
- AP4_Processor::FragmentHandler* handler = handlers[i];
-
- // get the track ID
- AP4_ContainerAtom* traf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moof->GetChild(AP4_ATOM_TYPE_TRAF, i));
- AP4_TfhdAtom* tfhd = AP4_DYNAMIC_CAST(AP4_TfhdAtom, traf->GetChild(AP4_ATOM_TYPE_TFHD, i));
-
- // create a sample table object so we can read the sample data
- result = fragment->CreateSampleTable(moov, tfhd->GetTrackId(), &input, moof_offset, mdat_payload_offset, sample_table);
- if (AP4_FAILED(result)) return result;
-
- // compute the mdat size
- AP4_UI64 mdat_size = 0;
- for (unsigned int j=0; j<sample_table->GetSampleCount(); j++) {
- result = sample_table->GetSample(j, sample);
- if (AP4_FAILED(result)) return result;
- mdat_size += sample.GetSize();
- }
-
- // write an mdat header
- if (mdat_size > 0xFFFFFFFF-8) {
- // we don't support large mdat fragments
- return AP4_ERROR_OUT_OF_RANGE;
- }
- if (mdat_size) {
- output.WriteUI32((AP4_UI32)(8+mdat_size));
- output.WriteUI32(AP4_ATOM_TYPE_MDAT);
- }
-
-#if defined(AP4_DEBUG)
- AP4_Position before;
- output.Tell(before);
-#endif
-
- // write the mdat
- for (unsigned int j=0; j<sample_table->GetSampleCount(); j++) {
- result = sample_table->GetSample(j, sample);
- if (AP4_FAILED(result)) return result;
- sample.ReadData(sample_data_in);
-
- // process the sample data
- if (handler) {
- result = handler->ProcessSample(sample_data_in, sample_data_out);
- if (AP4_FAILED(result)) return result;
-
- // write the sample data
- result = output.Write(sample_data_out.GetData(), sample_data_out.GetDataSize());
- if (AP4_FAILED(result)) return result;
-
- // give the handler a chance to update the atoms
- result = handler->FinishFragment();
- if (AP4_SUCCEEDED(result)) moof_has_changed = true;
- } else {
- // write the sample data (unmodified)
- result = output.Write(sample_data_in.GetData(), sample_data_in.GetDataSize());
- if (AP4_FAILED(result)) return result;
- }
- }
-
-#if defined(AP4_DEBUG)
- AP4_Position after;
- output.Tell(after);
- AP4_ASSERT(after-before == mdat_size);
-#endif
- delete sample_table;
- }
-
- // update the moof if needed
- AP4_UI64 mdat_out_end = 0;
- output.Tell(mdat_out_end);
- if (moof_has_changed) {
- output.Seek(moof_out_start);
- moof->Write(output);
- output.Seek(mdat_out_end);
- }
-
- // update the mfra if we have one
- if (mfra) {
- for (AP4_List<AP4_Atom>::Item* mfra_item = mfra->GetChildren().FirstItem();
- mfra_item;
- mfra_item = mfra_item->GetNext()) {
- if (mfra_item->GetData()->GetType() != AP4_ATOM_TYPE_TFRA) continue;
- AP4_TfraAtom* tfra = AP4_DYNAMIC_CAST(AP4_TfraAtom, mfra_item->GetData());
- if (tfra == NULL) continue;
- AP4_Array<AP4_TfraAtom::Entry>& entries = tfra->GetEntries();
- AP4_Cardinal entry_count = entries.ItemCount();
- for (unsigned int i=0; i<entry_count; i++) {
- if (entries[i].m_MoofOffset == locator->m_Offset) {
- entries[i].m_MoofOffset = moof_out_start;
- }
- }
- }
- }
-
- delete fragment;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Processor::Process
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_Processor::Process(AP4_ByteStream& input,
- AP4_ByteStream& output,
- ProgressListener* listener,
- AP4_AtomFactory& atom_factory)
-{
- // read all atoms.
- // keep all atoms except [mdat]
- // keep a ref to [moov]
- // put [moof] atoms in a separate list
- AP4_AtomParent top_level;
- AP4_MoovAtom* moov = NULL;
- AP4_ContainerAtom* mfra = NULL;
- AP4_List<AP4_MoofLocator> moofs;
- AP4_UI64 stream_offset = 0;
- for (AP4_Atom* atom = NULL;
- AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(input, atom));
- input.Tell(stream_offset)) {
- if (atom->GetType() == AP4_ATOM_TYPE_MDAT) {
- continue;
- } else if (atom->GetType() == AP4_ATOM_TYPE_MOOV) {
- moov = (AP4_MoovAtom*)atom;
- } else if (atom->GetType() == AP4_ATOM_TYPE_MOOF) {
- AP4_ContainerAtom* moof = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
- if (moof) {
- moofs.Add(new AP4_MoofLocator(moof, stream_offset));
- }
- continue;
- } else if (atom->GetType() == AP4_ATOM_TYPE_MFRA) {
- mfra = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
- continue;
- }
- top_level.AddChild(atom);
- }
-
- // initialize the processor
- AP4_Result result = Initialize(top_level, input);
- if (AP4_FAILED(result)) return result;
-
- // process the tracks if we have a moov atom
- AP4_Array<AP4_SampleLocator> locators;
- AP4_Cardinal track_count = 0;
- AP4_List<AP4_TrakAtom>* trak_atoms = NULL;
- AP4_LargeSize mdat_payload_size = 0;
- TrackHandler** handlers = NULL;
- AP4_SampleCursor* cursors = NULL;
- if (moov) {
- // build an array of track sample locators
- trak_atoms = &moov->GetTrakAtoms();
- track_count = trak_atoms->ItemCount();
- cursors = new AP4_SampleCursor[track_count];
- handlers = new TrackHandler*[track_count];
- for (AP4_Ordinal i=0; i<track_count; i++) {
- handlers[i] = NULL;
- }
-
- unsigned int index = 0;
- for (AP4_List<AP4_TrakAtom>::Item* item = trak_atoms->FirstItem(); item; item=item->GetNext()) {
- AP4_TrakAtom* trak = item->GetData();
-
- // find the stsd atom
- AP4_ContainerAtom* stbl = AP4_DYNAMIC_CAST(AP4_ContainerAtom, trak->FindChild("mdia/minf/stbl"));
- if (stbl == NULL) continue;
-
- // see if there's an external data source for this track
- AP4_ByteStream* trak_data_stream = &input;
- for (AP4_List<ExternalTrackData>::Item* ditem = m_ExternalTrackData.FirstItem(); ditem; ditem=ditem->GetNext()) {
- ExternalTrackData* tdata = ditem->GetData();
- if (tdata->m_TrackId == trak->GetId()) {
- trak_data_stream = tdata->m_MediaData;
- break;
- }
- }
-
- // create the track handler
- handlers[index] = CreateTrackHandler(trak);
- cursors[index].m_Locator.m_TrakIndex = index;
- cursors[index].m_Locator.m_SampleTable = new AP4_AtomSampleTable(stbl, *trak_data_stream);
- cursors[index].m_Locator.m_SampleIndex = 0;
- cursors[index].m_Locator.m_ChunkIndex = 0;
- if (cursors[index].m_Locator.m_SampleTable->GetSampleCount()) {
- cursors[index].m_Locator.m_SampleTable->GetSample(0, cursors[index].m_Locator.m_Sample);
- } else {
- cursors[index].m_EndReached = true;
- }
-
- index++;
- }
-
- // figure out the layout of the chunks
- for (;;) {
- // see which is the next sample to write
- AP4_UI64 min_offset = (AP4_UI64)(-1);
- int cursor = -1;
- for (unsigned int i=0; i<track_count; i++) {
- if (!cursors[i].m_EndReached &&
- cursors[i].m_Locator.m_Sample.GetOffset() <= min_offset) {
- min_offset = cursors[i].m_Locator.m_Sample.GetOffset();
- cursor = i;
- }
- }
-
- // stop if all cursors are exhausted
- if (cursor == -1) break;
-
- // append this locator to the layout list
- AP4_SampleLocator& locator = cursors[cursor].m_Locator;
- locators.Append(locator);
-
- // move the cursor to the next sample
- locator.m_SampleIndex++;
- if (locator.m_SampleIndex == locator.m_SampleTable->GetSampleCount()) {
- // mark this track as completed
- cursors[cursor].m_EndReached = true;
- } else {
- // get the next sample info
- locator.m_SampleTable->GetSample(locator.m_SampleIndex, locator.m_Sample);
- AP4_Ordinal skip, sdesc;
- locator.m_SampleTable->GetChunkForSample(locator.m_SampleIndex,
- locator.m_ChunkIndex,
- skip, sdesc);
- }
- }
-
- // update the stbl atoms and compute the mdat size
- int current_track = -1;
- int current_chunk = -1;
- AP4_Position current_chunk_offset = 0;
- AP4_Size current_chunk_size = 0;
- for (AP4_Ordinal i=0; i<locators.ItemCount(); i++) {
- AP4_SampleLocator& locator = locators[i];
- if ((int)locator.m_TrakIndex != current_track ||
- (int)locator.m_ChunkIndex != current_chunk) {
- // start a new chunk for this track
- current_chunk_offset += current_chunk_size;
- current_chunk_size = 0;
- current_track = locator.m_TrakIndex;
- current_chunk = locator.m_ChunkIndex;
- locator.m_SampleTable->SetChunkOffset(locator.m_ChunkIndex, current_chunk_offset);
- }
- AP4_Size sample_size;
- TrackHandler* handler = handlers[locator.m_TrakIndex];
- if (handler) {
- sample_size = handler->GetProcessedSampleSize(locator.m_Sample);
- locator.m_SampleTable->SetSampleSize(locator.m_SampleIndex, sample_size);
- } else {
- sample_size = locator.m_Sample.GetSize();
- }
- current_chunk_size += sample_size;
- mdat_payload_size += sample_size;
- }
-
- // process the tracks (ex: sample descriptions processing)
- for (AP4_Ordinal i=0; i<track_count; i++) {
- TrackHandler* handler = handlers[i];
- if (handler) handler->ProcessTrack();
- }
- }
-
- // finalize the processor
- Finalize(top_level);
-
- // calculate the size of all atoms combined
- AP4_UI64 atoms_size = 0;
- top_level.GetChildren().Apply(AP4_AtomSizeAdder(atoms_size));
-
- // see if we need a 64-bit or 32-bit mdat
- AP4_Size mdat_header_size = AP4_ATOM_HEADER_SIZE;
- if (mdat_payload_size+mdat_header_size > 0xFFFFFFFF) {
- // we need a 64-bit size
- mdat_header_size += 8;
- }
-
- // adjust the chunk offsets
- for (AP4_Ordinal i=0; i<track_count; i++) {
- AP4_TrakAtom* trak;
- trak_atoms->Get(i, trak);
- trak->AdjustChunkOffsets(atoms_size+mdat_header_size);
- }
-
- // write all atoms
- top_level.GetChildren().Apply(AP4_AtomListWriter(output));
-
- // write mdat header
- if (mdat_payload_size) {
- if (mdat_header_size == AP4_ATOM_HEADER_SIZE) {
- // 32-bit size
- output.WriteUI32((AP4_UI32)(mdat_header_size+mdat_payload_size));
- output.WriteUI32(AP4_ATOM_TYPE_MDAT);
- } else {
- // 64-bit size
- output.WriteUI32(1);
- output.WriteUI32(AP4_ATOM_TYPE_MDAT);
- output.WriteUI64(mdat_header_size+mdat_payload_size);
- }
- }
-
-#if defined(AP4_DEBUG)
- AP4_Position before;
- output.Tell(before);
-#endif
-
- // write the samples
- if (moov) {
- AP4_Sample sample;
- AP4_DataBuffer data_in;
- AP4_DataBuffer data_out;
- for (unsigned int i=0; i<locators.ItemCount(); i++) {
- AP4_SampleLocator& locator = locators[i];
- locator.m_Sample.ReadData(data_in);
- TrackHandler* handler = handlers[locator.m_TrakIndex];
- if (handler) {
- result = handler->ProcessSample(data_in, data_out);
- if (AP4_FAILED(result)) return result;
- output.Write(data_out.GetData(), data_out.GetDataSize());
- } else {
- output.Write(data_in.GetData(), data_in.GetDataSize());
- }
-
- // notify the progress listener
- if (listener) {
- listener->OnProgress(i+1, locators.ItemCount());
- }
- }
-
- // cleanup
- for (AP4_Ordinal i=0; i<track_count; i++) {
- delete cursors[i].m_Locator.m_SampleTable;
- delete handlers[i];
- }
- delete[] cursors;
- delete[] handlers;
- }
-
-#if defined(AP4_DEBUG)
- AP4_Position after;
- output.Tell(after);
- AP4_ASSERT(after-before == mdat_payload_size);
-#endif
-
- // process the fragments, if any
- result = ProcessFragments(moov, moofs, mfra, input, output);
- if (AP4_FAILED(result)) return result;
-
- // write the mfra atom at the end if we have one
- if (mfra) {
- mfra->Write(output);
- }
-
- // cleanup
- moofs.DeleteReferences();
- delete mfra;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Processor:Initialize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_Processor::Initialize(AP4_AtomParent& /* top_level */,
- AP4_ByteStream& /* stream */,
- ProgressListener* /* listener */)
-{
- // default implementation: do nothing
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_Processor:Finalize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_Processor::Finalize(AP4_AtomParent& /* top_level */,
- ProgressListener* /* listener */ )
-{
- // default implementation: do nothing
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - File Processor
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Processor.h"
+#include "Ap4AtomSampleTable.h"
+#include "Ap4MovieFragment.h"
+#include "Ap4FragmentSampleTable.h"
+#include "Ap4TfhdAtom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4Movie.h"
+#include "Ap4Array.h"
+#include "Ap4Sample.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4TfraAtom.h"
+#include "Ap4DataBuffer.h"
+#include "Ap4Debug.h"
+
+/*----------------------------------------------------------------------
+| types
++---------------------------------------------------------------------*/
+struct AP4_SampleLocator {
+ AP4_SampleLocator() :
+ m_TrakIndex(0),
+ m_SampleTable(NULL),
+ m_SampleIndex(0),
+ m_ChunkIndex(0) {}
+ AP4_Ordinal m_TrakIndex;
+ AP4_AtomSampleTable* m_SampleTable;
+ AP4_Ordinal m_SampleIndex;
+ AP4_Ordinal m_ChunkIndex;
+ AP4_Sample m_Sample;
+};
+
+struct AP4_SampleCursor {
+ AP4_SampleCursor() : m_EndReached(false) {}
+ AP4_SampleLocator m_Locator;
+ bool m_EndReached;
+};
+
+struct AP4_MoofLocator {
+ AP4_MoofLocator(AP4_ContainerAtom* moof, AP4_UI64 offset) :
+ m_Moof(moof),
+ m_Offset(offset) {}
+ AP4_ContainerAtom* m_Moof;
+ AP4_UI64 m_Offset;
+};
+
+/*----------------------------------------------------------------------
+| AP4_Processor::ProcessFragments
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_Processor::ProcessFragments(AP4_MoovAtom* moov,
+ AP4_List<AP4_MoofLocator>& moofs,
+ AP4_ContainerAtom* mfra,
+ AP4_ByteStream& input,
+ AP4_ByteStream& output)
+{
+ // FIXME: this only works for non-changing moofs
+
+ for (AP4_List<AP4_MoofLocator>::Item* item = moofs.FirstItem();
+ item;
+ item = item->GetNext()) {
+ AP4_MoofLocator* locator = item->GetData();
+ AP4_ContainerAtom* moof = locator->m_Moof;
+ AP4_UI64 moof_offset = locator->m_Offset;
+ AP4_UI64 mdat_payload_offset = moof_offset+moof->GetSize()+8;
+ AP4_MovieFragment* fragment = new AP4_MovieFragment(moof);
+ AP4_Sample sample;
+ AP4_DataBuffer sample_data_in;
+ AP4_DataBuffer sample_data_out;
+ AP4_Result result;
+
+ // process all the traf atoms
+ AP4_Array<AP4_Processor::FragmentHandler*> handlers;
+ for (;AP4_Atom* atom = moof->GetChild(AP4_ATOM_TYPE_TRAF, handlers.ItemCount());) {
+ AP4_ContainerAtom* traf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
+ AP4_Processor::FragmentHandler* handler = CreateFragmentHandler(traf);
+ if (handler) result = handler->ProcessFragment();
+ handlers.Append(handler);
+ }
+
+ // write the moof
+ AP4_UI64 moof_out_start = 0;
+ output.Tell(moof_out_start);
+ bool moof_has_changed = false;
+ moof->Write(output);
+
+ // process all track runs
+ for (unsigned int i=0; i<handlers.ItemCount(); i++) {
+ AP4_FragmentSampleTable* sample_table = NULL;
+ AP4_Processor::FragmentHandler* handler = handlers[i];
+
+ // get the track ID
+ AP4_ContainerAtom* traf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moof->GetChild(AP4_ATOM_TYPE_TRAF, i));
+ AP4_TfhdAtom* tfhd = AP4_DYNAMIC_CAST(AP4_TfhdAtom, traf->GetChild(AP4_ATOM_TYPE_TFHD, i));
+
+ // create a sample table object so we can read the sample data
+ result = fragment->CreateSampleTable(moov, tfhd->GetTrackId(), &input, moof_offset, mdat_payload_offset, sample_table);
+ if (AP4_FAILED(result)) return result;
+
+ // compute the mdat size
+ AP4_UI64 mdat_size = 0;
+ for (unsigned int j=0; j<sample_table->GetSampleCount(); j++) {
+ result = sample_table->GetSample(j, sample);
+ if (AP4_FAILED(result)) return result;
+ mdat_size += sample.GetSize();
+ }
+
+ // write an mdat header
+ if (mdat_size > 0xFFFFFFFF-8) {
+ // we don't support large mdat fragments
+ return AP4_ERROR_OUT_OF_RANGE;
+ }
+ if (mdat_size) {
+ output.WriteUI32((AP4_UI32)(8+mdat_size));
+ output.WriteUI32(AP4_ATOM_TYPE_MDAT);
+ }
+
+#if defined(AP4_DEBUG)
+ AP4_Position before;
+ output.Tell(before);
+#endif
+
+ // write the mdat
+ for (unsigned int j=0; j<sample_table->GetSampleCount(); j++) {
+ result = sample_table->GetSample(j, sample);
+ if (AP4_FAILED(result)) return result;
+ sample.ReadData(sample_data_in);
+
+ // process the sample data
+ if (handler) {
+ result = handler->ProcessSample(sample_data_in, sample_data_out);
+ if (AP4_FAILED(result)) return result;
+
+ // write the sample data
+ result = output.Write(sample_data_out.GetData(), sample_data_out.GetDataSize());
+ if (AP4_FAILED(result)) return result;
+
+ // give the handler a chance to update the atoms
+ result = handler->FinishFragment();
+ if (AP4_SUCCEEDED(result)) moof_has_changed = true;
+ } else {
+ // write the sample data (unmodified)
+ result = output.Write(sample_data_in.GetData(), sample_data_in.GetDataSize());
+ if (AP4_FAILED(result)) return result;
+ }
+ }
+
+#if defined(AP4_DEBUG)
+ AP4_Position after;
+ output.Tell(after);
+ AP4_ASSERT(after-before == mdat_size);
+#endif
+ delete sample_table;
+ }
+
+ // update the moof if needed
+ AP4_UI64 mdat_out_end = 0;
+ output.Tell(mdat_out_end);
+ if (moof_has_changed) {
+ output.Seek(moof_out_start);
+ moof->Write(output);
+ output.Seek(mdat_out_end);
+ }
+
+ // update the mfra if we have one
+ if (mfra) {
+ for (AP4_List<AP4_Atom>::Item* mfra_item = mfra->GetChildren().FirstItem();
+ mfra_item;
+ mfra_item = mfra_item->GetNext()) {
+ if (mfra_item->GetData()->GetType() != AP4_ATOM_TYPE_TFRA) continue;
+ AP4_TfraAtom* tfra = AP4_DYNAMIC_CAST(AP4_TfraAtom, mfra_item->GetData());
+ if (tfra == NULL) continue;
+ AP4_Array<AP4_TfraAtom::Entry>& entries = tfra->GetEntries();
+ AP4_Cardinal entry_count = entries.ItemCount();
+ for (unsigned int i=0; i<entry_count; i++) {
+ if (entries[i].m_MoofOffset == locator->m_Offset) {
+ entries[i].m_MoofOffset = moof_out_start;
+ }
+ }
+ }
+ }
+
+ delete fragment;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Processor::Process
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_Processor::Process(AP4_ByteStream& input,
+ AP4_ByteStream& output,
+ ProgressListener* listener,
+ AP4_AtomFactory& atom_factory)
+{
+ // read all atoms.
+ // keep all atoms except [mdat]
+ // keep a ref to [moov]
+ // put [moof] atoms in a separate list
+ AP4_AtomParent top_level;
+ AP4_MoovAtom* moov = NULL;
+ AP4_ContainerAtom* mfra = NULL;
+ AP4_List<AP4_MoofLocator> moofs;
+ AP4_UI64 stream_offset = 0;
+ for (AP4_Atom* atom = NULL;
+ AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(input, atom));
+ input.Tell(stream_offset)) {
+ if (atom->GetType() == AP4_ATOM_TYPE_MDAT) {
+ continue;
+ } else if (atom->GetType() == AP4_ATOM_TYPE_MOOV) {
+ moov = (AP4_MoovAtom*)atom;
+ } else if (atom->GetType() == AP4_ATOM_TYPE_MOOF) {
+ AP4_ContainerAtom* moof = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
+ if (moof) {
+ moofs.Add(new AP4_MoofLocator(moof, stream_offset));
+ }
+ continue;
+ } else if (atom->GetType() == AP4_ATOM_TYPE_MFRA) {
+ mfra = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
+ continue;
+ }
+ top_level.AddChild(atom);
+ }
+
+ // initialize the processor
+ AP4_Result result = Initialize(top_level, input);
+ if (AP4_FAILED(result)) return result;
+
+ // process the tracks if we have a moov atom
+ AP4_Array<AP4_SampleLocator> locators;
+ AP4_Cardinal track_count = 0;
+ AP4_List<AP4_TrakAtom>* trak_atoms = NULL;
+ AP4_LargeSize mdat_payload_size = 0;
+ TrackHandler** handlers = NULL;
+ AP4_SampleCursor* cursors = NULL;
+ if (moov) {
+ // build an array of track sample locators
+ trak_atoms = &moov->GetTrakAtoms();
+ track_count = trak_atoms->ItemCount();
+ cursors = new AP4_SampleCursor[track_count];
+ handlers = new TrackHandler*[track_count];
+ for (AP4_Ordinal i=0; i<track_count; i++) {
+ handlers[i] = NULL;
+ }
+
+ unsigned int index = 0;
+ for (AP4_List<AP4_TrakAtom>::Item* item = trak_atoms->FirstItem(); item; item=item->GetNext()) {
+ AP4_TrakAtom* trak = item->GetData();
+
+ // find the stsd atom
+ AP4_ContainerAtom* stbl = AP4_DYNAMIC_CAST(AP4_ContainerAtom, trak->FindChild("mdia/minf/stbl"));
+ if (stbl == NULL) continue;
+
+ // see if there's an external data source for this track
+ AP4_ByteStream* trak_data_stream = &input;
+ for (AP4_List<ExternalTrackData>::Item* ditem = m_ExternalTrackData.FirstItem(); ditem; ditem=ditem->GetNext()) {
+ ExternalTrackData* tdata = ditem->GetData();
+ if (tdata->m_TrackId == trak->GetId()) {
+ trak_data_stream = tdata->m_MediaData;
+ break;
+ }
+ }
+
+ // create the track handler
+ handlers[index] = CreateTrackHandler(trak);
+ cursors[index].m_Locator.m_TrakIndex = index;
+ cursors[index].m_Locator.m_SampleTable = new AP4_AtomSampleTable(stbl, *trak_data_stream);
+ cursors[index].m_Locator.m_SampleIndex = 0;
+ cursors[index].m_Locator.m_ChunkIndex = 0;
+ if (cursors[index].m_Locator.m_SampleTable->GetSampleCount()) {
+ cursors[index].m_Locator.m_SampleTable->GetSample(0, cursors[index].m_Locator.m_Sample);
+ } else {
+ cursors[index].m_EndReached = true;
+ }
+
+ index++;
+ }
+
+ // figure out the layout of the chunks
+ for (;;) {
+ // see which is the next sample to write
+ AP4_UI64 min_offset = (AP4_UI64)(-1);
+ int cursor = -1;
+ for (unsigned int i=0; i<track_count; i++) {
+ if (!cursors[i].m_EndReached &&
+ cursors[i].m_Locator.m_Sample.GetOffset() <= min_offset) {
+ min_offset = cursors[i].m_Locator.m_Sample.GetOffset();
+ cursor = i;
+ }
+ }
+
+ // stop if all cursors are exhausted
+ if (cursor == -1) break;
+
+ // append this locator to the layout list
+ AP4_SampleLocator& locator = cursors[cursor].m_Locator;
+ locators.Append(locator);
+
+ // move the cursor to the next sample
+ locator.m_SampleIndex++;
+ if (locator.m_SampleIndex == locator.m_SampleTable->GetSampleCount()) {
+ // mark this track as completed
+ cursors[cursor].m_EndReached = true;
+ } else {
+ // get the next sample info
+ locator.m_SampleTable->GetSample(locator.m_SampleIndex, locator.m_Sample);
+ AP4_Ordinal skip, sdesc;
+ locator.m_SampleTable->GetChunkForSample(locator.m_SampleIndex,
+ locator.m_ChunkIndex,
+ skip, sdesc);
+ }
+ }
+
+ // update the stbl atoms and compute the mdat size
+ int current_track = -1;
+ int current_chunk = -1;
+ AP4_Position current_chunk_offset = 0;
+ AP4_Size current_chunk_size = 0;
+ for (AP4_Ordinal i=0; i<locators.ItemCount(); i++) {
+ AP4_SampleLocator& locator = locators[i];
+ if ((int)locator.m_TrakIndex != current_track ||
+ (int)locator.m_ChunkIndex != current_chunk) {
+ // start a new chunk for this track
+ current_chunk_offset += current_chunk_size;
+ current_chunk_size = 0;
+ current_track = locator.m_TrakIndex;
+ current_chunk = locator.m_ChunkIndex;
+ locator.m_SampleTable->SetChunkOffset(locator.m_ChunkIndex, current_chunk_offset);
+ }
+ AP4_Size sample_size;
+ TrackHandler* handler = handlers[locator.m_TrakIndex];
+ if (handler) {
+ sample_size = handler->GetProcessedSampleSize(locator.m_Sample);
+ locator.m_SampleTable->SetSampleSize(locator.m_SampleIndex, sample_size);
+ } else {
+ sample_size = locator.m_Sample.GetSize();
+ }
+ current_chunk_size += sample_size;
+ mdat_payload_size += sample_size;
+ }
+
+ // process the tracks (ex: sample descriptions processing)
+ for (AP4_Ordinal i=0; i<track_count; i++) {
+ TrackHandler* handler = handlers[i];
+ if (handler) handler->ProcessTrack();
+ }
+ }
+
+ // finalize the processor
+ Finalize(top_level);
+
+ // calculate the size of all atoms combined
+ AP4_UI64 atoms_size = 0;
+ top_level.GetChildren().Apply(AP4_AtomSizeAdder(atoms_size));
+
+ // see if we need a 64-bit or 32-bit mdat
+ AP4_Size mdat_header_size = AP4_ATOM_HEADER_SIZE;
+ if (mdat_payload_size+mdat_header_size > 0xFFFFFFFF) {
+ // we need a 64-bit size
+ mdat_header_size += 8;
+ }
+
+ // adjust the chunk offsets
+ for (AP4_Ordinal i=0; i<track_count; i++) {
+ AP4_TrakAtom* trak;
+ trak_atoms->Get(i, trak);
+ trak->AdjustChunkOffsets(atoms_size+mdat_header_size);
+ }
+
+ // write all atoms
+ top_level.GetChildren().Apply(AP4_AtomListWriter(output));
+
+ // write mdat header
+ if (mdat_payload_size) {
+ if (mdat_header_size == AP4_ATOM_HEADER_SIZE) {
+ // 32-bit size
+ output.WriteUI32((AP4_UI32)(mdat_header_size+mdat_payload_size));
+ output.WriteUI32(AP4_ATOM_TYPE_MDAT);
+ } else {
+ // 64-bit size
+ output.WriteUI32(1);
+ output.WriteUI32(AP4_ATOM_TYPE_MDAT);
+ output.WriteUI64(mdat_header_size+mdat_payload_size);
+ }
+ }
+
+#if defined(AP4_DEBUG)
+ AP4_Position before;
+ output.Tell(before);
+#endif
+
+ // write the samples
+ if (moov) {
+ AP4_Sample sample;
+ AP4_DataBuffer data_in;
+ AP4_DataBuffer data_out;
+ for (unsigned int i=0; i<locators.ItemCount(); i++) {
+ AP4_SampleLocator& locator = locators[i];
+ locator.m_Sample.ReadData(data_in);
+ TrackHandler* handler = handlers[locator.m_TrakIndex];
+ if (handler) {
+ result = handler->ProcessSample(data_in, data_out);
+ if (AP4_FAILED(result)) return result;
+ output.Write(data_out.GetData(), data_out.GetDataSize());
+ } else {
+ output.Write(data_in.GetData(), data_in.GetDataSize());
+ }
+
+ // notify the progress listener
+ if (listener) {
+ listener->OnProgress(i+1, locators.ItemCount());
+ }
+ }
+
+ // cleanup
+ for (AP4_Ordinal i=0; i<track_count; i++) {
+ delete cursors[i].m_Locator.m_SampleTable;
+ delete handlers[i];
+ }
+ delete[] cursors;
+ delete[] handlers;
+ }
+
+#if defined(AP4_DEBUG)
+ AP4_Position after;
+ output.Tell(after);
+ AP4_ASSERT(after-before == mdat_payload_size);
+#endif
+
+ // process the fragments, if any
+ result = ProcessFragments(moov, moofs, mfra, input, output);
+ if (AP4_FAILED(result)) return result;
+
+ // write the mfra atom at the end if we have one
+ if (mfra) {
+ mfra->Write(output);
+ }
+
+ // cleanup
+ moofs.DeleteReferences();
+ delete mfra;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Processor:Initialize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_Processor::Initialize(AP4_AtomParent& /* top_level */,
+ AP4_ByteStream& /* stream */,
+ ProgressListener* /* listener */)
+{
+ // default implementation: do nothing
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_Processor:Finalize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_Processor::Finalize(AP4_AtomParent& /* top_level */,
+ ProgressListener* /* listener */ )
+{
+ // default implementation: do nothing
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.h
index 2e7b4186d..ff58942b3 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Processor.h
@@ -1,237 +1,237 @@
-/*****************************************************************
-|
-| AP4 - File Processor
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-#ifndef _AP4_PROCESSOR_H_
-#define _AP4_PROCESSOR_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4File.h"
-#include "Ap4Track.h"
-#include "Ap4Sample.h"
-
-/*----------------------------------------------------------------------
-| class references
-+---------------------------------------------------------------------*/
-class AP4_ContainerAtom;
-class AP4_ByteStream;
-class AP4_DataBuffer;
-class AP4_TrakAtom;
-struct AP4_MoofLocator;
-
-/*----------------------------------------------------------------------
-| AP4_Processor
-+---------------------------------------------------------------------*/
-class AP4_Processor {
-public:
- /**
- * Abstract class that defines the interface implemented by progress
- * listeners. A progress listener is called during the AP4_Processor::Process()
- * method to notify of progres information.
- */
- class ProgressListener {
- public:
- virtual ~ProgressListener() {}
-
- /**
- * This method is called during the call to AP4_Processor::Process() to
- * notify of the progress of the operation. If this method returns an
- * error result, processing is aborted.
- * @param step Ordinal of the current progress step.
- * @param total Total number of steps.
- * @return A result code. If this method returns AP4_SUCCESS, the
- * processing continues. If an error code is returned, the processing
- * is aborted.
- */
- virtual AP4_Result OnProgress(unsigned int step,
- unsigned int total) = 0;
- };
-
- /**
- * Abstract class that defines the interface implemented by concrete
- * track handlers. A track handler is responsible for processing a
- * track and its media samples.
- */
- class TrackHandler {
- public:
- /**
- * Default destructor.
- */
- virtual ~TrackHandler() {}
-
- /**
- * A track handler may override this method if it needs to modify
- * the track atoms before processing the track samples.
- */
- virtual AP4_Result ProcessTrack() { return AP4_SUCCESS; }
-
- /**
- * Returns the size of a sample after processing.
- * @param sample Sample of which the processed size is requested.
- * @return Size of the sample data after processing.
- */
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample) { return sample.GetSize(); }
-
- /**
- * Process the data of one sample.
- * @param data_in Data buffer with the data of the sample to process.
- * @param data_out Data buffer in which the processed sample data is
- * returned.
- */
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out) = 0;
- };
-
- /**
- * Abstract class that defines the interface implemented by concrete
- * fragment handlers. A fragment handler is responsible for processing a
- * fragment and its media samples.
- */
- class FragmentHandler {
- public:
- /**
- * Default destructor.
- */
- virtual ~FragmentHandler() {}
-
- /**
- * A fragment handler may override this method if it needs to modify
- * the fragment atoms before processing the fragment samples.
- */
- virtual AP4_Result ProcessFragment() { return AP4_SUCCESS; }
-
- /**
- * A fragment handler may override this method if it needs to modify
- * the fragment atoms after processing the fragment samples.
- * NOTE: this method MUST NOT change the size of any of the atoms.
- */
- virtual AP4_Result FinishFragment() { return AP4_ERROR_NOT_SUPPORTED; }
-
- /**
- * Returns the size of a sample after processing.
- * @param sample Sample of which the processed size is requested.
- * @return Size of the sample data after processing.
- */
- virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample) { return sample.GetSize(); }
-
- /**
- * Process the data of one sample.
- * @param data_in Data buffer with the data of the sample to process.
- * @param data_out Data buffer in which the processed sample data is
- * returned.
- */
- virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out) = 0;
- };
-
- /**
- * Default destructor
- */
- virtual ~AP4_Processor() { m_ExternalTrackData.DeleteReferences(); }
-
- /**
- * Process the input stream into an output stream.
- * @param input Reference to the file to process.
- * @param output Output stream to which the processed input
- * will be written.
- * @param listener Pointer to a listener, or NULL. The listener
- * will be called one or more times before this method returns,
- * with progress information.
- */
- AP4_Result Process(AP4_ByteStream& input,
- AP4_ByteStream& output,
- ProgressListener* listener = NULL,
- AP4_AtomFactory& atom_factory =
- AP4_DefaultAtomFactory::Instance);
-
- /**
- * This method can be overridden by concrete subclasses.
- * It is called just after the input stream has been parsed into
- * an atom tree, before the processing of the tracks.
- * @param top_level Container atom containing all the atoms parsed
- * from the input stream. Note that this atom does not actually
- * exist in the file; it is a synthetised container created for the
- * purpose of holding together all the input's top-level atoms.
- */
- virtual AP4_Result Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- ProgressListener* listener = NULL);
-
- /**
- * This method can be overridden by concrete subclasses.
- * It is called just after the tracks have been processed.
- */
- virtual AP4_Result Finalize(AP4_AtomParent& top_level,
- ProgressListener* listener = NULL);
-
- /**
- * This method can be overridden by concrete subclasses.
- * It is called once for each track in the input file.
- * @param track Pointer to the track for which a handler should be
- * created.
- * @return A pointer to a track handler, or NULL if no handler
- * needs to be created for that track.
- */
- virtual TrackHandler* CreateTrackHandler(AP4_TrakAtom* /*trak*/) { return NULL; }
-
- /**
- * This method can be overridden by concrete subclasses.
- * It is called once for each fragment in the input file.
- * @param track Pointer to the fragment for which a handler should be
- * created.
- * @return A pointer to a fragment handler, or NULL if no handler
- * needs to be created for that fragment.
- */
- virtual FragmentHandler* CreateFragmentHandler(AP4_ContainerAtom* /*traf*/) { return NULL; }
-
-protected:
- class ExternalTrackData {
- public:
- ExternalTrackData(unsigned int track_id, AP4_ByteStream* media_data) :
- m_TrackId(track_id), m_MediaData(media_data) {
- media_data->AddReference();
- }
- ~ExternalTrackData() { m_MediaData->Release(); }
- unsigned int m_TrackId;
- AP4_ByteStream* m_MediaData;
- };
-
- AP4_Result ProcessFragments(AP4_MoovAtom* moov,
- AP4_List<AP4_MoofLocator>& moofs,
- AP4_ContainerAtom* mfra,
- AP4_ByteStream& input,
- AP4_ByteStream& output);
-
-
- AP4_List<ExternalTrackData> m_ExternalTrackData;
-};
-
-#endif // _AP4_PROCESSOR_H_
+/*****************************************************************
+|
+| AP4 - File Processor
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+#ifndef _AP4_PROCESSOR_H_
+#define _AP4_PROCESSOR_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4File.h"
+#include "Ap4Track.h"
+#include "Ap4Sample.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class AP4_ContainerAtom;
+class AP4_ByteStream;
+class AP4_DataBuffer;
+class AP4_TrakAtom;
+struct AP4_MoofLocator;
+
+/*----------------------------------------------------------------------
+| AP4_Processor
++---------------------------------------------------------------------*/
+class AP4_Processor {
+public:
+ /**
+ * Abstract class that defines the interface implemented by progress
+ * listeners. A progress listener is called during the AP4_Processor::Process()
+ * method to notify of progres information.
+ */
+ class ProgressListener {
+ public:
+ virtual ~ProgressListener() {}
+
+ /**
+ * This method is called during the call to AP4_Processor::Process() to
+ * notify of the progress of the operation. If this method returns an
+ * error result, processing is aborted.
+ * @param step Ordinal of the current progress step.
+ * @param total Total number of steps.
+ * @return A result code. If this method returns AP4_SUCCESS, the
+ * processing continues. If an error code is returned, the processing
+ * is aborted.
+ */
+ virtual AP4_Result OnProgress(unsigned int step,
+ unsigned int total) = 0;
+ };
+
+ /**
+ * Abstract class that defines the interface implemented by concrete
+ * track handlers. A track handler is responsible for processing a
+ * track and its media samples.
+ */
+ class TrackHandler {
+ public:
+ /**
+ * Default destructor.
+ */
+ virtual ~TrackHandler() {}
+
+ /**
+ * A track handler may override this method if it needs to modify
+ * the track atoms before processing the track samples.
+ */
+ virtual AP4_Result ProcessTrack() { return AP4_SUCCESS; }
+
+ /**
+ * Returns the size of a sample after processing.
+ * @param sample Sample of which the processed size is requested.
+ * @return Size of the sample data after processing.
+ */
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample) { return sample.GetSize(); }
+
+ /**
+ * Process the data of one sample.
+ * @param data_in Data buffer with the data of the sample to process.
+ * @param data_out Data buffer in which the processed sample data is
+ * returned.
+ */
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out) = 0;
+ };
+
+ /**
+ * Abstract class that defines the interface implemented by concrete
+ * fragment handlers. A fragment handler is responsible for processing a
+ * fragment and its media samples.
+ */
+ class FragmentHandler {
+ public:
+ /**
+ * Default destructor.
+ */
+ virtual ~FragmentHandler() {}
+
+ /**
+ * A fragment handler may override this method if it needs to modify
+ * the fragment atoms before processing the fragment samples.
+ */
+ virtual AP4_Result ProcessFragment() { return AP4_SUCCESS; }
+
+ /**
+ * A fragment handler may override this method if it needs to modify
+ * the fragment atoms after processing the fragment samples.
+ * NOTE: this method MUST NOT change the size of any of the atoms.
+ */
+ virtual AP4_Result FinishFragment() { return AP4_ERROR_NOT_SUPPORTED; }
+
+ /**
+ * Returns the size of a sample after processing.
+ * @param sample Sample of which the processed size is requested.
+ * @return Size of the sample data after processing.
+ */
+ virtual AP4_Size GetProcessedSampleSize(AP4_Sample& sample) { return sample.GetSize(); }
+
+ /**
+ * Process the data of one sample.
+ * @param data_in Data buffer with the data of the sample to process.
+ * @param data_out Data buffer in which the processed sample data is
+ * returned.
+ */
+ virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out) = 0;
+ };
+
+ /**
+ * Default destructor
+ */
+ virtual ~AP4_Processor() { m_ExternalTrackData.DeleteReferences(); }
+
+ /**
+ * Process the input stream into an output stream.
+ * @param input Reference to the file to process.
+ * @param output Output stream to which the processed input
+ * will be written.
+ * @param listener Pointer to a listener, or NULL. The listener
+ * will be called one or more times before this method returns,
+ * with progress information.
+ */
+ AP4_Result Process(AP4_ByteStream& input,
+ AP4_ByteStream& output,
+ ProgressListener* listener = NULL,
+ AP4_AtomFactory& atom_factory =
+ AP4_DefaultAtomFactory::Instance);
+
+ /**
+ * This method can be overridden by concrete subclasses.
+ * It is called just after the input stream has been parsed into
+ * an atom tree, before the processing of the tracks.
+ * @param top_level Container atom containing all the atoms parsed
+ * from the input stream. Note that this atom does not actually
+ * exist in the file; it is a synthetised container created for the
+ * purpose of holding together all the input's top-level atoms.
+ */
+ virtual AP4_Result Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ ProgressListener* listener = NULL);
+
+ /**
+ * This method can be overridden by concrete subclasses.
+ * It is called just after the tracks have been processed.
+ */
+ virtual AP4_Result Finalize(AP4_AtomParent& top_level,
+ ProgressListener* listener = NULL);
+
+ /**
+ * This method can be overridden by concrete subclasses.
+ * It is called once for each track in the input file.
+ * @param track Pointer to the track for which a handler should be
+ * created.
+ * @return A pointer to a track handler, or NULL if no handler
+ * needs to be created for that track.
+ */
+ virtual TrackHandler* CreateTrackHandler(AP4_TrakAtom* /*trak*/) { return NULL; }
+
+ /**
+ * This method can be overridden by concrete subclasses.
+ * It is called once for each fragment in the input file.
+ * @param track Pointer to the fragment for which a handler should be
+ * created.
+ * @return A pointer to a fragment handler, or NULL if no handler
+ * needs to be created for that fragment.
+ */
+ virtual FragmentHandler* CreateFragmentHandler(AP4_ContainerAtom* /*traf*/) { return NULL; }
+
+protected:
+ class ExternalTrackData {
+ public:
+ ExternalTrackData(unsigned int track_id, AP4_ByteStream* media_data) :
+ m_TrackId(track_id), m_MediaData(media_data) {
+ media_data->AddReference();
+ }
+ ~ExternalTrackData() { m_MediaData->Release(); }
+ unsigned int m_TrackId;
+ AP4_ByteStream* m_MediaData;
+ };
+
+ AP4_Result ProcessFragments(AP4_MoovAtom* moov,
+ AP4_List<AP4_MoofLocator>& moofs,
+ AP4_ContainerAtom* mfra,
+ AP4_ByteStream& input,
+ AP4_ByteStream& output);
+
+
+ AP4_List<ExternalTrackData> m_ExternalTrackData;
+};
+
+#endif // _AP4_PROCESSOR_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.cpp
index cf918b3f9..9069a7b99 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.cpp
@@ -1,1335 +1,1335 @@
-/*****************************************************************
-|
-| AP4 - Protected Stream Support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Protection.h"
-#include "Ap4SchmAtom.h"
-#include "Ap4StsdAtom.h"
-#include "Ap4FtypAtom.h"
-#include "Ap4Sample.h"
-#include "Ap4StreamCipher.h"
-#include "Ap4IsfmAtom.h"
-#include "Ap4FrmaAtom.h"
-#include "Ap4IkmsAtom.h"
-#include "Ap4IsfmAtom.h"
-#include "Ap4IsltAtom.h"
-#include "Ap4Utils.h"
-#include "Ap4TrakAtom.h"
-#include "Ap4IsmaCryp.h"
-#include "Ap4AesBlockCipher.h"
-#include "Ap4OmaDcf.h"
-#include "Ap4Marlin.h"
-#include "Ap4Piff.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_ProtectedSampleDescription)
-
-/*----------------------------------------------------------------------
-| AP4_EncaSampleEntry::AP4_EncaSampleEntry
-+---------------------------------------------------------------------*/
-AP4_EncaSampleEntry::AP4_EncaSampleEntry(AP4_UI32 type,
- AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory) :
- AP4_AudioSampleEntry(type, size, stream, atom_factory)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncaSampleEntry::AP4_EncaSampleEntry
-+---------------------------------------------------------------------*/
-AP4_EncaSampleEntry::AP4_EncaSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory) :
- AP4_AudioSampleEntry(AP4_ATOM_TYPE_ENCA, size, stream, atom_factory)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncaSampleEntry::ToSampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_EncaSampleEntry::ToSampleDescription()
-{
- // get the original sample format
- AP4_FrmaAtom* frma = (AP4_FrmaAtom*)FindChild("sinf/frma");
-
- // get the schi atom
- AP4_ContainerAtom* schi;
- schi = static_cast<AP4_ContainerAtom*>(FindChild("sinf/schi"));
-
- // get the scheme info
- AP4_SchmAtom* schm = (AP4_SchmAtom*)FindChild("sinf/schm");
- AP4_UI32 original_format = frma?frma->GetOriginalFormat():AP4_ATOM_TYPE_MP4A;
- if (schm) {
- // create the original sample description
- return new AP4_ProtectedSampleDescription(
- m_Type,
- ToTargetSampleDescription(original_format),
- original_format,
- schm->GetSchemeType(),
- schm->GetSchemeVersion(),
- schm->GetSchemeUri().GetChars(),
- schi);
- } else if (schi) {
- // try to see if we can guess the protection scheme from the 'schi' contents
- AP4_Atom* odkm = schi->GetChild(AP4_ATOM_TYPE_ODKM);
- if (odkm) {
- // create the original sample description
- return new AP4_ProtectedSampleDescription(
- m_Type,
- ToTargetSampleDescription(original_format),
- original_format,
- AP4_PROTECTION_SCHEME_TYPE_OMA,
- AP4_PROTECTION_SCHEME_VERSION_OMA_20,
- NULL,
- schi);
- }
- }
-
- // unknown scheme
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncaSampleEntry::ToTargetSampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_EncaSampleEntry::ToTargetSampleDescription(AP4_UI32 format)
-{
- switch (format) {
- case AP4_ATOM_TYPE_MP4A: {
- AP4_EsdsAtom* esds = AP4_DYNAMIC_CAST(AP4_EsdsAtom, GetChild(AP4_ATOM_TYPE_ESDS));
- if (esds == NULL) {
- // check if this is a quicktime style sample description
- if (m_QtVersion > 0) {
- esds = AP4_DYNAMIC_CAST(AP4_EsdsAtom, FindChild("wave/esds"));
- }
- }
- return new AP4_MpegAudioSampleDescription(
- GetSampleRate(),
- GetSampleSize(),
- GetChannelCount(),
- esds);
- }
-
- default:
- return new AP4_GenericAudioSampleDescription(
- format,
- GetSampleRate(),
- GetSampleSize(),
- GetChannelCount(),
- this);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncvSampleEntry::AP4_EncvSampleEntry
-+---------------------------------------------------------------------*/
-AP4_EncvSampleEntry::AP4_EncvSampleEntry(AP4_UI32 type,
- AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory) :
- AP4_VisualSampleEntry(type, size, stream, atom_factory)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncvSampleEntry::AP4_EncvSampleEntry
-+---------------------------------------------------------------------*/
-AP4_EncvSampleEntry::AP4_EncvSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory) :
- AP4_VisualSampleEntry(AP4_ATOM_TYPE_ENCV, size, stream, atom_factory)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncvSampleEntry::ToSampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_EncvSampleEntry::ToSampleDescription()
-{
- // get the original sample format
- AP4_FrmaAtom* frma = (AP4_FrmaAtom*)FindChild("sinf/frma");
-
- // get the schi atom
- AP4_ContainerAtom* schi;
- schi = static_cast<AP4_ContainerAtom*>(FindChild("sinf/schi"));
-
- // get the scheme info
- AP4_SchmAtom* schm = (AP4_SchmAtom*)FindChild("sinf/schm");
- AP4_UI32 original_format = frma?frma->GetOriginalFormat():AP4_ATOM_TYPE_MP4V;
- if (schm) {
- // create the sample description
- return new AP4_ProtectedSampleDescription(
- m_Type,
- ToTargetSampleDescription(original_format),
- original_format,
- schm->GetSchemeType(),
- schm->GetSchemeVersion(),
- schm->GetSchemeUri().GetChars(),
- schi);
- } else if (schi) {
- // try to see if we can guess the protection scheme from the 'schi' contents
- AP4_Atom* odkm = schi->GetChild(AP4_ATOM_TYPE_ODKM);
- if (odkm) {
- // create the original sample description
- return new AP4_ProtectedSampleDescription(
- m_Type,
- ToTargetSampleDescription(original_format),
- original_format,
- AP4_PROTECTION_SCHEME_TYPE_OMA,
- AP4_PROTECTION_SCHEME_VERSION_OMA_20,
- NULL,
- schi);
- }
- }
-
- // unknown scheme
- return NULL;
-
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncvSampleEntry::ToTargetSampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_EncvSampleEntry::ToTargetSampleDescription(AP4_UI32 format)
-{
- switch (format) {
- case AP4_ATOM_TYPE_AVC1:
- return new AP4_AvcSampleDescription(
- m_Width,
- m_Height,
- m_Depth,
- m_CompressorName.GetChars(),
- this);
-
- case AP4_ATOM_TYPE_MP4V:
- return new AP4_MpegVideoSampleDescription(
- m_Width,
- m_Height,
- m_Depth,
- m_CompressorName.GetChars(),
- AP4_DYNAMIC_CAST(AP4_EsdsAtom, GetChild(AP4_ATOM_TYPE_ESDS)));
-
- default:
- return new AP4_GenericVideoSampleDescription(
- format,
- m_Width,
- m_Height,
- m_Depth,
- m_CompressorName.GetChars(),
- this);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_DrmsSampleEntry::AP4_DrmsSampleEntry
-+---------------------------------------------------------------------*/
-AP4_DrmsSampleEntry::AP4_DrmsSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory) :
- AP4_EncaSampleEntry(AP4_ATOM_TYPE_DRMS, size, stream, atom_factory)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_DrmiSampleEntry::AP4_DrmiSampleEntry
-+---------------------------------------------------------------------*/
-AP4_DrmiSampleEntry::AP4_DrmiSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory) :
- AP4_EncvSampleEntry(AP4_ATOM_TYPE_DRMI, size, stream, atom_factory)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionSchemeInfo::~AP4_ProtectionSchemeInfo
-+---------------------------------------------------------------------*/
-AP4_ProtectionSchemeInfo::~AP4_ProtectionSchemeInfo()
-{
- delete m_SchiAtom;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionSchemeInfo::AP4_ProtectionSchemeInfo
-+---------------------------------------------------------------------*/
-AP4_ProtectionSchemeInfo::AP4_ProtectionSchemeInfo(AP4_ContainerAtom* schi)
-{
- if (schi) {
- m_SchiAtom = (AP4_ContainerAtom*)schi->Clone();
- } else {
- m_SchiAtom = NULL;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::AP4_ProtectionKeyMap
-+---------------------------------------------------------------------*/
-AP4_ProtectionKeyMap::AP4_ProtectionKeyMap()
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::~AP4_ProtectionKeyMap
-+---------------------------------------------------------------------*/
-AP4_ProtectionKeyMap::~AP4_ProtectionKeyMap()
-{
- m_KeyEntries.DeleteReferences();
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::SetKey
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ProtectionKeyMap::SetKey(AP4_UI32 track_id, const AP4_UI08* key, const AP4_UI08* iv)
-{
- KeyEntry* entry = GetEntry(track_id);
- if (entry == NULL) {
- m_KeyEntries.Add(new KeyEntry(track_id, key, iv));
- } else {
- entry->SetKey(key, iv);
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::SetKey
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ProtectionKeyMap::SetKeys(const AP4_ProtectionKeyMap& key_map)
-{
- AP4_List<KeyEntry>::Item* item = key_map.m_KeyEntries.FirstItem();
- while (item) {
- KeyEntry* entry = item->GetData();
- m_KeyEntries.Add(new KeyEntry(entry->m_TrackId,
- entry->m_Key,
- entry->m_IV));
- item = item->GetNext();
- }
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::GetKeyIv
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ProtectionKeyMap::GetKeyAndIv(AP4_UI32 track_id,
- const AP4_UI08*& key,
- const AP4_UI08*& iv)
-{
- KeyEntry* entry = GetEntry(track_id);
- if (entry) {
- key = entry->m_Key;
- iv = entry->m_IV;
- return AP4_SUCCESS;
- } else {
- return AP4_ERROR_NO_SUCH_ITEM;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::GetKey
-+---------------------------------------------------------------------*/
-const AP4_UI08*
-AP4_ProtectionKeyMap::GetKey(AP4_UI32 track_id) const
-{
- KeyEntry* entry = GetEntry(track_id);
- if (entry) {
- return entry->m_Key;
- } else {
- return NULL;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::GetEntry
-+---------------------------------------------------------------------*/
-AP4_ProtectionKeyMap::KeyEntry*
-AP4_ProtectionKeyMap::GetEntry(AP4_UI32 track_id) const
-{
- AP4_List<KeyEntry>::Item* item = m_KeyEntries.FirstItem();
- while (item) {
- KeyEntry* entry = (KeyEntry*)item->GetData();
- if (entry->m_TrackId == track_id) return entry;
- item = item->GetNext();
- }
-
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::KeyEntry::KeyEntry
-+---------------------------------------------------------------------*/
-AP4_ProtectionKeyMap::KeyEntry::KeyEntry(AP4_UI32 track_id,
- const AP4_UI08* key,
- const AP4_UI08* iv /* = NULL */) :
- m_TrackId(track_id)
-{
- SetKey(key, iv);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap::KeyEntry::SetKey
-+---------------------------------------------------------------------*/
-void
-AP4_ProtectionKeyMap::KeyEntry::SetKey(const AP4_UI08* key, const AP4_UI08* iv)
-{
- AP4_CopyMemory(m_Key, key, sizeof(m_Key));
- if (iv) {
- AP4_CopyMemory(m_IV, iv, sizeof(m_IV));
- } else {
- AP4_SetMemory(m_IV, 0, sizeof(m_IV));
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrackPropertyMap::~AP4_TrackPropertyMap
-+---------------------------------------------------------------------*/
-AP4_TrackPropertyMap::~AP4_TrackPropertyMap()
-{
- m_Entries.DeleteReferences();
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrackPropertyMap::SetProperty
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_TrackPropertyMap::SetProperty(AP4_UI32 track_id,
- const char* name,
- const char* value)
-{
- return m_Entries.Add(new Entry(track_id, name, value));
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrackPropertyMap::SetProperties
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_TrackPropertyMap::SetProperties(const AP4_TrackPropertyMap& properties)
-{
- AP4_List<Entry>::Item* item = properties.m_Entries.FirstItem();
- while (item) {
- Entry* entry = item->GetData();
- m_Entries.Add(new Entry(entry->m_TrackId,
- entry->m_Name.GetChars(),
- entry->m_Value.GetChars()));
- item = item->GetNext();
- }
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrackPropertyMap::GetProperty
-+---------------------------------------------------------------------*/
-const char*
-AP4_TrackPropertyMap::GetProperty(AP4_UI32 track_id, const char* name)
-{
- AP4_List<Entry>::Item* item = m_Entries.FirstItem();
- while (item) {
- Entry* entry = item->GetData();
- if (entry->m_TrackId == track_id &&
- AP4_CompareStrings(entry->m_Name.GetChars(), name) == 0) {
- return entry->m_Value.GetChars();
- }
- item = item->GetNext();
- }
-
- // not found
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrackPropertyMap::GetTextualHeaders
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_TrackPropertyMap::GetTextualHeaders(AP4_UI32 track_id, AP4_DataBuffer& textual_headers)
-{
- AP4_Size buffer_size = 0;
- AP4_Result result = AP4_SUCCESS;
- AP4_Byte* data_buffer;
-
- // get the size needed for the textual headers
- AP4_List<Entry>::Item* item = m_Entries.FirstItem();
- while (item) {
- Entry* entry = item->GetData();
- if (entry->m_TrackId == track_id) {
- const char* name = entry->m_Name.GetChars();
- if (AP4_CompareStrings(name, "ContentId") != 0 &&
- AP4_CompareStrings(name, "RightsIssuerUrl") != 0 &&
- AP4_CompareStrings(name, "KID") != 0) {
- buffer_size += (entry->m_Name.GetLength() +
- entry->m_Value.GetLength() +
- 2); // colon + nul
-
- }
- }
- item = item->GetNext();
- }
-
- result = textual_headers.SetDataSize(buffer_size);
- AP4_CHECK(result);
-
- data_buffer = textual_headers.UseData();
-
- // set the textual headers
- item = m_Entries.FirstItem();
- while (item) {
- Entry* entry = item->GetData();
- if (entry->m_TrackId == track_id) {
- const char* name = entry->m_Name.GetChars();
- const char* value = NULL;
- AP4_Size name_len = 0;
- AP4_Size value_len = 0;
-
- if (AP4_CompareStrings(name, "ContentId") != 0 &&
- AP4_CompareStrings(name, "RightsIssuerUrl") != 0 &&
- AP4_CompareStrings(name, "KID") != 0) {
- name_len = entry->m_Name.GetLength();
- value = entry->m_Value.GetChars();
- value_len = entry->m_Value.GetLength();
-
- // format is name:value\0
- if (name && value) {
- AP4_CopyMemory(data_buffer, name, name_len);
- data_buffer[name_len] = ':';
- data_buffer += (1+name_len);
- AP4_CopyMemory(data_buffer, value, value_len);
- data_buffer[value_len] = '\0';
- data_buffer += (1+value_len);
- }
- }
- }
- item = item->GetNext();
- }
-
- // success path
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectedSampleDescription::AP4_ProtectedSampleDescription
-+---------------------------------------------------------------------*/
-AP4_ProtectedSampleDescription::AP4_ProtectedSampleDescription(
- AP4_UI32 format,
- AP4_SampleDescription* original_sample_description,
- AP4_UI32 original_format,
- AP4_UI32 scheme_type,
- AP4_UI32 scheme_version,
- const char* scheme_uri,
- AP4_ContainerAtom* schi,
- bool transfer_ownership_of_original /* = true */) :
- AP4_SampleDescription(TYPE_PROTECTED, format, NULL),
- m_OriginalSampleDescription(original_sample_description),
- m_OriginalSampleDescriptionIsOwned(transfer_ownership_of_original),
- m_OriginalFormat(original_format),
- m_SchemeType(scheme_type),
- m_SchemeVersion(scheme_version),
- m_SchemeUri(scheme_uri)
-{
- m_SchemeInfo = new AP4_ProtectionSchemeInfo(schi);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectedSampleDescription::~AP4_ProtectedSampleDescription
-+---------------------------------------------------------------------*/
-AP4_ProtectedSampleDescription::~AP4_ProtectedSampleDescription()
-{
- delete m_SchemeInfo;
- if (m_OriginalSampleDescriptionIsOwned) delete m_OriginalSampleDescription;
-}
-
-/*----------------------------------------------------------------------
-| AP4_ProtectedSampleDescription::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Atom*
-AP4_ProtectedSampleDescription::ToAtom() const
-{
- // construct the atom for the original sample description
- if (m_OriginalSampleDescription == NULL) return NULL;
- AP4_Atom* atom = m_OriginalSampleDescription->ToAtom();
-
- // switch the atom type
- atom->SetType(m_Format);
-
- // check that the constructed atom is a container
- AP4_ContainerAtom* container = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
- if (container == NULL) return atom; // not a container ?? return now.
-
- // create the sinf atom
- AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
-
- // create and add a frma atom
- AP4_FrmaAtom* frma = new AP4_FrmaAtom(m_OriginalFormat);
- sinf->AddChild(frma);
-
- // create and add a schm atom
- AP4_SchmAtom* schm = new AP4_SchmAtom(m_SchemeType, m_SchemeVersion, m_SchemeUri.GetChars());
- sinf->AddChild(schm);
-
- // add the schi atom
- if (m_SchemeInfo && m_SchemeInfo->GetSchiAtom()) {
- sinf->AddChild(m_SchemeInfo->GetSchiAtom()->Clone());
- }
-
- // add the sinf to the returned atom
- container->AddChild(sinf);
-
- return atom;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SampleDecrypter:Create
-+---------------------------------------------------------------------*/
-AP4_SampleDecrypter*
-AP4_SampleDecrypter::Create(AP4_ProtectedSampleDescription* sample_description,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory)
-{
- if (sample_description == NULL || key == NULL) return NULL;
-
- // select the block cipher factory
- if (block_cipher_factory == NULL) {
- block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
- }
-
- switch(sample_description->GetSchemeType()) {
- case AP4_PROTECTION_SCHEME_TYPE_OMA: {
- AP4_OmaDcfSampleDecrypter* decrypter = NULL;
- AP4_Result result = AP4_OmaDcfSampleDecrypter::Create(sample_description,
- key,
- key_size,
- block_cipher_factory,
- decrypter);
- if (AP4_FAILED(result)) return NULL;
- return decrypter;
- }
-
- case AP4_PROTECTION_SCHEME_TYPE_IAEC: {
- AP4_IsmaCipher* decrypter = NULL;
- AP4_Result result = AP4_IsmaCipher::CreateSampleDecrypter(sample_description,
- key,
- key_size,
- block_cipher_factory,
- decrypter);
- if (AP4_FAILED(result)) return NULL;
- return decrypter;
- }
-
- case AP4_PROTECTION_SCHEME_TYPE_PIFF: {
- AP4_PiffSampleDecrypter* decrypter = NULL;
- AP4_Result result = AP4_PiffSampleDecrypter::Create(sample_description,
- NULL,
- key,
- key_size,
- block_cipher_factory,
- decrypter);
- if (AP4_FAILED(result)) return NULL;
- return decrypter;
- }
-
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SampleDecrypter:Create
-+---------------------------------------------------------------------*/
-AP4_SampleDecrypter*
-AP4_SampleDecrypter::Create(AP4_ProtectedSampleDescription* sample_description,
- AP4_ContainerAtom* traf,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory)
-{
- if (sample_description == NULL || traf == NULL || key == NULL) return NULL;
-
- // select the block cipher factory
- if (block_cipher_factory == NULL) {
- block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
- }
-
- switch(sample_description->GetSchemeType()) {
- case AP4_PROTECTION_SCHEME_TYPE_PIFF: {
- AP4_PiffSampleDecrypter* decrypter = NULL;
- AP4_Result result = AP4_PiffSampleDecrypter::Create(sample_description,
- traf,
- key,
- key_size,
- block_cipher_factory,
- decrypter);
- if (AP4_FAILED(result)) return NULL;
- return decrypter;
- }
-
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_StandardDecryptingProcessor:AP4_StandardDecryptingProcessor
-+---------------------------------------------------------------------*/
-AP4_StandardDecryptingProcessor::AP4_StandardDecryptingProcessor(
- const AP4_ProtectionKeyMap* key_map /* = NULL */,
- AP4_BlockCipherFactory* block_cipher_factory /* = NULL */)
-{
- if (key_map) {
- // copy the keys
- m_KeyMap.SetKeys(*key_map);
- }
-
- if (block_cipher_factory == NULL) {
- m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
- } else {
- m_BlockCipherFactory = block_cipher_factory;
- }
-}
-
-/*----------------------------------------------------------------------
- | AP4_StandardDecryptingProcessor:Initialize
- +---------------------------------------------------------------------*/
-AP4_Result
-AP4_StandardDecryptingProcessor::Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& /*stream*/,
- ProgressListener* /*listener*/)
-{
- AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
- if (ftyp) {
- // remove the atom, it will be replaced with a new one
- top_level.RemoveChild(ftyp);
-
- // keep the existing brand and compatible brands except for the ones we want to remove
- AP4_Array<AP4_UI32> compatible_brands;
- compatible_brands.EnsureCapacity(ftyp->GetCompatibleBrands().ItemCount());
- for (unsigned int i=0; i<ftyp->GetCompatibleBrands().ItemCount(); i++) {
- if (ftyp->GetCompatibleBrands()[i] != AP4_OMA_DCF_BRAND_OPF2) {
- compatible_brands.Append(ftyp->GetCompatibleBrands()[i]);
- }
- }
-
- // create a replacement for the major brand
- top_level.AddChild(new AP4_FtypAtom(ftyp->GetMajorBrand(),
- ftyp->GetMinorVersion(),
- &compatible_brands[0],
- compatible_brands.ItemCount()), 0);
- delete ftyp;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_StandardDecryptingProcessor:CreateTrackHandler
-+---------------------------------------------------------------------*/
-AP4_Processor::TrackHandler*
-AP4_StandardDecryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
-{
- // find the stsd atom
- AP4_StsdAtom* stsd = AP4_DYNAMIC_CAST(AP4_StsdAtom, trak->FindChild("mdia/minf/stbl/stsd"));
-
- // avoid tracks with no stsd atom (should not happen)
- if (stsd == NULL) return NULL;
-
- // we only look at the first sample description
- AP4_SampleDescription* desc = stsd->GetSampleDescription(0);
- AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
- if (desc == NULL || entry == NULL) return NULL;
- if (desc->GetType() == AP4_SampleDescription::TYPE_PROTECTED) {
- // create a handler for this track
- AP4_ProtectedSampleDescription* protected_desc =
- static_cast<AP4_ProtectedSampleDescription*>(desc);
- if (protected_desc->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_OMA) {
- const AP4_UI08* key = m_KeyMap.GetKey(trak->GetId());
- if (key) {
- AP4_OmaDcfTrackDecrypter* handler = NULL;
- AP4_Result result = AP4_OmaDcfTrackDecrypter::Create(key,
- AP4_CIPHER_BLOCK_SIZE,
- protected_desc,
- entry,
- m_BlockCipherFactory,
- handler);
- if (AP4_FAILED(result)) return NULL;
- return handler;
- }
- } else if (protected_desc->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_IAEC) {
- const AP4_UI08* key = m_KeyMap.GetKey(trak->GetId());
- if (key) {
- AP4_IsmaTrackDecrypter* handler = NULL;
- AP4_Result result = AP4_IsmaTrackDecrypter::Create(key,
- AP4_CIPHER_BLOCK_SIZE,
- protected_desc,
- entry,
- m_BlockCipherFactory,
- handler);
- if (AP4_FAILED(result)) return NULL;
- return handler;
- }
- }
- }
-
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::AP4_DecryptingStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DecryptingStream::Create(CipherMode mode,
- AP4_ByteStream& encrypted_stream,
- AP4_LargeSize cleartext_size,
- const AP4_UI08* iv,
- AP4_Size iv_size,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream)
-{
- // default return value
- stream = NULL;
-
- // default cipher settings
- if (block_cipher_factory == NULL) {
- block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
- }
-
- // get the encrypted size (includes padding)
- AP4_LargeSize encrypted_size = 0;
- AP4_Result result = encrypted_stream.GetSize(encrypted_size);
- if (AP4_FAILED(result)) return result;
-
- // check IV
- if (iv == NULL || iv_size != 16) return AP4_ERROR_INVALID_PARAMETERS;
-
- // check that the encrypted size is consistent with the cipher mode
- if (mode == CIPHER_MODE_CBC) {
- // we need at least 32 bytes of data+padding
- // we also need a multiple of the block size
- if (encrypted_size < 32 || ((encrypted_size % 16) != 0)) {
- return AP4_ERROR_INVALID_FORMAT;
- }
- }
-
- // create the stream cipher
- AP4_BlockCipher* block_cipher;
- result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
- (mode == CIPHER_MODE_CTR ?
- AP4_BlockCipher::ENCRYPT :
- AP4_BlockCipher::DECRYPT),
- key, key_size, block_cipher);
- if (AP4_FAILED(result)) return result;
-
- // keep a reference to the source stream
- encrypted_stream.AddReference();
-
- // create the stream
- AP4_DecryptingStream* dec_stream = new AP4_DecryptingStream();
- stream = dec_stream;
- dec_stream->m_Mode = mode;
- dec_stream->m_CleartextSize = cleartext_size;
- dec_stream->m_CleartextPosition = 0;
- dec_stream->m_EncryptedSize = encrypted_size;
- dec_stream->m_EncryptedStream = &encrypted_stream;
- dec_stream->m_EncryptedPosition = 0;
- dec_stream->m_BufferFullness = 0;
- dec_stream->m_BufferOffset = 0;
- dec_stream->m_ReferenceCount = 1;
-
- // create the cipher according to the mode
- switch (mode) {
- case CIPHER_MODE_CBC:
- dec_stream->m_StreamCipher = new AP4_CbcStreamCipher(block_cipher,
- AP4_StreamCipher::DECRYPT);
- break;
- case CIPHER_MODE_CTR:
- dec_stream->m_StreamCipher = new AP4_CtrStreamCipher(block_cipher,
- NULL,
- AP4_CIPHER_BLOCK_SIZE);
- break;
- default:
- // should never occur
- AP4_ASSERT(0);
- }
-
- // set the IV
- dec_stream->m_StreamCipher->SetIV(iv);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::~AP4_DecryptingStream
-+---------------------------------------------------------------------*/
-AP4_DecryptingStream::~AP4_DecryptingStream()
-{
- delete m_StreamCipher;
- m_EncryptedStream->Release();
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::AddReference
-+---------------------------------------------------------------------*/
-void
-AP4_DecryptingStream::AddReference()
-{
- ++m_ReferenceCount;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::Release
-+---------------------------------------------------------------------*/
-void
-AP4_DecryptingStream::Release()
-{
- if (--m_ReferenceCount == 0) delete this;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::ReadPartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DecryptingStream::ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read)
-{
- bytes_read = 0;
-
- // never read more than what's available
- AP4_LargeSize available = m_CleartextSize-m_CleartextPosition;
- if (available < bytes_to_read) {
- if (available == 0) {
- return AP4_ERROR_EOS;
- }
- bytes_to_read = (AP4_Size)available;
- }
-
- if (m_BufferFullness) {
- // we have some leftovers
- AP4_Size chunk = bytes_to_read;
- if (chunk > m_BufferFullness) chunk = m_BufferFullness;
- AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
- buffer = (char*)buffer+chunk;
- m_CleartextPosition += chunk;
- available -= chunk;
- bytes_to_read -= chunk;
- m_BufferFullness -= chunk;
- m_BufferOffset += chunk;
- bytes_read += chunk;
- }
-
- // seek to the right place in the input
- m_EncryptedStream->Seek(m_EncryptedPosition);
-
- while (bytes_to_read) {
- // read from the source
- AP4_UI08 encrypted[16];
- AP4_Size encrypted_read = 0;
- AP4_Result result = m_EncryptedStream->ReadPartial(encrypted, 16, encrypted_read);
- if (result == AP4_ERROR_EOS) {
- if (bytes_read == 0) {
- return AP4_ERROR_EOS;
- } else {
- return AP4_SUCCESS;
- }
- } else if (result != AP4_SUCCESS) {
- return result;
- } else {
- m_EncryptedPosition += encrypted_read;
- }
- bool is_last_buffer = (m_EncryptedPosition >= m_EncryptedSize);
- AP4_Size buffer_size = 16;
- result = m_StreamCipher->ProcessBuffer(encrypted,
- encrypted_read,
- m_Buffer,
- &buffer_size,
- is_last_buffer);
- m_BufferOffset = 0;
- m_BufferFullness = buffer_size;
-
- AP4_Size chunk = bytes_to_read;
- if (chunk > m_BufferFullness) chunk = m_BufferFullness;
- AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
- buffer = (char*)buffer+chunk;
- m_CleartextPosition += chunk;
- available -= chunk;
- bytes_to_read -= chunk;
- m_BufferFullness -= chunk;
- m_BufferOffset += chunk;
- bytes_read += chunk;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::WritePartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DecryptingStream::WritePartial(const void* /* buffer */,
- AP4_Size /* bytes_to_write */,
- AP4_Size& /* bytes_written */)
-{
- return AP4_ERROR_NOT_SUPPORTED;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::Seek
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DecryptingStream::Seek(AP4_Position position)
-{
- AP4_Cardinal preroll = 0;
-
- // check bounds
- if (position > m_CleartextSize) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
-
- // try to put the stream cipher at the right offset
- AP4_CHECK(m_StreamCipher->SetStreamOffset(position, &preroll));
-
- // seek in the source stream
- AP4_CHECK(m_EncryptedStream->Seek(position-preroll));
-
- // if we need to, process the preroll bytes
- if (preroll > 0) {
- AP4_Size out_size = 0;
- AP4_UI08 buffer[2*AP4_CIPHER_BLOCK_SIZE]; // bigger than preroll
- AP4_CHECK(m_EncryptedStream->Read(buffer, preroll));
- AP4_CHECK(m_StreamCipher->ProcessBuffer(buffer, preroll, buffer, &out_size));
- AP4_ASSERT(out_size == 0); // we're just feeding prerolled bytes,
- // there can be no output
- }
-
- // update the counters
- m_CleartextPosition = position;
- m_EncryptedPosition = position;
- m_BufferFullness = 0;
- m_BufferOffset = 0;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::Tell
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DecryptingStream::Tell(AP4_Position& position)
-{
- position = m_CleartextPosition;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream::GetSize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DecryptingStream::GetSize(AP4_LargeSize& size)
-{
- size = m_CleartextSize;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::AP4_EncryptingStream
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_EncryptingStream::Create(CipherMode mode,
- AP4_ByteStream& cleartext_stream,
- const AP4_UI08* iv,
- AP4_Size iv_size,
- const AP4_UI08* key,
- AP4_Size key_size,
- bool prepend_iv,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream)
-{
- // default return value
- stream = NULL;
-
- // get the cleartext size
- AP4_LargeSize cleartext_size = 0;
- AP4_Result result = cleartext_stream.GetSize(cleartext_size);
- if (AP4_FAILED(result)) return result;
-
- // check IV
- if (iv == NULL || iv_size != 16) return AP4_ERROR_INVALID_PARAMETERS;
-
- // compute the encrypted size
- AP4_LargeSize encrypted_size = cleartext_size;
- if (mode == CIPHER_MODE_CBC) {
- encrypted_size += (16-(cleartext_size%16)); // with padding
- }
-
- // create the stream cipher
- AP4_BlockCipher* block_cipher;
- result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
- AP4_BlockCipher::ENCRYPT,
- key, key_size, block_cipher);
- if (AP4_FAILED(result)) return result;
-
- // keep a reference to the source stream
- cleartext_stream.AddReference();
-
- // create the stream
- AP4_EncryptingStream* enc_stream = new AP4_EncryptingStream();
- stream = enc_stream;
- enc_stream->m_Mode = mode;
- enc_stream->m_CleartextStream = &cleartext_stream;
- enc_stream->m_CleartextSize = cleartext_size;
- enc_stream->m_CleartextPosition = 0;
- enc_stream->m_EncryptedSize = encrypted_size;
- enc_stream->m_EncryptedPosition = 0;
- enc_stream->m_BufferFullness = 0;
- enc_stream->m_BufferOffset = 0;
- enc_stream->m_ReferenceCount = 1;
-
- // deal with the prepended IV if required
- if (prepend_iv) {
- enc_stream->m_EncryptedSize += 16;
- enc_stream->m_BufferFullness = 16;
- AP4_CopyMemory(enc_stream->m_Buffer, iv, 16);
- }
-
- // create the cipher according to the mode
- switch (mode) {
- case CIPHER_MODE_CBC:
- enc_stream->m_StreamCipher = new AP4_CbcStreamCipher(block_cipher,
- AP4_StreamCipher::ENCRYPT);
- break;
- case CIPHER_MODE_CTR:
- enc_stream->m_StreamCipher = new AP4_CtrStreamCipher(block_cipher,
- NULL,
- AP4_CIPHER_BLOCK_SIZE);
- break;
- default:
- // should never occur
- AP4_ASSERT(0);
- }
-
- // set the IV
- enc_stream->m_StreamCipher->SetIV(iv);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::~AP4_EncryptingStream
-+---------------------------------------------------------------------*/
-AP4_EncryptingStream::~AP4_EncryptingStream()
-{
- delete m_StreamCipher;
- m_CleartextStream->Release();
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::AddReference
-+---------------------------------------------------------------------*/
-void
-AP4_EncryptingStream::AddReference()
-{
- ++m_ReferenceCount;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::Release
-+---------------------------------------------------------------------*/
-void
-AP4_EncryptingStream::Release()
-{
- if (--m_ReferenceCount == 0) delete this;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::ReadPartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_EncryptingStream::ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read)
-{
- bytes_read = 0;
-
- // never read more than what's available
- AP4_LargeSize available = m_EncryptedSize-m_EncryptedPosition;
- if (available < bytes_to_read) {
- if (available == 0) return AP4_ERROR_EOS;
- bytes_to_read = (AP4_Size)available;
- }
-
- if (m_BufferFullness) {
- // we have some leftovers
- AP4_Size chunk = bytes_to_read;
- if (chunk > m_BufferFullness) chunk = m_BufferFullness;
- AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
- buffer = (char*)buffer+chunk;
- m_EncryptedPosition += chunk;
- available -= chunk;
- bytes_to_read -= chunk;
- m_BufferFullness -= chunk;
- m_BufferOffset += chunk;
- bytes_read += chunk;
- }
-
- // seek to the right place in the input
- m_CleartextStream->Seek(m_CleartextPosition);
-
- while (bytes_to_read) {
- // read from the source
- AP4_UI08 cleartext[16];
- AP4_Size cleartext_read = 0;
- AP4_Result result = m_CleartextStream->ReadPartial(cleartext, 16, cleartext_read);
- if (result == AP4_ERROR_EOS) {
- if (bytes_read == 0) {
- return AP4_ERROR_EOS;
- } else {
- return AP4_SUCCESS;
- }
- } else if (result != AP4_SUCCESS) {
- return result;
- } else {
- m_CleartextPosition += cleartext_read;
- }
- bool is_last_buffer = (m_CleartextPosition >= m_CleartextSize);
- AP4_Size buffer_size = 32; // enough for one block plus one block padding
- result = m_StreamCipher->ProcessBuffer(cleartext,
- cleartext_read,
- m_Buffer,
- &buffer_size,
- is_last_buffer);
- m_BufferOffset = 0;
- m_BufferFullness = buffer_size;
-
- AP4_Size chunk = bytes_to_read;
- if (chunk > m_BufferFullness) chunk = m_BufferFullness;
- if (chunk) {
- AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
- buffer = (char*)buffer+chunk;
- m_EncryptedPosition += chunk;
- available -= chunk;
- bytes_to_read -= chunk;
- m_BufferFullness -= chunk;
- m_BufferOffset += chunk;
- bytes_read += chunk;
- }
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::WritePartial
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_EncryptingStream::WritePartial(const void* /* buffer */,
- AP4_Size /* bytes_to_write */,
- AP4_Size& /* bytes_written */)
-{
- return AP4_ERROR_NOT_SUPPORTED;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::Seek
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_EncryptingStream::Seek(AP4_Position position)
-{
- if (position == m_EncryptedPosition) {
- return AP4_SUCCESS;
- } else {
- return AP4_ERROR_NOT_SUPPORTED;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::Tell
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_EncryptingStream::Tell(AP4_Position& position)
-{
- position = m_EncryptedPosition;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream::GetSize
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_EncryptingStream::GetSize(AP4_LargeSize& size)
-{
- size = m_EncryptedSize;
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DefaultBlockCipherFactory::Instance
-+---------------------------------------------------------------------*/
-AP4_DefaultBlockCipherFactory AP4_DefaultBlockCipherFactory::Instance;
-
-/*----------------------------------------------------------------------
-| AP4_DefaultBlockCipherFactory
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DefaultBlockCipherFactory::Create(AP4_BlockCipher::CipherType type,
- AP4_BlockCipher::CipherDirection direction,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipher*& cipher)
-{
- // setup default return vaule
- cipher = NULL;
-
- switch (type) {
- case AP4_BlockCipher::AES_128:
- // check cipher parameters
- if (key == NULL || key_size != AP4_AES_BLOCK_SIZE) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
-
- // create the cipher
- cipher = new AP4_AesBlockCipher(key, direction);
- return AP4_SUCCESS;
-
- default:
- // not supported
- return AP4_ERROR_NOT_SUPPORTED;
- }
-}
+/*****************************************************************
+|
+| AP4 - Protected Stream Support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Protection.h"
+#include "Ap4SchmAtom.h"
+#include "Ap4StsdAtom.h"
+#include "Ap4FtypAtom.h"
+#include "Ap4Sample.h"
+#include "Ap4StreamCipher.h"
+#include "Ap4IsfmAtom.h"
+#include "Ap4FrmaAtom.h"
+#include "Ap4IkmsAtom.h"
+#include "Ap4IsfmAtom.h"
+#include "Ap4IsltAtom.h"
+#include "Ap4Utils.h"
+#include "Ap4TrakAtom.h"
+#include "Ap4IsmaCryp.h"
+#include "Ap4AesBlockCipher.h"
+#include "Ap4OmaDcf.h"
+#include "Ap4Marlin.h"
+#include "Ap4Piff.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_ProtectedSampleDescription)
+
+/*----------------------------------------------------------------------
+| AP4_EncaSampleEntry::AP4_EncaSampleEntry
++---------------------------------------------------------------------*/
+AP4_EncaSampleEntry::AP4_EncaSampleEntry(AP4_UI32 type,
+ AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory) :
+ AP4_AudioSampleEntry(type, size, stream, atom_factory)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncaSampleEntry::AP4_EncaSampleEntry
++---------------------------------------------------------------------*/
+AP4_EncaSampleEntry::AP4_EncaSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory) :
+ AP4_AudioSampleEntry(AP4_ATOM_TYPE_ENCA, size, stream, atom_factory)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncaSampleEntry::ToSampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_EncaSampleEntry::ToSampleDescription()
+{
+ // get the original sample format
+ AP4_FrmaAtom* frma = (AP4_FrmaAtom*)FindChild("sinf/frma");
+
+ // get the schi atom
+ AP4_ContainerAtom* schi;
+ schi = static_cast<AP4_ContainerAtom*>(FindChild("sinf/schi"));
+
+ // get the scheme info
+ AP4_SchmAtom* schm = (AP4_SchmAtom*)FindChild("sinf/schm");
+ AP4_UI32 original_format = frma?frma->GetOriginalFormat():AP4_ATOM_TYPE_MP4A;
+ if (schm) {
+ // create the original sample description
+ return new AP4_ProtectedSampleDescription(
+ m_Type,
+ ToTargetSampleDescription(original_format),
+ original_format,
+ schm->GetSchemeType(),
+ schm->GetSchemeVersion(),
+ schm->GetSchemeUri().GetChars(),
+ schi);
+ } else if (schi) {
+ // try to see if we can guess the protection scheme from the 'schi' contents
+ AP4_Atom* odkm = schi->GetChild(AP4_ATOM_TYPE_ODKM);
+ if (odkm) {
+ // create the original sample description
+ return new AP4_ProtectedSampleDescription(
+ m_Type,
+ ToTargetSampleDescription(original_format),
+ original_format,
+ AP4_PROTECTION_SCHEME_TYPE_OMA,
+ AP4_PROTECTION_SCHEME_VERSION_OMA_20,
+ NULL,
+ schi);
+ }
+ }
+
+ // unknown scheme
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncaSampleEntry::ToTargetSampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_EncaSampleEntry::ToTargetSampleDescription(AP4_UI32 format)
+{
+ switch (format) {
+ case AP4_ATOM_TYPE_MP4A: {
+ AP4_EsdsAtom* esds = AP4_DYNAMIC_CAST(AP4_EsdsAtom, GetChild(AP4_ATOM_TYPE_ESDS));
+ if (esds == NULL) {
+ // check if this is a quicktime style sample description
+ if (m_QtVersion > 0) {
+ esds = AP4_DYNAMIC_CAST(AP4_EsdsAtom, FindChild("wave/esds"));
+ }
+ }
+ return new AP4_MpegAudioSampleDescription(
+ GetSampleRate(),
+ GetSampleSize(),
+ GetChannelCount(),
+ esds);
+ }
+
+ default:
+ return new AP4_GenericAudioSampleDescription(
+ format,
+ GetSampleRate(),
+ GetSampleSize(),
+ GetChannelCount(),
+ this);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncvSampleEntry::AP4_EncvSampleEntry
++---------------------------------------------------------------------*/
+AP4_EncvSampleEntry::AP4_EncvSampleEntry(AP4_UI32 type,
+ AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory) :
+ AP4_VisualSampleEntry(type, size, stream, atom_factory)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncvSampleEntry::AP4_EncvSampleEntry
++---------------------------------------------------------------------*/
+AP4_EncvSampleEntry::AP4_EncvSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory) :
+ AP4_VisualSampleEntry(AP4_ATOM_TYPE_ENCV, size, stream, atom_factory)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncvSampleEntry::ToSampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_EncvSampleEntry::ToSampleDescription()
+{
+ // get the original sample format
+ AP4_FrmaAtom* frma = (AP4_FrmaAtom*)FindChild("sinf/frma");
+
+ // get the schi atom
+ AP4_ContainerAtom* schi;
+ schi = static_cast<AP4_ContainerAtom*>(FindChild("sinf/schi"));
+
+ // get the scheme info
+ AP4_SchmAtom* schm = (AP4_SchmAtom*)FindChild("sinf/schm");
+ AP4_UI32 original_format = frma?frma->GetOriginalFormat():AP4_ATOM_TYPE_MP4V;
+ if (schm) {
+ // create the sample description
+ return new AP4_ProtectedSampleDescription(
+ m_Type,
+ ToTargetSampleDescription(original_format),
+ original_format,
+ schm->GetSchemeType(),
+ schm->GetSchemeVersion(),
+ schm->GetSchemeUri().GetChars(),
+ schi);
+ } else if (schi) {
+ // try to see if we can guess the protection scheme from the 'schi' contents
+ AP4_Atom* odkm = schi->GetChild(AP4_ATOM_TYPE_ODKM);
+ if (odkm) {
+ // create the original sample description
+ return new AP4_ProtectedSampleDescription(
+ m_Type,
+ ToTargetSampleDescription(original_format),
+ original_format,
+ AP4_PROTECTION_SCHEME_TYPE_OMA,
+ AP4_PROTECTION_SCHEME_VERSION_OMA_20,
+ NULL,
+ schi);
+ }
+ }
+
+ // unknown scheme
+ return NULL;
+
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncvSampleEntry::ToTargetSampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_EncvSampleEntry::ToTargetSampleDescription(AP4_UI32 format)
+{
+ switch (format) {
+ case AP4_ATOM_TYPE_AVC1:
+ return new AP4_AvcSampleDescription(
+ m_Width,
+ m_Height,
+ m_Depth,
+ m_CompressorName.GetChars(),
+ this);
+
+ case AP4_ATOM_TYPE_MP4V:
+ return new AP4_MpegVideoSampleDescription(
+ m_Width,
+ m_Height,
+ m_Depth,
+ m_CompressorName.GetChars(),
+ AP4_DYNAMIC_CAST(AP4_EsdsAtom, GetChild(AP4_ATOM_TYPE_ESDS)));
+
+ default:
+ return new AP4_GenericVideoSampleDescription(
+ format,
+ m_Width,
+ m_Height,
+ m_Depth,
+ m_CompressorName.GetChars(),
+ this);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_DrmsSampleEntry::AP4_DrmsSampleEntry
++---------------------------------------------------------------------*/
+AP4_DrmsSampleEntry::AP4_DrmsSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory) :
+ AP4_EncaSampleEntry(AP4_ATOM_TYPE_DRMS, size, stream, atom_factory)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_DrmiSampleEntry::AP4_DrmiSampleEntry
++---------------------------------------------------------------------*/
+AP4_DrmiSampleEntry::AP4_DrmiSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory) :
+ AP4_EncvSampleEntry(AP4_ATOM_TYPE_DRMI, size, stream, atom_factory)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionSchemeInfo::~AP4_ProtectionSchemeInfo
++---------------------------------------------------------------------*/
+AP4_ProtectionSchemeInfo::~AP4_ProtectionSchemeInfo()
+{
+ delete m_SchiAtom;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionSchemeInfo::AP4_ProtectionSchemeInfo
++---------------------------------------------------------------------*/
+AP4_ProtectionSchemeInfo::AP4_ProtectionSchemeInfo(AP4_ContainerAtom* schi)
+{
+ if (schi) {
+ m_SchiAtom = (AP4_ContainerAtom*)schi->Clone();
+ } else {
+ m_SchiAtom = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::AP4_ProtectionKeyMap
++---------------------------------------------------------------------*/
+AP4_ProtectionKeyMap::AP4_ProtectionKeyMap()
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::~AP4_ProtectionKeyMap
++---------------------------------------------------------------------*/
+AP4_ProtectionKeyMap::~AP4_ProtectionKeyMap()
+{
+ m_KeyEntries.DeleteReferences();
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::SetKey
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ProtectionKeyMap::SetKey(AP4_UI32 track_id, const AP4_UI08* key, const AP4_UI08* iv)
+{
+ KeyEntry* entry = GetEntry(track_id);
+ if (entry == NULL) {
+ m_KeyEntries.Add(new KeyEntry(track_id, key, iv));
+ } else {
+ entry->SetKey(key, iv);
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::SetKey
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ProtectionKeyMap::SetKeys(const AP4_ProtectionKeyMap& key_map)
+{
+ AP4_List<KeyEntry>::Item* item = key_map.m_KeyEntries.FirstItem();
+ while (item) {
+ KeyEntry* entry = item->GetData();
+ m_KeyEntries.Add(new KeyEntry(entry->m_TrackId,
+ entry->m_Key,
+ entry->m_IV));
+ item = item->GetNext();
+ }
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::GetKeyIv
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ProtectionKeyMap::GetKeyAndIv(AP4_UI32 track_id,
+ const AP4_UI08*& key,
+ const AP4_UI08*& iv)
+{
+ KeyEntry* entry = GetEntry(track_id);
+ if (entry) {
+ key = entry->m_Key;
+ iv = entry->m_IV;
+ return AP4_SUCCESS;
+ } else {
+ return AP4_ERROR_NO_SUCH_ITEM;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::GetKey
++---------------------------------------------------------------------*/
+const AP4_UI08*
+AP4_ProtectionKeyMap::GetKey(AP4_UI32 track_id) const
+{
+ KeyEntry* entry = GetEntry(track_id);
+ if (entry) {
+ return entry->m_Key;
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::GetEntry
++---------------------------------------------------------------------*/
+AP4_ProtectionKeyMap::KeyEntry*
+AP4_ProtectionKeyMap::GetEntry(AP4_UI32 track_id) const
+{
+ AP4_List<KeyEntry>::Item* item = m_KeyEntries.FirstItem();
+ while (item) {
+ KeyEntry* entry = (KeyEntry*)item->GetData();
+ if (entry->m_TrackId == track_id) return entry;
+ item = item->GetNext();
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::KeyEntry::KeyEntry
++---------------------------------------------------------------------*/
+AP4_ProtectionKeyMap::KeyEntry::KeyEntry(AP4_UI32 track_id,
+ const AP4_UI08* key,
+ const AP4_UI08* iv /* = NULL */) :
+ m_TrackId(track_id)
+{
+ SetKey(key, iv);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap::KeyEntry::SetKey
++---------------------------------------------------------------------*/
+void
+AP4_ProtectionKeyMap::KeyEntry::SetKey(const AP4_UI08* key, const AP4_UI08* iv)
+{
+ AP4_CopyMemory(m_Key, key, sizeof(m_Key));
+ if (iv) {
+ AP4_CopyMemory(m_IV, iv, sizeof(m_IV));
+ } else {
+ AP4_SetMemory(m_IV, 0, sizeof(m_IV));
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrackPropertyMap::~AP4_TrackPropertyMap
++---------------------------------------------------------------------*/
+AP4_TrackPropertyMap::~AP4_TrackPropertyMap()
+{
+ m_Entries.DeleteReferences();
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrackPropertyMap::SetProperty
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_TrackPropertyMap::SetProperty(AP4_UI32 track_id,
+ const char* name,
+ const char* value)
+{
+ return m_Entries.Add(new Entry(track_id, name, value));
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrackPropertyMap::SetProperties
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_TrackPropertyMap::SetProperties(const AP4_TrackPropertyMap& properties)
+{
+ AP4_List<Entry>::Item* item = properties.m_Entries.FirstItem();
+ while (item) {
+ Entry* entry = item->GetData();
+ m_Entries.Add(new Entry(entry->m_TrackId,
+ entry->m_Name.GetChars(),
+ entry->m_Value.GetChars()));
+ item = item->GetNext();
+ }
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrackPropertyMap::GetProperty
++---------------------------------------------------------------------*/
+const char*
+AP4_TrackPropertyMap::GetProperty(AP4_UI32 track_id, const char* name)
+{
+ AP4_List<Entry>::Item* item = m_Entries.FirstItem();
+ while (item) {
+ Entry* entry = item->GetData();
+ if (entry->m_TrackId == track_id &&
+ AP4_CompareStrings(entry->m_Name.GetChars(), name) == 0) {
+ return entry->m_Value.GetChars();
+ }
+ item = item->GetNext();
+ }
+
+ // not found
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrackPropertyMap::GetTextualHeaders
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_TrackPropertyMap::GetTextualHeaders(AP4_UI32 track_id, AP4_DataBuffer& textual_headers)
+{
+ AP4_Size buffer_size = 0;
+ AP4_Result result = AP4_SUCCESS;
+ AP4_Byte* data_buffer;
+
+ // get the size needed for the textual headers
+ AP4_List<Entry>::Item* item = m_Entries.FirstItem();
+ while (item) {
+ Entry* entry = item->GetData();
+ if (entry->m_TrackId == track_id) {
+ const char* name = entry->m_Name.GetChars();
+ if (AP4_CompareStrings(name, "ContentId") != 0 &&
+ AP4_CompareStrings(name, "RightsIssuerUrl") != 0 &&
+ AP4_CompareStrings(name, "KID") != 0) {
+ buffer_size += (entry->m_Name.GetLength() +
+ entry->m_Value.GetLength() +
+ 2); // colon + nul
+
+ }
+ }
+ item = item->GetNext();
+ }
+
+ result = textual_headers.SetDataSize(buffer_size);
+ AP4_CHECK(result);
+
+ data_buffer = textual_headers.UseData();
+
+ // set the textual headers
+ item = m_Entries.FirstItem();
+ while (item) {
+ Entry* entry = item->GetData();
+ if (entry->m_TrackId == track_id) {
+ const char* name = entry->m_Name.GetChars();
+ const char* value = NULL;
+ AP4_Size name_len = 0;
+ AP4_Size value_len = 0;
+
+ if (AP4_CompareStrings(name, "ContentId") != 0 &&
+ AP4_CompareStrings(name, "RightsIssuerUrl") != 0 &&
+ AP4_CompareStrings(name, "KID") != 0) {
+ name_len = entry->m_Name.GetLength();
+ value = entry->m_Value.GetChars();
+ value_len = entry->m_Value.GetLength();
+
+ // format is name:value\0
+ if (name && value) {
+ AP4_CopyMemory(data_buffer, name, name_len);
+ data_buffer[name_len] = ':';
+ data_buffer += (1+name_len);
+ AP4_CopyMemory(data_buffer, value, value_len);
+ data_buffer[value_len] = '\0';
+ data_buffer += (1+value_len);
+ }
+ }
+ }
+ item = item->GetNext();
+ }
+
+ // success path
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectedSampleDescription::AP4_ProtectedSampleDescription
++---------------------------------------------------------------------*/
+AP4_ProtectedSampleDescription::AP4_ProtectedSampleDescription(
+ AP4_UI32 format,
+ AP4_SampleDescription* original_sample_description,
+ AP4_UI32 original_format,
+ AP4_UI32 scheme_type,
+ AP4_UI32 scheme_version,
+ const char* scheme_uri,
+ AP4_ContainerAtom* schi,
+ bool transfer_ownership_of_original /* = true */) :
+ AP4_SampleDescription(TYPE_PROTECTED, format, NULL),
+ m_OriginalSampleDescription(original_sample_description),
+ m_OriginalSampleDescriptionIsOwned(transfer_ownership_of_original),
+ m_OriginalFormat(original_format),
+ m_SchemeType(scheme_type),
+ m_SchemeVersion(scheme_version),
+ m_SchemeUri(scheme_uri)
+{
+ m_SchemeInfo = new AP4_ProtectionSchemeInfo(schi);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectedSampleDescription::~AP4_ProtectedSampleDescription
++---------------------------------------------------------------------*/
+AP4_ProtectedSampleDescription::~AP4_ProtectedSampleDescription()
+{
+ delete m_SchemeInfo;
+ if (m_OriginalSampleDescriptionIsOwned) delete m_OriginalSampleDescription;
+}
+
+/*----------------------------------------------------------------------
+| AP4_ProtectedSampleDescription::ToAtom
++---------------------------------------------------------------------*/
+AP4_Atom*
+AP4_ProtectedSampleDescription::ToAtom() const
+{
+ // construct the atom for the original sample description
+ if (m_OriginalSampleDescription == NULL) return NULL;
+ AP4_Atom* atom = m_OriginalSampleDescription->ToAtom();
+
+ // switch the atom type
+ atom->SetType(m_Format);
+
+ // check that the constructed atom is a container
+ AP4_ContainerAtom* container = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
+ if (container == NULL) return atom; // not a container ?? return now.
+
+ // create the sinf atom
+ AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
+
+ // create and add a frma atom
+ AP4_FrmaAtom* frma = new AP4_FrmaAtom(m_OriginalFormat);
+ sinf->AddChild(frma);
+
+ // create and add a schm atom
+ AP4_SchmAtom* schm = new AP4_SchmAtom(m_SchemeType, m_SchemeVersion, m_SchemeUri.GetChars());
+ sinf->AddChild(schm);
+
+ // add the schi atom
+ if (m_SchemeInfo && m_SchemeInfo->GetSchiAtom()) {
+ sinf->AddChild(m_SchemeInfo->GetSchiAtom()->Clone());
+ }
+
+ // add the sinf to the returned atom
+ container->AddChild(sinf);
+
+ return atom;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SampleDecrypter:Create
++---------------------------------------------------------------------*/
+AP4_SampleDecrypter*
+AP4_SampleDecrypter::Create(AP4_ProtectedSampleDescription* sample_description,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory)
+{
+ if (sample_description == NULL || key == NULL) return NULL;
+
+ // select the block cipher factory
+ if (block_cipher_factory == NULL) {
+ block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
+ }
+
+ switch(sample_description->GetSchemeType()) {
+ case AP4_PROTECTION_SCHEME_TYPE_OMA: {
+ AP4_OmaDcfSampleDecrypter* decrypter = NULL;
+ AP4_Result result = AP4_OmaDcfSampleDecrypter::Create(sample_description,
+ key,
+ key_size,
+ block_cipher_factory,
+ decrypter);
+ if (AP4_FAILED(result)) return NULL;
+ return decrypter;
+ }
+
+ case AP4_PROTECTION_SCHEME_TYPE_IAEC: {
+ AP4_IsmaCipher* decrypter = NULL;
+ AP4_Result result = AP4_IsmaCipher::CreateSampleDecrypter(sample_description,
+ key,
+ key_size,
+ block_cipher_factory,
+ decrypter);
+ if (AP4_FAILED(result)) return NULL;
+ return decrypter;
+ }
+
+ case AP4_PROTECTION_SCHEME_TYPE_PIFF: {
+ AP4_PiffSampleDecrypter* decrypter = NULL;
+ AP4_Result result = AP4_PiffSampleDecrypter::Create(sample_description,
+ NULL,
+ key,
+ key_size,
+ block_cipher_factory,
+ decrypter);
+ if (AP4_FAILED(result)) return NULL;
+ return decrypter;
+ }
+
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SampleDecrypter:Create
++---------------------------------------------------------------------*/
+AP4_SampleDecrypter*
+AP4_SampleDecrypter::Create(AP4_ProtectedSampleDescription* sample_description,
+ AP4_ContainerAtom* traf,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory)
+{
+ if (sample_description == NULL || traf == NULL || key == NULL) return NULL;
+
+ // select the block cipher factory
+ if (block_cipher_factory == NULL) {
+ block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
+ }
+
+ switch(sample_description->GetSchemeType()) {
+ case AP4_PROTECTION_SCHEME_TYPE_PIFF: {
+ AP4_PiffSampleDecrypter* decrypter = NULL;
+ AP4_Result result = AP4_PiffSampleDecrypter::Create(sample_description,
+ traf,
+ key,
+ key_size,
+ block_cipher_factory,
+ decrypter);
+ if (AP4_FAILED(result)) return NULL;
+ return decrypter;
+ }
+
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_StandardDecryptingProcessor:AP4_StandardDecryptingProcessor
++---------------------------------------------------------------------*/
+AP4_StandardDecryptingProcessor::AP4_StandardDecryptingProcessor(
+ const AP4_ProtectionKeyMap* key_map /* = NULL */,
+ AP4_BlockCipherFactory* block_cipher_factory /* = NULL */)
+{
+ if (key_map) {
+ // copy the keys
+ m_KeyMap.SetKeys(*key_map);
+ }
+
+ if (block_cipher_factory == NULL) {
+ m_BlockCipherFactory = &AP4_DefaultBlockCipherFactory::Instance;
+ } else {
+ m_BlockCipherFactory = block_cipher_factory;
+ }
+}
+
+/*----------------------------------------------------------------------
+ | AP4_StandardDecryptingProcessor:Initialize
+ +---------------------------------------------------------------------*/
+AP4_Result
+AP4_StandardDecryptingProcessor::Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& /*stream*/,
+ ProgressListener* /*listener*/)
+{
+ AP4_FtypAtom* ftyp = AP4_DYNAMIC_CAST(AP4_FtypAtom, top_level.GetChild(AP4_ATOM_TYPE_FTYP));
+ if (ftyp) {
+ // remove the atom, it will be replaced with a new one
+ top_level.RemoveChild(ftyp);
+
+ // keep the existing brand and compatible brands except for the ones we want to remove
+ AP4_Array<AP4_UI32> compatible_brands;
+ compatible_brands.EnsureCapacity(ftyp->GetCompatibleBrands().ItemCount());
+ for (unsigned int i=0; i<ftyp->GetCompatibleBrands().ItemCount(); i++) {
+ if (ftyp->GetCompatibleBrands()[i] != AP4_OMA_DCF_BRAND_OPF2) {
+ compatible_brands.Append(ftyp->GetCompatibleBrands()[i]);
+ }
+ }
+
+ // create a replacement for the major brand
+ top_level.AddChild(new AP4_FtypAtom(ftyp->GetMajorBrand(),
+ ftyp->GetMinorVersion(),
+ &compatible_brands[0],
+ compatible_brands.ItemCount()), 0);
+ delete ftyp;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_StandardDecryptingProcessor:CreateTrackHandler
++---------------------------------------------------------------------*/
+AP4_Processor::TrackHandler*
+AP4_StandardDecryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
+{
+ // find the stsd atom
+ AP4_StsdAtom* stsd = AP4_DYNAMIC_CAST(AP4_StsdAtom, trak->FindChild("mdia/minf/stbl/stsd"));
+
+ // avoid tracks with no stsd atom (should not happen)
+ if (stsd == NULL) return NULL;
+
+ // we only look at the first sample description
+ AP4_SampleDescription* desc = stsd->GetSampleDescription(0);
+ AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
+ if (desc == NULL || entry == NULL) return NULL;
+ if (desc->GetType() == AP4_SampleDescription::TYPE_PROTECTED) {
+ // create a handler for this track
+ AP4_ProtectedSampleDescription* protected_desc =
+ static_cast<AP4_ProtectedSampleDescription*>(desc);
+ if (protected_desc->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_OMA) {
+ const AP4_UI08* key = m_KeyMap.GetKey(trak->GetId());
+ if (key) {
+ AP4_OmaDcfTrackDecrypter* handler = NULL;
+ AP4_Result result = AP4_OmaDcfTrackDecrypter::Create(key,
+ AP4_CIPHER_BLOCK_SIZE,
+ protected_desc,
+ entry,
+ m_BlockCipherFactory,
+ handler);
+ if (AP4_FAILED(result)) return NULL;
+ return handler;
+ }
+ } else if (protected_desc->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_IAEC) {
+ const AP4_UI08* key = m_KeyMap.GetKey(trak->GetId());
+ if (key) {
+ AP4_IsmaTrackDecrypter* handler = NULL;
+ AP4_Result result = AP4_IsmaTrackDecrypter::Create(key,
+ AP4_CIPHER_BLOCK_SIZE,
+ protected_desc,
+ entry,
+ m_BlockCipherFactory,
+ handler);
+ if (AP4_FAILED(result)) return NULL;
+ return handler;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::AP4_DecryptingStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DecryptingStream::Create(CipherMode mode,
+ AP4_ByteStream& encrypted_stream,
+ AP4_LargeSize cleartext_size,
+ const AP4_UI08* iv,
+ AP4_Size iv_size,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream)
+{
+ // default return value
+ stream = NULL;
+
+ // default cipher settings
+ if (block_cipher_factory == NULL) {
+ block_cipher_factory = &AP4_DefaultBlockCipherFactory::Instance;
+ }
+
+ // get the encrypted size (includes padding)
+ AP4_LargeSize encrypted_size = 0;
+ AP4_Result result = encrypted_stream.GetSize(encrypted_size);
+ if (AP4_FAILED(result)) return result;
+
+ // check IV
+ if (iv == NULL || iv_size != 16) return AP4_ERROR_INVALID_PARAMETERS;
+
+ // check that the encrypted size is consistent with the cipher mode
+ if (mode == CIPHER_MODE_CBC) {
+ // we need at least 32 bytes of data+padding
+ // we also need a multiple of the block size
+ if (encrypted_size < 32 || ((encrypted_size % 16) != 0)) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+ }
+
+ // create the stream cipher
+ AP4_BlockCipher* block_cipher;
+ result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
+ (mode == CIPHER_MODE_CTR ?
+ AP4_BlockCipher::ENCRYPT :
+ AP4_BlockCipher::DECRYPT),
+ key, key_size, block_cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // keep a reference to the source stream
+ encrypted_stream.AddReference();
+
+ // create the stream
+ AP4_DecryptingStream* dec_stream = new AP4_DecryptingStream();
+ stream = dec_stream;
+ dec_stream->m_Mode = mode;
+ dec_stream->m_CleartextSize = cleartext_size;
+ dec_stream->m_CleartextPosition = 0;
+ dec_stream->m_EncryptedSize = encrypted_size;
+ dec_stream->m_EncryptedStream = &encrypted_stream;
+ dec_stream->m_EncryptedPosition = 0;
+ dec_stream->m_BufferFullness = 0;
+ dec_stream->m_BufferOffset = 0;
+ dec_stream->m_ReferenceCount = 1;
+
+ // create the cipher according to the mode
+ switch (mode) {
+ case CIPHER_MODE_CBC:
+ dec_stream->m_StreamCipher = new AP4_CbcStreamCipher(block_cipher,
+ AP4_StreamCipher::DECRYPT);
+ break;
+ case CIPHER_MODE_CTR:
+ dec_stream->m_StreamCipher = new AP4_CtrStreamCipher(block_cipher,
+ NULL,
+ AP4_CIPHER_BLOCK_SIZE);
+ break;
+ default:
+ // should never occur
+ AP4_ASSERT(0);
+ }
+
+ // set the IV
+ dec_stream->m_StreamCipher->SetIV(iv);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::~AP4_DecryptingStream
++---------------------------------------------------------------------*/
+AP4_DecryptingStream::~AP4_DecryptingStream()
+{
+ delete m_StreamCipher;
+ m_EncryptedStream->Release();
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::AddReference
++---------------------------------------------------------------------*/
+void
+AP4_DecryptingStream::AddReference()
+{
+ ++m_ReferenceCount;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::Release
++---------------------------------------------------------------------*/
+void
+AP4_DecryptingStream::Release()
+{
+ if (--m_ReferenceCount == 0) delete this;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::ReadPartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DecryptingStream::ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read)
+{
+ bytes_read = 0;
+
+ // never read more than what's available
+ AP4_LargeSize available = m_CleartextSize-m_CleartextPosition;
+ if (available < bytes_to_read) {
+ if (available == 0) {
+ return AP4_ERROR_EOS;
+ }
+ bytes_to_read = (AP4_Size)available;
+ }
+
+ if (m_BufferFullness) {
+ // we have some leftovers
+ AP4_Size chunk = bytes_to_read;
+ if (chunk > m_BufferFullness) chunk = m_BufferFullness;
+ AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
+ buffer = (char*)buffer+chunk;
+ m_CleartextPosition += chunk;
+ available -= chunk;
+ bytes_to_read -= chunk;
+ m_BufferFullness -= chunk;
+ m_BufferOffset += chunk;
+ bytes_read += chunk;
+ }
+
+ // seek to the right place in the input
+ m_EncryptedStream->Seek(m_EncryptedPosition);
+
+ while (bytes_to_read) {
+ // read from the source
+ AP4_UI08 encrypted[16];
+ AP4_Size encrypted_read = 0;
+ AP4_Result result = m_EncryptedStream->ReadPartial(encrypted, 16, encrypted_read);
+ if (result == AP4_ERROR_EOS) {
+ if (bytes_read == 0) {
+ return AP4_ERROR_EOS;
+ } else {
+ return AP4_SUCCESS;
+ }
+ } else if (result != AP4_SUCCESS) {
+ return result;
+ } else {
+ m_EncryptedPosition += encrypted_read;
+ }
+ bool is_last_buffer = (m_EncryptedPosition >= m_EncryptedSize);
+ AP4_Size buffer_size = 16;
+ result = m_StreamCipher->ProcessBuffer(encrypted,
+ encrypted_read,
+ m_Buffer,
+ &buffer_size,
+ is_last_buffer);
+ m_BufferOffset = 0;
+ m_BufferFullness = buffer_size;
+
+ AP4_Size chunk = bytes_to_read;
+ if (chunk > m_BufferFullness) chunk = m_BufferFullness;
+ AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
+ buffer = (char*)buffer+chunk;
+ m_CleartextPosition += chunk;
+ available -= chunk;
+ bytes_to_read -= chunk;
+ m_BufferFullness -= chunk;
+ m_BufferOffset += chunk;
+ bytes_read += chunk;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::WritePartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DecryptingStream::WritePartial(const void* /* buffer */,
+ AP4_Size /* bytes_to_write */,
+ AP4_Size& /* bytes_written */)
+{
+ return AP4_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::Seek
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DecryptingStream::Seek(AP4_Position position)
+{
+ AP4_Cardinal preroll = 0;
+
+ // check bounds
+ if (position > m_CleartextSize) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+
+ // try to put the stream cipher at the right offset
+ AP4_CHECK(m_StreamCipher->SetStreamOffset(position, &preroll));
+
+ // seek in the source stream
+ AP4_CHECK(m_EncryptedStream->Seek(position-preroll));
+
+ // if we need to, process the preroll bytes
+ if (preroll > 0) {
+ AP4_Size out_size = 0;
+ AP4_UI08 buffer[2*AP4_CIPHER_BLOCK_SIZE]; // bigger than preroll
+ AP4_CHECK(m_EncryptedStream->Read(buffer, preroll));
+ AP4_CHECK(m_StreamCipher->ProcessBuffer(buffer, preroll, buffer, &out_size));
+ AP4_ASSERT(out_size == 0); // we're just feeding prerolled bytes,
+ // there can be no output
+ }
+
+ // update the counters
+ m_CleartextPosition = position;
+ m_EncryptedPosition = position;
+ m_BufferFullness = 0;
+ m_BufferOffset = 0;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::Tell
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DecryptingStream::Tell(AP4_Position& position)
+{
+ position = m_CleartextPosition;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream::GetSize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DecryptingStream::GetSize(AP4_LargeSize& size)
+{
+ size = m_CleartextSize;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::AP4_EncryptingStream
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_EncryptingStream::Create(CipherMode mode,
+ AP4_ByteStream& cleartext_stream,
+ const AP4_UI08* iv,
+ AP4_Size iv_size,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ bool prepend_iv,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream)
+{
+ // default return value
+ stream = NULL;
+
+ // get the cleartext size
+ AP4_LargeSize cleartext_size = 0;
+ AP4_Result result = cleartext_stream.GetSize(cleartext_size);
+ if (AP4_FAILED(result)) return result;
+
+ // check IV
+ if (iv == NULL || iv_size != 16) return AP4_ERROR_INVALID_PARAMETERS;
+
+ // compute the encrypted size
+ AP4_LargeSize encrypted_size = cleartext_size;
+ if (mode == CIPHER_MODE_CBC) {
+ encrypted_size += (16-(cleartext_size%16)); // with padding
+ }
+
+ // create the stream cipher
+ AP4_BlockCipher* block_cipher;
+ result = block_cipher_factory->Create(AP4_BlockCipher::AES_128,
+ AP4_BlockCipher::ENCRYPT,
+ key, key_size, block_cipher);
+ if (AP4_FAILED(result)) return result;
+
+ // keep a reference to the source stream
+ cleartext_stream.AddReference();
+
+ // create the stream
+ AP4_EncryptingStream* enc_stream = new AP4_EncryptingStream();
+ stream = enc_stream;
+ enc_stream->m_Mode = mode;
+ enc_stream->m_CleartextStream = &cleartext_stream;
+ enc_stream->m_CleartextSize = cleartext_size;
+ enc_stream->m_CleartextPosition = 0;
+ enc_stream->m_EncryptedSize = encrypted_size;
+ enc_stream->m_EncryptedPosition = 0;
+ enc_stream->m_BufferFullness = 0;
+ enc_stream->m_BufferOffset = 0;
+ enc_stream->m_ReferenceCount = 1;
+
+ // deal with the prepended IV if required
+ if (prepend_iv) {
+ enc_stream->m_EncryptedSize += 16;
+ enc_stream->m_BufferFullness = 16;
+ AP4_CopyMemory(enc_stream->m_Buffer, iv, 16);
+ }
+
+ // create the cipher according to the mode
+ switch (mode) {
+ case CIPHER_MODE_CBC:
+ enc_stream->m_StreamCipher = new AP4_CbcStreamCipher(block_cipher,
+ AP4_StreamCipher::ENCRYPT);
+ break;
+ case CIPHER_MODE_CTR:
+ enc_stream->m_StreamCipher = new AP4_CtrStreamCipher(block_cipher,
+ NULL,
+ AP4_CIPHER_BLOCK_SIZE);
+ break;
+ default:
+ // should never occur
+ AP4_ASSERT(0);
+ }
+
+ // set the IV
+ enc_stream->m_StreamCipher->SetIV(iv);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::~AP4_EncryptingStream
++---------------------------------------------------------------------*/
+AP4_EncryptingStream::~AP4_EncryptingStream()
+{
+ delete m_StreamCipher;
+ m_CleartextStream->Release();
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::AddReference
++---------------------------------------------------------------------*/
+void
+AP4_EncryptingStream::AddReference()
+{
+ ++m_ReferenceCount;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::Release
++---------------------------------------------------------------------*/
+void
+AP4_EncryptingStream::Release()
+{
+ if (--m_ReferenceCount == 0) delete this;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::ReadPartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_EncryptingStream::ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read)
+{
+ bytes_read = 0;
+
+ // never read more than what's available
+ AP4_LargeSize available = m_EncryptedSize-m_EncryptedPosition;
+ if (available < bytes_to_read) {
+ if (available == 0) return AP4_ERROR_EOS;
+ bytes_to_read = (AP4_Size)available;
+ }
+
+ if (m_BufferFullness) {
+ // we have some leftovers
+ AP4_Size chunk = bytes_to_read;
+ if (chunk > m_BufferFullness) chunk = m_BufferFullness;
+ AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
+ buffer = (char*)buffer+chunk;
+ m_EncryptedPosition += chunk;
+ available -= chunk;
+ bytes_to_read -= chunk;
+ m_BufferFullness -= chunk;
+ m_BufferOffset += chunk;
+ bytes_read += chunk;
+ }
+
+ // seek to the right place in the input
+ m_CleartextStream->Seek(m_CleartextPosition);
+
+ while (bytes_to_read) {
+ // read from the source
+ AP4_UI08 cleartext[16];
+ AP4_Size cleartext_read = 0;
+ AP4_Result result = m_CleartextStream->ReadPartial(cleartext, 16, cleartext_read);
+ if (result == AP4_ERROR_EOS) {
+ if (bytes_read == 0) {
+ return AP4_ERROR_EOS;
+ } else {
+ return AP4_SUCCESS;
+ }
+ } else if (result != AP4_SUCCESS) {
+ return result;
+ } else {
+ m_CleartextPosition += cleartext_read;
+ }
+ bool is_last_buffer = (m_CleartextPosition >= m_CleartextSize);
+ AP4_Size buffer_size = 32; // enough for one block plus one block padding
+ result = m_StreamCipher->ProcessBuffer(cleartext,
+ cleartext_read,
+ m_Buffer,
+ &buffer_size,
+ is_last_buffer);
+ m_BufferOffset = 0;
+ m_BufferFullness = buffer_size;
+
+ AP4_Size chunk = bytes_to_read;
+ if (chunk > m_BufferFullness) chunk = m_BufferFullness;
+ if (chunk) {
+ AP4_CopyMemory(buffer, &m_Buffer[m_BufferOffset], chunk);
+ buffer = (char*)buffer+chunk;
+ m_EncryptedPosition += chunk;
+ available -= chunk;
+ bytes_to_read -= chunk;
+ m_BufferFullness -= chunk;
+ m_BufferOffset += chunk;
+ bytes_read += chunk;
+ }
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::WritePartial
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_EncryptingStream::WritePartial(const void* /* buffer */,
+ AP4_Size /* bytes_to_write */,
+ AP4_Size& /* bytes_written */)
+{
+ return AP4_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::Seek
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_EncryptingStream::Seek(AP4_Position position)
+{
+ if (position == m_EncryptedPosition) {
+ return AP4_SUCCESS;
+ } else {
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::Tell
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_EncryptingStream::Tell(AP4_Position& position)
+{
+ position = m_EncryptedPosition;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream::GetSize
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_EncryptingStream::GetSize(AP4_LargeSize& size)
+{
+ size = m_EncryptedSize;
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DefaultBlockCipherFactory::Instance
++---------------------------------------------------------------------*/
+AP4_DefaultBlockCipherFactory AP4_DefaultBlockCipherFactory::Instance;
+
+/*----------------------------------------------------------------------
+| AP4_DefaultBlockCipherFactory
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DefaultBlockCipherFactory::Create(AP4_BlockCipher::CipherType type,
+ AP4_BlockCipher::CipherDirection direction,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipher*& cipher)
+{
+ // setup default return vaule
+ cipher = NULL;
+
+ switch (type) {
+ case AP4_BlockCipher::AES_128:
+ // check cipher parameters
+ if (key == NULL || key_size != AP4_AES_BLOCK_SIZE) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+
+ // create the cipher
+ cipher = new AP4_AesBlockCipher(key, direction);
+ return AP4_SUCCESS;
+
+ default:
+ // not supported
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.h
index 1979193ad..228188442 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Protection.h
@@ -1,479 +1,480 @@
-/*****************************************************************
-|
-| AP4 - Protected Streams support
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-#ifndef _AP4_PROTECTION_H_
-#define _AP4_PROTECTION_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4SampleEntry.h"
-#include "Ap4Atom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4SampleDescription.h"
-#include "Ap4Processor.h"
-
-/*----------------------------------------------------------------------
-| classes
-+---------------------------------------------------------------------*/
-class AP4_StreamCipher;
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-// this is fixed for now
-const unsigned int AP4_PROTECTION_KEY_LENGTH = 16;
-
-const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_ITUNES = AP4_ATOM_TYPE('i','t','u','n');
-
-/*----------------------------------------------------------------------
-| AP4_EncaSampleEntry
-+---------------------------------------------------------------------*/
-class AP4_EncaSampleEntry : public AP4_AudioSampleEntry
-{
-public:
- // methods
- AP4_EncaSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory);
- AP4_EncaSampleEntry(AP4_UI32 type,
- AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory);
-
- // methods
- AP4_SampleDescription* ToSampleDescription();
-
- // this method is used as a factory by the ISMACryp classes
- // NOTE: this should be named ToSampleDescription, but C++ has a
- // problem with that because the base class does not have this
- // overloaded method, but has another other one by that name
- virtual AP4_SampleDescription* ToTargetSampleDescription(AP4_UI32 format);
-};
-
-/*----------------------------------------------------------------------
-| AP4_EncvSampleEntry
-+---------------------------------------------------------------------*/
-class AP4_EncvSampleEntry : public AP4_VisualSampleEntry
-{
-public:
- // constructors
- AP4_EncvSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory);
- AP4_EncvSampleEntry(AP4_UI32 type,
- AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory);
-
- // methods
- AP4_SampleDescription* ToSampleDescription();
-
- // this method is used as a factory by the ISMACryp classes
- // NOTE: this should be named ToSampleDescription, but C++ has a
- // problem with that because the base class does not have this
- // overloaded method, but has another other one by that name
- virtual AP4_SampleDescription* ToTargetSampleDescription(AP4_UI32 format);
-};
-
-/*----------------------------------------------------------------------
-| AP4_DrmsSampleEntry
-+---------------------------------------------------------------------*/
-class AP4_DrmsSampleEntry : public AP4_EncaSampleEntry
-{
-public:
- // methods
- AP4_DrmsSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory);
-};
-
-/*----------------------------------------------------------------------
-| AP4_DrmiSampleEntry
-+---------------------------------------------------------------------*/
-class AP4_DrmiSampleEntry : public AP4_EncvSampleEntry
-{
-public:
- // methods
- AP4_DrmiSampleEntry(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory);
-};
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionKeyMap
-+---------------------------------------------------------------------*/
-class AP4_ProtectionKeyMap
-{
-public:
- // constructors and destructor
- AP4_ProtectionKeyMap();
- ~AP4_ProtectionKeyMap();
-
- // methods
- AP4_Result SetKey(AP4_UI32 track_id, const AP4_UI08* key, const AP4_UI08* iv = NULL);
- AP4_Result SetKeys(const AP4_ProtectionKeyMap& key_map);
- AP4_Result GetKeyAndIv(AP4_UI32 track_id, const AP4_UI08*& key, const AP4_UI08*& iv);
- const AP4_UI08* GetKey(AP4_UI32 track_id) const;
-
-private:
- // types
- class KeyEntry {
- public:
- KeyEntry(AP4_UI32 track_id, const AP4_UI08* key, const AP4_UI08* iv = NULL);
- void SetKey(const AP4_UI08* key, const AP4_UI08* iv);
- AP4_Ordinal m_TrackId;
- AP4_UI08 m_Key[AP4_PROTECTION_KEY_LENGTH];
- AP4_UI08 m_IV[AP4_PROTECTION_KEY_LENGTH];
- };
-
- // methods
- KeyEntry* GetEntry(AP4_UI32 track_id) const;
-
- // members
- AP4_List<KeyEntry> m_KeyEntries;
-};
-
-/*----------------------------------------------------------------------
-| AP4_TrackPropertyMap
-+---------------------------------------------------------------------*/
-class AP4_TrackPropertyMap
-{
-public:
- // methods
- AP4_Result SetProperty(AP4_UI32 track_id, const char* name, const char* value);
- AP4_Result SetProperties(const AP4_TrackPropertyMap& properties);
- const char* GetProperty(AP4_UI32 track_id, const char* name);
- AP4_Result GetTextualHeaders(AP4_UI32 track_id, AP4_DataBuffer& buffer);
-
-
- // destructor
- virtual ~AP4_TrackPropertyMap();
-
-private:
- // types
- class Entry {
- public:
- Entry(AP4_UI32 track_id, const char* name, const char* value) :
- m_TrackId(track_id), m_Name(name), m_Value(value) {}
- AP4_UI32 m_TrackId;
- AP4_String m_Name;
- AP4_String m_Value;
- };
-
- // members
- AP4_List<Entry> m_Entries;
-};
-
-/*----------------------------------------------------------------------
-| AP4_ProtectionSchemeInfo
-+---------------------------------------------------------------------*/
-class AP4_ProtectionSchemeInfo
-{
-public:
- // constructors and destructor
- AP4_ProtectionSchemeInfo(AP4_ContainerAtom* schi);
- virtual ~AP4_ProtectionSchemeInfo();
-
- // accessors
- AP4_ContainerAtom* GetSchiAtom() { return m_SchiAtom; }
-
-protected:
- AP4_ContainerAtom* m_SchiAtom;
-};
-
-/*----------------------------------------------------------------------
-| AP4_ProtectedSampleDescription
-+---------------------------------------------------------------------*/
-class AP4_ProtectedSampleDescription : public AP4_SampleDescription
-{
-public:
- AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_ProtectedSampleDescription, AP4_SampleDescription)
-
- // constructor and destructor
- AP4_ProtectedSampleDescription(AP4_UI32 format,
- AP4_SampleDescription* original_sample_description,
- AP4_UI32 original_format,
- AP4_UI32 scheme_type,
- AP4_UI32 scheme_version,
- const char* scheme_uri,
- AP4_ContainerAtom* schi_atom, // will be cloned
- bool transfer_ownership_of_original=true);
- ~AP4_ProtectedSampleDescription();
-
- // accessors
- AP4_SampleDescription* GetOriginalSampleDescription() {
- return m_OriginalSampleDescription;
- }
- AP4_UI32 GetOriginalFormat() const { return m_OriginalFormat; }
- AP4_UI32 GetSchemeType() const { return m_SchemeType; }
- AP4_UI32 GetSchemeVersion() const { return m_SchemeVersion; }
- const AP4_String& GetSchemeUri() const { return m_SchemeUri; }
- AP4_ProtectionSchemeInfo* GetSchemeInfo() const {
- return m_SchemeInfo;
- }
-
- // implementation of abstract base class methods
- virtual AP4_Atom* ToAtom() const;
-
-private:
- // members
- AP4_SampleDescription* m_OriginalSampleDescription;
- bool m_OriginalSampleDescriptionIsOwned;
- AP4_UI32 m_OriginalFormat;
- AP4_UI32 m_SchemeType;
- AP4_UI32 m_SchemeVersion;
- AP4_String m_SchemeUri;
- AP4_ProtectionSchemeInfo* m_SchemeInfo;
-};
-
-/*----------------------------------------------------------------------
-| AP4_BlockCipher
-+---------------------------------------------------------------------*/
-class AP4_BlockCipher
-{
-public:
- // types
- typedef enum {
- ENCRYPT,
- DECRYPT
- } CipherDirection;
-
- typedef enum {
- AES_128
- } CipherType;
-
- // constructor and destructor
- virtual ~AP4_BlockCipher() {}
-
- // methods
- virtual AP4_Result ProcessBlock(const AP4_UI08* block_in, AP4_UI08* block_out) = 0;
-};
-
-/*----------------------------------------------------------------------
-| AP4_BlockCipherFactory
-+---------------------------------------------------------------------*/
-class AP4_BlockCipherFactory
-{
-public:
- // methods
- virtual ~AP4_BlockCipherFactory() {}
- virtual AP4_Result Create(AP4_BlockCipher::CipherType type,
- AP4_BlockCipher::CipherDirection direction,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipher*& cipher) = 0;
-};
-
-/*----------------------------------------------------------------------
-| AP4_DefaultBlockCipherFactory
-+---------------------------------------------------------------------*/
-class AP4_DefaultBlockCipherFactory : public AP4_BlockCipherFactory
-{
-public:
- // class variables
- static AP4_DefaultBlockCipherFactory Instance;
-
- // methods
- virtual AP4_Result Create(AP4_BlockCipher::CipherType type,
- AP4_BlockCipher::CipherDirection direction,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipher*& cipher);
-};
-
-/*----------------------------------------------------------------------
-| AP4_SampleDecrypter
-+---------------------------------------------------------------------*/
-class AP4_SampleDecrypter
-{
-public:
- /**
- * Create a sample decrypter given a protected sample description
- */
- static AP4_SampleDecrypter* Create(AP4_ProtectedSampleDescription* sample_description,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
-
- /**
- * Create a fragment sample decrypter given a protected sample description and a track fragment
- */
- static AP4_SampleDecrypter* Create(AP4_ProtectedSampleDescription* sample_description,
- AP4_ContainerAtom* traf,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
-
- // destructor
- virtual ~AP4_SampleDecrypter() {}
-
- // methods
- virtual AP4_Size GetDecryptedSampleSize(AP4_Sample& sample) { return sample.GetSize(); }
- virtual AP4_Result SetSampleIndex(AP4_Ordinal /*index*/) { return AP4_SUCCESS; }
- virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
- AP4_DataBuffer& data_out,
- const AP4_UI08* iv = NULL) = 0;
-};
-
-/*----------------------------------------------------------------------
-| AP4_StandardDecryptingProcessor
-+---------------------------------------------------------------------*/
-class AP4_StandardDecryptingProcessor : public AP4_Processor
-{
-public:
- // constructor
- AP4_StandardDecryptingProcessor(const AP4_ProtectionKeyMap* key_map = NULL,
- AP4_BlockCipherFactory* block_cipher_factory = NULL);
-
- // accessors
- AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
-
- // methods
- virtual AP4_Result Initialize(AP4_AtomParent& top_level,
- AP4_ByteStream& stream,
- ProgressListener* listener);
- virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
-
-private:
- // members
- AP4_BlockCipherFactory* m_BlockCipherFactory;
- AP4_ProtectionKeyMap m_KeyMap;
-};
-
-/*----------------------------------------------------------------------
-| AP4_DecryptingStream
-+---------------------------------------------------------------------*/
-class AP4_DecryptingStream : public AP4_ByteStream {
-public:
- typedef enum {
- CIPHER_MODE_CTR,
- CIPHER_MODE_CBC
- } CipherMode;
-
- static AP4_Result Create(CipherMode mode,
- AP4_ByteStream& encrypted_stream,
- AP4_LargeSize cleartext_size,
- const AP4_UI08* iv,
- AP4_Size iv_size,
- const AP4_UI08* key,
- AP4_Size key_size,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream);
-
- // AP4_ByteStream methods
- virtual AP4_Result ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read);
- virtual AP4_Result WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written);
- virtual AP4_Result Seek(AP4_Position position);
- virtual AP4_Result Tell(AP4_Position& position);
- virtual AP4_Result GetSize(AP4_LargeSize& size);
-
- // AP4_Referenceable methods
- virtual void AddReference();
- virtual void Release();
-
-private:
- // methods
- AP4_DecryptingStream() {} // private constructor, use the factory instead
- ~AP4_DecryptingStream();
-
- // members
- CipherMode m_Mode;
- AP4_LargeSize m_CleartextSize;
- AP4_Position m_CleartextPosition;
- AP4_ByteStream* m_EncryptedStream;
- AP4_LargeSize m_EncryptedSize;
- AP4_Position m_EncryptedPosition;
- AP4_StreamCipher* m_StreamCipher;
- AP4_UI08 m_Buffer[16];
- AP4_Size m_BufferFullness;
- AP4_Size m_BufferOffset;
- AP4_Cardinal m_ReferenceCount;
-};
-
-/*----------------------------------------------------------------------
-| AP4_EncryptingStream
-+---------------------------------------------------------------------*/
-class AP4_EncryptingStream : public AP4_ByteStream {
-public:
- typedef enum {
- CIPHER_MODE_CTR,
- CIPHER_MODE_CBC
- } CipherMode;
-
- static AP4_Result Create(CipherMode mode,
- AP4_ByteStream& cleartext_stream,
- const AP4_UI08* iv,
- AP4_Size iv_size,
- const AP4_UI08* key,
- AP4_Size key_size,
- bool prepend_iv,
- AP4_BlockCipherFactory* block_cipher_factory,
- AP4_ByteStream*& stream);
-
- // AP4_ByteStream methods
- virtual AP4_Result ReadPartial(void* buffer,
- AP4_Size bytes_to_read,
- AP4_Size& bytes_read);
- virtual AP4_Result WritePartial(const void* buffer,
- AP4_Size bytes_to_write,
- AP4_Size& bytes_written);
- virtual AP4_Result Seek(AP4_Position position);
- virtual AP4_Result Tell(AP4_Position& position);
- virtual AP4_Result GetSize(AP4_LargeSize& size);
-
- // AP4_Referenceable methods
- virtual void AddReference();
- virtual void Release();
-
-private:
- // methods
- AP4_EncryptingStream() {} // private constructor, use the factory instead
- ~AP4_EncryptingStream();
-
- // members
- CipherMode m_Mode;
- AP4_LargeSize m_CleartextSize;
- AP4_Position m_CleartextPosition;
- AP4_ByteStream* m_CleartextStream;
- AP4_LargeSize m_EncryptedSize;
- AP4_Position m_EncryptedPosition;
- AP4_StreamCipher* m_StreamCipher;
- AP4_UI08 m_Buffer[32]; // one cipher block plus one block padding
- AP4_Size m_BufferFullness;
- AP4_Size m_BufferOffset;
- AP4_Cardinal m_ReferenceCount;
-};
-
-
-#endif // _AP4_PROTECTION_H_
+/*****************************************************************
+|
+| AP4 - Protected Streams support
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+#ifndef _AP4_PROTECTION_H_
+#define _AP4_PROTECTION_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4SampleEntry.h"
+#include "Ap4Atom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4SampleDescription.h"
+#include "Ap4Processor.h"
+
+/*----------------------------------------------------------------------
+| classes
++---------------------------------------------------------------------*/
+class AP4_StreamCipher;
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+// this is fixed for now
+const unsigned int AP4_PROTECTION_KEY_LENGTH = 16;
+
+const AP4_UI32 AP4_PROTECTION_SCHEME_TYPE_ITUNES = AP4_ATOM_TYPE('i','t','u','n');
+
+/*----------------------------------------------------------------------
+| AP4_EncaSampleEntry
++---------------------------------------------------------------------*/
+class AP4_EncaSampleEntry : public AP4_AudioSampleEntry
+{
+public:
+ // methods
+ AP4_EncaSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory);
+ AP4_EncaSampleEntry(AP4_UI32 type,
+ AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory);
+
+ // methods
+ AP4_SampleDescription* ToSampleDescription();
+
+ // this method is used as a factory by the ISMACryp classes
+ // NOTE: this should be named ToSampleDescription, but C++ has a
+ // problem with that because the base class does not have this
+ // overloaded method, but has another other one by that name
+ virtual AP4_SampleDescription* ToTargetSampleDescription(AP4_UI32 format);
+};
+
+/*----------------------------------------------------------------------
+| AP4_EncvSampleEntry
++---------------------------------------------------------------------*/
+class AP4_EncvSampleEntry : public AP4_VisualSampleEntry
+{
+public:
+ // constructors
+ AP4_EncvSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory);
+ AP4_EncvSampleEntry(AP4_UI32 type,
+ AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory);
+
+ // methods
+ AP4_SampleDescription* ToSampleDescription();
+
+ // this method is used as a factory by the ISMACryp classes
+ // NOTE: this should be named ToSampleDescription, but C++ has a
+ // problem with that because the base class does not have this
+ // overloaded method, but has another other one by that name
+ virtual AP4_SampleDescription* ToTargetSampleDescription(AP4_UI32 format);
+};
+
+/*----------------------------------------------------------------------
+| AP4_DrmsSampleEntry
++---------------------------------------------------------------------*/
+class AP4_DrmsSampleEntry : public AP4_EncaSampleEntry
+{
+public:
+ // methods
+ AP4_DrmsSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory);
+};
+
+/*----------------------------------------------------------------------
+| AP4_DrmiSampleEntry
++---------------------------------------------------------------------*/
+class AP4_DrmiSampleEntry : public AP4_EncvSampleEntry
+{
+public:
+ // methods
+ AP4_DrmiSampleEntry(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory);
+};
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionKeyMap
++---------------------------------------------------------------------*/
+class AP4_ProtectionKeyMap
+{
+public:
+ // constructors and destructor
+ AP4_ProtectionKeyMap();
+ ~AP4_ProtectionKeyMap();
+
+ // methods
+ AP4_Result SetKey(AP4_UI32 track_id, const AP4_UI08* key, const AP4_UI08* iv = NULL);
+ AP4_Result SetKeys(const AP4_ProtectionKeyMap& key_map);
+ AP4_Result GetKeyAndIv(AP4_UI32 track_id, const AP4_UI08*& key, const AP4_UI08*& iv);
+ const AP4_UI08* GetKey(AP4_UI32 track_id) const;
+
+private:
+ // types
+ class KeyEntry {
+ public:
+ KeyEntry(AP4_UI32 track_id, const AP4_UI08* key, const AP4_UI08* iv = NULL);
+ void SetKey(const AP4_UI08* key, const AP4_UI08* iv);
+ AP4_Ordinal m_TrackId;
+ AP4_UI08 m_Key[AP4_PROTECTION_KEY_LENGTH];
+ AP4_UI08 m_IV[AP4_PROTECTION_KEY_LENGTH];
+ };
+
+ // methods
+ KeyEntry* GetEntry(AP4_UI32 track_id) const;
+
+ // members
+ AP4_List<KeyEntry> m_KeyEntries;
+};
+
+/*----------------------------------------------------------------------
+| AP4_TrackPropertyMap
++---------------------------------------------------------------------*/
+class AP4_TrackPropertyMap
+{
+public:
+ // methods
+ AP4_Result SetProperty(AP4_UI32 track_id, const char* name, const char* value);
+ AP4_Result SetProperties(const AP4_TrackPropertyMap& properties);
+ const char* GetProperty(AP4_UI32 track_id, const char* name);
+ AP4_Result GetTextualHeaders(AP4_UI32 track_id, AP4_DataBuffer& buffer);
+
+
+ // destructor
+ virtual ~AP4_TrackPropertyMap();
+
+private:
+ // types
+ class Entry {
+ public:
+ Entry(AP4_UI32 track_id, const char* name, const char* value) :
+ m_TrackId(track_id), m_Name(name), m_Value(value) {}
+ AP4_UI32 m_TrackId;
+ AP4_String m_Name;
+ AP4_String m_Value;
+ };
+
+ // members
+ AP4_List<Entry> m_Entries;
+};
+
+/*----------------------------------------------------------------------
+| AP4_ProtectionSchemeInfo
++---------------------------------------------------------------------*/
+class AP4_ProtectionSchemeInfo
+{
+public:
+ // constructors and destructor
+ AP4_ProtectionSchemeInfo(AP4_ContainerAtom* schi);
+ virtual ~AP4_ProtectionSchemeInfo();
+
+ // accessors
+ AP4_ContainerAtom* GetSchiAtom() { return m_SchiAtom; }
+
+protected:
+ AP4_ContainerAtom* m_SchiAtom;
+};
+
+/*----------------------------------------------------------------------
+| AP4_ProtectedSampleDescription
++---------------------------------------------------------------------*/
+class AP4_ProtectedSampleDescription : public AP4_SampleDescription
+{
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_ProtectedSampleDescription, AP4_SampleDescription)
+
+ // constructor and destructor
+ AP4_ProtectedSampleDescription(AP4_UI32 format,
+ AP4_SampleDescription* original_sample_description,
+ AP4_UI32 original_format,
+ AP4_UI32 scheme_type,
+ AP4_UI32 scheme_version,
+ const char* scheme_uri,
+ AP4_ContainerAtom* schi_atom, // will be cloned
+ bool transfer_ownership_of_original=true);
+ ~AP4_ProtectedSampleDescription();
+
+ // accessors
+ AP4_SampleDescription* GetOriginalSampleDescription() {
+ return m_OriginalSampleDescription;
+ }
+ AP4_UI32 GetOriginalFormat() const { return m_OriginalFormat; }
+ AP4_UI32 GetSchemeType() const { return m_SchemeType; }
+ AP4_UI32 GetSchemeVersion() const { return m_SchemeVersion; }
+ const AP4_String& GetSchemeUri() const { return m_SchemeUri; }
+ AP4_ProtectionSchemeInfo* GetSchemeInfo() const {
+ return m_SchemeInfo;
+ }
+
+ // implementation of abstract base class methods
+ virtual AP4_Atom* ToAtom() const;
+
+private:
+ // members
+ AP4_SampleDescription* m_OriginalSampleDescription;
+ bool m_OriginalSampleDescriptionIsOwned;
+ AP4_UI32 m_OriginalFormat;
+ AP4_UI32 m_SchemeType;
+ AP4_UI32 m_SchemeVersion;
+ AP4_String m_SchemeUri;
+ AP4_ProtectionSchemeInfo* m_SchemeInfo;
+};
+
+/*----------------------------------------------------------------------
+| AP4_BlockCipher
++---------------------------------------------------------------------*/
+class AP4_BlockCipher
+{
+public:
+ // types
+ typedef enum {
+ ENCRYPT,
+ DECRYPT
+ } CipherDirection;
+
+ typedef enum {
+ AES_128
+ } CipherType;
+
+ // constructor and destructor
+ virtual ~AP4_BlockCipher() {}
+
+ // methods
+ virtual AP4_Result ProcessBlock(const AP4_UI08* block_in, AP4_UI08* block_out) = 0;
+};
+
+/*----------------------------------------------------------------------
+| AP4_BlockCipherFactory
++---------------------------------------------------------------------*/
+class AP4_BlockCipherFactory
+{
+public:
+ // methods
+ virtual ~AP4_BlockCipherFactory() {}
+ virtual AP4_Result Create(AP4_BlockCipher::CipherType type,
+ AP4_BlockCipher::CipherDirection direction,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipher*& cipher) = 0;
+};
+
+/*----------------------------------------------------------------------
+| AP4_DefaultBlockCipherFactory
++---------------------------------------------------------------------*/
+class AP4_DefaultBlockCipherFactory : public AP4_BlockCipherFactory
+{
+public:
+ // class variables
+ static AP4_DefaultBlockCipherFactory Instance;
+
+ // methods
+ virtual AP4_Result Create(AP4_BlockCipher::CipherType type,
+ AP4_BlockCipher::CipherDirection direction,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipher*& cipher);
+};
+
+/*----------------------------------------------------------------------
+| AP4_SampleDecrypter
++---------------------------------------------------------------------*/
+class AP4_SampleDecrypter
+{
+public:
+ /**
+ * Create a sample decrypter given a protected sample description
+ */
+ static AP4_SampleDecrypter* Create(AP4_ProtectedSampleDescription* sample_description,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+
+ /**
+ * Create a fragment sample decrypter given a protected sample description and a track fragment
+ */
+ static AP4_SampleDecrypter* Create(AP4_ProtectedSampleDescription* sample_description,
+ AP4_ContainerAtom* traf,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+
+ // destructor
+ virtual ~AP4_SampleDecrypter() {}
+
+ // methods
+ virtual AP4_Size GetDecryptedSampleSize(AP4_Sample& sample) { return sample.GetSize(); }
+ virtual AP4_Result SetSampleIndex(AP4_Ordinal /*index*/) { return AP4_SUCCESS; }
+ virtual AP4_Result DecryptSampleData(AP4_DataBuffer& data_in,
+ AP4_DataBuffer& data_out,
+ const AP4_UI08* iv = NULL) = 0;
+};
+
+/*----------------------------------------------------------------------
+| AP4_StandardDecryptingProcessor
++---------------------------------------------------------------------*/
+class AP4_StandardDecryptingProcessor : public AP4_Processor
+{
+public:
+ // constructor
+ AP4_StandardDecryptingProcessor(const AP4_ProtectionKeyMap* key_map = NULL,
+ AP4_BlockCipherFactory* block_cipher_factory = NULL);
+
+ // accessors
+ AP4_ProtectionKeyMap& GetKeyMap() { return m_KeyMap; }
+
+ // methods
+ virtual AP4_Result Initialize(AP4_AtomParent& top_level,
+ AP4_ByteStream& stream,
+ ProgressListener* listener);
+ virtual AP4_Processor::TrackHandler* CreateTrackHandler(AP4_TrakAtom* trak);
+
+private:
+ // members
+ AP4_BlockCipherFactory* m_BlockCipherFactory;
+ AP4_ProtectionKeyMap m_KeyMap;
+};
+
+/*----------------------------------------------------------------------
+| AP4_DecryptingStream
++---------------------------------------------------------------------*/
+class AP4_DecryptingStream : public AP4_ByteStream
+{
+public:
+ typedef enum {
+ CIPHER_MODE_CTR,
+ CIPHER_MODE_CBC
+ } CipherMode;
+
+ static AP4_Result Create(CipherMode mode,
+ AP4_ByteStream& encrypted_stream,
+ AP4_LargeSize cleartext_size,
+ const AP4_UI08* iv,
+ AP4_Size iv_size,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream);
+
+ // AP4_ByteStream methods
+ virtual AP4_Result ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read);
+ virtual AP4_Result WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written);
+ virtual AP4_Result Seek(AP4_Position position);
+ virtual AP4_Result Tell(AP4_Position& position);
+ virtual AP4_Result GetSize(AP4_LargeSize& size);
+
+ // AP4_Referenceable methods
+ virtual void AddReference();
+ virtual void Release();
+
+private:
+ // methods
+ AP4_DecryptingStream() {} // private constructor, use the factory instead
+ ~AP4_DecryptingStream();
+
+ // members
+ CipherMode m_Mode;
+ AP4_LargeSize m_CleartextSize;
+ AP4_Position m_CleartextPosition;
+ AP4_ByteStream* m_EncryptedStream;
+ AP4_LargeSize m_EncryptedSize;
+ AP4_Position m_EncryptedPosition;
+ AP4_StreamCipher* m_StreamCipher;
+ AP4_UI08 m_Buffer[16];
+ AP4_Size m_BufferFullness;
+ AP4_Size m_BufferOffset;
+ AP4_Cardinal m_ReferenceCount;
+};
+
+/*----------------------------------------------------------------------
+| AP4_EncryptingStream
++---------------------------------------------------------------------*/
+class AP4_EncryptingStream : public AP4_ByteStream
+{
+public:
+ typedef enum {
+ CIPHER_MODE_CTR,
+ CIPHER_MODE_CBC
+ } CipherMode;
+
+ static AP4_Result Create(CipherMode mode,
+ AP4_ByteStream& cleartext_stream,
+ const AP4_UI08* iv,
+ AP4_Size iv_size,
+ const AP4_UI08* key,
+ AP4_Size key_size,
+ bool prepend_iv,
+ AP4_BlockCipherFactory* block_cipher_factory,
+ AP4_ByteStream*& stream);
+
+ // AP4_ByteStream methods
+ virtual AP4_Result ReadPartial(void* buffer,
+ AP4_Size bytes_to_read,
+ AP4_Size& bytes_read);
+ virtual AP4_Result WritePartial(const void* buffer,
+ AP4_Size bytes_to_write,
+ AP4_Size& bytes_written);
+ virtual AP4_Result Seek(AP4_Position position);
+ virtual AP4_Result Tell(AP4_Position& position);
+ virtual AP4_Result GetSize(AP4_LargeSize& size);
+
+ // AP4_Referenceable methods
+ virtual void AddReference();
+ virtual void Release();
+
+private:
+ // methods
+ AP4_EncryptingStream() {} // private constructor, use the factory instead
+ ~AP4_EncryptingStream();
+
+ // members
+ CipherMode m_Mode;
+ AP4_LargeSize m_CleartextSize;
+ AP4_Position m_CleartextPosition;
+ AP4_ByteStream* m_CleartextStream;
+ AP4_LargeSize m_EncryptedSize;
+ AP4_Position m_EncryptedPosition;
+ AP4_StreamCipher* m_StreamCipher;
+ AP4_UI08 m_Buffer[32]; // one cipher block plus one block padding
+ AP4_Size m_BufferFullness;
+ AP4_Size m_BufferOffset;
+ AP4_Cardinal m_ReferenceCount;
+};
+
+#endif // _AP4_PROTECTION_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Results.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Results.h
index 58afaef55..014012005 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Results.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Results.h
@@ -1,76 +1,76 @@
-/*****************************************************************
-|
-| AP4 - Result Codes
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_RESULTS_H_
-#define _AP4_RESULTS_H_
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const int AP4_SUCCESS = 0;
-const int AP4_FAILURE = -1;
-const int AP4_ERROR_OUT_OF_MEMORY = -2;
-const int AP4_ERROR_INVALID_PARAMETERS = -3;
-const int AP4_ERROR_NO_SUCH_FILE = -4;
-const int AP4_ERROR_PERMISSION_DENIED = -5;
-const int AP4_ERROR_CANNOT_OPEN_FILE = -6;
-const int AP4_ERROR_EOS = -7;
-const int AP4_ERROR_WRITE_FAILED = -8;
-const int AP4_ERROR_READ_FAILED = -9;
-const int AP4_ERROR_INVALID_FORMAT = -10;
-const int AP4_ERROR_NO_SUCH_ITEM = -11;
-const int AP4_ERROR_OUT_OF_RANGE = -12;
-const int AP4_ERROR_INTERNAL = -13;
-const int AP4_ERROR_INVALID_STATE = -14;
-const int AP4_ERROR_LIST_EMPTY = -15;
-const int AP4_ERROR_LIST_OPERATION_ABORTED = -16;
-const int AP4_ERROR_INVALID_RTP_CONSTRUCTOR_TYPE = -17;
-const int AP4_ERROR_NOT_SUPPORTED = -18;
-const int AP4_ERROR_INVALID_TRACK_TYPE = -19;
-const int AP4_ERROR_INVALID_RTP_PACKET_EXTRA_DATA = -20;
-const int AP4_ERROR_BUFFER_TOO_SMALL = -21;
-const int AP4_ERROR_NOT_ENOUGH_DATA = -22;
-const int AP4_ERROR_NOT_ENOUGH_SPACE = -23;
-
-/*----------------------------------------------------------------------
-| utility functions
-+---------------------------------------------------------------------*/
-const char* AP4_ResultText(int result);
-
-/*----------------------------------------------------------------------
-| macros
-+---------------------------------------------------------------------*/
-#define AP4_FAILED(result) ((result) != AP4_SUCCESS)
-#define AP4_SUCCEEDED(result) ((result) == AP4_SUCCESS)
-
-#define AP4_CHECK(_x) do { \
- AP4_Result _result = (_x); \
- if (AP4_FAILED(_result)) return _result; \
-} while(0)
-
-#endif // _AP4_RESULTS_H_
+/*****************************************************************
+|
+| AP4 - Result Codes
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_RESULTS_H_
+#define _AP4_RESULTS_H_
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const int AP4_SUCCESS = 0;
+const int AP4_FAILURE = -1;
+const int AP4_ERROR_OUT_OF_MEMORY = -2;
+const int AP4_ERROR_INVALID_PARAMETERS = -3;
+const int AP4_ERROR_NO_SUCH_FILE = -4;
+const int AP4_ERROR_PERMISSION_DENIED = -5;
+const int AP4_ERROR_CANNOT_OPEN_FILE = -6;
+const int AP4_ERROR_EOS = -7;
+const int AP4_ERROR_WRITE_FAILED = -8;
+const int AP4_ERROR_READ_FAILED = -9;
+const int AP4_ERROR_INVALID_FORMAT = -10;
+const int AP4_ERROR_NO_SUCH_ITEM = -11;
+const int AP4_ERROR_OUT_OF_RANGE = -12;
+const int AP4_ERROR_INTERNAL = -13;
+const int AP4_ERROR_INVALID_STATE = -14;
+const int AP4_ERROR_LIST_EMPTY = -15;
+const int AP4_ERROR_LIST_OPERATION_ABORTED = -16;
+const int AP4_ERROR_INVALID_RTP_CONSTRUCTOR_TYPE = -17;
+const int AP4_ERROR_NOT_SUPPORTED = -18;
+const int AP4_ERROR_INVALID_TRACK_TYPE = -19;
+const int AP4_ERROR_INVALID_RTP_PACKET_EXTRA_DATA = -20;
+const int AP4_ERROR_BUFFER_TOO_SMALL = -21;
+const int AP4_ERROR_NOT_ENOUGH_DATA = -22;
+const int AP4_ERROR_NOT_ENOUGH_SPACE = -23;
+
+/*----------------------------------------------------------------------
+| utility functions
++---------------------------------------------------------------------*/
+const char* AP4_ResultText(int result);
+
+/*----------------------------------------------------------------------
+| macros
++---------------------------------------------------------------------*/
+#define AP4_FAILED(result) ((result) != AP4_SUCCESS)
+#define AP4_SUCCEEDED(result) ((result) == AP4_SUCCESS)
+
+#define AP4_CHECK(_x) do { \
+ AP4_Result _result = (_x); \
+ if (AP4_FAILED(_result)) return _result; \
+} while(0)
+
+#endif // _AP4_RESULTS_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.cpp
index 060084044..0ef187123 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.cpp
@@ -173,3 +173,20 @@ AP4_Sample::SetDataStream(AP4_ByteStream& stream)
m_DataStream = &stream;
AP4_ADD_REFERENCE(m_DataStream);
}
+
+/*----------------------------------------------------------------------
+| AP4_Sample::Reset
++---------------------------------------------------------------------*/
+void
+AP4_Sample::Reset()
+{
+ AP4_RELEASE(m_DataStream);
+
+ m_Offset = 0;
+ m_Size = 0;
+ m_Duration = 0;
+ m_DescriptionIndex = 0;
+ m_Dts = 0;
+ m_CtsDelta = 0;
+ m_IsSync = false;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.h
index ba5a0235f..01d5b3c9f 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Sample.h
@@ -1,168 +1,173 @@
-/*****************************************************************
-|
-| AP4 - Sample Objects
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_SAMPLE_H_
-#define _AP4_SAMPLE_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-
-/*----------------------------------------------------------------------
-| class references
-+---------------------------------------------------------------------*/
-class AP4_ByteStream;
-class AP4_DataBuffer;
-
-/*----------------------------------------------------------------------
-| AP4_Sample DO NOT DERIVE FROM THIS CLASS
-+---------------------------------------------------------------------*/
-class AP4_Sample
-{
-public:
- /**
- * Default constructor
- */
- AP4_Sample();
-
- /**
- * Copy constructor
- */
- AP4_Sample(const AP4_Sample& other);
-
- /**
- * Construct an AP4_Sample referencing a data stream
- *
- * @param data_stream The byte stream that contains the sample data.
- * The sample object added to the track will keep a reference to that byte
- * stream
- * @param offset Position of the first byte of sample data within the stream
- * @param size Size in bytes of the sample data
- * @param description_index Index of the sample description that applies to
- * this sample
- * @param dts Decoding timestamp of the sample
- * @param cts_delta Difference between the CTS (composition/display timestamp) and the
- * DTS (decoding timestamp), in the timescale of the media.
- * @param sync_flag Boolean flag indicating whether this is a sync sample
- * or not
- */
- AP4_Sample(AP4_ByteStream& data_stream,
- AP4_Position offset,
- AP4_Size size,
- AP4_UI32 duration,
- AP4_Ordinal description_index,
- AP4_UI64 dts,
- AP4_UI32 cts_delta,
- bool sync_flag);
-
- ~AP4_Sample(); // not virtual on purpose: do not derive from it
-
- // operators
- AP4_Sample& operator=(const AP4_Sample& other);
-
- // methods
- AP4_Result ReadData(AP4_DataBuffer& data);
- AP4_Result ReadData(AP4_DataBuffer& data,
- AP4_Size size,
- AP4_Size offset = 0);
-
- // sample properties accessors
- AP4_ByteStream* GetDataStream();
- void SetDataStream(AP4_ByteStream& stream);
- AP4_Position GetOffset() const { return m_Offset; }
- void SetOffset(AP4_Position offset) { m_Offset = offset; }
- AP4_Size GetSize() { return m_Size; }
- void SetSize(AP4_Size size) { m_Size = size; }
- AP4_Ordinal GetDescriptionIndex() const { return m_DescriptionIndex; }
- void SetDescriptionIndex(AP4_Ordinal index) { m_DescriptionIndex = index; }
-
- /**
- * Get the DTS (Decoding Time Stamp) of the sample in the timescale of the media
- */
- AP4_UI64 GetDts() const { return m_Dts; }
-
- /**
- * Set the DTS (Decoding Time Stamp) of the sample in the timescale of the media
- */
- void SetDts(AP4_UI64 dts) { m_Dts = dts; }
-
- /**
- * Get the CTS (Composition Time Stamp) of the sample in the timescale of the media
- */
- AP4_UI64 GetCts() const { return m_Dts+m_CtsDelta; }
-
- /**
- * Set the CTS (Composition Time Stamp) of the sample in the timescale of the media
- */
- void SetCts(AP4_UI64 cts) { m_CtsDelta = (cts > m_Dts) ? (AP4_UI32)(cts-m_Dts) : 0; }
-
- /**
- * Get the CTS Delta (difference between the CTS (Composition Time Stamp) and DTS (Decoding Time Stamp)
- * of the sample in the timescale of the media.
- */
- AP4_UI32 GetCtsDelta() const { return m_CtsDelta; }
-
- /**
- * Set the CTS Delta (difference between the CTS (Composition Time Stamp) and DTS (Decoding Time Stamp)
- * of the sample in the timescale of the media.
- */
- void SetCtsDelta(AP4_UI32 delta) { m_CtsDelta = (AP4_SI32)delta; }
-
- /**
- * Get the duration of the sample in the timescale of the media
- */
- AP4_UI32 GetDuration() const { return m_Duration; }
-
- /**
- * Set the duration of the sample in the timescale of the media
- */
- void SetDuration(AP4_UI32 duration) { m_Duration = duration; }
-
- /**
- * Return whether the sample is a sync (random-access point) sample or not.
- */
- bool IsSync() const { return m_IsSync; }
-
- /**
- * Set whether the sample is a sync (random-access point) sample or not.
- */
- void SetSync(bool is_sync) { m_IsSync = is_sync; }
-
-protected:
- AP4_ByteStream* m_DataStream;
- AP4_Position m_Offset;
- AP4_Size m_Size;
- AP4_UI32 m_Duration;
- AP4_Ordinal m_DescriptionIndex;
- AP4_UI64 m_Dts;
- AP4_SI32 m_CtsDelta; // make this a signed value, because quicktime can use negative offsets
- bool m_IsSync;
-};
-
-#endif // _AP4_SAMPLE_H_
+/*****************************************************************
+|
+| AP4 - Sample Objects
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_SAMPLE_H_
+#define _AP4_SAMPLE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+
+/*----------------------------------------------------------------------
+| class references
++---------------------------------------------------------------------*/
+class AP4_ByteStream;
+class AP4_DataBuffer;
+
+/*----------------------------------------------------------------------
+| AP4_Sample DO NOT DERIVE FROM THIS CLASS
++---------------------------------------------------------------------*/
+class AP4_Sample
+{
+public:
+ /**
+ * Default constructor
+ */
+ AP4_Sample();
+
+ /**
+ * Copy constructor
+ */
+ AP4_Sample(const AP4_Sample& other);
+
+ /**
+ * Construct an AP4_Sample referencing a data stream
+ *
+ * @param data_stream The byte stream that contains the sample data.
+ * The sample object added to the track will keep a reference to that byte
+ * stream
+ * @param offset Position of the first byte of sample data within the stream
+ * @param size Size in bytes of the sample data
+ * @param description_index Index of the sample description that applies to
+ * this sample
+ * @param dts Decoding timestamp of the sample
+ * @param cts_delta Difference between the CTS (composition/display timestamp) and the
+ * DTS (decoding timestamp), in the timescale of the media.
+ * @param sync_flag Boolean flag indicating whether this is a sync sample
+ * or not
+ */
+ AP4_Sample(AP4_ByteStream& data_stream,
+ AP4_Position offset,
+ AP4_Size size,
+ AP4_UI32 duration,
+ AP4_Ordinal description_index,
+ AP4_UI64 dts,
+ AP4_UI32 cts_delta,
+ bool sync_flag);
+
+ ~AP4_Sample(); // not virtual on purpose: do not derive from it
+
+ // operators
+ AP4_Sample& operator=(const AP4_Sample& other);
+
+ // methods
+ AP4_Result ReadData(AP4_DataBuffer& data);
+ AP4_Result ReadData(AP4_DataBuffer& data,
+ AP4_Size size,
+ AP4_Size offset = 0);
+
+ // sample properties accessors
+ AP4_ByteStream* GetDataStream();
+ void SetDataStream(AP4_ByteStream& stream);
+ AP4_Position GetOffset() const { return m_Offset; }
+ void SetOffset(AP4_Position offset) { m_Offset = offset; }
+ AP4_Size GetSize() { return m_Size; }
+ void SetSize(AP4_Size size) { m_Size = size; }
+ AP4_Ordinal GetDescriptionIndex() const { return m_DescriptionIndex; }
+ void SetDescriptionIndex(AP4_Ordinal index) { m_DescriptionIndex = index; }
+
+ /**
+ * Get the DTS (Decoding Time Stamp) of the sample in the timescale of the media
+ */
+ AP4_UI64 GetDts() const { return m_Dts; }
+
+ /**
+ * Set the DTS (Decoding Time Stamp) of the sample in the timescale of the media
+ */
+ void SetDts(AP4_UI64 dts) { m_Dts = dts; }
+
+ /**
+ * Get the CTS (Composition Time Stamp) of the sample in the timescale of the media
+ */
+ AP4_UI64 GetCts() const { return m_Dts+m_CtsDelta; }
+
+ /**
+ * Set the CTS (Composition Time Stamp) of the sample in the timescale of the media
+ */
+ void SetCts(AP4_UI64 cts) { m_CtsDelta = (cts > m_Dts) ? (AP4_UI32)(cts-m_Dts) : 0; }
+
+ /**
+ * Get the CTS Delta (difference between the CTS (Composition Time Stamp) and DTS (Decoding Time Stamp)
+ * of the sample in the timescale of the media.
+ */
+ AP4_UI32 GetCtsDelta() const { return m_CtsDelta; }
+
+ /**
+ * Set the CTS Delta (difference between the CTS (Composition Time Stamp) and DTS (Decoding Time Stamp)
+ * of the sample in the timescale of the media.
+ */
+ void SetCtsDelta(AP4_UI32 delta) { m_CtsDelta = (AP4_SI32)delta; }
+
+ /**
+ * Get the duration of the sample in the timescale of the media
+ */
+ AP4_UI32 GetDuration() const { return m_Duration; }
+
+ /**
+ * Set the duration of the sample in the timescale of the media
+ */
+ void SetDuration(AP4_UI32 duration) { m_Duration = duration; }
+
+ /**
+ * Return whether the sample is a sync (random-access point) sample or not.
+ */
+ bool IsSync() const { return m_IsSync; }
+
+ /**
+ * Set whether the sample is a sync (random-access point) sample or not.
+ */
+ void SetSync(bool is_sync) { m_IsSync = is_sync; }
+
+ /**
+ * Resets the sample: will also release any data stream reference
+ */
+ void Reset();
+
+protected:
+ AP4_ByteStream* m_DataStream;
+ AP4_Position m_Offset;
+ AP4_Size m_Size;
+ AP4_UI32 m_Duration;
+ AP4_Ordinal m_DescriptionIndex;
+ AP4_UI64 m_Dts;
+ AP4_SI32 m_CtsDelta; // make this a signed value, because quicktime can use negative offsets
+ bool m_IsSync;
+};
+
+#endif // _AP4_SAMPLE_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.cpp
index e301d0cf4..535acc686 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.cpp
@@ -1,618 +1,618 @@
-/*****************************************************************
-|
-| AP4 - Sample Description Objects
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4SampleDescription.h"
-#include "Ap4EsDescriptor.h"
-#include "Ap4SLConfigDescriptor.h"
-#include "Ap4SampleEntry.h"
-#include "Ap4AvccAtom.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_SampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_UnknownSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_AudioSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_VideoSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_GenericAudioSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_GenericVideoSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegAudioSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegVideoSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegSystemSampleDescription)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_AvcSampleDescription)
-
-/*----------------------------------------------------------------------
-| AP4_GetFormatName
-+---------------------------------------------------------------------*/
-const char*
-AP4_GetFormatName(AP4_UI32 format)
-{
- switch (format) {
- case AP4_SAMPLE_FORMAT_MP4A: return "MPEG-4 Audio";
- case AP4_SAMPLE_FORMAT_MP4V: return "MPEG-4 Video";
- case AP4_SAMPLE_FORMAT_MP4S: return "MPEG-4 Systems";
- case AP4_SAMPLE_FORMAT_ALAC: return "Apple Lossless Audio";
- case AP4_SAMPLE_FORMAT_AVC1: return "H.264";
- case AP4_SAMPLE_FORMAT_OVC1: return "VC-1";
- case AP4_SAMPLE_FORMAT_OWMA: return "WMA";
- case AP4_SAMPLE_FORMAT_AC_3: return "Dolby Digital (AC-3)";
- case AP4_SAMPLE_FORMAT_EC_3: return "Dolby Digital Plus (Enhanced AC-3)";
- case AP4_SAMPLE_FORMAT_AVCP: return "Advanced Video Coding Parameters";
- case AP4_SAMPLE_FORMAT_DRAC: return "Dirac";
- case AP4_SAMPLE_FORMAT_DRA1: return "DRA Audio";
- case AP4_SAMPLE_FORMAT_G726: return "G726";
- case AP4_SAMPLE_FORMAT_MJP2: return "Motion JPEG 2000";
- case AP4_SAMPLE_FORMAT_OKSD: return "OMA Keys";
- case AP4_SAMPLE_FORMAT_RAW_: return "Uncompressed Audio";
- case AP4_SAMPLE_FORMAT_RTP_: return "RTP Hints";
- case AP4_SAMPLE_FORMAT_S263: return "H.263";
- case AP4_SAMPLE_FORMAT_SAMR: return "Narrowband AMR";
- case AP4_SAMPLE_FORMAT_SAWB: return "Wideband AMR";
- case AP4_SAMPLE_FORMAT_SAWP: return "Extended AMR";
- case AP4_SAMPLE_FORMAT_SEVC: return "EVRC Voice";
- case AP4_SAMPLE_FORMAT_SQCP: return "13K Voice";
- case AP4_SAMPLE_FORMAT_SRTP: return "SRTP Hints";
- case AP4_SAMPLE_FORMAT_SSMV: return "SMV Voice";
- case AP4_SAMPLE_FORMAT_TEXT: return "Textual Metadata";
- case AP4_SAMPLE_FORMAT_TWOS: return "Uncompressed 16-bit Audio";
- case AP4_SAMPLE_FORMAT_TX3G: return "Timed Text";
- case AP4_SAMPLE_FORMAT_VC_1: return "SMPTE VC-1";
- case AP4_SAMPLE_FORMAT_XML_: return "XML Metadata";
- default: return NULL;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_SampleDescription::AP4_SampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription::AP4_SampleDescription(Type type,
- AP4_UI32 format,
- AP4_AtomParent* details) :
- m_Type(type), m_Format(format)
-{
- if (details) {
- for (AP4_List<AP4_Atom>::Item* item = details->GetChildren().FirstItem();
- item;
- item = item->GetNext()) {
- AP4_Atom* atom = item->GetData();
- if (atom) {
- AP4_Atom* clone = atom->Clone();
- if (clone) m_Details.AddChild(clone);
- }
- }
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_SampleDescription::Clone
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_SampleDescription::Clone(AP4_Result* result)
-{
- if (result) *result = AP4_SUCCESS;
- AP4_Atom* atom = ToAtom();
- if (atom == NULL) {
- if (result) *result = AP4_FAILURE;
- return NULL;
- }
- AP4_SampleEntry* sample_entry = AP4_DYNAMIC_CAST(AP4_SampleEntry, atom);
- if (sample_entry == NULL) {
- if (result) *result = AP4_ERROR_INTERNAL;
- delete atom;
- return NULL;
- }
-
- AP4_SampleDescription* clone = sample_entry->ToSampleDescription();
- if (clone == NULL) {
- if (result) *result = AP4_ERROR_INTERNAL;
- }
-
- delete atom;
- return clone;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SampleDescription::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Atom*
-AP4_SampleDescription::ToAtom() const
-{
- return new AP4_SampleEntry(m_Format);
-}
-
-/*----------------------------------------------------------------------
-| AP4_UnknownSampleDescription::AP4_UnknownSampleDescription
-+---------------------------------------------------------------------*/
-AP4_UnknownSampleDescription::AP4_UnknownSampleDescription(AP4_Atom* atom) :
- AP4_SampleDescription(AP4_SampleDescription::TYPE_UNKNOWN,
- atom->GetType(),
- NULL),
- m_Atom(atom->Clone())
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_UnknownSampleDescription::~AP4_UnknownSampleDescription
-+---------------------------------------------------------------------*/
-AP4_UnknownSampleDescription::~AP4_UnknownSampleDescription()
-{
- delete m_Atom;
-}
-
-/*----------------------------------------------------------------------
-| AP4_UnknownSampleDescription::Clone
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_UnknownSampleDescription::Clone(AP4_Result* result)
-{
- AP4_Atom* atom_clone = NULL;
- if (m_Atom) {
- atom_clone = m_Atom->Clone();
- if (atom_clone == NULL) {
- if (result) *result = AP4_FAILURE;
- return NULL;
- }
- }
- if (result) *result = AP4_SUCCESS;
- return new AP4_UnknownSampleDescription(atom_clone);
-}
-
-/*----------------------------------------------------------------------
-| AP4_UnknownSampleDescription::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Atom*
-AP4_UnknownSampleDescription::ToAtom() const
-{
- if (m_Atom) {
- return m_Atom->Clone();
- } else {
- return NULL;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvcSampleDescription::AP4_AvcSampleDescription
-+---------------------------------------------------------------------*/
-AP4_AvcSampleDescription::AP4_AvcSampleDescription(AP4_UI16 width,
- AP4_UI16 height,
- AP4_UI16 depth,
- const char* compressor_name,
- AP4_UI08 profile,
- AP4_UI08 level,
- AP4_UI08 profile_compatibility,
- AP4_UI08 length_size,
- const AP4_Array<AP4_DataBuffer>& sequence_parameters,
- const AP4_Array<AP4_DataBuffer>& picture_parameters) :
- AP4_SampleDescription(TYPE_AVC, AP4_SAMPLE_FORMAT_AVC1, NULL),
- AP4_VideoSampleDescription(width, height, depth, compressor_name)
-{
- m_AvccAtom = new AP4_AvccAtom(profile,
- level,
- profile_compatibility,
- length_size,
- sequence_parameters,
- picture_parameters);
- m_Details.AddChild(m_AvccAtom);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvcSampleDescription::AP4_AvcSampleDescription
-+---------------------------------------------------------------------*/
-AP4_AvcSampleDescription::AP4_AvcSampleDescription(AP4_UI16 width,
- AP4_UI16 height,
- AP4_UI16 depth,
- const char* compressor_name,
- const AP4_AvccAtom* avcc) :
- AP4_SampleDescription(TYPE_AVC, AP4_SAMPLE_FORMAT_AVC1, NULL),
- AP4_VideoSampleDescription(width, height, depth, compressor_name)
-{
- if (avcc) {
- m_AvccAtom = new AP4_AvccAtom(*avcc);
- } else {
- // should never happen
- m_AvccAtom = new AP4_AvccAtom();
- }
- m_Details.AddChild(m_AvccAtom);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvcSampleDescription::AP4_AvcSampleDescription
-+---------------------------------------------------------------------*/
-AP4_AvcSampleDescription::AP4_AvcSampleDescription(AP4_UI16 width,
- AP4_UI16 height,
- AP4_UI16 depth,
- const char* compressor_name,
- AP4_AtomParent* details) :
- AP4_SampleDescription(TYPE_AVC, AP4_SAMPLE_FORMAT_AVC1, details),
- AP4_VideoSampleDescription(width, height, depth, compressor_name),
- m_AvccAtom(NULL)
-{
- AP4_AvccAtom* avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, details->GetChild(AP4_ATOM_TYPE_AVCC));
- if (avcc) {
- m_AvccAtom = new AP4_AvccAtom(*avcc);
- } else {
- // shoud never happen
- m_AvccAtom = new AP4_AvccAtom();
- }
- m_Details.AddChild(m_AvccAtom);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AvcSampleDescription::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Atom*
-AP4_AvcSampleDescription::ToAtom() const
-{
- return new AP4_Avc1SampleEntry(m_Width,
- m_Height,
- m_Depth,
- m_CompressorName.GetChars(),
- *m_AvccAtom);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSampleDescription::AP4_MpegSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegSampleDescription::AP4_MpegSampleDescription(AP4_UI32 format,
- AP4_EsdsAtom* esds) :
- AP4_SampleDescription(TYPE_MPEG, format, NULL),
- m_StreamType(0),
- m_ObjectTypeId(0),
- m_BufferSize(0),
- m_MaxBitrate(0),
- m_AvgBitrate(0)
-{
- if (esds) {
- // get the es descriptor
- const AP4_EsDescriptor* es_desc = esds->GetEsDescriptor();
- if (es_desc == NULL) return;
-
- // get the decoder config descriptor
- const AP4_DecoderConfigDescriptor* dc_desc =
- es_desc->GetDecoderConfigDescriptor();
- if (dc_desc) {
- m_StreamType = dc_desc->GetStreamType();
- m_ObjectTypeId = dc_desc->GetObjectTypeIndication();
- m_BufferSize = dc_desc->GetBufferSize();
- m_MaxBitrate = dc_desc->GetMaxBitrate();
- m_AvgBitrate = dc_desc->GetAvgBitrate();
- const AP4_DecoderSpecificInfoDescriptor* dsi_desc =
- dc_desc->GetDecoderSpecificInfoDescriptor();
- if (dsi_desc != NULL) {
- m_DecoderInfo.SetData(dsi_desc->GetDecoderSpecificInfo().GetData(),
- dsi_desc->GetDecoderSpecificInfo().GetDataSize());
- }
- }
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSampleDescription::AP4_MpegSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegSampleDescription::AP4_MpegSampleDescription(
- AP4_UI32 format,
- StreamType stream_type,
- OTI oti,
- const AP4_DataBuffer* decoder_info,
- AP4_UI32 buffer_size,
- AP4_UI32 max_bitrate,
- AP4_UI32 avg_bitrate) :
- AP4_SampleDescription(TYPE_MPEG, format, NULL),
- m_StreamType(stream_type),
- m_ObjectTypeId(oti),
- m_BufferSize(buffer_size),
- m_MaxBitrate(max_bitrate),
- m_AvgBitrate(avg_bitrate)
-{
- if (decoder_info != NULL) {
- m_DecoderInfo.SetData(decoder_info->GetData(), decoder_info->GetDataSize());
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSampleDescription::CreateEsDescriptor
-+---------------------------------------------------------------------*/
-AP4_EsDescriptor*
-AP4_MpegSampleDescription::CreateEsDescriptor() const
-{
- AP4_EsDescriptor* desc = new AP4_EsDescriptor(0);
- AP4_DecoderSpecificInfoDescriptor* dsi_desc;
- if (m_DecoderInfo.GetDataSize() != 0) {
- dsi_desc = new AP4_DecoderSpecificInfoDescriptor(m_DecoderInfo);
- } else {
- dsi_desc = NULL;
- }
- AP4_DecoderConfigDescriptor* decoder_config =
- new AP4_DecoderConfigDescriptor(m_StreamType,
- m_ObjectTypeId,
- m_BufferSize,
- m_MaxBitrate,
- m_AvgBitrate,
- dsi_desc);
- desc->AddSubDescriptor(decoder_config);
-
- // add a fixed SL Config
- desc->AddSubDescriptor(new AP4_SLConfigDescriptor());
-
- return desc;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription(AP4_EsdsAtom* esds) :
- AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4S, esds)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription(
- StreamType stream_type,
- OTI oti,
- const AP4_DataBuffer* decoder_info,
- AP4_UI32 buffer_size,
- AP4_UI32 max_bitrate,
- AP4_UI32 avg_bitrate) :
- AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4S,
- stream_type,
- oti,
- decoder_info,
- buffer_size,
- max_bitrate,
- avg_bitrate)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSystemSampleDescription::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Atom*
-AP4_MpegSystemSampleDescription::ToAtom() const
-{
- return new AP4_Mp4sSampleEntry(CreateEsDescriptor());
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription(
- unsigned int sample_rate,
- unsigned int sample_size,
- unsigned int channel_count,
- AP4_EsdsAtom* esds) :
- AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4A, esds),
- AP4_AudioSampleDescription(sample_rate, sample_size, channel_count)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription(
- OTI oti,
- unsigned int sample_rate,
- unsigned int sample_size,
- unsigned int channel_count,
- const AP4_DataBuffer* decoder_info,
- AP4_UI32 buffer_size,
- AP4_UI32 max_bitrate,
- AP4_UI32 avg_bitrate) :
- AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4A,
- AP4_STREAM_TYPE_AUDIO,
- oti,
- decoder_info, buffer_size,
- max_bitrate, avg_bitrate),
- AP4_AudioSampleDescription(sample_rate, sample_size, channel_count)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegAudioSampleDescription::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Atom*
-AP4_MpegAudioSampleDescription::ToAtom() const
-{
- return new AP4_Mp4aSampleEntry(m_SampleRate<<16,
- m_SampleSize,
- m_ChannelCount,
- CreateEsDescriptor());
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectType
-+---------------------------------------------------------------------*/
-AP4_MpegAudioSampleDescription::Mpeg4AudioObjectType
-AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectType() const
-{
- if (m_ObjectTypeId == AP4_OTI_MPEG4_AUDIO &&
- m_DecoderInfo.GetDataSize() >= 1) {
- AP4_UI08 type = m_DecoderInfo.GetData()[0]>>3;
- if (type == 31) {
- if (m_DecoderInfo.GetDataSize() < 2) return 0;
- type = 32+(((m_DecoderInfo.GetData()[0]&0x07)<<3) |
- ((m_DecoderInfo.GetData()[1]&0xE0)>>5));
- }
- return type;
- } else {
- return 0;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription(
- AP4_UI16 width,
- AP4_UI16 height,
- AP4_UI16 depth,
- const char* compressor_name,
- AP4_EsdsAtom* esds) :
-
- AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4V, esds),
- AP4_VideoSampleDescription(width, height, depth, compressor_name)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription
-+---------------------------------------------------------------------*/
-AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription(
- OTI oti,
- AP4_UI16 width,
- AP4_UI16 height,
- AP4_UI16 depth,
- const char* compressor_name,
- const AP4_DataBuffer* decoder_info,
- AP4_UI32 buffer_size,
- AP4_UI32 max_bitrate,
- AP4_UI32 avg_bitrate) :
- AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4V,
- AP4_STREAM_TYPE_VISUAL,
- oti,
- decoder_info,
- buffer_size,
- max_bitrate,
- avg_bitrate),
- AP4_VideoSampleDescription(width, height, depth, compressor_name)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegVideoSampleDescription::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Atom*
-AP4_MpegVideoSampleDescription::ToAtom() const
-{
- return new AP4_Mp4vSampleEntry(m_Width,
- m_Height,
- m_Depth,
- m_CompressorName.GetChars(),
- CreateEsDescriptor());
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSampleDescription::GetStreamTypeString
-+---------------------------------------------------------------------*/
-const char*
-AP4_MpegSampleDescription::GetStreamTypeString(StreamType type)
-{
- switch (type) {
- case AP4_STREAM_TYPE_FORBIDDEN: return "INVALID";
- case AP4_STREAM_TYPE_OD: return "Object Descriptor";
- case AP4_STREAM_TYPE_CR: return "CR";
- case AP4_STREAM_TYPE_BIFS: return "BIFS";
- case AP4_STREAM_TYPE_VISUAL: return "Visual";
- case AP4_STREAM_TYPE_AUDIO: return "Audio";
- case AP4_STREAM_TYPE_MPEG7: return "MPEG-7";
- case AP4_STREAM_TYPE_IPMP: return "IPMP";
- case AP4_STREAM_TYPE_OCI: return "OCI";
- case AP4_STREAM_TYPE_MPEGJ: return "MPEG-J";
- default: return "UNKNOWN";
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegSampleDescription::GetObjectTypeString
-+---------------------------------------------------------------------*/
-const char*
-AP4_MpegSampleDescription::GetObjectTypeString(OTI oti)
-{
- switch (oti) {
- case AP4_OTI_MPEG4_SYSTEM: return "MPEG-4 System";
- case AP4_OTI_MPEG4_SYSTEM_COR: return "MPEG-4 System COR";
- case AP4_OTI_MPEG4_VISUAL: return "MPEG-4 Video";
- case AP4_OTI_MPEG4_AUDIO: return "MPEG-4 Audio";
- case AP4_OTI_MPEG2_VISUAL_SIMPLE: return "MPEG-2 Video Simple Profile";
- case AP4_OTI_MPEG2_VISUAL_MAIN: return "MPEG-2 Video Main Profile";
- case AP4_OTI_MPEG2_VISUAL_SNR: return "MPEG-2 Video SNR";
- case AP4_OTI_MPEG2_VISUAL_SPATIAL: return "MPEG-2 Video Spatial";
- case AP4_OTI_MPEG2_VISUAL_HIGH: return "MPEG-2 Video High";
- case AP4_OTI_MPEG2_VISUAL_422: return "MPEG-2 Video 4:2:2";
- case AP4_OTI_MPEG2_AAC_AUDIO_MAIN: return "MPEG-2 Audio AAC Main Profile";
- case AP4_OTI_MPEG2_AAC_AUDIO_LC: return "MPEG-2 Audio AAC Low Complexity";
- case AP4_OTI_MPEG2_AAC_AUDIO_SSRP: return "MPEG-2 Audio AAC SSRP";
- case AP4_OTI_MPEG2_PART3_AUDIO: return "MPEG-2 Audio Part-3";
- case AP4_OTI_MPEG1_VISUAL: return "MPEG-1 Video";
- case AP4_OTI_MPEG1_AUDIO: return "MPEG-1 Audio";
- case AP4_OTI_JPEG: return "JPEG";
- default: return "UNKNOWN";
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectTypeString
-+---------------------------------------------------------------------*/
-const char*
-AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectTypeString(Mpeg4AudioObjectType type)
-{
- switch (type) {
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_MAIN: return "AAC Main Profile";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_LC: return "AAC Low Complexity";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SSR: return "AAC Scalable Sample Rate";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_LTP: return "AAC Long Term Predictor";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR: return "Spectral Band Replication";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SCALABLE: return "AAC Scalable";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_TWINVQ: return "Twin VQ";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_CELP: return "CELP";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_HVXC: return "HVXC";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_TTSI: return "TTSI";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_MAIN_SYNTHETIC: return "Main Synthetic";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_WAVETABLE_SYNTHESIS: return "Wavetable Synthesis";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_GENERAL_MIDI: return "General MIDI";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ALGORITHMIC_SYNTHESIS: return "Algorithmic Synthesis";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LC: return "Error Resilient AAC Low Complexity";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LTP: return "Error Resilient AAC Long Term Prediction";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_SCALABLE: return "Error Resilient AAC Scalable";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_TWINVQ: return "Error Resilient Twin VQ";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC: return "Error Resilient Bit Sliced Arithmetic Coding";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LD: return "Error Resilient AAC Low Delay";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_CELP: return "Error Resilient CELP";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_HVXC: return "Error Resilient HVXC";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_HILN: return "Error Resilient HILN";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_PARAMETRIC: return "Error Resilient Parametric";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_SSC: return "SSC";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_MPEG_SURROUND: return "MPEG Surround";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_LAYER_1: return "MPEG Layer 1";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_LAYER_2: return "MPEG Layer 2";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_LAYER_3: return "MPEG Layer 3";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_DST: return "Direct Stream Transfer";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ALS: return "ALS Lossless Coding";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_SLS: return "SLS Scalable Lossless Coding";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_SLS_NON_CORE: return "SLS Scalable Lossless Coding (Non Core)";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_ELD: return "Error Resilient AAC ELD";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_SMR_SIMPLE: return "SMR Simple";
- case AP4_MPEG4_AUDIO_OBJECT_TYPE_SMR_MAIN: return "SMR Main";
- default: return "UNKNOWN";
- }
-}
+/*****************************************************************
+|
+| AP4 - Sample Description Objects
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4SampleDescription.h"
+#include "Ap4EsDescriptor.h"
+#include "Ap4SLConfigDescriptor.h"
+#include "Ap4SampleEntry.h"
+#include "Ap4AvccAtom.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_SampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_UnknownSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_AudioSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_VideoSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_GenericAudioSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_GenericVideoSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegAudioSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegVideoSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_MpegSystemSampleDescription)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_AvcSampleDescription)
+
+/*----------------------------------------------------------------------
+| AP4_GetFormatName
++---------------------------------------------------------------------*/
+const char*
+AP4_GetFormatName(AP4_UI32 format)
+{
+ switch (format) {
+ case AP4_SAMPLE_FORMAT_MP4A: return "MPEG-4 Audio";
+ case AP4_SAMPLE_FORMAT_MP4V: return "MPEG-4 Video";
+ case AP4_SAMPLE_FORMAT_MP4S: return "MPEG-4 Systems";
+ case AP4_SAMPLE_FORMAT_ALAC: return "Apple Lossless Audio";
+ case AP4_SAMPLE_FORMAT_AVC1: return "H.264";
+ case AP4_SAMPLE_FORMAT_OVC1: return "VC-1";
+ case AP4_SAMPLE_FORMAT_OWMA: return "WMA";
+ case AP4_SAMPLE_FORMAT_AC_3: return "Dolby Digital (AC-3)";
+ case AP4_SAMPLE_FORMAT_EC_3: return "Dolby Digital Plus (Enhanced AC-3)";
+ case AP4_SAMPLE_FORMAT_AVCP: return "Advanced Video Coding Parameters";
+ case AP4_SAMPLE_FORMAT_DRAC: return "Dirac";
+ case AP4_SAMPLE_FORMAT_DRA1: return "DRA Audio";
+ case AP4_SAMPLE_FORMAT_G726: return "G726";
+ case AP4_SAMPLE_FORMAT_MJP2: return "Motion JPEG 2000";
+ case AP4_SAMPLE_FORMAT_OKSD: return "OMA Keys";
+ case AP4_SAMPLE_FORMAT_RAW_: return "Uncompressed Audio";
+ case AP4_SAMPLE_FORMAT_RTP_: return "RTP Hints";
+ case AP4_SAMPLE_FORMAT_S263: return "H.263";
+ case AP4_SAMPLE_FORMAT_SAMR: return "Narrowband AMR";
+ case AP4_SAMPLE_FORMAT_SAWB: return "Wideband AMR";
+ case AP4_SAMPLE_FORMAT_SAWP: return "Extended AMR";
+ case AP4_SAMPLE_FORMAT_SEVC: return "EVRC Voice";
+ case AP4_SAMPLE_FORMAT_SQCP: return "13K Voice";
+ case AP4_SAMPLE_FORMAT_SRTP: return "SRTP Hints";
+ case AP4_SAMPLE_FORMAT_SSMV: return "SMV Voice";
+ case AP4_SAMPLE_FORMAT_TEXT: return "Textual Metadata";
+ case AP4_SAMPLE_FORMAT_TWOS: return "Uncompressed 16-bit Audio";
+ case AP4_SAMPLE_FORMAT_TX3G: return "Timed Text";
+ case AP4_SAMPLE_FORMAT_VC_1: return "SMPTE VC-1";
+ case AP4_SAMPLE_FORMAT_XML_: return "XML Metadata";
+ default: return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_SampleDescription::AP4_SampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription::AP4_SampleDescription(Type type,
+ AP4_UI32 format,
+ AP4_AtomParent* details) :
+ m_Type(type), m_Format(format)
+{
+ if (details) {
+ for (AP4_List<AP4_Atom>::Item* item = details->GetChildren().FirstItem();
+ item;
+ item = item->GetNext()) {
+ AP4_Atom* atom = item->GetData();
+ if (atom) {
+ AP4_Atom* clone = atom->Clone();
+ if (clone) m_Details.AddChild(clone);
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_SampleDescription::Clone
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_SampleDescription::Clone(AP4_Result* result)
+{
+ if (result) *result = AP4_SUCCESS;
+ AP4_Atom* atom = ToAtom();
+ if (atom == NULL) {
+ if (result) *result = AP4_FAILURE;
+ return NULL;
+ }
+ AP4_SampleEntry* sample_entry = AP4_DYNAMIC_CAST(AP4_SampleEntry, atom);
+ if (sample_entry == NULL) {
+ if (result) *result = AP4_ERROR_INTERNAL;
+ delete atom;
+ return NULL;
+ }
+
+ AP4_SampleDescription* clone = sample_entry->ToSampleDescription();
+ if (clone == NULL) {
+ if (result) *result = AP4_ERROR_INTERNAL;
+ }
+
+ delete atom;
+ return clone;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SampleDescription::ToAtom
++---------------------------------------------------------------------*/
+AP4_Atom*
+AP4_SampleDescription::ToAtom() const
+{
+ return new AP4_SampleEntry(m_Format);
+}
+
+/*----------------------------------------------------------------------
+| AP4_UnknownSampleDescription::AP4_UnknownSampleDescription
++---------------------------------------------------------------------*/
+AP4_UnknownSampleDescription::AP4_UnknownSampleDescription(AP4_Atom* atom) :
+ AP4_SampleDescription(AP4_SampleDescription::TYPE_UNKNOWN,
+ atom->GetType(),
+ NULL),
+ m_Atom(atom->Clone())
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_UnknownSampleDescription::~AP4_UnknownSampleDescription
++---------------------------------------------------------------------*/
+AP4_UnknownSampleDescription::~AP4_UnknownSampleDescription()
+{
+ delete m_Atom;
+}
+
+/*----------------------------------------------------------------------
+| AP4_UnknownSampleDescription::Clone
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_UnknownSampleDescription::Clone(AP4_Result* result)
+{
+ AP4_Atom* atom_clone = NULL;
+ if (m_Atom) {
+ atom_clone = m_Atom->Clone();
+ if (atom_clone == NULL) {
+ if (result) *result = AP4_FAILURE;
+ return NULL;
+ }
+ }
+ if (result) *result = AP4_SUCCESS;
+ return new AP4_UnknownSampleDescription(atom_clone);
+}
+
+/*----------------------------------------------------------------------
+| AP4_UnknownSampleDescription::ToAtom
++---------------------------------------------------------------------*/
+AP4_Atom*
+AP4_UnknownSampleDescription::ToAtom() const
+{
+ if (m_Atom) {
+ return m_Atom->Clone();
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvcSampleDescription::AP4_AvcSampleDescription
++---------------------------------------------------------------------*/
+AP4_AvcSampleDescription::AP4_AvcSampleDescription(AP4_UI16 width,
+ AP4_UI16 height,
+ AP4_UI16 depth,
+ const char* compressor_name,
+ AP4_UI08 profile,
+ AP4_UI08 level,
+ AP4_UI08 profile_compatibility,
+ AP4_UI08 length_size,
+ const AP4_Array<AP4_DataBuffer>& sequence_parameters,
+ const AP4_Array<AP4_DataBuffer>& picture_parameters) :
+ AP4_SampleDescription(TYPE_AVC, AP4_SAMPLE_FORMAT_AVC1, NULL),
+ AP4_VideoSampleDescription(width, height, depth, compressor_name)
+{
+ m_AvccAtom = new AP4_AvccAtom(profile,
+ level,
+ profile_compatibility,
+ length_size,
+ sequence_parameters,
+ picture_parameters);
+ m_Details.AddChild(m_AvccAtom);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvcSampleDescription::AP4_AvcSampleDescription
++---------------------------------------------------------------------*/
+AP4_AvcSampleDescription::AP4_AvcSampleDescription(AP4_UI16 width,
+ AP4_UI16 height,
+ AP4_UI16 depth,
+ const char* compressor_name,
+ const AP4_AvccAtom* avcc) :
+ AP4_SampleDescription(TYPE_AVC, AP4_SAMPLE_FORMAT_AVC1, NULL),
+ AP4_VideoSampleDescription(width, height, depth, compressor_name)
+{
+ if (avcc) {
+ m_AvccAtom = new AP4_AvccAtom(*avcc);
+ } else {
+ // should never happen
+ m_AvccAtom = new AP4_AvccAtom();
+ }
+ m_Details.AddChild(m_AvccAtom);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvcSampleDescription::AP4_AvcSampleDescription
++---------------------------------------------------------------------*/
+AP4_AvcSampleDescription::AP4_AvcSampleDescription(AP4_UI16 width,
+ AP4_UI16 height,
+ AP4_UI16 depth,
+ const char* compressor_name,
+ AP4_AtomParent* details) :
+ AP4_SampleDescription(TYPE_AVC, AP4_SAMPLE_FORMAT_AVC1, details),
+ AP4_VideoSampleDescription(width, height, depth, compressor_name),
+ m_AvccAtom(NULL)
+{
+ AP4_AvccAtom* avcc = AP4_DYNAMIC_CAST(AP4_AvccAtom, details->GetChild(AP4_ATOM_TYPE_AVCC));
+ if (avcc) {
+ m_AvccAtom = new AP4_AvccAtom(*avcc);
+ } else {
+ // shoud never happen
+ m_AvccAtom = new AP4_AvccAtom();
+ }
+ m_Details.AddChild(m_AvccAtom);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AvcSampleDescription::ToAtom
++---------------------------------------------------------------------*/
+AP4_Atom*
+AP4_AvcSampleDescription::ToAtom() const
+{
+ return new AP4_Avc1SampleEntry(m_Width,
+ m_Height,
+ m_Depth,
+ m_CompressorName.GetChars(),
+ *m_AvccAtom);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSampleDescription::AP4_MpegSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegSampleDescription::AP4_MpegSampleDescription(AP4_UI32 format,
+ AP4_EsdsAtom* esds) :
+ AP4_SampleDescription(TYPE_MPEG, format, NULL),
+ m_StreamType(0),
+ m_ObjectTypeId(0),
+ m_BufferSize(0),
+ m_MaxBitrate(0),
+ m_AvgBitrate(0)
+{
+ if (esds) {
+ // get the es descriptor
+ const AP4_EsDescriptor* es_desc = esds->GetEsDescriptor();
+ if (es_desc == NULL) return;
+
+ // get the decoder config descriptor
+ const AP4_DecoderConfigDescriptor* dc_desc =
+ es_desc->GetDecoderConfigDescriptor();
+ if (dc_desc) {
+ m_StreamType = dc_desc->GetStreamType();
+ m_ObjectTypeId = dc_desc->GetObjectTypeIndication();
+ m_BufferSize = dc_desc->GetBufferSize();
+ m_MaxBitrate = dc_desc->GetMaxBitrate();
+ m_AvgBitrate = dc_desc->GetAvgBitrate();
+ const AP4_DecoderSpecificInfoDescriptor* dsi_desc =
+ dc_desc->GetDecoderSpecificInfoDescriptor();
+ if (dsi_desc != NULL) {
+ m_DecoderInfo.SetData(dsi_desc->GetDecoderSpecificInfo().GetData(),
+ dsi_desc->GetDecoderSpecificInfo().GetDataSize());
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSampleDescription::AP4_MpegSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegSampleDescription::AP4_MpegSampleDescription(
+ AP4_UI32 format,
+ StreamType stream_type,
+ OTI oti,
+ const AP4_DataBuffer* decoder_info,
+ AP4_UI32 buffer_size,
+ AP4_UI32 max_bitrate,
+ AP4_UI32 avg_bitrate) :
+ AP4_SampleDescription(TYPE_MPEG, format, NULL),
+ m_StreamType(stream_type),
+ m_ObjectTypeId(oti),
+ m_BufferSize(buffer_size),
+ m_MaxBitrate(max_bitrate),
+ m_AvgBitrate(avg_bitrate)
+{
+ if (decoder_info != NULL) {
+ m_DecoderInfo.SetData(decoder_info->GetData(), decoder_info->GetDataSize());
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSampleDescription::CreateEsDescriptor
++---------------------------------------------------------------------*/
+AP4_EsDescriptor*
+AP4_MpegSampleDescription::CreateEsDescriptor() const
+{
+ AP4_EsDescriptor* desc = new AP4_EsDescriptor(0);
+ AP4_DecoderSpecificInfoDescriptor* dsi_desc;
+ if (m_DecoderInfo.GetDataSize() != 0) {
+ dsi_desc = new AP4_DecoderSpecificInfoDescriptor(m_DecoderInfo);
+ } else {
+ dsi_desc = NULL;
+ }
+ AP4_DecoderConfigDescriptor* decoder_config =
+ new AP4_DecoderConfigDescriptor(m_StreamType,
+ m_ObjectTypeId,
+ m_BufferSize,
+ m_MaxBitrate,
+ m_AvgBitrate,
+ dsi_desc);
+ desc->AddSubDescriptor(decoder_config);
+
+ // add a fixed SL Config
+ desc->AddSubDescriptor(new AP4_SLConfigDescriptor());
+
+ return desc;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription(AP4_EsdsAtom* esds) :
+ AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4S, esds)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegSystemSampleDescription::AP4_MpegSystemSampleDescription(
+ StreamType stream_type,
+ OTI oti,
+ const AP4_DataBuffer* decoder_info,
+ AP4_UI32 buffer_size,
+ AP4_UI32 max_bitrate,
+ AP4_UI32 avg_bitrate) :
+ AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4S,
+ stream_type,
+ oti,
+ decoder_info,
+ buffer_size,
+ max_bitrate,
+ avg_bitrate)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSystemSampleDescription::ToAtom
++---------------------------------------------------------------------*/
+AP4_Atom*
+AP4_MpegSystemSampleDescription::ToAtom() const
+{
+ return new AP4_Mp4sSampleEntry(CreateEsDescriptor());
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription(
+ unsigned int sample_rate,
+ unsigned int sample_size,
+ unsigned int channel_count,
+ AP4_EsdsAtom* esds) :
+ AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4A, esds),
+ AP4_AudioSampleDescription(sample_rate, sample_size, channel_count)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegAudioSampleDescription::AP4_MpegAudioSampleDescription(
+ OTI oti,
+ unsigned int sample_rate,
+ unsigned int sample_size,
+ unsigned int channel_count,
+ const AP4_DataBuffer* decoder_info,
+ AP4_UI32 buffer_size,
+ AP4_UI32 max_bitrate,
+ AP4_UI32 avg_bitrate) :
+ AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4A,
+ AP4_STREAM_TYPE_AUDIO,
+ oti,
+ decoder_info, buffer_size,
+ max_bitrate, avg_bitrate),
+ AP4_AudioSampleDescription(sample_rate, sample_size, channel_count)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegAudioSampleDescription::ToAtom
++---------------------------------------------------------------------*/
+AP4_Atom*
+AP4_MpegAudioSampleDescription::ToAtom() const
+{
+ return new AP4_Mp4aSampleEntry(m_SampleRate<<16,
+ m_SampleSize,
+ m_ChannelCount,
+ CreateEsDescriptor());
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectType
++---------------------------------------------------------------------*/
+AP4_MpegAudioSampleDescription::Mpeg4AudioObjectType
+AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectType() const
+{
+ if (m_ObjectTypeId == AP4_OTI_MPEG4_AUDIO &&
+ m_DecoderInfo.GetDataSize() >= 1) {
+ AP4_UI08 type = m_DecoderInfo.GetData()[0]>>3;
+ if (type == 31) {
+ if (m_DecoderInfo.GetDataSize() < 2) return 0;
+ type = 32+(((m_DecoderInfo.GetData()[0]&0x07)<<3) |
+ ((m_DecoderInfo.GetData()[1]&0xE0)>>5));
+ }
+ return type;
+ } else {
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription(
+ AP4_UI16 width,
+ AP4_UI16 height,
+ AP4_UI16 depth,
+ const char* compressor_name,
+ AP4_EsdsAtom* esds) :
+
+ AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4V, esds),
+ AP4_VideoSampleDescription(width, height, depth, compressor_name)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription
++---------------------------------------------------------------------*/
+AP4_MpegVideoSampleDescription::AP4_MpegVideoSampleDescription(
+ OTI oti,
+ AP4_UI16 width,
+ AP4_UI16 height,
+ AP4_UI16 depth,
+ const char* compressor_name,
+ const AP4_DataBuffer* decoder_info,
+ AP4_UI32 buffer_size,
+ AP4_UI32 max_bitrate,
+ AP4_UI32 avg_bitrate) :
+ AP4_MpegSampleDescription(AP4_ATOM_TYPE_MP4V,
+ AP4_STREAM_TYPE_VISUAL,
+ oti,
+ decoder_info,
+ buffer_size,
+ max_bitrate,
+ avg_bitrate),
+ AP4_VideoSampleDescription(width, height, depth, compressor_name)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegVideoSampleDescription::ToAtom
++---------------------------------------------------------------------*/
+AP4_Atom*
+AP4_MpegVideoSampleDescription::ToAtom() const
+{
+ return new AP4_Mp4vSampleEntry(m_Width,
+ m_Height,
+ m_Depth,
+ m_CompressorName.GetChars(),
+ CreateEsDescriptor());
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSampleDescription::GetStreamTypeString
++---------------------------------------------------------------------*/
+const char*
+AP4_MpegSampleDescription::GetStreamTypeString(StreamType type)
+{
+ switch (type) {
+ case AP4_STREAM_TYPE_FORBIDDEN: return "INVALID";
+ case AP4_STREAM_TYPE_OD: return "Object Descriptor";
+ case AP4_STREAM_TYPE_CR: return "CR";
+ case AP4_STREAM_TYPE_BIFS: return "BIFS";
+ case AP4_STREAM_TYPE_VISUAL: return "Visual";
+ case AP4_STREAM_TYPE_AUDIO: return "Audio";
+ case AP4_STREAM_TYPE_MPEG7: return "MPEG-7";
+ case AP4_STREAM_TYPE_IPMP: return "IPMP";
+ case AP4_STREAM_TYPE_OCI: return "OCI";
+ case AP4_STREAM_TYPE_MPEGJ: return "MPEG-J";
+ default: return "UNKNOWN";
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegSampleDescription::GetObjectTypeString
++---------------------------------------------------------------------*/
+const char*
+AP4_MpegSampleDescription::GetObjectTypeString(OTI oti)
+{
+ switch (oti) {
+ case AP4_OTI_MPEG4_SYSTEM: return "MPEG-4 System";
+ case AP4_OTI_MPEG4_SYSTEM_COR: return "MPEG-4 System COR";
+ case AP4_OTI_MPEG4_VISUAL: return "MPEG-4 Video";
+ case AP4_OTI_MPEG4_AUDIO: return "MPEG-4 Audio";
+ case AP4_OTI_MPEG2_VISUAL_SIMPLE: return "MPEG-2 Video Simple Profile";
+ case AP4_OTI_MPEG2_VISUAL_MAIN: return "MPEG-2 Video Main Profile";
+ case AP4_OTI_MPEG2_VISUAL_SNR: return "MPEG-2 Video SNR";
+ case AP4_OTI_MPEG2_VISUAL_SPATIAL: return "MPEG-2 Video Spatial";
+ case AP4_OTI_MPEG2_VISUAL_HIGH: return "MPEG-2 Video High";
+ case AP4_OTI_MPEG2_VISUAL_422: return "MPEG-2 Video 4:2:2";
+ case AP4_OTI_MPEG2_AAC_AUDIO_MAIN: return "MPEG-2 Audio AAC Main Profile";
+ case AP4_OTI_MPEG2_AAC_AUDIO_LC: return "MPEG-2 Audio AAC Low Complexity";
+ case AP4_OTI_MPEG2_AAC_AUDIO_SSRP: return "MPEG-2 Audio AAC SSRP";
+ case AP4_OTI_MPEG2_PART3_AUDIO: return "MPEG-2 Audio Part-3";
+ case AP4_OTI_MPEG1_VISUAL: return "MPEG-1 Video";
+ case AP4_OTI_MPEG1_AUDIO: return "MPEG-1 Audio";
+ case AP4_OTI_JPEG: return "JPEG";
+ default: return "UNKNOWN";
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectTypeString
++---------------------------------------------------------------------*/
+const char*
+AP4_MpegAudioSampleDescription::GetMpeg4AudioObjectTypeString(Mpeg4AudioObjectType type)
+{
+ switch (type) {
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_MAIN: return "AAC Main Profile";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_LC: return "AAC Low Complexity";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SSR: return "AAC Scalable Sample Rate";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_LTP: return "AAC Long Term Predictor";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_SBR: return "Spectral Band Replication";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_AAC_SCALABLE: return "AAC Scalable";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_TWINVQ: return "Twin VQ";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_CELP: return "CELP";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_HVXC: return "HVXC";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_TTSI: return "TTSI";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_MAIN_SYNTHETIC: return "Main Synthetic";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_WAVETABLE_SYNTHESIS: return "Wavetable Synthesis";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_GENERAL_MIDI: return "General MIDI";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ALGORITHMIC_SYNTHESIS: return "Algorithmic Synthesis";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LC: return "Error Resilient AAC Low Complexity";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LTP: return "Error Resilient AAC Long Term Prediction";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_SCALABLE: return "Error Resilient AAC Scalable";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_TWINVQ: return "Error Resilient Twin VQ";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_BSAC: return "Error Resilient Bit Sliced Arithmetic Coding";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_LD: return "Error Resilient AAC Low Delay";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_CELP: return "Error Resilient CELP";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_HVXC: return "Error Resilient HVXC";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_HILN: return "Error Resilient HILN";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_PARAMETRIC: return "Error Resilient Parametric";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_SSC: return "SSC";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_MPEG_SURROUND: return "MPEG Surround";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_LAYER_1: return "MPEG Layer 1";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_LAYER_2: return "MPEG Layer 2";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_LAYER_3: return "MPEG Layer 3";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_DST: return "Direct Stream Transfer";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ALS: return "ALS Lossless Coding";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_SLS: return "SLS Scalable Lossless Coding";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_SLS_NON_CORE: return "SLS Scalable Lossless Coding (Non Core)";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_ER_AAC_ELD: return "Error Resilient AAC ELD";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_SMR_SIMPLE: return "SMR Simple";
+ case AP4_MPEG4_AUDIO_OBJECT_TYPE_SMR_MAIN: return "SMR Main";
+ default: return "UNKNOWN";
+ }
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.h
index 9e60cad7d..fa695f73c 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleDescription.h
@@ -510,8 +510,8 @@ const AP4_UI08 AP4_MPEG4_AUDIO_OBJECT_TYPE_SMR_SIMPLE = 40; /**< SMR
const AP4_UI08 AP4_MPEG4_AUDIO_OBJECT_TYPE_SMR_MAIN = 41; /**< SMR Main */
// ==> Start patch MPC
-const AP4_MpegSampleDescription::OTI AP4_NERO_VOBSUB = 0xE0;
-// <== End patch MPC
+const AP4_MpegSampleDescription::OTI AP4_NERO_VOBSUB = 0xE0;
+// <== End patch MPC
#endif // _AP4_SAMPLE_DESCRIPTION_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleEntry.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleEntry.cpp
index 086401b01..ed4b77bae 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleEntry.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleEntry.cpp
@@ -66,7 +66,7 @@ AP4_SampleEntry::AP4_SampleEntry(AP4_Atom::Type format,
+---------------------------------------------------------------------*/
AP4_SampleEntry::AP4_SampleEntry(AP4_Atom::Type format,
AP4_Size size) :
- AP4_ContainerAtom(format, size, false)
+ AP4_ContainerAtom(format, (AP4_UI64)size, false)
{
}
@@ -77,7 +77,7 @@ AP4_SampleEntry::AP4_SampleEntry(AP4_Atom::Type format,
AP4_Size size,
AP4_ByteStream& stream,
AP4_AtomFactory& atom_factory) :
- AP4_ContainerAtom(format, size, false)
+ AP4_ContainerAtom(format, (AP4_UI64)size, false)
{
Read(stream, atom_factory);
}
@@ -1379,4 +1379,4 @@ AP4_AC3SampleEntry::GetFieldsSize()
{
return AP4_AudioSampleEntry::GetFieldsSize() + 11;
}
-// <== End patch MPC \ No newline at end of file
+// <== End patch MPC
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.cpp
index 3f892d2a9..3bbc302fd 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.cpp
@@ -1,209 +1,214 @@
-/*****************************************************************
-|
-| AP4 - Sample Table Interface
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4SampleTable.h"
-#include "Ap4ContainerAtom.h"
-#include "Ap4StsdAtom.h"
-#include "Ap4StszAtom.h"
-#include "Ap4StscAtom.h"
-#include "Ap4StcoAtom.h"
-#include "Ap4Co64Atom.h"
-#include "Ap4SttsAtom.h"
-#include "Ap4StssAtom.h"
-#include "Ap4CttsAtom.h"
-#include "Ap4Sample.h"
-
-/*----------------------------------------------------------------------
-| AP4_SampleTable::GenerateStblAtom
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SampleTable::GenerateStblAtom(AP4_ContainerAtom*& stbl)
-{
- // create the stbl container
- stbl = new AP4_ContainerAtom(AP4_ATOM_TYPE_STBL);
-
- // create the stsd atom
- AP4_StsdAtom* stsd = new AP4_StsdAtom(this);
-
- // create the stsz atom
- AP4_StszAtom* stsz = new AP4_StszAtom();
-
- // create the stsc atom
- AP4_StscAtom* stsc = new AP4_StscAtom();
-
- // create the stts atom
- AP4_SttsAtom* stts = new AP4_SttsAtom();
-
- // create the stss atom
- AP4_StssAtom* stss = new AP4_StssAtom();
-
- // declare the ctts atom (may be created later)
- AP4_CttsAtom* ctts = NULL;
-
- // start chunk table
- AP4_Ordinal current_chunk_index = 0;
- AP4_Size current_chunk_size = 0;
- AP4_Position current_chunk_offset = 0;
- AP4_Cardinal current_samples_in_chunk = 0;
- AP4_Ordinal current_sample_description_index = 0;
- AP4_UI32 current_duration = 0;
- AP4_Cardinal current_duration_run = 0;
- AP4_UI32 current_cts_delta = 0;
- AP4_Cardinal current_cts_delta_run = 0;
- AP4_Array<AP4_Position> chunk_offsets;
-
- // process all the samples
- bool all_samples_are_sync = false;
- AP4_Cardinal sample_count = GetSampleCount();
- for (AP4_Ordinal i=0; i<sample_count; i++) {
- AP4_Sample sample;
- GetSample(i, sample);
-
- // update DTS table
- AP4_UI32 new_duration = sample.GetDuration();
- if (new_duration != current_duration && current_duration_run != 0) {
- // emit a new stts entry
- stts->AddEntry(current_duration_run, current_duration);
-
- // reset the run count
- current_duration_run = 0;
- }
- ++current_duration_run;
- current_duration = new_duration;
-
- // update CTS table
- AP4_UI32 new_cts_delta = sample.GetCtsDelta();
- if (new_cts_delta != current_cts_delta && current_cts_delta_run != 0) {
- // create a ctts atom if we don't have one
- if (ctts == NULL) ctts = new AP4_CttsAtom();
-
- //emit a new ctts entry
- ctts->AddEntry(current_cts_delta_run, current_cts_delta);
-
- // reset the run count
- current_cts_delta_run = 0;
- }
- ++current_cts_delta_run;
- current_cts_delta = new_cts_delta;
-
- // add an entry into the stsz atom
- stsz->AddEntry(sample.GetSize());
-
- // update the sync sample table
- if (sample.IsSync()) {
- stss->AddEntry(i+1);
- if (i==0) all_samples_are_sync = true;
- } else {
- all_samples_are_sync = false;
- }
-
- // see in which chunk this sample is
- AP4_Ordinal chunk_index = 0;
- AP4_Ordinal position_in_chunk = 0;
- AP4_Result result = GetSampleChunkPosition(i, chunk_index, position_in_chunk);
- if (AP4_SUCCEEDED(result)) {
- if (chunk_index != current_chunk_index && current_samples_in_chunk != 0) {
- // new chunk
- chunk_offsets.Append(current_chunk_offset);
- current_chunk_offset += current_chunk_size;
-
- stsc->AddEntry(1,
- current_samples_in_chunk,
- current_sample_description_index+1);
-
- current_samples_in_chunk = 0;
- current_chunk_size = 0;
- }
- current_chunk_index = chunk_index;
- }
-
- // store the sample description index
- current_sample_description_index = sample.GetDescriptionIndex();
-
- // adjust the current chunk info
- current_chunk_size += sample.GetSize();
- ++current_samples_in_chunk;
- }
-
- // finish the stts table
- stts->AddEntry(current_duration_run, current_duration);
-
- // finish the ctts table if we have one
- if (ctts) {
- AP4_ASSERT(current_cts_delta_run != 0);
-
- // add a ctts entry
- ctts->AddEntry(current_cts_delta_run, current_cts_delta);
- }
-
- // process any unfinished chunk
- if (current_samples_in_chunk != 0) {
- // new chunk
- chunk_offsets.Append(current_chunk_offset);
- stsc->AddEntry(1,
- current_samples_in_chunk,
- current_sample_description_index+1);
- }
-
- // attach the children of stbl
- stbl->AddChild(stsd);
- stbl->AddChild(stsz);
- stbl->AddChild(stsc);
- stbl->AddChild(stts);
- if (ctts) stbl->AddChild(ctts);
- if (!all_samples_are_sync && stss->GetEntries().ItemCount() != 0) {
- stbl->AddChild(stss);
- } else {
- delete stss;
- }
-
- // see if we need a co64 or an stco atom
- AP4_Size chunk_count = chunk_offsets.ItemCount();
- if (current_chunk_offset <= 0xFFFFFFFF) {
- // make an array of 32-bit entries
- AP4_UI32* chunk_offsets_32 = new AP4_UI32[chunk_count];
- for (unsigned int i=0; i<chunk_count; i++) {
- chunk_offsets_32[i] = (AP4_UI32)chunk_offsets[i];
- }
- // create the stco atom
- AP4_StcoAtom* stco = new AP4_StcoAtom(&chunk_offsets_32[0], chunk_count);
- stbl->AddChild(stco);
-
- delete[] chunk_offsets_32;
- } else {
- // create the co64 atom
- AP4_Co64Atom* co64 = new AP4_Co64Atom(&chunk_offsets[0], chunk_count);
- stbl->AddChild(co64);
- }
-
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - Sample Table Interface
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4SampleTable.h"
+#include "Ap4ContainerAtom.h"
+#include "Ap4StsdAtom.h"
+#include "Ap4StszAtom.h"
+#include "Ap4StscAtom.h"
+#include "Ap4StcoAtom.h"
+#include "Ap4Co64Atom.h"
+#include "Ap4SttsAtom.h"
+#include "Ap4StssAtom.h"
+#include "Ap4CttsAtom.h"
+#include "Ap4Sample.h"
+
+/*----------------------------------------------------------------------
+| AP4_SampleTable Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_SampleTable)
+
+/*----------------------------------------------------------------------
+| AP4_SampleTable::GenerateStblAtom
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SampleTable::GenerateStblAtom(AP4_ContainerAtom*& stbl)
+{
+ // create the stbl container
+ stbl = new AP4_ContainerAtom(AP4_ATOM_TYPE_STBL);
+
+ // create the stsd atom
+ AP4_StsdAtom* stsd = new AP4_StsdAtom(this);
+
+ // create the stsz atom
+ AP4_StszAtom* stsz = new AP4_StszAtom();
+
+ // create the stsc atom
+ AP4_StscAtom* stsc = new AP4_StscAtom();
+
+ // create the stts atom
+ AP4_SttsAtom* stts = new AP4_SttsAtom();
+
+ // create the stss atom
+ AP4_StssAtom* stss = new AP4_StssAtom();
+
+ // declare the ctts atom (may be created later)
+ AP4_CttsAtom* ctts = NULL;
+
+ // start chunk table
+ AP4_Ordinal current_chunk_index = 0;
+ AP4_Size current_chunk_size = 0;
+ AP4_Position current_chunk_offset = 0;
+ AP4_Cardinal current_samples_in_chunk = 0;
+ AP4_Ordinal current_sample_description_index = 0;
+ AP4_UI32 current_duration = 0;
+ AP4_Cardinal current_duration_run = 0;
+ AP4_UI32 current_cts_delta = 0;
+ AP4_Cardinal current_cts_delta_run = 0;
+ AP4_Array<AP4_Position> chunk_offsets;
+
+ // process all the samples
+ bool all_samples_are_sync = false;
+ AP4_Cardinal sample_count = GetSampleCount();
+ for (AP4_Ordinal i=0; i<sample_count; i++) {
+ AP4_Sample sample;
+ GetSample(i, sample);
+
+ // update DTS table
+ AP4_UI32 new_duration = sample.GetDuration();
+ if (new_duration != current_duration && current_duration_run != 0) {
+ // emit a new stts entry
+ stts->AddEntry(current_duration_run, current_duration);
+
+ // reset the run count
+ current_duration_run = 0;
+ }
+ ++current_duration_run;
+ current_duration = new_duration;
+
+ // update CTS table
+ AP4_UI32 new_cts_delta = sample.GetCtsDelta();
+ if (new_cts_delta != current_cts_delta && current_cts_delta_run != 0) {
+ // create a ctts atom if we don't have one
+ if (ctts == NULL) ctts = new AP4_CttsAtom();
+
+ //emit a new ctts entry
+ ctts->AddEntry(current_cts_delta_run, current_cts_delta);
+
+ // reset the run count
+ current_cts_delta_run = 0;
+ }
+ ++current_cts_delta_run;
+ current_cts_delta = new_cts_delta;
+
+ // add an entry into the stsz atom
+ stsz->AddEntry(sample.GetSize());
+
+ // update the sync sample table
+ if (sample.IsSync()) {
+ stss->AddEntry(i+1);
+ if (i==0) all_samples_are_sync = true;
+ } else {
+ all_samples_are_sync = false;
+ }
+
+ // see in which chunk this sample is
+ AP4_Ordinal chunk_index = 0;
+ AP4_Ordinal position_in_chunk = 0;
+ AP4_Result result = GetSampleChunkPosition(i, chunk_index, position_in_chunk);
+ if (AP4_SUCCEEDED(result)) {
+ if (chunk_index != current_chunk_index && current_samples_in_chunk != 0) {
+ // new chunk
+ chunk_offsets.Append(current_chunk_offset);
+ current_chunk_offset += current_chunk_size;
+
+ stsc->AddEntry(1,
+ current_samples_in_chunk,
+ current_sample_description_index+1);
+
+ current_samples_in_chunk = 0;
+ current_chunk_size = 0;
+ }
+ current_chunk_index = chunk_index;
+ }
+
+ // store the sample description index
+ current_sample_description_index = sample.GetDescriptionIndex();
+
+ // adjust the current chunk info
+ current_chunk_size += sample.GetSize();
+ ++current_samples_in_chunk;
+ }
+
+ // finish the stts table
+ stts->AddEntry(current_duration_run, current_duration);
+
+ // finish the ctts table if we have one
+ if (ctts) {
+ AP4_ASSERT(current_cts_delta_run != 0);
+
+ // add a ctts entry
+ ctts->AddEntry(current_cts_delta_run, current_cts_delta);
+ }
+
+ // process any unfinished chunk
+ if (current_samples_in_chunk != 0) {
+ // new chunk
+ chunk_offsets.Append(current_chunk_offset);
+ stsc->AddEntry(1,
+ current_samples_in_chunk,
+ current_sample_description_index+1);
+ }
+
+ // attach the children of stbl
+ stbl->AddChild(stsd);
+ stbl->AddChild(stsz);
+ stbl->AddChild(stsc);
+ stbl->AddChild(stts);
+ if (ctts) stbl->AddChild(ctts);
+ if (!all_samples_are_sync && stss->GetEntries().ItemCount() != 0) {
+ stbl->AddChild(stss);
+ } else {
+ delete stss;
+ }
+
+ // see if we need a co64 or an stco atom
+ AP4_Size chunk_count = chunk_offsets.ItemCount();
+ if (current_chunk_offset <= 0xFFFFFFFF) {
+ // make an array of 32-bit entries
+ AP4_UI32* chunk_offsets_32 = new AP4_UI32[chunk_count];
+ for (unsigned int i=0; i<chunk_count; i++) {
+ chunk_offsets_32[i] = (AP4_UI32)chunk_offsets[i];
+ }
+ // create the stco atom
+ AP4_StcoAtom* stco = new AP4_StcoAtom(&chunk_offsets_32[0], chunk_count);
+ stbl->AddChild(stco);
+
+ delete[] chunk_offsets_32;
+ } else {
+ // create the co64 atom
+ AP4_Co64Atom* co64 = new AP4_Co64Atom(&chunk_offsets[0], chunk_count);
+ stbl->AddChild(co64);
+ }
+
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.h
index 45a6c7bb0..27cf7fbb6 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SampleTable.h
@@ -33,6 +33,7 @@
| includes
+---------------------------------------------------------------------*/
#include "Ap4Types.h"
+#include "Ap4DynamicCast.h"
/*----------------------------------------------------------------------
| class references
@@ -46,6 +47,8 @@ class AP4_SampleDescription;
+---------------------------------------------------------------------*/
class AP4_SampleTable {
public:
+ AP4_IMPLEMENT_DYNAMIC_CAST(AP4_SampleTable)
+
// constructors and destructor
virtual ~AP4_SampleTable() {};
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StscAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StscAtom.h
index 23def43b7..2333f5d1d 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StscAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StscAtom.h
@@ -97,9 +97,9 @@ public:
virtual AP4_Result WriteFields(AP4_ByteStream& stream);
// ==> Start patch MPC
- // FIXME
- friend class AP4_AtomSampleTable;
- // <== End patch MPC
+ // FIXME
+ friend class AP4_AtomSampleTable;
+ // <== End patch MPC
private:
// methods
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StsdAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StsdAtom.cpp
index 3ce86da1b..d7ce0f0bc 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StsdAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StsdAtom.cpp
@@ -1,222 +1,222 @@
-/*****************************************************************
-|
-| AP4 - stsd Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4StsdAtom.h"
-#include "Ap4AtomFactory.h"
-#include "Ap4Utils.h"
-#include "Ap4SampleEntry.h"
-#include "Ap4SampleTable.h"
-#include "Ap4SampleDescription.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_StsdAtom)
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::Create
-+---------------------------------------------------------------------*/
-AP4_StsdAtom*
-AP4_StsdAtom::Create(AP4_Size size,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version != 0) return NULL;
- return new AP4_StsdAtom(size, version, flags, stream, atom_factory);
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::AP4_StsdAtom
-+---------------------------------------------------------------------*/
-AP4_StsdAtom::AP4_StsdAtom(AP4_SampleTable* sample_table) :
- AP4_ContainerAtom(AP4_ATOM_TYPE_STSD, (AP4_UI32)0, (AP4_UI32)0)
-{
- m_Size32 += 4;
- AP4_Cardinal sample_description_count = sample_table->GetSampleDescriptionCount();
- m_SampleDescriptions.EnsureCapacity(sample_description_count);
- for (AP4_Ordinal i=0; i<sample_description_count; i++) {
- // clear the cache entry
- m_SampleDescriptions.Append(NULL);
-
- // create an entry for the description
- AP4_SampleDescription* sample_description = sample_table->GetSampleDescription(i);
- AP4_Atom* entry = sample_description->ToAtom();
- m_Children.Add(entry);
-
- // update the size
- m_Size32 += (AP4_UI32)entry->GetSize();
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::AP4_StsdAtom
-+---------------------------------------------------------------------*/
-AP4_StsdAtom::AP4_StsdAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream,
- AP4_AtomFactory& atom_factory) :
- AP4_ContainerAtom(AP4_ATOM_TYPE_STSD, size, false, version, flags)
-{
- // read the number of entries
- AP4_UI32 entry_count;
- stream.ReadUI32(entry_count);
-
- // save and switch the factory's context
- atom_factory.PushContext(m_Type);
-
- // read all entries
- AP4_LargeSize bytes_available = size-AP4_FULL_ATOM_HEADER_SIZE-4;
- for (unsigned int i=0; i<entry_count; i++) {
- AP4_Atom* atom;
- if (AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(stream,
- bytes_available,
- atom))) {
- atom->SetParent(this);
- m_Children.Add(atom);
- }
- }
-
- // restore the saved context
- atom_factory.PopContext();
-
- // initialize the sample description cache
- m_SampleDescriptions.EnsureCapacity(m_Children.ItemCount());
- for (AP4_Ordinal i=0; i<m_Children.ItemCount(); i++) {
- m_SampleDescriptions.Append(NULL);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::~AP4_StsdAtom
-+---------------------------------------------------------------------*/
-AP4_StsdAtom::~AP4_StsdAtom()
-{
- for (AP4_Ordinal i=0; i<m_SampleDescriptions.ItemCount(); i++) {
- delete m_SampleDescriptions[i];
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_StsdAtom::WriteFields(AP4_ByteStream& stream)
-{
- AP4_Result result;
-
- // entry count
- result = stream.WriteUI32(m_Children.ItemCount());
- if (AP4_FAILED(result)) return result;
-
- // entries
- return m_Children.Apply(AP4_AtomListWriter(stream));
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::OnChildChanged
-+---------------------------------------------------------------------*/
-void
-AP4_StsdAtom::OnChildChanged(AP4_Atom*)
-{
- // remcompute our size
- AP4_UI64 size = GetHeaderSize()+4;
- m_Children.Apply(AP4_AtomSizeAdder(size));
- m_Size32 = (AP4_UI32)size;
-
- // update our parent
- if (m_Parent) m_Parent->OnChildChanged(this);
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::GetSampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_StsdAtom::GetSampleDescription(AP4_Ordinal index)
-{
- // check index
- if (index >= m_Children.ItemCount()) return NULL;
-
- // return the description if we already have it in the internal table
- if (m_SampleDescriptions[index]) return m_SampleDescriptions[index];
-
- // create and cache a sample description for this entry
- AP4_Atom* entry;
- m_Children.Get(index, entry);
- AP4_SampleEntry* sample_entry = AP4_DYNAMIC_CAST(AP4_SampleEntry, entry);
- if (sample_entry == NULL) {
- m_SampleDescriptions[index] = new AP4_UnknownSampleDescription(entry);
- } else {
- m_SampleDescriptions[index] = sample_entry->ToSampleDescription();
- }
- return m_SampleDescriptions[index];
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::GetSampleEntry
-+---------------------------------------------------------------------*/
-AP4_SampleEntry*
-AP4_StsdAtom::GetSampleEntry(AP4_Ordinal index)
-{
- // check index
- if (index >= m_Children.ItemCount()) return NULL;
-
- // return the sample entry
- AP4_Atom* entry;
- m_Children.Get(index, entry);
- return AP4_DYNAMIC_CAST(AP4_SampleEntry, entry);
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::GetSampleDescriptionCount
-+---------------------------------------------------------------------*/
-AP4_Cardinal
-AP4_StsdAtom::GetSampleDescriptionCount()
-{
- return m_Children.ItemCount();
-}
-
-/*----------------------------------------------------------------------
-| AP4_StsdAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_StsdAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("entry-count", m_Children.ItemCount());
-
- // inspect children
- m_Children.Apply(AP4_AtomListInspector(inspector));
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - stsd Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4StsdAtom.h"
+#include "Ap4AtomFactory.h"
+#include "Ap4Utils.h"
+#include "Ap4SampleEntry.h"
+#include "Ap4SampleTable.h"
+#include "Ap4SampleDescription.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_StsdAtom)
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::Create
++---------------------------------------------------------------------*/
+AP4_StsdAtom*
+AP4_StsdAtom::Create(AP4_Size size,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version != 0) return NULL;
+ return new AP4_StsdAtom(size, version, flags, stream, atom_factory);
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::AP4_StsdAtom
++---------------------------------------------------------------------*/
+AP4_StsdAtom::AP4_StsdAtom(AP4_SampleTable* sample_table) :
+ AP4_ContainerAtom(AP4_ATOM_TYPE_STSD, (AP4_UI32)0, (AP4_UI32)0)
+{
+ m_Size32 += 4;
+ AP4_Cardinal sample_description_count = sample_table->GetSampleDescriptionCount();
+ m_SampleDescriptions.EnsureCapacity(sample_description_count);
+ for (AP4_Ordinal i=0; i<sample_description_count; i++) {
+ // clear the cache entry
+ m_SampleDescriptions.Append(NULL);
+
+ // create an entry for the description
+ AP4_SampleDescription* sample_description = sample_table->GetSampleDescription(i);
+ AP4_Atom* entry = sample_description->ToAtom();
+ m_Children.Add(entry);
+
+ // update the size
+ m_Size32 += (AP4_UI32)entry->GetSize();
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::AP4_StsdAtom
++---------------------------------------------------------------------*/
+AP4_StsdAtom::AP4_StsdAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream,
+ AP4_AtomFactory& atom_factory) :
+ AP4_ContainerAtom(AP4_ATOM_TYPE_STSD, size, false, version, flags)
+{
+ // read the number of entries
+ AP4_UI32 entry_count;
+ stream.ReadUI32(entry_count);
+
+ // save and switch the factory's context
+ atom_factory.PushContext(m_Type);
+
+ // read all entries
+ AP4_LargeSize bytes_available = size-AP4_FULL_ATOM_HEADER_SIZE-4;
+ for (unsigned int i=0; i<entry_count; i++) {
+ AP4_Atom* atom;
+ if (AP4_SUCCEEDED(atom_factory.CreateAtomFromStream(stream,
+ bytes_available,
+ atom))) {
+ atom->SetParent(this);
+ m_Children.Add(atom);
+ }
+ }
+
+ // restore the saved context
+ atom_factory.PopContext();
+
+ // initialize the sample description cache
+ m_SampleDescriptions.EnsureCapacity(m_Children.ItemCount());
+ for (AP4_Ordinal i=0; i<m_Children.ItemCount(); i++) {
+ m_SampleDescriptions.Append(NULL);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::~AP4_StsdAtom
++---------------------------------------------------------------------*/
+AP4_StsdAtom::~AP4_StsdAtom()
+{
+ for (AP4_Ordinal i=0; i<m_SampleDescriptions.ItemCount(); i++) {
+ delete m_SampleDescriptions[i];
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_StsdAtom::WriteFields(AP4_ByteStream& stream)
+{
+ AP4_Result result;
+
+ // entry count
+ result = stream.WriteUI32(m_Children.ItemCount());
+ if (AP4_FAILED(result)) return result;
+
+ // entries
+ return m_Children.Apply(AP4_AtomListWriter(stream));
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::OnChildChanged
++---------------------------------------------------------------------*/
+void
+AP4_StsdAtom::OnChildChanged(AP4_Atom*)
+{
+ // remcompute our size
+ AP4_UI64 size = GetHeaderSize()+4;
+ m_Children.Apply(AP4_AtomSizeAdder(size));
+ m_Size32 = (AP4_UI32)size;
+
+ // update our parent
+ if (m_Parent) m_Parent->OnChildChanged(this);
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::GetSampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_StsdAtom::GetSampleDescription(AP4_Ordinal index)
+{
+ // check index
+ if (index >= m_Children.ItemCount()) return NULL;
+
+ // return the description if we already have it in the internal table
+ if (m_SampleDescriptions[index]) return m_SampleDescriptions[index];
+
+ // create and cache a sample description for this entry
+ AP4_Atom* entry;
+ m_Children.Get(index, entry);
+ AP4_SampleEntry* sample_entry = AP4_DYNAMIC_CAST(AP4_SampleEntry, entry);
+ if (sample_entry == NULL) {
+ m_SampleDescriptions[index] = new AP4_UnknownSampleDescription(entry);
+ } else {
+ m_SampleDescriptions[index] = sample_entry->ToSampleDescription();
+ }
+ return m_SampleDescriptions[index];
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::GetSampleEntry
++---------------------------------------------------------------------*/
+AP4_SampleEntry*
+AP4_StsdAtom::GetSampleEntry(AP4_Ordinal index)
+{
+ // check index
+ if (index >= m_Children.ItemCount()) return NULL;
+
+ // return the sample entry
+ AP4_Atom* entry;
+ m_Children.Get(index, entry);
+ return AP4_DYNAMIC_CAST(AP4_SampleEntry, entry);
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::GetSampleDescriptionCount
++---------------------------------------------------------------------*/
+AP4_Cardinal
+AP4_StsdAtom::GetSampleDescriptionCount()
+{
+ return m_Children.ItemCount();
+}
+
+/*----------------------------------------------------------------------
+| AP4_StsdAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_StsdAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("entry-count", m_Children.ItemCount());
+
+ // inspect children
+ m_Children.Apply(AP4_AtomListInspector(inspector));
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StszAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StszAtom.h
index 70bfa9309..d41cf4073 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StszAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4StszAtom.h
@@ -68,9 +68,9 @@ public:
virtual AP4_Result AddEntry(AP4_UI32 size);
// ==> Start patch MPC
- // FIXME
- friend class AP4_AtomSampleTable;
- // <== End patch MPC
+ // FIXME
+ friend class AP4_AtomSampleTable;
+ // <== End patch MPC
private:
// methods
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SttsAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SttsAtom.h
index def7acc37..7d65096b6 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SttsAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SttsAtom.h
@@ -73,9 +73,9 @@ public:
virtual AP4_Result WriteFields(AP4_ByteStream& stream);
// ==> Start patch MPC
- // FIXME
- friend class AP4_AtomSampleTable;
- // <== End patch MPC
+ // FIXME
+ friend class AP4_AtomSampleTable;
+ // <== End patch MPC
private:
// methods
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.cpp
index b2926e4ac..6eb74faa1 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.cpp
@@ -1,228 +1,228 @@
-/*****************************************************************
-|
-| AP4 - Synthetic Sample Table
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4Atom.h"
-#include "Ap4SyntheticSampleTable.h"
-#include "Ap4Sample.h"
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::AP4_SyntheticSampleTable()
-+---------------------------------------------------------------------*/
-AP4_SyntheticSampleTable::AP4_SyntheticSampleTable(AP4_Cardinal chunk_size) :
- m_ChunkSize(chunk_size?chunk_size:AP4_SYNTHETIC_SAMPLE_TABLE_DEFAULT_CHUNK_SIZE)
-{
- m_LookupCache.m_Sample = 0;
- m_LookupCache.m_Chunk = 0;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::~AP4_SyntheticSampleTable()
-+---------------------------------------------------------------------*/
-AP4_SyntheticSampleTable::~AP4_SyntheticSampleTable()
-{
- m_SampleDescriptions.DeleteReferences();
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::GetSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SyntheticSampleTable::GetSample(AP4_Ordinal sample_index, AP4_Sample& sample)
-{
- if (sample_index >= m_Samples.ItemCount()) return AP4_ERROR_OUT_OF_RANGE;
-
- sample = m_Samples[sample_index];
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::GetSampleCount
-+---------------------------------------------------------------------*/
-AP4_Cardinal
-AP4_SyntheticSampleTable::GetSampleCount()
-{
- return m_Samples.ItemCount();
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::GetSampleChunkPosition
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SyntheticSampleTable::GetSampleChunkPosition(
- AP4_Ordinal sample_index,
- AP4_Ordinal& chunk_index,
- AP4_Ordinal& position_in_chunk)
-{
- // default values
- chunk_index = 0;
- position_in_chunk = 0;
-
- // check parameters
- if (sample_index >= m_Samples.ItemCount()) return AP4_ERROR_OUT_OF_RANGE;
-
- // look for the chunk
- AP4_Ordinal sample_cursor = 0;
- AP4_Ordinal chunk_cursor = 0;
- if (sample_index >= m_LookupCache.m_Sample) {
- sample_cursor = m_LookupCache.m_Sample;
- chunk_cursor = m_LookupCache.m_Chunk;
- }
- for (;
- chunk_cursor < m_SamplesInChunk.ItemCount();
- sample_cursor += m_SamplesInChunk[chunk_cursor++]) {
- if (sample_cursor+m_SamplesInChunk[chunk_cursor] > sample_index) {
- chunk_index = chunk_cursor;
- position_in_chunk = sample_index-sample_cursor;
- m_LookupCache.m_Sample = sample_cursor;
- m_LookupCache.m_Chunk = chunk_cursor;
- return AP4_SUCCESS;
- }
- }
-
- return AP4_ERROR_OUT_OF_RANGE;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::GetSampleDescriptionCount
-+---------------------------------------------------------------------*/
-AP4_Cardinal
-AP4_SyntheticSampleTable::GetSampleDescriptionCount()
-{
- return m_SampleDescriptions.ItemCount();
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::GetSampleDescription
-+---------------------------------------------------------------------*/
-AP4_SampleDescription*
-AP4_SyntheticSampleTable::GetSampleDescription(AP4_Ordinal index)
-{
- SampleDescriptionHolder* holder;
- if (AP4_SUCCEEDED(m_SampleDescriptions.Get(index, holder))) {
- return holder->m_SampleDescription;
- } else {
- return NULL;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::AddSampleDescription
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SyntheticSampleTable::AddSampleDescription(AP4_SampleDescription* description,
- bool transfer_ownership)
-{
- return m_SampleDescriptions.Add(new SampleDescriptionHolder(description, transfer_ownership));
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::AddSample
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SyntheticSampleTable::AddSample(AP4_ByteStream& data_stream,
- AP4_Position offset,
- AP4_Size size,
- AP4_UI32 duration,
- AP4_Ordinal description_index,
- AP4_UI64 dts,
- AP4_UI32 cts_delta,
- bool sync)
-{
- // decide if we need to start a new chunk or increment the last one
- if (m_SamplesInChunk.ItemCount() == 0 ||
- m_SamplesInChunk[m_SamplesInChunk.ItemCount()-1] >= m_ChunkSize ||
- m_Samples.ItemCount() == 0 ||
- m_Samples[m_Samples.ItemCount()-1].GetDescriptionIndex() != description_index) {
- m_SamplesInChunk.Append(1);
- } else {
- ++m_SamplesInChunk[m_SamplesInChunk.ItemCount()-1];
- }
-
- // compute the timestamps
- if (m_Samples.ItemCount() > 0) {
- AP4_Sample* prev_sample = &m_Samples[m_Samples.ItemCount()-1];
- if (dts == 0) {
- if (prev_sample->GetDuration() == 0) {
- // can't compute the DTS for this sample
- return AP4_ERROR_INVALID_PARAMETERS;
- }
- dts = prev_sample->GetDts()+prev_sample->GetDuration();
- } else {
- if (prev_sample->GetDuration() == 0) {
- // update the previous sample
- if (dts <= prev_sample->GetDts()) return AP4_ERROR_INVALID_PARAMETERS;
- prev_sample->SetDuration((AP4_UI32)(dts-prev_sample->GetDts()));
- } else {
- if (dts != prev_sample->GetDts()+prev_sample->GetDuration()) {
- // mismatch
- return AP4_ERROR_INVALID_PARAMETERS;
- }
- }
- }
- }
-
- // add the sample to the table
- AP4_Sample sample(data_stream, offset, size, duration, description_index, dts, cts_delta, sync);
- return m_Samples.Append(sample);
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::GetSampleIndexForTimeStamp
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SyntheticSampleTable::GetSampleIndexForTimeStamp(AP4_UI64 /* ts */,
- AP4_Ordinal& /* index */)
-{
- return AP4_ERROR_NOT_SUPPORTED;
-}
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable::GetNearestSyncSampleIndex
-+---------------------------------------------------------------------*/
-AP4_Ordinal
-AP4_SyntheticSampleTable::GetNearestSyncSampleIndex(AP4_Ordinal sample_index, bool before)
-{
- if (before) {
- for (int i=sample_index; i>=0; i--) {
- if (m_Samples[i].IsSync()) return i;
- }
- // not found?
- return 0;
- } else {
- AP4_Cardinal entry_count = m_Samples.ItemCount();
- for (unsigned int i=sample_index; i<entry_count; i++) {
- if (m_Samples[i].IsSync()) return i;
- }
- // not found?
- return m_Samples.ItemCount();
- }
-}
+/*****************************************************************
+|
+| AP4 - Synthetic Sample Table
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4Atom.h"
+#include "Ap4SyntheticSampleTable.h"
+#include "Ap4Sample.h"
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::AP4_SyntheticSampleTable()
++---------------------------------------------------------------------*/
+AP4_SyntheticSampleTable::AP4_SyntheticSampleTable(AP4_Cardinal chunk_size) :
+ m_ChunkSize(chunk_size?chunk_size:AP4_SYNTHETIC_SAMPLE_TABLE_DEFAULT_CHUNK_SIZE)
+{
+ m_LookupCache.m_Sample = 0;
+ m_LookupCache.m_Chunk = 0;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::~AP4_SyntheticSampleTable()
++---------------------------------------------------------------------*/
+AP4_SyntheticSampleTable::~AP4_SyntheticSampleTable()
+{
+ m_SampleDescriptions.DeleteReferences();
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::GetSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SyntheticSampleTable::GetSample(AP4_Ordinal sample_index, AP4_Sample& sample)
+{
+ if (sample_index >= m_Samples.ItemCount()) return AP4_ERROR_OUT_OF_RANGE;
+
+ sample = m_Samples[sample_index];
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::GetSampleCount
++---------------------------------------------------------------------*/
+AP4_Cardinal
+AP4_SyntheticSampleTable::GetSampleCount()
+{
+ return m_Samples.ItemCount();
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::GetSampleChunkPosition
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SyntheticSampleTable::GetSampleChunkPosition(
+ AP4_Ordinal sample_index,
+ AP4_Ordinal& chunk_index,
+ AP4_Ordinal& position_in_chunk)
+{
+ // default values
+ chunk_index = 0;
+ position_in_chunk = 0;
+
+ // check parameters
+ if (sample_index >= m_Samples.ItemCount()) return AP4_ERROR_OUT_OF_RANGE;
+
+ // look for the chunk
+ AP4_Ordinal sample_cursor = 0;
+ AP4_Ordinal chunk_cursor = 0;
+ if (sample_index >= m_LookupCache.m_Sample) {
+ sample_cursor = m_LookupCache.m_Sample;
+ chunk_cursor = m_LookupCache.m_Chunk;
+ }
+ for (;
+ chunk_cursor < m_SamplesInChunk.ItemCount();
+ sample_cursor += m_SamplesInChunk[chunk_cursor++]) {
+ if (sample_cursor+m_SamplesInChunk[chunk_cursor] > sample_index) {
+ chunk_index = chunk_cursor;
+ position_in_chunk = sample_index-sample_cursor;
+ m_LookupCache.m_Sample = sample_cursor;
+ m_LookupCache.m_Chunk = chunk_cursor;
+ return AP4_SUCCESS;
+ }
+ }
+
+ return AP4_ERROR_OUT_OF_RANGE;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::GetSampleDescriptionCount
++---------------------------------------------------------------------*/
+AP4_Cardinal
+AP4_SyntheticSampleTable::GetSampleDescriptionCount()
+{
+ return m_SampleDescriptions.ItemCount();
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::GetSampleDescription
++---------------------------------------------------------------------*/
+AP4_SampleDescription*
+AP4_SyntheticSampleTable::GetSampleDescription(AP4_Ordinal index)
+{
+ SampleDescriptionHolder* holder;
+ if (AP4_SUCCEEDED(m_SampleDescriptions.Get(index, holder))) {
+ return holder->m_SampleDescription;
+ } else {
+ return NULL;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::AddSampleDescription
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SyntheticSampleTable::AddSampleDescription(AP4_SampleDescription* description,
+ bool transfer_ownership)
+{
+ return m_SampleDescriptions.Add(new SampleDescriptionHolder(description, transfer_ownership));
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::AddSample
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SyntheticSampleTable::AddSample(AP4_ByteStream& data_stream,
+ AP4_Position offset,
+ AP4_Size size,
+ AP4_UI32 duration,
+ AP4_Ordinal description_index,
+ AP4_UI64 dts,
+ AP4_UI32 cts_delta,
+ bool sync)
+{
+ // decide if we need to start a new chunk or increment the last one
+ if (m_SamplesInChunk.ItemCount() == 0 ||
+ m_SamplesInChunk[m_SamplesInChunk.ItemCount()-1] >= m_ChunkSize ||
+ m_Samples.ItemCount() == 0 ||
+ m_Samples[m_Samples.ItemCount()-1].GetDescriptionIndex() != description_index) {
+ m_SamplesInChunk.Append(1);
+ } else {
+ ++m_SamplesInChunk[m_SamplesInChunk.ItemCount()-1];
+ }
+
+ // compute the timestamps
+ if (m_Samples.ItemCount() > 0) {
+ AP4_Sample* prev_sample = &m_Samples[m_Samples.ItemCount()-1];
+ if (dts == 0) {
+ if (prev_sample->GetDuration() == 0) {
+ // can't compute the DTS for this sample
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+ dts = prev_sample->GetDts()+prev_sample->GetDuration();
+ } else {
+ if (prev_sample->GetDuration() == 0) {
+ // update the previous sample
+ if (dts <= prev_sample->GetDts()) return AP4_ERROR_INVALID_PARAMETERS;
+ prev_sample->SetDuration((AP4_UI32)(dts-prev_sample->GetDts()));
+ } else {
+ if (dts != prev_sample->GetDts()+prev_sample->GetDuration()) {
+ // mismatch
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+ }
+ }
+ }
+
+ // add the sample to the table
+ AP4_Sample sample(data_stream, offset, size, duration, description_index, dts, cts_delta, sync);
+ return m_Samples.Append(sample);
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::GetSampleIndexForTimeStamp
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SyntheticSampleTable::GetSampleIndexForTimeStamp(AP4_UI64 /* ts */,
+ AP4_Ordinal& /* index */)
+{
+ return AP4_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable::GetNearestSyncSampleIndex
++---------------------------------------------------------------------*/
+AP4_Ordinal
+AP4_SyntheticSampleTable::GetNearestSyncSampleIndex(AP4_Ordinal sample_index, bool before)
+{
+ if (before) {
+ for (int i=sample_index; i>=0; i--) {
+ if (m_Samples[i].IsSync()) return i;
+ }
+ // not found?
+ return 0;
+ } else {
+ AP4_Cardinal entry_count = m_Samples.ItemCount();
+ for (unsigned int i=sample_index; i<entry_count; i++) {
+ if (m_Samples[i].IsSync()) return i;
+ }
+ // not found?
+ return m_Samples.ItemCount();
+ }
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.h
index e54d9074d..6994aba77 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4SyntheticSampleTable.h
@@ -1,144 +1,144 @@
-/*****************************************************************
-|
-| AP4 - Synthetic Sample Table
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_SYNTHETIC_SAMPLE_TABLE_H_
-#define _AP4_SYNTHETIC_SAMPLE_TABLE_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Array.h"
-#include "Ap4List.h"
-#include "Ap4Sample.h"
-#include "Ap4SampleTable.h"
-#include "Ap4SampleDescription.h"
-
-/*----------------------------------------------------------------------
-| forward declarations
-+---------------------------------------------------------------------*/
-class AP4_ByteStream;
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_Cardinal AP4_SYNTHETIC_SAMPLE_TABLE_DEFAULT_CHUNK_SIZE = 10;
-
-/*----------------------------------------------------------------------
-| AP4_SyntheticSampleTable
-+---------------------------------------------------------------------*/
-class AP4_SyntheticSampleTable : public AP4_SampleTable
-{
- public:
- // methods
- AP4_SyntheticSampleTable(AP4_Cardinal chunk_size
- = AP4_SYNTHETIC_SAMPLE_TABLE_DEFAULT_CHUNK_SIZE);
- virtual ~AP4_SyntheticSampleTable();
-
- // AP4_SampleTable methods
- virtual AP4_Result GetSample(AP4_Ordinal index, AP4_Sample& sample);
- virtual AP4_Cardinal GetSampleCount();
- virtual AP4_Result GetSampleChunkPosition(AP4_Ordinal sample_index,
- AP4_Ordinal& chunk_index,
- AP4_Ordinal& position_in_chunk);
- virtual AP4_Cardinal GetSampleDescriptionCount();
- virtual AP4_SampleDescription* GetSampleDescription(AP4_Ordinal index);
- virtual AP4_Result GetSampleIndexForTimeStamp(AP4_UI64 ts, AP4_Ordinal& index);
- virtual AP4_Ordinal GetNearestSyncSampleIndex(AP4_Ordinal index, bool before);
-
- // methods
- /**
- * Add a sample description to the sample table.
- * Each added sample description will have the next available index, starting at 0
- *
- * @param description Pointer to the sample description to add
- * @param transfer_ownership Boolean flag indicating whether the ownership of the
- * sample description object is transfered to the sample table object (true by default).
- * If true, the sample table object will own the sample description object, and will
- * delete it when it is itself deleted. If false, the ownership remains with the caller,
- * and only a referencing pointer is kept, thus the caller must ensure that the object
- * is not deleted before the sample table is deleted.
- */
- virtual AP4_Result AddSampleDescription(AP4_SampleDescription* description,
- bool transfer_ownership=true);
-
- /**
- * Add a sample to the sample table, where the sample duration is given
- *
- * @param data_stream The byte stream that contains the sample data. The sample
- * object added to the track will keep a reference to that byte stream.
- * @param offset Position of the first byte of sample data within the stream
- * @param size Size in bytes of the sample data
- * @param duration Duration of the sample (in the timescale of the media). This
- * value can be 0 if the duration is not known. In that case, the next sample
- * added to the table MUST have a non-zero value for the DTS (decoding timestamp),
- * which will allow the actual duration of this sample to be computed.
- * @param description_index Index of the sample description that applies to
- * this sample (typically 0).
- * @param dts DTS (decoding timestamp) of the sample. If this value is 0, and there
- * already are samples in the table, the DTS of the sample will be automatically
- * computed based on the DTS and duration of the preceding sample. If this value is
- * not equal to the DTS+duration of the preceding sample, the duration of the
- * preceding sample is automatically adjusted, unless it has a non-zero value, in which
- * case AP4_ERROR_INVALID_PARAMETERS is returned.
- * The DTS of the first sample in the table MUST always be 0.
- * @param cts_delta Difference between the CTS (composition/display timestamp) and DTS
- * (decoding timestamp) of the sample (in the timescale of the media)
- * @param sync Boolean flag indicating whether this is a sync sample or not.
- */
- virtual AP4_Result AddSample(AP4_ByteStream& data_stream,
- AP4_Position offset,
- AP4_Size size,
- AP4_UI32 duration,
- AP4_Ordinal description_index,
- AP4_UI64 dts,
- AP4_UI32 cts_delta,
- bool sync);
-
-private:
- // classes
- class SampleDescriptionHolder {
- public:
- SampleDescriptionHolder(AP4_SampleDescription* description, bool is_owned) :
- m_SampleDescription(description), m_IsOwned(is_owned) {}
- ~SampleDescriptionHolder() { if (m_IsOwned) delete m_SampleDescription; }
- AP4_SampleDescription* m_SampleDescription;
- bool m_IsOwned;
- };
-
- // members
- AP4_Array<AP4_Sample> m_Samples;
- AP4_List<SampleDescriptionHolder> m_SampleDescriptions;
- AP4_Cardinal m_ChunkSize;
- AP4_Array<AP4_UI32> m_SamplesInChunk;
- struct {
- AP4_Ordinal m_Sample;
- AP4_Ordinal m_Chunk;
- } m_LookupCache;
-};
-
-#endif // _AP4_SYNTHETIC_SAMPLE_TABLE_H_
+/*****************************************************************
+|
+| AP4 - Synthetic Sample Table
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_SYNTHETIC_SAMPLE_TABLE_H_
+#define _AP4_SYNTHETIC_SAMPLE_TABLE_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Array.h"
+#include "Ap4List.h"
+#include "Ap4Sample.h"
+#include "Ap4SampleTable.h"
+#include "Ap4SampleDescription.h"
+
+/*----------------------------------------------------------------------
+| forward declarations
++---------------------------------------------------------------------*/
+class AP4_ByteStream;
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_Cardinal AP4_SYNTHETIC_SAMPLE_TABLE_DEFAULT_CHUNK_SIZE = 10;
+
+/*----------------------------------------------------------------------
+| AP4_SyntheticSampleTable
++---------------------------------------------------------------------*/
+class AP4_SyntheticSampleTable : public AP4_SampleTable
+{
+ public:
+ // methods
+ AP4_SyntheticSampleTable(AP4_Cardinal chunk_size
+ = AP4_SYNTHETIC_SAMPLE_TABLE_DEFAULT_CHUNK_SIZE);
+ virtual ~AP4_SyntheticSampleTable();
+
+ // AP4_SampleTable methods
+ virtual AP4_Result GetSample(AP4_Ordinal index, AP4_Sample& sample);
+ virtual AP4_Cardinal GetSampleCount();
+ virtual AP4_Result GetSampleChunkPosition(AP4_Ordinal sample_index,
+ AP4_Ordinal& chunk_index,
+ AP4_Ordinal& position_in_chunk);
+ virtual AP4_Cardinal GetSampleDescriptionCount();
+ virtual AP4_SampleDescription* GetSampleDescription(AP4_Ordinal index);
+ virtual AP4_Result GetSampleIndexForTimeStamp(AP4_UI64 ts, AP4_Ordinal& index);
+ virtual AP4_Ordinal GetNearestSyncSampleIndex(AP4_Ordinal index, bool before);
+
+ // methods
+ /**
+ * Add a sample description to the sample table.
+ * Each added sample description will have the next available index, starting at 0
+ *
+ * @param description Pointer to the sample description to add
+ * @param transfer_ownership Boolean flag indicating whether the ownership of the
+ * sample description object is transfered to the sample table object (true by default).
+ * If true, the sample table object will own the sample description object, and will
+ * delete it when it is itself deleted. If false, the ownership remains with the caller,
+ * and only a referencing pointer is kept, thus the caller must ensure that the object
+ * is not deleted before the sample table is deleted.
+ */
+ virtual AP4_Result AddSampleDescription(AP4_SampleDescription* description,
+ bool transfer_ownership=true);
+
+ /**
+ * Add a sample to the sample table, where the sample duration is given
+ *
+ * @param data_stream The byte stream that contains the sample data. The sample
+ * object added to the track will keep a reference to that byte stream.
+ * @param offset Position of the first byte of sample data within the stream
+ * @param size Size in bytes of the sample data
+ * @param duration Duration of the sample (in the timescale of the media). This
+ * value can be 0 if the duration is not known. In that case, the next sample
+ * added to the table MUST have a non-zero value for the DTS (decoding timestamp),
+ * which will allow the actual duration of this sample to be computed.
+ * @param description_index Index of the sample description that applies to
+ * this sample (typically 0).
+ * @param dts DTS (decoding timestamp) of the sample. If this value is 0, and there
+ * already are samples in the table, the DTS of the sample will be automatically
+ * computed based on the DTS and duration of the preceding sample. If this value is
+ * not equal to the DTS+duration of the preceding sample, the duration of the
+ * preceding sample is automatically adjusted, unless it has a non-zero value, in which
+ * case AP4_ERROR_INVALID_PARAMETERS is returned.
+ * The DTS of the first sample in the table MUST always be 0.
+ * @param cts_delta Difference between the CTS (composition/display timestamp) and DTS
+ * (decoding timestamp) of the sample (in the timescale of the media)
+ * @param sync Boolean flag indicating whether this is a sync sample or not.
+ */
+ virtual AP4_Result AddSample(AP4_ByteStream& data_stream,
+ AP4_Position offset,
+ AP4_Size size,
+ AP4_UI32 duration,
+ AP4_Ordinal description_index,
+ AP4_UI64 dts,
+ AP4_UI32 cts_delta,
+ bool sync);
+
+private:
+ // classes
+ class SampleDescriptionHolder {
+ public:
+ SampleDescriptionHolder(AP4_SampleDescription* description, bool is_owned) :
+ m_SampleDescription(description), m_IsOwned(is_owned) {}
+ ~SampleDescriptionHolder() { if (m_IsOwned) delete m_SampleDescription; }
+ AP4_SampleDescription* m_SampleDescription;
+ bool m_IsOwned;
+ };
+
+ // members
+ AP4_Array<AP4_Sample> m_Samples;
+ AP4_List<SampleDescriptionHolder> m_SampleDescriptions;
+ AP4_Cardinal m_ChunkSize;
+ AP4_Array<AP4_UI32> m_SamplesInChunk;
+ struct {
+ AP4_Ordinal m_Sample;
+ AP4_Ordinal m_Chunk;
+ } m_LookupCache;
+};
+
+#endif // _AP4_SYNTHETIC_SAMPLE_TABLE_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.cpp
index 678e6ccb3..5747e2786 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.cpp
@@ -1,174 +1,174 @@
-/*****************************************************************
-|
-| AP4 - tfhd Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4TfhdAtom.h"
-#include "Ap4Utils.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_TfhdAtom)
-
-/*----------------------------------------------------------------------
-| AP4_TfhdAtom::Create
-+---------------------------------------------------------------------*/
-AP4_TfhdAtom*
-AP4_TfhdAtom::Create(AP4_Size size, AP4_ByteStream& stream)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version > 0) return NULL;
- if (size != ComputeSize(flags)) return NULL;
- return new AP4_TfhdAtom(size, version, flags, stream);
-}
-
-/*----------------------------------------------------------------------
-| AP4_TfhdAtom::ComputeSize
-+---------------------------------------------------------------------*/
-AP4_UI32
-AP4_TfhdAtom::ComputeSize(AP4_UI32 flags)
-{
- AP4_UI32 size = AP4_FULL_ATOM_HEADER_SIZE+4;
- if (flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) size += 8;
- if (flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) size += 4;
- if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) size += 4;
- if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) size += 4;
- if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) size += 4;
- return size;
-}
-
-/*----------------------------------------------------------------------
-| AP4_TfhdAtom::AP4_TfhdAtom
-+---------------------------------------------------------------------*/
-AP4_TfhdAtom::AP4_TfhdAtom(AP4_UI32 flags,
- AP4_UI32 track_id,
- AP4_UI64 base_data_offset,
- AP4_UI32 sample_description_index,
- AP4_UI32 default_sample_duration,
- AP4_UI32 default_sample_size,
- AP4_UI32 default_sample_flags) :
- AP4_Atom(AP4_ATOM_TYPE_TFHD, ComputeSize(flags), 0, flags),
- m_TrackId(track_id),
- m_BaseDataOffset(base_data_offset),
- m_SampleDescriptionIndex(sample_description_index),
- m_DefaultSampleDuration(default_sample_duration),
- m_DefaultSampleSize(default_sample_size),
- m_DefaultSampleFlags(default_sample_flags)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_TfhdAtom::AP4_TfhdAtom
-+---------------------------------------------------------------------*/
-AP4_TfhdAtom::AP4_TfhdAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream) :
- AP4_Atom(AP4_ATOM_TYPE_TFHD, size, version, flags)
-{
- stream.ReadUI32(m_TrackId);
- if (flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) {
- stream.ReadUI64(m_BaseDataOffset);
- }
- if (flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) {
- stream.ReadUI32(m_SampleDescriptionIndex);
- }
- if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) {
- stream.ReadUI32(m_DefaultSampleDuration);
- }
- if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) {
- stream.ReadUI32(m_DefaultSampleSize);
- }
- if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) {
- stream.ReadUI32(m_DefaultSampleFlags);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_TfhdAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_TfhdAtom::WriteFields(AP4_ByteStream& stream)
-{
- AP4_Result result;
-
- result = stream.WriteUI32(m_TrackId);
- if (AP4_FAILED(result)) return result;
- if (m_Flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) {
- result = stream.WriteUI64(m_BaseDataOffset);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) {
- result = stream.WriteUI32(m_SampleDescriptionIndex);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) {
- stream.WriteUI32(m_DefaultSampleDuration);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) {
- stream.WriteUI32(m_DefaultSampleSize);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) {
- stream.WriteUI32(m_DefaultSampleFlags);
- if (AP4_FAILED(result)) return result;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_TfhdAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_TfhdAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("track ID", m_TrackId);
- if (m_Flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) {
- inspector.AddField("base data offset", m_BaseDataOffset);
- }
- if (m_Flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) {
- inspector.AddField("sample description index", m_SampleDescriptionIndex);
- }
- if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) {
- inspector.AddField("default sample duration", m_DefaultSampleDuration);
- }
- if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) {
- inspector.AddField("default sample size", m_DefaultSampleSize);
- }
- if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) {
- inspector.AddField("default sample flags", m_DefaultSampleFlags, AP4_AtomInspector::HINT_HEX );
- }
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - tfhd Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4TfhdAtom.h"
+#include "Ap4Utils.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_TfhdAtom)
+
+/*----------------------------------------------------------------------
+| AP4_TfhdAtom::Create
++---------------------------------------------------------------------*/
+AP4_TfhdAtom*
+AP4_TfhdAtom::Create(AP4_Size size, AP4_ByteStream& stream)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version > 0) return NULL;
+ if (size != ComputeSize(flags)) return NULL;
+ return new AP4_TfhdAtom(size, version, flags, stream);
+}
+
+/*----------------------------------------------------------------------
+| AP4_TfhdAtom::ComputeSize
++---------------------------------------------------------------------*/
+AP4_UI32
+AP4_TfhdAtom::ComputeSize(AP4_UI32 flags)
+{
+ AP4_UI32 size = AP4_FULL_ATOM_HEADER_SIZE+4;
+ if (flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) size += 8;
+ if (flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) size += 4;
+ if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) size += 4;
+ if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) size += 4;
+ if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) size += 4;
+ return size;
+}
+
+/*----------------------------------------------------------------------
+| AP4_TfhdAtom::AP4_TfhdAtom
++---------------------------------------------------------------------*/
+AP4_TfhdAtom::AP4_TfhdAtom(AP4_UI32 flags,
+ AP4_UI32 track_id,
+ AP4_UI64 base_data_offset,
+ AP4_UI32 sample_description_index,
+ AP4_UI32 default_sample_duration,
+ AP4_UI32 default_sample_size,
+ AP4_UI32 default_sample_flags) :
+ AP4_Atom(AP4_ATOM_TYPE_TFHD, ComputeSize(flags), 0, flags),
+ m_TrackId(track_id),
+ m_BaseDataOffset(base_data_offset),
+ m_SampleDescriptionIndex(sample_description_index),
+ m_DefaultSampleDuration(default_sample_duration),
+ m_DefaultSampleSize(default_sample_size),
+ m_DefaultSampleFlags(default_sample_flags)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_TfhdAtom::AP4_TfhdAtom
++---------------------------------------------------------------------*/
+AP4_TfhdAtom::AP4_TfhdAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream) :
+ AP4_Atom(AP4_ATOM_TYPE_TFHD, size, version, flags)
+{
+ stream.ReadUI32(m_TrackId);
+ if (flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) {
+ stream.ReadUI64(m_BaseDataOffset);
+ }
+ if (flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) {
+ stream.ReadUI32(m_SampleDescriptionIndex);
+ }
+ if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) {
+ stream.ReadUI32(m_DefaultSampleDuration);
+ }
+ if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) {
+ stream.ReadUI32(m_DefaultSampleSize);
+ }
+ if (flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) {
+ stream.ReadUI32(m_DefaultSampleFlags);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_TfhdAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_TfhdAtom::WriteFields(AP4_ByteStream& stream)
+{
+ AP4_Result result;
+
+ result = stream.WriteUI32(m_TrackId);
+ if (AP4_FAILED(result)) return result;
+ if (m_Flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) {
+ result = stream.WriteUI64(m_BaseDataOffset);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) {
+ result = stream.WriteUI32(m_SampleDescriptionIndex);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) {
+ stream.WriteUI32(m_DefaultSampleDuration);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) {
+ stream.WriteUI32(m_DefaultSampleSize);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) {
+ stream.WriteUI32(m_DefaultSampleFlags);
+ if (AP4_FAILED(result)) return result;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_TfhdAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_TfhdAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("track ID", m_TrackId);
+ if (m_Flags & AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT) {
+ inspector.AddField("base data offset", m_BaseDataOffset);
+ }
+ if (m_Flags & AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT) {
+ inspector.AddField("sample description index", m_SampleDescriptionIndex);
+ }
+ if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT) {
+ inspector.AddField("default sample duration", m_DefaultSampleDuration);
+ }
+ if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT) {
+ inspector.AddField("default sample size", m_DefaultSampleSize);
+ }
+ if (m_Flags & AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT) {
+ inspector.AddField("default sample flags", m_DefaultSampleFlags, AP4_AtomInspector::HINT_HEX );
+ }
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.h
index db0d3f777..fd459894a 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfhdAtom.h
@@ -1,99 +1,99 @@
-/*****************************************************************
-|
-| AP4 - tfhd Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_TFHD_ATOM_H_
-#define _AP4_TFHD_ATOM_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Atom.h"
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_UI32 AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT = 0x00001;
-const AP4_UI32 AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT = 0x00002;
-const AP4_UI32 AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT = 0x00008;
-const AP4_UI32 AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT = 0x00010;
-const AP4_UI32 AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT = 0x00020;
-const AP4_UI32 AP4_TFHD_FLAG_DURATION_IS_EMPTY = 0x10000;
-
-/*----------------------------------------------------------------------
-| AP4_TfhdAtom
-+---------------------------------------------------------------------*/
-class AP4_TfhdAtom : public AP4_Atom
-{
-public:
- AP4_IMPLEMENT_DYNAMIC_CAST(AP4_TfhdAtom)
-
- // class methods
- static AP4_TfhdAtom* Create(AP4_Size size, AP4_ByteStream& stream);
- static AP4_UI32 ComputeSize(AP4_UI32 flags);
-
- // methods
- AP4_TfhdAtom(AP4_UI32 flags,
- AP4_UI32 track_id,
- AP4_UI64 base_data_offset,
- AP4_UI32 sample_description_index,
- AP4_UI32 default_sample_duration,
- AP4_UI32 default_sample_size,
- AP4_UI32 default_sample_flags);
- virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
- virtual AP4_Result WriteFields(AP4_ByteStream& stream);
-
- AP4_UI32 GetTrackId() { return m_TrackId; }
- void SetTrackId(AP4_UI32 track_id) { m_TrackId = track_id; }
- AP4_UI64 GetBaseDataOffset() { return m_BaseDataOffset; }
- void SetBaseDataOffset(AP4_UI64 offset) { m_BaseDataOffset = offset; }
- AP4_UI32 GetSampleDescriptionIndex() { return m_SampleDescriptionIndex; }
- void SetSampleDescriptionIndex(AP4_UI32 indx) { m_SampleDescriptionIndex = indx; }
- AP4_UI32 GetDefaultSampleDuration() { return m_DefaultSampleDuration; }
- void SetDefaultSampleDuration(AP4_UI32 duration) { m_DefaultSampleDuration = duration; }
- AP4_UI32 GetDefaultSampleSize() { return m_DefaultSampleSize; }
- void SetDefaultSampleSize(AP4_UI32 size) { m_DefaultSampleSize = size; }
- AP4_UI32 GetDefaultSampleFlags() { return m_DefaultSampleFlags; }
- void SetDefaultSampleFlags(AP4_UI32 flags) { m_DefaultSampleFlags = flags; }
-
-private:
- // methods
- AP4_TfhdAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream);
-
- // members
- AP4_UI32 m_TrackId;
- AP4_UI64 m_BaseDataOffset;
- AP4_UI32 m_SampleDescriptionIndex;
- AP4_UI32 m_DefaultSampleDuration;
- AP4_UI32 m_DefaultSampleSize;
- AP4_UI32 m_DefaultSampleFlags;
-};
-
-#endif // _AP4_TFHD_ATOM_H_
+/*****************************************************************
+|
+| AP4 - tfhd Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_TFHD_ATOM_H_
+#define _AP4_TFHD_ATOM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Atom.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_UI32 AP4_TFHD_FLAG_BASE_DATA_OFFSET_PRESENT = 0x00001;
+const AP4_UI32 AP4_TFHD_FLAG_SAMPLE_DESCRIPTION_INDEX_PRESENT = 0x00002;
+const AP4_UI32 AP4_TFHD_FLAG_DEFAULT_SAMPLE_DURATION_PRESENT = 0x00008;
+const AP4_UI32 AP4_TFHD_FLAG_DEFAULT_SAMPLE_SIZE_PRESENT = 0x00010;
+const AP4_UI32 AP4_TFHD_FLAG_DEFAULT_SAMPLE_FLAGS_PRESENT = 0x00020;
+const AP4_UI32 AP4_TFHD_FLAG_DURATION_IS_EMPTY = 0x10000;
+
+/*----------------------------------------------------------------------
+| AP4_TfhdAtom
++---------------------------------------------------------------------*/
+class AP4_TfhdAtom : public AP4_Atom
+{
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST(AP4_TfhdAtom)
+
+ // class methods
+ static AP4_TfhdAtom* Create(AP4_Size size, AP4_ByteStream& stream);
+ static AP4_UI32 ComputeSize(AP4_UI32 flags);
+
+ // methods
+ AP4_TfhdAtom(AP4_UI32 flags,
+ AP4_UI32 track_id,
+ AP4_UI64 base_data_offset,
+ AP4_UI32 sample_description_index,
+ AP4_UI32 default_sample_duration,
+ AP4_UI32 default_sample_size,
+ AP4_UI32 default_sample_flags);
+ virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
+ virtual AP4_Result WriteFields(AP4_ByteStream& stream);
+
+ AP4_UI32 GetTrackId() { return m_TrackId; }
+ void SetTrackId(AP4_UI32 track_id) { m_TrackId = track_id; }
+ AP4_UI64 GetBaseDataOffset() { return m_BaseDataOffset; }
+ void SetBaseDataOffset(AP4_UI64 offset) { m_BaseDataOffset = offset; }
+ AP4_UI32 GetSampleDescriptionIndex() { return m_SampleDescriptionIndex; }
+ void SetSampleDescriptionIndex(AP4_UI32 indx) { m_SampleDescriptionIndex = indx; }
+ AP4_UI32 GetDefaultSampleDuration() { return m_DefaultSampleDuration; }
+ void SetDefaultSampleDuration(AP4_UI32 duration) { m_DefaultSampleDuration = duration; }
+ AP4_UI32 GetDefaultSampleSize() { return m_DefaultSampleSize; }
+ void SetDefaultSampleSize(AP4_UI32 size) { m_DefaultSampleSize = size; }
+ AP4_UI32 GetDefaultSampleFlags() { return m_DefaultSampleFlags; }
+ void SetDefaultSampleFlags(AP4_UI32 flags) { m_DefaultSampleFlags = flags; }
+
+private:
+ // methods
+ AP4_TfhdAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream);
+
+ // members
+ AP4_UI32 m_TrackId;
+ AP4_UI64 m_BaseDataOffset;
+ AP4_UI32 m_SampleDescriptionIndex;
+ AP4_UI32 m_DefaultSampleDuration;
+ AP4_UI32 m_DefaultSampleSize;
+ AP4_UI32 m_DefaultSampleFlags;
+};
+
+#endif // _AP4_TFHD_ATOM_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.cpp
index 1c5437128..370247551 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.cpp
@@ -34,6 +34,11 @@
#include "Ap4Utils.h"
/*----------------------------------------------------------------------
+| AP4_TfraAtom Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_TfraAtom)
+
+/*----------------------------------------------------------------------
| AP4_TfraAtom::Create
+---------------------------------------------------------------------*/
AP4_TfraAtom*
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.h
index fc5f78495..6ae08a391 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TfraAtom.h
@@ -47,6 +47,8 @@ class AP4_ByteStream;
class AP4_TfraAtom : public AP4_Atom
{
public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_TfraAtom, AP4_Atom)
+
// types
struct Entry {
Entry() : m_Time(0), m_MoofOffset(0), m_TrafNumber(0), m_TrunNumber(0), m_SampleNumber(0) {}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.cpp
index 9dc915571..7748c71a8 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.cpp
@@ -215,7 +215,7 @@ AP4_Track::Clone(AP4_Result* result)
GetDuration(),
GetMediaTimeScale(),
GetMediaDuration(),
- GetTrackLanguage().GetChars(),
+ GetTrackLanguage(),
GetWidth(),
GetHeight());
@@ -449,11 +449,11 @@ AP4_Track::GetMediaDuration()
/*----------------------------------------------------------------------
| AP4_Track::GetTrackName
+---------------------------------------------------------------------*/
-const AP4_String
+const char*
AP4_Track::GetTrackName()
{
if (AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, m_TrakAtom->FindChild("mdia/hdlr"))) {
- return hdlr->GetHandlerName();
+ return hdlr->GetHandlerName().GetChars();
}
return NULL;
}
@@ -461,11 +461,11 @@ AP4_Track::GetTrackName()
/*----------------------------------------------------------------------
| AP4_Track::GetTrackLanguage
+---------------------------------------------------------------------*/
-const AP4_String
+const char*
AP4_Track::GetTrackLanguage()
{
if (AP4_MdhdAtom* mdhd = AP4_DYNAMIC_CAST(AP4_MdhdAtom, m_TrakAtom->FindChild("mdia/mdhd"))) {
- return mdhd->GetLanguage();
+ return mdhd->GetLanguage().GetChars();
}
return NULL;
}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.h
index 12b48560c..4c6588e53 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Track.h
@@ -128,8 +128,8 @@ class AP4_Track {
AP4_UI32 GetMovieTimeScale() { return m_MovieTimeScale; }
AP4_UI32 GetMediaTimeScale();
AP4_UI64 GetMediaDuration(); // in the timescale of the media
- const AP4_String GetTrackName();
- const AP4_String GetTrackLanguage();
+ const char* GetTrackName();
+ const char* GetTrackLanguage();
AP4_Result Attach(AP4_MoovAtom* moov);
protected:
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.cpp
index e7d4ffc71..98675a69b 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.cpp
@@ -1,243 +1,243 @@
-/*****************************************************************
-|
-| AP4 - trun Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4TrunAtom.h"
-#include "Ap4Utils.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_TrunAtom)
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom::Create
-+---------------------------------------------------------------------*/
-AP4_TrunAtom*
-AP4_TrunAtom::Create(AP4_Size size, AP4_ByteStream& stream)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version > 0) return NULL;
- return new AP4_TrunAtom(size, version, flags, stream);
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom::ComputeRecordFieldsCount
-+---------------------------------------------------------------------*/
-unsigned int
-AP4_TrunAtom::ComputeRecordFieldsCount(AP4_UI32 flags)
-{
- // count the number of bits set to 1 in the second byte of the flags
- unsigned int count = 0;
- for (unsigned int i=0; i<8; i++) {
- if (flags & (1<<(i+8))) ++count;
- }
- return count;
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom::ComputeOptionalFieldsCount
-+---------------------------------------------------------------------*/
-unsigned int
-AP4_TrunAtom::ComputeOptionalFieldsCount(AP4_UI32 flags)
-{
- // count the number of bits set to 1 in the LSB of the flags
- unsigned int count = 0;
- for (unsigned int i=0; i<8; i++) {
- if (flags & (1<<i)) ++count;
- }
- return count;
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom::AP4_TrunAtom
-+---------------------------------------------------------------------*/
-AP4_TrunAtom::AP4_TrunAtom(AP4_UI32 flags,
- AP4_SI32 data_offset,
- AP4_UI32 first_sample_flags) :
- AP4_Atom(AP4_ATOM_TYPE_TRUN, AP4_FULL_ATOM_HEADER_SIZE+4, 0, flags),
- m_DataOffset(data_offset),
- m_FirstSampleFlags(first_sample_flags)
-{
- m_Size32 += 4*ComputeOptionalFieldsCount(flags);
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom::AP4_TrunAtom
-+---------------------------------------------------------------------*/
-AP4_TrunAtom::AP4_TrunAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream) :
- AP4_Atom(AP4_ATOM_TYPE_TRUN, size, version, flags)
-{
- AP4_UI32 sample_count = 0;
- stream.ReadUI32(sample_count);
-
- // read optional fields
- int optional_fields_count = (int)ComputeOptionalFieldsCount(flags);
- if (flags & AP4_TRUN_FLAG_DATA_OFFSET_PRESENT) {
- AP4_UI32 offset = 0;
- stream.ReadUI32(offset);
- m_DataOffset = (AP4_SI32)offset;
- --optional_fields_count;
- }
- if (flags & AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) {
- stream.ReadUI32(m_FirstSampleFlags);
- --optional_fields_count;
- }
-
- // discard unknown optional fields
- for (int i=0; i<optional_fields_count; i++) {
- AP4_UI32 discard;
- stream.ReadUI32(discard);
- }
-
- int record_fields_count = (int)ComputeRecordFieldsCount(flags);
- m_Entries.SetItemCount(sample_count);
- for (unsigned int i=0; i<sample_count; i++) {
- if (flags & AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT) {
- stream.ReadUI32(m_Entries[i].sample_duration);
- --record_fields_count;
- }
- if (flags & AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT) {
- stream.ReadUI32(m_Entries[i].sample_size);
- --record_fields_count;
- }
- if (flags & AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT) {
- stream.ReadUI32(m_Entries[i].sample_flags);
- --record_fields_count;
- }
- if (flags & AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) {
- stream.ReadUI32(m_Entries[i].sample_composition_time_offset);
- --record_fields_count;
- }
-
- // skip unknown fields
- for (int j=0;j<record_fields_count; j++) {
- AP4_UI32 discard;
- stream.ReadUI32(discard);
- }
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_TrunAtom::WriteFields(AP4_ByteStream& stream)
-{
- AP4_Result result;
-
- result = stream.WriteUI32(m_Entries.ItemCount());
- if (AP4_FAILED(result)) return result;
- if (m_Flags & AP4_TRUN_FLAG_DATA_OFFSET_PRESENT) {
- result = stream.WriteUI32((AP4_UI32)m_DataOffset);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) {
- result = stream.WriteUI32(m_FirstSampleFlags);
- if (AP4_FAILED(result)) return result;
- }
- AP4_UI32 sample_count = m_Entries.ItemCount();
- for (unsigned int i=0; i<sample_count; i++) {
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT) {
- result = stream.WriteUI32(m_Entries[i].sample_duration);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT) {
- result = stream.WriteUI32(m_Entries[i].sample_size);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT) {
- result = stream.WriteUI32(m_Entries[i].sample_flags);
- if (AP4_FAILED(result)) return result;
- }
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) {
- stream.WriteUI32(m_Entries[i].sample_composition_time_offset);
- if (AP4_FAILED(result)) return result;
- }
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_TrunAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("sample count", m_Entries.ItemCount());
- if (m_Flags & AP4_TRUN_FLAG_DATA_OFFSET_PRESENT) {
- inspector.AddField("data offset", m_DataOffset);
- }
- if (m_Flags & AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) {
- inspector.AddField("first sample flags", m_FirstSampleFlags, AP4_AtomInspector::HINT_HEX);
- }
- if (inspector.GetVerbosity() >= 1) {
- AP4_UI32 sample_count = m_Entries.ItemCount();
- for (unsigned int i=0; i<sample_count; i++) {
- char header[32];
- AP4_FormatString(header, sizeof(header), "entry %04d", i);
- char v0[32];
- char v1[32];
- char v2[32];
- char v3[64];
- const char* s0 = "";
- const char* s1 = "";
- const char* s2 = "";
- const char* s3 = "";
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT) {
- AP4_FormatString(v0, sizeof(v0), "sample duration:%d", m_Entries[i].sample_duration);
- s0 = v0;
- }
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT) {
- AP4_FormatString(v1, sizeof(v1), "sample size:%d", m_Entries[i].sample_size);
- s1 = v1;
- }
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT) {
- AP4_FormatString(v2, sizeof(v2), "sample flags:%x", m_Entries[i].sample_flags);
- s2 = v2;
- }
- if (m_Flags & AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) {
- AP4_FormatString(v3, sizeof(v3), "sample composition time offset:%d", m_Entries[i].sample_composition_time_offset);
- s3 = v3;
- }
- char value[128];
- AP4_FormatString(value, sizeof(value), "%s %s %s %s", s0, s1, s2, s3);
- inspector.AddField(header, value);
- }
- }
-
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - trun Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4TrunAtom.h"
+#include "Ap4Utils.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_TrunAtom)
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom::Create
++---------------------------------------------------------------------*/
+AP4_TrunAtom*
+AP4_TrunAtom::Create(AP4_Size size, AP4_ByteStream& stream)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version > 0) return NULL;
+ return new AP4_TrunAtom(size, version, flags, stream);
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom::ComputeRecordFieldsCount
++---------------------------------------------------------------------*/
+unsigned int
+AP4_TrunAtom::ComputeRecordFieldsCount(AP4_UI32 flags)
+{
+ // count the number of bits set to 1 in the second byte of the flags
+ unsigned int count = 0;
+ for (unsigned int i=0; i<8; i++) {
+ if (flags & (1<<(i+8))) ++count;
+ }
+ return count;
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom::ComputeOptionalFieldsCount
++---------------------------------------------------------------------*/
+unsigned int
+AP4_TrunAtom::ComputeOptionalFieldsCount(AP4_UI32 flags)
+{
+ // count the number of bits set to 1 in the LSB of the flags
+ unsigned int count = 0;
+ for (unsigned int i=0; i<8; i++) {
+ if (flags & (1<<i)) ++count;
+ }
+ return count;
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom::AP4_TrunAtom
++---------------------------------------------------------------------*/
+AP4_TrunAtom::AP4_TrunAtom(AP4_UI32 flags,
+ AP4_SI32 data_offset,
+ AP4_UI32 first_sample_flags) :
+ AP4_Atom(AP4_ATOM_TYPE_TRUN, AP4_FULL_ATOM_HEADER_SIZE+4, 0, flags),
+ m_DataOffset(data_offset),
+ m_FirstSampleFlags(first_sample_flags)
+{
+ m_Size32 += 4*ComputeOptionalFieldsCount(flags);
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom::AP4_TrunAtom
++---------------------------------------------------------------------*/
+AP4_TrunAtom::AP4_TrunAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream) :
+ AP4_Atom(AP4_ATOM_TYPE_TRUN, size, version, flags)
+{
+ AP4_UI32 sample_count = 0;
+ stream.ReadUI32(sample_count);
+
+ // read optional fields
+ int optional_fields_count = (int)ComputeOptionalFieldsCount(flags);
+ if (flags & AP4_TRUN_FLAG_DATA_OFFSET_PRESENT) {
+ AP4_UI32 offset = 0;
+ stream.ReadUI32(offset);
+ m_DataOffset = (AP4_SI32)offset;
+ --optional_fields_count;
+ }
+ if (flags & AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) {
+ stream.ReadUI32(m_FirstSampleFlags);
+ --optional_fields_count;
+ }
+
+ // discard unknown optional fields
+ for (int i=0; i<optional_fields_count; i++) {
+ AP4_UI32 discard;
+ stream.ReadUI32(discard);
+ }
+
+ int record_fields_count = (int)ComputeRecordFieldsCount(flags);
+ m_Entries.SetItemCount(sample_count);
+ for (unsigned int i=0; i<sample_count; i++) {
+ if (flags & AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT) {
+ stream.ReadUI32(m_Entries[i].sample_duration);
+ --record_fields_count;
+ }
+ if (flags & AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT) {
+ stream.ReadUI32(m_Entries[i].sample_size);
+ --record_fields_count;
+ }
+ if (flags & AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT) {
+ stream.ReadUI32(m_Entries[i].sample_flags);
+ --record_fields_count;
+ }
+ if (flags & AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) {
+ stream.ReadUI32(m_Entries[i].sample_composition_time_offset);
+ --record_fields_count;
+ }
+
+ // skip unknown fields
+ for (int j=0;j<record_fields_count; j++) {
+ AP4_UI32 discard;
+ stream.ReadUI32(discard);
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_TrunAtom::WriteFields(AP4_ByteStream& stream)
+{
+ AP4_Result result;
+
+ result = stream.WriteUI32(m_Entries.ItemCount());
+ if (AP4_FAILED(result)) return result;
+ if (m_Flags & AP4_TRUN_FLAG_DATA_OFFSET_PRESENT) {
+ result = stream.WriteUI32((AP4_UI32)m_DataOffset);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) {
+ result = stream.WriteUI32(m_FirstSampleFlags);
+ if (AP4_FAILED(result)) return result;
+ }
+ AP4_UI32 sample_count = m_Entries.ItemCount();
+ for (unsigned int i=0; i<sample_count; i++) {
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT) {
+ result = stream.WriteUI32(m_Entries[i].sample_duration);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT) {
+ result = stream.WriteUI32(m_Entries[i].sample_size);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT) {
+ result = stream.WriteUI32(m_Entries[i].sample_flags);
+ if (AP4_FAILED(result)) return result;
+ }
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) {
+ stream.WriteUI32(m_Entries[i].sample_composition_time_offset);
+ if (AP4_FAILED(result)) return result;
+ }
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_TrunAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("sample count", m_Entries.ItemCount());
+ if (m_Flags & AP4_TRUN_FLAG_DATA_OFFSET_PRESENT) {
+ inspector.AddField("data offset", m_DataOffset);
+ }
+ if (m_Flags & AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT) {
+ inspector.AddField("first sample flags", m_FirstSampleFlags, AP4_AtomInspector::HINT_HEX);
+ }
+ if (inspector.GetVerbosity() >= 1) {
+ AP4_UI32 sample_count = m_Entries.ItemCount();
+ for (unsigned int i=0; i<sample_count; i++) {
+ char header[32];
+ AP4_FormatString(header, sizeof(header), "entry %04d", i);
+ char v0[32];
+ char v1[32];
+ char v2[32];
+ char v3[64];
+ const char* s0 = "";
+ const char* s1 = "";
+ const char* s2 = "";
+ const char* s3 = "";
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT) {
+ AP4_FormatString(v0, sizeof(v0), "sample duration:%d", m_Entries[i].sample_duration);
+ s0 = v0;
+ }
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT) {
+ AP4_FormatString(v1, sizeof(v1), "sample size:%d", m_Entries[i].sample_size);
+ s1 = v1;
+ }
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT) {
+ AP4_FormatString(v2, sizeof(v2), "sample flags:%x", m_Entries[i].sample_flags);
+ s2 = v2;
+ }
+ if (m_Flags & AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT) {
+ AP4_FormatString(v3, sizeof(v3), "sample composition time offset:%d", m_Entries[i].sample_composition_time_offset);
+ s3 = v3;
+ }
+ char value[128];
+ AP4_FormatString(value, sizeof(value), "%s %s %s %s", s0, s1, s2, s3);
+ inspector.AddField(header, value);
+ }
+ }
+
+ return AP4_SUCCESS;
+}
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.h
index 9bdc382b3..d4f88d269 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4TrunAtom.h
@@ -1,95 +1,95 @@
-/*****************************************************************
-|
-| AP4 - trun Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_TRUN_ATOM_H_
-#define _AP4_TRUN_ATOM_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Atom.h"
-#include "Ap4Array.h"
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_UI32 AP4_TRUN_FLAG_DATA_OFFSET_PRESENT = 0x0001;
-const AP4_UI32 AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT = 0x0004;
-const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT = 0x0100;
-const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT = 0x0200;
-const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT = 0x0400;
-const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT = 0x0800;
-
-/*----------------------------------------------------------------------
-| AP4_TrunAtom
-+---------------------------------------------------------------------*/
-class AP4_TrunAtom : public AP4_Atom
-{
-public:
- AP4_IMPLEMENT_DYNAMIC_CAST(AP4_TrunAtom)
-
- // types
- struct Entry {
- Entry() : sample_duration(0), sample_size(0), sample_flags(0), sample_composition_time_offset(0) {}
- AP4_UI32 sample_duration;
- AP4_UI32 sample_size;
- AP4_UI32 sample_flags;
- AP4_UI32 sample_composition_time_offset;
- };
-
- // class methods
- static AP4_TrunAtom* Create(AP4_Size size, AP4_ByteStream& stream);
- static unsigned int ComputeOptionalFieldsCount(AP4_UI32 flags);
- static unsigned int ComputeRecordFieldsCount(AP4_UI32 flags);
-
- // methods
- AP4_TrunAtom(AP4_UI32 flags,
- AP4_SI32 data_offset,
- AP4_UI32 first_sample_flags);
- virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
- virtual AP4_Result WriteFields(AP4_ByteStream& stream);
-
- // accessors
- AP4_SI32 GetDataOffset() { return m_DataOffset; }
- AP4_UI32 GetFirstSampleFlags() { return m_FirstSampleFlags; }
- const AP4_Array<Entry>& GetEntries() { return m_Entries; }
-
-private:
- // methods
- AP4_TrunAtom(AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream);
-
- // members
- AP4_SI32 m_DataOffset;
- AP4_UI32 m_FirstSampleFlags;
- AP4_Array<Entry> m_Entries;
-};
-
-#endif // _AP4_TRUN_ATOM_H_
+/*****************************************************************
+|
+| AP4 - trun Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_TRUN_ATOM_H_
+#define _AP4_TRUN_ATOM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Atom.h"
+#include "Ap4Array.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_UI32 AP4_TRUN_FLAG_DATA_OFFSET_PRESENT = 0x0001;
+const AP4_UI32 AP4_TRUN_FLAG_FIRST_SAMPLE_FLAGS_PRESENT = 0x0004;
+const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_DURATION_PRESENT = 0x0100;
+const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_SIZE_PRESENT = 0x0200;
+const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_FLAGS_PRESENT = 0x0400;
+const AP4_UI32 AP4_TRUN_FLAG_SAMPLE_COMPOSITION_TIME_OFFSET_PRESENT = 0x0800;
+
+/*----------------------------------------------------------------------
+| AP4_TrunAtom
++---------------------------------------------------------------------*/
+class AP4_TrunAtom : public AP4_Atom
+{
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST(AP4_TrunAtom)
+
+ // types
+ struct Entry {
+ Entry() : sample_duration(0), sample_size(0), sample_flags(0), sample_composition_time_offset(0) {}
+ AP4_UI32 sample_duration;
+ AP4_UI32 sample_size;
+ AP4_UI32 sample_flags;
+ AP4_UI32 sample_composition_time_offset;
+ };
+
+ // class methods
+ static AP4_TrunAtom* Create(AP4_Size size, AP4_ByteStream& stream);
+ static unsigned int ComputeOptionalFieldsCount(AP4_UI32 flags);
+ static unsigned int ComputeRecordFieldsCount(AP4_UI32 flags);
+
+ // methods
+ AP4_TrunAtom(AP4_UI32 flags,
+ AP4_SI32 data_offset,
+ AP4_UI32 first_sample_flags);
+ virtual AP4_Result InspectFields(AP4_AtomInspector& inspector);
+ virtual AP4_Result WriteFields(AP4_ByteStream& stream);
+
+ // accessors
+ AP4_SI32 GetDataOffset() { return m_DataOffset; }
+ AP4_UI32 GetFirstSampleFlags() { return m_FirstSampleFlags; }
+ const AP4_Array<Entry>& GetEntries() { return m_Entries; }
+
+private:
+ // methods
+ AP4_TrunAtom(AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream);
+
+ // members
+ AP4_SI32 m_DataOffset;
+ AP4_UI32 m_FirstSampleFlags;
+ AP4_Array<Entry> m_Entries;
+};
+
+#endif // _AP4_TRUN_ATOM_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Types.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Types.h
index 86409c337..ef7ee8ed7 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Types.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Types.h
@@ -47,8 +47,8 @@ typedef signed int AP4_SI32;
typedef unsigned short AP4_UI16;
typedef signed short AP4_SI16;
typedef unsigned char AP4_UI08;
-typedef unsigned char AP4_Byte;
-typedef unsigned long AP4_Size;
+typedef AP4_UI08 AP4_Byte;
+typedef AP4_UI32 AP4_Size;
// the rest depends on whether the platform supports 64-bit integers
#if defined(AP4_CONFIG_HAVE_INT64)
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.cpp
index ef7834a3c..a8f332366 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.cpp
@@ -1,266 +1,266 @@
-/*****************************************************************
-|
-| AP4 - Utilities
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Utils.h"
-
-/*----------------------------------------------------------------------
-| AP4_BytesToDoubleBE
-+---------------------------------------------------------------------*/
-double
-AP4_BytesToDoubleBE(const unsigned char* bytes)
-{
- AP4_UI64 i_value = AP4_BytesToUInt64BE(bytes);
- void* v_value = reinterpret_cast<void*>(&i_value);
- double* d_value = reinterpret_cast<double*>(v_value);
-
- return *d_value;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesToUInt64BE
-+---------------------------------------------------------------------*/
-AP4_UI64
-AP4_BytesToUInt64BE(const unsigned char* bytes)
-{
- return
- ( ((AP4_UI64)bytes[0])<<56 ) |
- ( ((AP4_UI64)bytes[1])<<48 ) |
- ( ((AP4_UI64)bytes[2])<<40 ) |
- ( ((AP4_UI64)bytes[3])<<32 ) |
- ( ((AP4_UI64)bytes[4])<<24 ) |
- ( ((AP4_UI64)bytes[5])<<16 ) |
- ( ((AP4_UI64)bytes[6])<<8 ) |
- ( ((AP4_UI64)bytes[7]) );
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesFromDoubleBE
-+---------------------------------------------------------------------*/
-void
-AP4_BytesFromDoubleBE(unsigned char* bytes, double value)
-{
- void* v_value = reinterpret_cast<void*>(&value);
- AP4_UI64* i_value = reinterpret_cast<AP4_UI64*>(v_value);
-
- AP4_BytesFromUInt64BE(bytes, *i_value);
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesFromUInt64BE
-+---------------------------------------------------------------------*/
-void
-AP4_BytesFromUInt64BE(unsigned char* bytes, AP4_UI64 value)
-{
- bytes[0] = (unsigned char)(value >> 56);
- bytes[1] = (unsigned char)(value >> 48);
- bytes[2] = (unsigned char)(value >> 40);
- bytes[3] = (unsigned char)(value >> 32);
- bytes[4] = (unsigned char)(value >> 24);
- bytes[5] = (unsigned char)(value >> 16);
- bytes[6] = (unsigned char)(value >> 8);
- bytes[7] = (unsigned char)(value );
-}
-
-/*----------------------------------------------------------------------
-| AP4_DurationMsFromUnits
-+---------------------------------------------------------------------*/
-AP4_UI32
-AP4_DurationMsFromUnits(AP4_UI64 units, AP4_UI32 units_per_second)
-{
- if (units_per_second == 0) return 0;
- return (AP4_UI32)(((double)units*1000.0)/(double)units_per_second);
-}
-
-/*----------------------------------------------------------------------
-| AP4_ConvertTime
-+---------------------------------------------------------------------*/
-AP4_UI64
-AP4_ConvertTime(AP4_UI64 time_value,
- AP4_UI32 from_time_scale,
- AP4_UI32 to_time_scale)
-{
- if (from_time_scale == 0) return 0;
- double ratio = (double)to_time_scale/(double)from_time_scale;
- return ((AP4_UI64)((double)time_value*ratio));
-}
-
-/*----------------------------------------------------------------------
-| AP4_FormatFourChars
-+---------------------------------------------------------------------*/
-void
-AP4_FormatFourChars(char* str, AP4_UI32 value) {
- str[0] = (value >> 24) & 0xFF;
- str[1] = (value >> 16) & 0xFF;
- str[2] = (value >> 8) & 0xFF;
- str[3] = (value ) & 0xFF;
- str[4] = '\0';
-}
-
-/*----------------------------------------------------------------------
-| AP4_FormatFourCharsPrintable
-+---------------------------------------------------------------------*/
-void
-AP4_FormatFourCharsPrintable(char* str, AP4_UI32 value) {
- AP4_FormatFourChars(str, value);
- for (int i=0; i<4; i++) {
- if (str[i]<' ' || str[i] >= 127) {
- str[i] = '.';
- }
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_SplitArgs
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SplitArgs(char* arg, char*& arg0, char*& arg1)
-{
- arg0 = arg;
- char* c = arg;
- while (*c != 0 && *c != ':') {
- c++;
- }
- if (*c == ':') {
- *c++ = '\0';
- arg1 = c;
- return AP4_SUCCESS;
- } else {
- return AP4_FAILURE;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_SplitArgs
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_SplitArgs(char* arg, char*& arg0, char*& arg1, char*& arg2)
-{
- AP4_Result result = AP4_SplitArgs(arg, arg0, arg1);
- if (AP4_FAILED(result)) return result;
- return AP4_SplitArgs(arg1, arg1, arg2);
-}
-
-/*----------------------------------------------------------------------
-| AP4_HexNibble
-+---------------------------------------------------------------------*/
-unsigned char
-AP4_HexNibble(char c)
-{
- switch (c) {
- case '0': return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- case 'a': case 'A': return 10;
- case 'b': case 'B': return 11;
- case 'c': case 'C': return 12;
- case 'd': case 'D': return 13;
- case 'e': case 'E': return 14;
- case 'f': case 'F': return 15;
- default: return 0;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_NibbleHex
-+---------------------------------------------------------------------*/
-char
-AP4_NibbleHex(unsigned int nibble)
-{
- if (nibble < 10) {
- return '0'+nibble;
- } else if (nibble < 16) {
- return 'A'+(nibble-10);
- } else {
- return ' ';
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_ParseHex
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_ParseHex(const char* hex, unsigned char* bytes, unsigned int count)
-{
- if (AP4_StringLength(hex) != 2*count) return AP4_ERROR_INVALID_PARAMETERS;
- for (unsigned int i=0; i<count; i++) {
- bytes[i] = (AP4_HexNibble(hex[2*i]) << 4) | (AP4_HexNibble(hex[2*i+1]));
- }
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_FormatHex
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_FormatHex(const AP4_UI08* data, unsigned int data_size, char* hex)
-{
- for (unsigned int i=0; i<data_size; i++) {
- *hex++ = AP4_NibbleHex(data[i]>>4);
- *hex++ = AP4_NibbleHex(data[i]&0x0F);
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BitWriter::Write
-+---------------------------------------------------------------------*/
-void
-AP4_BitWriter::Write(AP4_UI32 bits, unsigned int bit_count)
-{
- unsigned char* data = m_Data;
- if (m_BitCount+bit_count > m_DataSize*8) return;
- data += m_BitCount/8;
- unsigned int space = 8-(m_BitCount%8);
- while (bit_count) {
- unsigned int mask = bit_count==32 ? 0xFFFFFFFF : ((1<<bit_count)-1);
- if (bit_count <= space) {
- *data |= ((bits&mask) << (space-bit_count));
- m_BitCount += bit_count;
- return;
- } else {
- *data |= ((bits&mask) >> (bit_count-space));
- ++data;
- m_BitCount += space;
- bit_count -= space;
- space = 8;
- }
- }
-}
-
-
+/*****************************************************************
+|
+| AP4 - Utilities
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Utils.h"
+
+/*----------------------------------------------------------------------
+| AP4_BytesToDoubleBE
++---------------------------------------------------------------------*/
+double
+AP4_BytesToDoubleBE(const unsigned char* bytes)
+{
+ AP4_UI64 i_value = AP4_BytesToUInt64BE(bytes);
+ void* v_value = reinterpret_cast<void*>(&i_value);
+ double* d_value = reinterpret_cast<double*>(v_value);
+
+ return *d_value;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesToUInt64BE
++---------------------------------------------------------------------*/
+AP4_UI64
+AP4_BytesToUInt64BE(const unsigned char* bytes)
+{
+ return
+ ( ((AP4_UI64)bytes[0])<<56 ) |
+ ( ((AP4_UI64)bytes[1])<<48 ) |
+ ( ((AP4_UI64)bytes[2])<<40 ) |
+ ( ((AP4_UI64)bytes[3])<<32 ) |
+ ( ((AP4_UI64)bytes[4])<<24 ) |
+ ( ((AP4_UI64)bytes[5])<<16 ) |
+ ( ((AP4_UI64)bytes[6])<<8 ) |
+ ( ((AP4_UI64)bytes[7]) );
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesFromDoubleBE
++---------------------------------------------------------------------*/
+void
+AP4_BytesFromDoubleBE(unsigned char* bytes, double value)
+{
+ void* v_value = reinterpret_cast<void*>(&value);
+ AP4_UI64* i_value = reinterpret_cast<AP4_UI64*>(v_value);
+
+ AP4_BytesFromUInt64BE(bytes, *i_value);
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesFromUInt64BE
++---------------------------------------------------------------------*/
+void
+AP4_BytesFromUInt64BE(unsigned char* bytes, AP4_UI64 value)
+{
+ bytes[0] = (unsigned char)(value >> 56);
+ bytes[1] = (unsigned char)(value >> 48);
+ bytes[2] = (unsigned char)(value >> 40);
+ bytes[3] = (unsigned char)(value >> 32);
+ bytes[4] = (unsigned char)(value >> 24);
+ bytes[5] = (unsigned char)(value >> 16);
+ bytes[6] = (unsigned char)(value >> 8);
+ bytes[7] = (unsigned char)(value );
+}
+
+/*----------------------------------------------------------------------
+| AP4_DurationMsFromUnits
++---------------------------------------------------------------------*/
+AP4_UI32
+AP4_DurationMsFromUnits(AP4_UI64 units, AP4_UI32 units_per_second)
+{
+ if (units_per_second == 0) return 0;
+ return (AP4_UI32)(((double)units*1000.0)/(double)units_per_second);
+}
+
+/*----------------------------------------------------------------------
+| AP4_ConvertTime
++---------------------------------------------------------------------*/
+AP4_UI64
+AP4_ConvertTime(AP4_UI64 time_value,
+ AP4_UI32 from_time_scale,
+ AP4_UI32 to_time_scale)
+{
+ if (from_time_scale == 0) return 0;
+ double ratio = (double)to_time_scale/(double)from_time_scale;
+ return ((AP4_UI64)((double)time_value*ratio));
+}
+
+/*----------------------------------------------------------------------
+| AP4_FormatFourChars
++---------------------------------------------------------------------*/
+void
+AP4_FormatFourChars(char* str, AP4_UI32 value) {
+ str[0] = (value >> 24) & 0xFF;
+ str[1] = (value >> 16) & 0xFF;
+ str[2] = (value >> 8) & 0xFF;
+ str[3] = (value ) & 0xFF;
+ str[4] = '\0';
+}
+
+/*----------------------------------------------------------------------
+| AP4_FormatFourCharsPrintable
++---------------------------------------------------------------------*/
+void
+AP4_FormatFourCharsPrintable(char* str, AP4_UI32 value) {
+ AP4_FormatFourChars(str, value);
+ for (int i=0; i<4; i++) {
+ if (str[i]<' ' || str[i] >= 127) {
+ str[i] = '.';
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_SplitArgs
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SplitArgs(char* arg, char*& arg0, char*& arg1)
+{
+ arg0 = arg;
+ char* c = arg;
+ while (*c != 0 && *c != ':') {
+ c++;
+ }
+ if (*c == ':') {
+ *c++ = '\0';
+ arg1 = c;
+ return AP4_SUCCESS;
+ } else {
+ return AP4_FAILURE;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_SplitArgs
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_SplitArgs(char* arg, char*& arg0, char*& arg1, char*& arg2)
+{
+ AP4_Result result = AP4_SplitArgs(arg, arg0, arg1);
+ if (AP4_FAILED(result)) return result;
+ return AP4_SplitArgs(arg1, arg1, arg2);
+}
+
+/*----------------------------------------------------------------------
+| AP4_HexNibble
++---------------------------------------------------------------------*/
+unsigned char
+AP4_HexNibble(char c)
+{
+ switch (c) {
+ case '0': return 0;
+ case '1': return 1;
+ case '2': return 2;
+ case '3': return 3;
+ case '4': return 4;
+ case '5': return 5;
+ case '6': return 6;
+ case '7': return 7;
+ case '8': return 8;
+ case '9': return 9;
+ case 'a': case 'A': return 10;
+ case 'b': case 'B': return 11;
+ case 'c': case 'C': return 12;
+ case 'd': case 'D': return 13;
+ case 'e': case 'E': return 14;
+ case 'f': case 'F': return 15;
+ default: return 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_NibbleHex
++---------------------------------------------------------------------*/
+char
+AP4_NibbleHex(unsigned int nibble)
+{
+ if (nibble < 10) {
+ return '0'+nibble;
+ } else if (nibble < 16) {
+ return 'A'+(nibble-10);
+ } else {
+ return ' ';
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_ParseHex
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_ParseHex(const char* hex, unsigned char* bytes, unsigned int count)
+{
+ if (AP4_StringLength(hex) != 2*count) return AP4_ERROR_INVALID_PARAMETERS;
+ for (unsigned int i=0; i<count; i++) {
+ bytes[i] = (AP4_HexNibble(hex[2*i]) << 4) | (AP4_HexNibble(hex[2*i+1]));
+ }
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_FormatHex
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_FormatHex(const AP4_UI08* data, unsigned int data_size, char* hex)
+{
+ for (unsigned int i=0; i<data_size; i++) {
+ *hex++ = AP4_NibbleHex(data[i]>>4);
+ *hex++ = AP4_NibbleHex(data[i]&0x0F);
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BitWriter::Write
++---------------------------------------------------------------------*/
+void
+AP4_BitWriter::Write(AP4_UI32 bits, unsigned int bit_count)
+{
+ unsigned char* data = m_Data;
+ if (m_BitCount+bit_count > m_DataSize*8) return;
+ data += m_BitCount/8;
+ unsigned int space = 8-(m_BitCount%8);
+ while (bit_count) {
+ unsigned int mask = bit_count==32 ? 0xFFFFFFFF : ((1<<bit_count)-1);
+ if (bit_count <= space) {
+ *data |= ((bits&mask) << (space-bit_count));
+ m_BitCount += bit_count;
+ return;
+ } else {
+ *data |= ((bits&mask) >> (bit_count-space));
+ ++data;
+ m_BitCount += space;
+ bit_count -= space;
+ space = 8;
+ }
+ }
+}
+
+
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.h
index e2d3b6c93..0b678b3e0 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Utils.h
@@ -1,212 +1,212 @@
-/*****************************************************************
-|
-| AP4 - Utilities
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-#ifndef _AP4_UTILS_H_
-#define _AP4_UTILS_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Config.h"
-#include "Ap4Types.h"
-#include "Ap4Results.h"
-#include "Ap4Config.h"
-
-/*----------------------------------------------------------------------
-| non-inline functions
-+---------------------------------------------------------------------*/
-double AP4_BytesToDoubleBE(const unsigned char* bytes);
-AP4_UI64 AP4_BytesToUInt64BE(const unsigned char* bytes);
-void AP4_BytesFromDoubleBE(unsigned char* bytes, double value);
-void AP4_BytesFromUInt64BE(unsigned char* bytes, AP4_UI64 value);
-
-/*----------------------------------------------------------------------
-| AP4_BytesToUInt32BE
-+---------------------------------------------------------------------*/
-inline AP4_UI32
-AP4_BytesToUInt32BE(const unsigned char* bytes)
-{
- return
- ( ((AP4_UI32)bytes[0])<<24 ) |
- ( ((AP4_UI32)bytes[1])<<16 ) |
- ( ((AP4_UI32)bytes[2])<<8 ) |
- ( ((AP4_UI32)bytes[3]) );
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesToInt32BE
-+---------------------------------------------------------------------*/
-inline AP4_SI32
-AP4_BytesToInt32BE(const unsigned char* bytes)
-{
- return AP4_BytesToUInt32BE(bytes);
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesToUInt24BE
-+---------------------------------------------------------------------*/
-inline AP4_UI32
-AP4_BytesToUInt24BE(const unsigned char* bytes)
-{
- return
- ( ((AP4_UI32)bytes[0])<<16 ) |
- ( ((AP4_UI32)bytes[1])<<8 ) |
- ( ((AP4_UI32)bytes[2]) );
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesToInt16BE
-+---------------------------------------------------------------------*/
-inline AP4_UI16
-AP4_BytesToUInt16BE(const unsigned char* bytes)
-{
- return
- ( ((AP4_UI16)bytes[0])<<8 ) |
- ( ((AP4_UI16)bytes[1]) );
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesToInt16BE
-+---------------------------------------------------------------------*/
-inline AP4_SI16
-AP4_BytesToInt16BE(const unsigned char* bytes)
-{
- return (AP4_SI16)AP4_BytesToUInt16BE(bytes);
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesFromUInt32BE
-+---------------------------------------------------------------------*/
-inline void
-AP4_BytesFromUInt32BE(unsigned char* bytes, AP4_UI32 value)
-{
- bytes[0] = (unsigned char)(value >> 24);
- bytes[1] = (unsigned char)(value >> 16);
- bytes[2] = (unsigned char)(value >> 8);
- bytes[3] = (unsigned char)(value );
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesFromUInt24BE
-+---------------------------------------------------------------------*/
-inline void
-AP4_BytesFromUInt24BE(unsigned char* bytes, AP4_UI32 value)
-{
- bytes[0] = (unsigned char)(value >> 16);
- bytes[1] = (unsigned char)(value >> 8);
- bytes[2] = (unsigned char)(value );
-}
-
-/*----------------------------------------------------------------------
-| AP4_BytesFromUInt16BE
-+---------------------------------------------------------------------*/
-inline void
-AP4_BytesFromUInt16BE(unsigned char* bytes, AP4_UI16 value)
-{
- bytes[0] = (unsigned char)(value >> 8);
- bytes[1] = (unsigned char)(value );
-}
-
-/*----------------------------------------------------------------------
-| time functions
-+---------------------------------------------------------------------*/
-AP4_UI32 AP4_DurationMsFromUnits(AP4_UI64 units,
- AP4_UI32 units_per_second);
-AP4_UI64 AP4_ConvertTime(AP4_UI64 time_value,
- AP4_UI32 from_time_scale,
- AP4_UI32 to_time_scale);
-
-/*----------------------------------------------------------------------
-| string utils
-+---------------------------------------------------------------------*/
-#if defined (AP4_CONFIG_HAVE_STDIO_H)
-#include <stdio.h>
-#endif
-
-#if defined (AP4_CONFIG_HAVE_SNPRINTF)
-#define AP4_FormatString AP4_snprintf
-#else
-int AP4_FormatString(char* str, AP4_Size size, const char* format, ...);
-#endif
-#if defined(AP4_CONFIG_HAVE_VSNPRINTF)
-#define AP4_FormatStringVN(s,c,f,a) AP4_vsnprintf(s,c,f,a)
-#else
-extern int AP4_FormatStringVN(char *buffer, size_t count, const char *format, va_list argptr);
-#endif
-
-#if defined (AP4_CONFIG_HAVE_STRING_H)
-#include <string.h>
-#define AP4_StringLength(x) strlen(x)
-#define AP4_CopyMemory(x,y,z) memcpy(x,y,z)
-#define AP4_CompareMemory(x, y, z) memcmp(x, y, z)
-#define AP4_SetMemory(x,y,z) memset(x,y,z)
-#define AP4_CompareStrings(x,y) strcmp(x,y)
-#endif
-
-unsigned char AP4_HexNibble(char c);
-char AP4_NibbleHex(unsigned int nibble);
-void AP4_FormatFourChars(char* str, AP4_UI32 value);
-void AP4_FormatFourCharsPrintable(char* str, AP4_UI32 value);
-AP4_Result
-AP4_ParseHex(const char* hex, unsigned char* bytes, unsigned int count);
-AP4_Result
-AP4_FormatHex(const AP4_UI08* data, unsigned int data_size, char* hex);
-AP4_Result
-AP4_SplitArgs(char* arg, char*& arg0, char*& arg1, char*& arg2);
-AP4_Result
-AP4_SplitArgs(char* arg, char*& arg0, char*& arg1);
-
-/*----------------------------------------------------------------------
-| AP4_BitWriter
-+---------------------------------------------------------------------*/
-class AP4_BitWriter
-{
-public:
- AP4_BitWriter(AP4_Size size) : m_DataSize(size), m_BitCount(0) {
- if (size) {
- m_Data = new unsigned char[size];
- AP4_SetMemory(m_Data, 0, size);
- } else {
- m_Data = NULL;
- }
- }
- ~AP4_BitWriter() { delete m_Data; }
-
- void Write(AP4_UI32 bits, unsigned int bit_count);
-
- unsigned int GetBitCount() { return m_BitCount; }
- const unsigned char* GetData() { return m_Data; }
-
-private:
- unsigned char* m_Data;
- unsigned int m_DataSize;
- unsigned int m_BitCount;
-};
-
-
-#endif // _AP4_UTILS_H_
+/*****************************************************************
+|
+| AP4 - Utilities
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+#ifndef _AP4_UTILS_H_
+#define _AP4_UTILS_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Config.h"
+#include "Ap4Types.h"
+#include "Ap4Results.h"
+#include "Ap4Config.h"
+
+/*----------------------------------------------------------------------
+| non-inline functions
++---------------------------------------------------------------------*/
+double AP4_BytesToDoubleBE(const unsigned char* bytes);
+AP4_UI64 AP4_BytesToUInt64BE(const unsigned char* bytes);
+void AP4_BytesFromDoubleBE(unsigned char* bytes, double value);
+void AP4_BytesFromUInt64BE(unsigned char* bytes, AP4_UI64 value);
+
+/*----------------------------------------------------------------------
+| AP4_BytesToUInt32BE
++---------------------------------------------------------------------*/
+inline AP4_UI32
+AP4_BytesToUInt32BE(const unsigned char* bytes)
+{
+ return
+ ( ((AP4_UI32)bytes[0])<<24 ) |
+ ( ((AP4_UI32)bytes[1])<<16 ) |
+ ( ((AP4_UI32)bytes[2])<<8 ) |
+ ( ((AP4_UI32)bytes[3]) );
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesToInt32BE
++---------------------------------------------------------------------*/
+inline AP4_SI32
+AP4_BytesToInt32BE(const unsigned char* bytes)
+{
+ return AP4_BytesToUInt32BE(bytes);
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesToUInt24BE
++---------------------------------------------------------------------*/
+inline AP4_UI32
+AP4_BytesToUInt24BE(const unsigned char* bytes)
+{
+ return
+ ( ((AP4_UI32)bytes[0])<<16 ) |
+ ( ((AP4_UI32)bytes[1])<<8 ) |
+ ( ((AP4_UI32)bytes[2]) );
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesToInt16BE
++---------------------------------------------------------------------*/
+inline AP4_UI16
+AP4_BytesToUInt16BE(const unsigned char* bytes)
+{
+ return
+ ( ((AP4_UI16)bytes[0])<<8 ) |
+ ( ((AP4_UI16)bytes[1]) );
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesToInt16BE
++---------------------------------------------------------------------*/
+inline AP4_SI16
+AP4_BytesToInt16BE(const unsigned char* bytes)
+{
+ return (AP4_SI16)AP4_BytesToUInt16BE(bytes);
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesFromUInt32BE
++---------------------------------------------------------------------*/
+inline void
+AP4_BytesFromUInt32BE(unsigned char* bytes, AP4_UI32 value)
+{
+ bytes[0] = (unsigned char)(value >> 24);
+ bytes[1] = (unsigned char)(value >> 16);
+ bytes[2] = (unsigned char)(value >> 8);
+ bytes[3] = (unsigned char)(value );
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesFromUInt24BE
++---------------------------------------------------------------------*/
+inline void
+AP4_BytesFromUInt24BE(unsigned char* bytes, AP4_UI32 value)
+{
+ bytes[0] = (unsigned char)(value >> 16);
+ bytes[1] = (unsigned char)(value >> 8);
+ bytes[2] = (unsigned char)(value );
+}
+
+/*----------------------------------------------------------------------
+| AP4_BytesFromUInt16BE
++---------------------------------------------------------------------*/
+inline void
+AP4_BytesFromUInt16BE(unsigned char* bytes, AP4_UI16 value)
+{
+ bytes[0] = (unsigned char)(value >> 8);
+ bytes[1] = (unsigned char)(value );
+}
+
+/*----------------------------------------------------------------------
+| time functions
++---------------------------------------------------------------------*/
+AP4_UI32 AP4_DurationMsFromUnits(AP4_UI64 units,
+ AP4_UI32 units_per_second);
+AP4_UI64 AP4_ConvertTime(AP4_UI64 time_value,
+ AP4_UI32 from_time_scale,
+ AP4_UI32 to_time_scale);
+
+/*----------------------------------------------------------------------
+| string utils
++---------------------------------------------------------------------*/
+#if defined (AP4_CONFIG_HAVE_STDIO_H)
+#include <stdio.h>
+#endif
+
+#if defined (AP4_CONFIG_HAVE_SNPRINTF)
+#define AP4_FormatString AP4_snprintf
+#else
+int AP4_FormatString(char* str, AP4_Size size, const char* format, ...);
+#endif
+#if defined(AP4_CONFIG_HAVE_VSNPRINTF)
+#define AP4_FormatStringVN(s,c,f,a) AP4_vsnprintf(s,c,f,a)
+#else
+extern int AP4_FormatStringVN(char *buffer, size_t count, const char *format, va_list argptr);
+#endif
+
+#if defined (AP4_CONFIG_HAVE_STRING_H)
+#include <string.h>
+#define AP4_StringLength(x) strlen(x)
+#define AP4_CopyMemory(x,y,z) memcpy(x,y,z)
+#define AP4_CompareMemory(x, y, z) memcmp(x, y, z)
+#define AP4_SetMemory(x,y,z) memset(x,y,z)
+#define AP4_CompareStrings(x,y) strcmp(x,y)
+#endif
+
+unsigned char AP4_HexNibble(char c);
+char AP4_NibbleHex(unsigned int nibble);
+void AP4_FormatFourChars(char* str, AP4_UI32 value);
+void AP4_FormatFourCharsPrintable(char* str, AP4_UI32 value);
+AP4_Result
+AP4_ParseHex(const char* hex, unsigned char* bytes, unsigned int count);
+AP4_Result
+AP4_FormatHex(const AP4_UI08* data, unsigned int data_size, char* hex);
+AP4_Result
+AP4_SplitArgs(char* arg, char*& arg0, char*& arg1, char*& arg2);
+AP4_Result
+AP4_SplitArgs(char* arg, char*& arg0, char*& arg1);
+
+/*----------------------------------------------------------------------
+| AP4_BitWriter
++---------------------------------------------------------------------*/
+class AP4_BitWriter
+{
+public:
+ AP4_BitWriter(AP4_Size size) : m_DataSize(size), m_BitCount(0) {
+ if (size) {
+ m_Data = new unsigned char[size];
+ AP4_SetMemory(m_Data, 0, size);
+ } else {
+ m_Data = NULL;
+ }
+ }
+ ~AP4_BitWriter() { delete m_Data; }
+
+ void Write(AP4_UI32 bits, unsigned int bit_count);
+
+ unsigned int GetBitCount() { return m_BitCount; }
+ const unsigned char* GetData() { return m_Data; }
+
+private:
+ unsigned char* m_Data;
+ unsigned int m_DataSize;
+ unsigned int m_BitCount;
+};
+
+
+#endif // _AP4_UTILS_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.cpp b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.cpp
index e71eced66..36e62c167 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.cpp
@@ -1,193 +1,203 @@
-/*****************************************************************
-|
-| AP4 - UUID Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Types.h"
-#include "Ap4UuidAtom.h"
-#include "Ap4Utils.h"
-
-/*----------------------------------------------------------------------
-| AP4_UuidAtom::AP4_UuidAtom
-+---------------------------------------------------------------------*/
-AP4_UuidAtom::AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid) :
- AP4_Atom(AP4_ATOM_TYPE_UUID, size)
-{
- AP4_CopyMemory(m_Uuid, uuid, 16);
-}
-
-/*----------------------------------------------------------------------
-| AP4_UuidAtom::AP4_UuidAtom
-+---------------------------------------------------------------------*/
-AP4_UuidAtom::AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_UI32 version, AP4_UI32 flags) :
- AP4_Atom(AP4_ATOM_TYPE_UUID, size, false, version, flags)
-{
- AP4_CopyMemory(m_Uuid, uuid, 16);
-}
-
-/*----------------------------------------------------------------------
-| AP4_UuidAtom::AP4_UuidAtom
-+---------------------------------------------------------------------*/
-AP4_UuidAtom::AP4_UuidAtom(AP4_UI64 size, bool is_full, AP4_ByteStream& stream) :
- AP4_Atom(AP4_ATOM_TYPE_UUID, size)
-{
- if (is_full) {
- m_IsFull = true;
- ReadFullHeader(stream, m_Version, m_Flags);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_UuidAtom::GetHeaderSize
-+---------------------------------------------------------------------*/
-AP4_Size
-AP4_UuidAtom::GetHeaderSize() const
-{
- return (m_IsFull ? AP4_FULL_UUID_ATOM_HEADER_SIZE : AP4_UUID_ATOM_HEADER_SIZE)+(m_Size32==1?8:0);
-}
-
-/*----------------------------------------------------------------------
-| AP4_UuidAtom::WriteHeader
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_UuidAtom::WriteHeader(AP4_ByteStream& stream)
-{
- AP4_Result result;
-
- // write the size
- result = stream.WriteUI32(m_Size32);
- if (AP4_FAILED(result)) return result;
-
- // write the type
- result = stream.WriteUI32(m_Type);
- if (AP4_FAILED(result)) return result;
-
- // handle 64-bit sizes
- if (m_Size32 == 1) {
- result = stream.WriteUI64(m_Size64);
- if (AP4_FAILED(result)) return result;
- }
-
- // write the extended type
- result = stream.Write(m_Uuid, 16);
- if (AP4_FAILED(result)) return result;
-
- // for full atoms, write version and flags
- if (m_IsFull) {
- result = stream.WriteUI08(m_Version);
- if (AP4_FAILED(result)) return result;
- result = stream.WriteUI24(m_Flags);
- if (AP4_FAILED(result)) return result;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_UuidAtom::InspectHeader
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_UuidAtom::InspectHeader(AP4_AtomInspector& inspector)
-{
- char uuid[37];
- uuid[36] = '\0';
- char* dst = uuid;
- for (unsigned int i=0; i<16; i++) {
- *dst++ = AP4_NibbleHex(m_Uuid[i]>>4);
- *dst++ = AP4_NibbleHex(m_Uuid[i]&0x0F);
- if (i == 5 || i == 7 || i == 9 || i == 11) *dst++ = '-';
- }
-
- // write atom name
- char name[7];
- name[0] = '[';
- AP4_FormatFourCharsPrintable(&name[1], m_Type);
- name[5] = ']';
- name[6] = '\0';
- char header[128];
- char extra[32] = "";
- if (m_IsFull) {
- if (m_Version && m_Flags) {
- AP4_FormatString(extra, sizeof(extra),
- ", version=%d, flags=%x",
- m_Version,
- m_Flags);
- } else if (m_Version) {
- AP4_FormatString(extra, sizeof(extra),
- ", version=%d",
- m_Version);
- } else if (m_Flags) {
- AP4_FormatString(extra, sizeof(extra),
- ", flags=%x",
- m_Flags);
- }
- }
- AP4_FormatString(header, sizeof(header),
- "{%s} size=%ld+%lld%s",
- uuid,
- GetHeaderSize(),
- GetSize()-GetHeaderSize(),
- extra);
- inspector.StartElement(name, header);
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_UnknownUuidAtom::AP4_UnknownUuidAtom
-+---------------------------------------------------------------------*/
-AP4_UnknownUuidAtom::AP4_UnknownUuidAtom(AP4_UI64 size, AP4_ByteStream& stream) :
- AP4_UuidAtom(size, false, stream)
-{
- // store the data
- m_Data.SetDataSize((AP4_Size)size-GetHeaderSize());
- stream.Read(m_Data.UseData(), m_Data.GetDataSize());
-}
-
-/*----------------------------------------------------------------------
-| AP4_UnknownUuidAtom::AP4_UnknownUuidAtom
-+---------------------------------------------------------------------*/
-AP4_UnknownUuidAtom::AP4_UnknownUuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_ByteStream& stream) :
- AP4_UuidAtom(size, uuid)
-{
- // store the data
- m_Data.SetDataSize((AP4_Size)size-GetHeaderSize());
- stream.Read(m_Data.UseData(), m_Data.GetDataSize());
-}
-
-/*----------------------------------------------------------------------
-| AP4_UnknownUuidAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_UnknownUuidAtom::WriteFields(AP4_ByteStream& stream)
-{
- // write the data
- return stream.Write(m_Data.GetData(), m_Data.GetDataSize());
-}
-
+/*****************************************************************
+|
+| AP4 - UUID Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Types.h"
+#include "Ap4UuidAtom.h"
+#include "Ap4Utils.h"
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_UuidAtom)
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom::AP4_UuidAtom
++---------------------------------------------------------------------*/
+AP4_UuidAtom::AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid) :
+ AP4_Atom(AP4_ATOM_TYPE_UUID, size)
+{
+ AP4_CopyMemory(m_Uuid, uuid, 16);
+}
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom::AP4_UuidAtom
++---------------------------------------------------------------------*/
+AP4_UuidAtom::AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_UI32 version, AP4_UI32 flags) :
+ AP4_Atom(AP4_ATOM_TYPE_UUID, size, false, version, flags)
+{
+ AP4_CopyMemory(m_Uuid, uuid, 16);
+}
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom::AP4_UuidAtom
++---------------------------------------------------------------------*/
+AP4_UuidAtom::AP4_UuidAtom(AP4_UI64 size, bool is_full, AP4_ByteStream& stream) :
+ AP4_Atom(AP4_ATOM_TYPE_UUID, size)
+{
+ if (is_full) {
+ m_IsFull = true;
+ ReadFullHeader(stream, m_Version, m_Flags);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom::GetHeaderSize
++---------------------------------------------------------------------*/
+AP4_Size
+AP4_UuidAtom::GetHeaderSize() const
+{
+ return (m_IsFull ? AP4_FULL_UUID_ATOM_HEADER_SIZE : AP4_UUID_ATOM_HEADER_SIZE)+(m_Size32==1?8:0);
+}
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom::WriteHeader
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_UuidAtom::WriteHeader(AP4_ByteStream& stream)
+{
+ AP4_Result result;
+
+ // write the size
+ result = stream.WriteUI32(m_Size32);
+ if (AP4_FAILED(result)) return result;
+
+ // write the type
+ result = stream.WriteUI32(m_Type);
+ if (AP4_FAILED(result)) return result;
+
+ // handle 64-bit sizes
+ if (m_Size32 == 1) {
+ result = stream.WriteUI64(m_Size64);
+ if (AP4_FAILED(result)) return result;
+ }
+
+ // write the extended type
+ result = stream.Write(m_Uuid, 16);
+ if (AP4_FAILED(result)) return result;
+
+ // for full atoms, write version and flags
+ if (m_IsFull) {
+ result = stream.WriteUI08(m_Version);
+ if (AP4_FAILED(result)) return result;
+ result = stream.WriteUI24(m_Flags);
+ if (AP4_FAILED(result)) return result;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom::InspectHeader
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_UuidAtom::InspectHeader(AP4_AtomInspector& inspector)
+{
+ char uuid[37];
+ uuid[36] = '\0';
+ char* dst = uuid;
+ for (unsigned int i=0; i<16; i++) {
+ *dst++ = AP4_NibbleHex(m_Uuid[i]>>4);
+ *dst++ = AP4_NibbleHex(m_Uuid[i]&0x0F);
+ if (i == 5 || i == 7 || i == 9 || i == 11) *dst++ = '-';
+ }
+
+ // write atom name
+ char name[7];
+ name[0] = '[';
+ AP4_FormatFourCharsPrintable(&name[1], m_Type);
+ name[5] = ']';
+ name[6] = '\0';
+ char header[128];
+ char extra[32] = "";
+ if (m_IsFull) {
+ if (m_Version && m_Flags) {
+ AP4_FormatString(extra, sizeof(extra),
+ ", version=%d, flags=%x",
+ m_Version,
+ m_Flags);
+ } else if (m_Version) {
+ AP4_FormatString(extra, sizeof(extra),
+ ", version=%d",
+ m_Version);
+ } else if (m_Flags) {
+ AP4_FormatString(extra, sizeof(extra),
+ ", flags=%x",
+ m_Flags);
+ }
+ }
+ AP4_FormatString(header, sizeof(header),
+ "{%s} size=%d+%lld%s",
+ uuid,
+ (int)GetHeaderSize(),
+ GetSize()-GetHeaderSize(),
+ extra);
+ inspector.StartElement(name, header);
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_UnknownUuidAtom Dynamic Cast Anchor
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_UnknownUuidAtom)
+
+/*----------------------------------------------------------------------
+| AP4_UnknownUuidAtom::AP4_UnknownUuidAtom
++---------------------------------------------------------------------*/
+AP4_UnknownUuidAtom::AP4_UnknownUuidAtom(AP4_UI64 size, AP4_ByteStream& stream) :
+ AP4_UuidAtom(size, false, stream)
+{
+ // store the data
+ m_Data.SetDataSize((AP4_Size)size-GetHeaderSize());
+ stream.Read(m_Data.UseData(), m_Data.GetDataSize());
+}
+
+/*----------------------------------------------------------------------
+| AP4_UnknownUuidAtom::AP4_UnknownUuidAtom
++---------------------------------------------------------------------*/
+AP4_UnknownUuidAtom::AP4_UnknownUuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_ByteStream& stream) :
+ AP4_UuidAtom(size, uuid)
+{
+ // store the data
+ m_Data.SetDataSize((AP4_Size)size-GetHeaderSize());
+ stream.Read(m_Data.UseData(), m_Data.GetDataSize());
+}
+
+/*----------------------------------------------------------------------
+| AP4_UnknownUuidAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_UnknownUuidAtom::WriteFields(AP4_ByteStream& stream)
+{
+ // write the data
+ return stream.Write(m_Data.GetData(), m_Data.GetDataSize());
+}
+
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.h
index 2c425193a..26631d651 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4UuidAtom.h
@@ -1,95 +1,99 @@
-/*****************************************************************
-|
-| AP4 - UUID Atoms
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
- ****************************************************************/
-/**
-* @file
-* @brief UUID Atoms
-*/
-
-#ifndef _AP4_UUID_ATOM_H_
-#define _AP4_UUID_ATOM_H_
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4Atom.h"
-#include "Ap4ByteStream.h"
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_UI32 AP4_UUID_ATOM_HEADER_SIZE = AP4_ATOM_HEADER_SIZE+16;
-const AP4_UI32 AP4_FULL_UUID_ATOM_HEADER_SIZE = AP4_FULL_ATOM_HEADER_SIZE+16;
-
-/*----------------------------------------------------------------------
-| AP4_UuidAtom
-+---------------------------------------------------------------------*/
-/**
- * Base class for uuid atoms.
- */
-class AP4_UuidAtom : public AP4_Atom {
-public:
- // constructor and destructor
- virtual ~AP4_UuidAtom() {};
-
- // methods
- virtual AP4_Size GetHeaderSize() const;
- virtual AP4_Result WriteHeader(AP4_ByteStream& stream);
- virtual AP4_Result InspectHeader(AP4_AtomInspector& inspector);
-
- // accessors
- const AP4_UI08* GetUuid() { return m_Uuid; }
-
-protected:
- // members
- AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid);
- AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_UI32 version, AP4_UI32 flags);
- AP4_UuidAtom(AP4_UI64 size, bool is_full, AP4_ByteStream& stream);
- AP4_UI08 m_Uuid[16];
-};
-
-/*----------------------------------------------------------------------
-| AP4_UnknownUuidAtom
-+---------------------------------------------------------------------*/
-/**
- * Unknown uuid atoms.
- */
-class AP4_UnknownUuidAtom : public AP4_UuidAtom {
-public:
- // constructors
- AP4_UnknownUuidAtom(AP4_UI64 size, AP4_ByteStream& stream);
- AP4_UnknownUuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_ByteStream& stream);
-
- // methods
- virtual AP4_Result WriteFields(AP4_ByteStream& stream);
-
-protected:
- // members
- AP4_DataBuffer m_Data;
-};
-
-#endif // _AP4_UUID_ATOM_H_
+/*****************************************************************
+|
+| AP4 - UUID Atoms
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+ ****************************************************************/
+/**
+* @file
+* @brief UUID Atoms
+*/
+
+#ifndef _AP4_UUID_ATOM_H_
+#define _AP4_UUID_ATOM_H_
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4Atom.h"
+#include "Ap4ByteStream.h"
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_UI32 AP4_UUID_ATOM_HEADER_SIZE = AP4_ATOM_HEADER_SIZE+16;
+const AP4_UI32 AP4_FULL_UUID_ATOM_HEADER_SIZE = AP4_FULL_ATOM_HEADER_SIZE+16;
+
+/*----------------------------------------------------------------------
+| AP4_UuidAtom
++---------------------------------------------------------------------*/
+/**
+ * Base class for uuid atoms.
+ */
+class AP4_UuidAtom : public AP4_Atom {
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_UuidAtom, AP4_Atom)
+
+ // constructor and destructor
+ virtual ~AP4_UuidAtom() {};
+
+ // methods
+ virtual AP4_Size GetHeaderSize() const;
+ virtual AP4_Result WriteHeader(AP4_ByteStream& stream);
+ virtual AP4_Result InspectHeader(AP4_AtomInspector& inspector);
+
+ // accessors
+ const AP4_UI08* GetUuid() { return m_Uuid; }
+
+protected:
+ // members
+ AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid);
+ AP4_UuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_UI32 version, AP4_UI32 flags);
+ AP4_UuidAtom(AP4_UI64 size, bool is_full, AP4_ByteStream& stream);
+ AP4_UI08 m_Uuid[16];
+};
+
+/*----------------------------------------------------------------------
+| AP4_UnknownUuidAtom
++---------------------------------------------------------------------*/
+/**
+ * Unknown uuid atoms.
+ */
+class AP4_UnknownUuidAtom : public AP4_UuidAtom {
+public:
+ AP4_IMPLEMENT_DYNAMIC_CAST_D(AP4_UnknownUuidAtom, AP4_UuidAtom)
+
+ // constructors
+ AP4_UnknownUuidAtom(AP4_UI64 size, AP4_ByteStream& stream);
+ AP4_UnknownUuidAtom(AP4_UI64 size, const AP4_UI08* uuid, AP4_ByteStream& stream);
+
+ // methods
+ virtual AP4_Result WriteFields(AP4_ByteStream& stream);
+
+protected:
+ // members
+ AP4_DataBuffer m_Data;
+};
+
+#endif // _AP4_UUID_ATOM_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Version.h b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Version.h
index f93fa5f3f..d948eea91 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Version.h
+++ b/src/filters/parser/MP4Splitter/AP4/Source/Core/Ap4Version.h
@@ -1,43 +1,43 @@
-/*****************************************************************
-|
-| AP4 - Version Numbers
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-#ifndef _AP4_VERSION_H_
-#define _AP4_VERSION_H_
-
-/*----------------------------------------------------------------------
-| version constants
-+---------------------------------------------------------------------*/
-/**
- * Version number of the SDK
- */
-#define AP4_VERSION 0x01020200
-#define AP4_VERSION_STRING "1.2.2.0"
-
-#endif // _AP4_VERSION_H_
+/*****************************************************************
+|
+| AP4 - Version Numbers
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+#ifndef _AP4_VERSION_H_
+#define _AP4_VERSION_H_
+
+/*----------------------------------------------------------------------
+| version constants
++---------------------------------------------------------------------*/
+/**
+ * Version number of the SDK
+ */
+#define AP4_VERSION 0x01020300
+#define AP4_VERSION_STRING "1.2.3.0"
+
+#endif // _AP4_VERSION_H_
diff --git a/src/filters/parser/MP4Splitter/AP4/Source/MetaData/Ap4MetaData.cpp b/src/filters/parser/MP4Splitter/AP4/Source/MetaData/Ap4MetaData.cpp
index 5f97839d9..a7b825d3a 100644
--- a/src/filters/parser/MP4Splitter/AP4/Source/MetaData/Ap4MetaData.cpp
+++ b/src/filters/parser/MP4Splitter/AP4/Source/MetaData/Ap4MetaData.cpp
@@ -1,1736 +1,1736 @@
-/*****************************************************************
-|
-| AP4 - MetaData
-|
-| Copyright 2002-2008 Axiomatic Systems, LLC
-|
-|
-| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
-|
-| Unless you have obtained Bento4 under a difference license,
-| this version of Bento4 is Bento4|GPL.
-| Bento4|GPL is free software; you can redistribute it and/or modify
-| it under the terms of the GNU General Public License as published by
-| the Free Software Foundation; either version 2, or (at your option)
-| any later version.
-|
-| Bento4|GPL is distributed in the hope that it will be useful,
-| but WITHOUT ANY WARRANTY; without even the implied warranty of
-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-| GNU General Public License for more details.
-|
-| You should have received a copy of the GNU General Public License
-| along with Bento4|GPL; see the file COPYING. If not, write to the
-| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-| 02111-1307, USA.
-|
-****************************************************************/
-
-/*----------------------------------------------------------------------
-| includes
-+---------------------------------------------------------------------*/
-#include "Ap4File.h"
-#include "Ap4Movie.h"
-#include "Ap4MetaData.h"
-#include "Ap4ContainerAtom.h"
-#include "Ap4MoovAtom.h"
-#include "Ap4HdlrAtom.h"
-#include "Ap4DataBuffer.h"
-#include "Ap4Utils.h"
-#include "Ap4String.h"
-
-/*----------------------------------------------------------------------
-| dynamic cast support
-+---------------------------------------------------------------------*/
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_3GppLocalizedStringAtom)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_DcfdAtom)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_DcfStringAtom)
-AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_DataAtom)
-
-/*----------------------------------------------------------------------
-| metadata keys
-+---------------------------------------------------------------------*/
-static const AP4_MetaData::KeyInfo AP4_MetaData_KeyInfos [] = {
- {"Name", "Name", AP4_ATOM_TYPE_cNAM, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Artist", "Artist", AP4_ATOM_TYPE_cART, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"AlbumArtist", "Album Artist", AP4_ATOM_TYPE_aART, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Composer", "Composer", AP4_ATOM_TYPE_cCOM, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Writer", "Writer", AP4_ATOM_TYPE_cWRT, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Album", "Album", AP4_ATOM_TYPE_cALB, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"GenreCode", "Genre", AP4_ATOM_TYPE_GNRE, AP4_MetaData::Value::TYPE_BINARY},
- {"GenreName", "Genre", AP4_ATOM_TYPE_cGEN, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Grouping", "Grouping", AP4_ATOM_TYPE_cGRP, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Date", "Date", AP4_ATOM_TYPE_cDAY, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Tool", "Encoding Tool", AP4_ATOM_TYPE_cTOO, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Comment", "Comment", AP4_ATOM_TYPE_cCMT, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Lyrics", "Lyrics", AP4_ATOM_TYPE_cLYR, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Copyright", "Copyright", AP4_ATOM_TYPE_CPRT, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Track", "Track Number", AP4_ATOM_TYPE_TRKN, AP4_MetaData::Value::TYPE_BINARY},
- {"Disc", "Disc Number", AP4_ATOM_TYPE_DISK, AP4_MetaData::Value::TYPE_BINARY},
- {"Cover", "Cover Art", AP4_ATOM_TYPE_COVR, AP4_MetaData::Value::TYPE_BINARY},
- {"Description", "Description", AP4_ATOM_TYPE_DESC, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Rating", "Rating", AP4_ATOM_TYPE_RTNG, AP4_MetaData::Value::TYPE_INT_08_BE},
- {"Tempo", "Tempo", AP4_ATOM_TYPE_TMPO, AP4_MetaData::Value::TYPE_INT_16_BE},
- {"Compilation", "Compilation", AP4_ATOM_TYPE_CPIL, AP4_MetaData::Value::TYPE_INT_08_BE},
- {"IsGapless", "Is Gapless", AP4_ATOM_TYPE_PGAP, AP4_MetaData::Value::TYPE_INT_08_BE},
- {"Title", "Title", AP4_ATOM_TYPE_TITL, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Description", "Description", AP4_ATOM_TYPE_DSCP, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"StoreFrontID", "Store Front ID", AP4_ATOM_TYPE_sfID, AP4_MetaData::Value::TYPE_INT_32_BE},
- {"FileKind", "File Kind", AP4_ATOM_TYPE_STIK, AP4_MetaData::Value::TYPE_INT_08_BE},
- {"ShowName", "Show Name", AP4_ATOM_TYPE_TVSH, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"ShowSeason", "Show Season Number", AP4_ATOM_TYPE_TVSN, AP4_MetaData::Value::TYPE_INT_32_BE},
- {"ShowEpisodeNumber", "Show Episode Number", AP4_ATOM_TYPE_TVES, AP4_MetaData::Value::TYPE_INT_32_BE},
- {"ShowEpisodeName", "Show Episode Name", AP4_ATOM_TYPE_TVEN, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"TVNetworkName", "TV Network Name", AP4_ATOM_TYPE_TVNN, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"IsPodcast", "Is a Podcast", AP4_ATOM_TYPE_PCST, AP4_MetaData::Value::TYPE_INT_08_BE},
- {"PodcastUrl", "Podcast URL", AP4_ATOM_TYPE_PURL, AP4_MetaData::Value::TYPE_BINARY},
- {"PodcastGuid", "Podcast GUID", AP4_ATOM_TYPE_EGID, AP4_MetaData::Value::TYPE_BINARY},
- {"PodcastCategory", "Podcast Category", AP4_ATOM_TYPE_CATG, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Keywords", "Keywords", AP4_ATOM_TYPE_KEYW, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"PurchaseDate", "Purchase Date", AP4_ATOM_TYPE_PURD, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"IconUri", "Icon URI", AP4_ATOM_TYPE_ICNU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"InfoUrl", "Info URL", AP4_ATOM_TYPE_INFU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"CoverUri", "Cover Art URI", AP4_ATOM_TYPE_CVRU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"LyricsUri", "Lyrics URI", AP4_ATOM_TYPE_LRCU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Duration", "Duration", AP4_ATOM_TYPE_DCFD, AP4_MetaData::Value::TYPE_INT_32_BE},
- {"Performer", "Performer", AP4_ATOM_TYPE_PERF, AP4_MetaData::Value::TYPE_STRING_UTF_8},
- {"Author", "Author", AP4_ATOM_TYPE_AUTH, AP4_MetaData::Value::TYPE_STRING_UTF_8},
-};
-AP4_Array<AP4_MetaData::KeyInfo> AP4_MetaData::KeyInfos(
- AP4_MetaData_KeyInfos,
- sizeof(AP4_MetaData_KeyInfos)/sizeof(KeyInfo));
-
-/*----------------------------------------------------------------------
-| genre IDs
-+---------------------------------------------------------------------*/
-static const char* const Ap4Id3Genres[] =
-{
- "Blues",
- "Classic Rock",
- "Country",
- "Dance",
- "Disco",
- "Funk",
- "Grunge",
- "Hip-Hop",
- "Jazz",
- "Metal",
- "New Age",
- "Oldies",
- "Other",
- "Pop",
- "R&B",
- "Rap",
- "Reggae",
- "Rock",
- "Techno",
- "Industrial",
- "Alternative",
- "Ska",
- "Death Metal",
- "Pranks",
- "Soundtrack",
- "Euro-Techno",
- "Ambient",
- "Trip-Hop",
- "Vocal",
- "Jazz+Funk",
- "Fusion",
- "Trance",
- "Classical",
- "Instrumental",
- "Acid",
- "House",
- "Game",
- "Sound Clip",
- "Gospel",
- "Noise",
- "AlternRock",
- "Bass",
- "Soul",
- "Punk",
- "Space",
- "Meditative",
- "Instrumental Pop",
- "Instrumental Rock",
- "Ethnic",
- "Gothic",
- "Darkwave",
- "Techno-Industrial",
- "Electronic",
- "Pop-Folk",
- "Eurodance",
- "Dream",
- "Southern Rock",
- "Comedy",
- "Cult",
- "Gangsta",
- "Top 40",
- "Christian Rap",
- "Pop/Funk",
- "Jungle",
- "Native American",
- "Cabaret",
- "New Wave",
- "Psychadelic",
- "Rave",
- "Showtunes",
- "Trailer",
- "Lo-Fi",
- "Tribal",
- "Acid Punk",
- "Acid Jazz",
- "Polka",
- "Retro",
- "Musical",
- "Rock & Roll",
- "Hard Rock",
- "Folk",
- "Folk-Rock",
- "National Folk",
- "Swing",
- "Fast Fusion",
- "Bebob",
- "Latin",
- "Revival",
- "Celtic",
- "Bluegrass",
- "Avantgarde",
- "Gothic Rock",
- "Progressive Rock",
- "Psychedelic Rock",
- "Symphonic Rock",
- "Slow Rock",
- "Big Band",
- "Chorus",
- "Easy Listening",
- "Acoustic",
- "Humour",
- "Speech",
- "Chanson",
- "Opera",
- "Chamber Music",
- "Sonata",
- "Symphony",
- "Booty Bass",
- "Primus",
- "Porn Groove",
- "Satire",
- "Slow Jam",
- "Club",
- "Tango",
- "Samba",
- "Folklore",
- "Ballad",
- "Power Ballad",
- "Rhythmic Soul",
- "Freestyle",
- "Duet",
- "Punk Rock",
- "Drum Solo",
- "Acapella",
- "Euro-House",
- "Dance Hall"
-};
-
-static const char*
-Ap4StikNames[] = {
- "Movie", // 0
- "Normal", // 1
- "Audiobook", // 2
- "?", // 3
- "?", // 4
- "Whacked Bookmark", // 5
- "Music Video", // 6
- "?", // 7
- "?", // 8
- "Short Film", // 9
- "TV Show", // 10
- "Booklet", // 11
- "?", // 12
- "?", // 13
- "Ring Tone" // 14
-};
-
-
-/* sfID Store Front country
- Australia => 143460,
- Austria => 143445,
- Belgium => 143446,
- Canada => 143455,
- Denmark => 143458,
- Finland => 143447,
- France => 143442,
- Germany => 143443,
- Greece => 143448,
- Ireland => 143449,
- Italy => 143450,
- Japan => 143462,
- Luxembourg => 143451,
- Netherlands => 143452,
- Norway => 143457,
- Portugal => 143453,
- Spain => 143454,
- Sweden => 143456,
- Switzerland => 143459,
- UK => 143444,
- USA => 143441,
-*/
-
-/*----------------------------------------------------------------------
-| constants
-+---------------------------------------------------------------------*/
-const AP4_Size AP4_DATA_ATOM_MAX_SIZE = 0x40000000;
-
-/*----------------------------------------------------------------------
-| 3GPP localized string atoms
-+---------------------------------------------------------------------*/
-const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::_3gppLocalizedStringTypes[] = {
- AP4_ATOM_TYPE_TITL,
- AP4_ATOM_TYPE_DSCP,
- AP4_ATOM_TYPE_CPRT,
- AP4_ATOM_TYPE_PERF,
- AP4_ATOM_TYPE_AUTH,
- AP4_ATOM_TYPE_GNRE
-};
-const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::_3gppLocalizedStringTypeList = {
- _3gppLocalizedStringTypes,
- sizeof(_3gppLocalizedStringTypes)/sizeof(_3gppLocalizedStringTypes[0])
-};
-
-/*----------------------------------------------------------------------
-| other 3GPP atoms
-+---------------------------------------------------------------------*/
-const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::_3gppOtherTypes[] = {
- AP4_ATOM_TYPE_RTNG,
- AP4_ATOM_TYPE_CLSF,
- AP4_ATOM_TYPE_KYWD,
- AP4_ATOM_TYPE_LOCI,
- AP4_ATOM_TYPE_ALBM,
- AP4_ATOM_TYPE_YRRC,
-};
-const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::_3gppOtherTypeList = {
- _3gppOtherTypes,
- sizeof(_3gppOtherTypes)/sizeof(_3gppOtherTypes[0])
-};
-
-/*----------------------------------------------------------------------
-| DCF string atoms
-+---------------------------------------------------------------------*/
-const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::DcfStringTypes[] = {
- AP4_ATOM_TYPE_ICNU,
- AP4_ATOM_TYPE_INFU,
- AP4_ATOM_TYPE_CVRU,
- AP4_ATOM_TYPE_LRCU
-};
-const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::DcfStringTypeList = {
- DcfStringTypes,
- sizeof(DcfStringTypes)/sizeof(DcfStringTypes[0])
-};
-
-/*----------------------------------------------------------------------
-| atom type lists
-+---------------------------------------------------------------------*/
-const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::IlstTypes[] =
-{
- AP4_ATOM_TYPE_dddd,
- AP4_ATOM_TYPE_cNAM,
- AP4_ATOM_TYPE_cART,
- AP4_ATOM_TYPE_cCOM,
- AP4_ATOM_TYPE_cWRT,
- AP4_ATOM_TYPE_cALB,
- AP4_ATOM_TYPE_cGEN,
- AP4_ATOM_TYPE_cGRP,
- AP4_ATOM_TYPE_cDAY,
- AP4_ATOM_TYPE_cTOO,
- AP4_ATOM_TYPE_cCMT,
- AP4_ATOM_TYPE_CPRT,
- AP4_ATOM_TYPE_TRKN,
- AP4_ATOM_TYPE_DISK,
- AP4_ATOM_TYPE_COVR,
- AP4_ATOM_TYPE_DESC,
- AP4_ATOM_TYPE_GNRE,
- AP4_ATOM_TYPE_CPIL,
- AP4_ATOM_TYPE_TMPO,
- AP4_ATOM_TYPE_RTNG,
- AP4_ATOM_TYPE_apID,
- AP4_ATOM_TYPE_cnID,
- AP4_ATOM_TYPE_cmID,
- AP4_ATOM_TYPE_atID,
- AP4_ATOM_TYPE_plID,
- AP4_ATOM_TYPE_geID,
- AP4_ATOM_TYPE_sfID,
- AP4_ATOM_TYPE_akID,
- AP4_ATOM_TYPE_aART,
- AP4_ATOM_TYPE_TVNN,
- AP4_ATOM_TYPE_TVSH,
- AP4_ATOM_TYPE_TVEN,
- AP4_ATOM_TYPE_TVSN,
- AP4_ATOM_TYPE_TVES,
- AP4_ATOM_TYPE_STIK,
- AP4_ATOM_TYPE_PGAP,
- AP4_ATOM_TYPE_PCST,
- AP4_ATOM_TYPE_PURD,
- AP4_ATOM_TYPE_PURL,
- AP4_ATOM_TYPE_EGID,
- AP4_ATOM_TYPE_SONM,
- AP4_ATOM_TYPE_SOAL,
- AP4_ATOM_TYPE_SOAR,
- AP4_ATOM_TYPE_SOAA,
- AP4_ATOM_TYPE_SOCO,
- AP4_ATOM_TYPE_SOSN
-};
-const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::IlstTypeList = {
- IlstTypes,
- sizeof(IlstTypes)/sizeof(IlstTypes[0])
-};
-
-/*----------------------------------------------------------------------
-| AP4_MetaDataAtomTypeHandler::CreateAtom
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaDataAtomTypeHandler::CreateAtom(AP4_Atom::Type type,
- AP4_UI32 size,
- AP4_ByteStream& stream,
- AP4_Atom::Type context,
- AP4_Atom*& atom)
-{
- atom = NULL;
-
- if (context == AP4_ATOM_TYPE_ILST) {
- if (IsTypeInList(type, IlstTypeList)) {
- m_AtomFactory->PushContext(type);
- atom = AP4_ContainerAtom::Create(type, size, false, false, stream, *m_AtomFactory);
- m_AtomFactory->PopContext();
- }
- } else if (type == AP4_ATOM_TYPE_DATA) {
- if (IsTypeInList(context, IlstTypeList)) {
- atom = new AP4_DataAtom(size, stream);
- }
- } else if (context == AP4_ATOM_TYPE_dddd) {
- if (type == AP4_ATOM_TYPE_MEAN || type == AP4_ATOM_TYPE_NAME) {
- atom = new AP4_MetaDataStringAtom(type, size, stream);
- }
- } else if (context == AP4_ATOM_TYPE_UDTA) {
- if (IsTypeInList(type, _3gppLocalizedStringTypeList)) {
- atom = AP4_3GppLocalizedStringAtom::Create(type, size, stream);
- } else if (IsTypeInList(type, DcfStringTypeList)) {
- atom = AP4_DcfStringAtom::Create(type, size, stream);
- } else if (type == AP4_ATOM_TYPE_DCFD) {
- atom = AP4_DcfdAtom::Create(size, stream);
- }
- }
-
- return atom?AP4_SUCCESS:AP4_FAILURE;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaDataAtomTypeHandler::IsTypeInList
-+---------------------------------------------------------------------*/
-bool
-AP4_MetaDataAtomTypeHandler::IsTypeInList(AP4_Atom::Type type, const AP4_MetaDataAtomTypeHandler::TypeList& list)
-{
- for (unsigned int i=0; i<list.m_Size; i++) {
- if (type == list.m_Types[i]) return true;
- }
- return false;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::AP4_MetaData
-+---------------------------------------------------------------------*/
-AP4_MetaData::AP4_MetaData(AP4_File* file)
-{
- // get the file's movie
- AP4_Movie* movie = file->GetMovie();
-
- // handle the movie's metadata if there is a movie in the file
- if (movie) {
- AP4_MoovAtom* moov = movie->GetMoovAtom();
- if (moov == NULL) return;
- ParseMoov(moov);
- } else {
- // if we don't have a movie, try to show metadata from a udta atom
- AP4_List<AP4_Atom>& top_level_atoms = file->GetTopLevelAtoms();
-
- AP4_List<AP4_Atom>::Item* atom_item = top_level_atoms.FirstItem();
- while (atom_item) {
- AP4_ContainerAtom* container = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom_item->GetData());
- if (container) {
- // look for a udta in a DCF layout
- AP4_Atom* udta = container->FindChild("odhe/udta");
- if (udta) {
- AP4_ContainerAtom* udta_container = AP4_DYNAMIC_CAST(AP4_ContainerAtom, udta);
- if (udta_container) {
- ParseUdta(udta_container, "dcf");
- }
- }
- }
- atom_item = atom_item->GetNext();
- }
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::ParseMoov
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::ParseMoov(AP4_MoovAtom* moov)
-{
- // look for a 'meta' atom with 'hdlr' type 'mdir'
- AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, moov->FindChild("udta/meta/hdlr"));
- if (hdlr == NULL || hdlr->GetHandlerType() != AP4_HANDLER_TYPE_MDIR) return AP4_ERROR_NO_SUCH_ITEM;
-
- // get the list of entries
- AP4_ContainerAtom* ilst = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moov->FindChild("udta/meta/ilst"));
- if (ilst == NULL) return AP4_ERROR_NO_SUCH_ITEM;
-
- AP4_List<AP4_Atom>::Item* ilst_item = ilst->GetChildren().FirstItem();
- while (ilst_item) {
- AP4_ContainerAtom* entry_atom = AP4_DYNAMIC_CAST(AP4_ContainerAtom, ilst_item->GetData());
- if (entry_atom) {
- AddIlstEntries(entry_atom, "meta");
- }
- ilst_item = ilst_item->GetNext();
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::ParseUdta
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::ParseUdta(AP4_ContainerAtom* udta, const char* namespc)
-{
- // check that the atom is indeed a 'udta' atom
- if (udta->GetType() != AP4_ATOM_TYPE_UDTA) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
-
- AP4_List<AP4_Atom>::Item* udta_item = udta->GetChildren().FirstItem();
- for (; udta_item; udta_item = udta_item->GetNext()) {
- AP4_3GppLocalizedStringAtom* _3gpp_atom = AP4_DYNAMIC_CAST(AP4_3GppLocalizedStringAtom, udta_item->GetData());
- if (_3gpp_atom) {
- Add3GppEntry(_3gpp_atom, namespc);
- continue;
- }
-
- AP4_DcfStringAtom* dcfs_atom = AP4_DYNAMIC_CAST(AP4_DcfStringAtom, udta_item->GetData());
- if (dcfs_atom) {
- AddDcfStringEntry(dcfs_atom, namespc);
- continue;
- }
-
- AP4_DcfdAtom* dcfd_atom = AP4_DYNAMIC_CAST(AP4_DcfdAtom, udta_item->GetData());
- if (dcfd_atom) {
- AddDcfdEntry(dcfd_atom, namespc);
- }
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::~AP4_MetaData
-+---------------------------------------------------------------------*/
-AP4_MetaData::~AP4_MetaData()
-{
- m_Entries.DeleteReferences();
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::ResolveKeyName
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::ResolveKeyName(AP4_Atom::Type atom_type, AP4_String& value)
-{
- const char* key_name = NULL;
- char four_cc[5];
-
- // look for a match in the key infos
- for (unsigned int i=0;
- i<sizeof(AP4_MetaData_KeyInfos)/sizeof(AP4_MetaData_KeyInfos[0]);
- i++) {
- if (AP4_MetaData_KeyInfos[i].four_cc == atom_type) {
- key_name = AP4_MetaData_KeyInfos[i].name;
- break;
- }
- }
- if (key_name == NULL) {
- // this key was not found in the key infos, create a name for it
- AP4_FormatFourChars(four_cc, (AP4_UI32)atom_type);
- key_name = four_cc;
- }
- value = key_name;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::AddIlstEntries
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::AddIlstEntries(AP4_ContainerAtom* atom, const char* namespc)
-{
- AP4_MetaData::Value* value = NULL;
-
- if (atom->GetType() == AP4_ATOM_TYPE_dddd) {
- // look for the namespace
- AP4_MetaDataStringAtom* mean = static_cast<AP4_MetaDataStringAtom*>(atom->GetChild(AP4_ATOM_TYPE_MEAN));
- if (mean == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // look for the name
- AP4_MetaDataStringAtom* name = static_cast<AP4_MetaDataStringAtom*>(atom->GetChild(AP4_ATOM_TYPE_NAME));
- if (name == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // get the value
- AP4_DataAtom* data_atom = static_cast<AP4_DataAtom*>(atom->GetChild(AP4_ATOM_TYPE_DATA));
- value = new AP4_AtomMetaDataValue(data_atom, atom->GetType());
- if (value == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- return m_Entries.Add(new Entry(name->GetValue().GetChars(),
- mean->GetValue().GetChars(),
- value));
- } else {
- const char* key_name = NULL;
- char four_cc[5];
-
- // convert the atom type to a name
- AP4_FormatFourChars(four_cc, (AP4_UI32)atom->GetType());
- key_name = four_cc;
-
- // add one entry for each data atom
- AP4_List<AP4_Atom>::Item* data_item = atom->GetChildren().FirstItem();
- while (data_item) {
- AP4_Atom* item_atom = data_item->GetData();
- if (item_atom->GetType() == AP4_ATOM_TYPE_DATA) {
- AP4_DataAtom* data_atom = static_cast<AP4_DataAtom*>(item_atom);
- value = new AP4_AtomMetaDataValue(data_atom, atom->GetType());
- m_Entries.Add(new Entry(key_name, namespc, value));
- }
- data_item = data_item->GetNext();
- }
-
- return AP4_SUCCESS;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Add3GppEntry
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Add3GppEntry(AP4_3GppLocalizedStringAtom* atom, const char* namespc)
-{
- AP4_String key_name;
- ResolveKeyName(atom->GetType(), key_name);
-
- const char* language = NULL;
- if (atom->GetLanguage()[0]) {
- language = atom->GetLanguage();
- }
- AP4_MetaData::Value* value = new AP4_StringMetaDataValue(atom->GetValue().GetChars(),
- language);
- m_Entries.Add(new Entry(key_name.GetChars(), namespc, value));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::AddDcfStringEntry
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::AddDcfStringEntry(AP4_DcfStringAtom* atom, const char* namespc)
-{
- AP4_String key_name;
- ResolveKeyName(atom->GetType(), key_name);
-
- AP4_MetaData::Value* value = new AP4_StringMetaDataValue(atom->GetValue().GetChars());
- m_Entries.Add(new Entry(key_name.GetChars(), namespc, value));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::AddDcfdEntry
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::AddDcfdEntry(AP4_DcfdAtom* atom, const char* namespc)
-{
- AP4_String key_name;
- ResolveKeyName(atom->GetType(), key_name);
-
- AP4_MetaData::Value* value = new AP4_IntegerMetaDataValue(AP4_MetaData::Value::TYPE_INT_32_BE,
- atom->GetDuration());
- m_Entries.Add(new Entry(key_name.GetChars(), namespc, value));
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Value::MapDataTypeToCategory
-+---------------------------------------------------------------------*/
-AP4_MetaData::Value::TypeCategory
-AP4_MetaData::Value::MapTypeToCategory(Type type)
-{
- switch (type) {
- case AP4_MetaData::Value::TYPE_INT_08_BE:
- case AP4_MetaData::Value::TYPE_INT_16_BE:
- case AP4_MetaData::Value::TYPE_INT_32_BE:
- return AP4_MetaData::Value::TYPE_CATEGORY_INTEGER;
-
- case AP4_MetaData::Value::TYPE_STRING_UTF_8:
- case AP4_MetaData::Value::TYPE_STRING_UTF_16:
- case AP4_MetaData::Value::TYPE_STRING_PASCAL:
- return AP4_MetaData::Value::TYPE_CATEGORY_STRING;
-
- case AP4_MetaData::Value::TYPE_FLOAT_32_BE:
- case AP4_MetaData::Value::TYPE_FLOAT_64_BE:
- return AP4_MetaData::Value::TYPE_CATEGORY_FLOAT;
-
- default:
- return AP4_MetaData::Value::TYPE_CATEGORY_BINARY;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Value::GetTypeCategory
-+---------------------------------------------------------------------*/
-AP4_MetaData::Value::TypeCategory
-AP4_MetaData::Value::GetTypeCategory() const
-{
- return MapTypeToCategory(m_Type);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::ToAtom
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Entry::ToAtom(AP4_Atom*& atom) const
-{
- atom = NULL;
-
- if (m_Value == NULL) {
- return AP4_ERROR_INVALID_PARAMETERS;
- }
-
- if (m_Key.GetNamespace() == "meta") {
- // convert the name into an atom type
- if (m_Key.GetName().GetLength() != 4) {
- // the name is not in the right format
- return AP4_ERROR_INVALID_PARAMETERS;
- }
- AP4_Atom::Type atom_type = AP4_Atom::TypeFromString(m_Key.GetName().GetChars());
-
- // create a container atom for the data
- AP4_ContainerAtom* container = new AP4_ContainerAtom(atom_type);
-
- // add the data atom
- AP4_DataAtom* data = new AP4_DataAtom(*m_Value);
- container->AddChild(data);
-
- atom = container;
- return AP4_SUCCESS;
- } else if (m_Key.GetNamespace() == "dcf") {
- // convert the name into an atom type
- if (m_Key.GetName().GetLength() != 4) {
- // the name is not in the right format
- return AP4_ERROR_INVALID_PARAMETERS;
- }
- AP4_Atom::Type atom_type = AP4_Atom::TypeFromString(m_Key.GetName().GetChars());
-
- if (AP4_MetaDataAtomTypeHandler::IsTypeInList(atom_type,
- AP4_MetaDataAtomTypeHandler::DcfStringTypeList)) {
- AP4_String atom_value = m_Value->ToString();
- atom = new AP4_DcfStringAtom(atom_type, atom_value.GetChars());
- return AP4_SUCCESS;
- } else if (AP4_MetaDataAtomTypeHandler::IsTypeInList(atom_type,
- AP4_MetaDataAtomTypeHandler::_3gppLocalizedStringTypeList)) {
- AP4_String atom_value = m_Value->ToString();
- const char* language = "eng"; // default
- if (m_Value->GetLanguage().GetLength() != 0) {
- language = m_Value->GetLanguage().GetChars();
- }
- atom = new AP4_3GppLocalizedStringAtom(atom_type, language, atom_value.GetChars());
- return AP4_SUCCESS;
- } else if (atom_type == AP4_ATOM_TYPE_DCFD) {
- atom = new AP4_DcfdAtom(m_Value->ToInteger());
- return AP4_SUCCESS;
- }
-
- // not supported
- return AP4_ERROR_NOT_SUPPORTED;
- } else {
- // create a '----' atom
- AP4_ContainerAtom* container = new AP4_ContainerAtom(AP4_ATOM_TYPE_dddd);
-
- // add a 'mean' string
- container->AddChild(new AP4_MetaDataStringAtom(AP4_ATOM_TYPE_MEAN, m_Key.GetNamespace().GetChars()));
-
- // add a 'name' string
- container->AddChild(new AP4_MetaDataStringAtom(AP4_ATOM_TYPE_NAME, m_Key.GetName().GetChars()));
-
- // add the data atom
- AP4_DataAtom* data = new AP4_DataAtom(*m_Value);
- container->AddChild(data);
-
- atom = container;
- return AP4_SUCCESS;
- }
-
- return AP4_ERROR_NOT_SUPPORTED;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::FindInIlst
-+---------------------------------------------------------------------*/
-AP4_ContainerAtom*
-AP4_MetaData::Entry::FindInIlst(AP4_ContainerAtom* ilst) const
-{
- if (m_Key.GetNamespace() == "meta") {
- AP4_Atom::Type atom_type = AP4_Atom::TypeFromString(m_Key.GetName().GetChars());
- return AP4_DYNAMIC_CAST(AP4_ContainerAtom, ilst->GetChild(atom_type));
- } else {
- AP4_List<AP4_Atom>::Item* ilst_item = ilst->GetChildren().FirstItem();
- while (ilst_item) {
- AP4_ContainerAtom* entry_atom = AP4_DYNAMIC_CAST(AP4_ContainerAtom, ilst_item->GetData());
- if (entry_atom) {
- AP4_MetaDataStringAtom* mean = static_cast<AP4_MetaDataStringAtom*>(entry_atom->GetChild(AP4_ATOM_TYPE_MEAN));
- AP4_MetaDataStringAtom* name = static_cast<AP4_MetaDataStringAtom*>(entry_atom->GetChild(AP4_ATOM_TYPE_NAME));
- if (mean && name &&
- mean->GetValue() == m_Key.GetNamespace() &&
- name->GetValue() == m_Key.GetName()) {
- return entry_atom;
- }
- }
- ilst_item = ilst_item->GetNext();
- }
- }
-
- // not found
- return NULL;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::AddToFileIlst
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Entry::AddToFileIlst(AP4_File& file, AP4_Ordinal index)
-{
- // check that we have a correct entry
- if (m_Value == NULL) return AP4_ERROR_INVALID_STATE;
-
- // convert the entry into an atom
- AP4_Atom* atom;
- AP4_Result result = ToAtom(atom);
- if (AP4_FAILED(result)) return result;
- AP4_ContainerAtom* entry_atom = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
- if (entry_atom == NULL) {
- return AP4_ERROR_INVALID_FORMAT;
- }
-
- // look for the 'moov'
- AP4_Movie* movie = file.GetMovie();
- if (movie == NULL) return AP4_ERROR_INVALID_FORMAT;
- AP4_MoovAtom* moov = movie->GetMoovAtom();
- if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // look for 'udta', and create if it does not exist
- AP4_ContainerAtom* udta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moov->FindChild("udta", true));
- if (udta == NULL) return AP4_ERROR_INTERNAL;
-
- // look for 'meta', and create if it does not exist ('meta' is a FULL atom)
- AP4_ContainerAtom* meta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, udta->FindChild("meta", true, true));
- if (meta == NULL) return AP4_ERROR_INTERNAL;
-
- // look for a 'hdlr' atom type 'mdir'
- AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, meta->FindChild("hdlr"));
- if (hdlr == NULL) {
- hdlr = new AP4_HdlrAtom(AP4_HANDLER_TYPE_MDIR, "");
- meta->AddChild(hdlr);
- } else {
- if (hdlr->GetHandlerType() != AP4_HANDLER_TYPE_MDIR) {
- return AP4_ERROR_INVALID_FORMAT;
- }
- }
-
- // get/create the list of entries
- AP4_ContainerAtom* ilst = AP4_DYNAMIC_CAST(AP4_ContainerAtom, meta->FindChild("ilst", true));
- if (ilst == NULL) return AP4_ERROR_INTERNAL;
-
- // look if there is already a container for this entry
- AP4_ContainerAtom* existing = FindInIlst(ilst);
- if (existing == NULL) {
- // just add the one we have
- ilst->AddChild(entry_atom);
- } else {
- // add the entry's data to the existing entry
- AP4_DataAtom* data_atom = AP4_DYNAMIC_CAST(AP4_DataAtom, entry_atom->GetChild(AP4_ATOM_TYPE_DATA));
- if (data_atom == NULL) return AP4_ERROR_INTERNAL;
- entry_atom->RemoveChild(data_atom);
- existing->AddChild(data_atom, index);
- delete entry_atom;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::AddToFileDcf
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Entry::AddToFileDcf(AP4_File& file, AP4_Ordinal index)
-{
- // check that we have a correct entry
- if (m_Value == NULL) return AP4_ERROR_INVALID_STATE;
-
- // look for 'odrm/odhe'
- AP4_ContainerAtom* odhe = AP4_DYNAMIC_CAST(AP4_ContainerAtom, file.FindChild("odrm/odhe"));
- if (odhe == NULL) return AP4_ERROR_NO_SUCH_ITEM;
-
- // get/create the list of entries
- AP4_ContainerAtom* udta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, odhe->FindChild("udta", true));
- if (udta == NULL) return AP4_ERROR_INTERNAL;
-
- // convert the entry into an atom
- AP4_Atom* data_atom;
- AP4_Result result = ToAtom(data_atom);
- if (AP4_FAILED(result)) return result;
-
- // add the entry's data to the container
- return udta->AddChild(data_atom, index);
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::AddToFile
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Entry::AddToFile(AP4_File& file, AP4_Ordinal index)
-{
- // check that we have a correct entry
- if (m_Value == NULL) return AP4_ERROR_INVALID_STATE;
-
- // check the namespace of the key to know where to add the atom
- if (m_Key.GetNamespace() == "meta") {
- return AddToFileIlst(file, index);
- } else if (m_Key.GetNamespace() == "dcf") {
- return AddToFileDcf(file, index);
- } else {
- // custom namespace
- return AddToFileIlst(file, index);
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::RemoveFromFileIlst
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Entry::RemoveFromFileIlst(AP4_File& file, AP4_Ordinal index)
-{
- // look for the 'moov'
- AP4_Movie* movie = file.GetMovie();
- if (movie == NULL) return AP4_ERROR_INVALID_FORMAT;
- AP4_MoovAtom* moov = movie->GetMoovAtom();
- if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
-
- // look for 'udta/meta/ilst'
- AP4_ContainerAtom* ilst = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moov->FindChild("udta/meta/ilst"));
- if (ilst == NULL) return AP4_ERROR_NO_SUCH_ITEM;
-
- // look if there is already a container for this entry
- AP4_ContainerAtom* existing = FindInIlst(ilst);
- if (existing == NULL) return AP4_ERROR_NO_SUCH_ITEM;
-
- // remove the data atom in the entry
- AP4_Result result = existing->DeleteChild(AP4_ATOM_TYPE_DATA, index);
- if (AP4_FAILED(result)) return result;
-
- // if the entry is empty, remove it
- if (existing->GetChildren().ItemCount() == 0) {
- ilst->RemoveChild(existing);
- delete existing;
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::RemoveFromFileDcf
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Entry::RemoveFromFileDcf(AP4_File& file, AP4_Ordinal index)
-{
- // look for 'odrm/odhe/udta'
- AP4_ContainerAtom* udta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, file.FindChild("odrm/odhe/udta"));
- if (udta == NULL) return AP4_ERROR_NO_SUCH_ITEM;
-
- // remove the data atom in the entry
- AP4_UI32 type = AP4_BytesToUInt32BE((const unsigned char*)m_Key.GetName().GetChars());
- AP4_Result result = udta->DeleteChild(type, index);
- if (AP4_FAILED(result)) return result;
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaData::Entry::RemoveFromFile
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaData::Entry::RemoveFromFile(AP4_File& file, AP4_Ordinal index)
-{
- // check the namespace of the key to know where to add the atom
- if (m_Key.GetNamespace() == "meta") {
- return RemoveFromFileIlst(file, index);
- } else if (m_Key.GetNamespace() == "dcf") {
- return RemoveFromFileDcf(file, index);
- } else {
- // unsupported namespace
- return AP4_ERROR_NOT_SUPPORTED;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_StringMetaDataValue::ToString
-+---------------------------------------------------------------------*/
-AP4_String
-AP4_StringMetaDataValue::ToString() const
-{
- return m_Value;
-}
-
-/*----------------------------------------------------------------------
-| AP4_StringMetaDataValue::ToBytes
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_StringMetaDataValue::ToBytes(AP4_DataBuffer& /* bytes */) const
-{
- return AP4_ERROR_NOT_SUPPORTED;
-}
-
-/*----------------------------------------------------------------------
-| AP4_StringMetaDataValue::ToInteger
-+---------------------------------------------------------------------*/
-long
-AP4_StringMetaDataValue::ToInteger() const
-{
- return 0;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IntegerMetaDataValue::ToString
-+---------------------------------------------------------------------*/
-AP4_String
-AP4_IntegerMetaDataValue::ToString() const
-{
- char value[16];
- AP4_FormatString(value, sizeof(value), "%ld", m_Value);
- return AP4_String(value);
-}
-
-/*----------------------------------------------------------------------
-| AP4_IntegerMetaDataValue::ToBytes
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_IntegerMetaDataValue::ToBytes(AP4_DataBuffer& /* bytes */) const
-{
- return AP4_ERROR_NOT_SUPPORTED;
-}
-
-/*----------------------------------------------------------------------
-| AP4_IntegerMetaDataValue::ToInteger
-+---------------------------------------------------------------------*/
-long
-AP4_IntegerMetaDataValue::ToInteger() const
-{
- return m_Value;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BinaryMetaDataValue::ToString
-+---------------------------------------------------------------------*/
-AP4_String
-AP4_BinaryMetaDataValue::ToString() const
-{
- return AP4_String(); // not supported
-}
-
-/*----------------------------------------------------------------------
-| AP4_BinaryMetaDataValue::ToBytes
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_BinaryMetaDataValue::ToBytes(AP4_DataBuffer& bytes) const
-{
- bytes.SetDataSize(m_Value.GetDataSize());
- AP4_CopyMemory(bytes.UseData(), m_Value.GetData(), m_Value.GetDataSize());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_BinaryMetaDataValue::ToInteger
-+---------------------------------------------------------------------*/
-long
-AP4_BinaryMetaDataValue::ToInteger() const
-{
- return 0; // NOT SUPPORTED
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomMetaDataValue::AP4_AtomMetaDataValue
-+---------------------------------------------------------------------*/
-AP4_AtomMetaDataValue::AP4_AtomMetaDataValue(AP4_DataAtom* atom,
- AP4_UI32 parent_type) :
- Value(atom->GetValueType()),
- m_DataAtom(atom)
-{
- switch (parent_type) {
- case AP4_ATOM_TYPE_GNRE:
- m_Meaning = MEANING_ID3_GENRE;
- break;
-
- case AP4_ATOM_TYPE_CPIL:
- m_Meaning = MEANING_BOOLEAN;
- break;
-
- case AP4_ATOM_TYPE_PGAP:
- case AP4_ATOM_TYPE_PCST:
- m_Meaning = MEANING_BOOLEAN;
- break;
-
- case AP4_ATOM_TYPE_STIK:
- m_Meaning = MEANING_FILE_KIND;
- break;
-
- case AP4_ATOM_TYPE_PURL:
- case AP4_ATOM_TYPE_EGID:
- m_Meaning = MEANING_BINARY_ENCODED_CHARS;
- break;
-
- default:
- break;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomMetaDataValue::ToString
-+---------------------------------------------------------------------*/
-AP4_String
-AP4_AtomMetaDataValue::ToString() const
-{
- char string[256] = "";
-
- AP4_MetaData::Value::Type value_type = m_DataAtom->GetValueType();
- switch (AP4_MetaData::Value::MapTypeToCategory(value_type)) {
- case AP4_MetaData::Value::TYPE_CATEGORY_INTEGER:
- {
- long value;
- if (AP4_SUCCEEDED(m_DataAtom->LoadInteger(value))) {
- if (m_Meaning == MEANING_BOOLEAN) {
- if (value) {
- return "True";
- } else {
- return "False";
- }
- } else if (m_Meaning == MEANING_FILE_KIND) {
- if (value >= 0 && ((unsigned int)value) <= sizeof(Ap4StikNames)/sizeof(Ap4StikNames[0])) {
- AP4_FormatString(string, sizeof(string), "(%ld) %s", value, Ap4StikNames[value]);
- } else {
- return "Unknown";
- }
- } else {
- AP4_FormatString(string, sizeof(string), "%ld", value);
- }
- }
- return AP4_String((const char*)string);
- break;
- }
-
- case AP4_MetaData::Value::TYPE_CATEGORY_STRING:
- {
- AP4_String* category_string;
- if (AP4_SUCCEEDED(m_DataAtom->LoadString(category_string))) {
- AP4_String result(*category_string);
- delete category_string;
- return result;
- }
- break;
- }
-
- case AP4_MetaData::Value::TYPE_CATEGORY_BINARY:
- {
- AP4_DataBuffer data;
- if (AP4_SUCCEEDED(m_DataAtom->LoadBytes(data))) {
- if (m_Meaning == MEANING_ID3_GENRE && data.GetDataSize() == 2) {
- unsigned int genre = (data.GetData()[0])*256+data.GetData()[1];
- if (genre >= 1 && genre <= sizeof(Ap4Id3Genres)/sizeof(Ap4Id3Genres[0])) {
- AP4_FormatString(string, sizeof(string), "(%d) %s", genre, Ap4Id3Genres[genre-1]);
- return AP4_String((const char*)string);
- } else {
- return "Unknown";
- }
- } else if (m_Meaning == MEANING_BINARY_ENCODED_CHARS) {
- AP4_String result;
- result.Assign((const char*)data.GetData(), data.GetDataSize());
- return result;
- } else {
- unsigned int dump_length = data.GetDataSize();
- bool truncate = false;
- if (dump_length > 16) {
- dump_length = 16;
- truncate = true;
- }
- char* out = string;
- for (unsigned int i=0; i<dump_length; i++) {
- AP4_FormatString(out, sizeof(string)-(out-string), "%02x ", data.GetData()[i]);
- out += 3;
- }
- if (truncate) {
- *out++='.'; *out++='.'; *out++='.'; *out++=' ';
- }
- AP4_FormatString(out, sizeof(string)-(out-string), "[%ld bytes]", data.GetDataSize());
- }
- }
- return AP4_String(string);
- }
- default:
- return AP4_String();
- }
-
- return AP4_String();
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomMetaDataValue::ToBytes
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_AtomMetaDataValue::ToBytes(AP4_DataBuffer& bytes) const
-{
- return m_DataAtom->LoadBytes(bytes);
-}
-
-/*----------------------------------------------------------------------
-| AP4_AtomMetaDataValue::ToInteger
-+---------------------------------------------------------------------*/
-long
-AP4_AtomMetaDataValue::ToInteger() const
-{
- long value;
- if (AP4_SUCCEEDED(m_DataAtom->LoadInteger(value))) {
- return value;
- } else {
- return 0;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::AP4_DataAtom
-+---------------------------------------------------------------------*/
-AP4_DataAtom::AP4_DataAtom(const AP4_MetaData::Value& value) :
- AP4_Atom(AP4_ATOM_TYPE_DATA, AP4_ATOM_HEADER_SIZE),
- m_DataType(DATA_TYPE_BINARY)
-{
- AP4_MemoryByteStream* memory = new AP4_MemoryByteStream(256);
- AP4_Size payload_size = 8;
- m_Source = memory;
-
- switch (value.GetType()) {
- case AP4_MetaData::Value::TYPE_STRING_UTF_8: {
- m_DataType = DATA_TYPE_STRING_UTF_8;
- AP4_String string_value = value.ToString();
- if (string_value.GetLength()) {
- memory->Write(string_value.GetChars(), string_value.GetLength());
- }
- payload_size += string_value.GetLength();
- break;
- }
-
- case AP4_MetaData::Value::TYPE_INT_08_BE: {
- m_DataType = DATA_TYPE_SIGNED_INT_BE;
- AP4_UI08 int_value = (AP4_UI08)value.ToInteger();
- memory->Write(&int_value, 1);
- payload_size += 1;
- break;
- }
-
- case AP4_MetaData::Value::TYPE_INT_16_BE: {
- m_DataType = DATA_TYPE_SIGNED_INT_BE;
- AP4_UI16 int_value = (AP4_UI16)value.ToInteger();
- memory->Write(&int_value, 2);
- payload_size += 2;
- break;
- }
-
- case AP4_MetaData::Value::TYPE_INT_32_BE: {
- m_DataType = DATA_TYPE_SIGNED_INT_BE;
- AP4_UI32 int_value = (AP4_UI32)value.ToInteger();
- memory->Write(&int_value, 4);
- payload_size += 4;
- break;
- }
-
- case AP4_MetaData::Value::TYPE_JPEG:
- m_DataType = DATA_TYPE_JPEG;
- // FALLTHROUGH
- case AP4_MetaData::Value::TYPE_GIF:
- if (m_DataType == DATA_TYPE_BINARY) m_DataType = DATA_TYPE_GIF;
- // FALLTHROUGH
- case AP4_MetaData::Value::TYPE_BINARY: {
- AP4_DataBuffer buffer;
- value.ToBytes(buffer);
- if (buffer.GetDataSize()) {
- memory->Write(buffer.GetData(), buffer.GetDataSize());
- }
- payload_size += buffer.GetDataSize();
- break;
- }
-
- default:
- break;
- }
-
- const AP4_String& language = value.GetLanguage();
- if (language == "en") {
- m_DataLang = LANGUAGE_ENGLISH;
- } else {
- // default
- m_DataLang = LANGUAGE_ENGLISH;
- }
-
- m_Size32 += payload_size;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::AP4_DataAtom
-+---------------------------------------------------------------------*/
-AP4_DataAtom::AP4_DataAtom(AP4_UI32 size, AP4_ByteStream& stream) :
- AP4_Atom(AP4_ATOM_TYPE_DATA, size)
-{
- if (size < AP4_ATOM_HEADER_SIZE+8) return;
-
- AP4_UI32 i;
- stream.ReadUI32(i); m_DataType = (DataType)i;
- stream.ReadUI32(i); m_DataLang = (DataLang)i;
-
- // the stream for the data is a substream of this source
- AP4_Position data_offset;
- stream.Tell(data_offset);
- AP4_Size data_size = size-AP4_ATOM_HEADER_SIZE-8;
- m_Source = new AP4_SubStream(stream, data_offset, data_size);
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::~AP4_DataAtom
-+---------------------------------------------------------------------*/
-AP4_DataAtom::~AP4_DataAtom()
-{
- delete(m_Source);
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::GetValueType
-+---------------------------------------------------------------------*/
-AP4_MetaData::Value::Type
-AP4_DataAtom::GetValueType()
-{
- switch (m_DataType) {
- case DATA_TYPE_BINARY:
- return AP4_MetaData::Value::TYPE_BINARY;
-
- case DATA_TYPE_SIGNED_INT_BE:
- switch (m_Size32-16) {
- case 1: return AP4_MetaData::Value::TYPE_INT_08_BE;
- case 2: return AP4_MetaData::Value::TYPE_INT_16_BE;
- case 4: return AP4_MetaData::Value::TYPE_INT_32_BE;
- default: return AP4_MetaData::Value::TYPE_BINARY;
- }
- break;
-
- case DATA_TYPE_STRING_UTF_8:
- return AP4_MetaData::Value::TYPE_STRING_UTF_8;
-
- case DATA_TYPE_STRING_UTF_16:
- return AP4_MetaData::Value::TYPE_STRING_UTF_16;
-
- case DATA_TYPE_STRING_PASCAL:
- return AP4_MetaData::Value::TYPE_STRING_PASCAL;
-
- case DATA_TYPE_GIF:
- return AP4_MetaData::Value::TYPE_GIF;
-
- case DATA_TYPE_JPEG:
- return AP4_MetaData::Value::TYPE_JPEG;
-
- default:
- return AP4_MetaData::Value::TYPE_BINARY;
- }
-
- return AP4_MetaData::Value::TYPE_BINARY;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataAtom::WriteFields(AP4_ByteStream& stream)
-{
- stream.WriteUI32(m_DataType);
- stream.WriteUI32(m_DataLang);
- if (m_Source) {
- AP4_LargeSize size = 0;
- m_Source->GetSize(size);
- m_Source->Seek(0);
- m_Source->CopyTo(stream, size);
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("type", m_DataType);
- inspector.AddField("lang", m_DataLang);
- if (m_DataType == DATA_TYPE_STRING_UTF_8) {
- AP4_String* str;
- if (AP4_SUCCEEDED(LoadString(str))) {
- inspector.AddField("value", str->GetChars());
- delete str;
- }
- } else if (m_DataType == DATA_TYPE_SIGNED_INT_BE) {
- long value;
- if (AP4_SUCCEEDED(LoadInteger(value))) {
- inspector.AddField("value", value);
- }
- }
-
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::LoadString
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataAtom::LoadString(AP4_String*& string)
-{
- if (m_Source == NULL) {
- string = new AP4_String();
- return AP4_SUCCESS;
- } else {
- // create a string with enough capactiy for the data
- AP4_LargeSize size = 0;
- m_Source->GetSize(size);
- if (size > AP4_DATA_ATOM_MAX_SIZE) return AP4_ERROR_OUT_OF_RANGE;
- string = new AP4_String((AP4_Size)size);
-
- // read from the start of the stream
- m_Source->Seek(0);
- AP4_Result result = m_Source->Read(string->UseChars(), (AP4_Size)size);
- if (AP4_FAILED(result)) {
- delete string;
- string = NULL;
- }
-
- return result;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::LoadBytes
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataAtom::LoadBytes(AP4_DataBuffer& bytes)
-{
- if (m_Source == NULL) {
- bytes.SetDataSize(0);
- return AP4_SUCCESS;
- }
- AP4_LargeSize size = 0;
- m_Source->GetSize(size);
- if (size > AP4_DATA_ATOM_MAX_SIZE) return AP4_ERROR_OUT_OF_RANGE;
- bytes.SetDataSize((AP4_Size)size);
- m_Source->Seek(0);
- AP4_Result result = m_Source->Read(bytes.UseData(), (AP4_Size)size);
- if (AP4_FAILED(result)) {
- bytes.SetDataSize(0);
- }
- return result;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DataAtom::LoadInteger
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DataAtom::LoadInteger(long& value)
-{
- AP4_Result result = AP4_FAILURE;
- value = 0;
- if (m_Source == NULL) return AP4_SUCCESS;
- AP4_LargeSize size = 0;
- m_Source->GetSize(size);
- if (size > 4) {
- return AP4_ERROR_OUT_OF_RANGE;
- }
- unsigned char bytes[4];
- m_Source->Seek(0);
- m_Source->Read(bytes, (AP4_Size)size);
- result = AP4_SUCCESS;
- switch (size) {
- case 1: value = bytes[0]; break;
- case 2: value = AP4_BytesToInt16BE(bytes); break;
- case 4: value = AP4_BytesToInt32BE(bytes); break;
- default: value = 0; result = AP4_ERROR_INVALID_FORMAT; break;
- }
- return result;
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaDataStringAtom::AP4_MetaDataStringAtom
-+---------------------------------------------------------------------*/
-AP4_MetaDataStringAtom::AP4_MetaDataStringAtom(Type type, const char* value) :
- AP4_Atom(type, AP4_ATOM_HEADER_SIZE),
- m_Value(value)
-{
- m_Size32 += 4+m_Value.GetLength();
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaDataStringAtom::AP4_MetaDataStringAtom
-+---------------------------------------------------------------------*/
-AP4_MetaDataStringAtom::AP4_MetaDataStringAtom(Type type, AP4_UI32 size, AP4_ByteStream& stream) :
- AP4_Atom(type, size),
- m_Value((AP4_Size)(size-AP4_ATOM_HEADER_SIZE-4))
-{
- stream.ReadUI32(m_Reserved);
- stream.Read(m_Value.UseChars(), m_Value.GetLength());
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaDataStringAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaDataStringAtom::WriteFields(AP4_ByteStream& stream)
-{
- stream.WriteUI32(m_Reserved);
- return stream.Write(m_Value.GetChars(), m_Value.GetLength());
-}
-
-/*----------------------------------------------------------------------
-| AP4_MetaDataStringAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_MetaDataStringAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("value", m_Value.GetChars());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_3GppLocalizedStringAtom::Create
-+---------------------------------------------------------------------*/
-AP4_3GppLocalizedStringAtom*
-AP4_3GppLocalizedStringAtom::Create(Type type, AP4_UI32 size, AP4_ByteStream& stream)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version != 0) return NULL;
- return new AP4_3GppLocalizedStringAtom(type, size, version, flags, stream);
-}
-
-/*----------------------------------------------------------------------
-| AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom
-+---------------------------------------------------------------------*/
-AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom(Type type,
- const char* language,
- const char* value) :
- AP4_Atom(type, AP4_FULL_ATOM_HEADER_SIZE+2, 0, 0),
- m_Value(value)
-{
- m_Language[0] = language[0];
- m_Language[1] = language[1];
- m_Language[2] = language[2];
- m_Language[3] = language[3];
-
- m_Size32 += m_Value.GetLength()+1;
-}
-
-/*----------------------------------------------------------------------
-| AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom
-+---------------------------------------------------------------------*/
-AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom(Type type,
- AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream) :
- AP4_Atom(type, size, version, flags)
-{
- // read the language code
- AP4_UI16 packed_language;
- stream.ReadUI16(packed_language);
- m_Language[0] = 0x60+((packed_language>>10)&0x1F);
- m_Language[1] = 0x60+((packed_language>> 5)&0x1F);
- m_Language[2] = 0x60+((packed_language )&0x1F);
- m_Language[3] = '\0';
-
- // read the value (should be a NULL-terminated string, but we'll
- // allow for strings that are not terminated)
- if (size > AP4_FULL_ATOM_HEADER_SIZE+2) {
- AP4_UI32 value_size = size-(AP4_FULL_ATOM_HEADER_SIZE+2);
- char* value = new char[value_size];
- stream.Read(value, value_size);
- m_Value.Assign(value, value_size);
- delete[] value;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_3GppLocalizedStringAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_3GppLocalizedStringAtom::WriteFields(AP4_ByteStream& stream)
-{
- AP4_UI16 packed_language = ((m_Language[0]-0x60)<<10) |
- ((m_Language[1]-0x60)<< 5) |
- ((m_Language[2]-0x60));
- stream.WriteUI16(packed_language);
- AP4_Size payload_size = (AP4_UI32)GetSize()-GetHeaderSize();
- if (payload_size < 2) return AP4_ERROR_INVALID_FORMAT;
- AP4_Size value_size = m_Value.GetLength()+1;
- if (value_size > payload_size-2) {
- value_size = payload_size-2;
- }
- stream.Write(m_Value.GetChars(), value_size);
- for (unsigned int i=value_size; i<payload_size-2; i++) {
- stream.WriteUI08(0);
- }
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_3GppLocalizedStringAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_3GppLocalizedStringAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("language", GetLanguage());
- inspector.AddField("value", m_Value.GetChars());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfStringAtom::Create
-+---------------------------------------------------------------------*/
-AP4_DcfStringAtom*
-AP4_DcfStringAtom::Create(Type type, AP4_UI32 size, AP4_ByteStream& stream)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version != 0) return NULL;
- return new AP4_DcfStringAtom(type, size, version, flags, stream);
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfStringAtom::AP4_DcfStringAtom
-+---------------------------------------------------------------------*/
-AP4_DcfStringAtom::AP4_DcfStringAtom(Type type, const char* value) :
- AP4_Atom(type, AP4_FULL_ATOM_HEADER_SIZE, 0, 0),
- m_Value(value)
-{
- m_Size32 += m_Value.GetLength();
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfStringAtom::AP4_DcfStringAtom
-+---------------------------------------------------------------------*/
-AP4_DcfStringAtom::AP4_DcfStringAtom(Type type,
- AP4_UI32 size,
- AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream) :
- AP4_Atom(type, size, version, flags)
-{
- if (size > AP4_FULL_ATOM_HEADER_SIZE) {
- AP4_UI32 value_size = size-(AP4_FULL_ATOM_HEADER_SIZE);
- char* value = new char[value_size];
- stream.Read(value, value_size);
- m_Value.Assign(value, value_size);
- delete[] value;
- }
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfStringAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DcfStringAtom::WriteFields(AP4_ByteStream& stream)
-{
- if (m_Value.GetLength()) stream.Write(m_Value.GetChars(), m_Value.GetLength());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfStringAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DcfStringAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("value", m_Value.GetChars());
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfdAtom::Create
-+---------------------------------------------------------------------*/
-AP4_DcfdAtom*
-AP4_DcfdAtom::Create(AP4_UI32 size, AP4_ByteStream& stream)
-{
- AP4_UI32 version;
- AP4_UI32 flags;
- if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
- if (version != 0) return NULL;
- if (size != AP4_FULL_ATOM_HEADER_SIZE+4) return NULL;
- return new AP4_DcfdAtom(version, flags, stream);
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfdAtom::AP4_DcfdAtom
-+---------------------------------------------------------------------*/
-AP4_DcfdAtom::AP4_DcfdAtom(AP4_UI32 version,
- AP4_UI32 flags,
- AP4_ByteStream& stream) :
- AP4_Atom(AP4_ATOM_TYPE_DCFD, AP4_FULL_ATOM_HEADER_SIZE+4, version, flags)
-{
- stream.ReadUI32(m_Duration);
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfdAtom::AP4_DcfdAtom
-+---------------------------------------------------------------------*/
-AP4_DcfdAtom::AP4_DcfdAtom(AP4_UI32 duration) :
- AP4_Atom(AP4_ATOM_TYPE_DCFD, AP4_FULL_ATOM_HEADER_SIZE+4, 0, 0),
- m_Duration(duration)
-{
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfdAtom::WriteFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DcfdAtom::WriteFields(AP4_ByteStream& stream)
-{
- stream.WriteUI32(m_Duration);
- return AP4_SUCCESS;
-}
-
-/*----------------------------------------------------------------------
-| AP4_DcfdAtom::InspectFields
-+---------------------------------------------------------------------*/
-AP4_Result
-AP4_DcfdAtom::InspectFields(AP4_AtomInspector& inspector)
-{
- inspector.AddField("duration", m_Duration);
- return AP4_SUCCESS;
-}
+/*****************************************************************
+|
+| AP4 - MetaData
+|
+| Copyright 2002-2008 Axiomatic Systems, LLC
+|
+|
+| This file is part of Bento4/AP4 (MP4 Atom Processing Library).
+|
+| Unless you have obtained Bento4 under a difference license,
+| this version of Bento4 is Bento4|GPL.
+| Bento4|GPL is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| Bento4|GPL is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with Bento4|GPL; see the file COPYING. If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02111-1307, USA.
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+| includes
++---------------------------------------------------------------------*/
+#include "Ap4File.h"
+#include "Ap4Movie.h"
+#include "Ap4MetaData.h"
+#include "Ap4ContainerAtom.h"
+#include "Ap4MoovAtom.h"
+#include "Ap4HdlrAtom.h"
+#include "Ap4DataBuffer.h"
+#include "Ap4Utils.h"
+#include "Ap4String.h"
+
+/*----------------------------------------------------------------------
+| dynamic cast support
++---------------------------------------------------------------------*/
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_3GppLocalizedStringAtom)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_DcfdAtom)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_DcfStringAtom)
+AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_DataAtom)
+
+/*----------------------------------------------------------------------
+| metadata keys
++---------------------------------------------------------------------*/
+static const AP4_MetaData::KeyInfo AP4_MetaData_KeyInfos [] = {
+ {"Name", "Name", AP4_ATOM_TYPE_cNAM, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Artist", "Artist", AP4_ATOM_TYPE_cART, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"AlbumArtist", "Album Artist", AP4_ATOM_TYPE_aART, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Composer", "Composer", AP4_ATOM_TYPE_cCOM, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Writer", "Writer", AP4_ATOM_TYPE_cWRT, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Album", "Album", AP4_ATOM_TYPE_cALB, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"GenreCode", "Genre", AP4_ATOM_TYPE_GNRE, AP4_MetaData::Value::TYPE_BINARY},
+ {"GenreName", "Genre", AP4_ATOM_TYPE_cGEN, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Grouping", "Grouping", AP4_ATOM_TYPE_cGRP, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Date", "Date", AP4_ATOM_TYPE_cDAY, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Tool", "Encoding Tool", AP4_ATOM_TYPE_cTOO, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Comment", "Comment", AP4_ATOM_TYPE_cCMT, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Lyrics", "Lyrics", AP4_ATOM_TYPE_cLYR, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Copyright", "Copyright", AP4_ATOM_TYPE_CPRT, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Track", "Track Number", AP4_ATOM_TYPE_TRKN, AP4_MetaData::Value::TYPE_BINARY},
+ {"Disc", "Disc Number", AP4_ATOM_TYPE_DISK, AP4_MetaData::Value::TYPE_BINARY},
+ {"Cover", "Cover Art", AP4_ATOM_TYPE_COVR, AP4_MetaData::Value::TYPE_BINARY},
+ {"Description", "Description", AP4_ATOM_TYPE_DESC, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Rating", "Rating", AP4_ATOM_TYPE_RTNG, AP4_MetaData::Value::TYPE_INT_08_BE},
+ {"Tempo", "Tempo", AP4_ATOM_TYPE_TMPO, AP4_MetaData::Value::TYPE_INT_16_BE},
+ {"Compilation", "Compilation", AP4_ATOM_TYPE_CPIL, AP4_MetaData::Value::TYPE_INT_08_BE},
+ {"IsGapless", "Is Gapless", AP4_ATOM_TYPE_PGAP, AP4_MetaData::Value::TYPE_INT_08_BE},
+ {"Title", "Title", AP4_ATOM_TYPE_TITL, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Description", "Description", AP4_ATOM_TYPE_DSCP, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"StoreFrontID", "Store Front ID", AP4_ATOM_TYPE_sfID, AP4_MetaData::Value::TYPE_INT_32_BE},
+ {"FileKind", "File Kind", AP4_ATOM_TYPE_STIK, AP4_MetaData::Value::TYPE_INT_08_BE},
+ {"ShowName", "Show Name", AP4_ATOM_TYPE_TVSH, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"ShowSeason", "Show Season Number", AP4_ATOM_TYPE_TVSN, AP4_MetaData::Value::TYPE_INT_32_BE},
+ {"ShowEpisodeNumber", "Show Episode Number", AP4_ATOM_TYPE_TVES, AP4_MetaData::Value::TYPE_INT_32_BE},
+ {"ShowEpisodeName", "Show Episode Name", AP4_ATOM_TYPE_TVEN, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"TVNetworkName", "TV Network Name", AP4_ATOM_TYPE_TVNN, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"IsPodcast", "Is a Podcast", AP4_ATOM_TYPE_PCST, AP4_MetaData::Value::TYPE_INT_08_BE},
+ {"PodcastUrl", "Podcast URL", AP4_ATOM_TYPE_PURL, AP4_MetaData::Value::TYPE_BINARY},
+ {"PodcastGuid", "Podcast GUID", AP4_ATOM_TYPE_EGID, AP4_MetaData::Value::TYPE_BINARY},
+ {"PodcastCategory", "Podcast Category", AP4_ATOM_TYPE_CATG, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Keywords", "Keywords", AP4_ATOM_TYPE_KEYW, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"PurchaseDate", "Purchase Date", AP4_ATOM_TYPE_PURD, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"IconUri", "Icon URI", AP4_ATOM_TYPE_ICNU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"InfoUrl", "Info URL", AP4_ATOM_TYPE_INFU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"CoverUri", "Cover Art URI", AP4_ATOM_TYPE_CVRU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"LyricsUri", "Lyrics URI", AP4_ATOM_TYPE_LRCU, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Duration", "Duration", AP4_ATOM_TYPE_DCFD, AP4_MetaData::Value::TYPE_INT_32_BE},
+ {"Performer", "Performer", AP4_ATOM_TYPE_PERF, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+ {"Author", "Author", AP4_ATOM_TYPE_AUTH, AP4_MetaData::Value::TYPE_STRING_UTF_8},
+};
+AP4_Array<AP4_MetaData::KeyInfo> AP4_MetaData::KeyInfos(
+ AP4_MetaData_KeyInfos,
+ sizeof(AP4_MetaData_KeyInfos)/sizeof(KeyInfo));
+
+/*----------------------------------------------------------------------
+| genre IDs
++---------------------------------------------------------------------*/
+static const char* const Ap4Id3Genres[] =
+{
+ "Blues",
+ "Classic Rock",
+ "Country",
+ "Dance",
+ "Disco",
+ "Funk",
+ "Grunge",
+ "Hip-Hop",
+ "Jazz",
+ "Metal",
+ "New Age",
+ "Oldies",
+ "Other",
+ "Pop",
+ "R&B",
+ "Rap",
+ "Reggae",
+ "Rock",
+ "Techno",
+ "Industrial",
+ "Alternative",
+ "Ska",
+ "Death Metal",
+ "Pranks",
+ "Soundtrack",
+ "Euro-Techno",
+ "Ambient",
+ "Trip-Hop",
+ "Vocal",
+ "Jazz+Funk",
+ "Fusion",
+ "Trance",
+ "Classical",
+ "Instrumental",
+ "Acid",
+ "House",
+ "Game",
+ "Sound Clip",
+ "Gospel",
+ "Noise",
+ "AlternRock",
+ "Bass",
+ "Soul",
+ "Punk",
+ "Space",
+ "Meditative",
+ "Instrumental Pop",
+ "Instrumental Rock",
+ "Ethnic",
+ "Gothic",
+ "Darkwave",
+ "Techno-Industrial",
+ "Electronic",
+ "Pop-Folk",
+ "Eurodance",
+ "Dream",
+ "Southern Rock",
+ "Comedy",
+ "Cult",
+ "Gangsta",
+ "Top 40",
+ "Christian Rap",
+ "Pop/Funk",
+ "Jungle",
+ "Native American",
+ "Cabaret",
+ "New Wave",
+ "Psychadelic",
+ "Rave",
+ "Showtunes",
+ "Trailer",
+ "Lo-Fi",
+ "Tribal",
+ "Acid Punk",
+ "Acid Jazz",
+ "Polka",
+ "Retro",
+ "Musical",
+ "Rock & Roll",
+ "Hard Rock",
+ "Folk",
+ "Folk-Rock",
+ "National Folk",
+ "Swing",
+ "Fast Fusion",
+ "Bebob",
+ "Latin",
+ "Revival",
+ "Celtic",
+ "Bluegrass",
+ "Avantgarde",
+ "Gothic Rock",
+ "Progressive Rock",
+ "Psychedelic Rock",
+ "Symphonic Rock",
+ "Slow Rock",
+ "Big Band",
+ "Chorus",
+ "Easy Listening",
+ "Acoustic",
+ "Humour",
+ "Speech",
+ "Chanson",
+ "Opera",
+ "Chamber Music",
+ "Sonata",
+ "Symphony",
+ "Booty Bass",
+ "Primus",
+ "Porn Groove",
+ "Satire",
+ "Slow Jam",
+ "Club",
+ "Tango",
+ "Samba",
+ "Folklore",
+ "Ballad",
+ "Power Ballad",
+ "Rhythmic Soul",
+ "Freestyle",
+ "Duet",
+ "Punk Rock",
+ "Drum Solo",
+ "Acapella",
+ "Euro-House",
+ "Dance Hall"
+};
+
+static const char*
+Ap4StikNames[] = {
+ "Movie", // 0
+ "Normal", // 1
+ "Audiobook", // 2
+ "?", // 3
+ "?", // 4
+ "Whacked Bookmark", // 5
+ "Music Video", // 6
+ "?", // 7
+ "?", // 8
+ "Short Film", // 9
+ "TV Show", // 10
+ "Booklet", // 11
+ "?", // 12
+ "?", // 13
+ "Ring Tone" // 14
+};
+
+
+/* sfID Store Front country
+ Australia => 143460,
+ Austria => 143445,
+ Belgium => 143446,
+ Canada => 143455,
+ Denmark => 143458,
+ Finland => 143447,
+ France => 143442,
+ Germany => 143443,
+ Greece => 143448,
+ Ireland => 143449,
+ Italy => 143450,
+ Japan => 143462,
+ Luxembourg => 143451,
+ Netherlands => 143452,
+ Norway => 143457,
+ Portugal => 143453,
+ Spain => 143454,
+ Sweden => 143456,
+ Switzerland => 143459,
+ UK => 143444,
+ USA => 143441,
+*/
+
+/*----------------------------------------------------------------------
+| constants
++---------------------------------------------------------------------*/
+const AP4_Size AP4_DATA_ATOM_MAX_SIZE = 0x40000000;
+
+/*----------------------------------------------------------------------
+| 3GPP localized string atoms
++---------------------------------------------------------------------*/
+const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::_3gppLocalizedStringTypes[] = {
+ AP4_ATOM_TYPE_TITL,
+ AP4_ATOM_TYPE_DSCP,
+ AP4_ATOM_TYPE_CPRT,
+ AP4_ATOM_TYPE_PERF,
+ AP4_ATOM_TYPE_AUTH,
+ AP4_ATOM_TYPE_GNRE
+};
+const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::_3gppLocalizedStringTypeList = {
+ _3gppLocalizedStringTypes,
+ sizeof(_3gppLocalizedStringTypes)/sizeof(_3gppLocalizedStringTypes[0])
+};
+
+/*----------------------------------------------------------------------
+| other 3GPP atoms
++---------------------------------------------------------------------*/
+const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::_3gppOtherTypes[] = {
+ AP4_ATOM_TYPE_RTNG,
+ AP4_ATOM_TYPE_CLSF,
+ AP4_ATOM_TYPE_KYWD,
+ AP4_ATOM_TYPE_LOCI,
+ AP4_ATOM_TYPE_ALBM,
+ AP4_ATOM_TYPE_YRRC,
+};
+const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::_3gppOtherTypeList = {
+ _3gppOtherTypes,
+ sizeof(_3gppOtherTypes)/sizeof(_3gppOtherTypes[0])
+};
+
+/*----------------------------------------------------------------------
+| DCF string atoms
++---------------------------------------------------------------------*/
+const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::DcfStringTypes[] = {
+ AP4_ATOM_TYPE_ICNU,
+ AP4_ATOM_TYPE_INFU,
+ AP4_ATOM_TYPE_CVRU,
+ AP4_ATOM_TYPE_LRCU
+};
+const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::DcfStringTypeList = {
+ DcfStringTypes,
+ sizeof(DcfStringTypes)/sizeof(DcfStringTypes[0])
+};
+
+/*----------------------------------------------------------------------
+| atom type lists
++---------------------------------------------------------------------*/
+const AP4_Atom::Type AP4_MetaDataAtomTypeHandler::IlstTypes[] =
+{
+ AP4_ATOM_TYPE_dddd,
+ AP4_ATOM_TYPE_cNAM,
+ AP4_ATOM_TYPE_cART,
+ AP4_ATOM_TYPE_cCOM,
+ AP4_ATOM_TYPE_cWRT,
+ AP4_ATOM_TYPE_cALB,
+ AP4_ATOM_TYPE_cGEN,
+ AP4_ATOM_TYPE_cGRP,
+ AP4_ATOM_TYPE_cDAY,
+ AP4_ATOM_TYPE_cTOO,
+ AP4_ATOM_TYPE_cCMT,
+ AP4_ATOM_TYPE_CPRT,
+ AP4_ATOM_TYPE_TRKN,
+ AP4_ATOM_TYPE_DISK,
+ AP4_ATOM_TYPE_COVR,
+ AP4_ATOM_TYPE_DESC,
+ AP4_ATOM_TYPE_GNRE,
+ AP4_ATOM_TYPE_CPIL,
+ AP4_ATOM_TYPE_TMPO,
+ AP4_ATOM_TYPE_RTNG,
+ AP4_ATOM_TYPE_apID,
+ AP4_ATOM_TYPE_cnID,
+ AP4_ATOM_TYPE_cmID,
+ AP4_ATOM_TYPE_atID,
+ AP4_ATOM_TYPE_plID,
+ AP4_ATOM_TYPE_geID,
+ AP4_ATOM_TYPE_sfID,
+ AP4_ATOM_TYPE_akID,
+ AP4_ATOM_TYPE_aART,
+ AP4_ATOM_TYPE_TVNN,
+ AP4_ATOM_TYPE_TVSH,
+ AP4_ATOM_TYPE_TVEN,
+ AP4_ATOM_TYPE_TVSN,
+ AP4_ATOM_TYPE_TVES,
+ AP4_ATOM_TYPE_STIK,
+ AP4_ATOM_TYPE_PGAP,
+ AP4_ATOM_TYPE_PCST,
+ AP4_ATOM_TYPE_PURD,
+ AP4_ATOM_TYPE_PURL,
+ AP4_ATOM_TYPE_EGID,
+ AP4_ATOM_TYPE_SONM,
+ AP4_ATOM_TYPE_SOAL,
+ AP4_ATOM_TYPE_SOAR,
+ AP4_ATOM_TYPE_SOAA,
+ AP4_ATOM_TYPE_SOCO,
+ AP4_ATOM_TYPE_SOSN
+};
+const AP4_MetaDataAtomTypeHandler::TypeList AP4_MetaDataAtomTypeHandler::IlstTypeList = {
+ IlstTypes,
+ sizeof(IlstTypes)/sizeof(IlstTypes[0])
+};
+
+/*----------------------------------------------------------------------
+| AP4_MetaDataAtomTypeHandler::CreateAtom
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaDataAtomTypeHandler::CreateAtom(AP4_Atom::Type type,
+ AP4_UI32 size,
+ AP4_ByteStream& stream,
+ AP4_Atom::Type context,
+ AP4_Atom*& atom)
+{
+ atom = NULL;
+
+ if (context == AP4_ATOM_TYPE_ILST) {
+ if (IsTypeInList(type, IlstTypeList)) {
+ m_AtomFactory->PushContext(type);
+ atom = AP4_ContainerAtom::Create(type, size, false, false, stream, *m_AtomFactory);
+ m_AtomFactory->PopContext();
+ }
+ } else if (type == AP4_ATOM_TYPE_DATA) {
+ if (IsTypeInList(context, IlstTypeList)) {
+ atom = new AP4_DataAtom(size, stream);
+ }
+ } else if (context == AP4_ATOM_TYPE_dddd) {
+ if (type == AP4_ATOM_TYPE_MEAN || type == AP4_ATOM_TYPE_NAME) {
+ atom = new AP4_MetaDataStringAtom(type, size, stream);
+ }
+ } else if (context == AP4_ATOM_TYPE_UDTA) {
+ if (IsTypeInList(type, _3gppLocalizedStringTypeList)) {
+ atom = AP4_3GppLocalizedStringAtom::Create(type, size, stream);
+ } else if (IsTypeInList(type, DcfStringTypeList)) {
+ atom = AP4_DcfStringAtom::Create(type, size, stream);
+ } else if (type == AP4_ATOM_TYPE_DCFD) {
+ atom = AP4_DcfdAtom::Create(size, stream);
+ }
+ }
+
+ return atom?AP4_SUCCESS:AP4_FAILURE;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaDataAtomTypeHandler::IsTypeInList
++---------------------------------------------------------------------*/
+bool
+AP4_MetaDataAtomTypeHandler::IsTypeInList(AP4_Atom::Type type, const AP4_MetaDataAtomTypeHandler::TypeList& list)
+{
+ for (unsigned int i=0; i<list.m_Size; i++) {
+ if (type == list.m_Types[i]) return true;
+ }
+ return false;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::AP4_MetaData
++---------------------------------------------------------------------*/
+AP4_MetaData::AP4_MetaData(AP4_File* file)
+{
+ // get the file's movie
+ AP4_Movie* movie = file->GetMovie();
+
+ // handle the movie's metadata if there is a movie in the file
+ if (movie) {
+ AP4_MoovAtom* moov = movie->GetMoovAtom();
+ if (moov == NULL) return;
+ ParseMoov(moov);
+ } else {
+ // if we don't have a movie, try to show metadata from a udta atom
+ AP4_List<AP4_Atom>& top_level_atoms = file->GetTopLevelAtoms();
+
+ AP4_List<AP4_Atom>::Item* atom_item = top_level_atoms.FirstItem();
+ while (atom_item) {
+ AP4_ContainerAtom* container = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom_item->GetData());
+ if (container) {
+ // look for a udta in a DCF layout
+ AP4_Atom* udta = container->FindChild("odhe/udta");
+ if (udta) {
+ AP4_ContainerAtom* udta_container = AP4_DYNAMIC_CAST(AP4_ContainerAtom, udta);
+ if (udta_container) {
+ ParseUdta(udta_container, "dcf");
+ }
+ }
+ }
+ atom_item = atom_item->GetNext();
+ }
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::ParseMoov
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::ParseMoov(AP4_MoovAtom* moov)
+{
+ // look for a 'meta' atom with 'hdlr' type 'mdir'
+ AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, moov->FindChild("udta/meta/hdlr"));
+ if (hdlr == NULL || hdlr->GetHandlerType() != AP4_HANDLER_TYPE_MDIR) return AP4_ERROR_NO_SUCH_ITEM;
+
+ // get the list of entries
+ AP4_ContainerAtom* ilst = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moov->FindChild("udta/meta/ilst"));
+ if (ilst == NULL) return AP4_ERROR_NO_SUCH_ITEM;
+
+ AP4_List<AP4_Atom>::Item* ilst_item = ilst->GetChildren().FirstItem();
+ while (ilst_item) {
+ AP4_ContainerAtom* entry_atom = AP4_DYNAMIC_CAST(AP4_ContainerAtom, ilst_item->GetData());
+ if (entry_atom) {
+ AddIlstEntries(entry_atom, "meta");
+ }
+ ilst_item = ilst_item->GetNext();
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::ParseUdta
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::ParseUdta(AP4_ContainerAtom* udta, const char* namespc)
+{
+ // check that the atom is indeed a 'udta' atom
+ if (udta->GetType() != AP4_ATOM_TYPE_UDTA) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+
+ AP4_List<AP4_Atom>::Item* udta_item = udta->GetChildren().FirstItem();
+ for (; udta_item; udta_item = udta_item->GetNext()) {
+ AP4_3GppLocalizedStringAtom* _3gpp_atom = AP4_DYNAMIC_CAST(AP4_3GppLocalizedStringAtom, udta_item->GetData());
+ if (_3gpp_atom) {
+ Add3GppEntry(_3gpp_atom, namespc);
+ continue;
+ }
+
+ AP4_DcfStringAtom* dcfs_atom = AP4_DYNAMIC_CAST(AP4_DcfStringAtom, udta_item->GetData());
+ if (dcfs_atom) {
+ AddDcfStringEntry(dcfs_atom, namespc);
+ continue;
+ }
+
+ AP4_DcfdAtom* dcfd_atom = AP4_DYNAMIC_CAST(AP4_DcfdAtom, udta_item->GetData());
+ if (dcfd_atom) {
+ AddDcfdEntry(dcfd_atom, namespc);
+ }
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::~AP4_MetaData
++---------------------------------------------------------------------*/
+AP4_MetaData::~AP4_MetaData()
+{
+ m_Entries.DeleteReferences();
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::ResolveKeyName
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::ResolveKeyName(AP4_Atom::Type atom_type, AP4_String& value)
+{
+ const char* key_name = NULL;
+ char four_cc[5];
+
+ // look for a match in the key infos
+ for (unsigned int i=0;
+ i<sizeof(AP4_MetaData_KeyInfos)/sizeof(AP4_MetaData_KeyInfos[0]);
+ i++) {
+ if (AP4_MetaData_KeyInfos[i].four_cc == atom_type) {
+ key_name = AP4_MetaData_KeyInfos[i].name;
+ break;
+ }
+ }
+ if (key_name == NULL) {
+ // this key was not found in the key infos, create a name for it
+ AP4_FormatFourChars(four_cc, (AP4_UI32)atom_type);
+ key_name = four_cc;
+ }
+ value = key_name;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::AddIlstEntries
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::AddIlstEntries(AP4_ContainerAtom* atom, const char* namespc)
+{
+ AP4_MetaData::Value* value = NULL;
+
+ if (atom->GetType() == AP4_ATOM_TYPE_dddd) {
+ // look for the namespace
+ AP4_MetaDataStringAtom* mean = static_cast<AP4_MetaDataStringAtom*>(atom->GetChild(AP4_ATOM_TYPE_MEAN));
+ if (mean == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // look for the name
+ AP4_MetaDataStringAtom* name = static_cast<AP4_MetaDataStringAtom*>(atom->GetChild(AP4_ATOM_TYPE_NAME));
+ if (name == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // get the value
+ AP4_DataAtom* data_atom = static_cast<AP4_DataAtom*>(atom->GetChild(AP4_ATOM_TYPE_DATA));
+ value = new AP4_AtomMetaDataValue(data_atom, atom->GetType());
+ if (value == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ return m_Entries.Add(new Entry(name->GetValue().GetChars(),
+ mean->GetValue().GetChars(),
+ value));
+ } else {
+ const char* key_name = NULL;
+ char four_cc[5];
+
+ // convert the atom type to a name
+ AP4_FormatFourChars(four_cc, (AP4_UI32)atom->GetType());
+ key_name = four_cc;
+
+ // add one entry for each data atom
+ AP4_List<AP4_Atom>::Item* data_item = atom->GetChildren().FirstItem();
+ while (data_item) {
+ AP4_Atom* item_atom = data_item->GetData();
+ if (item_atom->GetType() == AP4_ATOM_TYPE_DATA) {
+ AP4_DataAtom* data_atom = static_cast<AP4_DataAtom*>(item_atom);
+ value = new AP4_AtomMetaDataValue(data_atom, atom->GetType());
+ m_Entries.Add(new Entry(key_name, namespc, value));
+ }
+ data_item = data_item->GetNext();
+ }
+
+ return AP4_SUCCESS;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Add3GppEntry
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Add3GppEntry(AP4_3GppLocalizedStringAtom* atom, const char* namespc)
+{
+ AP4_String key_name;
+ ResolveKeyName(atom->GetType(), key_name);
+
+ const char* language = NULL;
+ if (atom->GetLanguage()[0]) {
+ language = atom->GetLanguage();
+ }
+ AP4_MetaData::Value* value = new AP4_StringMetaDataValue(atom->GetValue().GetChars(),
+ language);
+ m_Entries.Add(new Entry(key_name.GetChars(), namespc, value));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::AddDcfStringEntry
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::AddDcfStringEntry(AP4_DcfStringAtom* atom, const char* namespc)
+{
+ AP4_String key_name;
+ ResolveKeyName(atom->GetType(), key_name);
+
+ AP4_MetaData::Value* value = new AP4_StringMetaDataValue(atom->GetValue().GetChars());
+ m_Entries.Add(new Entry(key_name.GetChars(), namespc, value));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::AddDcfdEntry
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::AddDcfdEntry(AP4_DcfdAtom* atom, const char* namespc)
+{
+ AP4_String key_name;
+ ResolveKeyName(atom->GetType(), key_name);
+
+ AP4_MetaData::Value* value = new AP4_IntegerMetaDataValue(AP4_MetaData::Value::TYPE_INT_32_BE,
+ atom->GetDuration());
+ m_Entries.Add(new Entry(key_name.GetChars(), namespc, value));
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Value::MapDataTypeToCategory
++---------------------------------------------------------------------*/
+AP4_MetaData::Value::TypeCategory
+AP4_MetaData::Value::MapTypeToCategory(Type type)
+{
+ switch (type) {
+ case AP4_MetaData::Value::TYPE_INT_08_BE:
+ case AP4_MetaData::Value::TYPE_INT_16_BE:
+ case AP4_MetaData::Value::TYPE_INT_32_BE:
+ return AP4_MetaData::Value::TYPE_CATEGORY_INTEGER;
+
+ case AP4_MetaData::Value::TYPE_STRING_UTF_8:
+ case AP4_MetaData::Value::TYPE_STRING_UTF_16:
+ case AP4_MetaData::Value::TYPE_STRING_PASCAL:
+ return AP4_MetaData::Value::TYPE_CATEGORY_STRING;
+
+ case AP4_MetaData::Value::TYPE_FLOAT_32_BE:
+ case AP4_MetaData::Value::TYPE_FLOAT_64_BE:
+ return AP4_MetaData::Value::TYPE_CATEGORY_FLOAT;
+
+ default:
+ return AP4_MetaData::Value::TYPE_CATEGORY_BINARY;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Value::GetTypeCategory
++---------------------------------------------------------------------*/
+AP4_MetaData::Value::TypeCategory
+AP4_MetaData::Value::GetTypeCategory() const
+{
+ return MapTypeToCategory(m_Type);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::ToAtom
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Entry::ToAtom(AP4_Atom*& atom) const
+{
+ atom = NULL;
+
+ if (m_Value == NULL) {
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+
+ if (m_Key.GetNamespace() == "meta") {
+ // convert the name into an atom type
+ if (m_Key.GetName().GetLength() != 4) {
+ // the name is not in the right format
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+ AP4_Atom::Type atom_type = AP4_Atom::TypeFromString(m_Key.GetName().GetChars());
+
+ // create a container atom for the data
+ AP4_ContainerAtom* container = new AP4_ContainerAtom(atom_type);
+
+ // add the data atom
+ AP4_DataAtom* data = new AP4_DataAtom(*m_Value);
+ container->AddChild(data);
+
+ atom = container;
+ return AP4_SUCCESS;
+ } else if (m_Key.GetNamespace() == "dcf") {
+ // convert the name into an atom type
+ if (m_Key.GetName().GetLength() != 4) {
+ // the name is not in the right format
+ return AP4_ERROR_INVALID_PARAMETERS;
+ }
+ AP4_Atom::Type atom_type = AP4_Atom::TypeFromString(m_Key.GetName().GetChars());
+
+ if (AP4_MetaDataAtomTypeHandler::IsTypeInList(atom_type,
+ AP4_MetaDataAtomTypeHandler::DcfStringTypeList)) {
+ AP4_String atom_value = m_Value->ToString();
+ atom = new AP4_DcfStringAtom(atom_type, atom_value.GetChars());
+ return AP4_SUCCESS;
+ } else if (AP4_MetaDataAtomTypeHandler::IsTypeInList(atom_type,
+ AP4_MetaDataAtomTypeHandler::_3gppLocalizedStringTypeList)) {
+ AP4_String atom_value = m_Value->ToString();
+ const char* language = "eng"; // default
+ if (m_Value->GetLanguage().GetLength() != 0) {
+ language = m_Value->GetLanguage().GetChars();
+ }
+ atom = new AP4_3GppLocalizedStringAtom(atom_type, language, atom_value.GetChars());
+ return AP4_SUCCESS;
+ } else if (atom_type == AP4_ATOM_TYPE_DCFD) {
+ atom = new AP4_DcfdAtom(m_Value->ToInteger());
+ return AP4_SUCCESS;
+ }
+
+ // not supported
+ return AP4_ERROR_NOT_SUPPORTED;
+ } else {
+ // create a '----' atom
+ AP4_ContainerAtom* container = new AP4_ContainerAtom(AP4_ATOM_TYPE_dddd);
+
+ // add a 'mean' string
+ container->AddChild(new AP4_MetaDataStringAtom(AP4_ATOM_TYPE_MEAN, m_Key.GetNamespace().GetChars()));
+
+ // add a 'name' string
+ container->AddChild(new AP4_MetaDataStringAtom(AP4_ATOM_TYPE_NAME, m_Key.GetName().GetChars()));
+
+ // add the data atom
+ AP4_DataAtom* data = new AP4_DataAtom(*m_Value);
+ container->AddChild(data);
+
+ atom = container;
+ return AP4_SUCCESS;
+ }
+
+ return AP4_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::FindInIlst
++---------------------------------------------------------------------*/
+AP4_ContainerAtom*
+AP4_MetaData::Entry::FindInIlst(AP4_ContainerAtom* ilst) const
+{
+ if (m_Key.GetNamespace() == "meta") {
+ AP4_Atom::Type atom_type = AP4_Atom::TypeFromString(m_Key.GetName().GetChars());
+ return AP4_DYNAMIC_CAST(AP4_ContainerAtom, ilst->GetChild(atom_type));
+ } else {
+ AP4_List<AP4_Atom>::Item* ilst_item = ilst->GetChildren().FirstItem();
+ while (ilst_item) {
+ AP4_ContainerAtom* entry_atom = AP4_DYNAMIC_CAST(AP4_ContainerAtom, ilst_item->GetData());
+ if (entry_atom) {
+ AP4_MetaDataStringAtom* mean = static_cast<AP4_MetaDataStringAtom*>(entry_atom->GetChild(AP4_ATOM_TYPE_MEAN));
+ AP4_MetaDataStringAtom* name = static_cast<AP4_MetaDataStringAtom*>(entry_atom->GetChild(AP4_ATOM_TYPE_NAME));
+ if (mean && name &&
+ mean->GetValue() == m_Key.GetNamespace() &&
+ name->GetValue() == m_Key.GetName()) {
+ return entry_atom;
+ }
+ }
+ ilst_item = ilst_item->GetNext();
+ }
+ }
+
+ // not found
+ return NULL;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::AddToFileIlst
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Entry::AddToFileIlst(AP4_File& file, AP4_Ordinal index)
+{
+ // check that we have a correct entry
+ if (m_Value == NULL) return AP4_ERROR_INVALID_STATE;
+
+ // convert the entry into an atom
+ AP4_Atom* atom;
+ AP4_Result result = ToAtom(atom);
+ if (AP4_FAILED(result)) return result;
+ AP4_ContainerAtom* entry_atom = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom);
+ if (entry_atom == NULL) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+
+ // look for the 'moov'
+ AP4_Movie* movie = file.GetMovie();
+ if (movie == NULL) return AP4_ERROR_INVALID_FORMAT;
+ AP4_MoovAtom* moov = movie->GetMoovAtom();
+ if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // look for 'udta', and create if it does not exist
+ AP4_ContainerAtom* udta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moov->FindChild("udta", true));
+ if (udta == NULL) return AP4_ERROR_INTERNAL;
+
+ // look for 'meta', and create if it does not exist ('meta' is a FULL atom)
+ AP4_ContainerAtom* meta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, udta->FindChild("meta", true, true));
+ if (meta == NULL) return AP4_ERROR_INTERNAL;
+
+ // look for a 'hdlr' atom type 'mdir'
+ AP4_HdlrAtom* hdlr = AP4_DYNAMIC_CAST(AP4_HdlrAtom, meta->FindChild("hdlr"));
+ if (hdlr == NULL) {
+ hdlr = new AP4_HdlrAtom(AP4_HANDLER_TYPE_MDIR, "");
+ meta->AddChild(hdlr);
+ } else {
+ if (hdlr->GetHandlerType() != AP4_HANDLER_TYPE_MDIR) {
+ return AP4_ERROR_INVALID_FORMAT;
+ }
+ }
+
+ // get/create the list of entries
+ AP4_ContainerAtom* ilst = AP4_DYNAMIC_CAST(AP4_ContainerAtom, meta->FindChild("ilst", true));
+ if (ilst == NULL) return AP4_ERROR_INTERNAL;
+
+ // look if there is already a container for this entry
+ AP4_ContainerAtom* existing = FindInIlst(ilst);
+ if (existing == NULL) {
+ // just add the one we have
+ ilst->AddChild(entry_atom);
+ } else {
+ // add the entry's data to the existing entry
+ AP4_DataAtom* data_atom = AP4_DYNAMIC_CAST(AP4_DataAtom, entry_atom->GetChild(AP4_ATOM_TYPE_DATA));
+ if (data_atom == NULL) return AP4_ERROR_INTERNAL;
+ entry_atom->RemoveChild(data_atom);
+ existing->AddChild(data_atom, index);
+ delete entry_atom;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::AddToFileDcf
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Entry::AddToFileDcf(AP4_File& file, AP4_Ordinal index)
+{
+ // check that we have a correct entry
+ if (m_Value == NULL) return AP4_ERROR_INVALID_STATE;
+
+ // look for 'odrm/odhe'
+ AP4_ContainerAtom* odhe = AP4_DYNAMIC_CAST(AP4_ContainerAtom, file.FindChild("odrm/odhe"));
+ if (odhe == NULL) return AP4_ERROR_NO_SUCH_ITEM;
+
+ // get/create the list of entries
+ AP4_ContainerAtom* udta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, odhe->FindChild("udta", true));
+ if (udta == NULL) return AP4_ERROR_INTERNAL;
+
+ // convert the entry into an atom
+ AP4_Atom* data_atom;
+ AP4_Result result = ToAtom(data_atom);
+ if (AP4_FAILED(result)) return result;
+
+ // add the entry's data to the container
+ return udta->AddChild(data_atom, index);
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::AddToFile
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Entry::AddToFile(AP4_File& file, AP4_Ordinal index)
+{
+ // check that we have a correct entry
+ if (m_Value == NULL) return AP4_ERROR_INVALID_STATE;
+
+ // check the namespace of the key to know where to add the atom
+ if (m_Key.GetNamespace() == "meta") {
+ return AddToFileIlst(file, index);
+ } else if (m_Key.GetNamespace() == "dcf") {
+ return AddToFileDcf(file, index);
+ } else {
+ // custom namespace
+ return AddToFileIlst(file, index);
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::RemoveFromFileIlst
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Entry::RemoveFromFileIlst(AP4_File& file, AP4_Ordinal index)
+{
+ // look for the 'moov'
+ AP4_Movie* movie = file.GetMovie();
+ if (movie == NULL) return AP4_ERROR_INVALID_FORMAT;
+ AP4_MoovAtom* moov = movie->GetMoovAtom();
+ if (moov == NULL) return AP4_ERROR_INVALID_FORMAT;
+
+ // look for 'udta/meta/ilst'
+ AP4_ContainerAtom* ilst = AP4_DYNAMIC_CAST(AP4_ContainerAtom, moov->FindChild("udta/meta/ilst"));
+ if (ilst == NULL) return AP4_ERROR_NO_SUCH_ITEM;
+
+ // look if there is already a container for this entry
+ AP4_ContainerAtom* existing = FindInIlst(ilst);
+ if (existing == NULL) return AP4_ERROR_NO_SUCH_ITEM;
+
+ // remove the data atom in the entry
+ AP4_Result result = existing->DeleteChild(AP4_ATOM_TYPE_DATA, index);
+ if (AP4_FAILED(result)) return result;
+
+ // if the entry is empty, remove it
+ if (existing->GetChildren().ItemCount() == 0) {
+ ilst->RemoveChild(existing);
+ delete existing;
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::RemoveFromFileDcf
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Entry::RemoveFromFileDcf(AP4_File& file, AP4_Ordinal index)
+{
+ // look for 'odrm/odhe/udta'
+ AP4_ContainerAtom* udta = AP4_DYNAMIC_CAST(AP4_ContainerAtom, file.FindChild("odrm/odhe/udta"));
+ if (udta == NULL) return AP4_ERROR_NO_SUCH_ITEM;
+
+ // remove the data atom in the entry
+ AP4_UI32 type = AP4_BytesToUInt32BE((const unsigned char*)m_Key.GetName().GetChars());
+ AP4_Result result = udta->DeleteChild(type, index);
+ if (AP4_FAILED(result)) return result;
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaData::Entry::RemoveFromFile
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaData::Entry::RemoveFromFile(AP4_File& file, AP4_Ordinal index)
+{
+ // check the namespace of the key to know where to add the atom
+ if (m_Key.GetNamespace() == "meta") {
+ return RemoveFromFileIlst(file, index);
+ } else if (m_Key.GetNamespace() == "dcf") {
+ return RemoveFromFileDcf(file, index);
+ } else {
+ // unsupported namespace
+ return AP4_ERROR_NOT_SUPPORTED;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_StringMetaDataValue::ToString
++---------------------------------------------------------------------*/
+AP4_String
+AP4_StringMetaDataValue::ToString() const
+{
+ return m_Value;
+}
+
+/*----------------------------------------------------------------------
+| AP4_StringMetaDataValue::ToBytes
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_StringMetaDataValue::ToBytes(AP4_DataBuffer& /* bytes */) const
+{
+ return AP4_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| AP4_StringMetaDataValue::ToInteger
++---------------------------------------------------------------------*/
+long
+AP4_StringMetaDataValue::ToInteger() const
+{
+ return 0;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IntegerMetaDataValue::ToString
++---------------------------------------------------------------------*/
+AP4_String
+AP4_IntegerMetaDataValue::ToString() const
+{
+ char value[16];
+ AP4_FormatString(value, sizeof(value), "%ld", m_Value);
+ return AP4_String(value);
+}
+
+/*----------------------------------------------------------------------
+| AP4_IntegerMetaDataValue::ToBytes
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_IntegerMetaDataValue::ToBytes(AP4_DataBuffer& /* bytes */) const
+{
+ return AP4_ERROR_NOT_SUPPORTED;
+}
+
+/*----------------------------------------------------------------------
+| AP4_IntegerMetaDataValue::ToInteger
++---------------------------------------------------------------------*/
+long
+AP4_IntegerMetaDataValue::ToInteger() const
+{
+ return m_Value;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BinaryMetaDataValue::ToString
++---------------------------------------------------------------------*/
+AP4_String
+AP4_BinaryMetaDataValue::ToString() const
+{
+ return AP4_String(); // not supported
+}
+
+/*----------------------------------------------------------------------
+| AP4_BinaryMetaDataValue::ToBytes
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_BinaryMetaDataValue::ToBytes(AP4_DataBuffer& bytes) const
+{
+ bytes.SetDataSize(m_Value.GetDataSize());
+ AP4_CopyMemory(bytes.UseData(), m_Value.GetData(), m_Value.GetDataSize());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_BinaryMetaDataValue::ToInteger
++---------------------------------------------------------------------*/
+long
+AP4_BinaryMetaDataValue::ToInteger() const
+{
+ return 0; // NOT SUPPORTED
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomMetaDataValue::AP4_AtomMetaDataValue
++---------------------------------------------------------------------*/
+AP4_AtomMetaDataValue::AP4_AtomMetaDataValue(AP4_DataAtom* atom,
+ AP4_UI32 parent_type) :
+ Value(atom->GetValueType()),
+ m_DataAtom(atom)
+{
+ switch (parent_type) {
+ case AP4_ATOM_TYPE_GNRE:
+ m_Meaning = MEANING_ID3_GENRE;
+ break;
+
+ case AP4_ATOM_TYPE_CPIL:
+ m_Meaning = MEANING_BOOLEAN;
+ break;
+
+ case AP4_ATOM_TYPE_PGAP:
+ case AP4_ATOM_TYPE_PCST:
+ m_Meaning = MEANING_BOOLEAN;
+ break;
+
+ case AP4_ATOM_TYPE_STIK:
+ m_Meaning = MEANING_FILE_KIND;
+ break;
+
+ case AP4_ATOM_TYPE_PURL:
+ case AP4_ATOM_TYPE_EGID:
+ m_Meaning = MEANING_BINARY_ENCODED_CHARS;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomMetaDataValue::ToString
++---------------------------------------------------------------------*/
+AP4_String
+AP4_AtomMetaDataValue::ToString() const
+{
+ char string[256] = "";
+
+ AP4_MetaData::Value::Type value_type = m_DataAtom->GetValueType();
+ switch (AP4_MetaData::Value::MapTypeToCategory(value_type)) {
+ case AP4_MetaData::Value::TYPE_CATEGORY_INTEGER:
+ {
+ long value;
+ if (AP4_SUCCEEDED(m_DataAtom->LoadInteger(value))) {
+ if (m_Meaning == MEANING_BOOLEAN) {
+ if (value) {
+ return "True";
+ } else {
+ return "False";
+ }
+ } else if (m_Meaning == MEANING_FILE_KIND) {
+ if (value >= 0 && ((unsigned int)value) <= sizeof(Ap4StikNames)/sizeof(Ap4StikNames[0])) {
+ AP4_FormatString(string, sizeof(string), "(%ld) %s", value, Ap4StikNames[value]);
+ } else {
+ return "Unknown";
+ }
+ } else {
+ AP4_FormatString(string, sizeof(string), "%ld", value);
+ }
+ }
+ return AP4_String((const char*)string);
+ break;
+ }
+
+ case AP4_MetaData::Value::TYPE_CATEGORY_STRING:
+ {
+ AP4_String* category_string;
+ if (AP4_SUCCEEDED(m_DataAtom->LoadString(category_string))) {
+ AP4_String result(*category_string);
+ delete category_string;
+ return result;
+ }
+ break;
+ }
+
+ case AP4_MetaData::Value::TYPE_CATEGORY_BINARY:
+ {
+ AP4_DataBuffer data;
+ if (AP4_SUCCEEDED(m_DataAtom->LoadBytes(data))) {
+ if (m_Meaning == MEANING_ID3_GENRE && data.GetDataSize() == 2) {
+ unsigned int genre = (data.GetData()[0])*256+data.GetData()[1];
+ if (genre >= 1 && genre <= sizeof(Ap4Id3Genres)/sizeof(Ap4Id3Genres[0])) {
+ AP4_FormatString(string, sizeof(string), "(%d) %s", genre, Ap4Id3Genres[genre-1]);
+ return AP4_String((const char*)string);
+ } else {
+ return "Unknown";
+ }
+ } else if (m_Meaning == MEANING_BINARY_ENCODED_CHARS) {
+ AP4_String result;
+ result.Assign((const char*)data.GetData(), data.GetDataSize());
+ return result;
+ } else {
+ unsigned int dump_length = data.GetDataSize();
+ bool truncate = false;
+ if (dump_length > 16) {
+ dump_length = 16;
+ truncate = true;
+ }
+ char* out = string;
+ for (unsigned int i=0; i<dump_length; i++) {
+ AP4_FormatString(out, sizeof(string)-(out-string), "%02x ", data.GetData()[i]);
+ out += 3;
+ }
+ if (truncate) {
+ *out++='.'; *out++='.'; *out++='.'; *out++=' ';
+ }
+ AP4_FormatString(out, sizeof(string)-(out-string), "[%d bytes]", (int)data.GetDataSize());
+ }
+ }
+ return AP4_String(string);
+ }
+ default:
+ return AP4_String();
+ }
+
+ return AP4_String();
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomMetaDataValue::ToBytes
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_AtomMetaDataValue::ToBytes(AP4_DataBuffer& bytes) const
+{
+ return m_DataAtom->LoadBytes(bytes);
+}
+
+/*----------------------------------------------------------------------
+| AP4_AtomMetaDataValue::ToInteger
++---------------------------------------------------------------------*/
+long
+AP4_AtomMetaDataValue::ToInteger() const
+{
+ long value;
+ if (AP4_SUCCEEDED(m_DataAtom->LoadInteger(value))) {
+ return value;
+ } else {
+ return 0;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::AP4_DataAtom
++---------------------------------------------------------------------*/
+AP4_DataAtom::AP4_DataAtom(const AP4_MetaData::Value& value) :
+ AP4_Atom(AP4_ATOM_TYPE_DATA, AP4_ATOM_HEADER_SIZE),
+ m_DataType(DATA_TYPE_BINARY)
+{
+ AP4_MemoryByteStream* memory = new AP4_MemoryByteStream(256);
+ AP4_Size payload_size = 8;
+ m_Source = memory;
+
+ switch (value.GetType()) {
+ case AP4_MetaData::Value::TYPE_STRING_UTF_8: {
+ m_DataType = DATA_TYPE_STRING_UTF_8;
+ AP4_String string_value = value.ToString();
+ if (string_value.GetLength()) {
+ memory->Write(string_value.GetChars(), string_value.GetLength());
+ }
+ payload_size += string_value.GetLength();
+ break;
+ }
+
+ case AP4_MetaData::Value::TYPE_INT_08_BE: {
+ m_DataType = DATA_TYPE_SIGNED_INT_BE;
+ AP4_UI08 int_value = (AP4_UI08)value.ToInteger();
+ memory->Write(&int_value, 1);
+ payload_size += 1;
+ break;
+ }
+
+ case AP4_MetaData::Value::TYPE_INT_16_BE: {
+ m_DataType = DATA_TYPE_SIGNED_INT_BE;
+ AP4_UI16 int_value = (AP4_UI16)value.ToInteger();
+ memory->Write(&int_value, 2);
+ payload_size += 2;
+ break;
+ }
+
+ case AP4_MetaData::Value::TYPE_INT_32_BE: {
+ m_DataType = DATA_TYPE_SIGNED_INT_BE;
+ AP4_UI32 int_value = (AP4_UI32)value.ToInteger();
+ memory->Write(&int_value, 4);
+ payload_size += 4;
+ break;
+ }
+
+ case AP4_MetaData::Value::TYPE_JPEG:
+ m_DataType = DATA_TYPE_JPEG;
+ // FALLTHROUGH
+ case AP4_MetaData::Value::TYPE_GIF:
+ if (m_DataType == DATA_TYPE_BINARY) m_DataType = DATA_TYPE_GIF;
+ // FALLTHROUGH
+ case AP4_MetaData::Value::TYPE_BINARY: {
+ AP4_DataBuffer buffer;
+ value.ToBytes(buffer);
+ if (buffer.GetDataSize()) {
+ memory->Write(buffer.GetData(), buffer.GetDataSize());
+ }
+ payload_size += buffer.GetDataSize();
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ const AP4_String& language = value.GetLanguage();
+ if (language == "en") {
+ m_DataLang = LANGUAGE_ENGLISH;
+ } else {
+ // default
+ m_DataLang = LANGUAGE_ENGLISH;
+ }
+
+ m_Size32 += payload_size;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::AP4_DataAtom
++---------------------------------------------------------------------*/
+AP4_DataAtom::AP4_DataAtom(AP4_UI32 size, AP4_ByteStream& stream) :
+ AP4_Atom(AP4_ATOM_TYPE_DATA, size)
+{
+ if (size < AP4_ATOM_HEADER_SIZE+8) return;
+
+ AP4_UI32 i;
+ stream.ReadUI32(i); m_DataType = (DataType)i;
+ stream.ReadUI32(i); m_DataLang = (DataLang)i;
+
+ // the stream for the data is a substream of this source
+ AP4_Position data_offset;
+ stream.Tell(data_offset);
+ AP4_Size data_size = size-AP4_ATOM_HEADER_SIZE-8;
+ m_Source = new AP4_SubStream(stream, data_offset, data_size);
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::~AP4_DataAtom
++---------------------------------------------------------------------*/
+AP4_DataAtom::~AP4_DataAtom()
+{
+ delete(m_Source);
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::GetValueType
++---------------------------------------------------------------------*/
+AP4_MetaData::Value::Type
+AP4_DataAtom::GetValueType()
+{
+ switch (m_DataType) {
+ case DATA_TYPE_BINARY:
+ return AP4_MetaData::Value::TYPE_BINARY;
+
+ case DATA_TYPE_SIGNED_INT_BE:
+ switch (m_Size32-16) {
+ case 1: return AP4_MetaData::Value::TYPE_INT_08_BE;
+ case 2: return AP4_MetaData::Value::TYPE_INT_16_BE;
+ case 4: return AP4_MetaData::Value::TYPE_INT_32_BE;
+ default: return AP4_MetaData::Value::TYPE_BINARY;
+ }
+ break;
+
+ case DATA_TYPE_STRING_UTF_8:
+ return AP4_MetaData::Value::TYPE_STRING_UTF_8;
+
+ case DATA_TYPE_STRING_UTF_16:
+ return AP4_MetaData::Value::TYPE_STRING_UTF_16;
+
+ case DATA_TYPE_STRING_PASCAL:
+ return AP4_MetaData::Value::TYPE_STRING_PASCAL;
+
+ case DATA_TYPE_GIF:
+ return AP4_MetaData::Value::TYPE_GIF;
+
+ case DATA_TYPE_JPEG:
+ return AP4_MetaData::Value::TYPE_JPEG;
+
+ default:
+ return AP4_MetaData::Value::TYPE_BINARY;
+ }
+
+ return AP4_MetaData::Value::TYPE_BINARY;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataAtom::WriteFields(AP4_ByteStream& stream)
+{
+ stream.WriteUI32(m_DataType);
+ stream.WriteUI32(m_DataLang);
+ if (m_Source) {
+ AP4_LargeSize size = 0;
+ m_Source->GetSize(size);
+ m_Source->Seek(0);
+ m_Source->CopyTo(stream, size);
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("type", m_DataType);
+ inspector.AddField("lang", m_DataLang);
+ if (m_DataType == DATA_TYPE_STRING_UTF_8) {
+ AP4_String* str;
+ if (AP4_SUCCEEDED(LoadString(str))) {
+ inspector.AddField("value", str->GetChars());
+ delete str;
+ }
+ } else if (m_DataType == DATA_TYPE_SIGNED_INT_BE) {
+ long value;
+ if (AP4_SUCCEEDED(LoadInteger(value))) {
+ inspector.AddField("value", value);
+ }
+ }
+
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::LoadString
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataAtom::LoadString(AP4_String*& string)
+{
+ if (m_Source == NULL) {
+ string = new AP4_String();
+ return AP4_SUCCESS;
+ } else {
+ // create a string with enough capactiy for the data
+ AP4_LargeSize size = 0;
+ m_Source->GetSize(size);
+ if (size > AP4_DATA_ATOM_MAX_SIZE) return AP4_ERROR_OUT_OF_RANGE;
+ string = new AP4_String((AP4_Size)size);
+
+ // read from the start of the stream
+ m_Source->Seek(0);
+ AP4_Result result = m_Source->Read(string->UseChars(), (AP4_Size)size);
+ if (AP4_FAILED(result)) {
+ delete string;
+ string = NULL;
+ }
+
+ return result;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::LoadBytes
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataAtom::LoadBytes(AP4_DataBuffer& bytes)
+{
+ if (m_Source == NULL) {
+ bytes.SetDataSize(0);
+ return AP4_SUCCESS;
+ }
+ AP4_LargeSize size = 0;
+ m_Source->GetSize(size);
+ if (size > AP4_DATA_ATOM_MAX_SIZE) return AP4_ERROR_OUT_OF_RANGE;
+ bytes.SetDataSize((AP4_Size)size);
+ m_Source->Seek(0);
+ AP4_Result result = m_Source->Read(bytes.UseData(), (AP4_Size)size);
+ if (AP4_FAILED(result)) {
+ bytes.SetDataSize(0);
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DataAtom::LoadInteger
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DataAtom::LoadInteger(long& value)
+{
+ AP4_Result result = AP4_FAILURE;
+ value = 0;
+ if (m_Source == NULL) return AP4_SUCCESS;
+ AP4_LargeSize size = 0;
+ m_Source->GetSize(size);
+ if (size > 4) {
+ return AP4_ERROR_OUT_OF_RANGE;
+ }
+ unsigned char bytes[4];
+ m_Source->Seek(0);
+ m_Source->Read(bytes, (AP4_Size)size);
+ result = AP4_SUCCESS;
+ switch (size) {
+ case 1: value = bytes[0]; break;
+ case 2: value = AP4_BytesToInt16BE(bytes); break;
+ case 4: value = AP4_BytesToInt32BE(bytes); break;
+ default: value = 0; result = AP4_ERROR_INVALID_FORMAT; break;
+ }
+ return result;
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaDataStringAtom::AP4_MetaDataStringAtom
++---------------------------------------------------------------------*/
+AP4_MetaDataStringAtom::AP4_MetaDataStringAtom(Type type, const char* value) :
+ AP4_Atom(type, AP4_ATOM_HEADER_SIZE),
+ m_Value(value)
+{
+ m_Size32 += 4+m_Value.GetLength();
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaDataStringAtom::AP4_MetaDataStringAtom
++---------------------------------------------------------------------*/
+AP4_MetaDataStringAtom::AP4_MetaDataStringAtom(Type type, AP4_UI32 size, AP4_ByteStream& stream) :
+ AP4_Atom(type, size),
+ m_Value((AP4_Size)(size-AP4_ATOM_HEADER_SIZE-4))
+{
+ stream.ReadUI32(m_Reserved);
+ stream.Read(m_Value.UseChars(), m_Value.GetLength());
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaDataStringAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaDataStringAtom::WriteFields(AP4_ByteStream& stream)
+{
+ stream.WriteUI32(m_Reserved);
+ return stream.Write(m_Value.GetChars(), m_Value.GetLength());
+}
+
+/*----------------------------------------------------------------------
+| AP4_MetaDataStringAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_MetaDataStringAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("value", m_Value.GetChars());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_3GppLocalizedStringAtom::Create
++---------------------------------------------------------------------*/
+AP4_3GppLocalizedStringAtom*
+AP4_3GppLocalizedStringAtom::Create(Type type, AP4_UI32 size, AP4_ByteStream& stream)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version != 0) return NULL;
+ return new AP4_3GppLocalizedStringAtom(type, size, version, flags, stream);
+}
+
+/*----------------------------------------------------------------------
+| AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom
++---------------------------------------------------------------------*/
+AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom(Type type,
+ const char* language,
+ const char* value) :
+ AP4_Atom(type, AP4_FULL_ATOM_HEADER_SIZE+2, 0, 0),
+ m_Value(value)
+{
+ m_Language[0] = language[0];
+ m_Language[1] = language[1];
+ m_Language[2] = language[2];
+ m_Language[3] = language[3];
+
+ m_Size32 += m_Value.GetLength()+1;
+}
+
+/*----------------------------------------------------------------------
+| AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom
++---------------------------------------------------------------------*/
+AP4_3GppLocalizedStringAtom::AP4_3GppLocalizedStringAtom(Type type,
+ AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream) :
+ AP4_Atom(type, size, version, flags)
+{
+ // read the language code
+ AP4_UI16 packed_language;
+ stream.ReadUI16(packed_language);
+ m_Language[0] = 0x60+((packed_language>>10)&0x1F);
+ m_Language[1] = 0x60+((packed_language>> 5)&0x1F);
+ m_Language[2] = 0x60+((packed_language )&0x1F);
+ m_Language[3] = '\0';
+
+ // read the value (should be a NULL-terminated string, but we'll
+ // allow for strings that are not terminated)
+ if (size > AP4_FULL_ATOM_HEADER_SIZE+2) {
+ AP4_UI32 value_size = size-(AP4_FULL_ATOM_HEADER_SIZE+2);
+ char* value = new char[value_size];
+ stream.Read(value, value_size);
+ m_Value.Assign(value, value_size);
+ delete[] value;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_3GppLocalizedStringAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_3GppLocalizedStringAtom::WriteFields(AP4_ByteStream& stream)
+{
+ AP4_UI16 packed_language = ((m_Language[0]-0x60)<<10) |
+ ((m_Language[1]-0x60)<< 5) |
+ ((m_Language[2]-0x60));
+ stream.WriteUI16(packed_language);
+ AP4_Size payload_size = (AP4_UI32)GetSize()-GetHeaderSize();
+ if (payload_size < 2) return AP4_ERROR_INVALID_FORMAT;
+ AP4_Size value_size = m_Value.GetLength()+1;
+ if (value_size > payload_size-2) {
+ value_size = payload_size-2;
+ }
+ stream.Write(m_Value.GetChars(), value_size);
+ for (unsigned int i=value_size; i<payload_size-2; i++) {
+ stream.WriteUI08(0);
+ }
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_3GppLocalizedStringAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_3GppLocalizedStringAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("language", GetLanguage());
+ inspector.AddField("value", m_Value.GetChars());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfStringAtom::Create
++---------------------------------------------------------------------*/
+AP4_DcfStringAtom*
+AP4_DcfStringAtom::Create(Type type, AP4_UI32 size, AP4_ByteStream& stream)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version != 0) return NULL;
+ return new AP4_DcfStringAtom(type, size, version, flags, stream);
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfStringAtom::AP4_DcfStringAtom
++---------------------------------------------------------------------*/
+AP4_DcfStringAtom::AP4_DcfStringAtom(Type type, const char* value) :
+ AP4_Atom(type, AP4_FULL_ATOM_HEADER_SIZE, 0, 0),
+ m_Value(value)
+{
+ m_Size32 += m_Value.GetLength();
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfStringAtom::AP4_DcfStringAtom
++---------------------------------------------------------------------*/
+AP4_DcfStringAtom::AP4_DcfStringAtom(Type type,
+ AP4_UI32 size,
+ AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream) :
+ AP4_Atom(type, size, version, flags)
+{
+ if (size > AP4_FULL_ATOM_HEADER_SIZE) {
+ AP4_UI32 value_size = size-(AP4_FULL_ATOM_HEADER_SIZE);
+ char* value = new char[value_size];
+ stream.Read(value, value_size);
+ m_Value.Assign(value, value_size);
+ delete[] value;
+ }
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfStringAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DcfStringAtom::WriteFields(AP4_ByteStream& stream)
+{
+ if (m_Value.GetLength()) stream.Write(m_Value.GetChars(), m_Value.GetLength());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfStringAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DcfStringAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("value", m_Value.GetChars());
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfdAtom::Create
++---------------------------------------------------------------------*/
+AP4_DcfdAtom*
+AP4_DcfdAtom::Create(AP4_UI32 size, AP4_ByteStream& stream)
+{
+ AP4_UI32 version;
+ AP4_UI32 flags;
+ if (AP4_FAILED(AP4_Atom::ReadFullHeader(stream, version, flags))) return NULL;
+ if (version != 0) return NULL;
+ if (size != AP4_FULL_ATOM_HEADER_SIZE+4) return NULL;
+ return new AP4_DcfdAtom(version, flags, stream);
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfdAtom::AP4_DcfdAtom
++---------------------------------------------------------------------*/
+AP4_DcfdAtom::AP4_DcfdAtom(AP4_UI32 version,
+ AP4_UI32 flags,
+ AP4_ByteStream& stream) :
+ AP4_Atom(AP4_ATOM_TYPE_DCFD, AP4_FULL_ATOM_HEADER_SIZE+4, version, flags)
+{
+ stream.ReadUI32(m_Duration);
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfdAtom::AP4_DcfdAtom
++---------------------------------------------------------------------*/
+AP4_DcfdAtom::AP4_DcfdAtom(AP4_UI32 duration) :
+ AP4_Atom(AP4_ATOM_TYPE_DCFD, AP4_FULL_ATOM_HEADER_SIZE+4, 0, 0),
+ m_Duration(duration)
+{
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfdAtom::WriteFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DcfdAtom::WriteFields(AP4_ByteStream& stream)
+{
+ stream.WriteUI32(m_Duration);
+ return AP4_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+| AP4_DcfdAtom::InspectFields
++---------------------------------------------------------------------*/
+AP4_Result
+AP4_DcfdAtom::InspectFields(AP4_AtomInspector& inspector)
+{
+ inspector.AddField("duration", m_Duration);
+ return AP4_SUCCESS;
+}