예제 #1
0
GF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *traf, u64 moof_offset, Bool is_first_merge)
{
    u32 i, j, chunk_size;
    u64 base_offset, data_offset;
    u32 def_duration, DescIndex, def_size, def_flags;
    u32 duration, size, flags, cts_offset, prev_trun_data_offset;
    u8 pad, sync;
    u16 degr;
    GF_TrackFragmentRunBox *trun;
    GF_TrunEntry *ent;

    void stbl_AppendTime(GF_SampleTableBox *stbl, u32 duration);
    void stbl_AppendSize(GF_SampleTableBox *stbl, u32 size);
    void stbl_AppendChunk(GF_SampleTableBox *stbl, u64 offset);
    void stbl_AppendSampleToChunk(GF_SampleTableBox *stbl, u32 DescIndex, u32 samplesInChunk);
    void stbl_AppendCTSOffset(GF_SampleTableBox *stbl, u32 CTSOffset);
    void stbl_AppendRAP(GF_SampleTableBox *stbl, u8 isRap);
    void stbl_AppendPadding(GF_SampleTableBox *stbl, u8 padding);
    void stbl_AppendDegradation(GF_SampleTableBox *stbl, u16 DegradationPriority);

    if (trak->Header->trackID != traf->tfhd->trackID) return GF_OK;

    //setup all our defaults
    DescIndex = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_DESC) ? traf->tfhd->sample_desc_index : traf->trex->def_sample_desc_index;
    def_duration = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_DUR) ? traf->tfhd->def_sample_duration : traf->trex->def_sample_duration;
    def_size = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_SIZE) ? traf->tfhd->def_sample_size : traf->trex->def_sample_size;
    def_flags = (traf->tfhd->flags & GF_ISOM_TRAF_SAMPLE_FLAGS) ? traf->tfhd->def_sample_flags : traf->trex->def_sample_flags;

    //locate base offset
    base_offset = (traf->tfhd->flags & GF_ISOM_TRAF_BASE_OFFSET) ? traf->tfhd->base_data_offset : moof_offset;

    chunk_size = 0;
    prev_trun_data_offset = 0;

    /*in playback mode*/
    if (traf->tfdt && is_first_merge) {
#ifndef GPAC_DISABLE_LOG
        if (trak->sample_count_at_seg_start && (trak->dts_at_seg_start != traf->tfdt->baseMediaDecodeTime)) {
            s32 drift = (s32) ((s64)trak->dts_at_seg_start - (s64) traf->tfdt->baseMediaDecodeTime);
            if (drift<0) drift = -drift;
            if (drift > 1) {
                GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Error: TFDT timing "LLD" different from track cumulated timing "LLD" - using tfdt\n", traf->tfdt->baseMediaDecodeTime, trak->dts_at_seg_start ));
            }
        }
#endif
        trak->dts_at_seg_start = traf->tfdt->baseMediaDecodeTime;
    }

    i=0;
    while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {
        //merge the run
        for (j=0; j<trun->sample_count; j++) {
            ent = (GF_TrunEntry*)gf_list_get(trun->entries, j);
            size = def_size;
            duration = def_duration;
            flags = def_flags;

            if (ent) {
                if (trun->flags & GF_ISOM_TRUN_DURATION) duration = ent->Duration;
                if (trun->flags & GF_ISOM_TRUN_SIZE) size = ent->size;
                if (trun->flags & GF_ISOM_TRUN_FLAGS) {
                    flags = ent->flags;
                } else if (!j && (trun->flags & GF_ISOM_TRUN_FIRST_FLAG)) {
                    flags = trun->first_sample_flags;
                }
            }
            //add size first
            stbl_AppendSize(trak->Media->information->sampleTable, size);
            //then TS
            stbl_AppendTime(trak->Media->information->sampleTable, duration);
            //add chunk on first sample
            if (!j) {
                data_offset = base_offset;
                //aggregated offset if base-data-offset-present is not set AND if default-base-is-moof is not set
                if (!(traf->tfhd->flags & GF_ISOM_TRAF_BASE_OFFSET) && !(traf->tfhd->flags & GF_ISOM_MOOF_BASE_OFFSET) )
                    data_offset += chunk_size;

                if (trun->flags & GF_ISOM_TRUN_DATA_OFFSET) {
                    data_offset += trun->data_offset;
                    /*reset chunk size since data is now relative to this trun*/
                    chunk_size = 0;
                    /*remember this data offset for following trun*/
                    prev_trun_data_offset = trun->data_offset;
                } else {
                    /*data offset is previous chunk size plus previous offset of the trun*/
                    data_offset += prev_trun_data_offset;
                }
                stbl_AppendChunk(trak->Media->information->sampleTable, data_offset);
                //then sampleToChunk
                stbl_AppendSampleToChunk(trak->Media->information->sampleTable,
                                         DescIndex, trun->sample_count);
            }
            chunk_size += size;


            //CTS
            cts_offset = (trun->flags & GF_ISOM_TRUN_CTS_OFFSET) ? ent->CTS_Offset : 0;
            stbl_AppendCTSOffset(trak->Media->information->sampleTable, cts_offset);

            //flags
            sync = GF_ISOM_GET_FRAG_SYNC(flags);
            stbl_AppendRAP(trak->Media->information->sampleTable, sync);
            pad = GF_ISOM_GET_FRAG_PAD(flags);
            if (pad) stbl_AppendPadding(trak->Media->information->sampleTable, pad);
            degr = GF_ISOM_GET_FRAG_DEG(flags);
            if (degr) stbl_AppendDegradation(trak->Media->information->sampleTable, degr);
        }
    }
    /*merge sample groups*/
    if (traf->sampleGroups) {
        GF_List *groups;
        GF_List *groupDescs;
        if (!trak->Media->information->sampleTable->sampleGroups)
            trak->Media->information->sampleTable->sampleGroups = gf_list_new();

        if (!trak->Media->information->sampleTable->sampleGroupsDescription)
            trak->Media->information->sampleTable->sampleGroupsDescription = gf_list_new();

        groupDescs = trak->Media->information->sampleTable->sampleGroupsDescription;
        for (i=0; i<gf_list_count(traf->sampleGroupsDescription); i++) {
            GF_SampleGroupDescriptionBox *new_sgdesc = NULL;
            GF_SampleGroupDescriptionBox *sgdesc = gf_list_get(traf->sampleGroupsDescription, i);
            for (j=0; j<gf_list_count(groupDescs); j++) {
                new_sgdesc = gf_list_get(groupDescs, j);
                if (new_sgdesc->grouping_type==sgdesc->grouping_type) break;
                new_sgdesc = NULL;
            }
            /*new description, move it to our sample table*/
            if (!new_sgdesc) {
                gf_list_add(groupDescs, sgdesc);
                gf_list_rem(traf->sampleGroupsDescription, i);
                i--;
            }
            /*merge descriptions*/
            else {
                u32 idx = gf_list_count(new_sgdesc->group_descriptions);
                for (j=idx; j<gf_list_count(sgdesc->group_descriptions); j++) {
                    void *ptr = gf_list_get(sgdesc->group_descriptions, j);
                    if (ptr) {
                        gf_list_add(new_sgdesc->group_descriptions, ptr);
                        gf_list_rem(sgdesc->group_descriptions, j);
                        j--;
                    }
                }
            }
        }

        groups = trak->Media->information->sampleTable->sampleGroups;
        for (i=0; i<gf_list_count(traf->sampleGroups); i++) {
            GF_SampleGroupBox *stbl_group = NULL;
            GF_SampleGroupBox *frag_group = gf_list_get(traf->sampleGroups, i);


            for (j=0; j<gf_list_count(groups); j++) {
                stbl_group = gf_list_get(groups, j);
                if ((frag_group->grouping_type==stbl_group->grouping_type) && (frag_group->grouping_type_parameter==stbl_group->grouping_type_parameter))
                    break;
                stbl_group = NULL;
            }
            if (!stbl_group) {
                stbl_group = (GF_SampleGroupBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SBGP);
                stbl_group->grouping_type = frag_group->grouping_type;
                stbl_group->grouping_type_parameter = frag_group->grouping_type_parameter;
                stbl_group->version = frag_group->version;
                gf_list_add(groups, stbl_group);
            }
            if (frag_group->entry_count && stbl_group->entry_count &&
                    (frag_group->sample_entries[0].group_description_index==stbl_group->sample_entries[stbl_group->entry_count-1].group_description_index)
               ) {
                stbl_group->sample_entries[stbl_group->entry_count - 1].sample_count += frag_group->sample_entries[0].sample_count;
                if (frag_group->entry_count>1) {
                    stbl_group->sample_entries = gf_realloc(stbl_group->sample_entries, sizeof(GF_SampleGroupEntry) * (stbl_group->entry_count + frag_group->entry_count - 1));
                    memcpy(&stbl_group->sample_entries[stbl_group->entry_count], &frag_group->sample_entries[1], sizeof(GF_SampleGroupEntry) * (frag_group->entry_count - 1));
                    stbl_group->entry_count += frag_group->entry_count - 1;
                }
            } else {
                stbl_group->sample_entries = gf_realloc(stbl_group->sample_entries, sizeof(GF_SampleGroupEntry) * (stbl_group->entry_count + frag_group->entry_count));
                memcpy(&stbl_group->sample_entries[stbl_group->entry_count], &frag_group->sample_entries[0], sizeof(GF_SampleGroupEntry) * frag_group->entry_count);
                stbl_group->entry_count += frag_group->entry_count;
            }
        }
    }
    return GF_OK;
}
예제 #2
0
M4Err MergeTrack(TrackAtom *trak, TrackFragmentAtom *traf, u64 *moof_offset)
{
	u32 i, j, chunk_size;
	u64 base_offset, data_offset;
	u32 def_duration, DescIndex, def_size, def_flags;
	u32 duration, size, flags, cts_offset;
	u8 pad, sync;
	u16 degr;
	TrackFragmentRunAtom *trun;
	TrunEntry *ent;

	void stbl_AppendTime(SampleTableAtom *stbl, u32 duration);
	void stbl_AppendSize(SampleTableAtom *stbl, u32 size);
	void stbl_AppendChunk(SampleTableAtom *stbl, u64 offset);
	void stbl_AppendSampleToChunk(SampleTableAtom *stbl, u32 DescIndex, u32 samplesInChunk);
	void stbl_AppendCTSOffset(SampleTableAtom *stbl, u32 CTSOffset);
	void stbl_AppendRAP(SampleTableAtom *stbl, u8 isRap);
	void stbl_AppendPadding(SampleTableAtom *stbl, u8 padding);
	void stbl_AppendDegradation(SampleTableAtom *stbl, u16 DegradationPriority);


	//setup all our defaults
	DescIndex = (traf->tfhd->flags & TF_SAMPLE_DESC) ? traf->tfhd->sample_desc_index : traf->trex->def_sample_desc_index;
	def_duration = (traf->tfhd->flags & TF_SAMPLE_DUR) ? traf->tfhd->def_sample_duration : traf->trex->def_sample_duration;
	def_size = (traf->tfhd->flags & TF_SAMPLE_SIZE) ? traf->tfhd->def_sample_size : traf->trex->def_sample_size;
	def_flags = (traf->tfhd->flags & TF_SAMPLE_FLAGS) ? traf->tfhd->def_sample_flags : traf->trex->def_sample_flags;

	//locate base offset
	base_offset = (traf->tfhd->flags & TF_BASE_OFFSET) ? traf->tfhd->base_data_offset : *moof_offset;

	chunk_size = 0;

	for (i=0; i<ChainGetCount(traf->TrackRuns); i++) {
		trun = ChainGetEntry(traf->TrackRuns, i);
		//merge the run
		for (j=0;j<trun->sample_count; j++) {
			ent = ChainGetEntry(trun->entries, j);
			size = def_size;
			duration = def_duration;
			flags = def_flags;
			
			if (ent) {
				if (trun->flags & TR_DURATION) duration = ent->Duration;
				if (trun->flags & TR_SIZE) size = ent->size;
				if (trun->flags & TR_FLAGS) {
					flags = ent->flags;
				} else if (!j && (trun->flags & TR_FIRST_FLAG)) {
					flags = trun->first_sample_flags;
				}
			}
			//add size first
			stbl_AppendSize(trak->Media->information->sampleTable, size);
			//then TS
			stbl_AppendTime(trak->Media->information->sampleTable, duration);
			//add chunk on first sample
			if (!j) {
				data_offset = base_offset;
				//aggregated offset
				if (!(traf->tfhd->flags & TF_BASE_OFFSET)) data_offset += chunk_size;

				if (trun->flags & TR_DATA_OFFSET) data_offset += trun->data_offset;

				stbl_AppendChunk(trak->Media->information->sampleTable, data_offset);
				//then sampleToChunk
				stbl_AppendSampleToChunk(trak->Media->information->sampleTable, 
					DescIndex, trun->sample_count);
			}
			chunk_size += size;
			

			//CTS
			cts_offset = (trun->flags & TR_CTS_OFFSET) ? ent->CTS_Offset : 0;
			if (cts_offset) stbl_AppendCTSOffset(trak->Media->information->sampleTable, cts_offset);
			
			//flags
			sync = GET_FRAG_SYNC(flags);
			stbl_AppendRAP(trak->Media->information->sampleTable, sync);
			pad = GET_FRAG_PAD(flags);
			if (pad) stbl_AppendPadding(trak->Media->information->sampleTable, pad);
			degr = GET_FRAG_DEG(flags);
			if (degr) stbl_AppendDegradation(trak->Media->information->sampleTable, degr);
		}
	}
	//end of the fragment, update offset
	*moof_offset += chunk_size;
	return M4OK;
}