/*---------------------------------------------------------------------- | AP4_FragmentSampleTable::AP4_FragmentSampleTable +---------------------------------------------------------------------*/ AP4_FragmentSampleTable::AP4_FragmentSampleTable(AP4_ContainerAtom* traf, AP4_TrexAtom* trex, AP4_Cardinal internal_track_id, AP4_ByteStream* sample_stream, AP4_Position moof_offset, AP4_Position mdat_payload_offset, AP4_UI64 dts_origin) :m_InternalTrackId(internal_track_id) { AP4_TfhdAtom* tfhd = AP4_DYNAMIC_CAST(AP4_TfhdAtom, traf->GetChild(AP4_ATOM_TYPE_TFHD)); if (tfhd == NULL) return; // count all the samples and reserve space for them unsigned int sample_count = 0; for (AP4_List<AP4_Atom>::Item* item = traf->GetChildren().FirstItem(); item; item = item->GetNext()) { AP4_Atom* atom = item->GetData(); if (atom->GetType() == AP4_ATOM_TYPE_TRUN) { AP4_TrunAtom* trun = AP4_DYNAMIC_CAST(AP4_TrunAtom, atom); if (trun) sample_count += trun->GetEntries().ItemCount(); } } m_Samples.EnsureCapacity(sample_count); // check if we have a timecode base AP4_TfdtAtom* tfdt = AP4_DYNAMIC_CAST(AP4_TfdtAtom, traf->GetChild(AP4_ATOM_TYPE_TFDT)); if (tfdt) { dts_origin = tfdt->GetBaseMediaDecodeTime(); } // process all the trun atoms for (AP4_List<AP4_Atom>::Item* item = traf->GetChildren().FirstItem(); item; item = item->GetNext()) { AP4_Atom* atom = item->GetData(); if (atom->GetType() == AP4_ATOM_TYPE_TRUN) { AP4_TrunAtom* trun = AP4_DYNAMIC_CAST(AP4_TrunAtom, atom); if (trun) { AP4_Result result = AddTrun(trun, tfhd, trex, sample_stream, moof_offset, mdat_payload_offset, dts_origin); if (AP4_FAILED(result)) return; } } } }
/*---------------------------------------------------------------------- | AP4_Movie::ProcessMoof +---------------------------------------------------------------------*/ void AP4_Movie::ProcessMoof(AP4_ContainerAtom* moof, AP4_ByteStream& stream) { if (moof) { AP4_Offset offset = 0; stream.Tell(offset); AP4_Offset moof_offset = offset - moof->GetSize(); AP4_Offset mdat_payload_offset = offset + 8; AP4_MfhdAtom* mfhd = AP4_DYNAMIC_CAST(AP4_MfhdAtom, moof->GetChild(AP4_ATOM_TYPE_MFHD)); if (mfhd) { for (AP4_List<AP4_Atom>::Item* item = moof->GetChildren().FirstItem(); item; item = item->GetNext()) { AP4_Atom* atom = item->GetData(); if (atom->GetType() == AP4_ATOM_TYPE_TRAF) { AP4_ContainerAtom* traf = AP4_DYNAMIC_CAST(AP4_ContainerAtom, atom); if (traf) { AP4_TfhdAtom* tfhd = AP4_DYNAMIC_CAST(AP4_TfhdAtom, traf->GetChild(AP4_ATOM_TYPE_TFHD)); if (!tfhd) { continue; } AP4_Track* track = GetTrack(tfhd->GetTrackId()); if (!track) { continue; } AP4_TfdtAtom* tfdt = AP4_DYNAMIC_CAST(AP4_TfdtAtom, traf->GetChild(AP4_ATOM_TYPE_TFDT)); AP4_TrexAtom* trex = NULL; AP4_ContainerAtom* mvex = AP4_DYNAMIC_CAST(AP4_ContainerAtom, m_MoovAtom->GetChild(AP4_ATOM_TYPE_MVEX)); if (mvex) { for (AP4_List<AP4_Atom>::Item* child_item = mvex->GetChildren().FirstItem(); child_item; child_item = child_item->GetNext()) { AP4_Atom* child_atom = child_item->GetData(); if (child_atom->GetType() == AP4_ATOM_TYPE_TREX) { trex = AP4_DYNAMIC_CAST(AP4_TrexAtom, child_atom); if (trex && trex->GetTrackId() == tfhd->GetTrackId()) break; trex = NULL; } } } AP4_FragmentSampleTable* sampleTable = track->GetFragmentSampleTable(); AP4_Cardinal sample_count = 0; for (AP4_List<AP4_Atom>::Item* child_item = traf->GetChildren().FirstItem(); child_item; child_item = child_item->GetNext()) { AP4_Atom* child_atom = child_item->GetData(); if (child_atom->GetType() == AP4_ATOM_TYPE_TRUN) { AP4_TrunAtom* trun = AP4_DYNAMIC_CAST(AP4_TrunAtom, child_atom); if (trun) { sample_count += trun->GetEntries().ItemCount(); } } } if (!sample_count) { return; } if (sampleTable->GetSampleCount() == 0) { track->CreateFragmentFromStdSamples(); } if (AP4_FAILED(sampleTable->EnsureCapacity(sample_count + sampleTable->GetSampleCount()))) { return; } AP4_UI64 dts_origin = tfdt ? tfdt->GetBaseMediaDecodeTime() : 0; for (AP4_List<AP4_Atom>::Item* child_item = traf->GetChildren().FirstItem(); child_item; child_item = child_item->GetNext()) { AP4_Atom* child_atom = child_item->GetData(); if (child_atom->GetType() == AP4_ATOM_TYPE_TRUN) { AP4_TrunAtom* trun = AP4_DYNAMIC_CAST(AP4_TrunAtom, child_atom); if (trun) { sampleTable->AddTrun(trun, tfhd, trex, stream, dts_origin, moof_offset, mdat_payload_offset); } } } } } } } } }