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

📄 track.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>GF_TrackBox *GetTrackbyID(GF_MovieBox *moov, u32 TrackID){	GF_TrackBox *trak;	u32 i;	if (!moov) return NULL;	i=0;	while ((trak = (GF_TrackBox *)gf_list_enum(moov->trackList, &i))) {		if (trak->Header->trackID == TrackID) return trak;	}	return NULL;}GF_TrackBox *gf_isom_get_track(GF_MovieBox *moov, u32 trackNumber){	GF_TrackBox *trak;	if (!moov || !trackNumber || (trackNumber > gf_list_count(moov->trackList))) return NULL;	trak = (GF_TrackBox*)gf_list_get(moov->trackList, trackNumber - 1);	return trak;}//get the number of a track given its ID//return 0 if not found erroru32 gf_isom_get_tracknum_from_id(GF_MovieBox *moov, u32 trackID){	u32 i;	GF_TrackBox *trak;	i=0;	while ((trak = (GF_TrackBox *)gf_list_enum(moov->trackList, &i))) {		if (trak->Header->trackID == trackID) return i;	}	return 0;}//extraction of the ESD from the trackGF_Err GetESD(GF_MovieBox *moov, u32 trackID, u32 StreamDescIndex, GF_ESD **outESD){	GF_Err e;	GF_ESD *esd;	GF_SampleTableBox *stbl;	GF_TrackBox *trak, *OCRTrack;	GF_TrackReferenceTypeBox *dpnd;	GF_SLConfig *slc;	GF_MPEGSampleEntryBox *entry;	dpnd = NULL;	*outESD = NULL;	trak = gf_isom_get_track(moov, gf_isom_get_tracknum_from_id(moov, trackID));	if (!trak) return GF_ISOM_INVALID_FILE;	e = Media_GetESD(trak->Media, StreamDescIndex, &esd, 0);	if (e) return e;	e = Media_GetSampleDesc(trak->Media, StreamDescIndex, (GF_SampleEntryBox **) &entry, NULL);	if (e) return e;	//set the ID	esd->ESID = trackID;		//find stream dependencies	e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_DPND , &dpnd);	if (e) return e;	if (dpnd) {		//ONLY ONE STREAM DEPENDENCY IS ALLOWED		if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;		//fix the spec: where is the index located ??		esd->dependsOnESID = dpnd->trackIDs[0];	} else {		esd->dependsOnESID = 0;	}	//OK, get the OCR (in a REAL MP4File, OCR is 0 in ESD and is specified through track reference	dpnd = NULL;	OCRTrack = NULL;	//find OCR dependencies	e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_SYNC, &dpnd);	if (e) return e;	if (dpnd) {		if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA;		esd->OCRESID = dpnd->trackIDs[0];		OCRTrack = gf_isom_get_track_from_id(trak->moov, dpnd->trackIDs[0]);		while (OCRTrack) {			/*if we have a dependency on a track that doesn't have OCR dep, remove that dependency*/			e = Track_FindRef(OCRTrack, GF_ISOM_BOX_TYPE_SYNC, &dpnd);			if (e || !dpnd || !dpnd->trackIDCount) {				OCRTrack = NULL;				goto default_sync;			}			/*this is explicit desync*/			if (dpnd && ((dpnd->trackIDs[0]==0) || (dpnd->trackIDs[0]==OCRTrack->Header->trackID))) break;			/*loop in OCRs, break it*/			if (esd->ESID == OCRTrack->Header->trackID) {				OCRTrack = NULL;				goto default_sync;			}			/*check next*/			OCRTrack = gf_isom_get_track_from_id(trak->moov, dpnd->trackIDs[0]);		}		if (!OCRTrack) goto default_sync;	} else {default_sync:		/*all tracks are sync'ed by default*/		if (trak->moov->mov->es_id_default_sync<0) {			if (esd->OCRESID)				trak->moov->mov->es_id_default_sync = esd->OCRESID;			else				trak->moov->mov->es_id_default_sync = esd->ESID;		}		if (trak->moov->mov->es_id_default_sync) esd->OCRESID = (u16) trak->moov->mov->es_id_default_sync;		/*cf ESD writer*/		if (esd->OCRESID == esd->ESID) esd->OCRESID = 0;	}	//update the IPI stuff if needed	if (esd->ipiPtr != NULL) {		dpnd = NULL;		e = Track_FindRef(trak, GF_ISOM_BOX_TYPE_IPIR, &dpnd);		if (e) return e;		if (dpnd) {			if (esd->ipiPtr->tag != GF_ODF_ISOM_IPI_PTR_TAG) return GF_ISOM_INVALID_FILE;			//OK, retrieve the ID: the IPI_ES_Id is currently the ref track			esd->ipiPtr->IPI_ES_Id = dpnd->trackIDs[esd->ipiPtr->IPI_ES_Id - 1];			//and change the tag			esd->ipiPtr->tag = GF_ODF_IPI_PTR_TAG;		} else {			return GF_ISOM_INVALID_FILE;		}	}	if ((trak->Media->mediaHeader->packedLanguage[0] != 'u')		|| (trak->Media->mediaHeader->packedLanguage[1] != 'n')		|| (trak->Media->mediaHeader->packedLanguage[2] != 'd') ) {		if (!esd->langDesc) esd->langDesc = (GF_Language *) gf_odf_desc_new(GF_ODF_LANG_TAG);		esd->langDesc->langCode = trak->Media->mediaHeader->packedLanguage[0]; esd->langDesc->langCode <<= 8;		esd->langDesc->langCode |= trak->Media->mediaHeader->packedLanguage[1]; esd->langDesc->langCode <<= 8;		esd->langDesc->langCode |= trak->Media->mediaHeader->packedLanguage[2];	}	/*normally all files shall be stored with predefined=SLPredef_MP4, but of course some are broken (philips)	so we just check the ESD_URL. If set, use the given cfg, otherwise always rewrite it*/	if (esd->URLString != NULL) {		*outESD = esd;		return GF_OK;	}	//if we are in publishing mode and we have an SLConfig specified, use it as is	switch (entry->type) {	case GF_ISOM_BOX_TYPE_MP4V:		slc = ((GF_MPEGVisualSampleEntryBox *)entry)->slc;		break;	case GF_ISOM_BOX_TYPE_MP4A:		slc = ((GF_MPEGAudioSampleEntryBox *)entry)->slc;		break;	case GF_ISOM_BOX_TYPE_MP4S:		slc = entry->slc;		break;	default:		slc = NULL;		break;	}	if (slc) {		gf_odf_desc_del((GF_Descriptor *)esd->slConfig);		gf_odf_desc_copy((GF_Descriptor *)slc, (GF_Descriptor **)&esd->slConfig);		*outESD = esd;		return GF_OK;	}	//otherwise use the regular mapping		//this is a desc for a media in the file, let's rewrite some param	esd->slConfig->timestampLength = 32;	esd->slConfig->timestampResolution = trak->Media->mediaHeader->timeScale;	//NO OCR from MP4File streams (eg, constant OC Res one)	esd->slConfig->OCRLength = 0;	if (OCRTrack) {		esd->slConfig->OCRResolution = OCRTrack->Media->mediaHeader->timeScale;	} else {		esd->slConfig->OCRResolution = 0;	}	stbl = trak->Media->information->sampleTable;	// a little optimization here: if all our samples are sync, 	//set the RAPOnly to true... for external users...	if (! stbl->SyncSample) {		esd->slConfig->hasRandomAccessUnitsOnlyFlag = 1;		esd->slConfig->useRandomAccessPointFlag = 0;	} else {		esd->slConfig->hasRandomAccessUnitsOnlyFlag = 0;		//signal we are NOT using sync points if no info is present in the table		esd->slConfig->useRandomAccessPointFlag = stbl->SyncSample->entryCount ? 1 : 0;	}	//do we have DegradationPriority ?	if (stbl->DegradationPriority) {		esd->slConfig->degradationPriorityLength = 15;	} else {		esd->slConfig->degradationPriorityLength = 0;	}	//paddingBits	if (stbl->PaddingBits) {		esd->slConfig->usePaddingFlag = 1;	}	//change to support reflecting OD streams	esd->slConfig->useAccessUnitEndFlag = 1;	esd->slConfig->useAccessUnitStartFlag = 1;	//signal we do have padding flag (since we only use logical SL packet	//the user can decide whether to use the info or not	esd->slConfig->usePaddingFlag = stbl->PaddingBits ? 1 : 0;	//same with degradation priority	esd->slConfig->degradationPriorityLength = stbl->DegradationPriority ? 32 : 0;	//this new SL will be OUT OF THE FILE. Let's set its predefined to 0	esd->slConfig->predefined = 0;		*outESD = esd;	return GF_OK;}//extraction of the ESD from the track for the given timeGF_Err GetESDForTime(GF_MovieBox *moov, u32 trackID, u64 CTS, GF_ESD **outESD){	GF_Err e;	u32 sampleDescIndex;	GF_TrackBox *trak;	trak = gf_isom_get_track(moov, gf_isom_get_tracknum_from_id(moov, trackID));	if (!trak) return GF_ISOM_INVALID_FILE;		e = Media_GetSampleDescIndex(trak->Media, CTS, &sampleDescIndex );	if (e) return e;	return GetESD(moov, trackID, sampleDescIndex, outESD);}GF_Err Track_FindRef(GF_TrackBox *trak, u32 ReferenceType, GF_TrackReferenceTypeBox **dpnd){	GF_TrackReferenceBox *ref;	GF_Box *a;	u32 i;	if (! trak) return GF_BAD_PARAM;	if (! trak->References) {		*dpnd = NULL;		return GF_OK;	}	ref = trak->References;	i=0;	while ((a = (GF_Box *)gf_list_enum(ref->boxList, &i))) {		if (a->type == ReferenceType) {			*dpnd = (GF_TrackReferenceTypeBox *)a;			return GF_OK;		}	}	*dpnd = NULL;	return GF_OK;	}Bool Track_IsMPEG4Stream(u32 HandlerType){	switch (HandlerType) {	case GF_ISOM_MEDIA_VISUAL:	case GF_ISOM_MEDIA_AUDIO:    case GF_ISOM_MEDIA_SUBPIC:	case GF_ISOM_MEDIA_OD:	case GF_ISOM_MEDIA_OCR:	case GF_ISOM_MEDIA_SCENE:	case GF_ISOM_MEDIA_MPEG7:	case GF_ISOM_MEDIA_OCI:	case GF_ISOM_MEDIA_IPMP:	case GF_ISOM_MEDIA_MPEGJ:	case GF_ISOM_MEDIA_ESM:		return 1;	/*Timedtext is NOT an MPEG-4 stream*/	default:		return 0;	}}GF_Err SetTrackDuration(GF_TrackBox *trak){	u64 trackDuration;	u32 i;	GF_EdtsEntry *ent;	GF_EditListBox *elst;	GF_Err e;	//the total duration is the media duration: adjust it in case...	e = Media_SetDuration(trak);	if (e) return e;	//if we have an edit list, the duration is the sum of all the editList 	//entries' duration (always expressed in MovieTimeScale)	if (trak->editBox && trak->editBox->editList) {		trackDuration = 0;		elst = trak->editBox->editList;		i=0;		while ((ent = (GF_EdtsEntry*)gf_list_enum(elst->entryList, &i))) {			trackDuration += ent->segmentDuration;		}	} else {		//assert the timeScales are non-NULL		if (!trak->moov->mvhd->timeScale && !trak->Media->mediaHeader->timeScale) return GF_ISOM_INVALID_FILE;		trackDuration = (trak->Media->mediaHeader->duration * trak->moov->mvhd->timeScale) / trak->Media->mediaHeader->timeScale;	}	trak->Header->duration = trackDuration;	trak->Header->modificationTime = gf_isom_get_mp4time();	return GF_OK;}#ifndef	GF_ISOM_NO_FRAGMENTSGF_Err MergeTrack(GF_TrackBox *trak, GF_TrackFragmentBox *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;	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);	//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;	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;

⌨️ 快捷键说明

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