diff options
Diffstat (limited to 'Src/external_dependencies/libmp4v2/mp4.cpp')
-rw-r--r-- | Src/external_dependencies/libmp4v2/mp4.cpp | 4642 |
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); +} |