ref: c0ae72652fc9619e8b1e8f365ab977614179779a
dir: /common/mp4v2/mp4.cpp/
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. * * Contributor(s): * Dave Mackie [email protected] * Alix Marchandise-Franquet [email protected] */ /* * 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 */ extern "C" MP4FileHandle MP4Read(const 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; } } #ifdef USE_FILE_CALLBACKS extern "C" MP4FileHandle MP4CreateCb(u_int32_t verbosity, bool use64bits, bool useExtensibleFormat, MP4OpenCallback MP4fopen, MP4CloseCallback MP4fclose, MP4ReadCallback MP4fread, MP4WriteCallback MP4fwrite, MP4SetposCallback MP4fsetpos, MP4GetposCallback MP4fgetpos, MP4FilesizeCallback MP4filesize, void *userData) { MP4File* pFile = NULL; try { pFile = new MP4File(verbosity); // LATER useExtensibleFormat, moov first, then mvex's // Set user data and callbacks pFile->m_userData = userData; pFile->m_MP4fopen = MP4fopen; pFile->m_MP4fclose = MP4fclose; pFile->m_MP4fread = MP4fread; pFile->m_MP4fwrite = MP4fwrite; pFile->m_MP4fsetpos = MP4fsetpos; pFile->m_MP4fgetpos = MP4fgetpos; pFile->m_MP4filesize = MP4filesize; pFile->Create("", use64bits); return (MP4FileHandle)pFile; } catch (MP4Error* e) { VERBOSE_ERROR(verbosity, e->Print()); delete e; delete pFile; return MP4_INVALID_FILE_HANDLE; } } extern "C" MP4FileHandle MP4ReadCb(u_int32_t verbosity, MP4OpenCallback MP4fopen, MP4CloseCallback MP4fclose, MP4ReadCallback MP4fread, MP4WriteCallback MP4fwrite, MP4SetposCallback MP4fsetpos, MP4GetposCallback MP4fgetpos, MP4FilesizeCallback MP4filesize, void *userData ) { MP4File* pFile = NULL; try { pFile = new MP4File(verbosity); // Set user data and callbacks pFile->m_userData = userData; pFile->m_MP4fopen = MP4fopen; pFile->m_MP4fclose = MP4fclose; pFile->m_MP4fread = MP4fread; pFile->m_MP4fwrite = MP4fwrite; pFile->m_MP4fsetpos = MP4fsetpos; pFile->m_MP4fgetpos = MP4fgetpos; pFile->m_MP4filesize = MP4filesize; pFile->Read(""); return (MP4FileHandle)pFile; } catch (MP4Error* e) { VERBOSE_ERROR(verbosity, e->Print()); delete e; delete pFile; return MP4_INVALID_FILE_HANDLE; } } extern "C" MP4FileHandle MP4ModifyCb(int32_t verbosity, bool useExtensibleFormat, MP4OpenCallback MP4fopen, MP4CloseCallback MP4fclose, MP4ReadCallback MP4fread, MP4WriteCallback MP4fwrite, MP4SetposCallback MP4fsetpos, MP4GetposCallback MP4fgetpos, MP4FilesizeCallback MP4filesize, void *userData) { MP4File* pFile = NULL; try { pFile = new MP4File(verbosity); // Set user data and callbacks pFile->m_userData = userData; pFile->m_MP4fopen = MP4fopen; pFile->m_MP4fclose = MP4fclose; pFile->m_MP4fread = MP4fread; pFile->m_MP4fwrite = MP4fwrite; pFile->m_MP4fsetpos = MP4fsetpos; pFile->m_MP4fgetpos = MP4fgetpos; pFile->m_MP4filesize = MP4filesize; // LATER useExtensibleFormat, moov first, then mvex's pFile->Modify(""); return (MP4FileHandle)pFile; } catch (MP4Error* e) { VERBOSE_ERROR(verbosity, e->Print()); delete e; delete pFile; return MP4_INVALID_FILE_HANDLE; } } #endif extern "C" MP4FileHandle MP4Create(const char* fileName, u_int32_t verbosity, bool use64bits, bool useExtensibleFormat) { MP4File* pFile = NULL; try { pFile = new MP4File(verbosity); // LATER useExtensibleFormat, moov first, then mvex's pFile->Create(fileName, use64bits); 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 char* fileName, u_int32_t verbosity, bool useExtensibleFormat) { 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 char* existingFileName, const 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" bool MP4Close(MP4FileHandle hFile) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { ((MP4File*)hFile)->Close(); delete (MP4File*)hFile; return true; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4Dump( MP4FileHandle hFile, FILE* pDumpFile, bool dumpImplicits) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { ((MP4File*)hFile)->Dump(pDumpFile, dumpImplicits); return true; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } /* 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" bool MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { ((MP4File*)hFile)->SetVerbosity(verbosity); return true; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } 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) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetVideoProfileLevel(); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return 0; } extern "C" bool MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { ((MP4File*)hFile)->SetVideoProfileLevel(value); return true; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } 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" bool MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { ((MP4File*)hFile)->SetAudioProfileLevel(value); return true; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } 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" u_int64_t MP4GetIntegerProperty( MP4FileHandle hFile, const char* propName) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetIntegerProperty(propName); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return (u_int64_t)-1; } extern "C" float MP4GetFloatProperty( MP4FileHandle hFile, const char* propName) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetFloatProperty(propName); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return NAN; } extern "C" const char* MP4GetStringProperty( MP4FileHandle hFile, const char* propName) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetStringProperty(propName); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return NULL; } extern "C" void 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; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } *ppValue = NULL; *pValueSize = 0; return; } 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; } extern "C" MP4TrackId MP4AddEncAudioTrack(MP4FileHandle hFile, u_int32_t timeScale, MP4Duration sampleDuration, u_int8_t audioType) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)-> AddEncAudioTrack(timeScale, sampleDuration, audioType); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return MP4_INVALID_TRACK_ID; } extern "C" MP4TrackId MP4AddVideoTrack( MP4FileHandle hFile, u_int32_t timeScale, MP4Duration sampleDuration, u_int16_t width, u_int16_t height, u_int8_t videoType) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->AddVideoTrack( 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, u_int8_t videoType) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->AddEncVideoTrack(timeScale, sampleDuration, width, height, videoType); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return MP4_INVALID_TRACK_ID; } extern "C" MP4TrackId MP4AddHintTrack( MP4FileHandle hFile, MP4TrackId refTrackId) { 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 MP4CloneTrack( MP4FileHandle srcFile, MP4TrackId srcTrackId, MP4FileHandle dstFile) { 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)) { MP4SetVideoProfileLevel(dstFile, MP4GetVideoProfileLevel(srcFile)); dstTrackId = MP4AddVideoTrack( dstFile, MP4GetTrackTimeScale(srcFile, srcTrackId), MP4GetTrackFixedSampleDuration(srcFile, srcTrackId), MP4GetTrackVideoWidth(srcFile, srcTrackId), MP4GetTrackVideoHeight(srcFile, srcTrackId), MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId)); } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) { MP4SetAudioProfileLevel(dstFile, MP4GetAudioProfileLevel(srcFile)); dstTrackId = MP4AddAudioTrack( dstFile, MP4GetTrackTimeScale(srcFile, srcTrackId), MP4GetTrackFixedSampleDuration(srcFile, srcTrackId), 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)) { 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; MP4GetTrackESConfiguration( srcFile, srcTrackId, &pConfig, &configSize); MP4SetTrackESConfiguration( dstFile, dstTrackId, pConfig, configSize); 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; MP4GetHintTrackRtpPayload( srcFile, srcTrackId, &payloadName, &payloadNumber, &maxPayloadSize, &encodingParms); MP4SetHintTrackRtpPayload( dstFile, dstTrackId, payloadName, &payloadNumber, maxPayloadSize, encodingParms); MP4SetHintTrackSdp( dstFile, dstTrackId, MP4GetHintTrackSdp(srcFile, srcTrackId)); } return dstTrackId; } // Given a track, make an encrypted clone of it in the dest. file extern "C" MP4TrackId MP4EncAndCloneTrack(MP4FileHandle srcFile, MP4TrackId srcTrackId, MP4FileHandle dstFile) { 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)) { MP4SetVideoProfileLevel(dstFile, MP4GetVideoProfileLevel(srcFile)); dstTrackId = MP4AddEncVideoTrack(dstFile, MP4GetTrackTimeScale(srcFile, srcTrackId), MP4GetTrackFixedSampleDuration(srcFile, srcTrackId), MP4GetTrackVideoWidth(srcFile, srcTrackId), MP4GetTrackVideoHeight(srcFile, srcTrackId), MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId)); } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) { MP4SetAudioProfileLevel(dstFile, MP4GetAudioProfileLevel(srcFile)); dstTrackId = MP4AddEncAudioTrack(dstFile, MP4GetTrackTimeScale(srcFile, srcTrackId), MP4GetTrackFixedSampleDuration(srcFile, srcTrackId), MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId)); } 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)) { 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); } return dstTrackId; } extern "C" MP4TrackId MP4CopyTrack(MP4FileHandle srcFile, MP4TrackId srcTrackId, MP4FileHandle dstFile, bool applyEdits) { bool copySamples = true; // LATER allow false => reference samples MP4TrackId dstTrackId = MP4CloneTrack(srcFile, srcTrackId, dstFile); if (dstTrackId == MP4_INVALID_TRACK_ID) { return dstTrackId; } bool viaEdits = applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId); MP4SampleId sampleId = 0; MP4SampleId numSamples = MP4GetTrackNumberOfSamples(srcFile, srcTrackId); MP4Timestamp when = 0; MP4Duration editsDuration = MP4GetTrackEditTotalDuration(srcFile, srcTrackId); while (true) { MP4Duration sampleDuration = MP4_INVALID_DURATION; if (viaEdits) { sampleId = MP4GetSampleIdFromEditTime( srcFile, srcTrackId, when, NULL, &sampleDuration); // in theory, this shouldn't happen if (sampleId == MP4_INVALID_SAMPLE_ID) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } when += sampleDuration; if (when >= editsDuration) { break; } } else { sampleId++; if (sampleId > numSamples) { break; } } bool rc = false; if (copySamples) { rc = MP4CopySample( srcFile, srcTrackId, sampleId, dstFile, dstTrackId, sampleDuration); } else { rc = MP4ReferenceSample( srcFile, srcTrackId, sampleId, dstFile, dstTrackId, sampleDuration); } if (!rc) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } } return dstTrackId; } // Given a source track in a source file, make an encrypted copy of // the track in the destination file, including sample encryption extern "C" MP4TrackId MP4EncAndCopyTrack(MP4FileHandle srcFile, MP4TrackId srcTrackId, MP4FileHandle dstFile, bool applyEdits) { bool copySamples = true; // LATER allow false => reference samples MP4TrackId dstTrackId = MP4EncAndCloneTrack(srcFile, srcTrackId, dstFile); if (dstTrackId == MP4_INVALID_TRACK_ID) { return dstTrackId; } bool viaEdits = applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId); MP4SampleId sampleId = 0; MP4SampleId numSamples = MP4GetTrackNumberOfSamples(srcFile, srcTrackId); MP4Timestamp when = 0; MP4Duration editsDuration = MP4GetTrackEditTotalDuration(srcFile, srcTrackId); while (true) { MP4Duration sampleDuration = MP4_INVALID_DURATION; if (viaEdits) { sampleId = MP4GetSampleIdFromEditTime(srcFile, srcTrackId, when, NULL, &sampleDuration); // in theory, this shouldn't happen if (sampleId == MP4_INVALID_SAMPLE_ID) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } when += sampleDuration; if (when >= editsDuration) { break; } } else { sampleId++; if (sampleId > numSamples) { break; } } bool rc = false; if (copySamples) { // will need to encrypt the sample here rc = MP4CopySample(srcFile, srcTrackId, sampleId, dstFile, dstTrackId, sampleDuration); } else { rc = MP4ReferenceSample(srcFile, srcTrackId, sampleId, dstFile, dstTrackId, sampleDuration); } if (!rc) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } } return dstTrackId; } extern "C" bool MP4DeleteTrack( MP4FileHandle hFile, MP4TrackId trackId) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { ((MP4File*)hFile)->DeleteTrack(trackId); return true; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } 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" 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" bool MP4SetTrackTimeScale( MP4FileHandle hFile, MP4TrackId trackId, u_int32_t value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { ((MP4File*)hFile)->SetTrackTimeScale(trackId, value); return true; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } // This function should not be used anymore // use MP4GetTrackEsdsObjectTypeId instead extern "C" u_int8_t MP4GetTrackAudioType( MP4FileHandle hFile, MP4TrackId trackId) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetTrackAudioType(trackId); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return MP4_INVALID_AUDIO_TYPE; } 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; } // This function should not be used anymore // use MP4GetTrackEsdsObjectTypeId instead extern "C" u_int8_t MP4GetTrackVideoType( MP4FileHandle hFile, MP4TrackId trackId) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetTrackVideoType(trackId); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return MP4_INVALID_VIDEO_TYPE; } // Replacement to MP4GetTrackVideoType and MP4GetTrackAudioType // Basically does the same thing but with a more self-explanatory name extern "C" u_int8_t MP4GetTrackEsdsObjectTypeId( MP4FileHandle hFile, MP4TrackId trackId) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetTrackEsdsObjectTypeId(trackId); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return MP4_INVALID_AUDIO_TYPE; } extern "C" MP4Duration MP4GetTrackFixedSampleDuration( MP4FileHandle hFile, MP4TrackId trackId) { 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)) { try { return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, "mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate"); } 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 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" 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" 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" float 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; } /* generic track properties */ extern "C" u_int64_t MP4GetTrackIntegerProperty( MP4FileHandle hFile, MP4TrackId trackId, const char* propName) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, propName); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return (u_int64_t)-1; } extern "C" float MP4GetTrackFloatProperty( MP4FileHandle hFile, MP4TrackId trackId, const char* propName) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetTrackFloatProperty(trackId, propName); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return NAN; } extern "C" const char* MP4GetTrackStringProperty( MP4FileHandle hFile, MP4TrackId trackId, const char* propName) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetTrackStringProperty(trackId, propName); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return NULL; } extern "C" void 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; } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } *ppValue = NULL; *pValueSize = 0; return; } 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 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 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) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetSampleIdFromTime( trackId, when, wantSyncSample); } 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; } /* ISMA specific operations */ extern "C" bool MP4MakeIsmaCompliant( const char* fileName, u_int32_t verbosity, bool addIsmaComplianceSdp) { MP4File* 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); sprintf(sdpIod, "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; } delete pFile; 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, const 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)->SetMetadataName(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)->GetMetadataName(value); } 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)->SetMetadataWriter(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)->GetMetadataWriter(value); } 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)->SetMetadataAlbum(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataAlbum(MP4FileHandle hFile, char** value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataAlbum(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataArtist(MP4FileHandle hFile, const char* value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataArtist(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataArtist(MP4FileHandle hFile, char** value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataArtist(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataTool(MP4FileHandle hFile, const char* value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataTool(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataTool(MP4FileHandle hFile, char** value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataTool(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataComment(MP4FileHandle hFile, const char* value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataComment(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataComment(MP4FileHandle hFile, char** value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataComment(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataYear(MP4FileHandle hFile, const char* value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataYear(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataYear(MP4FileHandle hFile, char** value) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataYear(value); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataTrack(MP4FileHandle hFile, u_int16_t track, u_int16_t totalTracks) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataTrack(track, totalTracks); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataTrack(MP4FileHandle hFile, u_int16_t* track, u_int16_t* totalTracks) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataTrack(track, totalTracks); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataDisk(MP4FileHandle hFile, u_int16_t disk, u_int16_t totalDisks) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataDisk(disk, totalDisks); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataDisk(MP4FileHandle hFile, u_int16_t* disk, u_int16_t* totalDisks) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataDisk(disk, totalDisks); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataGenre(MP4FileHandle hFile, 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 MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataTempo(tempo); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataTempo(tempo); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataCompilation(cpl); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataCompilation(cpl); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataCoverArt(MP4FileHandle hFile, u_int8_t *coverArt, u_int32_t size) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataCoverArt(coverArt, size); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataCoverArt(MP4FileHandle hFile, u_int8_t **coverArt, u_int32_t* size) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataCoverArt(coverArt, size); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name, u_int8_t* pValue, u_int32_t valueSize) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->SetMetadataFreeForm(name, pValue, valueSize); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; } extern "C" bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name, u_int8_t** pValue, u_int32_t* valueSize) { if (MP4_IS_VALID_FILE_HANDLE(hFile)) { try { return ((MP4File*)hFile)->GetMetadataFreeForm(name, pValue, valueSize); } catch (MP4Error* e) { PRINT_ERROR(e); delete e; } } return false; }