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

📄 stbl_read.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>//Get the sample numberGF_Err findEntryForTime(GF_SampleTableBox *stbl, u64 DTS, u8 useCTS, u32 *sampleNumber, u32 *prevSampleNumber){	u32 i, j, curSampNum, CTSOffset, count;	u64 curDTS;	GF_SttsEntry *ent;	(*sampleNumber) = 0;	(*prevSampleNumber) = 0;	if (!stbl->CompositionOffset) useCTS = 0;	/*FIXME: CTS is ALWAYS disabled for now to make sure samples are fetched in 	decoding order. */	useCTS = 0;	//our cache	if (stbl->TimeToSample->r_FirstSampleInEntry &&		(DTS >= stbl->TimeToSample->r_CurrentDTS) ) {		//if we're using CTS, we don't really know whether we're in the good entry or not		//(eg, the real DTS of the sample could be in a previous entry		i = stbl->TimeToSample->r_currentEntryIndex;		curDTS = stbl->TimeToSample->r_CurrentDTS;		curSampNum = stbl->TimeToSample->r_FirstSampleInEntry;	} else {		i = 0;		curDTS = stbl->TimeToSample->r_CurrentDTS = 0;		curSampNum = stbl->TimeToSample->r_FirstSampleInEntry = 1;		stbl->TimeToSample->r_currentEntryIndex = 0;	}	//we need to validate our cache if we are using CTS because of B-frames and co...	if (i && useCTS) {		while (1) {			stbl_GetSampleCTS(stbl->CompositionOffset, curSampNum, &CTSOffset);			//we're too far, rewind			if ( i && (curDTS + CTSOffset > DTS) ) {				ent = (GF_SttsEntry*)gf_list_get(stbl->TimeToSample->entryList, i);				curSampNum -= ent->sampleCount;				curDTS -= ent->sampleDelta * ent->sampleCount;				i --;			} else if (!i) {				//begining of the table, no choice				curDTS = stbl->TimeToSample->r_CurrentDTS = 0;				curSampNum = stbl->TimeToSample->r_FirstSampleInEntry = 1;				stbl->TimeToSample->r_currentEntryIndex = 0;				break;			} else {				//OK now we're good				break;			}		}	}	//look for the DTS from this entry	count = gf_list_count(stbl->TimeToSample->entryList);	for (; i<count; i++) {		ent = (GF_SttsEntry*)gf_list_get(stbl->TimeToSample->entryList, i);		if (useCTS) {			stbl_GetSampleCTS(stbl->CompositionOffset, curSampNum, &CTSOffset);		} else {			CTSOffset = 0;		}		for (j=0; j<ent->sampleCount; j++) {			if (curDTS + CTSOffset >= DTS) goto entry_found;			curSampNum += 1;			curDTS += ent->sampleDelta;		}		//we're switching to the next entry, update the cache!		stbl->TimeToSample->r_CurrentDTS += ent->sampleCount * ent->sampleDelta;		stbl->TimeToSample->r_currentEntryIndex += 1;		stbl->TimeToSample->r_FirstSampleInEntry += ent->sampleCount;	}	//return as is	return GF_OK;entry_found:	//do we have the exact time ?	if (curDTS + CTSOffset == DTS) {		(*sampleNumber) = curSampNum;	}	//if we match the exact DTS also select this sample 	else if (curDTS == DTS) {		(*sampleNumber) = curSampNum;	} else {		//exception for the first sample (we need to "load" the playback)		if (curSampNum != 1) {			(*prevSampleNumber) = curSampNum - 1;		} else {			(*prevSampleNumber) = 1;		}	}	return GF_OK;}//Get the Size of a given sampleGF_Err stbl_GetSampleSize(GF_SampleSizeBox *stsz, u32 SampleNumber, u32 *Size){	if (!stsz || !SampleNumber || SampleNumber > stsz->sampleCount) return GF_BAD_PARAM;	(*Size) = 0;	if (stsz->sampleSize && (stsz->type != GF_ISOM_BOX_TYPE_STZ2)) {		(*Size) = stsz->sampleSize;	} else {		(*Size) = stsz->sizes[SampleNumber - 1];	}	return GF_OK;}//Get the CTS offset of a given sampleGF_Err stbl_GetSampleCTS(GF_CompositionOffsetBox *ctts, u32 SampleNumber, u32 *CTSoffset){	u32 i, count;	GF_DttsEntry *ent;	(*CTSoffset) = 0;	ent = NULL;	//test on SampleNumber is done before	if (!ctts || !SampleNumber) return GF_BAD_PARAM;	if (ctts->r_FirstSampleInEntry && (ctts->r_FirstSampleInEntry < SampleNumber) ) {		i = ctts->r_currentEntryIndex;	} else {		ctts->r_FirstSampleInEntry = 1;		ctts->r_currentEntryIndex = 0;		i = 0;	}	count = gf_list_count(ctts->entryList);	for (; i< count; i++) {		ent = (GF_DttsEntry*)gf_list_get(ctts->entryList, i);		if (SampleNumber < ctts->r_FirstSampleInEntry + ent->sampleCount) break;		//update our cache		ctts->r_currentEntryIndex += 1;		ctts->r_FirstSampleInEntry += ent->sampleCount;	}	//no ent, set everything to 0...	if (!ent) return GF_OK;	/*asked for a sample not in table - this means CTTS is 0 (that's due to out internal packing construction of CTTS)*/	if (SampleNumber >= ctts->r_FirstSampleInEntry + ent->sampleCount) return GF_OK;	(*CTSoffset) = ent->decodingOffset;	return GF_OK;}//Get the DTS of a sampleGF_Err stbl_GetSampleDTS(GF_TimeToSampleBox *stts, u32 SampleNumber, u64 *DTS){	u32 i, j, count;	GF_SttsEntry *ent;	(*DTS) = 0;	if (!stts || !SampleNumber) return GF_BAD_PARAM;	ent = NULL;	//use our cache	count = gf_list_count(stts->entryList);	if (stts->r_FirstSampleInEntry 		&& (stts->r_FirstSampleInEntry <= SampleNumber)		//this is for read/write access		&& (stts->r_currentEntryIndex < count) ) {		i = stts->r_currentEntryIndex;	} else {		i = stts->r_currentEntryIndex = 0;		stts->r_FirstSampleInEntry = 1;		stts->r_CurrentDTS = 0;	}	for (; i < count; i++) {		ent = (GF_SttsEntry*)gf_list_get(stts->entryList, i);		//in our entry		if (ent->sampleCount + stts->r_FirstSampleInEntry >= 1 + SampleNumber) {			j = SampleNumber - stts->r_FirstSampleInEntry;			goto found;		}					//update our cache		stts->r_CurrentDTS += ent->sampleCount * ent->sampleDelta;		stts->r_currentEntryIndex += 1;		stts->r_FirstSampleInEntry += ent->sampleCount;	}//	if (SampleNumber >= stts->r_FirstSampleInEntry + ent->sampleCount) return GF_BAD_PARAM;	//no ent, this is really weird. Let's assume the DTS is then what is written in the table	if (!ent || (i == count)) (*DTS) = stts->r_CurrentDTS;	return GF_OK;found:	(*DTS) = stts->r_CurrentDTS + j * (u64) ent->sampleDelta;	if (stts->r_FirstSampleInEntry == 1)		stts->r_FirstSampleInEntry = 1;			return GF_OK;}//Set the RAP flag of a sampleGF_Err stbl_GetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, u8 *IsRAP, u32 *prevRAP, u32 *nextRAP){	u32 i;	if (prevRAP) *prevRAP = 0;	if (nextRAP) *nextRAP = 0;	(*IsRAP) = 0;	if (!stss || !SampleNumber) return GF_BAD_PARAM;	if (stss->r_LastSyncSample && (stss->r_LastSyncSample < SampleNumber) ) {		i = stss->r_LastSampleIndex;	} else {		i = 0;	}	for (; i < stss->entryCount; i++) {		//get the entry		if (stss->sampleNumbers[i] == SampleNumber) {			//update the cache			stss->r_LastSyncSample = SampleNumber;			stss->r_LastSampleIndex = i;			(*IsRAP) = 1;		}		else if (stss->sampleNumbers[i] > SampleNumber) {			if (nextRAP) *nextRAP = stss->sampleNumbers[i];			return GF_OK;		}		if (prevRAP) *prevRAP = stss->sampleNumbers[i];	}	return GF_OK;}//get the number of "ghost chunk" (implicit chunks described by an entry)void GetGhostNum(GF_StscEntry *ent, u32 EntryIndex, u32 count, GF_SampleTableBox *stbl){

⌨️ 快捷键说明

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