| /* |
| * 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 "src/impl.h" |
| |
| using namespace mp4v2::impl; |
| |
| static MP4File *ConstructMP4File ( void ) |
| { |
| MP4File* pFile = NULL; |
| try { |
| pFile = new MP4File(); |
| } |
| catch( std::bad_alloc ) { |
| mp4v2::impl::log.errorf("%s: unable to allocate MP4File", __FUNCTION__); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf("%s: unknown exception constructing MP4File", __FUNCTION__ ); |
| } |
| |
| return pFile; |
| } |
| |
| extern "C" { |
| |
| const char* MP4GetFilename( MP4FileHandle hFile ) |
| { |
| if (!MP4_IS_VALID_FILE_HANDLE(hFile)) |
| return NULL; |
| try |
| { |
| ASSERT(hFile); |
| MP4File& file = *static_cast<MP4File*>(hFile); |
| ASSERT(file.GetFilename().c_str()); |
| return file.GetFilename().c_str(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf("%s: unknown exception accessing MP4File " |
| "filename", __FUNCTION__ ); |
| } |
| |
| return NULL; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| MP4FileHandle MP4Read( const char* fileName ) |
| { |
| if (!fileName) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| MP4File *pFile = ConstructMP4File(); |
| if (!pFile) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| try |
| { |
| ASSERT(pFile); |
| pFile->Read( fileName, NULL ); |
| return (MP4FileHandle)pFile; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf("%s: \"%s\": failed", __FUNCTION__, |
| fileName ); |
| } |
| |
| if (pFile) |
| delete pFile; |
| return MP4_INVALID_FILE_HANDLE; |
| } |
| |
| MP4FileHandle MP4ReadProvider( const char* fileName, const MP4FileProvider* fileProvider ) |
| { |
| if (!fileName) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| MP4File *pFile = ConstructMP4File(); |
| if (!pFile) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| try { |
| pFile->Read( fileName, fileProvider ); |
| return (MP4FileHandle)pFile; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf("%s: \"%s\": failed", __FUNCTION__, |
| fileName ); |
| } |
| |
| if (pFile) |
| delete pFile; |
| return MP4_INVALID_FILE_HANDLE; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| MP4FileHandle MP4Create (const char* fileName, |
| uint32_t flags) |
| { |
| return MP4CreateProviderEx(fileName, flags); |
| } |
| |
| MP4FileHandle MP4CreateEx (const char* fileName, |
| uint32_t flags, |
| int add_ftyp, |
| int add_iods, |
| char* majorBrand, |
| uint32_t minorVersion, |
| char** supportedBrands, |
| uint32_t supportedBrandsCount) |
| { |
| return MP4CreateProviderEx(fileName, flags, NULL, |
| add_ftyp, add_iods, |
| majorBrand, minorVersion, |
| supportedBrands, supportedBrandsCount); |
| } |
| |
| MP4FileHandle MP4CreateProvider (const char* fileName, |
| uint32_t flags, |
| const MP4FileProvider* fileProvider) |
| { |
| return MP4CreateProviderEx(fileName, flags, fileProvider); |
| } |
| |
| MP4FileHandle MP4CreateProviderEx (const char* fileName, |
| uint32_t flags, |
| const MP4FileProvider* fileProvider, |
| int add_ftyp, |
| int add_iods, |
| char* majorBrand, |
| uint32_t minorVersion, |
| char** supportedBrands, |
| uint32_t supportedBrandsCount) |
| { |
| if (!fileName) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| MP4File* pFile = ConstructMP4File(); |
| if (!pFile) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| try { |
| ASSERT(pFile); |
| // LATER useExtensibleFormat, moov first, then mvex's |
| pFile->Create(fileName, flags, fileProvider, |
| add_ftyp, add_iods, |
| majorBrand, minorVersion, |
| supportedBrands, supportedBrandsCount); |
| return (MP4FileHandle)pFile; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf("%s: \"%s\": failed", __FUNCTION__, |
| fileName ); |
| } |
| |
| if (pFile) |
| delete pFile; |
| return MP4_INVALID_FILE_HANDLE; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| MP4FileHandle MP4Modify(const char* fileName, |
| uint32_t flags) |
| { |
| if (!fileName) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| MP4File* pFile = ConstructMP4File(); |
| if (!pFile) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| try { |
| ASSERT(pFile); |
| // LATER useExtensibleFormat, moov first, then mvex's |
| if (pFile->Modify(fileName)) |
| return (MP4FileHandle)pFile; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf("%s: \"%s\": failed", __FUNCTION__, |
| fileName ); |
| } |
| |
| if (pFile) |
| delete pFile; |
| return MP4_INVALID_FILE_HANDLE; |
| } |
| |
| bool MP4Optimize(const char* fileName, |
| const char* newFileName) |
| { |
| // Must at least have fileName for in-place optimize; newFileName |
| // can be null, however. |
| if (fileName == NULL) |
| return false; |
| |
| MP4File* pFile = ConstructMP4File(); |
| if (!pFile) |
| return MP4_INVALID_FILE_HANDLE; |
| |
| try { |
| ASSERT(pFile); |
| pFile->Optimize(fileName, newFileName); |
| delete pFile; |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf("%s(%s,%s) failed", __FUNCTION__, |
| fileName, newFileName ); |
| } |
| |
| if (pFile) |
| delete pFile; |
| return false; |
| } |
| |
| void MP4Close(MP4FileHandle hFile, uint32_t flags) |
| { |
| if( !MP4_IS_VALID_FILE_HANDLE( hFile )) |
| return; |
| |
| MP4File& f = *(MP4File*)hFile; |
| try { |
| f.Close(flags); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| |
| delete &f; |
| } |
| |
| bool MP4Dump( |
| MP4FileHandle hFile, |
| bool dumpImplicits) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->Dump(dumpImplicits); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| MP4Duration MP4GetDuration(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetDuration(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_DURATION; |
| } |
| |
| uint32_t MP4GetTimeScale(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTimeScale(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| bool MP4SetTimeScale(MP4FileHandle hFile, uint32_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetTimeScale(value); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| uint8_t MP4GetODProfileLevel(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetODProfileLevel(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| bool MP4SetODProfileLevel(MP4FileHandle hFile, uint8_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetODProfileLevel(value); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| uint8_t MP4GetSceneProfileLevel(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetSceneProfileLevel(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| bool MP4SetSceneProfileLevel(MP4FileHandle hFile, uint8_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetSceneProfileLevel(value); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| uint8_t MP4GetVideoProfileLevel(MP4FileHandle hFile, |
| MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetVideoProfileLevel(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| 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 (MP4V2_HTONL(*(uint32_t *)ptr) == 0x1b0) { |
| uint8_t ret = ptr[4]; |
| free(foo); |
| return ret; |
| } |
| ptr++; |
| bufsize--; |
| } |
| free(foo); |
| } |
| } |
| } |
| |
| } |
| return 0; |
| } |
| |
| void MP4SetVideoProfileLevel(MP4FileHandle hFile, uint8_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetVideoProfileLevel(value); |
| return ; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return ; |
| } |
| |
| uint8_t MP4GetAudioProfileLevel(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetAudioProfileLevel(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| void MP4SetAudioProfileLevel(MP4FileHandle hFile, uint8_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetAudioProfileLevel(value); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| uint8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetGraphicsProfileLevel(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, uint8_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetGraphicsProfileLevel(value); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| /* generic file properties */ |
| |
| bool MP4HaveAtom (MP4FileHandle hFile, const char *atomName) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File *)hFile)->FindAtom(atomName) != NULL; |
| } catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| bool MP4GetIntegerProperty( |
| MP4FileHandle hFile, const char* propName, uint64_t *retvalue) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| *retvalue = ((MP4File*)hFile)->GetIntegerProperty(propName); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| bool MP4GetBytesProperty( |
| MP4FileHandle hFile, const char* propName, |
| uint8_t** ppValue, uint32_t* pValueSize) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->GetBytesProperty(propName, ppValue, pValueSize); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| *ppValue = NULL; |
| *pValueSize = 0; |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| bool MP4SetBytesProperty( |
| MP4FileHandle hFile, const char* propName, |
| const uint8_t* pValue, uint32_t valueSize) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetBytesProperty(propName, pValue, valueSize); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| /* track operations */ |
| |
| MP4TrackId MP4AddTrack( |
| MP4FileHandle hFile, const char* type,uint32_t timeScale) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddSystemsTrack(type, timeScale); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddSystemsTrack( |
| MP4FileHandle hFile, const char* type) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddSystemsTrack(type); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddODTrack(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddODTrack(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddSceneTrack(MP4FileHandle hFile) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddSceneTrack(); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddULawAudioTrack( |
| MP4FileHandle hFile, |
| uint32_t timeScale) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)-> |
| AddULawAudioTrack(timeScale); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddALawAudioTrack( |
| MP4FileHandle hFile, |
| uint32_t timeScale) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)-> |
| AddALawAudioTrack(timeScale); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddAudioTrack( |
| MP4FileHandle hFile, |
| uint32_t timeScale, |
| MP4Duration sampleDuration, |
| uint8_t audioType) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)-> |
| AddAudioTrack(timeScale, sampleDuration, audioType); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| 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. |
| // |
| 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 nullptr; |
| } |
| } |
| |
| |
| MP4TrackId MP4AddAC3AudioTrack( |
| MP4FileHandle hFile, |
| uint32_t samplingRate, |
| uint8_t fscod, |
| uint8_t bsid, |
| uint8_t bsmod, |
| uint8_t acmod, |
| uint8_t lfeon, |
| uint8_t bit_rate_code) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)-> |
| AddAC3AudioTrack(samplingRate, fscod, bsid, bsmod, acmod, lfeon, bit_rate_code); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddEncAudioTrack(MP4FileHandle hFile, |
| uint32_t timeScale, |
| MP4Duration sampleDuration, |
| mp4v2_ismacrypParams *icPp, |
| uint8_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| MP4TrackId MP4AddAmrAudioTrack( |
| MP4FileHandle hFile, |
| uint32_t timeScale, |
| uint16_t modeSet, |
| uint8_t modeChangePeriod, |
| uint8_t framesPerSample, |
| bool isAmrWB) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)-> |
| AddAmrAudioTrack(timeScale, modeSet, modeChangePeriod, framesPerSample, isAmrWB); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| void MP4SetAmrVendor( |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| uint32_t vendor) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)-> |
| SetAmrVendor(trackId, vendor); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| void MP4SetAmrDecoderVersion( |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| uint8_t decoderVersion) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)-> |
| SetAmrDecoderVersion(trackId, decoderVersion); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| void MP4SetAmrModeSet( |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| uint16_t modeSet) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)-> |
| SetAmrModeSet(trackId, modeSet); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| uint16_t MP4GetAmrModeSet( |
| MP4FileHandle hFile, |
| MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)-> |
| GetAmrModeSet(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return NULL; |
| } |
| |
| MP4TrackId MP4AddVideoTrack( |
| MP4FileHandle hFile, |
| uint32_t timeScale, |
| MP4Duration sampleDuration, |
| uint16_t width, |
| uint16_t height, |
| uint8_t videoType) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| MP4File *pFile = (MP4File *)hFile; |
| |
| return pFile->AddMP4VideoTrack(timeScale, |
| sampleDuration, |
| width, |
| height, |
| videoType); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddEncVideoTrack(MP4FileHandle hFile, |
| uint32_t timeScale, |
| MP4Duration sampleDuration, |
| uint16_t width, |
| uint16_t height, |
| mp4v2_ismacrypParams *icPp, |
| uint8_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddColr( |
| MP4FileHandle hFile, MP4TrackId refTrackId, uint16_t pri, uint16_t tran, uint16_t mat) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddColr(refTrackId, pri, tran, mat); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| |
| MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile, |
| uint32_t timeScale, |
| MP4Duration sampleDuration, |
| uint16_t width, |
| uint16_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddEncH264VideoTrack( |
| MP4FileHandle hFile, |
| uint32_t timeScale, |
| MP4Duration sampleDuration, |
| uint16_t width, |
| uint16_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return; |
| } |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return; |
| } |
| |
| MP4TrackId MP4AddH263VideoTrack( |
| MP4FileHandle hFile, |
| uint32_t timeScale, |
| MP4Duration sampleDuration, |
| uint16_t width, |
| uint16_t height, |
| uint8_t h263Level, |
| uint8_t h263Profile, |
| uint32_t avgBitrate, |
| uint32_t maxBitrate) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)-> |
| AddH263VideoTrack(timeScale, sampleDuration, width, height, h263Level, h263Profile, avgBitrate, maxBitrate); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| void MP4SetH263Vendor( |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| uint32_t vendor) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)-> |
| SetH263Vendor(trackId, vendor); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| void MP4SetH263DecoderVersion( |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| uint8_t decoderVersion) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| |
| try { |
| ((MP4File*)hFile)-> |
| SetH263DecoderVersion(trackId, decoderVersion); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| void MP4SetH263Bitrates( |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| uint32_t avgBitrate, |
| uint32_t maxBitrate) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| |
| try { |
| ((MP4File*)hFile)-> |
| SetH263Bitrates(trackId, avgBitrate, maxBitrate); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| MP4TrackId MP4AddHintTrack( |
| MP4FileHandle hFile, MP4TrackId refTrackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddHintTrack(refTrackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddTextTrack( |
| MP4FileHandle hFile, MP4TrackId refTrackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddTextTrack(refTrackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddSubtitleTrack(MP4FileHandle hFile, |
| uint32_t timescale, |
| uint16_t width, |
| uint16_t height) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddSubtitleTrack(timescale, width, height); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddSubpicTrack(MP4FileHandle hFile, |
| uint32_t timescale, |
| uint16_t width, |
| uint16_t height) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddSubpicTrack(timescale, width, height); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddChapterTextTrack( |
| MP4FileHandle hFile, MP4TrackId refTrackId, uint32_t timescale) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddChapterTextTrack(refTrackId, timescale); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| MP4TrackId MP4AddPixelAspectRatio( |
| MP4FileHandle hFile, MP4TrackId refTrackId, uint32_t hSpacing, uint32_t vSpacing) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->AddPixelAspectRatio(refTrackId, hSpacing, vSpacing); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| void MP4AddChapter( |
| MP4FileHandle hFile, MP4TrackId chapterTrackId, MP4Duration chapterDuration, const char *chapterTitle) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->AddChapter(chapterTrackId, chapterDuration, chapterTitle); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| void MP4AddNeroChapter( |
| MP4FileHandle hFile, MP4Timestamp chapterStart, const char *chapterTitle) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->AddNeroChapter(chapterStart, chapterTitle); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| MP4ChapterType MP4ConvertChapters( |
| MP4FileHandle hFile, MP4ChapterType toChapterType) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) |
| { |
| try { |
| return ((MP4File*)hFile)->ConvertChapters(toChapterType); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4ChapterTypeNone; |
| } |
| |
| MP4ChapterType MP4DeleteChapters( |
| MP4FileHandle hFile, MP4ChapterType fromChapterType, MP4TrackId chapterTrackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->DeleteChapters(fromChapterType, chapterTrackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4ChapterTypeNone; |
| } |
| |
| MP4ChapterType MP4GetChapters( |
| MP4FileHandle hFile, MP4Chapter_t ** chapterList, uint32_t * chapterCount, MP4ChapterType fromChapterType) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetChapters(chapterList, chapterCount, fromChapterType); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4ChapterTypeNone; |
| } |
| |
| MP4ChapterType MP4SetChapters( |
| MP4FileHandle hFile, MP4Chapter_t * chapterList, uint32_t chapterCount, MP4ChapterType toChapterType) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->SetChapters(chapterList, chapterCount, toChapterType); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4ChapterTypeNone; |
| } |
| |
| void MP4ChangeMovieTimeScale( |
| MP4FileHandle hFile, uint32_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->ChangeMovieTimeScale(value); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| } |
| |
| 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 |
| uint8_t* pConfig = NULL; |
| uint32_t configSize = 0; |
| MP4LogLevel verb = mp4v2::impl::log.verbosity; |
| mp4v2::impl::log.setVerbosity(MP4_LOG_NONE); |
| bool haveEs = MP4GetTrackESConfiguration(srcFile, |
| srcTrackId, |
| &pConfig, |
| &configSize); |
| mp4v2::impl::log.setVerbosity(verb); |
| if (haveEs && |
| 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; |
| uint8_t payloadNumber; |
| uint16_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 |
| 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 |
| uint8_t* pConfig = NULL; |
| uint32_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; |
| uint8_t payloadNumber; |
| uint16_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; |
| } |
| |
| 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 |
| MP4TrackId MP4EncAndCopyTrack(MP4FileHandle srcFile, |
| MP4TrackId srcTrackId, |
| mp4v2_ismacrypParams *icPp, |
| encryptFunc_t encfcnp, |
| uint32_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; |
| } |
| |
| bool MP4DeleteTrack( |
| MP4FileHandle hFile, |
| MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->DeleteTrack(trackId); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| uint32_t MP4GetNumberOfTracks( |
| MP4FileHandle hFile, |
| const char* type, |
| uint8_t subType) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetNumberOfTracks(type, subType); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| MP4TrackId MP4FindTrackId( |
| MP4FileHandle hFile, |
| uint16_t index, |
| const char* type, |
| uint8_t subType) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->FindTrackId(index, type, subType); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_TRACK_ID; |
| } |
| |
| uint16_t MP4FindTrackIndex( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->FindTrackIndex(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return (uint16_t)-1; |
| } |
| |
| /* specific track properties */ |
| |
| const char* MP4GetTrackType( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackType(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return NULL; |
| } |
| const char* MP4GetTrackMediaDataName( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackMediaDataName(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return NULL; |
| } |
| |
| bool MP4GetTrackMediaDataOriginalFormat( |
| MP4FileHandle hFile, MP4TrackId trackId, char *originalFormat, |
| uint32_t buflen) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| |
| return ((MP4File*)hFile)->GetTrackMediaDataOriginalFormat(trackId, |
| originalFormat, buflen); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| MP4Duration MP4GetTrackDuration( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackDuration(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_DURATION; |
| } |
| |
| uint32_t MP4GetTrackTimeScale( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackTimeScale(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| bool MP4SetTrackTimeScale( |
| MP4FileHandle hFile, MP4TrackId trackId, uint32_t value) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetTrackTimeScale(trackId, value); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| uint8_t MP4GetTrackAudioMpeg4Type( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackAudioMpeg4Type(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_MPEG4_INVALID_AUDIO_TYPE; |
| } |
| |
| |
| |
| // Replacement to MP4GetTrackVideoType and MP4GetTrackAudioType |
| // Basically does the same thing but with a more self-explanatory name |
| uint8_t MP4GetTrackEsdsObjectTypeId( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| |
| return ((MP4File*)hFile)->GetTrackEsdsObjectTypeId(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_AUDIO_TYPE; |
| } |
| |
| MP4Duration MP4GetTrackFixedSampleDuration( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackFixedSampleDuration(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return MP4_INVALID_DURATION; |
| } |
| |
| uint32_t MP4GetTrackBitRate( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| MP4File *pFile = (MP4File *)hFile; |
| try { |
| uint32_t bitrate = pFile->GetTrackIntegerProperty(trackId, |
| "mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate"); |
| if( bitrate != 0 ) { |
| return bitrate; |
| } |
| } |
| catch( Exception* x ) { |
| //mp4v2::impl::log.errorf(*x); we don't really need to print this. |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| // 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); |
| uint64_t bytes = pTrack->GetTotalOfSampleSizes(); |
| bytes *= UINT64_C(8000); // 8 * 1000 |
| bytes /= msDuration; |
| return (uint32_t)bytes; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| bool MP4GetTrackESConfiguration( |
| MP4FileHandle hFile, MP4TrackId trackId, |
| uint8_t** ppConfig, uint32_t* pConfigSize) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->GetTrackESConfiguration( |
| trackId, ppConfig, pConfigSize); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| *ppConfig = NULL; |
| *pConfigSize = 0; |
| return false; |
| } |
| bool MP4GetTrackVideoMetadata( |
| MP4FileHandle hFile, MP4TrackId trackId, |
| uint8_t** ppConfig, uint32_t* pConfigSize) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->GetTrackVideoMetadata( |
| trackId, ppConfig, pConfigSize); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| *ppConfig = NULL; |
| *pConfigSize = 0; |
| return false; |
| } |
| |
| bool MP4SetTrackESConfiguration( |
| MP4FileHandle hFile, MP4TrackId trackId, |
| const uint8_t* pConfig, uint32_t configSize) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetTrackESConfiguration( |
| trackId, pConfig, configSize); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| void MP4FreeH264SeqPictHeaders(uint8_t** pSeqHeaders, |
| uint32_t* pSeqHeaderSize, |
| uint8_t** pPictHeader, |
| uint32_t* pPictHeaderSize ) |
| { |
| uint32_t ix; |
| |
| for (ix = 0; pSeqHeaderSize[ix] != 0; ++ix) { |
| free(pSeqHeaders[ix]); |
| } |
| free(pSeqHeaders); |
| free(pSeqHeaderSize); |
| |
| for (ix = 0; pPictHeaderSize[ix] != 0; ++ix) { |
| free(pPictHeader[ix]); |
| } |
| free(pPictHeader); |
| free(pPictHeaderSize); |
| } |
| |
| bool 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 true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| MP4SampleId MP4GetTrackNumberOfSamples( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackNumberOfSamples(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| uint16_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| uint16_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0; |
| } |
| |
| double MP4GetTrackVideoFrameRate( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackVideoFrameRate(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return 0.0; |
| } |
| |
| int MP4GetTrackAudioChannels (MP4FileHandle hFile, |
| MP4TrackId trackId) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| return ((MP4File*)hFile)->GetTrackAudioChannels(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return -1; |
| } |
| |
| // returns true if the track is a media track encrypted according to ismacryp |
| bool MP4IsIsmaCrypMediaTrack( |
| MP4FileHandle hFile, MP4TrackId trackId) |
| { |
| bool retval = false; |
| MP4LogLevel verb = mp4v2::impl::log.verbosity; |
| mp4v2::impl::log.setVerbosity(MP4_LOG_NONE); |
| |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| retval = ((MP4File*)hFile)->IsIsmaCrypMediaTrack(trackId); |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| mp4v2::impl::log.setVerbosity(verb); |
| return retval; |
| } |
| |
| |
| /* generic track properties */ |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| bool MP4GetTrackIntegerProperty ( |
| MP4FileHandle hFile, MP4TrackId trackId, |
| const char* propName, |
| uint64_t *retvalue) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| *retvalue = ((MP4File*)hFile)->GetTrackIntegerProperty(trackId, |
| propName); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| bool MP4GetTrackBytesProperty( |
| MP4FileHandle hFile, MP4TrackId trackId, const char* propName, |
| uint8_t** ppValue, uint32_t* pValueSize) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->GetTrackBytesProperty( |
| trackId, propName, ppValue, pValueSize); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| *ppValue = NULL; |
| *pValueSize = 0; |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| 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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| bool MP4SetTrackBytesProperty( |
| MP4FileHandle hFile, MP4TrackId trackId, |
| const char* propName, const uint8_t* pValue, uint32_t valueSize) |
| { |
| if (MP4_IS_VALID_FILE_HANDLE(hFile)) { |
| try { |
| ((MP4File*)hFile)->SetTrackBytesProperty( |
| trackId, propName, pValue, valueSize); |
| return true; |
| } |
| catch( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
| |
| /* sample operations */ |
| |
| bool MP4ReadSample( |
| /* input parameters */ |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| MP4SampleId sampleId, |
| /* output parameters */ |
| uint8_t** ppBytes, |
| uint32_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| *pNumBytes = 0; |
| return false; |
| } |
| |
| bool MP4ReadSampleFromTime( |
| /* input parameters */ |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| MP4Timestamp when, |
| /* output parameters */ |
| uint8_t** ppBytes, |
| uint32_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| *pNumBytes = 0; |
| return false; |
| } |
| |
| bool MP4WriteSample( |
| MP4FileHandle hFile, |
| MP4TrackId trackId, |
| const uint8_t* pBytes, |
| uint32_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( Exception* x ) { |
| mp4v2::impl::log.errorf(*x); |
| delete x; |
| } |
| catch( ... ) { |
| mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); |
| } |
| } |
| return false; |
| } |
|