/* * 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); }