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

📄 data_map.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			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>#include <gpac/network.h>void gf_isom_datamap_del(GF_DataMap *ptr){	if (!ptr) return;	//then delete the structure itself....	switch (ptr->type) {	//file-based	case GF_ISOM_DATA_FILE:		gf_isom_fdm_del((GF_FileDataMap *)ptr);		break;	case GF_ISOM_DATA_FILE_MAPPING:		gf_isom_fmo_del((GF_FileMappingDataMap *)ptr);		break;	//not implemented	default:		break;	}}//Close a data entryvoid gf_isom_datamap_close(GF_MediaInformationBox *minf){	GF_DataEntryBox *ent;	if (!minf || !minf->dataHandler) return;	ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->boxList, minf->dataEntryIndex - 1);	//if ent NULL, the data entry was not used (should never happen)	if (ent == NULL) return;	//self contained, do nothing	switch (ent->type) {	case GF_ISOM_BOX_TYPE_URL:	case GF_ISOM_BOX_TYPE_URN:		if (ent->flags == 1) return;		break;	default:		return;	}	//finally close it	gf_isom_datamap_del(minf->dataHandler);	minf->dataHandler = NULL;}/*cf below, we disable filedatamap since it tricks mem usage on w32*/#if 0static Bool IsLargeFile(char *path){#ifndef _WIN32_WCE	FILE *stream;	s64 size;	stream = gf_f64_open(path, "rb");	if (!stream) return 0;	gf_f64_seek(stream, 0, SEEK_END);	size = gf_f64_tell(stream);	fclose(stream);	if (size == -1L) return 0;	if (size > 0xFFFFFFFF) return 1;#endif	return 0;}#endif//Special constructor, we need some error feedback...GF_Err gf_isom_datamap_new(const char *location, const char *parentPath, u8 mode, GF_DataMap **outDataMap){	Bool extern_file;	char *sPath;	*outDataMap = NULL;	//if nothing specified, this is a MEMORY data map	if (!location) {		//not supported yet		return GF_NOT_SUPPORTED;	}	//we need a temp file ...	if (!strcmp(location, "mp4_tmp_edit")) {#ifndef GPAC_READ_ONLY		*outDataMap = gf_isom_fdm_new_temp(parentPath);		if (! (*outDataMap)) return GF_IO_ERR;		return GF_OK;#else		return GF_NOT_SUPPORTED;#endif	}	extern_file = !gf_url_is_local(location);	if (mode == GF_ISOM_DATA_MAP_EDIT) {		//we need a local file for edition!!!		if (extern_file) return GF_ISOM_INVALID_MODE;		//OK, switch back to READ mode		mode = GF_ISOM_DATA_MAP_READ;	}	//TEMP: however, only support for file right now (we'd have to add some callback functions at some point)	if (extern_file) return GF_NOT_SUPPORTED;	sPath = gf_url_get_absolute_path(location, parentPath);	if (sPath == NULL) return GF_URL_ERROR;	if (mode == GF_ISOM_DATA_MAP_READ_ONLY) {		mode = GF_ISOM_DATA_MAP_READ;		/*It seems win32 file mapping is reported in prog mem usage -> large increases of occupancy. Should not be a pb 		but unless you want mapping, only regular IO will be used...*/#if 0		if (IsLargeFile(sPath)) {			*outDataMap = gf_isom_fdm_new(sPath, mode);		} else {			*outDataMap = gf_isom_fmo_new(sPath, mode);		}#else		*outDataMap = gf_isom_fdm_new(sPath, mode);#endif	} else {		*outDataMap = gf_isom_fdm_new(sPath, mode);	}	free(sPath);	if (! (*outDataMap)) return GF_URL_ERROR;	return GF_OK;}//Open a data entry of a track//Edit is used to switch between original and edition fileGF_Err gf_isom_datamap_open(GF_MediaBox *mdia, u32 dataRefIndex, u8 Edit){	GF_DataEntryBox *ent;	GF_MediaInformationBox *minf;	u32 SelfCont;	GF_Err e = GF_OK;	if ((mdia == NULL) || (! mdia->information) || !dataRefIndex)		return GF_ISOM_INVALID_MEDIA;	minf = mdia->information;	if (dataRefIndex > gf_list_count(minf->dataInformation->dref->boxList))		return GF_BAD_PARAM;	ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->boxList, dataRefIndex - 1);	if (ent == NULL) return GF_ISOM_INVALID_MEDIA;	//if the current dataEntry is the desired one, and not self contained, return	if ((minf->dataEntryIndex == dataRefIndex) && (ent->flags != 1)) {		return GF_OK;	}	//we need to open a new one	//first close the existing one	if (minf->dataHandler) gf_isom_datamap_close(minf);	SelfCont = 0;	switch (ent->type) {	case GF_ISOM_BOX_TYPE_URL:	case GF_ISOM_BOX_TYPE_URN:		if (ent->flags == 1) SelfCont = 1;		break;	default:		SelfCont = 1;		break;	}	//if self-contained, assign the input file	if (SelfCont) {		//if no edit, open the input file		if (!Edit) {			if (mdia->mediaTrack->moov->mov->movieFileMap == NULL) return GF_ISOM_INVALID_FILE;			minf->dataHandler = mdia->mediaTrack->moov->mov->movieFileMap;		} else {#ifndef GPAC_READ_ONLY			if (mdia->mediaTrack->moov->mov->editFileMap == NULL) return GF_ISOM_INVALID_FILE;			minf->dataHandler = mdia->mediaTrack->moov->mov->editFileMap;#else			//this should never be the case in an read-only MP4 file			return GF_BAD_PARAM;#endif				}	//else this is a URL (read mode only)	} else {		e = gf_isom_datamap_new(ent->location, mdia->mediaTrack->moov->mov->fileName, GF_ISOM_DATA_MAP_READ, & mdia->information->dataHandler);		if (e) return (e==GF_URL_ERROR) ? GF_ISOM_UNKNOWN_DATA_REF : e;	}	//OK, set the data entry index	minf->dataEntryIndex = dataRefIndex;	return GF_OK;}//return the NB of bytes actually read (used for HTTP, ...) in case file is uncompleteu32 gf_isom_datamap_get_data(GF_DataMap *map, char *buffer, u32 bufferLength, u64 Offset){	if (!map || !buffer) return 0;	switch (map->type) {	case GF_ISOM_DATA_FILE:		return gf_isom_fdm_get_data((GF_FileDataMap *)map, buffer, bufferLength, Offset);	case GF_ISOM_DATA_FILE_MAPPING:		return gf_isom_fmo_get_data((GF_FileMappingDataMap *)map, buffer, bufferLength, Offset);	default:		return 0;	}}#ifndef GPAC_READ_ONLYu64 FDM_GetTotalOffset(GF_FileDataMap *ptr);GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize);u64 gf_isom_datamap_get_offset(GF_DataMap *map){	if (!map) return 0;	switch (map->type) {	case GF_ISOM_DATA_FILE:		return FDM_GetTotalOffset((GF_FileDataMap *)map);	default:		return 0;	}}GF_Err gf_isom_datamap_add_data(GF_DataMap *ptr, char *data, u32 dataSize){	if (!ptr || !data|| !dataSize) return GF_BAD_PARAM;	switch (ptr->type) {	case GF_ISOM_DATA_FILE:		return FDM_AddData((GF_FileDataMap *)ptr, data, dataSize);	default:		return GF_NOT_SUPPORTED;	}}#endif#ifndef GPAC_READ_ONLYGF_DataMap *gf_isom_fdm_new_temp(const char *sPath){	GF_FileDataMap *tmp = (GF_FileDataMap *) malloc(sizeof(GF_FileDataMap));	if (!tmp) return NULL;	memset(tmp, 0, sizeof(GF_FileDataMap));	tmp->type = GF_ISOM_DATA_FILE;	tmp->mode = GF_ISOM_DATA_MAP_WRITE;	if (!sPath) {		tmp->stream = gf_temp_file_new();	} else {		char szPath[GF_MAX_PATH];		if ((sPath[strlen(sPath)-1] != '\\') && (sPath[strlen(sPath)-1] != '/')) {			sprintf(szPath, "%s%c%d_isotmp", sPath, GF_PATH_SEPARATOR, (u32) tmp);		} else {			sprintf(szPath, "%s%d_isotmp", sPath, (u32) tmp);		}		tmp->stream = gf_f64_open(szPath, "w+b");		tmp->temp_file = strdup(szPath);	}	if (!tmp->stream) {		free(tmp);		return NULL;	}	tmp->bs = gf_bs_from_file(tmp->stream, GF_BITSTREAM_READ);	if (!tmp->bs) {		fclose(tmp->stream);		free(tmp);		return NULL;	}	return (GF_DataMap *)tmp;}#endifGF_DataMap *gf_isom_fdm_new(const char *sPath, u8 mode){	u8 bs_mode;	GF_FileDataMap *tmp = (GF_FileDataMap *) malloc(sizeof(GF_FileDataMap));	if (!tmp) return NULL;	memset(tmp, 0, sizeof(GF_FileDataMap));	tmp->type = GF_ISOM_DATA_FILE;	tmp->mode = mode;#ifndef GPAC_READ_ONLY	//open a temp file	if (!strcmp(sPath, "mp4_tmp_edit")) {		//create  a temp file (that only occurs in EDIT/WRITE mode)		tmp->stream = gf_temp_file_new();		bs_mode = GF_BITSTREAM_READ;	}#endif	switch (mode) {	case GF_ISOM_DATA_MAP_READ:		if (!tmp->stream) tmp->stream = gf_f64_open(sPath, "rb");		bs_mode = GF_BITSTREAM_READ;		break;	///we open the file in READ/WRITE mode, in case 	case GF_ISOM_DATA_MAP_WRITE:		if (!tmp->stream) tmp->stream = gf_f64_open(sPath, "w+b");		if (!tmp->stream) tmp->stream = gf_f64_open(sPath, "wb");		bs_mode = GF_BITSTREAM_WRITE;		break;	default:		free(tmp);		return NULL;	}	if (!tmp->stream) {		free(tmp);		return NULL;	}	tmp->bs = gf_bs_from_file(tmp->stream, bs_mode);	if (!tmp->bs) {		fclose(tmp->stream);		free(tmp);		return NULL;	}	return (GF_DataMap *)tmp;}void gf_isom_fdm_del(GF_FileDataMap *ptr){	if (!ptr || (ptr->type != GF_ISOM_DATA_FILE)) return;	if (ptr->bs) gf_bs_del(ptr->bs);	if (ptr->stream) fclose(ptr->stream);#ifndef GPAC_READ_ONLY	if (ptr->temp_file) {		gf_delete_file(ptr->temp_file);		free(ptr->temp_file);	}#endif	free(ptr);}u32 gf_isom_fdm_get_data(GF_FileDataMap *ptr, char *buffer, u32 bufferLength, u64 fileOffset){	u32 bytesRead;	//can we seek till that point ???	if (fileOffset > gf_bs_get_size(ptr->bs)) return 0;	//ouch, we are not at the previous location, do a seek	if (ptr->curPos != fileOffset) {		if (gf_bs_seek(ptr->bs, fileOffset) != GF_OK) return 0;		ptr->curPos = fileOffset;	}	//read our data.	bytesRead = gf_bs_read_data(ptr->bs, buffer, bufferLength);	//update our cache	if (bytesRead == bufferLength) {		ptr->curPos += bytesRead;	} else {		//rewind to original (if seek fails, return 0 cause this means:		//1- no support for seek on the platform		//2- corrupted file for the OS		fflush(ptr->stream);		gf_bs_seek(ptr->bs, ptr->curPos);	}	ptr->last_acces_was_read = 1;	return bytesRead;}#ifndef GPAC_READ_ONLYu64 FDM_GetTotalOffset(GF_FileDataMap *ptr){	if (!ptr) return 0;	//the pos is not always at the end	//this function is called to set up the chunks	//so we need the next WRITE offset	return gf_bs_get_size(ptr->bs);}GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize){	u32 ret;	u64 orig;	if (ptr->mode == GF_ISOM_DATA_MAP_READ) return GF_BAD_PARAM;	orig = gf_bs_get_size(ptr->bs);	/*last access was read, seek to end of file*/	if (ptr->last_acces_was_read) {		gf_bs_seek(ptr->bs, orig);		ptr->last_acces_was_read = 0;	}	//OK, write our stuff to the datamap...	//we don't use bs here cause we want to know more about what has been written	ret = gf_bs_write_data(ptr->bs, data, dataSize);	if (ret != dataSize) {		ptr->curPos = orig;		gf_bs_seek(ptr->bs, orig);		return GF_IO_ERR;	}	ptr->curPos = gf_bs_get_position(ptr->bs);	//flush the stream !!	fflush(ptr->stream);	return GF_OK;}#endif	//GPAC_READ_ONLY#ifdef WIN32#include <windows.h>#include <winerror.h>GF_DataMap *gf_isom_fmo_new(const char *sPath, u8 mode){	GF_FileMappingDataMap *tmp;	HANDLE fileH, fileMapH;	DWORD err;#ifdef _WIN32_WCE	unsigned short sWPath[MAX_PATH];#endif	//only in read only	if (mode != GF_ISOM_DATA_MAP_READ) return NULL;	tmp = (GF_FileMappingDataMap *) malloc(sizeof(GF_FileMappingDataMap));	if (!tmp) return NULL;	memset(tmp, 0, sizeof(GF_FileMappingDataMap));	tmp->type = GF_ISOM_DATA_FILE_MAPPING;	tmp->mode = mode;		tmp->name = _strdup(sPath);	//	//	Open the file 	//#ifdef _WIN32_WCE	//convert to WIDE	CE_CharToWide((char *)sPath, sWPath);	fileH = CreateFileForMapping(sWPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,						(FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS), NULL );#else	fileH = CreateFile(sPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,						(FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS), NULL );#endif		if (fileH == INVALID_HANDLE_VALUE) {		free(tmp->name);		free(tmp);		return NULL;	}	tmp->file_size = GetFileSize(fileH, NULL);	if (tmp->file_size == 0xFFFFFFFF) {		CloseHandle(fileH);		free(tmp->name);		free(tmp);		return NULL;	}	//	//	Create the mapping	//	fileMapH = CreateFileMapping(fileH, NULL, PAGE_READONLY, 0, 0, NULL);	if (fileMapH == NULL) {		CloseHandle(fileH);		free(tmp->name);		free(tmp);		err = GetLastError();		return NULL;	}			tmp->byte_map = MapViewOfFile(fileMapH, FILE_MAP_READ, 0, 0, 0);	if (tmp->byte_map == NULL) {		CloseHandle(fileMapH);		CloseHandle(fileH);		free(tmp->name);		free(tmp);		return NULL;	}	CloseHandle(fileH);	CloseHandle(fileMapH);			//finaly open our bitstream (from buffer)	tmp->bs = gf_bs_new(tmp->byte_map, tmp->file_size, GF_BITSTREAM_READ);	return (GF_DataMap *)tmp;}void gf_isom_fmo_del(GF_FileMappingDataMap *ptr){	if (!ptr || (ptr->type != GF_ISOM_DATA_FILE_MAPPING)) return;	if (ptr->bs) gf_bs_del(ptr->bs);	if (ptr->byte_map) UnmapViewOfFile(ptr->byte_map);	free(ptr->name);	free(ptr);}u32 gf_isom_fmo_get_data(GF_FileMappingDataMap *ptr, char *buffer, u32 bufferLength, u64 fileOffset){	u32 size;	//can we seek till that point ???	if (fileOffset > ptr->file_size) return 0;	size = (u32) fileOffset;	//we do only read operations, so trivial	memcpy(buffer, ptr->byte_map + fileOffset, bufferLength);	return bufferLength;}#elseGF_DataMap *gf_isom_fmo_new(const char *sPath, u8 mode) { return gf_isom_fdm_new(sPath, mode); }void gf_isom_fmo_del(GF_FileMappingDataMap *ptr) { gf_isom_fdm_del((GF_FileDataMap *)ptr); }u32 gf_isom_fmo_get_data(GF_FileMappingDataMap *ptr, char *buffer, u32 bufferLength, u64 fileOffset) {	return gf_isom_fdm_get_data((GF_FileDataMap *)ptr, buffer, bufferLength, fileOffset);}#endif

⌨️ 快捷键说明

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