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

📄 stbl_write.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
	stsz->sizes[stsz->sampleCount-1] += data_size;	return GF_OK;}#endif	//GPAC_READ_ONLYvoid stbl_AppendTime(GF_SampleTableBox *stbl, u32 duration){	GF_SttsEntry *ent;	u32 count;	count = gf_list_count(stbl->TimeToSample->entryList);	if (count) {		ent = (GF_SttsEntry *)gf_list_get(stbl->TimeToSample->entryList, count-1);		if (ent->sampleDelta == duration) {			ent->sampleCount += 1;			return;		}	}	//nope need a new entry	ent = (GF_SttsEntry *)malloc(sizeof(GF_SttsEntry));	ent->sampleCount = 1;	ent->sampleDelta = duration;	gf_list_add(stbl->TimeToSample->entryList, ent);}void stbl_AppendSize(GF_SampleTableBox *stbl, u32 size){	u32 *new_sizes, i;	if (!stbl->SampleSize->sampleCount) {		stbl->SampleSize->sampleSize = size;		stbl->SampleSize->sampleCount = 1;		return;	}	if (stbl->SampleSize->sampleSize && (stbl->SampleSize->sampleSize==size)) {		stbl->SampleSize->sampleCount += 1;		return;	}	//realloc	new_sizes = (u32 *)malloc(sizeof(u32)*(stbl->SampleSize->sampleCount+1));	if (stbl->SampleSize->sizes) {		memcpy(new_sizes, stbl->SampleSize->sizes, sizeof(u32)*stbl->SampleSize->sampleCount);		free(stbl->SampleSize->sizes);	} else {		for (i=0; i<stbl->SampleSize->sampleCount;i++) new_sizes[i] = stbl->SampleSize->sampleSize;	}	stbl->SampleSize->sampleSize = 0;	new_sizes[stbl->SampleSize->sampleCount] = size;	stbl->SampleSize->sampleCount += 1;	stbl->SampleSize->sizes = new_sizes;}void stbl_AppendChunk(GF_SampleTableBox *stbl, u64 offset){	GF_ChunkOffsetBox *stco;	GF_ChunkLargeOffsetBox *co64;	u32 *new_offsets, i;	u64 *off_64;	//we may have to convert the table...	if (stbl->ChunkOffset->type==GF_ISOM_BOX_TYPE_STCO) {		stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset;		if (offset>0xFFFFFFFF) {			co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64);			co64->entryCount = stco->entryCount + 1;			co64->offsets = (u64*)malloc(sizeof(u64) * co64->entryCount);			for (i=0; i<stco->entryCount; i++) co64->offsets[i] = stco->offsets[i];			co64->offsets[i] = offset;			gf_isom_box_del(stbl->ChunkOffset);			stbl->ChunkOffset = (GF_Box *) co64;			return;		}		//we're fine		new_offsets = (u32*)malloc(sizeof(u32)*(stco->entryCount+1));		for (i=0; i<stco->entryCount; i++) new_offsets[i] = stco->offsets[i];		new_offsets[i] = (u32) offset;		if (stco->offsets) free(stco->offsets);		stco->offsets = new_offsets;		stco->entryCount += 1;	}	//large offsets	else {		co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset;		off_64 = (u64*)malloc(sizeof(u32)*(co64->entryCount+1));		for (i=0; i<co64->entryCount; i++) off_64[i] = co64->offsets[i];		off_64[i] = offset;		if (co64->offsets) free(co64->offsets);		co64->offsets = off_64;		co64->entryCount += 1;	}}void stbl_AppendSampleToChunk(GF_SampleTableBox *stbl, u32 DescIndex, u32 samplesInChunk){	u32 count, nextChunk;	GF_StscEntry *ent;	count = gf_list_count(stbl->SampleToChunk->entryList);	nextChunk = ((GF_ChunkOffsetBox *) stbl->ChunkOffset)->entryCount;	if (count) {		ent = (GF_StscEntry *)gf_list_get(stbl->SampleToChunk->entryList, count-1);		//good we can use this one		if ( (ent->sampleDescriptionIndex == DescIndex) && (ent->samplesPerChunk==samplesInChunk)) 			return;		//set the next chunk btw ...		ent->nextChunk = nextChunk;	}	//ok we need a new entry - this assumes this function is called AFTER AppendChunk	GF_SAFEALLOC(ent, GF_StscEntry);	ent->firstChunk = nextChunk;	ent->sampleDescriptionIndex = DescIndex;	ent->samplesPerChunk = samplesInChunk;	gf_list_add(stbl->SampleToChunk->entryList, ent);}//called AFTER AddSizevoid stbl_AppendRAP(GF_SampleTableBox *stbl, u8 isRap){	u32 *new_raps, i;	//no sync table	if (!stbl->SyncSample) {		//all samples RAP - no table		if (isRap) return;		//nope, create one		stbl->SyncSample = (GF_SyncSampleBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSS);		if (stbl->SampleSize->sampleCount > 1) {			stbl->SyncSample->sampleNumbers = (u32*)malloc(sizeof(u32) * (stbl->SampleSize->sampleCount-1));			for (i=0; i<stbl->SampleSize->sampleCount-1; i++) 				stbl->SyncSample->sampleNumbers[i] = i+1;		}		stbl->SyncSample->entryCount = stbl->SampleSize->sampleCount-1;		return;	}	if (!isRap) return;	new_raps = (u32*)malloc(sizeof(u32) * (stbl->SyncSample->entryCount + 1));	for (i=0; i<stbl->SyncSample->entryCount; i++) new_raps[i] = stbl->SyncSample->sampleNumbers[i];	new_raps[i] = stbl->SampleSize->sampleCount;	if (stbl->SyncSample->sampleNumbers) free(stbl->SyncSample->sampleNumbers);	stbl->SyncSample->sampleNumbers = new_raps;	stbl->SyncSample->entryCount += 1;}void stbl_AppendPadding(GF_SampleTableBox *stbl, u8 padding){	u32 i;	u8 *pad_bits;	if (!stbl->PaddingBits) stbl->PaddingBits = (GF_PaddingBitsBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FADB);	pad_bits = (u8*)malloc(sizeof(u8) * stbl->SampleSize->sampleCount);	memset(pad_bits, 0, sizeof(pad_bits));//	for (i=0; i<stbl->SampleSize->sampleCount; i++) pad_bits[i] = 0;	for (i=0; i<stbl->PaddingBits->SampleCount; i++) pad_bits[i] = stbl->PaddingBits->padbits[i];	pad_bits[stbl->SampleSize->sampleCount-1] = padding;	if (stbl->PaddingBits->padbits) free(stbl->PaddingBits->padbits);	stbl->PaddingBits->padbits = pad_bits;	stbl->PaddingBits->SampleCount = stbl->SampleSize->sampleCount;}void stbl_AppendCTSOffset(GF_SampleTableBox *stbl, u32 CTSOffset){	u32 count;	GF_DttsEntry *ent;	if (!stbl->CompositionOffset) stbl->CompositionOffset = (GF_CompositionOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CTTS);	count = gf_list_count(stbl->CompositionOffset->entryList);	if (count) {		ent = (GF_DttsEntry *)gf_list_get(stbl->CompositionOffset->entryList, count-1);		if (ent->decodingOffset == CTSOffset) {			ent->sampleCount ++;			return;		}	}	ent = (GF_DttsEntry *)malloc(sizeof(GF_DttsEntry));	ent->sampleCount = 1;	ent->decodingOffset = CTSOffset;	gf_list_add(stbl->CompositionOffset->entryList, ent);}void stbl_AppendDegradation(GF_SampleTableBox *stbl, u16 DegradationPriority){	if (!stbl->DegradationPriority) stbl->DegradationPriority = (GF_DegradationPriorityBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STDP);	stbl->DegradationPriority->priorities = (u16 *)realloc(stbl->DegradationPriority->priorities, sizeof(u16) * stbl->SampleSize->sampleCount);	stbl->DegradationPriority->priorities[stbl->SampleSize->sampleCount-1] = DegradationPriority;	stbl->DegradationPriority->entryCount = stbl->SampleSize->sampleCount;}void stbl_AppendDepType(GF_SampleTableBox *stbl, u32 DepType){	if (!stbl->SampleDep) stbl->SampleDep= (GF_SampleDependencyTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SDTP);	stbl->SampleDep->sample_info = (u8*)realloc(stbl->SampleDep->sample_info, sizeof(u8)*stbl->SampleSize->sampleCount );	stbl->SampleDep->sample_info[stbl->SampleDep->sampleCount] = DepType;	stbl->SampleDep->sampleCount = stbl->SampleSize->sampleCount;}//This functions unpack the offset for easy editing, eg each sample//is contained in one chunk...GF_Err stbl_UnpackOffsets(GF_SampleTableBox *stbl){	GF_Err e;	u8 isEdited;	u32 i, chunkNumber, sampleDescIndex;	u64 dataOffset;	GF_StscEntry *ent;	GF_ChunkOffsetBox *stco_tmp;	GF_ChunkLargeOffsetBox *co64_tmp;	GF_SampleToChunkBox *stsc_tmp;	if (!stbl) return GF_ISOM_INVALID_FILE;	//we should have none of the mandatory boxes (allowed in the spec)	if (!stbl->ChunkOffset && !stbl->SampleDescription && !stbl->SampleSize && !stbl->SampleToChunk && !stbl->TimeToSample)		return GF_OK;	/*empty track (just created)*/	if (!stbl->SampleToChunk && !stbl->TimeToSample) return GF_OK;	//or all the mandatory ones ...	if (!stbl->ChunkOffset || !stbl->SampleDescription || !stbl->SampleSize || !stbl->SampleToChunk || !stbl->TimeToSample)		return GF_ISOM_INVALID_FILE;	//do we need to unpack? Not if we have only one sample per chunk.	if (stbl->SampleSize->sampleCount == gf_list_count(stbl->SampleToChunk->entryList)) return GF_OK;	//create a new SampleToChunk table	stsc_tmp = (GF_SampleToChunkBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSC);	//check the offset type and create a new table...	if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {		co64_tmp = NULL;		stco_tmp = (GF_ChunkOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STCO);		stco_tmp->entryCount = stbl->SampleSize->sampleCount;		stco_tmp->offsets = (u32*)malloc(stco_tmp->entryCount * sizeof(u32));	} else if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_CO64) {		stco_tmp = NULL;		co64_tmp = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64);		co64_tmp->entryCount = stbl->SampleSize->sampleCount;		co64_tmp->offsets = (u64*)malloc(co64_tmp->entryCount * sizeof(u64));	} else {		return GF_ISOM_INVALID_FILE;	}	ent = NULL;	//OK write our two tables...	for (i = 0; i < stbl->SampleSize->sampleCount; i++) {		//get the data info for the sample		e = stbl_GetSampleInfos(stbl, i+1, &dataOffset, &chunkNumber, &sampleDescIndex, &isEdited);		if (e) goto err_exit;		ent = (GF_StscEntry*)malloc(sizeof(GF_StscEntry));		ent->isEdited = 0;		ent->sampleDescriptionIndex = sampleDescIndex;		//here's the trick: each sample is in ONE chunk		ent->firstChunk = i+1;		ent->nextChunk = i+2;		ent->samplesPerChunk = 1;		e = gf_list_add(stsc_tmp->entryList, ent);		if (e) goto err_exit;		if (stco_tmp) {			stco_tmp->offsets[i] = (u32) dataOffset;		} else {			co64_tmp->offsets[i] = dataOffset;		}	}	//close the list	if (ent) ent->nextChunk = 0;		//done, remove our previous tables	gf_isom_box_del(stbl->ChunkOffset);	gf_isom_box_del((GF_Box *)stbl->SampleToChunk);	//and set these ones...	if (stco_tmp) {		stbl->ChunkOffset = (GF_Box *)stco_tmp;	} else {		stbl->ChunkOffset = (GF_Box *)co64_tmp;	}	stbl->SampleToChunk = stsc_tmp;	stbl->SampleToChunk->currentEntry = (GF_StscEntry*)gf_list_get(stbl->SampleToChunk->entryList, 0);	stbl->SampleToChunk->currentIndex = 0;	stbl->SampleToChunk->currentChunk = 0;	stbl->SampleToChunk->firstSampleInCurrentChunk = 0;	return GF_OK;err_exit:	if (stco_tmp) gf_isom_box_del((GF_Box *) stco_tmp);	if (co64_tmp) gf_isom_box_del((GF_Box *) co64_tmp);	if (stsc_tmp) gf_isom_box_del((GF_Box *) stsc_tmp);	return e;}#ifndef GPAC_READ_ONLYstatic GFINLINE GF_Err stbl_AddOffset(GF_Box **a, u64 offset){	GF_ChunkOffsetBox *stco;	GF_ChunkLargeOffsetBox *co64;	u32 i;	if ((*a)->type == GF_ISOM_BOX_TYPE_STCO) {		stco = (GF_ChunkOffsetBox *) *a;		//if dataOffset is bigger than 0xFFFFFFFF, move to LARGE offset		if (offset > 0xFFFFFFFF) {			co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64);			if (!co64) return GF_OUT_OF_MEM;			co64->entryCount = stco->entryCount + 1;			co64->offsets = (u64*)malloc(co64->entryCount * sizeof(u64));			if (!co64->offsets) {				gf_isom_box_del((GF_Box *)co64);				return GF_OUT_OF_MEM;			}			for (i = 0; i< co64->entryCount - 1; i++) {				co64->offsets[i] = (u64) stco->offsets[i];			}			co64->offsets[i] = offset;			//delete the box...			gf_isom_box_del(*a);			*a = (GF_Box *)co64;			return GF_OK;		}		//OK, stick with regular...		stco->offsets = (u32*)realloc(stco->offsets, (stco->entryCount + 1) * sizeof(u32));		if (!stco->offsets) return GF_OUT_OF_MEM;		stco->offsets[stco->entryCount] = (u32) offset;		stco->entryCount += 1;	} else {		//this is a large offset		co64 = (GF_ChunkLargeOffsetBox *) *a;		co64->offsets = (u64*)realloc(co64->offsets, (co64->entryCount + 1) * sizeof(u64));		if (!co64->offsets) return GF_OUT_OF_MEM;		co64->offsets[co64->entryCount] = offset;		co64->entryCount += 1;	}	return GF_OK;}//This function packs the offset after easy editing, eg samples//are re-arranged in chunks according to the chunkOffsets//NOTE: this has to be called once interleaving or whatever is done and //the final MDAT is written!!!GF_Err stbl_SetChunkAndOffset(GF_SampleTableBox *stbl, u32 sampleNumber, u32 StreamDescIndex, GF_SampleToChunkBox *the_stsc, GF_Box **the_stco, u64 data_offset, u8 forceNewChunk){	GF_Err e;	u32 count;	u8 newChunk;	GF_StscEntry *ent, *newEnt;	if (!stbl) return GF_ISOM_INVALID_FILE;	newChunk = 0;	//do we need a new chunk ??? For that, we need	//1 - make sure this sample data is contiguous to the prev one	//force new chunk is set during writing (flat / interleaved)	//it is set to 1 when data is not contiguous in the media (eg, interleaving)	//when writing flat files, it is never used	if (forceNewChunk) newChunk = 1;	//2 - make sure we have the table inited (i=0)	if (! the_stsc->currentEntry) {		newChunk = 1;	} else {	//3 - make sure we do not exceed the MaxSamplesPerChunk and we have the same descIndex		if (StreamDescIndex != the_stsc->currentEntry->sampleDescriptionIndex) 			newChunk = 1;		if (stbl->MaxSamplePerChunk && the_stsc->currentEntry->samplesPerChunk == stbl->MaxSamplePerChunk) 			newChunk = 1;	}	//no need for a new chunk	if (!newChunk) {		the_stsc->currentEntry->samplesPerChunk += 1;		return GF_OK;	}	//OK, we have to create a new chunk...	count = gf_list_count(the_stsc->entryList);	//check if we can remove the current sampleToChunk entry (same properties)	if (count > 1) {		ent = (GF_StscEntry*)gf_list_get(the_stsc->entryList, count - 2);		if ( (ent->sampleDescriptionIndex == the_stsc->currentEntry->sampleDescriptionIndex)			&& (ent->samplesPerChunk == the_stsc->currentEntry->samplesPerChunk)			) {			//OK, it's the same SampleToChunk, so delete it			ent->nextChunk = the_stsc->currentEntry->firstChunk;			free(the_stsc->currentEntry);			gf_list_rem(the_stsc->entryList, count - 1);			the_stsc->currentEntry = ent;		}	}	//add our offset	e = stbl_AddOffset(the_stco, data_offset);	if (e) return e;	//create a new entry (could be the first one, BTW)	newEnt = (GF_StscEntry*)malloc(sizeof(GF_StscEntry));	//get the first chunk value	if ((*the_stco)->type == GF_ISOM_BOX_TYPE_STCO) {		newEnt->firstChunk = ((GF_ChunkOffsetBox *) (*the_stco) )->entryCount;	} else {		newEnt->firstChunk = ((GF_ChunkLargeOffsetBox *) (*the_stco) )->entryCount;	}	newEnt->sampleDescriptionIndex = StreamDescIndex;	newEnt->samplesPerChunk = 1;	newEnt->nextChunk = 0;	gf_list_add(the_stsc->entryList, newEnt);	//if we already have an entry, adjust its next chunk to point to our new chunk	if (the_stsc->currentEntry)		the_stsc->currentEntry->nextChunk = newEnt->firstChunk;	the_stsc->currentEntry = newEnt;	return GF_OK;}GF_Err gf_isom_refresh_size_info(GF_ISOFile *file, u32 trackNumber){	u32 i, size;	GF_TrackBox *trak;	GF_SampleSizeBox *stsz;	trak = gf_isom_get_track_from_file(file, trackNumber);	if (!trak) return GF_BAD_PARAM;	stsz = trak->Media->information->sampleTable->SampleSize;	if (stsz->sampleSize || !stsz->sampleCount) return GF_OK;	size = stsz->sizes[0];	for (i=1; i<stsz->sampleCount; i++) {		if (stsz->sizes[i] != size) {			size = 0;			break;		}	}	if (size) {		free(stsz->sizes);		stsz->sizes = NULL;		stsz->sampleSize = size;	}	return GF_OK;}#endif //GPAC_READ_ONLY

⌨️ 快捷键说明

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