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

📄 media.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			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>GF_Err Media_GetSampleDesc(GF_MediaBox *mdia, u32 SampleDescIndex, GF_SampleEntryBox **out_entry, u32 *dataRefIndex){	GF_SampleDescriptionBox *stsd;	GF_SampleEntryBox *entry = NULL;	if (!mdia) return GF_ISOM_INVALID_FILE;	stsd = mdia->information->sampleTable->SampleDescription;	if (!stsd) return GF_ISOM_INVALID_FILE;	if (!SampleDescIndex || (SampleDescIndex > gf_list_count(stsd->boxList)) ) return GF_BAD_PARAM;	entry = (GF_SampleEntryBox*)gf_list_get(stsd->boxList, SampleDescIndex - 1);	if (!entry) return GF_ISOM_INVALID_FILE;	if (out_entry) *out_entry = entry;	if (dataRefIndex) *dataRefIndex = entry->dataReferenceIndex;	return GF_OK;}GF_Err Media_GetSampleDescIndex(GF_MediaBox *mdia, u64 DTS, u32 *sampleDescIndex){	GF_Err e;	u32 sampleNumber, prevSampleNumber, num;	u64 offset;	u8 isEdited;	if (sampleDescIndex == NULL) return GF_BAD_PARAM;	//find the sample for this time	e = findEntryForTime(mdia->information->sampleTable, (u32) DTS, 0, &sampleNumber, &prevSampleNumber);	if (e) return e;	if (!sampleNumber && !prevSampleNumber) {		//we have to assume the track was created to be used... If we have a sampleDesc, OK		if (gf_list_count(mdia->information->sampleTable->SampleDescription->boxList)) {			(*sampleDescIndex) = 1;			return GF_OK;		}				return GF_BAD_PARAM;	}	return stbl_GetSampleInfos(mdia->information->sampleTable, ( sampleNumber ? sampleNumber : prevSampleNumber), &offset, &num, sampleDescIndex, &isEdited);}static GF_Err gf_isom_get_3gpp_audio_esd(GF_SampleTableBox *stbl, GF_GenericAudioSampleEntryBox *entry, GF_ESD **out_esd){	GF_BitStream *bs;	char szName[80];	(*out_esd) = gf_odf_desc_esd_new(2);	(*out_esd)->decoderConfig->streamType = 0x05;	/*official mapping to MPEG-4*/	switch (entry->type) {	case GF_ISOM_SUBTYPE_3GP_EVRC: 		(*out_esd)->decoderConfig->objectTypeIndication = 0xA0;		return GF_OK;	case GF_ISOM_SUBTYPE_3GP_QCELP:	{		u32 block_size, sample_rate, sample_size, i;		GF_SttsEntry *ent;		/*only map CBR*/		sample_size = stbl->SampleSize->sampleSize;		(*out_esd)->decoderConfig->objectTypeIndication = 0xE1;		bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);		gf_bs_write_data(bs, "QLCMfmt ", 8);		gf_bs_write_u32_le(bs, 150);/*fmt chunk size*/		gf_bs_write_u8(bs, 1);		gf_bs_write_u8(bs, 0);		/*QCELP GUID*/		gf_bs_write_data(bs, "\x41\x6D\x7F\x5E\x15\xB1\xD0\x11\xBA\x91\x00\x80\x5F\xB4\xB9\x7E", 16);		gf_bs_write_u16_le(bs, 1);		memset(szName, 0, 80);		strcpy(szName, "QCELP-13K(GPAC-emulated)");		gf_bs_write_data(bs, szName, 80);		ent = (GF_SttsEntry*)gf_list_get(stbl->TimeToSample->entryList, 0);		sample_rate = entry->samplerate_hi;		block_size = ent ? ent->sampleDelta : 160;		gf_bs_write_u16_le(bs, 8*sample_size*sample_rate/block_size);		gf_bs_write_u16_le(bs, sample_size);		gf_bs_write_u16_le(bs, block_size);		gf_bs_write_u16_le(bs, sample_rate);		gf_bs_write_u16_le(bs, entry->bitspersample);		gf_bs_write_u32_le(bs, sample_size ? 0 : 7);		/**/		for (i=0; i<7; i++) {			static const u32 qcelp_r2s [] = {0, 1, 1, 4, 2, 8, 3, 17, 4, 35, 5, 8, 14, 1};			if (sample_size) {				gf_bs_write_u16(bs, 0);			} else {				gf_bs_write_u8(bs, qcelp_r2s[2*i+1]);				gf_bs_write_u8(bs, qcelp_r2s[2*i]);			}		}		gf_bs_write_u16(bs, 0);		memset(szName, 0, 80);		gf_bs_write_data(bs, szName, 20);/*reserved*/		gf_bs_get_content(bs, & (*out_esd)->decoderConfig->decoderSpecificInfo->data, & (*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);		gf_bs_del(bs);	}		return GF_OK;	case GF_ISOM_SUBTYPE_3GP_SMV:		(*out_esd)->decoderConfig->objectTypeIndication = 0xA1;		return GF_OK;	default:		break;	}	/*this is a user-reserved used in gpac - we need a std OTI for AMR/AMRWB*/	(*out_esd)->decoderConfig->objectTypeIndication = 0x80;	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);	gf_bs_write_u32(bs, entry->type);	gf_bs_write_u16(bs, entry->samplerate_hi);	gf_bs_write_u16(bs, (entry->type == GF_ISOM_SUBTYPE_3GP_AMR) ? 160 : 320);	gf_bs_write_u8(bs, entry->channel_count);	gf_bs_write_u8(bs, entry->bitspersample);	gf_bs_write_u8(bs, 0);	gf_bs_get_content(bs, & (*out_esd)->decoderConfig->decoderSpecificInfo->data, & (*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);	gf_bs_del(bs);	return GF_OK;}GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bool true_desc_only){	GF_ESD *esd;	GF_MPEGSampleEntryBox *entry = NULL;	GF_ESDBox *ESDa;	GF_SampleDescriptionBox *stsd = mdia->information->sampleTable->SampleDescription;		*out_esd = NULL;	if (!stsd || !stsd->boxList || !sampleDescIndex || (sampleDescIndex > gf_list_count(stsd->boxList)) )		return GF_BAD_PARAM;	esd = NULL;	entry = (GF_MPEGSampleEntryBox*)gf_list_get(stsd->boxList, sampleDescIndex - 1);	if (! entry) return GF_ISOM_INVALID_MEDIA;	*out_esd = NULL;	ESDa = NULL;	switch (entry->type) {	case GF_ISOM_BOX_TYPE_MP4V:	case GF_ISOM_BOX_TYPE_ENCV:		ESDa = ((GF_MPEGVisualSampleEntryBox*)entry)->esd;		if (ESDa) esd = (GF_ESD *) ESDa->desc;		/*avc1 encrypted*/		else esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;		break;	case GF_ISOM_BOX_TYPE_AVC1:		esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;		break;	case GF_ISOM_BOX_TYPE_MP4A:	case GF_ISOM_BOX_TYPE_ENCA:		ESDa = ((GF_MPEGAudioSampleEntryBox*)entry)->esd;		if (ESDa) esd = (GF_ESD *) ESDa->desc;		break;	case GF_ISOM_BOX_TYPE_MP4S:	case GF_ISOM_BOX_TYPE_ENCS:		ESDa = entry->esd;		if (ESDa) esd = (GF_ESD *) ESDa->desc;		break;	case GF_ISOM_BOX_TYPE_TX3G:		if (!true_desc_only && mdia->mediaTrack->moov->mov->convert_streaming_text) {			GF_Err e = gf_isom_get_ttxt_esd(mdia, out_esd);			if (e) return e;			break;		}		else return GF_ISOM_INVALID_MEDIA;	case GF_ISOM_SUBTYPE_3GP_AMR:	case GF_ISOM_SUBTYPE_3GP_AMR_WB:	case GF_ISOM_SUBTYPE_3GP_EVRC: 	case GF_ISOM_SUBTYPE_3GP_QCELP:	case GF_ISOM_SUBTYPE_3GP_SMV:		if (!true_desc_only) {			GF_Err e = gf_isom_get_3gpp_audio_esd(mdia->information->sampleTable, (GF_GenericAudioSampleEntryBox*)entry, out_esd);			if (e) return e;			break;		} else return GF_ISOM_INVALID_MEDIA;	case GF_ISOM_SUBTYPE_3GP_H263: 		if (true_desc_only) {			return GF_ISOM_INVALID_MEDIA;		} else {			GF_BitStream *bs;			esd =  gf_odf_desc_esd_new(2);			*out_esd = esd;			esd->decoderConfig->streamType = 0x04;			esd->decoderConfig->objectTypeIndication = 0x80;			bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);			gf_bs_write_u32(bs, entry->type);			gf_bs_write_u16(bs, ((GF_MPEGVisualSampleEntryBox*)entry)->Width);			gf_bs_write_u16(bs, ((GF_MPEGVisualSampleEntryBox*)entry)->Height);			gf_bs_get_content(bs, & esd->decoderConfig->decoderSpecificInfo->data, & esd->decoderConfig->decoderSpecificInfo->dataLength);			gf_bs_del(bs);			return GF_OK;		}	default: return GF_ISOM_INVALID_MEDIA;	}	if (true_desc_only) {		if (!esd) return GF_ISOM_INVALID_MEDIA;		*out_esd = esd;		return GF_OK;	} else {		if (!esd && !*out_esd) return GF_ISOM_INVALID_MEDIA;		if (*out_esd == NULL) gf_odf_desc_copy((GF_Descriptor *)esd, (GF_Descriptor **)out_esd);	}	return GF_OK;}Bool Media_IsSampleSyncShadow(GF_ShadowSyncBox *stsh, u32 sampleNumber){	u32 i;	GF_StshEntry *ent;	if (!stsh) return 0;	i=0;	while ((ent = (GF_StshEntry*)gf_list_enum(stsh->entries, &i))) {		if ((u32) ent->syncSampleNumber == sampleNumber) return 1;		else if ((u32) ent->syncSampleNumber > sampleNumber) return 0;	}	return 0;}GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp, u32 *sIDX, Bool no_data, u64 *out_offset){	GF_Err e;	u32 bytesRead;	u32 dataRefIndex, chunkNumber;	u64 offset, new_size;	u8 isEdited;	GF_SampleEntryBox *entry;		if (!mdia || !mdia->information->sampleTable) return GF_BAD_PARAM;	//OK, here we go....	if (sampleNumber > mdia->information->sampleTable->SampleSize->sampleCount) return GF_BAD_PARAM;	//get the DTS	e = stbl_GetSampleDTS(mdia->information->sampleTable->TimeToSample, sampleNumber, &(*samp)->DTS);	if (e) return e;	//the CTS offset	if (mdia->information->sampleTable->CompositionOffset) {		e = stbl_GetSampleCTS(mdia->information->sampleTable->CompositionOffset , sampleNumber, &(*samp)->CTS_Offset);		if (e) return e;	} else {		(*samp)->CTS_Offset = 0;	}	//the size	e = stbl_GetSampleSize(mdia->information->sampleTable->SampleSize, sampleNumber, &(*samp)->dataLength);	if (e) return e;	//the RAP	if (mdia->information->sampleTable->SyncSample) {		e = stbl_GetSampleRAP(mdia->information->sampleTable->SyncSample, sampleNumber, &(*samp)->IsRAP, NULL, NULL);		if (e) return e;	} else {		//if no SyncSample, all samples are sync (cf spec)		(*samp)->IsRAP = 1;	}	/*overwrite sync sample with sample dep if any*/	if (mdia->information->sampleTable->SampleDep) {		u32 dependsOn, dependedOn, redundant;		e = stbl_GetSampleDepType(mdia->information->sampleTable->SampleDep, sampleNumber, &dependsOn, &dependedOn, &redundant);		if (!e) {			if (dependsOn==1) (*samp)->IsRAP = 0;			else if (dependsOn==2) (*samp)->IsRAP = 1;			/*if not depended upon and redundant, mark as carousel sample*/			if ((dependedOn==2) && (redundant==1)) (*samp)->IsRAP = 2;			/*TODO FIXME - we must enhance the IsRAP semantics to carry disposable info ... */		}	}	/*get sync shadow*/	if (Media_IsSampleSyncShadow(mdia->information->sampleTable->ShadowSync, sampleNumber)) (*samp)->IsRAP = 2;	//the data info	if (!sIDX && !no_data) return GF_BAD_PARAM;	if (!sIDX && !out_offset) return GF_OK;	(*sIDX) = 0;	e = stbl_GetSampleInfos(mdia->information->sampleTable, sampleNumber, &offset, &chunkNumber, sIDX, &isEdited);	if (e) return e;	//then get the DataRef	e = Media_GetSampleDesc(mdia, *sIDX, &entry, &dataRefIndex);	if (e) return e;	// Open the data handler - check our mode, don't reopen in read only if this is 	//the same entry. In other modes we have no choice because the main data map is 	//divided into the original and the edition files	if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_READ) {			//same as last call in read mode		if (!mdia->information->dataHandler || (mdia->information->dataEntryIndex != dataRefIndex)) {			e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);			if (e) return e;		}	} else {		e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);		if (e) return e;	}	if (out_offset) *out_offset = offset;	if (no_data) return GF_OK;	/*and finally get the data, include padding if needed*/ 	(*samp)->data = (char *) malloc(sizeof(char) * ( (*samp)->dataLength + mdia->mediaTrack->padding_bytes) );	if (mdia->mediaTrack->padding_bytes)		memset((*samp)->data + (*samp)->dataLength, 0, sizeof(char) * mdia->mediaTrack->padding_bytes);	//check if we can get the sample (make sure we have enougth data...)	new_size = gf_bs_get_size(mdia->information->dataHandler->bs);	if (offset + (*samp)->dataLength > new_size) {		//always refresh the size to avoid wrong info on http/ftp 		new_size = gf_bs_get_refreshed_size(mdia->information->dataHandler->bs);		if (offset + (*samp)->dataLength > new_size) {			mdia->BytesMissing = offset + (*samp)->dataLength - new_size;			return GF_ISOM_INCOMPLETE_FILE;		}		}	bytesRead = gf_isom_datamap_get_data(mdia->information->dataHandler, (*samp)->data, (*samp)->dataLength, offset);	//if bytesRead != sampleSize, we have an IO err	if (bytesRead < (*samp)->dataLength) {		return GF_IO_ERR;	}	mdia->BytesMissing = 0;	//finally rewrite the sample if this is an OD Access Unit	if (mdia->handler->handlerType == GF_ISOM_MEDIA_OD) {		e = Media_RewriteODFrame(mdia, *samp);		if (e) return e;	}	else if (mdia->mediaTrack->moov->mov->convert_streaming_text 		&& (mdia->handler->handlerType == GF_ISOM_MEDIA_TEXT) ) {		u64 dur;		if (sampleNumber == mdia->information->sampleTable->SampleSize->sampleCount) {			dur = mdia->mediaHeader->duration - (*samp)->DTS;		} else {			stbl_GetSampleDTS(mdia->information->sampleTable->TimeToSample, sampleNumber+1, &dur);			dur -= (*samp)->DTS;		}		e = gf_isom_rewrite_text_sample(*samp, *sIDX, (u32) dur);		if (e) return e;	}	return GF_OK;}GF_Err Media_CheckDataEntry(GF_MediaBox *mdia, u32 dataEntryIndex){	GF_DataEntryURLBox *entry;	GF_DataMap *map;	GF_Err e;	if (!mdia || !dataEntryIndex || dataEntryIndex > gf_list_count(mdia->information->dataInformation->dref->boxList)) return GF_BAD_PARAM;	entry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, dataEntryIndex - 1);	if (!entry) return GF_ISOM_INVALID_FILE;	if (entry->flags == 1) return GF_OK;		//ok, not self contained, let's go for it...	//we don't know what's a URN yet	if (entry->type == GF_ISOM_BOX_TYPE_URN) return GF_NOT_SUPPORTED;	if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_WRITE) {		e = gf_isom_datamap_new(entry->location, NULL, GF_ISOM_DATA_MAP_READ, &map);	} else {		e = gf_isom_datamap_new(entry->location, mdia->mediaTrack->moov->mov->fileName, GF_ISOM_DATA_MAP_READ, &map);	}	if (e) return e;	gf_isom_datamap_del(map);	return GF_OK;}Bool Media_IsSelfContained(GF_MediaBox *mdia, u32 StreamDescIndex){	u32 drefIndex=0;	GF_FullBox *a;	GF_SampleEntryBox *se = NULL;	Media_GetSampleDesc(mdia, StreamDescIndex, &se, &drefIndex);	if (!drefIndex) return 0;	a = (GF_FullBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, drefIndex - 1);

⌨️ 快捷键说明

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