aboutsummaryrefslogtreecommitdiff
path: root/src/itmf/CoverArtBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/itmf/CoverArtBox.cpp')
-rw-r--r--src/itmf/CoverArtBox.cpp258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/itmf/CoverArtBox.cpp b/src/itmf/CoverArtBox.cpp
new file mode 100644
index 0000000..330d053
--- /dev/null
+++ b/src/itmf/CoverArtBox.cpp
@@ -0,0 +1,258 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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 MP4v2.
+//
+// The Initial Developer of the Original Code is Kona Blend.
+// Portions created by Kona Blend are Copyright (C) 2008.
+// All Rights Reserved.
+//
+// Contributors:
+// Kona Blend, kona8lend@@gmail.com
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "impl.h"
+
+namespace mp4v2 { namespace impl { namespace itmf {
+
+///////////////////////////////////////////////////////////////////////////////
+
+CoverArtBox::Item::Item()
+ : type ( BT_UNDEFINED )
+ , buffer ( NULL )
+ , size ( 0 )
+ , autofree ( false )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+CoverArtBox::Item::Item( const Item& rhs )
+ : type ( BT_UNDEFINED )
+ , buffer ( NULL )
+ , size ( 0 )
+ , autofree ( false )
+{
+ operator=( rhs );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+CoverArtBox::Item::~Item()
+{
+ reset();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+CoverArtBox::Item&
+CoverArtBox::Item::operator=( const Item& rhs )
+{
+ type = rhs.type;
+ size = rhs.size;
+ autofree = rhs.autofree;
+
+ if( rhs.autofree ) {
+ buffer = (uint8_t*)MP4Malloc(rhs.size);
+ memcpy( buffer, rhs.buffer, rhs.size );
+ }
+ else {
+ buffer = rhs.buffer;
+ }
+
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void
+CoverArtBox::Item::reset()
+{
+ if( autofree && buffer )
+ MP4Free( buffer );
+
+ type = BT_UNDEFINED;
+ buffer = NULL;
+ size = 0;
+ autofree = false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+CoverArtBox::add( MP4FileHandle hFile, const Item& item )
+{
+ MP4File& file = *((MP4File*)hFile);
+
+ const char* const covr_name = "moov.udta.meta.ilst.covr";
+ MP4Atom* covr = file.FindAtom( covr_name );
+ if( !covr ) {
+ file.AddDescendantAtoms( "moov", "udta.meta.ilst.covr" );
+
+ covr = file.FindAtom( covr_name );
+ if( !covr )
+ return true;
+ }
+
+ // use empty data atom if one exists
+ MP4Atom* data = NULL;
+ uint32_t index = 0;
+ const uint32_t atomc = covr->GetNumberOfChildAtoms();
+ for( uint32_t i = 0; i < atomc; i++ ) {
+ MP4Atom* atom = covr->GetChildAtom( i );
+
+ MP4BytesProperty* metadata = NULL;
+ if( !atom->FindProperty( "data.metadata", (MP4Property**)&metadata ))
+ continue;
+
+ if( metadata->GetCount() )
+ continue;
+
+ data = atom;
+ index = i;
+ break;
+ }
+
+ // no empty atom found, create one.
+ if( !data ) {
+ data = MP4Atom::CreateAtom( covr, "data" );
+ covr->AddChildAtom( data );
+ data->Generate();
+ index = covr->GetNumberOfChildAtoms() - 1;
+ }
+
+ return set( hFile, item, index );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+CoverArtBox::get( MP4FileHandle hFile, Item& item, uint32_t index )
+{
+ item.reset();
+ MP4File& file = *((MP4File*)hFile);
+
+ MP4Atom* covr = file.FindAtom( "moov.udta.meta.ilst.covr" );
+ if( !covr )
+ return true;
+
+ if( !(index < covr->GetNumberOfChildAtoms()) )
+ return true;
+
+ MP4DataAtom* data = static_cast<MP4DataAtom*>( covr->GetChildAtom( index ));
+ if( !data )
+ return true;
+
+ MP4BytesProperty* metadata = NULL;
+ if ( !data->FindProperty( "data.metadata", (MP4Property**)&metadata ))
+ return true;
+
+ metadata->GetValue( &item.buffer, &item.size );
+ item.autofree = true;
+ item.type = data->typeCode.GetValue();
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+CoverArtBox::list( MP4FileHandle hFile, ItemList& out )
+{
+ out.clear();
+ MP4File& file = *((MP4File*)hFile);
+ MP4ItmfItemList* itemList = genericGetItemsByCode( file, "covr" ); // alloc
+
+ out.resize( itemList->size );
+ for( uint32_t i = 0; i < itemList->size; i++ )
+ get( hFile, out[i], i );
+
+ genericItemListFree( itemList ); // free
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+CoverArtBox::remove( MP4FileHandle hFile, uint32_t index )
+{
+ MP4File& file = *((MP4File*)hFile);
+
+ MP4Atom* covr = file.FindAtom( "moov.udta.meta.ilst.covr" );
+ if( !covr )
+ return true;
+
+ // wildcard mode: delete covr and all images
+ if( index == numeric_limits<uint32_t>::max() ) {
+ covr->GetParentAtom()->DeleteChildAtom( covr );
+ delete covr;
+ return false;
+ }
+
+ if( !(index < covr->GetNumberOfChildAtoms()) )
+ return true;
+
+ MP4Atom* data = covr->GetChildAtom( index );
+ if( !data )
+ return true;
+
+ // delete single image
+ covr->DeleteChildAtom( data );
+ delete data;
+
+ // delete empty covr
+ if( covr->GetNumberOfChildAtoms() == 0 ) {
+ covr->GetParentAtom()->DeleteChildAtom( covr );
+ delete covr;
+ }
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool
+CoverArtBox::set( MP4FileHandle hFile, const Item& item, uint32_t index )
+{
+ MP4File& file = *((MP4File*)hFile);
+
+ MP4Atom* covr = file.FindAtom( "moov.udta.meta.ilst.covr" );
+ if( !covr )
+ return true;
+
+ if( !(index < covr->GetNumberOfChildAtoms()) )
+ return true;
+
+ MP4DataAtom* data = static_cast<MP4DataAtom*>( covr->GetChildAtom( index ));
+ if( !data )
+ return true;
+
+ MP4BytesProperty* metadata = NULL;
+ if ( !data->FindProperty( "data.metadata", (MP4Property**)&metadata ))
+ return true;
+
+ // autodetect type if BT_UNDEFINED
+ const BasicType final_type = (item.type == BT_UNDEFINED)
+ ? computeBasicType( item.buffer, item.size )
+ : item.type;
+
+ // set type; note: not really flags due to b0rked atom structure
+ data->typeCode.SetValue( final_type );
+ metadata->SetValue( item.buffer, item.size );
+
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+}}} // namespace mp4v2::impl::itmf