aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/libmp4v2/mp4.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/external_dependencies/libmp4v2/mp4.cpp')
-rw-r--r--Src/external_dependencies/libmp4v2/mp4.cpp4642
1 files changed, 4642 insertions, 0 deletions
diff --git a/Src/external_dependencies/libmp4v2/mp4.cpp b/Src/external_dependencies/libmp4v2/mp4.cpp
new file mode 100644
index 00000000..2f7ff236
--- /dev/null
+++ b/Src/external_dependencies/libmp4v2/mp4.cpp
@@ -0,0 +1,4642 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is MPEG4IP.
+ *
+ * The Initial Developer of the Original Code is Cisco Systems Inc.
+ * Portions created by Cisco Systems Inc. are
+ * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved.
+ *
+ * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
+ * and was contributed by Ximpo Group Ltd.
+ *
+ * Portions created by Ximpo Group Ltd. are
+ * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dave Mackie dmackie@cisco.com
+ * Alix Marchandise-Franquet alix@cisco.com
+ * Ximpo Group Ltd. mp4v2@ximpo.com
+ * Bill May wmay@cisco.com
+ */
+
+/*
+ * MP4 library API functions
+ *
+ * These are wrapper functions that provide C linkage conventions
+ * to the library, and catch any internal errors, ensuring that
+ * a proper return value is given.
+ */
+
+#include "mp4common.h"
+
+#define PRINT_ERROR(e) \
+ VERBOSE_ERROR(((MP4File*)hFile)->GetVerbosity(), e->Print());
+
+/* file operations */
+// benski>
+ extern "C" MP4FileHandle MP4ReadEx (const MP4_FILENAME_CHAR *fileName,
+ void *user,
+ struct Virtual_IO *virtual_IO,
+ u_int32_t verbosity)
+{
+ MP4File* pFile = NULL;
+ try {
+ pFile = new MP4File(verbosity);
+
+ pFile->ReadEx(fileName, user, virtual_IO);
+ return (MP4FileHandle)pFile;
+ } catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ delete pFile;
+ return MP4_INVALID_FILE_HANDLE;
+ }
+}
+
+extern "C" MP4FileHandle MP4Read(const MP4_FILENAME_CHAR *fileName, u_int32_t verbosity)
+{
+ MP4File* pFile = NULL;
+ try {
+ pFile = new MP4File(verbosity);
+ pFile->Read(fileName);
+ return (MP4FileHandle)pFile;
+ }
+ catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ delete pFile;
+ return MP4_INVALID_FILE_HANDLE;
+ }
+}
+
+extern "C" MP4FileHandle MP4Create (const MP4_FILENAME_CHAR *fileName,
+ u_int32_t verbosity,
+ u_int32_t flags)
+{
+ return MP4CreateEx(fileName, verbosity, flags);
+}
+
+extern "C" MP4FileHandle MP4CreateEx (const MP4_FILENAME_CHAR *fileName,
+ u_int32_t verbosity,
+ u_int32_t flags,
+ int add_ftyp,
+ int add_iods,
+ char* majorBrand,
+ u_int32_t minorVersion,
+ char** supportedBrands,
+ u_int32_t supportedBrandsCount)
+{
+ MP4File* pFile = NULL;
+ try {
+ pFile = new MP4File(verbosity);
+ // LATER useExtensibleFormat, moov first, then mvex's
+ pFile->Create(fileName, flags, add_ftyp, add_iods,
+ majorBrand, minorVersion,
+ supportedBrands, supportedBrandsCount);
+ return (MP4FileHandle)pFile;
+ }
+ catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ delete pFile;
+ return MP4_INVALID_FILE_HANDLE;
+ }
+}
+
+extern "C" MP4FileHandle MP4Modify(const MP4_FILENAME_CHAR *fileName,
+ u_int32_t verbosity, u_int32_t flags)
+{
+ MP4File* pFile = NULL;
+ try {
+ pFile = new MP4File(verbosity);
+ // LATER useExtensibleFormat, moov first, then mvex's
+ pFile->Modify(fileName);
+ return (MP4FileHandle)pFile;
+ }
+ catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ delete pFile;
+ return MP4_INVALID_FILE_HANDLE;
+ }
+}
+
+extern "C" bool MP4Optimize(const MP4_FILENAME_CHAR* existingFileName,
+ const MP4_FILENAME_CHAR* newFileName,
+ u_int32_t verbosity)
+{
+ try {
+ MP4File* pFile = new MP4File(verbosity);
+ pFile->Optimize(existingFileName, newFileName);
+ delete pFile;
+ return true;
+ }
+ catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ }
+ return false;
+}
+
+extern "C" void MP4Close(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->Close();
+ delete (MP4File*)hFile;
+ return;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return ;
+}
+
+/* specific file properties */
+
+extern "C" u_int32_t MP4GetVerbosity(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetVerbosity();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" void MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetVerbosity(verbosity);
+ return;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return;
+}
+
+extern "C" MP4Duration MP4GetDuration(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetDuration();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" u_int32_t MP4GetTimeScale(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTimeScale();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" bool MP4SetTimeScale(MP4FileHandle hFile, u_int32_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTimeScale(value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" u_int8_t MP4GetODProfileLevel(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetODProfileLevel();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" bool MP4SetODProfileLevel(MP4FileHandle hFile, u_int8_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetODProfileLevel(value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" u_int8_t MP4GetSceneProfileLevel(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSceneProfileLevel();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" bool MP4SetSceneProfileLevel(MP4FileHandle hFile, u_int8_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetSceneProfileLevel(value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile,
+ MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetVideoProfileLevel();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ if (MP4_IS_VALID_TRACK_ID(trackId)) {
+ uint8_t *foo;
+ uint32_t bufsize;
+ uint8_t type;
+ // for mpeg4 video tracks, try to look for the VOSH header,
+ // which has this info.
+ type = MP4GetTrackEsdsObjectTypeId(hFile, trackId);
+ if (type == MP4_MPEG4_VIDEO_TYPE) {
+ if (MP4GetTrackESConfiguration(hFile,
+ trackId,
+ &foo,
+ &bufsize)) {
+ uint8_t *ptr = foo;
+ while (bufsize > 0) {
+ if (htonl(*(uint32_t *)ptr) == 0x1b0) {
+ uint8_t ret = ptr[4];
+ free(foo);
+ return ret;
+ }
+ ptr++;
+ bufsize--;
+ }
+ free(foo);
+ }
+ }
+ }
+
+ }
+ return 0;
+}
+
+extern "C" void MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetVideoProfileLevel(value);
+ return ;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return ;
+}
+
+extern "C" u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetAudioProfileLevel();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" void MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetAudioProfileLevel(value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+extern "C" u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetGraphicsProfileLevel();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, u_int8_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetGraphicsProfileLevel(value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+/* generic file properties */
+
+extern "C" bool MP4HaveAtom (MP4FileHandle hFile, const char *atomName)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File *)hFile)->FindAtomMP4File(atomName) != NULL;
+ } catch (MP4Error *e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetIntegerProperty(
+ MP4FileHandle hFile, const char* propName, u_int64_t *retvalue)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *retvalue = ((MP4File*)hFile)->GetIntegerProperty(propName);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetFloatProperty(
+ MP4FileHandle hFile, const char* propName, float *retvalue)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *retvalue = ((MP4File*)hFile)->GetFloatProperty(propName);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetStringProperty(
+ MP4FileHandle hFile, const char* propName,
+ const char **retvalue)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *retvalue = ((MP4File*)hFile)->GetStringProperty(propName);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetBytesProperty(
+ MP4FileHandle hFile, const char* propName,
+ u_int8_t** ppValue, u_int32_t* pValueSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->GetBytesProperty(propName, ppValue, pValueSize);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ *ppValue = NULL;
+ *pValueSize = 0;
+ return false;
+}
+
+extern "C" bool MP4SetIntegerProperty(
+ MP4FileHandle hFile, const char* propName, int64_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetIntegerProperty(propName, value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetFloatProperty(
+ MP4FileHandle hFile, const char* propName, float value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetFloatProperty(propName, value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetStringProperty(
+ MP4FileHandle hFile, const char* propName, const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetStringProperty(propName, value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetBytesProperty(
+ MP4FileHandle hFile, const char* propName,
+ const u_int8_t* pValue, u_int32_t valueSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetBytesProperty(propName, pValue, valueSize);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+/* track operations */
+
+extern "C" MP4TrackId MP4AddTrack(
+ MP4FileHandle hFile, const char* type)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddSystemsTrack(type);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddSystemsTrack(
+ MP4FileHandle hFile, const char* type)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddSystemsTrack(type);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddODTrack(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddODTrack();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddSceneTrack(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddSceneTrack();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddAudioTrack(
+ MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int8_t audioType)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ AddAudioTrack(timeScale, sampleDuration, audioType);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+//
+// API to initialize ismacryp properties to sensible defaults.
+// if the input pointer is null then an ismacryp params is malloc'd.
+// caller must see to it that it is properly disposed of.
+//
+extern "C" mp4v2_ismacrypParams *MP4DefaultISMACrypParams(mp4v2_ismacrypParams *ptr)
+{
+ try
+ {
+ if (ptr == NULL) {
+ ptr = (mp4v2_ismacrypParams *)MP4Malloc(sizeof(mp4v2_ismacrypParams));
+ }
+ memset(ptr, 0, sizeof(*ptr));
+ return ptr;
+ }
+
+ catch (...) {
+ return 0;
+ }
+}
+
+
+extern "C" MP4TrackId MP4AddEncAudioTrack(MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ mp4v2_ismacrypParams *icPp,
+ u_int8_t audioType)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ if (icPp == NULL) {
+ return ((MP4File*)hFile)->
+ AddEncAudioTrack(timeScale, sampleDuration, audioType,
+ 0, 0,
+ 0, 0,
+ false, NULL, false);
+ } else {
+ return ((MP4File*)hFile)->
+ AddEncAudioTrack(timeScale, sampleDuration, audioType,
+ icPp->scheme_type, icPp->scheme_version,
+ icPp->key_ind_len, icPp->iv_len,
+ icPp->selective_enc, icPp->kms_uri, true);
+ }
+ } catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+extern "C" MP4TrackId MP4AddAmrAudioTrack(
+ MP4FileHandle hFile,
+ u_int32_t timeScale,
+ u_int16_t modeSet,
+ u_int8_t modeChangePeriod,
+ u_int8_t framesPerSample,
+ bool isAmrWB)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ AddAmrAudioTrack(timeScale, modeSet, modeChangePeriod, framesPerSample, isAmrWB);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" void MP4SetAmrVendor(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int32_t vendor)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->
+ SetAmrVendor(trackId, vendor);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+extern "C" void MP4SetAmrDecoderVersion(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int8_t decoderVersion)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->
+ SetAmrDecoderVersion(trackId, decoderVersion);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+extern "C" void MP4SetAmrModeSet(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int16_t modeSet)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->
+ SetAmrModeSet(trackId, modeSet);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+extern "C" uint16_t MP4GetAmrModeSet(
+ MP4FileHandle hFile,
+ MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ GetAmrModeSet(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" MP4TrackId MP4AddHrefTrack (MP4FileHandle hFile,
+ uint32_t timeScale,
+ MP4Duration sampleDuration,
+ const char *base_url)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ MP4File *pFile = (MP4File *)hFile;
+
+ return pFile->AddHrefTrack(timeScale,
+ sampleDuration,
+ base_url);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" const char *MP4GetHrefTrackBaseUrl (MP4FileHandle hFile,
+ MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackStringProperty(trackId,
+ "mdia.minf.stbl.stsd.href.burl.base_url");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return NULL;
+}
+
+extern "C" MP4TrackId MP4AddVideoTrack(
+ MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ u_int8_t videoType)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ MP4File *pFile = (MP4File *)hFile;
+
+ return pFile->AddMP4VideoTrack(timeScale,
+ sampleDuration,
+ width,
+ height,
+ videoType);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddEncVideoTrack(MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ mp4v2_ismacrypParams *icPp,
+ u_int8_t videoType,
+ const char *oFormat)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+
+ // test for valid ismacrypt session descriptor
+ if (icPp == NULL) {
+ return MP4_INVALID_TRACK_ID;
+ }
+ MP4File *pFile = (MP4File *)hFile;
+
+ return pFile->AddEncVideoTrack(timeScale,
+ sampleDuration,
+ width,
+ height,
+ videoType,
+ icPp,
+ oFormat);
+
+ } catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+
+extern "C" MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ uint8_t AVCProfileIndication,
+ uint8_t profile_compat,
+ uint8_t AVCLevelIndication,
+ uint8_t sampleLenFieldSizeMinusOne)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ MP4File *pFile = (MP4File *)hFile;
+
+ return pFile->AddH264VideoTrack(timeScale,
+ sampleDuration,
+ width,
+ height,
+ AVCProfileIndication,
+ profile_compat,
+ AVCLevelIndication,
+ sampleLenFieldSizeMinusOne);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddEncH264VideoTrack(
+ MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ mp4v2_ismacrypParams *icPp
+)
+
+{
+ MP4Atom *srcAtom;
+ MP4File *pFile;
+
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+
+ pFile = (MP4File *)srcFile;
+ srcAtom = pFile->FindTrackAtom(srcTrackId, "mdia.minf.stbl.stsd.avc1.avcC");
+ if (srcAtom == NULL)
+ return MP4_INVALID_TRACK_ID;
+
+ pFile = (MP4File *)hFile;
+
+ return pFile->AddEncH264VideoTrack(timeScale,
+ sampleDuration,
+ width,
+ height,
+ srcAtom,
+ icPp);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" void MP4AddH264SequenceParameterSet (MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const uint8_t *pSequence,
+ uint16_t sequenceLen)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ MP4File *pFile = (MP4File *)hFile;
+
+ pFile->AddH264SequenceParameterSet(trackId,
+ pSequence,
+ sequenceLen);
+ return;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return;
+}
+extern "C" void MP4AddH264PictureParameterSet (MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const uint8_t *pPict,
+ uint16_t pictLen)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ MP4File *pFile = (MP4File *)hFile;
+
+ pFile->AddH264PictureParameterSet(trackId,
+ pPict,
+ pictLen);
+ return;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return;
+}
+
+extern "C" MP4TrackId MP4AddH263VideoTrack(
+ MP4FileHandle hFile,
+ u_int32_t timeScale,
+ MP4Duration sampleDuration,
+ u_int16_t width,
+ u_int16_t height,
+ u_int8_t h263Level,
+ u_int8_t h263Profile,
+ u_int32_t avgBitrate,
+ u_int32_t maxBitrate)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ AddH263VideoTrack(timeScale, sampleDuration, width, height, h263Level, h263Profile, avgBitrate, maxBitrate);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" void MP4SetH263Vendor(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int32_t vendor)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->
+ SetH263Vendor(trackId, vendor);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+extern "C" void MP4SetH263DecoderVersion(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int8_t decoderVersion)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+
+ try {
+ ((MP4File*)hFile)->
+ SetH263DecoderVersion(trackId, decoderVersion);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+extern "C" void MP4SetH263Bitrates(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int32_t avgBitrate,
+ u_int32_t maxBitrate)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+
+ try {
+ ((MP4File*)hFile)->
+ SetH263Bitrates(trackId, avgBitrate, maxBitrate);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+extern "C" MP4TrackId MP4AddHintTrack(
+ MP4FileHandle hFile, MP4TrackId refTrackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddHintTrack(refTrackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddTextTrack(
+ MP4FileHandle hFile, MP4TrackId refTrackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddTextTrack(refTrackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" MP4TrackId MP4AddChapterTextTrack(MP4FileHandle hFile, MP4TrackId refTrackId, u_int32_t timescale)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->AddChapterTextTrack(refTrackId, timescale);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+extern "C" void MP4AddQTChapter(
+ MP4FileHandle hFile,
+ MP4TrackId chapterTrackId,
+ MP4Duration chapterDuration,
+ u_int32_t chapterNr,
+ const char * chapterTitle)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AddChapter(chapterTrackId, chapterDuration, chapterNr, chapterTitle);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+
+extern "C" void MP4AddChapter(
+ MP4FileHandle hFile,
+ MP4Timestamp chapterStart,
+ const char * chapterTitle)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AddChapter(chapterStart, chapterTitle);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+
+extern "C" void MP4ConvertChapters(
+ MP4FileHandle hFile,
+ bool toQT)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->ConvertChapters(toQT);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+
+extern "C" void MP4DeleteChapters(
+ MP4FileHandle hFile,
+ MP4TrackId chapterTrackId,
+ bool deleteQT)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->DeleteChapters(chapterTrackId, deleteQT);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+
+extern "C" void MP4GetChaptersList(
+ MP4FileHandle hFile,
+ MP4Chapters_t ** chapterList,
+ u_int32_t * chapterCount,
+ bool getQT)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->GetChaptersList(chapterList, chapterCount, getQT);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+}
+
+
+
+extern "C" MP4TrackId MP4CloneTrack (MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile,
+ MP4TrackId dstHintTrackReferenceTrack)
+{
+ MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
+
+ if (dstFile == NULL) {
+ dstFile = srcFile;
+ }
+
+ const char* trackType =
+ MP4GetTrackType(srcFile, srcTrackId);
+
+ if (!trackType) {
+ return dstTrackId;
+ }
+
+ const char *media_data_name =
+ MP4GetTrackMediaDataName(srcFile, srcTrackId);
+ if (media_data_name == NULL) return dstTrackId;
+
+ if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+ if (ATOMID(media_data_name) == ATOMID("mp4v")) {
+ MP4SetVideoProfileLevel(dstFile,
+ MP4GetVideoProfileLevel(srcFile));
+ dstTrackId = MP4AddVideoTrack(
+ dstFile,
+ MP4GetTrackTimeScale(srcFile,
+ srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile,
+ srcTrackId),
+ MP4GetTrackVideoWidth(srcFile,
+ srcTrackId),
+ MP4GetTrackVideoHeight(srcFile,
+ srcTrackId),
+ MP4GetTrackEsdsObjectTypeId(srcFile,
+ srcTrackId));
+ } else if (ATOMID(media_data_name) == ATOMID("avc1")) {
+ uint8_t AVCProfileIndication;
+ uint8_t profile_compat;
+ uint8_t AVCLevelIndication;
+ uint32_t sampleLenFieldSizeMinusOne;
+ uint64_t temp;
+
+ if (MP4GetTrackH264ProfileLevel(srcFile, srcTrackId,
+ &AVCProfileIndication,
+ &AVCLevelIndication) == false) {
+ return dstTrackId;
+ }
+ if (MP4GetTrackH264LengthSize(srcFile, srcTrackId,
+ &sampleLenFieldSizeMinusOne) == false) {
+ return dstTrackId;
+ }
+ sampleLenFieldSizeMinusOne--;
+ if (MP4GetTrackIntegerProperty(srcFile, srcTrackId,
+ "mdia.minf.stbl.stsd.*[0].avcC.profile_compatibility",
+ &temp) == false) return dstTrackId;
+ profile_compat = temp & 0xff;
+
+ dstTrackId = MP4AddH264VideoTrack(dstFile,
+ MP4GetTrackTimeScale(srcFile,
+ srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile,
+ srcTrackId),
+ MP4GetTrackVideoWidth(srcFile,
+ srcTrackId),
+ MP4GetTrackVideoHeight(srcFile,
+ srcTrackId),
+ AVCProfileIndication,
+ profile_compat,
+ AVCLevelIndication,
+ sampleLenFieldSizeMinusOne);
+ uint8_t **seqheader, **pictheader;
+ uint32_t *pictheadersize, *seqheadersize;
+ uint32_t ix;
+ MP4GetTrackH264SeqPictHeaders(srcFile, srcTrackId,
+ &seqheader, &seqheadersize,
+ &pictheader, &pictheadersize);
+ for (ix = 0; seqheadersize[ix] != 0; ix++) {
+ MP4AddH264SequenceParameterSet(dstFile, dstTrackId,
+ seqheader[ix], seqheadersize[ix]);
+ free(seqheader[ix]);
+ }
+ free(seqheader);
+ free(seqheadersize);
+ for (ix = 0; pictheadersize[ix] != 0; ix++) {
+ MP4AddH264PictureParameterSet(dstFile, dstTrackId,
+ pictheader[ix], pictheadersize[ix]);
+ free(pictheader[ix]);
+ }
+ free(pictheader);
+ free(pictheadersize);
+ } else
+ return dstTrackId;
+ } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
+ if (ATOMID(media_data_name) != ATOMID("mp4a")) return dstTrackId;
+ MP4SetAudioProfileLevel(dstFile,
+ MP4GetAudioProfileLevel(srcFile));
+ dstTrackId = MP4AddAudioTrack(
+ dstFile,
+ MP4GetTrackTimeScale(srcFile, srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
+ MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId));
+
+ } else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddODTrack(dstFile);
+
+ } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddSceneTrack(dstFile);
+
+ } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
+ if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) {
+ dstTrackId = MP4_INVALID_TRACK_ID;
+ } else {
+ dstTrackId = MP4AddHintTrack(
+ dstFile,
+ dstHintTrackReferenceTrack);
+ }
+
+ } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddSystemsTrack(dstFile, trackType);
+
+ } else {
+ dstTrackId = MP4AddTrack(dstFile, trackType);
+ }
+
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ return dstTrackId;
+ }
+
+ MP4SetTrackTimeScale(
+ dstFile,
+ dstTrackId,
+ MP4GetTrackTimeScale(srcFile, srcTrackId));
+
+ if (MP4_IS_AUDIO_TRACK_TYPE(trackType)
+ || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+ // copy track ES configuration
+ u_int8_t* pConfig = NULL;
+ u_int32_t configSize = 0;
+
+ if (MP4GetTrackESConfiguration(
+ srcFile,
+ srcTrackId,
+ &pConfig,
+ &configSize) &&
+ pConfig != NULL && configSize != 0) {
+ if (!MP4SetTrackESConfiguration(
+ dstFile,
+ dstTrackId,
+ pConfig,
+ configSize)) {
+ free(pConfig);
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+
+ free(pConfig);
+ }
+ }
+
+ if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
+ // probably not exactly what is wanted
+ // but caller can adjust later to fit their desires
+
+ char* payloadName = NULL;
+ char *encodingParms = NULL;
+ u_int8_t payloadNumber;
+ u_int16_t maxPayloadSize;
+
+ if (MP4GetHintTrackRtpPayload(
+ srcFile,
+ srcTrackId,
+ &payloadName,
+ &payloadNumber,
+ &maxPayloadSize,
+ &encodingParms)) {
+
+ if (MP4SetHintTrackRtpPayload(
+ dstFile,
+ dstTrackId,
+ payloadName,
+ &payloadNumber,
+ maxPayloadSize,
+ encodingParms) == false) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+ }
+#if 0
+ MP4SetHintTrackSdp(
+ dstFile,
+ dstTrackId,
+ MP4GetHintTrackSdp(srcFile, srcTrackId));
+#endif
+ }
+
+ return dstTrackId;
+}
+
+// Given a track, make an encrypted clone of it in the dest. file
+extern "C" MP4TrackId MP4EncAndCloneTrack(MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ mp4v2_ismacrypParams *icPp,
+ MP4FileHandle dstFile,
+ MP4TrackId dstHintTrackReferenceTrack
+ )
+{
+ const char *oFormat;
+
+ MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
+
+ if (dstFile == NULL) {
+ dstFile = srcFile;
+ }
+
+ const char* trackType = MP4GetTrackType(srcFile, srcTrackId);
+
+ if (!trackType) {
+ return dstTrackId;
+ }
+
+ if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+
+ // test source file format for avc1
+ oFormat = MP4GetTrackMediaDataName(srcFile, srcTrackId);
+ if (!strcasecmp(oFormat, "avc1"))
+ {
+ dstTrackId = MP4AddEncH264VideoTrack(dstFile,
+ MP4GetTrackTimeScale(srcFile, srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
+ MP4GetTrackVideoWidth(srcFile, srcTrackId),
+ MP4GetTrackVideoHeight(srcFile, srcTrackId),
+ srcFile,
+ srcTrackId,
+ icPp
+ );
+ }
+ else
+ {
+ MP4SetVideoProfileLevel(dstFile, MP4GetVideoProfileLevel(srcFile));
+ dstTrackId = MP4AddEncVideoTrack(dstFile,
+ MP4GetTrackTimeScale(srcFile, srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
+ MP4GetTrackVideoWidth(srcFile, srcTrackId),
+ MP4GetTrackVideoHeight(srcFile, srcTrackId),
+ icPp,
+ MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId),
+ oFormat
+ );
+ }
+
+ } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
+ MP4SetAudioProfileLevel(dstFile, MP4GetAudioProfileLevel(srcFile));
+ dstTrackId = MP4AddEncAudioTrack(dstFile,
+ MP4GetTrackTimeScale(srcFile, srcTrackId),
+ MP4GetTrackFixedSampleDuration(srcFile,
+ srcTrackId),
+ icPp,
+ MP4GetTrackEsdsObjectTypeId(srcFile,
+ srcTrackId)
+ );
+
+ } else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddODTrack(dstFile);
+
+ } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddSceneTrack(dstFile);
+
+ } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
+ if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) {
+ dstTrackId = MP4_INVALID_TRACK_ID;
+ } else {
+ dstTrackId = MP4AddHintTrack(dstFile,
+ MP4GetHintTrackReferenceTrackId(srcFile,
+ srcTrackId));
+ }
+ } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) {
+ dstTrackId = MP4AddSystemsTrack(dstFile, trackType);
+
+ } else {
+ dstTrackId = MP4AddTrack(dstFile, trackType);
+ }
+
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ return dstTrackId;
+ }
+
+ MP4SetTrackTimeScale(dstFile,
+ dstTrackId,
+ MP4GetTrackTimeScale(srcFile, srcTrackId));
+
+ if (MP4_IS_AUDIO_TRACK_TYPE(trackType)
+ || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
+ // copy track ES configuration
+ u_int8_t* pConfig = NULL;
+ u_int32_t configSize = 0;
+ if (MP4GetTrackESConfiguration(srcFile, srcTrackId,
+ &pConfig, &configSize)) {
+
+ if (pConfig != NULL) {
+ MP4SetTrackESConfiguration(dstFile, dstTrackId,
+ pConfig, configSize);
+ }
+ }
+ if (pConfig != NULL)
+ free(pConfig);
+ }
+
+ // Bill's change to MP4CloneTrack
+ if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
+ // probably not exactly what is wanted
+ // but caller can adjust later to fit their desires
+
+ char* payloadName = NULL;
+ char *encodingParms = NULL;
+ u_int8_t payloadNumber;
+ u_int16_t maxPayloadSize;
+
+ if (MP4GetHintTrackRtpPayload(
+ srcFile,
+ srcTrackId,
+ &payloadName,
+ &payloadNumber,
+ &maxPayloadSize,
+ &encodingParms)) {
+
+ (void)MP4SetHintTrackRtpPayload(
+ dstFile,
+ dstTrackId,
+ payloadName,
+ &payloadNumber,
+ maxPayloadSize,
+ encodingParms);
+ }
+#if 0
+ MP4SetHintTrackSdp(
+ dstFile,
+ dstTrackId,
+ MP4GetHintTrackSdp(srcFile, srcTrackId));
+#endif
+ }
+
+ return dstTrackId;
+}
+
+extern "C" MP4TrackId MP4CopyTrack(MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4FileHandle dstFile,
+ bool applyEdits,
+ MP4TrackId dstHintTrackReferenceTrack)
+{
+ bool copySamples = true; // LATER allow false => reference samples
+
+ MP4TrackId dstTrackId =
+ MP4CloneTrack(srcFile, srcTrackId, dstFile, dstHintTrackReferenceTrack);
+
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ return dstTrackId;
+ }
+
+ bool viaEdits =
+ applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId);
+
+ MP4SampleId sampleId = 0;
+ MP4SampleId numSamples =
+ MP4GetTrackNumberOfSamples(srcFile, srcTrackId);
+
+ MP4Timestamp when = 0;
+ MP4Duration editsDuration =
+ MP4GetTrackEditTotalDuration(srcFile, srcTrackId);
+
+ while (true) {
+ MP4Duration sampleDuration = MP4_INVALID_DURATION;
+
+ if (viaEdits) {
+ sampleId = MP4GetSampleIdFromEditTime(
+ srcFile,
+ srcTrackId,
+ when,
+ NULL,
+ &sampleDuration);
+
+ // in theory, this shouldn't happen
+ if (sampleId == MP4_INVALID_SAMPLE_ID) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+
+ when += sampleDuration;
+
+ if (when >= editsDuration) {
+ break;
+ }
+ } else {
+ sampleId++;
+ if (sampleId > numSamples) {
+ break;
+ }
+ }
+
+ bool rc = false;
+
+ if (copySamples) {
+ rc = MP4CopySample(
+ srcFile,
+ srcTrackId,
+ sampleId,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+
+ } else {
+ rc = MP4ReferenceSample(
+ srcFile,
+ srcTrackId,
+ sampleId,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+ }
+
+ if (!rc) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+ }
+
+ return dstTrackId;
+}
+
+// Given a source track in a source file, make an encrypted copy of
+// the track in the destination file, including sample encryption
+extern "C" MP4TrackId MP4EncAndCopyTrack(MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ mp4v2_ismacrypParams *icPp,
+ encryptFunc_t encfcnp,
+ u_int32_t encfcnparam1,
+ MP4FileHandle dstFile,
+ bool applyEdits,
+ MP4TrackId dstHintTrackReferenceTrack
+ )
+{
+ bool copySamples = true; // LATER allow false => reference samples
+
+ MP4TrackId dstTrackId =
+ MP4EncAndCloneTrack(srcFile, srcTrackId,
+ icPp,
+ dstFile, dstHintTrackReferenceTrack);
+
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ return dstTrackId;
+ }
+
+ bool viaEdits =
+ applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId);
+
+ MP4SampleId sampleId = 0;
+ MP4SampleId numSamples =
+ MP4GetTrackNumberOfSamples(srcFile, srcTrackId);
+
+ MP4Timestamp when = 0;
+ MP4Duration editsDuration =
+ MP4GetTrackEditTotalDuration(srcFile, srcTrackId);
+
+ while (true) {
+ MP4Duration sampleDuration = MP4_INVALID_DURATION;
+
+ if (viaEdits) {
+ sampleId = MP4GetSampleIdFromEditTime(srcFile,
+ srcTrackId,
+ when,
+ NULL,
+ &sampleDuration);
+
+ // in theory, this shouldn't happen
+ if (sampleId == MP4_INVALID_SAMPLE_ID) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+
+ when += sampleDuration;
+
+ if (when >= editsDuration) {
+ break;
+ }
+ } else {
+ sampleId++;
+ if (sampleId > numSamples) {
+ break;
+ }
+ }
+
+ bool rc = false;
+
+ if (copySamples) {
+ // encrypt and copy
+ rc = MP4EncAndCopySample(srcFile,
+ srcTrackId,
+ sampleId,
+ encfcnp,
+ encfcnparam1,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+
+ } else {
+ // not sure what these are - encrypt?
+ rc = MP4ReferenceSample(srcFile,
+ srcTrackId,
+ sampleId,
+ dstFile,
+ dstTrackId,
+ sampleDuration);
+ }
+
+ if (!rc) {
+ MP4DeleteTrack(dstFile, dstTrackId);
+ return MP4_INVALID_TRACK_ID;
+ }
+ }
+
+ return dstTrackId;
+}
+
+extern "C" void MP4DeleteTrack(
+ MP4FileHandle hFile,
+ MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->DeleteTrack(trackId);
+ return ;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return;
+}
+
+extern "C" u_int32_t MP4GetNumberOfTracks(
+ MP4FileHandle hFile,
+ const char* type,
+ u_int8_t subType)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetNumberOfTracks(type, subType);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" MP4TrackId MP4FindTrackId(
+ MP4FileHandle hFile,
+ u_int16_t index,
+ const char* type,
+ u_int8_t subType)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->FindTrackId(index, type, subType);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" u_int16_t MP4FindTrackIndex(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->FindTrackIndex(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return (u_int16_t)-1;
+}
+
+/* specific track properties */
+
+extern "C" const char* MP4GetTrackType(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackType(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return NULL;
+}
+extern "C" const char* MP4GetTrackMediaDataName(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackMediaDataName(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return NULL;
+}
+
+extern "C" bool MP4GetTrackMediaDataOriginalFormat(
+ MP4FileHandle hFile, MP4TrackId trackId, char *originalFormat,
+ u_int32_t buflen)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+
+ return ((MP4File*)hFile)->GetTrackMediaDataOriginalFormat(trackId,
+ originalFormat, buflen);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" MP4Duration MP4GetTrackDuration(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackDuration(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" u_int32_t MP4GetTrackTimeScale(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackTimeScale(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" void MP4SetTrackTimeScale(
+ MP4FileHandle hFile, MP4TrackId trackId, u_int32_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackTimeScale(trackId, value);
+ return;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return;
+}
+
+extern "C" u_int8_t MP4GetTrackAudioMpeg4Type(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackAudioMpeg4Type(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_MPEG4_INVALID_AUDIO_TYPE;
+}
+
+
+
+// Replacement to MP4GetTrackVideoType and MP4GetTrackAudioType
+// Basically does the same thing but with a more self-explanatory name
+extern "C" u_int8_t MP4GetTrackEsdsObjectTypeId(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+
+ return ((MP4File*)hFile)->GetTrackEsdsObjectTypeId(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_AUDIO_TYPE;
+}
+
+extern "C" MP4Duration MP4GetTrackFixedSampleDuration(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackFixedSampleDuration(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" u_int32_t MP4GetTrackBitRate(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ uint32_t br = 0;
+ MP4File *pFile = (MP4File *)hFile;
+ try {
+ br = pFile->GetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate");
+ if (br > 16000)
+ return br;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ // if we're here, we can't get the bitrate from above -
+ // lets calculate it
+ try {
+ MP4Duration trackDur;
+ trackDur = MP4GetTrackDuration(hFile, trackId);
+ uint64_t msDuration =
+ pFile->ConvertFromTrackDuration(trackId, trackDur,
+ MP4_MSECS_TIME_SCALE);
+ if (msDuration == 0) return 0;
+
+ MP4Track *pTrack = pFile->GetTrack(trackId);
+ double bytes = pTrack->GetTotalOfSampleSizes();
+ //bytes *= TO_U64(8 * 1000);
+ //bytes /= msDuration;
+ //return (uint32_t)bytes;
+
+ // divide first !!!
+ bytes /= (double)msDuration;
+ bytes *= TO_U64(8 * 1000);
+ return (uint32_t)bytes;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+
+ }
+ return 0;
+}
+
+extern "C" bool MP4GetTrackESConfiguration(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ u_int8_t** ppConfig, u_int32_t* pConfigSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->GetTrackESConfiguration(
+ trackId, ppConfig, pConfigSize);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ *ppConfig = NULL;
+ *pConfigSize = 0;
+ return false;
+}
+extern "C" bool MP4GetTrackVideoMetadata(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ u_int8_t** ppConfig, u_int32_t* pConfigSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->GetTrackVideoMetadata(
+ trackId, ppConfig, pConfigSize);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ *ppConfig = NULL;
+ *pConfigSize = 0;
+ return false;
+}
+
+extern "C" bool MP4SetTrackESConfiguration(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const u_int8_t* pConfig, u_int32_t configSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackESConfiguration(
+ trackId, pConfig, configSize);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetTrackH264ProfileLevel (MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t *pProfile,
+ uint8_t *pLevel)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *pProfile =
+ ((MP4File *)hFile)->GetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.*[0].avcC.AVCProfileIndication");
+ *pLevel =
+ ((MP4File *)hFile)->GetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.*[0].avcC.AVCLevelIndication");
+
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+extern "C" void MP4GetTrackH264SeqPictHeaders (MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint8_t ***pSeqHeader,
+ uint32_t **pSeqHeaderSize,
+ uint8_t ***pPictHeader,
+ uint32_t **pPictHeaderSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->GetTrackH264SeqPictHeaders(trackId,
+ pSeqHeader,
+ pSeqHeaderSize,
+ pPictHeader,
+ pPictHeaderSize);
+ return;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return;
+}
+extern "C" bool MP4GetTrackH264LengthSize (MP4FileHandle hFile,
+ MP4TrackId trackId,
+ uint32_t *pLength)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *pLength = 1 +
+ ((MP4File*) hFile)->GetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.*[0].avcC.lengthSizeMinusOne");
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" MP4SampleId MP4GetTrackNumberOfSamples(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackNumberOfSamples(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" MP4ChunkId MP4GetTrackNumberOfChunks(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackNumberOfChunks(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" u_int16_t MP4GetTrackVideoWidth(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.*.width");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" u_int16_t MP4GetTrackVideoHeight(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
+ "mdia.minf.stbl.stsd.*.height");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" double MP4GetTrackVideoFrameRate(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackVideoFrameRate(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0.0;
+}
+
+extern "C" int MP4GetTrackAudioChannels (MP4FileHandle hFile,
+ MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackAudioChannels(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return -1;
+}
+
+// returns true if the track is a media track encrypted according to ismacryp
+extern "C" bool MP4IsIsmaCrypMediaTrack(
+ MP4FileHandle hFile, MP4TrackId trackId)
+{
+ bool retval = false;
+ uint32_t verb = MP4GetVerbosity(hFile);
+ MP4SetVerbosity(hFile, verb & ~(MP4_DETAILS_ERROR));
+
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ retval = ((MP4File*)hFile)->IsIsmaCrypMediaTrack(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ MP4SetVerbosity(hFile, verb);
+ return retval;
+}
+
+
+/* generic track properties */
+
+extern "C" bool MP4HaveTrackAtom (MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const char *atomName)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->FindTrackAtom(trackId, atomName) != NULL;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetTrackIntegerProperty (
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const char* propName,
+ u_int64_t *retvalue)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *retvalue = ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
+ propName);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetTrackFloatProperty(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const char* propName,
+ float *retvalue)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *retvalue = ((MP4File*)hFile)->GetTrackFloatProperty(trackId, propName);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetTrackStringProperty(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const char* propName,
+ const char **retvalue)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ *retvalue = ((MP4File*)hFile)->GetTrackStringProperty(trackId, propName);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetTrackBytesProperty(
+ MP4FileHandle hFile, MP4TrackId trackId, const char* propName,
+ u_int8_t** ppValue, u_int32_t* pValueSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->GetTrackBytesProperty(
+ trackId, propName, ppValue, pValueSize);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ *ppValue = NULL;
+ *pValueSize = 0;
+ return false;
+}
+
+extern "C" bool MP4SetTrackIntegerProperty(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const char* propName, int64_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackIntegerProperty(trackId,
+ propName, value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetTrackFloatProperty(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const char* propName, float value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackFloatProperty(trackId, propName, value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetTrackStringProperty(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const char* propName, const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackStringProperty(trackId, propName, value);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetTrackBytesProperty(
+ MP4FileHandle hFile, MP4TrackId trackId,
+ const char* propName, const u_int8_t* pValue, u_int32_t valueSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackBytesProperty(
+ trackId, propName, pValue, valueSize);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+/* sample operations */
+
+extern "C" bool MP4ReadSample(
+ /* input parameters */
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId,
+ /* output parameters */
+ u_int8_t** ppBytes,
+ u_int32_t* pNumBytes,
+ MP4Timestamp* pStartTime,
+ MP4Duration* pDuration,
+ MP4Duration* pRenderingOffset,
+ bool* pIsSyncSample)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->ReadSample(
+ trackId,
+ sampleId,
+ ppBytes,
+ pNumBytes,
+ pStartTime,
+ pDuration,
+ pRenderingOffset,
+ pIsSyncSample);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ *pNumBytes = 0;
+ return false;
+}
+
+extern "C" bool MP4ReadChunk(
+ /* input parameters */
+ MP4FileHandle hFile,
+ MP4ChunkId trackId,
+ MP4SampleId sampleId,
+ /* output parameters */
+ u_int8_t** ppBytes,
+ u_int32_t* pNumBytes,
+ MP4Timestamp* pStartTime,
+ MP4Duration* pDuration)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile))
+ {
+ try
+ {
+ ((MP4File*)hFile)->ReadChunk(
+ trackId,
+ sampleId,
+ ppBytes,
+ pNumBytes,
+ pStartTime,
+ pDuration);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ *pNumBytes = 0;
+ return false;
+}
+
+extern "C" bool MP4ReadSampleFromTime(
+ /* input parameters */
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ /* output parameters */
+ u_int8_t** ppBytes,
+ u_int32_t* pNumBytes,
+ MP4Timestamp* pStartTime,
+ MP4Duration* pDuration,
+ MP4Duration* pRenderingOffset,
+ bool* pIsSyncSample)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ MP4SampleId sampleId =
+ ((MP4File*)hFile)->GetSampleIdFromTime(
+ trackId, when, false);
+
+ ((MP4File*)hFile)->ReadSample(
+ trackId,
+ sampleId,
+ ppBytes,
+ pNumBytes,
+ pStartTime,
+ pDuration,
+ pRenderingOffset,
+ pIsSyncSample);
+
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ *pNumBytes = 0;
+ return false;
+}
+
+extern "C" bool MP4WriteSample(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ const u_int8_t* pBytes,
+ u_int32_t numBytes,
+ MP4Duration duration,
+ MP4Duration renderingOffset,
+ bool isSyncSample)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->WriteSample(
+ trackId,
+ pBytes,
+ numBytes,
+ duration,
+ renderingOffset,
+ isSyncSample);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4CopySample(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4SampleId srcSampleId,
+ MP4FileHandle dstFile,
+ MP4TrackId dstTrackId,
+ MP4Duration dstSampleDuration)
+{
+ bool rc;
+ u_int8_t* pBytes = NULL;
+ u_int32_t numBytes = 0;
+ MP4Duration sampleDuration;
+ MP4Duration renderingOffset;
+ bool isSyncSample;
+
+ // Note: we leave it up to the caller to ensure that the
+ // source and destination tracks are compatible.
+ // i.e. copying audio samples into a video track
+ // is unlikely to do anything useful
+
+ rc = MP4ReadSample(
+ srcFile,
+ srcTrackId,
+ srcSampleId,
+ &pBytes,
+ &numBytes,
+ NULL,
+ &sampleDuration,
+ &renderingOffset,
+ &isSyncSample);
+
+ if (!rc) {
+ return false;
+ }
+
+ if (dstFile == MP4_INVALID_FILE_HANDLE) {
+ dstFile = srcFile;
+ }
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ dstTrackId = srcTrackId;
+ }
+ if (dstSampleDuration != MP4_INVALID_DURATION) {
+ sampleDuration = dstSampleDuration;
+ }
+
+ rc = MP4WriteSample(
+ dstFile,
+ dstTrackId,
+ pBytes,
+ numBytes,
+ sampleDuration,
+ renderingOffset,
+ isSyncSample);
+
+ free(pBytes);
+
+ return rc;
+}
+
+extern "C" bool MP4EncAndCopySample(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4SampleId srcSampleId,
+ encryptFunc_t encfcnp,
+ u_int32_t encfcnparam1,
+ MP4FileHandle dstFile,
+ MP4TrackId dstTrackId,
+ MP4Duration dstSampleDuration)
+{
+ bool rc;
+ u_int8_t* pBytes = NULL;
+ u_int32_t numBytes = 0;
+ u_int8_t* encSampleData = NULL;
+ u_int32_t encSampleLength = 0;
+ MP4Duration sampleDuration;
+ MP4Duration renderingOffset;
+ bool isSyncSample;
+
+ // Note: we leave it up to the caller to ensure that the
+ // source and destination tracks are compatible.
+ // i.e. copying audio samples into a video track
+ // is unlikely to do anything useful
+
+ rc = MP4ReadSample(
+ srcFile,
+ srcTrackId,
+ srcSampleId,
+ &pBytes,
+ &numBytes,
+ NULL,
+ &sampleDuration,
+ &renderingOffset,
+ &isSyncSample);
+
+ if (!rc) {
+ return false;
+ }
+
+ if (dstFile == MP4_INVALID_FILE_HANDLE) {
+ dstFile = srcFile;
+ }
+ if (dstTrackId == MP4_INVALID_TRACK_ID) {
+ dstTrackId = srcTrackId;
+ }
+ if (dstSampleDuration != MP4_INVALID_DURATION) {
+ sampleDuration = dstSampleDuration;
+ }
+
+ //if (ismacrypEncryptSampleAddHeader(ismaCryptSId, numBytes, pBytes,
+ // &encSampleLength, &encSampleData) != 0) {
+ if (encfcnp(encfcnparam1, numBytes, pBytes,
+ &encSampleLength, &encSampleData) != 0) {
+ fprintf(stderr,
+ "Can't encrypt the sample and add its header %u\n",
+ srcSampleId);
+ }
+
+ rc = MP4WriteSample(
+ dstFile,
+ dstTrackId,
+ encSampleData,
+ encSampleLength,
+ sampleDuration,
+ renderingOffset,
+ isSyncSample);
+
+ free(pBytes);
+
+ if (encSampleData != NULL) {
+ free(encSampleData);
+ }
+
+ return rc;
+}
+
+extern "C" bool MP4ReferenceSample(
+ MP4FileHandle srcFile,
+ MP4TrackId srcTrackId,
+ MP4SampleId srcSampleId,
+ MP4FileHandle dstFile,
+ MP4TrackId dstTrackId,
+ MP4Duration dstSampleDuration)
+{
+ // LATER Not yet implemented
+ return false;
+}
+
+extern "C" u_int32_t MP4GetSampleSize(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSampleSize(
+ trackId, sampleId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" u_int32_t MP4GetTrackMaxSampleSize(
+ MP4FileHandle hFile,
+ MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackMaxSampleSize(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" MP4SampleId MP4GetSampleIdFromTime(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ bool wantSyncSample,
+ bool rewind)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSampleIdFromTime(
+ trackId, when, wantSyncSample, rewind);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_SAMPLE_ID;
+}
+
+extern "C" MP4ChunkId MP4GetChunkIdFromTime(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetChunkIdFromTime(
+ trackId, when);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_SAMPLE_ID;
+}
+
+extern "C" MP4Timestamp MP4GetSampleTime(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSampleTime(
+ trackId, sampleId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TIMESTAMP;
+}
+
+extern "C" MP4Duration MP4GetSampleDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSampleDuration(
+ trackId, sampleId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" MP4Duration MP4GetSampleRenderingOffset(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSampleRenderingOffset(
+ trackId, sampleId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" bool MP4SetSampleRenderingOffset(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId,
+ MP4Duration renderingOffset)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetSampleRenderingOffset(
+ trackId, sampleId, renderingOffset);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" int8_t MP4GetSampleSync(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4SampleId sampleId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSampleSync(
+ trackId, sampleId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return -1;
+}
+
+
+extern "C" u_int64_t MP4ConvertFromMovieDuration(
+ MP4FileHandle hFile,
+ MP4Duration duration,
+ u_int32_t timeScale)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->ConvertFromMovieDuration(
+ duration, timeScale);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return (u_int64_t)MP4_INVALID_DURATION;
+}
+
+extern "C" u_int64_t MP4ConvertFromTrackTimestamp(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp timeStamp,
+ u_int32_t timeScale)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->ConvertFromTrackTimestamp(
+ trackId, timeStamp, timeScale);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return (u_int64_t)MP4_INVALID_TIMESTAMP;
+}
+
+extern "C" MP4Timestamp MP4ConvertToTrackTimestamp(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int64_t timeStamp,
+ u_int32_t timeScale)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->ConvertToTrackTimestamp(
+ trackId, timeStamp, timeScale);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TIMESTAMP;
+}
+
+extern "C" u_int64_t MP4ConvertFromTrackDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Duration duration,
+ u_int32_t timeScale)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->ConvertFromTrackDuration(
+ trackId, duration, timeScale);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return (u_int64_t)MP4_INVALID_DURATION;
+}
+
+extern "C" MP4Duration MP4ConvertToTrackDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ u_int64_t duration,
+ u_int32_t timeScale)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->ConvertToTrackDuration(
+ trackId, duration, timeScale);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" bool MP4GetHintTrackRtpPayload(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ char** ppPayloadName,
+ u_int8_t* pPayloadNumber,
+ u_int16_t* pMaxPayloadSize,
+ char **ppEncodingParams)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->GetHintTrackRtpPayload(
+ hintTrackId, ppPayloadName, pPayloadNumber, pMaxPayloadSize,
+ ppEncodingParams);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetHintTrackRtpPayload(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const char* pPayloadName,
+ u_int8_t* pPayloadNumber,
+ u_int16_t maxPayloadSize,
+ const char *encode_params,
+ bool include_rtp_map,
+ bool include_mpeg4_esid)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetHintTrackRtpPayload(
+ hintTrackId, pPayloadName, pPayloadNumber, maxPayloadSize, encode_params,
+ include_rtp_map, include_mpeg4_esid);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" const char* MP4GetSessionSdp(
+ MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSessionSdp();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return NULL;
+}
+
+extern "C" bool MP4SetSessionSdp(
+ MP4FileHandle hFile,
+ const char* sdpString)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetSessionSdp(sdpString);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4AppendSessionSdp(
+ MP4FileHandle hFile,
+ const char* sdpString)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AppendSessionSdp(sdpString);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" const char* MP4GetHintTrackSdp(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetHintTrackSdp(hintTrackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return NULL;
+}
+
+extern "C" bool MP4SetHintTrackSdp(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const char* sdpString)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetHintTrackSdp(hintTrackId, sdpString);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4AppendHintTrackSdp(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const char* sdpString)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AppendHintTrackSdp(hintTrackId, sdpString);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" MP4TrackId MP4GetHintTrackReferenceTrackId(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ GetHintTrackReferenceTrackId(hintTrackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TRACK_ID;
+}
+
+extern "C" bool MP4ReadRtpHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4SampleId hintSampleId,
+ u_int16_t* pNumPackets)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->ReadRtpHint(
+ hintTrackId, hintSampleId, pNumPackets);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" u_int16_t MP4GetRtpHintNumberOfPackets(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetRtpHintNumberOfPackets(hintTrackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" int8_t MP4GetRtpPacketBFrame(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ u_int16_t packetIndex)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ GetRtpPacketBFrame(hintTrackId, packetIndex);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return -1;
+}
+
+extern "C" int32_t MP4GetRtpPacketTransmitOffset(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ u_int16_t packetIndex)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->
+ GetRtpPacketTransmitOffset(hintTrackId, packetIndex);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" bool MP4ReadRtpPacket(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ u_int16_t packetIndex,
+ u_int8_t** ppBytes,
+ u_int32_t* pNumBytes,
+ u_int32_t ssrc,
+ bool includeHeader,
+ bool includePayload)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->ReadRtpPacket(
+ hintTrackId, packetIndex,
+ ppBytes, pNumBytes,
+ ssrc, includeHeader, includePayload);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" MP4Timestamp MP4GetRtpTimestampStart(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetRtpTimestampStart(hintTrackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TIMESTAMP;
+}
+
+extern "C" bool MP4SetRtpTimestampStart(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4Timestamp rtpStart)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetRtpTimestampStart(
+ hintTrackId, rtpStart);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4AddRtpHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId)
+{
+ return MP4AddRtpVideoHint(hFile, hintTrackId, false, 0);
+}
+
+extern "C" bool MP4AddRtpVideoHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ bool isBframe,
+ u_int32_t timestampOffset)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AddRtpHint(hintTrackId,
+ isBframe, timestampOffset);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4AddRtpPacket(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ bool setMbit,
+ int32_t transmitOffset)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AddRtpPacket(
+ hintTrackId, setMbit, transmitOffset);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4AddRtpImmediateData(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ const u_int8_t* pBytes,
+ u_int32_t numBytes)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AddRtpImmediateData(hintTrackId,
+ pBytes, numBytes);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4AddRtpSampleData(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4SampleId sampleId,
+ u_int32_t dataOffset,
+ u_int32_t dataLength)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AddRtpSampleData(
+ hintTrackId, sampleId, dataOffset, dataLength);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4AddRtpESConfigurationPacket(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->AddRtpESConfigurationPacket(hintTrackId);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4WriteRtpHint(
+ MP4FileHandle hFile,
+ MP4TrackId hintTrackId,
+ MP4Duration duration,
+ bool isSyncSample)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->WriteRtpHint(
+ hintTrackId, duration, isSyncSample);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+/* 3GPP specific operations */
+
+extern "C" bool MP4Make3GPCompliant(
+ const MP4_FILENAME_CHAR* fileName,
+ u_int32_t verbosity,
+ char* majorBrand,
+ u_int32_t minorVersion,
+ char** supportedBrands,
+ u_int32_t supportedBrandsCount,
+ bool deleteIodsAtom)
+{
+ MP4File* pFile;
+ pFile = NULL;
+
+ try {
+ pFile = new MP4File(verbosity);
+ pFile->Modify(fileName);
+ pFile->Make3GPCompliant(fileName, majorBrand, minorVersion, supportedBrands, supportedBrandsCount, deleteIodsAtom);
+ pFile->Close();
+ delete pFile;
+ return true;
+ }
+ catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ }
+ delete pFile;
+ return false;
+}
+
+/* ISMA specific operations */
+
+extern "C" bool MP4MakeIsmaCompliant(
+ const MP4_FILENAME_CHAR* fileName,
+ u_int32_t verbosity,
+ bool addIsmaComplianceSdp)
+{
+ MP4File* pFile;
+ pFile = NULL;
+
+ try {
+ pFile = new MP4File(verbosity);
+ pFile->Modify(fileName);
+ pFile->MakeIsmaCompliant(addIsmaComplianceSdp);
+ pFile->Close();
+ delete pFile;
+ return true;
+ }
+ catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ }
+ delete pFile;
+ return false;
+}
+
+extern "C" char* MP4MakeIsmaSdpIod(
+ u_int8_t videoProfile,
+ u_int32_t videoBitrate,
+ u_int8_t* videoConfig,
+ u_int32_t videoConfigLength,
+ u_int8_t audioProfile,
+ u_int32_t audioBitrate,
+ u_int8_t* audioConfig,
+ u_int32_t audioConfigLength,
+ u_int32_t verbosity)
+{
+ MP4File* pFile = NULL;
+
+ try {
+ pFile = new MP4File(verbosity);
+
+ u_int8_t* pBytes = NULL;
+ u_int64_t numBytes = 0;
+
+ pFile->CreateIsmaIodFromParams(
+ videoProfile,
+ videoBitrate,
+ videoConfig,
+ videoConfigLength,
+ audioProfile,
+ audioBitrate,
+ audioConfig,
+ audioConfigLength,
+ &pBytes,
+ &numBytes);
+
+ char* iodBase64 =
+ MP4ToBase64(pBytes, numBytes);
+ MP4Free(pBytes);
+
+ char* sdpIod =
+ (char*)MP4Malloc(strlen(iodBase64) + 64);
+ snprintf(sdpIod, strlen(iodBase64) + 64,
+ "a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042",
+ iodBase64);
+ MP4Free(iodBase64);
+
+ delete pFile;
+
+ return sdpIod;
+ }
+ catch (MP4Error* e) {
+ VERBOSE_ERROR(verbosity, e->Print());
+ delete e;
+ }
+ return NULL;
+}
+
+/* Edit list */
+
+extern "C" MP4EditId MP4AddTrackEdit(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId,
+ MP4Timestamp startTime,
+ MP4Duration duration,
+ bool dwell)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ MP4EditId newEditId =
+ ((MP4File*)hFile)->AddTrackEdit(trackId, editId);
+
+ if (newEditId != MP4_INVALID_EDIT_ID) {
+ ((MP4File*)hFile)->SetTrackEditMediaStart(
+ trackId, newEditId, startTime);
+ ((MP4File*)hFile)->SetTrackEditDuration(
+ trackId, newEditId, duration);
+ ((MP4File*)hFile)->SetTrackEditDwell(
+ trackId, newEditId, dwell);
+ }
+
+ return newEditId;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_EDIT_ID;
+}
+
+extern "C" bool MP4DeleteTrackEdit(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->DeleteTrackEdit(trackId, editId);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" u_int32_t MP4GetTrackNumberOfEdits(
+ MP4FileHandle hFile,
+ MP4TrackId trackId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackNumberOfEdits(trackId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return 0;
+}
+
+extern "C" MP4Timestamp MP4GetTrackEditMediaStart(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackEditMediaStart(
+ trackId, editId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_TIMESTAMP;
+}
+
+extern "C" MP4Duration MP4GetTrackEditTotalDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackEditTotalDuration(
+ trackId, editId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" bool MP4SetTrackEditMediaStart(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId,
+ MP4Timestamp startTime)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackEditMediaStart(
+ trackId, editId, startTime);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" MP4Duration MP4GetTrackEditDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackEditDuration(trackId, editId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_DURATION;
+}
+
+extern "C" bool MP4SetTrackEditDuration(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId,
+ MP4Duration duration)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackEditDuration(trackId, editId, duration);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" int8_t MP4GetTrackEditDwell(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetTrackEditDwell(trackId, editId);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return -1;
+}
+
+extern "C" bool MP4SetTrackEditDwell(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4EditId editId,
+ bool dwell)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ ((MP4File*)hFile)->SetTrackEditDwell(trackId, editId, dwell);
+ return true;
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4ReadSampleFromEditTime(
+ /* input parameters */
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ /* output parameters */
+ u_int8_t** ppBytes,
+ u_int32_t* pNumBytes,
+ MP4Timestamp* pStartTime,
+ MP4Duration* pDuration,
+ MP4Duration* pRenderingOffset,
+ bool* pIsSyncSample)
+{
+ MP4SampleId sampleId =
+ MP4GetSampleIdFromEditTime(
+ hFile,
+ trackId,
+ when,
+ pStartTime,
+ pDuration);
+
+ return MP4ReadSample(
+ hFile,
+ trackId,
+ sampleId,
+ ppBytes,
+ pNumBytes,
+ NULL,
+ NULL,
+ pRenderingOffset,
+ pIsSyncSample);
+}
+
+extern "C" MP4SampleId MP4GetSampleIdFromEditTime(
+ MP4FileHandle hFile,
+ MP4TrackId trackId,
+ MP4Timestamp when,
+ MP4Timestamp* pStartTime,
+ MP4Duration* pDuration)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetSampleIdFromEditTime(
+ trackId, when, pStartTime, pDuration);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return MP4_INVALID_SAMPLE_ID;
+}
+
+/* Utlities */
+
+extern "C" char* MP4BinaryToBase16(
+ const u_int8_t* pData,
+ u_int32_t dataSize)
+{
+ if (pData || dataSize == 0) {
+ try {
+ return MP4ToBase16(pData, dataSize);
+ }
+ catch (MP4Error* e) {
+ delete e;
+ }
+ }
+ return NULL;
+}
+
+extern "C" char* MP4BinaryToBase64(
+ const u_int8_t* pData,
+ u_int32_t dataSize)
+{
+ if (pData || dataSize == 0) {
+ try {
+ return MP4ToBase64(pData, dataSize);
+ }
+ catch (MP4Error* e) {
+ delete e;
+ }
+ }
+ return NULL;
+}
+
+/* iTunes meta data handling */
+extern "C" bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index,
+ char** ppName,
+ u_int8_t** ppValue, u_int32_t* pValueSize)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataByIndex(
+ index, ppName, ppValue, pValueSize);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4MetadataDelete(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->MetadataDelete();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataName(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251nam", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataName(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251nam", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataName(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251nam");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataWriter(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251wrt", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataWriter(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251wrt", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataWriter(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251wrt");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataAlbum(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251alb", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataAlbum(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251alb", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataAlbum(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251alb");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataArtist(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251ART", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataArtist(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251ART", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataArtist(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251ART");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataRating(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("rate", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataRating(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("rate", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataRating(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("rate");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataTool(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251too", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataTool(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251too", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataTool(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251too");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataComment(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251cmt", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataComment(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251cmt", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataComment(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251cmt");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataYear(MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251day", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataYear(MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251day", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataYear(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251day");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataTrack(MP4FileHandle hFile,
+ u_int16_t track, u_int16_t totalTracks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataTrack(track, totalTracks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataTrack(MP4FileHandle hFile,
+ u_int16_t* track, u_int16_t* totalTracks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataTrack(track, totalTracks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataTrack(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("trkn");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataDisk(MP4FileHandle hFile,
+ u_int16_t disk, u_int16_t totalDisks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataDisk(disk, totalDisks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataDisk(MP4FileHandle hFile,
+ u_int16_t* disk, u_int16_t* totalDisks)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataDisk(disk, totalDisks);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataDisk(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("disk");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataGenre(genre);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataGenre(MP4FileHandle hFile, char **genre)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataGenre(genre);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataGenre(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataGenre();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataGrouping(MP4FileHandle hFile, const char *grouping)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("\251grp", grouping);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataGrouping(MP4FileHandle hFile, char **grouping)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("\251grp", grouping);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataGrouping(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("\251grp");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataTempo(tempo);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataTempo(tempo);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataTempo(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("tmpo");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataUint8("cpil", cpl & 0x1);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataUint8("cpil", cpl);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataCompilation(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("cpil");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataPartOfGaplessAlbum (MP4FileHandle hFile,
+ u_int8_t pgap)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataUint8("pgap", pgap & 0x1);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataPartOfGaplessAlbum (MP4FileHandle hFile,
+ u_int8_t* pgap)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataUint8("pgap", pgap);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataPartOfGaplessAlbum (MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("pgap");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataCoverArt(MP4FileHandle hFile, u_int8_t *coverArt, u_int32_t size, int flags)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataCoverArt(coverArt, size, flags);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataCoverArt(MP4FileHandle hFile, u_int8_t **coverArt, u_int32_t* size, int *flags, uint32_t index)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataCoverArt(coverArt, size, index);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" u_int32_t MP4GetMetadataCoverArtCount(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataCoverArtCount();
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataCoverArt(MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("covr");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+extern "C" bool MP4SetMetadataAlbumArtist (MP4FileHandle hFile,
+ const char* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataString("aART", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataAlbumArtist (MP4FileHandle hFile,
+ char** value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataString("aART", value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataAlbumArtist (MP4FileHandle hFile)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataAtom("aART");
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4SetMetadataFreeForm(MP4FileHandle hFile,
+ const char *name,
+ const u_int8_t* pValue,
+ u_int32_t valueSize,
+ const char *owner)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->SetMetadataFreeForm(name, pValue, valueSize, owner);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4GetMetadataFreeForm(MP4FileHandle hFile, const char *name,
+ u_int8_t** pValue, u_int32_t* valueSize, const char *owner)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->GetMetadataFreeForm(name, pValue, valueSize, owner);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4DeleteMetadataFreeForm(MP4FileHandle hFile, const char *name, const char *owner)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->DeleteMetadataFreeForm(name, owner);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4Get3GPMetadata(MP4FileHandle hFile, const char *name, uint16_t **value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->Get3GPMetadataString(name, value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4Set3GPMetadata(MP4FileHandle hFile, const char *name, const uint16_t* value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->Set3GPMetadataString(name, value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" bool MP4Get3GPMetadataInteger(MP4FileHandle hFile, const char *name, uint64_t *value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->Get3GPMetadataInteger(name, value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+bool MP4Set3GPMetadataInteger(MP4FileHandle hFile, const char *name, uint64_t value)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->Set3GPMetadataInteger(name, value);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+extern "C" bool MP4Delete3GPMetadata(MP4FileHandle hFile, const char *name)
+{
+ if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
+ try {
+ return ((MP4File*)hFile)->Delete3GPMetadataAtom(name);
+ }
+ catch (MP4Error* e) {
+ PRINT_ERROR(e);
+ delete e;
+ }
+ }
+ return false;
+}
+
+extern "C" void MP4Free (void *p)
+{
+ if (p != NULL)
+ free(p);
+}