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

📄 epoc_codec.cpp

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 CPP
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / AAC reader module * *  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/modules/codec.h>#include <gpac/constants.h>#include <gpac/avparse.h>#include <mmf/server/mmfcodec.h>#include <mmf/plugin/mmfcodecimplementationuids.hrh>#define KMMFFourCCCodeEAACP			0x43414520  // ' ' 'E' 'A' 'C' enum{	GF_EPOC_HAS_AMR = 1,	GF_EPOC_HAS_AMR_WB = 1<<1,	GF_EPOC_HAS_AAC = 1<<2,	GF_EPOC_HAS_HEAAC = 1<<3,	GF_EPOC_HAS_MP3 = 1<<4,};typedef struct{	u32 caps;	Bool is_audio;	u32 sample_rate, out_size, num_samples;	u8 num_channels;	const char *codec_name;	CMMFCodec *dec;	CMMFPtrBuffer *mmf_in, *mmf_out;	TPtr8 ptr_in, ptr_out;} EPOCCodec;static void EDEC_LoadCaps(GF_BaseDecoder *ifcg){	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	CMMFCodec *codec = NULL;	TInt err;	ctx->caps = 0;	/*AMR*/	TRAP(err, codec = CMMFCodec::NewL(KMMFFourCCCodeAMR, KMMFFourCCCodePCM16));	if (err==KErrNone) {		ctx->caps |= GF_EPOC_HAS_AMR;		delete codec;	}	/*AMR-WB*/	TRAP(err, codec = CMMFCodec::NewL(KMMFFourCCCodeAWB, KMMFFourCCCodePCM16));	if (err==KErrNone) {		ctx->caps |= GF_EPOC_HAS_AMR_WB;		delete codec;	}	/*AAC*/	TRAP(err, codec = CMMFCodec::NewL(KMMFFourCCCodeAAC, KMMFFourCCCodePCM16));	if (err==KErrNone) {		ctx->caps |= GF_EPOC_HAS_AAC;		delete codec;	}	/*HE-AAC*/	TRAP(err, codec = CMMFCodec::NewL(KMMFFourCCCodeEAACP, KMMFFourCCCodePCM16));	if (err==KErrNone) {		ctx->caps |= GF_EPOC_HAS_HEAAC;		delete codec;	}		/*MP3*/	TRAP(err, codec = CMMFCodec::NewL(KMMFFourCCCodeMP3, KMMFFourCCCodePCM16));	if (err==KErrNone) {		ctx->caps |= GF_EPOC_HAS_MP3;		delete codec;	}}static GF_Err EDEC_AttachStream(GF_BaseDecoder *ifcg, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream){	RArray<TInt> configParams;	GF_M4ADecSpecInfo a_cfg;	Bool aac_sbr_upsample;	TInt err;	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	if (DependsOnES_ID) return GF_NOT_SUPPORTED;	if (ctx->dec) return GF_BAD_PARAM;	/*audio decs*/		switch (objectTypeIndication) {	/*MPEG2 aac*/	case 0x66:	case 0x67:	case 0x68:	/*MPEG4 aac*/	case 0x40: 		if (!decSpecInfoSize || !decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM;		if (gf_m4a_get_config(decSpecInfo, decSpecInfoSize, &a_cfg) != GF_OK) return GF_NON_COMPLIANT_BITSTREAM;				aac_sbr_upsample = 0;		if (a_cfg.has_sbr && (ctx->caps & GF_EPOC_HAS_HEAAC)) {			TRAP(err, ctx->dec = CMMFCodec::NewL(KMMFFourCCCodeEAACP, KMMFFourCCCodePCM16));			if (err != KErrNone) {				a_cfg.has_sbr = 0;				goto retry_no_sbr;			}			aac_sbr_upsample = (a_cfg.base_sr<=24000) ? 1 : 0;			configParams.Append(a_cfg.base_sr);						//  0: Input Sample Frequency			configParams.Append(a_cfg.nb_chan);						//  1: Num Channels [1|2]			configParams.Append(1);									//  2: Input Profile Object type [1 - LC, 3 - LTP]			configParams.Append(aac_sbr_upsample ? 2048 : 1024);	//  3: Output Frame Size			configParams.Append(1024);								//  4: Input Frame Len [1024, 960]			configParams.Append(a_cfg.base_sr);						//  5: Input Sample Rate			configParams.Append(0);									//  6: 0			configParams.Append(aac_sbr_upsample ? 0 : 1);			//  7: Down Sample Mode [0|1]			configParams.Append(16);								//  8: Sample resolution, 8Khz (8-bit PCM) or 16Khz (16-bit)			configParams.Append(a_cfg.sbr_sr);						//  9: Output Sample Frequency			configParams.Append(5);									// 10: Extension Object Type					TRAP(err, ctx->dec->ConfigureL(TUid::Uid(KUidMmfCodecAudioSettings), (TDesC8&) configParams));			if (err != KErrNone) {				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[EPOC Decoder] Failed to configure HE-AAC decoder (error %d) - retrying with AAC\n", err));				configParams.Reset();				goto retry_no_sbr;			}			ctx->codec_name = "EPOC HE-AAC Decoder";			ctx->num_channels = a_cfg.nb_chan;			ctx->num_samples = aac_sbr_upsample ? 2048 : 1024;			ctx->sample_rate = a_cfg.sbr_sr;		} else {retry_no_sbr:			TRAP(err, ctx->dec = CMMFCodec::NewL(KMMFFourCCCodeAAC, KMMFFourCCCodePCM16));			if (err != KErrNone) {				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[EPOC Decoder] Unable to load native codec: error %d\n", err));				return GF_IO_ERR;			}			configParams.Append(a_cfg.base_sr); // Input Sample Rate			configParams.Append(a_cfg.nb_chan);       // Num Channels [1|2]			configParams.Append((a_cfg.base_object_type==GF_M4A_AAC_LC) ? 1 : 3);       // AAC Input Profile [1 - LC, 3 - LTP]			configParams.Append(1024);       // Input Frame Len [1024, 960]			configParams.Append(0);                    // AAC Down Mixing [0-none | 1 mono | 2 stereo]			configParams.Append(0);                    // Aac output channels selection {0 - none, 1 - 1, 2 - 2}			configParams.Append(0);                    // Aac decimation factor {0 - none, 2 - decimation by 2, 4 - decimation by 4}			configParams.Append(0);                    // Aac concealment - It can be {0 - none, 1 - basic}			configParams.Append(16);     // Sample resolution - It can be {16 - 16-bit resolution}			configParams.Append(0);                    // Sample Rate Conversion 0 : none 			TRAP(err, ctx->dec->ConfigureL(TUid::Uid(KUidMmfCodecAudioSettings), (TDesC8&) configParams));			if (err != KErrNone) {				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[EPOC Decoder] Failed to configure AAC decoder (error %d)\n", err));				return GF_NON_COMPLIANT_BITSTREAM;			}			ctx->codec_name = "EPOC AAC Decoder";			ctx->num_channels = a_cfg.nb_chan;			ctx->num_samples = 1024;			ctx->sample_rate = a_cfg.base_sr;		}		ctx->out_size = ctx->num_channels * ctx->num_samples * 2;		break;	/*non-mpeg4 codecs*/	case GPAC_EXTRA_CODECS_OTI:		if (decSpecInfoSize<4) return GF_BAD_PARAM;		if (!strnicmp(decSpecInfo, "samr", 4) || !strnicmp(decSpecInfo, "amr ", 4)) {			TRAP(err, ctx->dec = CMMFCodec::NewL(KMMFFourCCCodeAMR, KMMFFourCCCodePCM16));			if (err != KErrNone) {				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[EPOC Decoder] Unable to load native codec: error %d\n", err));				return GF_IO_ERR;			}			ctx->is_audio = 1;			ctx->num_channels = 1;			ctx->num_samples = 160;			ctx->sample_rate = 8000;			ctx->out_size = ctx->num_channels * ctx->num_samples * 2;			ctx->codec_name = "EPOC AMR Decoder";		}		else if (!strnicmp(decSpecInfo, "sawb", 4)) {			TRAP(err, ctx->dec = CMMFCodec::NewL(KMMFFourCCCodeAWB, KMMFFourCCCodePCM16));			if (err != KErrNone) {				GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[EPOC Decoder] Unable to load native codec: error %d\n", err));				return GF_IO_ERR;			}			ctx->is_audio = 1;			ctx->num_channels = 1;			ctx->num_samples = 320;			ctx->sample_rate = 16000;			ctx->out_size = ctx->num_channels * ctx->num_samples * 2;			ctx->codec_name = "EPOC AMR-Wideband Decoder";		}		break;	default:		return GF_BAD_PARAM;	}	ctx->mmf_in = CMMFPtrBuffer::NewL();	ctx->mmf_out = CMMFPtrBuffer::NewL();	return GF_OK;}static GF_Err EDEC_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID){	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	if (ctx->mmf_in) {		delete ctx->mmf_in;		ctx->mmf_in = NULL;	}	if (ctx->mmf_out) {		delete ctx->mmf_out;		ctx->mmf_out = NULL;	}	if (ctx->dec) {		delete ctx->dec;		ctx->dec = NULL;	}	return GF_OK;}static GF_Err EDEC_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability){	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	switch (capability->CapCode) {	/*not tested yet*/	case GF_CODEC_RESILIENT:		capability->cap.valueInt = 1;		break;	case GF_CODEC_OUTPUT_SIZE:		capability->cap.valueInt = ctx->out_size;		break;	case GF_CODEC_SAMPLERATE:		capability->cap.valueInt = ctx->sample_rate;		break;	case GF_CODEC_NB_CHAN:		capability->cap.valueInt = ctx->num_channels;		break;	case GF_CODEC_BITS_PER_SAMPLE:		capability->cap.valueInt = 16;		break;	case GF_CODEC_BUFFER_MIN:		capability->cap.valueInt = 4;		break;	case GF_CODEC_BUFFER_MAX:		capability->cap.valueInt = 12;		break;	case GF_CODEC_CU_DURATION:		capability->cap.valueInt = ctx->num_samples;		break;	/*to refine, it seems that 4 bytes padding is not enough on all streams ?*/	case GF_CODEC_PADDING_BYTES:		capability->cap.valueInt = 4;		break;	case GF_CODEC_CHANNEL_CONFIG:		capability->cap.valueInt = (ctx->num_channels==1) ? GF_AUDIO_CH_FRONT_CENTER : (GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT);		break;	default:		capability->cap.valueInt = 0;		break;	}	return GF_OK;}static GF_Err EDEC_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability){	/*return unsupported to avoid confusion by the player (like SR changing ...) */	return GF_NOT_SUPPORTED;}static GF_Err EDEC_ProcessData(GF_MediaDecoder *ifcg, 		char *inBuffer, u32 inBufferLength,		u16 ES_ID,		char *outBuffer, u32 *outBufferLength,		u8 PaddingBits, u32 mmlevel){	TCodecProcessResult res;	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	if (*outBufferLength < ctx->out_size) {		*outBufferLength = ctx->out_size;		GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("AMR buffer too small\n"));		return GF_BUFFER_TOO_SMALL;	}	ctx->ptr_in.Set((TUint8*)inBuffer, inBufferLength, inBufferLength);	ctx->mmf_in->SetPtr(ctx->ptr_in);	ctx->ptr_out.Set((TUint8*)outBuffer, *outBufferLength, *outBufferLength);	ctx->mmf_out->SetPtr(ctx->ptr_out);	TRAPD(e, res = ctx->dec->ProcessL(*ctx->mmf_in, *ctx->mmf_out));	if (res.iStatus==TCodecProcessResult::EProcessError) {		GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[EPOC Decoder] Decode failed - error %d\n", res.iStatus));		return GF_NON_COMPLIANT_BITSTREAM;	}	return GF_OK;}static const char *EDEC_GetCodecName(GF_BaseDecoder *ifcg){	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	return ctx->codec_name;}static Bool EDEC_CanHandleStream(GF_BaseDecoder *ifcg, u32 StreamType, u32 ObjectType, char *decSpecInfo, u32 decSpecInfoSize, u32 PL){	GF_M4ADecSpecInfo a_cfg;	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	/*audio decs*/		if (StreamType == GF_STREAM_AUDIO) {		switch (ObjectType) {		/*MPEG2 aac*/		case 0x66:		case 0x67:		case 0x68:		/*MPEG4 aac*/		case 0x40: 			if (!decSpecInfoSize || !decSpecInfo) return 0;			if (gf_m4a_get_config(decSpecInfo, decSpecInfoSize, &a_cfg) != GF_OK) return 0;			switch (a_cfg.base_object_type) {			/*only LTP and LC supported*/			case GF_M4A_AAC_LC:			case GF_M4A_AAC_LTP:				if ((ctx->caps & GF_EPOC_HAS_AAC) || (ctx->caps & GF_EPOC_HAS_HEAAC) ) return 1;			default:				break;			}			break;		/*MPEG1 audio*/		case 0x69:		/*MPEG2 audio*/		case 0x6B:			/* NOT SUPPORTED YET if (ctx->caps & GF_EPOC_HAS_MP3) return 1; */			break;		/*non-mpeg4 codecs*/		case GPAC_EXTRA_CODECS_OTI:			if (!decSpecInfoSize || !decSpecInfo) return 0;			if (decSpecInfoSize<4) return 0;			if (!strnicmp(decSpecInfo, "samr", 4) || !strnicmp(decSpecInfo, "amr ", 4)) {				if (ctx->caps & GF_EPOC_HAS_AMR) return 1;			}			if (!strnicmp(decSpecInfo, "sawb", 4)) {				if (ctx->caps & GF_EPOC_HAS_AMR_WB) return 1;			}			break;		/*cap query*/		case 0:			return 1;		default:			return 0;		}	}	return 0;}#ifdef __cplusplusextern "C" {#endifGF_BaseDecoder *EPOC_codec_new(){	GF_MediaDecoder *ifce;	EPOCCodec *ctx;	GF_SAFEALLOC(ifce, GF_MediaDecoder);	GF_REGISTER_MODULE_INTERFACE(ifce, GF_MEDIA_DECODER_INTERFACE, "EPOC Native Decoder", "gpac distribution")	GF_SAFEALLOC(ctx, EPOCCodec);	ifce->privateStack = ctx;	/*setup our own interface*/		ifce->AttachStream = EDEC_AttachStream;	ifce->DetachStream = EDEC_DetachStream;	ifce->GetCapabilities = EDEC_GetCapabilities;	ifce->SetCapabilities = EDEC_SetCapabilities;	ifce->ProcessData = EDEC_ProcessData;	ifce->CanHandleStream = EDEC_CanHandleStream;	ifce->GetName = EDEC_GetCodecName;	EDEC_LoadCaps((GF_BaseDecoder*)ifce);	return (GF_BaseDecoder *) ifce;}void EPOC_codec_del(GF_BaseDecoder *ifcg){	EPOCCodec *ctx = (EPOCCodec *)ifcg->privateStack;	free(ctx);	free(ifcg);}#ifdef __cplusplus}#endif

⌨️ 快捷键说明

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