diff --git a/CMakeLists.txt b/CMakeLists.txt index 94a6b7e..17fc8e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,6 +246,7 @@ set(MP4V2_SOURCE_FILES src/atom_root.cpp src/atom_rtp.cpp src/atom_s263.cpp + src/atom_vp09.cpp src/atom_sdp.cpp src/atom_sdtp.cpp src/atom_smi.cpp diff --git a/GNUmakefile.am b/GNUmakefile.am index 3aca98e..c842a9d 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -47,6 +47,7 @@ libmp4v2_la_SOURCES = \ src/atom_root.cpp \ src/atom_rtp.cpp \ src/atom_s263.cpp \ + src/atom_vp09.cpp \ src/atom_sdp.cpp \ src/atom_sdtp.cpp \ src/atom_smi.cpp \ diff --git a/include/mp4v2/track_prop.h b/include/mp4v2/track_prop.h index f15bf05..6f601aa 100644 --- a/include/mp4v2/track_prop.h +++ b/include/mp4v2/track_prop.h @@ -612,6 +612,50 @@ bool MP4HaveTrackAtom( MP4TrackId trackId, const char* atomName ); +/** Get the raw data of a track atom. + * + * MP4GetTrackAtomData reads the raw data of the track atom identified by + * @p atomName for the track identified by @p trackId. The atom name can + * specify a path relative to the track's trak atom, e.g. + * "mdia.minf.stbl.stsd.avc1.avcC". + * + * The caller is responsible for freeing the returned data with + * MP4FreeTrackAtomData(). + * + * @param hFile handle of file for operation. + * @param trackId id of track for operation. + * @param atomName path to the atom to read. + * @param ppAtomData pointer to a variable to receive the atom data. + * @param pAtomDataSize pointer to a variable to receive the size of the + * atom data. + * + * @return true (1) on success, false (0) otherwise. + */ +MP4V2_EXPORT +bool MP4GetTrackAtomData( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* atomName, + uint8_t** ppAtomData, + uint64_t* pAtomDataSize ); + +/** Free atom data allocated by MP4GetTrackAtomData. + * + * MP4FreeTrackAtomData frees the memory that was allocated by a call to + * the MP4GetTrackAtomData function. + * + * On the Windows platform this cannot be done directly by the client + * application because the C runtime of the client application and the C + * runtime of the mp4v2 DLL may be different, which will result in an + * error at runtime. This function allows the client application to let + * the mp4v2 DLL free the memory with the appropriate CRT heap manager. + * + * @param pAtomData pointer to atom data allocated with MP4GetTrackAtomData. + */ +MP4V2_EXPORT +void MP4FreeTrackAtomData( + uint8_t* pAtomData ); + /** Get the value of an integer property for a track. * * MP4GetTrackIntegerProperty determines the value of the integer property diff --git a/src/atom_stsd.cpp b/src/atom_stsd.cpp index c83ff39..c9ff592 100644 --- a/src/atom_stsd.cpp +++ b/src/atom_stsd.cpp @@ -58,6 +58,7 @@ MP4StsdAtom::MP4StsdAtom(MP4File &file) ExpectChildAtom("sawb", Optional, Many); // For AMR-WB ExpectChildAtom("s263", Optional, Many); // For H.263 ExpectChildAtom("avc1", Optional, Many); + ExpectChildAtom("vp09", Optional, Many); // For VP9 ExpectChildAtom("alac", Optional, Many); ExpectChildAtom("text", Optional, Many); ExpectChildAtom("tx3g", Optional, Many); diff --git a/src/atom_vp09.cpp b/src/atom_vp09.cpp new file mode 100644 index 0000000..e429964 --- /dev/null +++ b/src/atom_vp09.cpp @@ -0,0 +1,81 @@ +/* + * 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. 2004. All Rights Reserved. + * + * Contributor(s): + */ + +#include "src/impl.h" + +namespace mp4v2 { +namespace impl { + +/////////////////////////////////////////////////////////////////////////////// + +MP4Vp09Atom::MP4Vp09Atom(MP4File &file) + : MP4Atom(file, "vp09") +{ + AddReserved(*this, "reserved1", 6); + AddProperty(new MP4Integer16Property(*this, "dataReferenceIndex")); + AddReserved(*this, "reserved2", 16); // version, revision level, vendor, temporal quality, spatial quality + AddProperty(new MP4Integer16Property(*this, "width")); + AddProperty(new MP4Integer16Property(*this, "height")); + AddReserved(*this, "reserved3", 14); // horiz and vert resolution, datasize and framecount + + MP4StringProperty* pProp = new MP4StringProperty(*this, "compressorName"); + pProp->SetFixedLength(32); + pProp->SetCountedFormat(true); + pProp->SetValue("vp09 Coding"); + AddProperty(pProp); + + AddReserved(*this, "reserved4", 4); // depth and color table ID + + ExpectChildAtom("vpcC", Required, OnlyOne); + ExpectChildAtom("btrt", Optional, OnlyOne); + ExpectChildAtom("colr", Optional, OnlyOne); + ExpectChildAtom("pasp", Optional, OnlyOne); +} + +void MP4Vp09Atom::Generate() +{ + MP4Atom::Generate(); + + ((MP4Integer16Property*)m_pProperties[1])->SetValue(1); + + // property reserved3 has non-zero fixed values + static uint8_t reserved3[14] = { + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x48, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + }; + m_pProperties[5]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[5])->SetValue(reserved3, sizeof(reserved3)); + m_pProperties[5]->SetReadOnly(true); + + // property reserved4 has non-zero fixed values + static uint8_t reserved4[4] = { + 0x00, 0x18, 0xFF, 0xFF, + }; + m_pProperties[7]->SetReadOnly(false); + ((MP4BytesProperty*)m_pProperties[7])->SetValue(reserved4, sizeof(reserved4)); + m_pProperties[7]->SetReadOnly(true); +} + +/////////////////////////////////////////////////////////////////////////////// + +} +} // namespace mp4v2::impl diff --git a/src/atoms.h b/src/atoms.h index 382706f..600b6af 100644 --- a/src/atoms.h +++ b/src/atoms.h @@ -271,6 +271,16 @@ class MP4Mp4vAtom : public MP4Atom { MP4Mp4vAtom &operator= ( const MP4Mp4vAtom &src ); }; +class MP4Vp09Atom : public MP4Atom { +public: + MP4Vp09Atom(MP4File &file); + void Generate(); +private: + MP4Vp09Atom(); + MP4Vp09Atom( const MP4Vp09Atom &src ); + MP4Vp09Atom &operator= ( const MP4Vp09Atom &src ); +}; + class MP4S263Atom : public MP4Atom { public: diff --git a/src/mp4.cpp b/src/mp4.cpp index c56f3ee..793679c 100644 --- a/src/mp4.cpp +++ b/src/mp4.cpp @@ -2861,6 +2861,32 @@ MP4FileHandle MP4ModifyCallbacks(const MP4IOCallbacks* callbacks, return false; } + bool MP4GetTrackAtomData( + MP4FileHandle hFile, MP4TrackId trackId, + const char *atomName, + uint8_t **ppAtomData, uint64_t *pAtomDataSize) + { + if (MP4_IS_VALID_FILE_HANDLE(hFile)) { + try { + return ((MP4File*)hFile)->GetTrackAtomData( + trackId, atomName, ppAtomData, pAtomDataSize); + } + catch( Exception* x ) { + mp4v2::impl::log.errorf(*x); + delete x; + } + catch( ... ) { + mp4v2::impl::log.errorf( "%s: failed", __FUNCTION__ ); + } + } + return false; + } + + void MP4FreeTrackAtomData(uint8_t *pAtomData) + { + MP4Free(pAtomData); + } + bool MP4GetTrackIntegerProperty ( MP4FileHandle hFile, MP4TrackId trackId, const char* propName, diff --git a/src/mp4atom.cpp b/src/mp4atom.cpp index 999fa3e..90b2cd3 100644 --- a/src/mp4atom.cpp +++ b/src/mp4atom.cpp @@ -1012,6 +1012,8 @@ MP4Atom::factory( MP4File &file, MP4Atom* parent, const char* type ) case 'v': if( ATOMID(type) == ATOMID("vmhd") ) return new MP4VmhdAtom(file); + if( ATOMID(type) == ATOMID("vp09") ) + return new MP4Vp09Atom(file); break; case 'y': diff --git a/src/mp4file.cpp b/src/mp4file.cpp index 4e43903..fc37081 100644 --- a/src/mp4file.cpp +++ b/src/mp4file.cpp @@ -3209,6 +3209,29 @@ MP4Atom *MP4File::FindTrackAtom (MP4TrackId trackId, const char *name) return FindAtom(MakeTrackName(trackId, name)); } +bool MP4File::GetTrackAtomData(MP4TrackId trackId, const char *name, + uint8_t **ppAtomData, uint64_t *pAtomDataSize) +{ + MP4Atom *pAtom = FindTrackAtom(trackId, name); + if (pAtom == NULL) + return false; + + // Need to offset past the header (4 bytes for size and 4 bytes for atom type) + uint64_t headerSize = 8; + if (pAtom->GetLargesizeMode()) + headerSize = 16; + + SetPosition(pAtom->GetStart() + headerSize); + + uint64_t atomDataSize = pAtom->GetSize(); + uint8_t *pData = (uint8_t *)MP4Malloc(atomDataSize); + ReadBytes(pData, atomDataSize); + + *ppAtomData = pData; + *pAtomDataSize = atomDataSize; + return true; +} + uint64_t MP4File::GetTrackIntegerProperty(MP4TrackId trackId, const char* name) { return GetIntegerProperty(MakeTrackName(trackId, name)); diff --git a/src/mp4file.h b/src/mp4file.h index a1a2eb4..8933964 100644 --- a/src/mp4file.h +++ b/src/mp4file.h @@ -161,6 +161,8 @@ class MP4File /* track properties */ MP4Atom *FindTrackAtom(MP4TrackId trackId, const char *name); + bool GetTrackAtomData(MP4TrackId trackId, const char *name, + uint8_t **ppAtomData, uint64_t *pAtomDataSize); uint64_t GetTrackIntegerProperty( MP4TrackId trackId, const char* name); float GetTrackFloatProperty(