movie_fragments.c

来自「一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库」· C语言 代码 · 共 776 行 · 第 1/2 页

C
776
字号
				else if (UseDefaultFlag==1) trun->flags |= GF_ISOM_TRUN_FIRST_FLAG;			}			//indicated in local setup			else if (first_ent->flags == traf->tfhd->def_sample_flags) {				if (!UseDefaultFlag) UseDefaultFlag = 1;				else if (UseDefaultFlag==2) trun->flags |= GF_ISOM_TRUN_FIRST_FLAG;			}			//explicit store			else {				trun->flags |= GF_ISOM_TRUN_FIRST_FLAG;			}		}		//CTS flag		if (UseCTS) trun->flags |= GF_ISOM_TRUN_CTS_OFFSET;		//run data offset if the offset indicated is 0 (first sample in this MDAT) don't 		//indicate it		if (trun->data_offset) trun->flags |= GF_ISOM_TRUN_DATA_OFFSET;		sampleCount += trun->sample_count;	}	//last update TRAF flags	if (UseDefaultSize==1) traf->tfhd->flags |= GF_ISOM_TRAF_SAMPLE_SIZE;	if (UseDefaultDur==1) traf->tfhd->flags |= GF_ISOM_TRAF_SAMPLE_DUR;	if (UseDefaultFlag==1) traf->tfhd->flags |= GF_ISOM_TRAF_SAMPLE_FLAGS;	if (traf->tfhd->sample_desc_index && traf->tfhd->sample_desc_index != traf->trex->def_sample_desc_index) traf->tfhd->flags |= GF_ISOM_TRAF_SAMPLE_DESC;	return sampleCount;}GF_Err StoreFragment(GF_ISOFile *movie){	GF_Err e;	u64 moof_start;	u32 size, i, s_count;	char *buffer;	GF_TrackFragmentBox *traf;	GF_TrackFragmentRunBox *trun;	GF_BitStream *bs;	if (!movie->moof) return GF_OK;	bs = movie->editFileMap->bs;	//1- flush all caches	i=0;	while ((traf = (GF_TrackFragmentBox*)gf_list_enum(movie->moof->TrackList, &i))) {		if (!traf->DataCache) continue;		s_count = gf_list_count(traf->TrackRuns);		if (!s_count) continue;		trun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, s_count-1);		if (!trun->cache || !trun->sample_count) continue;				//update offset		trun->data_offset = (u32) (gf_bs_get_position(movie->editFileMap->bs) - movie->current_top_box_start - 8);		//write cache		gf_bs_get_content(trun->cache, &buffer, &size);		gf_bs_write_data(movie->editFileMap->bs, buffer, size);		gf_bs_del(trun->cache);		free(buffer);		trun->cache = NULL;	}	//2- update MOOF MDAT header	moof_start = gf_bs_get_position(bs);	//start of MDAT	gf_bs_seek(bs, movie->current_top_box_start);	//we assume we never write large MDATs in fragment mode which should always be true	size = (u32) (moof_start - movie->current_top_box_start);	gf_bs_write_u32(bs, (u32) size);	gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_MDAT);	gf_bs_seek(bs, moof_start);	//3- clean our traf's	i=0;	while ((traf = (GF_TrackFragmentBox*) gf_list_enum(movie->moof->TrackList, &i))) {		//compute default settings for the TRAF		ComputeFragmentDefaults(traf);		//updates all trun and set all flags, INCLUDING TRAF FLAGS (durations, ...)		s_count = UpdateRuns(traf);		//empty fragment destroy it		if (!traf->tfhd->EmptyDuration && !s_count) {			i--;			gf_list_rem(movie->moof->TrackList, i);			gf_isom_box_del((GF_Box *) traf);			continue;		}	}	//4- Write moof	e = gf_isom_box_size((GF_Box *) movie->moof);	if (e) return e;	e = gf_isom_box_write((GF_Box *) movie->moof, bs);	if (e) return e;		//5- destroy our moof	gf_isom_box_del((GF_Box *) movie->moof);	movie->moof = NULL;	movie->NextMoofNumber ++;	return GF_OK;}GF_Err gf_isom_start_fragment(GF_ISOFile *movie){	u32 i, count;	GF_TrackExtendsBox *trex;	GF_TrackFragmentBox *traf;	GF_Err e;	//and only at setup	if (!movie || !(movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) ) return GF_BAD_PARAM;	if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_ISOM_INVALID_MODE;	count = gf_list_count(movie->moov->mvex->TrackExList);	if (!count) return GF_BAD_PARAM;	//store fragment	if (movie->moof) {		e = StoreFragment(movie);		if (e) return e;	} 		//format MDAT	movie->current_top_box_start = gf_bs_get_position(movie->editFileMap->bs);	gf_bs_write_u32(movie->editFileMap->bs, 0);	gf_bs_write_u32(movie->editFileMap->bs, GF_ISOM_BOX_TYPE_MDAT);	//create new fragment	movie->moof = (GF_MovieFragmentBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MOOF);	movie->moof->mfhd = (GF_MovieFragmentHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MFHD);	movie->moof->mfhd->sequence_number = movie->NextMoofNumber;		//we create a TRAF for each setup track, unused ones will be removed at store time	for (i=0; i<count; i++) {		trex = (GF_TrackExtendsBox*)gf_list_get(movie->moov->mvex->TrackExList, i);		traf = (GF_TrackFragmentBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TRAF);		traf->trex = trex;		traf->tfhd = (GF_TrackFragmentHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TFHD);		traf->tfhd->trackID = trex->trackID;		//add 8 bytes (MDAT size+type) to avoid the data_offset in the first trun		traf->tfhd->base_data_offset = movie->current_top_box_start + 8;		gf_list_add(movie->moof->TrackList, traf);	}	return GF_OK;}u32 GetRunSize(GF_TrackFragmentRunBox *trun){	u32 i, size;	GF_TrunEntry *ent;	size = 0;	i=0;	while ((ent = (GF_TrunEntry*)gf_list_enum(trun->entries, &i))) {		size += ent->size;	}	return size;}GF_Err gf_isom_fragment_add_sample(GF_ISOFile *movie, u32 TrackID, GF_ISOSample *sample, u32 DescIndex, 								 u32 Duration,								 u8 PaddingBits, u16 DegradationPriority){	u32 count, buffer_size;	char *buffer;	u64 pos;	GF_TrunEntry *ent;	GF_TrackFragmentBox *traf, *traf_2;	GF_TrackFragmentRunBox *trun;	if (!movie->moof || !(movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) || !sample) return GF_BAD_PARAM;	traf = GetTraf(movie, TrackID);	if (!traf) return GF_BAD_PARAM;	if (!traf->tfhd->sample_desc_index) traf->tfhd->sample_desc_index = DescIndex ? DescIndex : traf->trex->def_sample_desc_index;	pos = gf_bs_get_position(movie->editFileMap->bs);		//WARNING: we change stream description, create a new TRAF	if ( DescIndex && (traf->tfhd->sample_desc_index != DescIndex)) {		//if we're caching flush the current run		if (traf->DataCache) {			count = gf_list_count(traf->TrackRuns);			if (count) {				trun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, count-1);				trun->data_offset = (u32) (pos - movie->current_top_box_start - 8);				gf_bs_get_content(trun->cache, &buffer, &buffer_size);				gf_bs_write_data(movie->editFileMap->bs, buffer, buffer_size);				gf_bs_del(trun->cache);				trun->cache = NULL;				free(buffer);			}		}		traf_2 = (GF_TrackFragmentBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TRAF);		traf_2->trex = traf->trex;		traf_2->tfhd = (GF_TrackFragmentHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TFHD);		traf_2->tfhd->trackID = traf->tfhd->trackID;		//keep the same offset		traf_2->tfhd->base_data_offset = movie->current_top_box_start + 8;		gf_list_add(movie->moof->TrackList, traf_2);		//duplicate infos		traf_2->tfhd->IFrameSwitching = traf->tfhd->IFrameSwitching;		traf_2->DataCache  = traf->DataCache;		traf_2->tfhd->sample_desc_index  = DescIndex;		//switch them ...		traf = traf_2;	}	//add TRUN entry	count = gf_list_count(traf->TrackRuns);	if (count) {		trun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, count-1);		//check data offset when no caching as trun entries shall ALWAYS be contiguous samples		if (!traf->DataCache && (movie->current_top_box_start + 8 + trun->data_offset + GetRunSize(trun) != pos) )			count = 0;				//check I-frame detection		if (traf->tfhd->IFrameSwitching && sample->IsRAP) 			count = 0;		if (traf->DataCache && (traf->DataCache==trun->sample_count) )			count = 0;		//if data cache is on and we're changing TRUN, store the cache and update data offset		if (!count && traf->DataCache) {			trun->data_offset = (u32) (pos - movie->current_top_box_start - 8);			gf_bs_get_content(trun->cache, &buffer, &buffer_size);			gf_bs_write_data(movie->editFileMap->bs, buffer, buffer_size);			gf_bs_del(trun->cache);			trun->cache = NULL;			free(buffer);		}	}	//new run	if (!count) {		trun = (GF_TrackFragmentRunBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TRUN);		//store data offset (we have the 8 btyes offset of the MDAT)		trun->data_offset = (u32) (pos - movie->current_top_box_start - 8);		gf_list_add(traf->TrackRuns, trun);		//if we use data caching, create a bitstream		if (traf->DataCache) 			trun->cache = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);	}	GF_SAFEALLOC(ent, GF_TrunEntry);	ent->CTS_Offset = sample->CTS_Offset;	ent->Duration = Duration;	ent->size = sample->dataLength;	ent->flags = GF_ISOM_FORMAT_FRAG_FLAGS(PaddingBits, sample->IsRAP, DegradationPriority);	gf_list_add(trun->entries, ent);		trun->sample_count += 1;	//rewrite OD frames	if (traf->trex->track->Media->handler->handlerType == GF_ISOM_MEDIA_OD) {		//this may fail if depandancies are not well done ...		Media_ParseODFrame(traf->trex->track->Media, sample);	}	//finally write the data	if (!traf->DataCache) {		gf_bs_write_data(movie->editFileMap->bs, sample->data, sample->dataLength);	} else if (trun->cache) {		gf_bs_write_data(trun->cache, sample->data, sample->dataLength);	} else {		return GF_BAD_PARAM;	}	return GF_OK;}GF_Err gf_isom_fragment_append_data(GF_ISOFile *movie, u32 TrackID, char *data, u32 data_size, u8 PaddingBits){	u32 count;	u8 rap;	u16 degp;	GF_TrunEntry *ent;	GF_TrackFragmentBox *traf;	GF_TrackFragmentRunBox *trun;	if (!movie->moof || !(movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) ) return GF_BAD_PARAM;	traf = GetTraf(movie, TrackID);	if (!traf || !traf->tfhd->sample_desc_index) return GF_BAD_PARAM;	//add TRUN entry	count = gf_list_count(traf->TrackRuns);	if (!count) return GF_BAD_PARAM;	trun = (GF_TrackFragmentRunBox *)gf_list_get(traf->TrackRuns, count-1);	count = gf_list_count(trun->entries);	if (!count) return GF_BAD_PARAM;	ent = (GF_TrunEntry *)gf_list_get(trun->entries, count-1);	ent->size += data_size;	rap = GF_ISOM_GET_FRAG_SYNC(ent->flags);	degp = GF_ISOM_GET_FRAG_DEG(ent->flags);	ent->flags = GF_ISOM_FORMAT_FRAG_FLAGS(PaddingBits, rap, degp);	//finally write the data	if (!traf->DataCache) {		gf_bs_write_data(movie->editFileMap->bs, data, data_size);	} else if (trun->cache) {		gf_bs_write_data(trun->cache, data, data_size);	} else {		return GF_BAD_PARAM;	}	return GF_OK;}#endif	//GPAC_READ_ONLYGF_EXPORTu32 gf_isom_is_track_fragmented(GF_ISOFile *movie, u32 TrackID){	if (!movie || !movie->moov || !movie->moov->mvex) return 0;	return (GetTrex(movie->moov, TrackID) != NULL) ? 1 : 0;}GF_EXPORTu32 gf_isom_is_fragmented(GF_ISOFile *movie){	if (!movie || !movie->moov) return 0;	/*only check moof number (in read mode, mvex can be deleted on the fly)*/	return movie->NextMoofNumber ? 1 : 0;}#elseGF_Err gf_isom_finalize_for_fragment(GF_ISOFile *the_file){	return GF_NOT_SUPPORTED;}GF_Err gf_isom_setup_track_fragment(GF_ISOFile *the_file, u32 TrackID, 							 u32 DefaultSampleDescriptionIndex,							 u32 DefaultSampleDuration,							 u32 DefaultSampleSize,							 u8 DefaultSampleIsSync,							 u8 DefaultSamplePadding,							 u16 DefaultDegradationPriority){	return GF_NOT_SUPPORTED;}GF_Err gf_isom_set_fragment_option(GF_ISOFile *the_file, u32 TrackID, u32 Code, u32 Param){	return GF_NOT_SUPPORTED;}GF_Err gf_isom_start_fragment(GF_ISOFile *the_file){	return GF_NOT_SUPPORTED;}GF_Err gf_isom_fragment_add_sample(GF_ISOFile *the_file, u32 TrackID, GF_ISOSample *sample, u32 DescIndex, 								 u32 Duration,								 u8 PaddingBits, u16 DegradationPriority){	return GF_NOT_SUPPORTED;}GF_EXPORTu32 gf_isom_is_track_fragmented(GF_ISOFile *the_file, u32 TrackID){	return 0;}GF_EXPORTu32 gf_isom_is_fragmented(GF_ISOFile *the_file){	return 0;}#endif

⌨️ 快捷键说明

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