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

📄 stbl_write.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *			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 GPAC_READ_ONLY//adds a DTS in the table and get the sample number of this new sample//we could return an error if a sample with the same DTS already exists//but this is not true for QT or MJ2K, only for MP4...//we assume the authoring tool tries to create a compliant MP4 file.GF_Err stbl_AddDTS(GF_SampleTableBox *stbl, u64 DTS, u32 *sampleNumber, u32 LastAUDefDuration){	u32 i, j, sampNum;	u64 *DTSs, *newDTSs, curDTS;	GF_SttsEntry *ent;	GF_TimeToSampleBox *stts = stbl->TimeToSample;	//We don't update the reading cache when adding a sample	*sampleNumber = 0;	//if we don't have an entry, that's the first one...	if (! gf_list_count(stts->entryList)) {		//assert the first DTS is 0. If not, that will break the whole file		if (DTS) return GF_BAD_PARAM;		ent = (GF_SttsEntry*)malloc(sizeof(GF_SttsEntry));		if (!ent) return GF_OUT_OF_MEM;		ent->sampleCount = 1;		ent->sampleDelta = LastAUDefDuration;		stts->w_currentEntry = ent;		stts->w_currentSampleNum = (*sampleNumber) = 1;		return gf_list_add(stts->entryList, ent);	}	//check the last DTS...	if (DTS > stts->w_LastDTS) {		//OK, we're adding at the end		if (DTS == stts->w_LastDTS + stts->w_currentEntry->sampleDelta) {			stts->w_currentEntry->sampleCount ++;			stts->w_currentSampleNum ++;			(*sampleNumber) = stts->w_currentSampleNum;			stts->w_LastDTS = DTS;			return GF_OK;		}		//we need to split the entry		if (stts->w_currentEntry->sampleCount == 1) {			//use this one and adjust...			stts->w_currentEntry->sampleDelta = (u32) (DTS - stts->w_LastDTS);			stts->w_currentEntry->sampleCount ++;			stts->w_currentSampleNum ++;			stts->w_LastDTS = DTS;			(*sampleNumber) = stts->w_currentSampleNum;			return GF_OK;		}		//we definitely need to split the entry ;)		stts->w_currentEntry->sampleCount --;		ent = (GF_SttsEntry*)malloc(sizeof(GF_SttsEntry));		ent->sampleCount = 2;		ent->sampleDelta = (u32) (DTS - stts->w_LastDTS);		stts->w_LastDTS = DTS;		stts->w_currentSampleNum ++;		(*sampleNumber) = stts->w_currentSampleNum;		stts->w_currentEntry = ent;		return gf_list_add(stts->entryList, ent);	}	//unpack the DTSs...	DTSs = (u64*)malloc(sizeof(u64) * stbl->SampleSize->sampleCount);	curDTS = 0;	sampNum = 0;	ent = NULL;	i=0;	while ((ent = (GF_SttsEntry *)gf_list_enum(stts->entryList, &i))) {		for (j = 0; j<ent->sampleCount; j++) {			DTSs[sampNum] = curDTS;			curDTS += ent->sampleDelta;			sampNum ++;		}	}	//delete the table..	while (gf_list_count(stts->entryList)) {		ent = (GF_SttsEntry*)gf_list_get(stts->entryList, 0);		free(ent);		gf_list_rem(stts->entryList, 0);	}	//create the new DTSs	newDTSs = (u64*)malloc(sizeof(u64) * (stbl->SampleSize->sampleCount + 1));	i = 0;	while (i < stbl->SampleSize->sampleCount) {		if (DTSs[i] > DTS) break;		newDTSs[i] = DTSs[i];		i++;	}	//if we add a sample with the same DTS as an existing one, it's added after.	newDTSs[i] = DTS;	*sampleNumber = i+1;	for (; i<stbl->SampleSize->sampleCount; i++) {		newDTSs[i+1] = DTSs[i];	}	free(DTSs);	//rewrite the table	ent = (GF_SttsEntry*)malloc(sizeof(GF_SttsEntry));	ent->sampleCount = 0;	ent->sampleDelta = (u32) newDTSs[1];	i = 0;	while (1) {		if (i == stbl->SampleSize->sampleCount) {			//and by default, our last sample has the same delta as the prev			ent->sampleCount++;			gf_list_add(stts->entryList, ent);			break;		}		if (newDTSs[i+1] - newDTSs[i] == ent->sampleDelta) {			ent->sampleCount += 1;		} else {			gf_list_add(stts->entryList, ent);			ent = (GF_SttsEntry*)malloc(sizeof(GF_SttsEntry));			ent->sampleCount = 1;			ent->sampleDelta = (u32) (newDTSs[i+1] - newDTSs[i]);		}		i++;	}	free(newDTSs);	//reset the cache to the end	stts->w_currentEntry = ent;	stts->w_currentSampleNum = stbl->SampleSize->sampleCount + 1;	return GF_OK;}GF_Err AddCompositionOffset(GF_CompositionOffsetBox *ctts, u32 offset){	GF_DttsEntry *entry;	if (!ctts) return GF_BAD_PARAM;	entry = ctts->w_currentEntry;	if ( (entry == NULL) || (entry->decodingOffset != offset) ) {		entry = (GF_DttsEntry *) malloc(sizeof(GF_DttsEntry));		if (!entry) return GF_OUT_OF_MEM;		entry->sampleCount = 1;		entry->decodingOffset = offset;		gf_list_add(ctts->entryList, entry);		ctts->w_currentEntry = entry;	} else {		entry->sampleCount++;	}	ctts->w_LastSampleNumber++;	return GF_OK;}//adds a CTS offset for a new sampleGF_Err stbl_AddCTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 CTSoffset){	GF_DttsEntry *ent;	u32 i, j, count, sampNum, *CTSs, *newCTSs;	GF_CompositionOffsetBox *ctts = stbl->CompositionOffset;	/*in unpack mode we're sure to have 1 ctts entry per sample*/	if (ctts->unpack_mode) {		ent = (GF_DttsEntry *) malloc(sizeof(GF_DttsEntry));		if (!ent) return GF_OUT_OF_MEM;		ent->sampleCount = 1;		ent->decodingOffset = CTSoffset;		return gf_list_add(ctts->entryList, ent);	}	/*move to last entry*/	if (!ctts->w_currentEntry) {		ctts->w_LastSampleNumber = 0;		count = gf_list_count(ctts->entryList);		for (i=0; i<count; i++) {			ctts->w_currentEntry = (GF_DttsEntry *)gf_list_get(ctts->entryList, i);			ctts->w_LastSampleNumber += ctts->w_currentEntry->sampleCount;		}	}	//check if we're working in order...	if (ctts->w_LastSampleNumber < sampleNumber) {		//add some 0 till we get to the sample		while (ctts->w_LastSampleNumber + 1 != sampleNumber) {			AddCompositionOffset(ctts, 0);		}		return AddCompositionOffset(ctts, CTSoffset);	}	//NOPE we are inserting a sample...	CTSs = (u32*)malloc(sizeof(u32) * stbl->SampleSize->sampleCount);	sampNum = 0;	i=0;	while ((ent = (GF_DttsEntry *)gf_list_enum(ctts->entryList, &i))) {		for (j = 0; j<ent->sampleCount; j++) {			CTSs[sampNum] = ent->decodingOffset;			sampNum ++;		}	}		//delete the entries	while (gf_list_count(ctts->entryList)) {		ent = (GF_DttsEntry*)gf_list_get(ctts->entryList, 0);		free(ent);		gf_list_rem(ctts->entryList, 0);	}		//create the new CTS	newCTSs = (u32*)malloc(sizeof(u32) * (stbl->SampleSize->sampleCount + 1));	j = 0;	for (i = 0; i < stbl->SampleSize->sampleCount; i++) {		if (i+1 == sampleNumber) {			newCTSs[i] = CTSoffset;			j = 1;		}		newCTSs[i+j] = CTSs[i];	}	free(CTSs);	//rewrite the table	ent = (GF_DttsEntry*)malloc(sizeof(GF_DttsEntry));	ent->sampleCount = 1;	ent->decodingOffset = newCTSs[0];	i = 1;	while (1) {		if (i == stbl->SampleSize->sampleCount) {			gf_list_add(ctts->entryList, ent);			break;		}		if (newCTSs[i] == ent->decodingOffset) {			ent->sampleCount += 1;		} else {			gf_list_add(ctts->entryList, ent);			ent = (GF_DttsEntry*)malloc(sizeof(GF_DttsEntry));			ent->sampleCount = 1;			ent->decodingOffset = newCTSs[i];		}		i++;	}	free(newCTSs);	//reset the cache to the end	ctts->w_currentEntry = ent;	//we've inserted a sample, therefore the last sample (n) has now number n+1	//we cannot use SampleCount because we have probably skipped some samples	//(we're calling AddCTS only if the sample gas a CTSOffset !!!)	ctts->w_LastSampleNumber += 1;	return GF_OK;}GF_Err stbl_repackCTS(GF_CompositionOffsetBox *ctts){	GF_DttsEntry *entry, *next;	GF_List *newTable;	u32 i, count;	if (!ctts->unpack_mode) return GF_OK;	ctts->unpack_mode = 0;	count = gf_list_count(ctts->entryList);	if (!count) return GF_OK;	newTable = gf_list_new();	entry = (GF_DttsEntry *)gf_list_get(ctts->entryList, 0);	ctts->w_LastSampleNumber = entry->sampleCount;	gf_list_add(newTable, entry);	for (i=1; i<count; i++) {		next = (GF_DttsEntry *)gf_list_get(ctts->entryList, i);		ctts->w_LastSampleNumber += next->sampleCount;		if (entry->decodingOffset != next->decodingOffset) {			entry = next;			gf_list_add(newTable, entry);			ctts->w_currentEntry = entry;		} else {			entry->sampleCount += next->sampleCount;			free(next);		}	} 	gf_list_del(ctts->entryList);	ctts->entryList = newTable;	return GF_OK;}GF_Err stbl_unpackCTS(GF_SampleTableBox *stbl){	GF_DttsEntry *entry, *next;	u32 i, j, remain;	GF_CompositionOffsetBox *ctts;	GF_List *newTable;	ctts = stbl->CompositionOffset;	if (ctts->unpack_mode) return GF_OK;	ctts->unpack_mode = 1;	newTable = gf_list_new();	i=0;	while ((entry = (GF_DttsEntry *)gf_list_enum(ctts->entryList, &i))) {		gf_list_add(newTable, entry);		for (j=1; j<entry->sampleCount; j++) {			next = (GF_DttsEntry *)malloc(sizeof(GF_DttsEntry));			next->decodingOffset = entry->decodingOffset;			next->sampleCount = 1;			gf_list_add(newTable, next);		}		entry->sampleCount = 1;	}	gf_list_del(ctts->entryList);	ctts->entryList = newTable;	remain = stbl->SampleSize->sampleCount - gf_list_count(ctts->entryList);	while (remain) {		entry = (GF_DttsEntry *)malloc(sizeof(GF_DttsEntry));		entry->decodingOffset = 0;		entry->sampleCount = 1;		gf_list_add(ctts->entryList, entry);		remain--;	}	return GF_OK;}//add sizeGF_Err stbl_AddSize(GF_SampleSizeBox *stsz, u32 sampleNumber, u32 size){	u32 i, k;	u32 *newSizes;	if (!stsz || !size || !sampleNumber) return GF_BAD_PARAM;	if (sampleNumber > stsz->sampleCount + 1) return GF_BAD_PARAM;	//all samples have the same size	if (stsz->sizes == NULL) {		//1 first sample added in NON COMPACT MODE		if (! stsz->sampleCount && (stsz->type != GF_ISOM_BOX_TYPE_STZ2) ) {			stsz->sampleCount = 1;			stsz->sampleSize = size;			return GF_OK;		}		//2- sample has the same size		if (stsz->sampleSize == size) {			stsz->sampleCount++;			return GF_OK;		}		//3- no, need to alloc a size table		stsz->sizes = (u32*)malloc(sizeof(u32) * (stsz->sampleCount + 1));		if (!stsz->sizes) return GF_OUT_OF_MEM;		stsz->alloc_size = stsz->sampleCount + 1;		k = 0;		for (i = 0 ; i < stsz->sampleCount; i++) {			if (i + 1 == sampleNumber) {				stsz->sizes[i + k] = size;				k = 1;			}			stsz->sizes[i+k] = stsz->sampleSize;		}		//this if we append a new sample		if (stsz->sampleCount + 1 == sampleNumber) {			stsz->sizes[stsz->sampleCount] = size;		}		stsz->sampleSize = 0;		stsz->sampleCount++;		return GF_OK;	}	/*append*/	if (stsz->sampleCount + 1 == sampleNumber) {		if (!stsz->alloc_size) stsz->alloc_size = stsz->sampleCount;		if (stsz->sampleCount == stsz->alloc_size) {			stsz->alloc_size += 50;			newSizes = (u32*)malloc(sizeof(u32)*(stsz->alloc_size) );			if (!newSizes) return GF_OUT_OF_MEM;			memcpy(newSizes, stsz->sizes, sizeof(u32)*stsz->sampleCount);			free(stsz->sizes);			stsz->sizes = newSizes;		}		stsz->sizes[stsz->sampleCount] = size;	} else {		newSizes = (u32*)malloc(sizeof(u32)*(1 + stsz->sampleCount) );		if (!newSizes) return GF_OUT_OF_MEM;		k = 0;		for (i = 0; i < stsz->sampleCount; i++) {			if (i + 1 == sampleNumber) {				newSizes[i + k] = size;				k = 1;			}			newSizes[i + k] = stsz->sizes[i];		}		free(stsz->sizes);		stsz->sizes = newSizes;		stsz->alloc_size = 1 + stsz->sampleCount;	}	stsz->sampleCount++;	return GF_OK;}GF_Err stbl_AddRAP(GF_SyncSampleBox *stss, u32 sampleNumber){	u32 i, k;	u32 *newNumbers;	if (!stss || !sampleNumber) return GF_BAD_PARAM;	if (stss->sampleNumbers == NULL) {		stss->sampleNumbers = (u32*)malloc(sizeof(u32));		if (!stss->sampleNumbers) return GF_OUT_OF_MEM;		stss->sampleNumbers[0] = sampleNumber;		stss->entryCount = 1;		return GF_OK;	}	newNumbers = (u32*)malloc(sizeof(u32) * (stss->entryCount + 1));	if (!newNumbers) return GF_OUT_OF_MEM;	if (stss->sampleNumbers[stss->entryCount-1] < sampleNumber) {		memcpy(newNumbers, stss->sampleNumbers, sizeof(u32)*stss->entryCount);		newNumbers[stss->entryCount] = sampleNumber;	} else {		//the table is in increasing order of sampleNumber		k = 0;		for (i = 0; i < stss->entryCount; i++) {			if (stss->sampleNumbers[i] >= sampleNumber) {				newNumbers[i + k] = sampleNumber;				k = 1;			}			newNumbers[i + k] = stss->sampleNumbers[i] + k;		}	}	free(stss->sampleNumbers);	stss->sampleNumbers = newNumbers;	//update our list	stss->entryCount ++;	return GF_OK;}GF_Err stbl_AddRedundant(GF_SampleTableBox *stbl, u32 sampleNumber){	GF_SampleDependencyTypeBox *sdtp;	if (stbl->SampleDep == NULL) {		stbl->SampleDep = (GF_SampleDependencyTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SDTP);		if (!stbl->SampleDep) return GF_OUT_OF_MEM;	}	sdtp = stbl->SampleDep;

⌨️ 快捷键说明

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