MP4ItmfItemList* genericGetItemsByCode( MP4File& file, const string& code ) { MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" ); if( !ilst ) return __itemListAlloc(); // pass 1: filter by code and populate indexList const uint32_t childCount = ilst->GetNumberOfChildAtoms(); vector<uint32_t> indexList; for( uint32_t i = 0; i < childCount; i++ ) { if( ATOMID( ilst->GetChildAtom( i )->GetType() ) != ATOMID( code.c_str() )) continue; indexList.push_back( i ); } if( indexList.size() < 1 ) return __itemListAlloc(); MP4ItmfItemList& list = *__itemListAlloc(); __itemListResize( list, (uint32_t)indexList.size() ); // pass 2: process each atom const vector<uint32_t>::size_type max = indexList.size(); for( vector<uint32_t>::size_type i = 0; i < max; i++ ) { uint32_t& aidx = indexList[i]; __itemAtomToModel( *(MP4ItemAtom*)ilst->GetChildAtom( aidx ), list.elements[i] ); } return &list; }
MP4ItmfItemList* genericGetItemsByMeaning( MP4File& file, const string& meaning, const string& name ) { MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" ); if( !ilst ) return __itemListAlloc(); // pass 1: filter by code and populate indexList const uint32_t childCount = ilst->GetNumberOfChildAtoms(); vector<uint32_t> indexList; for( uint32_t i = 0; i < childCount; i++ ) { MP4Atom& atom = *ilst->GetChildAtom( i ); if( ATOMID( atom.GetType() ) != ATOMID( "----" )) continue; // filter-out meaning mismatch MP4MeanAtom* meanAtom = (MP4MeanAtom*)atom.FindAtom( "----.mean" ); if( !meanAtom ) continue; if( meanAtom->value.CompareToString( meaning )) continue; if( !name.empty() ) { // filter-out name mismatch MP4MeanAtom* nameAtom = (MP4MeanAtom*)atom.FindAtom( "----.name" ); if( !nameAtom ) continue; if( nameAtom->value.CompareToString( name )) continue; } indexList.push_back( i ); } if( indexList.size() < 1 ) return __itemListAlloc(); MP4ItmfItemList& list = *__itemListAlloc(); __itemListResize( list, (uint32_t)indexList.size() ); // pass 2: process each atom const vector<uint32_t>::size_type max = indexList.size(); for( vector<uint32_t>::size_type i = 0; i < max; i++ ) { uint32_t& aidx = indexList[i]; __itemAtomToModel( *(MP4ItemAtom*)ilst->GetChildAtom( aidx ), list.elements[i] ); } return &list; }
bool genericSetItem( MP4File& file, const MP4ItmfItem* item ) { if( !item || !item->__handle ) return false; MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" ); if( !ilst ) return false; MP4ItemAtom* const old = static_cast<MP4ItemAtom*>(item->__handle); const uint32_t childCount = ilst->GetNumberOfChildAtoms(); uint32_t fidx = numeric_limits<uint32_t>::max(); for( uint32_t i = 0; i < childCount; i++ ) { MP4Atom* atom = ilst->GetChildAtom( i ); if( atom == old ) { fidx = i; break; } } if( fidx == numeric_limits<uint32_t>::max() ) return false; ilst->DeleteChildAtom( old ); delete old; MP4ItemAtom& itemAtom = *(MP4ItemAtom*)MP4Atom::CreateAtom( file, ilst, item->code ); ilst->InsertChildAtom( &itemAtom, fidx ); return __itemModelToAtom( *item, itemAtom ); }
MP4ItmfItemList* genericGetItems( MP4File& file ) { MP4Atom* ilst = file.FindAtom( "moov.udta.meta.ilst" ); if( !ilst ) return __itemListAlloc(); const uint32_t itemCount = ilst->GetNumberOfChildAtoms(); if( itemCount < 1 ) return __itemListAlloc(); MP4ItmfItemList& list = *__itemListAlloc(); __itemListResize( list, itemCount ); for( uint32_t i = 0; i < list.size; i++ ) __itemAtomToModel( *(MP4ItemAtom*)ilst->GetChildAtom( i ), list.elements[i] ); return &list; }
void searchFor64bit( MP4Atom& atom, FileSummaryInfo& info ) { const uint32_t max = atom.GetNumberOfChildAtoms(); for( uint32_t i = 0; i < max; i++ ) { MP4Atom& child = *atom.GetChildAtom( i ); if( child.GetLargesizeMode() ) info.nlargesize++; MP4Integer8Property* version; if( child.FindProperty( "version", (MP4Property**)&version ) && version->GetValue() == 1 ) info.nversion1++; if( !strcmp( child.GetType(), "co64" )) info.nspecial++; searchFor64bit( child, info ); } }
FILE* MP4Track::GetSampleFile(MP4SampleId sampleId) { u_int32_t stscIndex = GetSampleStscIndex(sampleId); u_int32_t stsdIndex = m_pStscSampleDescrIndexProperty->GetValue(stscIndex); // check if the answer will be the same as last time if (m_lastStsdIndex && stsdIndex == m_lastStsdIndex) { return m_lastSampleFile; } MP4Atom* pStsdAtom = m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd"); ASSERT(pStsdAtom); MP4Atom* pStsdEntryAtom = pStsdAtom->GetChildAtom(stsdIndex - 1); ASSERT(pStsdEntryAtom); MP4Integer16Property* pDrefIndexProperty = NULL; pStsdEntryAtom->FindProperty( "*.dataReferenceIndex", (MP4Property**)&pDrefIndexProperty); if (pDrefIndexProperty == NULL) { throw new MP4Error("invalid stsd entry", "GetSampleFile"); } u_int32_t drefIndex = pDrefIndexProperty->GetValue(); MP4Atom* pDrefAtom = m_pTrakAtom->FindAtom("trak.mdia.minf.dinf.dref"); ASSERT(pDrefAtom); MP4Atom* pUrlAtom = pDrefAtom->GetChildAtom(drefIndex - 1); ASSERT(pUrlAtom); FILE* pFile; if (pUrlAtom->GetFlags() & 1) { pFile = NULL; // self-contained } else { #ifndef USE_FILE_CALLBACKS MP4StringProperty* pLocationProperty = NULL; pUrlAtom->FindProperty( "*.location", (MP4Property**)&pLocationProperty); ASSERT(pLocationProperty); const char* url = pLocationProperty->GetValue(); VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(), printf("dref url = %s\n", url)); pFile = (FILE*)-1; // attempt to open url if it's a file url // currently this is the only thing we understand if (!strncmp(url, "file:", 5)) { const char* fileName = url + 5; if (!strncmp(fileName, "//", 2)) { fileName = strchr(fileName + 2, '/'); } if (fileName) { pFile = fopen(fileName, "rb"); if (!pFile) { pFile = (FILE*)-1; } } } #else throw new MP4Error(errno, "Function not supported when using callbacks", "GetSampleFile"); #endif } if (m_lastSampleFile) { #ifndef USE_FILE_CALLBACKS fclose(m_lastSampleFile); #else throw new MP4Error(errno, "Function not supported when using callbacks", "GetSampleFile"); #endif } // cache the answer m_lastStsdIndex = stsdIndex; m_lastSampleFile = pFile; return pFile; }