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

📄 isom_write.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *			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_ONLYGF_Err CanAccessMovie(GF_ISOFile *movie, u32 Mode){	if (!movie) return GF_BAD_PARAM;	if (movie->openMode < Mode) return GF_ISOM_INVALID_MODE;#ifndef	GF_ISOM_NO_FRAGMENTS	if (movie->FragmentsFlags & GF_ISOM_FRAG_WRITE_READY) return GF_ISOM_INVALID_MODE;#endif	return GF_OK;}static GF_Err unpack_track(GF_TrackBox *trak){	GF_Err e = GF_OK;	if (!trak->is_unpacked) {		e = stbl_UnpackOffsets(trak->Media->information->sampleTable);		trak->is_unpacked = 1;	}	return e;}GF_Err FlushCaptureMode(GF_ISOFile *movie){	GF_Err e;	if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_OK;	/*make sure nothing was added*/	if (gf_bs_get_position(movie->editFileMap->bs)) return GF_OK;	/*add all first boxes*/	if (movie->brand) {		e = gf_isom_box_size((GF_Box *)movie->brand);		if (e) return e;		e = gf_isom_box_write((GF_Box *)movie->brand, movie->editFileMap->bs);		if (e) return e;	}	if (movie->pdin) {		e = gf_isom_box_size((GF_Box *)movie->pdin);		if (e) return e;		e = gf_isom_box_write((GF_Box *)movie->pdin, movie->editFileMap->bs);		if (e) return e;	}	/*we have a trick here: the data will be stored on the fly, so the first	thing in the file is the MDAT. As we don't know if we have a large file (>4 GB) or not	do as if we had one and write 16 bytes: 4 (type) + 4 (size) + 8 (largeSize)...*/	gf_bs_write_int(movie->editFileMap->bs, 0, 128);	return GF_OK;}static GF_Err CheckNoData(GF_ISOFile *movie){	if (movie->openMode != GF_ISOM_OPEN_WRITE) return GF_OK;	if (gf_bs_get_position(movie->editFileMap->bs)) return GF_BAD_PARAM;	return GF_OK;}/**************************************************************					File Writing / Editing**************************************************************///quick function to add an IOD/OD to the file if not present (iods is optional)GF_Err AddMovieIOD(GF_MovieBox *moov, u8 isIOD){	GF_Descriptor *od;	GF_ObjectDescriptorBox *iods;		//do we have an IOD ?? If not, create one.	if (moov->iods) return GF_OK;	if (isIOD) {		od = gf_odf_desc_new(GF_ODF_ISOM_IOD_TAG);	} else {		od = gf_odf_desc_new(GF_ODF_ISOM_OD_TAG);	}	if (!od) return GF_OUT_OF_MEM;	((GF_IsomObjectDescriptor *)od)->objectDescriptorID = 1;	iods = (GF_ObjectDescriptorBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_IODS);	iods->descriptor = od;	return moov_AddBox((GF_Box*)moov, (GF_Box *)iods);}//add a track to the root ODGF_EXPORTGF_Err gf_isom_add_track_to_root_od(GF_ISOFile *movie, u32 trackNumber){	GF_Err e;	GF_ES_ID_Inc *inc;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	gf_isom_insert_moov(movie);		if (!movie->moov->iods) AddMovieIOD(movie->moov, 0);	if (gf_isom_is_track_in_root_od(movie, trackNumber) == 1) return GF_OK;	inc = (GF_ES_ID_Inc *) gf_odf_desc_new(GF_ODF_ESD_INC_TAG);	inc->trackID = gf_isom_get_track_id(movie, trackNumber);	if (!inc->trackID) {		gf_odf_desc_del((GF_Descriptor *)inc);		return movie->LastError;	}	if ( (movie->LastError = gf_isom_add_desc_to_root_od(movie, (GF_Descriptor *)inc) ) ) {		return movie->LastError;	}	gf_odf_desc_del((GF_Descriptor *)inc);	return GF_OK;}//remove the root ODGF_Err gf_isom_remove_root_od(GF_ISOFile *movie){	GF_Err e;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	if (!movie->moov || !movie->moov->iods) return GF_OK;	gf_isom_box_del((GF_Box *)movie->moov->iods);	movie->moov->iods = NULL;	return GF_OK;}//remove a track to the root ODGF_Err gf_isom_remove_track_from_root_od(GF_ISOFile *movie, u32 trackNumber){	GF_List *esds;	GF_ES_ID_Inc *inc;	u32 i;	GF_Err e;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	if (!movie->moov) return GF_OK;	if (!gf_isom_is_track_in_root_od(movie, trackNumber)) return GF_OK;	if (!movie->moov->iods) AddMovieIOD(movie->moov, 0);	switch (movie->moov->iods->descriptor->tag) {	case GF_ODF_ISOM_IOD_TAG:		esds = ((GF_IsomInitialObjectDescriptor *)movie->moov->iods->descriptor)->ES_ID_IncDescriptors;		break;	case GF_ODF_ISOM_OD_TAG:		esds = ((GF_IsomObjectDescriptor *)movie->moov->iods->descriptor)->ES_ID_IncDescriptors;		break;	default:		return GF_ISOM_INVALID_FILE;	}	//get the desc	i=0;	while ((inc = (GF_ES_ID_Inc*)gf_list_enum(esds, &i))) {		if (inc->trackID == gf_isom_get_track_id(movie, trackNumber)) {			gf_odf_desc_del((GF_Descriptor *)inc);			gf_list_rem(esds, i-1);			break;		}	}	//we don't remove the iod for P&Ls and other potential info	return GF_OK;}//sets the enable flag of a trackGF_EXPORTGF_Err gf_isom_set_track_enabled(GF_ISOFile *movie, u32 trackNumber, u8 enableTrack){	GF_Err e;	GF_TrackBox *trak;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	trak = gf_isom_get_track_from_file(movie, trackNumber);	if (!trak) return GF_BAD_PARAM;	if (enableTrack) {		trak->Header->flags |= 1;	} else {		trak->Header->flags &= ~1;	}	return GF_OK;}GF_Err gf_isom_set_media_language(GF_ISOFile *movie, u32 trackNumber, char *three_char_code){	GF_Err e;	GF_TrackBox *trak;	trak = gf_isom_get_track_from_file(movie, trackNumber);	if (!trak) return GF_BAD_PARAM;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	memcpy(trak->Media->mediaHeader->packedLanguage, three_char_code, sizeof(char)*3);	trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();	return GF_OK;}static void gf_isom_set_root_iod(GF_ISOFile *movie){	GF_IsomInitialObjectDescriptor *iod;	GF_IsomObjectDescriptor *od;	gf_isom_insert_moov(movie);	if (!movie->moov->iods) {		AddMovieIOD(movie->moov, 1);		return;	}	//if OD, switch to IOD	if (movie->moov->iods->descriptor->tag == GF_ODF_ISOM_IOD_TAG) return;	od = (GF_IsomObjectDescriptor *) movie->moov->iods->descriptor;	iod = (GF_IsomInitialObjectDescriptor*)malloc(sizeof(GF_IsomInitialObjectDescriptor));	memset(iod, 0, sizeof(GF_IsomInitialObjectDescriptor));	iod->ES_ID_IncDescriptors = od->ES_ID_IncDescriptors;	od->ES_ID_IncDescriptors = NULL;	//not used in root OD	iod->ES_ID_RefDescriptors = NULL;	iod->extensionDescriptors = od->extensionDescriptors;	od->extensionDescriptors = NULL;	iod->IPMP_Descriptors = od->IPMP_Descriptors;	od->IPMP_Descriptors = NULL;	iod->objectDescriptorID = od->objectDescriptorID;	iod->OCIDescriptors = od->OCIDescriptors;	od->OCIDescriptors = NULL;	iod->tag = GF_ODF_ISOM_IOD_TAG;	iod->URLString = od->URLString;	od->URLString = NULL;	gf_odf_desc_del((GF_Descriptor *) od);	movie->moov->iods->descriptor = (GF_Descriptor *)iod;}GF_Err gf_isom_add_desc_to_root_od(GF_ISOFile *movie, GF_Descriptor *theDesc){	GF_Err e;	GF_Descriptor *desc, *dupDesc;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	gf_isom_insert_moov(movie);	if (!movie->moov->iods) AddMovieIOD(movie->moov, 0);	if (theDesc->tag==GF_ODF_IPMP_TL_TAG) gf_isom_set_root_iod(movie);	desc = movie->moov->iods->descriptor;	//the type of desc is handled at the OD/IOD level, we'll be notified	//if the desc is not allowed	switch (desc->tag) {	case GF_ODF_ISOM_IOD_TAG:	case GF_ODF_ISOM_OD_TAG:		//duplicate the desc		e = gf_odf_desc_copy(theDesc, &dupDesc);		if (e) return e;		//add it (MUST BE  (I)OD level desc)		movie->LastError = gf_odf_desc_add_desc(desc, dupDesc);		if (movie->LastError) gf_odf_desc_del((GF_Descriptor *)dupDesc);		break;	default:		movie->LastError = GF_ISOM_INVALID_FILE;		break;	}	return movie->LastError;}GF_Err gf_isom_set_timescale(GF_ISOFile *movie, u32 timeScale){	GF_Err e;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	gf_isom_insert_moov(movie);		movie->moov->mvhd->timeScale = timeScale;	movie->interleavingTime = timeScale;	return GF_OK;}GF_Err gf_isom_set_pl_indication(GF_ISOFile *movie, u8 PL_Code, u8 ProfileLevel){	GF_IsomInitialObjectDescriptor *iod;	GF_Err e;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	gf_isom_set_root_iod(movie);	iod = (GF_IsomInitialObjectDescriptor *)movie->moov->iods->descriptor;	switch (PL_Code) {	case GF_ISOM_PL_AUDIO:		iod->audio_profileAndLevel = ProfileLevel;		break;	case GF_ISOM_PL_GRAPHICS:		iod->graphics_profileAndLevel = ProfileLevel;		break;	case GF_ISOM_PL_OD:		iod->OD_profileAndLevel = ProfileLevel;		break;	case GF_ISOM_PL_SCENE:		iod->scene_profileAndLevel = ProfileLevel;		break;	case GF_ISOM_PL_VISUAL:		iod->visual_profileAndLevel = ProfileLevel;		break;	case GF_ISOM_PL_INLINE:		iod->inlineProfileFlag = ProfileLevel ? 1 : 0;		break;	}	return GF_OK;}GF_Err gf_isom_set_root_od_id(GF_ISOFile *movie, u32 OD_ID){	GF_Err e;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	gf_isom_insert_moov(movie);	if (!movie->moov->iods) AddMovieIOD(movie->moov, 0);	switch (movie->moov->iods->descriptor->tag) {	case GF_ODF_ISOM_OD_TAG:		((GF_IsomObjectDescriptor *)movie->moov->iods->descriptor)->objectDescriptorID = OD_ID;		break;	case GF_ODF_ISOM_IOD_TAG:		((GF_IsomInitialObjectDescriptor *)movie->moov->iods->descriptor)->objectDescriptorID = OD_ID;		break;	default:		return GF_ISOM_INVALID_FILE;	}	return GF_OK;}GF_Err gf_isom_set_root_od_url(GF_ISOFile *movie, char *url_string){	GF_Err e;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) return e;	gf_isom_insert_moov(movie);	if (!movie->moov->iods) AddMovieIOD(movie->moov, 0);	switch (movie->moov->iods->descriptor->tag) {	case GF_ODF_ISOM_OD_TAG:		if (((GF_IsomObjectDescriptor *)movie->moov->iods->descriptor)->URLString) free(((GF_IsomObjectDescriptor *)movie->moov->iods->descriptor)->URLString);		((GF_IsomObjectDescriptor *)movie->moov->iods->descriptor)->URLString = url_string ? strdup(url_string) : NULL;		break;	case GF_ODF_ISOM_IOD_TAG:		if (((GF_IsomInitialObjectDescriptor *)movie->moov->iods->descriptor)->URLString) free(((GF_IsomInitialObjectDescriptor *)movie->moov->iods->descriptor)->URLString);		((GF_IsomInitialObjectDescriptor *)movie->moov->iods->descriptor)->URLString = url_string ? strdup(url_string) : NULL;		break;	default:		return GF_ISOM_INVALID_FILE;	}	return GF_OK;}//creates a new Track. If trackID = 0, the trackID is chosen by the API//returns the track number or 0 if errorGF_EXPORTu32 gf_isom_new_track(GF_ISOFile *movie, u32 trakID, u32 MediaType, u32 TimeScale){	GF_Err e;	u64 now;	u8 isHint;	GF_TrackBox *trak;	GF_TrackHeaderBox *tkhd;	GF_MediaBox *mdia;	e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);	if (e) {		gf_isom_set_last_error(movie, e);		return 0;	}	gf_isom_insert_moov(movie);	isHint = 0;	//we're creating a hint track... it's the same, but mode HAS TO BE EDIT	if (MediaType == GF_ISOM_MEDIA_HINT) {//		if (movie->openMode != GF_ISOM_OPEN_EDIT) return 0;		isHint = 1;	}	mdia = NULL;	tkhd = NULL;	trak = NULL;	if (trakID) {		//check if we are in ES_ID boundaries		if (!isHint && (trakID > 0xFFFF)) {			gf_isom_set_last_error(movie, GF_BAD_PARAM);			return 0;		}		//here we should look for available IDs ...		if (!RequestTrack(movie->moov, trakID)) return 0;	} else {		trakID = movie->moov->mvhd->nextTrackID;		if (!trakID) trakID = 1;		/*ESIDs are on 16 bits*/		if (! isHint && (trakID > 0xFFFF)) trakID = 1;		while (1) {			if (RequestTrack(movie->moov, trakID)) break;			trakID += 1;			if (trakID == 0xFFFFFFFF) break;		}		if (trakID == 0xFFFFFFFF) {			gf_isom_set_last_error(movie, GF_BAD_PARAM);			return 0;		}		if (! isHint && (trakID > 0xFFFF)) {			gf_isom_set_last_error(movie, GF_BAD_PARAM);			return 0;		}	}		//OK, now create a track...

⌨️ 快捷键说明

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