⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 movie_fragments.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / ISO Media File Format sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/internal/isomedia_dev.h>#ifndef	GF_ISOM_NO_FRAGMENTSGF_TrackExtendsBox *GetTrex(GF_MovieBox *moov, u32 TrackID){	u32 i;	GF_TrackExtendsBox *trex;	i=0;	while ((trex = (GF_TrackExtendsBox *)gf_list_enum(moov->mvex->TrackExList, &i))) {		if (trex->trackID == TrackID) return trex;	}	return NULL;}#ifndef GPAC_READ_ONLYGF_TrackFragmentBox *GetTraf(GF_ISOFile *mov, u32 TrackID){	u32 i;	GF_TrackFragmentBox *traf;	if (!mov->moof) return NULL;	//reverse browse the TRAFs, as there may be more than one per track ...	for (i=gf_list_count(mov->moof->TrackList); i>0; i--) {		traf = (GF_TrackFragmentBox *)gf_list_get(mov->moof->TrackList, i-1);		if (traf->tfhd->trackID == TrackID) return traf;	}	return NULL;}GF_Err gf_isom_finalize_for_fragment(GF_ISOFile *movie){	GF_Err e;	u32 i;	GF_TrackExtendsBox *trex;	if (!movie || !movie->moov) return GF_BAD_PARAM;	//this is only allowed in write mode	if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_ISOM_INVALID_MODE;	if (movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) return GF_OK;	movie->FragmentsFlags = 0;	//update durations	gf_isom_get_duration(movie);	//write movie	e = WriteToFile(movie);	if (e) return e;	//make sure we do have all we need. If not this is not an error, just consider 	//the file closed	if (!movie->moov->mvex || !gf_list_count(movie->moov->mvex->TrackExList)) return GF_OK;	i=0;	while ((trex = (GF_TrackExtendsBox *)gf_list_enum(movie->moov->mvex->TrackExList, &i))) {		if (!trex->trackID || !gf_isom_get_track_from_id(movie->moov, trex->trackID)) return GF_IO_ERR;		//we could also check all our data refs are local but we'll do that at run time		//in order to allow a mix of both (remote refs in MOOV and local in MVEX)		//one thing that MUST be done is OD cross-dependancies. The movie fragment spec 		//is broken here, since it cannot allow dynamic insertion of new ESD and their		//dependancies	}	//ok we are fine - note the data map is created at the begining	if (i) movie->FragmentsFlags |= GF_ISOM_FRAG_WRITE_READY;	movie->NextMoofNumber = 1;	return GF_OK;}GF_Err gf_isom_setup_track_fragment(GF_ISOFile *movie, u32 TrackID, 							 u32 DefaultSampleDescriptionIndex,							 u32 DefaultSampleDuration,							 u32 DefaultSampleSize,							 u8 DefaultSampleIsSync,							 u8 DefaultSamplePadding,							 u16 DefaultDegradationPriority){	GF_MovieExtendsBox *mvex;	GF_TrackExtendsBox *trex;	GF_TrackBox *trak;	if (!movie || !movie->moov) return GF_BAD_PARAM;	//this is only allowed in write mode	if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_ISOM_INVALID_MODE;	//and only at setup	if (movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) return GF_BAD_PARAM;	trak = gf_isom_get_track_from_id(movie->moov, TrackID);	if (!trak) return GF_BAD_PARAM;	//create MVEX if needed	if (!movie->moov->mvex) {		mvex = (GF_MovieExtendsBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MVEX);		moov_AddBox((GF_Box*)movie->moov, (GF_Box *) mvex);	} else {		mvex = movie->moov->mvex;	}	trex = GetTrex(movie->moov, TrackID);	if (!trex) {		trex = (GF_TrackExtendsBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREX);		trex->trackID = TrackID;		mvex_AddBox((GF_Box*)mvex, (GF_Box *) trex);	}	trex->track = trak;	trex->def_sample_desc_index = DefaultSampleDescriptionIndex;	trex->def_sample_duration = DefaultSampleDuration;	trex->def_sample_size = DefaultSampleSize;	trex->def_sample_flags = GF_ISOM_FORMAT_FRAG_FLAGS(DefaultSamplePadding, DefaultSampleIsSync, DefaultDegradationPriority);	return GF_OK;}u32 GetNumUsedValues(GF_TrackFragmentBox *traf, u32 value, u32 index){	u32 i, j, NumValue = 0;	GF_TrackFragmentRunBox *trun;	GF_TrunEntry *ent;	i=0;	while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {		j=0;		while ((ent = (GF_TrunEntry *)gf_list_enum(trun->entries, &j))) {			switch (index) {			case 1:				if (value == ent->Duration) NumValue ++;				break;			case 2:				if (value == ent->size) NumValue ++;				break;			case 3:				if (value == ent->flags) NumValue ++;				break;			}		}	}	return NumValue;}void ComputeFragmentDefaults(GF_TrackFragmentBox *traf){	u32 i, j, MaxNum, DefValue, ret;	GF_TrackFragmentRunBox *trun;	GF_TrunEntry *ent;	//Duration default	MaxNum = DefValue = 0;	i=0;	while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {		j=0;		while ((ent = (GF_TrunEntry *)gf_list_enum(trun->entries, &j))) {			ret = GetNumUsedValues(traf, ent->Duration, 1);			if (ret>MaxNum) {				//at least 2 duration, specify for all				if (MaxNum) {					DefValue = 0;					goto escape_duration;				}				MaxNum = ret;				DefValue = ent->Duration;			}		}	}escape_duration:	//store if #	if (DefValue && (DefValue != traf->trex->def_sample_duration)) {		traf->tfhd->def_sample_duration = DefValue;	}	//Size default	MaxNum = DefValue = 0;	i=0;	while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {		j=0;		while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) {			ret = GetNumUsedValues(traf, ent->size, 2);			if (ret>MaxNum || (ret==1)) {				//at least 2 sizes so we must specify all sizes				if (MaxNum) {					DefValue = 0;					goto escape_size;				}				MaxNum = ret;				DefValue = ent->size;			}		}	}escape_size:	//store if #	if (DefValue && (DefValue != traf->trex->def_sample_size)) {		traf->tfhd->def_sample_size = DefValue;	}	//Flags default	MaxNum = DefValue = 0;	i=0;	while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {		j=0;		while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &j))) {			ret = GetNumUsedValues(traf, ent->flags, 3);			if (ret>MaxNum) {				MaxNum = ret;				DefValue = ent->flags;			}		}	}	//store if #	if (DefValue && (DefValue != traf->trex->def_sample_flags)) {		traf->tfhd->def_sample_flags = DefValue;	}}GF_Err gf_isom_set_fragment_option(GF_ISOFile *movie, u32 TrackID, u32 Code, u32 Param){	GF_TrackFragmentBox *traf;	if (!movie || !movie->moov) return GF_BAD_PARAM;	//this is only allowed in write mode	if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_ISOM_INVALID_MODE;	traf = GetTraf(movie, TrackID);	if (!traf) return GF_BAD_PARAM;	switch (Code) {	case GF_ISOM_TRAF_EMPTY:		traf->tfhd->EmptyDuration = Param;		break;	case GF_ISOM_TRAF_RANDOM_ACCESS:		traf->tfhd->IFrameSwitching = Param;		break;	case GF_ISOM_TRAF_DATA_CACHE:		//don't cache only one sample ...		traf->DataCache = Param > 1 ? Param : 0;		break;	}	return GF_OK;}u32 UpdateRuns(GF_TrackFragmentBox *traf){	u32 sampleCount, i, j, RunSize, UseDefaultSize, RunDur, UseDefaultDur, RunFlags, NeedFlags, UseDefaultFlag, UseCTS, count;	GF_TrackFragmentRunBox *trun;	GF_TrunEntry *ent, *first_ent;		sampleCount = 0;	//traf data offset - we ALWAYS use data offset indication when writting otherwise	//we would need to have one TRUN max in a TRAF for offset reconstruction or store	//all TRUN in memory before writting :( Anyway it is much safer to indicate the	//base offset of each traf rather than using offset aggregation rules specified 	//in the std	traf->tfhd->flags = GF_ISOM_TRAF_BASE_OFFSET;	//empty runs	if (traf->tfhd->EmptyDuration) {		while (gf_list_count(traf->TrackRuns)) {			trun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, 0);			gf_list_rem(traf->TrackRuns, 0);			gf_isom_box_del((GF_Box *)trun);		}		traf->tfhd->flags = GF_ISOM_TRAF_DUR_EMPTY;		if (traf->tfhd->EmptyDuration != traf->trex->def_sample_duration) {			traf->tfhd->def_sample_duration = traf->tfhd->EmptyDuration;			traf->tfhd->flags |= GF_ISOM_TRAF_SAMPLE_DUR;		}		return 0;	}	UseDefaultSize = 0;	UseDefaultDur = 0;	UseDefaultFlag = 0;	i=0;	while ((trun = (GF_TrackFragmentRunBox *)gf_list_enum(traf->TrackRuns, &i))) {		RunSize = 0;		RunDur = 0;		RunFlags = 0;		UseCTS = 0;		NeedFlags = 0;		first_ent = NULL;		//process all samples in run		count = gf_list_count(trun->entries);		for (j=0; j<count; j++) {			ent = (GF_TrunEntry*)gf_list_get(trun->entries, j);			if (!j) {				first_ent = ent;				RunSize = ent->size;				RunDur = ent->Duration;			} 			//we may have one entry only ...			if (j || (count==1)) {				//flags are only after first entry				if (j==1 || (count==1) ) RunFlags = ent->flags;				if (ent->size != RunSize) RunSize = 0;				if (ent->Duration != RunDur) RunDur = 0;				if (j && (RunFlags != ent->flags)) NeedFlags = 1;			}			if (ent->CTS_Offset) UseCTS = 1;		}		//empty list		if (!first_ent) {			i--;			gf_list_rem(traf->TrackRuns, i);			continue;		}		trun->sample_count = gf_list_count(trun->entries);		trun->flags = 0;		//size checking		//constant size, check if this is from current fragment default or global default		if (RunSize && (traf->trex->def_sample_size == RunSize)) {			if (!UseDefaultSize) UseDefaultSize = 2;			else if (UseDefaultSize==1) RunSize = 0;		} else if (RunSize && (traf->tfhd->def_sample_size == RunSize)) {			if (!UseDefaultSize) UseDefaultSize = 1;			else if (UseDefaultSize==2) RunSize = 0;		}		//we could check for single entry runs and set the default size in the tfhd but 		//that's no bit saving...		else {			RunSize=0;		}		if (!RunSize) trun->flags |= GF_ISOM_TRUN_SIZE;				//duration checking		if (RunDur && (traf->trex->def_sample_duration == RunDur)) {			if (!UseDefaultDur) UseDefaultDur = 2;			else if (UseDefaultDur==1) RunDur = 0;		} else if (RunDur && (traf->tfhd->def_sample_duration == RunDur)) {			if (!UseDefaultDur) UseDefaultDur = 1;			else if (UseDefaultDur==2) RunDur = 0;		}		if (!RunDur) trun->flags |= GF_ISOM_TRUN_DURATION;		//flag checking		if (!NeedFlags) {			if (RunFlags == traf->trex->def_sample_flags) {				if (!UseDefaultFlag) UseDefaultFlag = 2;				else if (UseDefaultFlag==1) NeedFlags = 1;			} else if (RunFlags == traf->tfhd->def_sample_flags) {				if (!UseDefaultFlag) UseDefaultFlag = 1;				else if(UseDefaultFlag==2) NeedFlags = 1;			}		}		if (NeedFlags) {			//one flags entry per sample only			trun->flags |= GF_ISOM_TRUN_FLAGS;		} else {			//indicated in global setup			if (first_ent->flags == traf->trex->def_sample_flags) {				if (!UseDefaultFlag) UseDefaultFlag = 2;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -