/*----------------------------------------------------------------------
|   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;
            }
        }
    }
}
Esempio n. 2
0
/*----------------------------------------------------------------------
|   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);
								}
							}
						}
					}
				}
			}
		}
	}
}