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

📄 isom_store.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *			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#define GPAC_ISOM_CPRT_NOTICE "IsoMedia File Produced with GPAC "GPAC_VERSIONstatic GF_Err gf_isom_insert_copyright(GF_ISOFile *movie){	u32 i;	GF_Box *a;	GF_FreeSpaceBox *_free;	i=0;	while ((a = (GF_Box *)gf_list_enum(movie->TopBoxes, &i))) {		if (a->type == GF_ISOM_BOX_TYPE_FREE) {			_free = (GF_FreeSpaceBox *)a;			if (_free->dataSize) {				if (!strcmp(_free->data, GPAC_ISOM_CPRT_NOTICE)) return GF_OK;				if (strstr(_free->data, "File Produced with GPAC")) {					free(_free->data);					_free->data = strdup(GPAC_ISOM_CPRT_NOTICE);					_free->dataSize = strlen(_free->data);					return GF_OK;				}			}		}	}	a = gf_isom_box_new(GF_ISOM_BOX_TYPE_FREE);	if (!a) return GF_OUT_OF_MEM;	_free = (GF_FreeSpaceBox *)a;	_free->dataSize = strlen(GPAC_ISOM_CPRT_NOTICE) + 1;	_free->data = strdup(GPAC_ISOM_CPRT_NOTICE);	if (!_free->data) return GF_OUT_OF_MEM;	return gf_list_add(movie->TopBoxes, _free);}typedef struct {	/*the curent sample of this track*/	u32 sampleNumber;	/*timeScale of the media (for interleaving)*/	u32 timeScale;	/*this is for generic, time-based interleaving. Expressed in Media TimeScale*/	u32 chunkDur;	u64 DTSprev;	u8 isDone;	u64 prev_offset;	GF_MediaBox *mdia;	/*each writer has a sampleToChunck and ChunkOffset tables	these tables are filled during emulation mode and then will	replace the table in the GF_SampleTableBox*/	GF_SampleToChunkBox *stsc;	/*we don't know if it's a large offset or not*/	GF_Box *stco;} TrackWriter;typedef struct{	char *buffer;	u32 size;	GF_ISOFile *movie;	u32 total_samples, nb_done;} MovieWriter;void CleanWriters(GF_List *writers){	TrackWriter *writer;	while (gf_list_count(writers)) {		writer = (TrackWriter*)gf_list_get(writers, 0);		gf_isom_box_del(writer->stco);		gf_isom_box_del((GF_Box *)writer->stsc);		free(writer);		gf_list_rem(writers, 0);	}}void ResetWriters(GF_List *writers){	u32 i;	TrackWriter *writer;	i=0;	while ((writer = (TrackWriter *)gf_list_enum(writers, &i))) {		writer->isDone = 0;		writer->chunkDur = 0;		writer->DTSprev = 0;		writer->sampleNumber = 1;		gf_isom_box_del((GF_Box *)writer->stsc);		writer->stsc = (GF_SampleToChunkBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSC);		if (writer->stco->type == GF_ISOM_BOX_TYPE_STCO) {			free(((GF_ChunkOffsetBox *)writer->stco)->offsets);			((GF_ChunkOffsetBox *)writer->stco)->offsets = NULL;			((GF_ChunkOffsetBox *)writer->stco)->entryCount = 0;		} else {			free(((GF_ChunkLargeOffsetBox *)writer->stco)->offsets);			((GF_ChunkLargeOffsetBox *)writer->stco)->offsets = NULL;			((GF_ChunkLargeOffsetBox *)writer->stco)->entryCount = 0;		}	}}GF_Err SetupWriters(MovieWriter *mw, GF_List *writers, u8 interleaving){	u32 i, trackCount;	TrackWriter *writer;	GF_TrackBox *trak;	GF_ISOFile *movie = mw->movie;	mw->total_samples = mw->nb_done = 0;	if (!movie->moov) return GF_OK;	trackCount = gf_list_count(movie->moov->trackList);	for (i = 0; i < trackCount; i++) {		trak = gf_isom_get_track(movie->moov, i+1);				GF_SAFEALLOC(writer, TrackWriter);		if (!writer) goto exit;		writer->sampleNumber = 1;		writer->mdia = trak->Media;		writer->timeScale = trak->Media->mediaHeader->timeScale;		writer->isDone = 0;		writer->DTSprev = 0;		writer->chunkDur = 0;		writer->stsc = (GF_SampleToChunkBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSC);		if (trak->Media->information->sampleTable->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) {			writer->stco = gf_isom_box_new(GF_ISOM_BOX_TYPE_STCO);		} else {			writer->stco = gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64);		}		/*stops from chunk escape*/		if (interleaving) writer->mdia->information->sampleTable->MaxSamplePerChunk = 0;		/*for progress, assume only one descIndex*/		if (Media_IsSelfContained(writer->mdia, 1)) mw->total_samples += trak->Media->information->sampleTable->SampleSize->sampleCount;		/*optimization for interleaving: put audio last (this can be overriden by priorities)*/		if (movie->storageMode != GF_ISOM_STORE_INTERLEAVED) {			gf_list_add(writers, writer);			} else {			if (writer->mdia->information->InfoHeader && writer->mdia->information->InfoHeader->type == GF_ISOM_BOX_TYPE_SMHD) {				gf_list_add(writers, writer);				} else {				gf_list_insert(writers, writer, 0);				}		}	}	return GF_OK;exit:	CleanWriters(writers);	return GF_OUT_OF_MEM;}static void ShiftMetaOffset(GF_MetaBox *meta, u64 offset){	u32 i, count;	if (!meta->item_locations) return;	count = gf_list_count(meta->item_locations->location_entries);	for (i=0; i<count; i++) {		GF_ItemLocationEntry *iloc = (GF_ItemLocationEntry *)gf_list_get(meta->item_locations->location_entries, i);		if (iloc->data_reference_index) continue;		if (!iloc->base_offset) {			GF_ItemExtentEntry *entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0);			if (entry && !entry->extent_length && !entry->original_extent_offset && (gf_list_count(iloc->extent_entries)==1) )				continue;		}		iloc->base_offset += offset;	}}static GF_Err ShiftOffset(GF_ISOFile *file, GF_List *writers, u64 offset){	u32 i, j, k, l, last;	TrackWriter *writer;	GF_StscEntry *ent;	GF_ChunkOffsetBox *stco;	GF_ChunkLargeOffsetBox *co64;	if (file->meta) ShiftMetaOffset(file->meta, offset);	if (file->moov && file->moov->meta) ShiftMetaOffset(file->moov->meta, offset);	i=0;	while ((writer = (TrackWriter *)gf_list_enum(writers, &i))) {		if (writer->mdia->mediaTrack->meta) ShiftMetaOffset(writer->mdia->mediaTrack->meta, offset);		//we have to proceed entry by entry in case a part of the media is not self-contained...		j=0;		while ((ent = (GF_StscEntry *)gf_list_enum(writer->stsc->entryList, &j))) {			if (!Media_IsSelfContained(writer->mdia, ent->sampleDescriptionIndex)) continue;			//OK, get the chunk(s) number(s) and "shift" its (their) offset(s).			if (writer->stco->type == GF_ISOM_BOX_TYPE_STCO) {				stco = (GF_ChunkOffsetBox *) writer->stco;				//be carefull for the last entry, nextChunk is set to 0 in edit mode...				last = ent->nextChunk ? ent->nextChunk : stco->entryCount + 1;				for (k = ent->firstChunk; k < last; k++) {					if (stco->offsets[k-1] + offset > 0xFFFFFFFF) {						//too bad, rewrite the table....						co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64);						if (!co64) return GF_OUT_OF_MEM;						co64->entryCount = stco->entryCount;						co64->offsets = (u64*)malloc(co64->entryCount * sizeof(u64));						if (!co64) {							gf_isom_box_del((GF_Box *)co64);							return GF_OUT_OF_MEM;						}						//duplicate the table 						for (l = 0; l < co64->entryCount; l++) {							co64->offsets[l] = (u64) stco->offsets[l];							if (l + 1 == k) co64->offsets[l] += offset;						}						//and replace our box						gf_isom_box_del(writer->stco);						writer->stco = (GF_Box *)co64;					} else {						stco->offsets[k-1] += (u32) offset;					}				}			} else {				co64 = (GF_ChunkLargeOffsetBox *) writer->stco;				//be carefull for the last entry ...				last = ent->nextChunk ? ent->nextChunk : co64->entryCount + 1;				for (k = ent->firstChunk; k < last; k++) {					co64->offsets[k-1] += offset;				}			}		}	}		return GF_OK;}//replace the chunk and offset tables...static GF_Err WriteMoovAndMeta(GF_ISOFile *movie, GF_List *writers, GF_BitStream *bs){	u32 i;	TrackWriter *writer;	GF_Err e;	GF_Box *stco;	GF_SampleToChunkBox *stsc;	if (movie->meta) {		//write the moov box...		e = gf_isom_box_size((GF_Box *)movie->meta);		if (e) return e;		e = gf_isom_box_write((GF_Box *)movie->meta, bs);		if (e) return e;	}	if (movie->moov) {		//switch all our tables		i=0;		while ((writer = (TrackWriter*)gf_list_enum(writers, &i))) {			//don't delete them !!!			stsc = writer->mdia->information->sampleTable->SampleToChunk;			stco = writer->mdia->information->sampleTable->ChunkOffset;			writer->mdia->information->sampleTable->SampleToChunk = writer->stsc;			writer->mdia->information->sampleTable->ChunkOffset = writer->stco;			writer->stco = stco;			writer->stsc = stsc;		}		//write the moov box...		e = gf_isom_box_size((GF_Box *)movie->moov);		if (e) return e;		e = gf_isom_box_write((GF_Box *)movie->moov, bs);		//and re-switch our table. We have to do it that way because it is 		//needed when the moov is written first		i=0;		while ((writer = (TrackWriter*)gf_list_enum(writers, &i))) {			//don't delete them !!!			stsc = writer->stsc;			stco = writer->stco;			writer->stsc = writer->mdia->information->sampleTable->SampleToChunk;			writer->stco = writer->mdia->information->sampleTable->ChunkOffset;			writer->mdia->information->sampleTable->SampleToChunk = stsc;			writer->mdia->information->sampleTable->ChunkOffset = stco;		}		if (e) return e;	}	return GF_OK;}//compute the size of the moov as it will be written.u64 GetMoovAndMetaSize(GF_ISOFile *movie, GF_List *writers){	u32 i;	u64 size;	TrackWriter *writer;	size = 0;	if (movie->moov) {		gf_isom_box_size((GF_Box *)movie->moov);		size = movie->moov->size;		if (size > 0xFFFFFFFF) size += 8;		i=0;		while ((writer = (TrackWriter*)gf_list_enum(writers, &i))) {			size -= writer->mdia->information->sampleTable->ChunkOffset->size;			size -= writer->mdia->information->sampleTable->SampleToChunk->size;			gf_isom_box_size((GF_Box *)writer->stsc);			gf_isom_box_size(writer->stco);			size += writer->stsc->size;			size += writer->stco->size;		}	}	if (movie->meta) {		u64 msize;		gf_isom_box_size((GF_Box *)movie->meta);		msize = movie->meta->size;		if (msize > 0xFFFFFFFF) msize += 8;		size += msize;	}	return size;}//Write a sample to the file - this is only called for self-contained mediaGF_Err WriteSample(MovieWriter *mw, u32 size, u64 offset, u8 isEdited, GF_BitStream *bs){	GF_DataMap *map;	u32 bytes;	if (size>mw->size) {		mw->buffer = (char*)realloc(mw->buffer, size);		mw->size = size;	}	if (!mw->buffer) return GF_OUT_OF_MEM;	if (isEdited) {		map = mw->movie->editFileMap;	} else {		map = mw->movie->movieFileMap;	}	//get the payload...	bytes = gf_isom_datamap_get_data(map, mw->buffer, size, offset);	if (bytes != size) return GF_IO_ERR;	//write it to our stream...	bytes = gf_bs_write_data(bs, mw->buffer, size);	if (bytes != size) return GF_IO_ERR;	mw->nb_done++;	gf_set_progress("ISO File Writing", mw->nb_done, mw->total_samples);	return GF_OK;}GF_Err DoWriteMeta(GF_ISOFile *file, GF_MetaBox *meta, GF_BitStream *bs, Bool Emulation, u64 baseOffset, u64 *mdatSize){	GF_ItemExtentEntry *entry;	u64 maxExtendOffset, maxExtendSize;	u32 i, j, count;	maxExtendOffset = 0;	maxExtendSize = 0;	*mdatSize = 0;	if (!meta->item_locations) return GF_OK;	count = gf_list_count(meta->item_locations->location_entries);	for (i=0; i<count; i++) {		u64 it_size;		GF_ItemLocationEntry *iloc = (GF_ItemLocationEntry *)gf_list_get(meta->item_locations->location_entries, i);		/*get item info*/		GF_ItemInfoEntryBox *iinf = NULL;		j=0;		while ((iinf = (GF_ItemInfoEntryBox *)gf_list_enum(meta->item_infos->item_infos, &j))) {			if (iinf->item_ID==iloc->item_ID) break;			iinf = NULL;		}		if (!iloc->base_offset && (gf_list_count(iloc->extent_entries)==1)) {			entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0);			if (!entry->extent_length && !entry->original_extent_offset) {				entry->extent_offset = 0;				continue;			}		}		it_size = 0;		/*for self contained only*/		if (!iloc->data_reference_index) {			iloc->base_offset = baseOffset;				/*new resource*/			if (iinf->full_path) {				FILE *src = gf_f64_open(iinf->full_path, "rb");				if (!src) continue;				gf_f64_seek(src, 0, SEEK_END);				it_size = gf_f64_tell(src);				gf_f64_seek(src, 0, SEEK_SET);				if (maxExtendSize<it_size) maxExtendSize = it_size;				if (!gf_list_count(iloc->extent_entries)) {					GF_SAFEALLOC(entry, GF_ItemExtentEntry);					gf_list_add(iloc->extent_entries, entry);				}				entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0);				entry->extent_offset = 0;				entry->extent_length = it_size;

⌨️ 快捷键说明

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