/* * 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 dmackie@cisco.com */ #include "src/impl.h" namespace mp4v2 { namespace impl { /////////////////////////////////////////////////////////////////////////////// MP4RootAtom::MP4RootAtom(MP4File &file) : MP4Atom( file, NULL ) , m_rewrite_ftyp ( NULL ) , m_rewrite_ftypPosition ( 0 ) , m_rewrite_free ( NULL ) , m_rewrite_freePosition ( 0 ) { ExpectChildAtom( "moov", Required, OnlyOne ); ExpectChildAtom( "ftyp", Optional, OnlyOne ); ExpectChildAtom( "mdat", Optional, Many ); ExpectChildAtom( "free", Optional, Many ); ExpectChildAtom( "skip", Optional, Many ); ExpectChildAtom( "udta", Optional, Many ); ExpectChildAtom( "moof", Optional, Many ); } void MP4RootAtom::BeginWrite(bool use64) { m_rewrite_ftyp = (MP4FtypAtom*)FindChildAtom( "ftyp" ); if( m_rewrite_ftyp ) { m_rewrite_free = (MP4FreeAtom*)MP4Atom::CreateAtom( m_File, NULL, "free" ); m_rewrite_free->SetSize( 32*4 ); // room for 32 additional brands AddChildAtom( m_rewrite_free ); m_rewrite_ftypPosition = m_File.GetPosition(); m_rewrite_ftyp->Write(); m_rewrite_freePosition = m_File.GetPosition(); m_rewrite_free->Write(); } m_pChildAtoms[GetLastMdatIndex()]->BeginWrite( m_File.Use64Bits( "mdat" )); } void MP4RootAtom::Write() { // no-op } void MP4RootAtom::FinishWrite(bool use64) { if( m_rewrite_ftyp ) { const uint64_t savepos = m_File.GetPosition(); m_File.SetPosition( m_rewrite_ftypPosition ); m_rewrite_ftyp->Write(); const uint64_t newpos = m_File.GetPosition(); if( newpos > m_rewrite_freePosition ) m_rewrite_free->SetSize( m_rewrite_free->GetSize() - (newpos - m_rewrite_freePosition) ); // shrink else if( newpos < m_rewrite_freePosition ) m_rewrite_free->SetSize( m_rewrite_free->GetSize() + (m_rewrite_freePosition - newpos) ); // grow m_rewrite_free->Write(); m_File.SetPosition( savepos ); } // finish writing last mdat atom const uint32_t mdatIndex = GetLastMdatIndex(); m_pChildAtoms[mdatIndex]->FinishWrite( m_File.Use64Bits( "mdat" )); // write all atoms after last mdat const uint32_t size = m_pChildAtoms.Size(); for ( uint32_t i = mdatIndex + 1; i < size; i++ ) m_pChildAtoms[i]->Write(); } void MP4RootAtom::BeginOptimalWrite() { WriteAtomType("ftyp", OnlyOne); WriteAtomType("moov", OnlyOne); WriteAtomType("udta", Many); m_pChildAtoms[GetLastMdatIndex()]->BeginWrite(m_File.Use64Bits("mdat")); } void MP4RootAtom::FinishOptimalWrite() { // finish writing mdat m_pChildAtoms[GetLastMdatIndex()]->FinishWrite(m_File.Use64Bits("mdat")); // find moov atom uint32_t size = m_pChildAtoms.Size(); MP4Atom* pMoovAtom = NULL; uint32_t i; for (i = 0; i < size; i++) { if (!strcmp("moov", m_pChildAtoms[i]->GetType())) { pMoovAtom = m_pChildAtoms[i]; break; } } ASSERT(i < size); ASSERT(pMoovAtom != NULL); // rewrite moov so that updated chunkOffsets are written to disk m_File.SetPosition(pMoovAtom->GetStart()); uint64_t oldSize = pMoovAtom->GetSize(); pMoovAtom->Write(); // sanity check uint64_t newSize = pMoovAtom->GetSize(); ASSERT(oldSize == newSize); } uint32_t MP4RootAtom::GetLastMdatIndex() { for (int32_t i = m_pChildAtoms.Size() - 1; i >= 0; i--) { if (!strcmp("mdat", m_pChildAtoms[i]->GetType())) { return i; } } ASSERT(false); return (uint32_t)-1; } void MP4RootAtom::WriteAtomType(const char* type, bool onlyOne) { uint32_t size = m_pChildAtoms.Size(); for (uint32_t i = 0; i < size; i++) { if (!strcmp(type, m_pChildAtoms[i]->GetType())) { m_pChildAtoms[i]->Write(); if (onlyOne) { break; } } } } /////////////////////////////////////////////////////////////////////////////// }} // namespace mp4v2::impl