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

📄 faad_dec.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 / 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.  * */#ifdef GPAC_HAS_FAAD#include <faad.h>#include <gpac/modules/codec.h>#include <gpac/constants.h>#include <gpac/avparse.h>typedef struct{	faacDecHandle codec;	faacDecFrameInfo info;	u32 sample_rate, out_size, num_samples;	u8 num_channels;	/*no support for scalability in FAAD yet*/	u16 ES_ID;	Bool signal_mc;	Bool is_sbr;		char ch_reorder[16];} FAADDec;#define FAADCTX() FAADDec *ctx = (FAADDec *) ifcg->privateStackstatic GF_Err FAAD_AttachStream(GF_BaseDecoder *ifcg, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream){	GF_Err e;	GF_M4ADecSpecInfo a_cfg;	FAADCTX();		if (ctx->ES_ID && ctx->ES_ID!=ES_ID) return GF_NOT_SUPPORTED;	if (!decSpecInfoSize || !decSpecInfo) return GF_NON_COMPLIANT_BITSTREAM;	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Attaching stream %d\n", ES_ID));	if (ctx->codec) faacDecClose(ctx->codec);	ctx->codec = faacDecOpen();	if (!ctx->codec) {		GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error initializing decoder\n"));		return GF_IO_ERR;	}	e = gf_m4a_get_config((unsigned char *) decSpecInfo, decSpecInfoSize, &a_cfg);	if (e) return e;	if ( (s8) faacDecInit2(ctx->codec, (unsigned char *) decSpecInfo, decSpecInfoSize, (unsigned long *) &ctx->sample_rate, (u8 *) &ctx->num_channels) < 0) {		GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[FAAD] Error initializing stream %d\n", ES_ID));		return GF_NOT_SUPPORTED;	}	ctx->is_sbr = a_cfg.has_sbr;	ctx->num_samples = 1024;	ctx->out_size = 2 * ctx->num_samples * ctx->num_channels;	ctx->ES_ID = ES_ID;	ctx->signal_mc = ctx->num_channels>2 ? 1 : 0;	return GF_OK;}static GF_Err FAAD_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID){	FAADCTX();	if (ES_ID != ctx->ES_ID) return GF_BAD_PARAM;	if (ctx->codec) faacDecClose(ctx->codec);	ctx->codec = NULL;	ctx->ES_ID = 0;	ctx->sample_rate = ctx->out_size = ctx->num_samples = 0;	ctx->num_channels = 0;	return GF_OK;}static GF_Err FAAD_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability){	u32 i;	FAADCTX();	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;	/*by default AAC access unit lasts num_samples (timescale being sampleRate)*/	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 = 8;		break;	case GF_CODEC_CHANNEL_CONFIG:		capability->cap.valueInt = 0;		for (i=0; i<ctx->num_channels; i++) {			switch (ctx->info.channel_position[i]) {			case FRONT_CHANNEL_CENTER: capability->cap.valueInt |= GF_AUDIO_CH_FRONT_CENTER; break;			case FRONT_CHANNEL_LEFT: capability->cap.valueInt |= GF_AUDIO_CH_FRONT_LEFT; break;			case FRONT_CHANNEL_RIGHT: capability->cap.valueInt |= GF_AUDIO_CH_FRONT_RIGHT; break;			case SIDE_CHANNEL_LEFT: capability->cap.valueInt |= GF_AUDIO_CH_SIDE_LEFT; break;			case SIDE_CHANNEL_RIGHT: capability->cap.valueInt |= GF_AUDIO_CH_SIDE_RIGHT; break;			case BACK_CHANNEL_LEFT: capability->cap.valueInt |= GF_AUDIO_CH_BACK_LEFT; break;			case BACK_CHANNEL_RIGHT: capability->cap.valueInt |= GF_AUDIO_CH_BACK_RIGHT; break;			case BACK_CHANNEL_CENTER: capability->cap.valueInt |= GF_AUDIO_CH_BACK_CENTER; break;			case LFE_CHANNEL: capability->cap.valueInt |= GF_AUDIO_CH_LFE; break;			default: break;			}		}		break;	default:		capability->cap.valueInt = 0;		break;	}	return GF_OK;}static GF_Err FAAD_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability){	/*return unsupported to avoid confusion by the player (like SR changing ...) */	return GF_NOT_SUPPORTED;}static s8 FAAD_GetChannelPos(FAADDec *ffd, u32 ch_cfg){	u32 i;	for (i=0; i<ffd->info.channels; i++) {		switch (ffd->info.channel_position[i]) {		case FRONT_CHANNEL_CENTER: if (ch_cfg==GF_AUDIO_CH_FRONT_CENTER) return i; break;		case FRONT_CHANNEL_LEFT: if (ch_cfg==GF_AUDIO_CH_FRONT_LEFT) return i; break;		case FRONT_CHANNEL_RIGHT: if (ch_cfg==GF_AUDIO_CH_FRONT_RIGHT) return i; break;		case SIDE_CHANNEL_LEFT: if (ch_cfg==GF_AUDIO_CH_SIDE_LEFT) return i; break;		case SIDE_CHANNEL_RIGHT: if (ch_cfg==GF_AUDIO_CH_SIDE_RIGHT) return i; break;		case BACK_CHANNEL_LEFT: if (ch_cfg==GF_AUDIO_CH_BACK_LEFT) return i; break;		case BACK_CHANNEL_RIGHT: if (ch_cfg==GF_AUDIO_CH_BACK_RIGHT) return i; break;		case BACK_CHANNEL_CENTER: if (ch_cfg==GF_AUDIO_CH_BACK_CENTER) return i; break;		case LFE_CHANNEL: if (ch_cfg==GF_AUDIO_CH_LFE) return i; break;		}	}	return -1;}static GF_Err FAAD_ProcessData(GF_MediaDecoder *ifcg, 		char *inBuffer, u32 inBufferLength,		u16 ES_ID,		char *outBuffer, u32 *outBufferLength,		u8 PaddingBits, u32 mmlevel){	void *buffer;	unsigned short *conv_in, *conv_out;	u32 i, j;	FAADCTX();	/*check not using scalabilty*/	if (ctx->ES_ID != ES_ID) return GF_BAD_PARAM;	/*if late or seeking don't decode*/	switch (mmlevel) {	case GF_CODEC_LEVEL_SEEK:	case GF_CODEC_LEVEL_DROP:		*outBufferLength = 0;		return GF_OK;	default:		break;	}	if (ctx->out_size > *outBufferLength) {		*outBufferLength = ctx->out_size;		return GF_BUFFER_TOO_SMALL;	}	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Decoding AU\n"));	buffer = faacDecDecode(ctx->codec, &ctx->info, inBuffer, inBufferLength);	if (ctx->info.error>0) {		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] Error decoding AU %d\n", ctx->info.error));		*outBufferLength = 0;		return GF_NON_COMPLIANT_BITSTREAM;	}	if (!ctx->info.samples || !buffer || !ctx->info.bytesconsumed) {		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] empty/non complete AU\n"));		*outBufferLength = 0;		return GF_OK;	}	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[FAAD] AU decoded\n"));	/*FAAD froces us to decode a frame to get channel cfg*/	if (ctx->signal_mc) {		s32 ch, idx;		ctx->signal_mc = 0;		idx = 0;		/*NOW WATCH OUT!! FAAD may very well decide to output more channels than indicated!!!*/		ctx->num_channels = ctx->info.channels;		/*get cfg*/		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_FRONT_LEFT);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_FRONT_RIGHT);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_FRONT_CENTER);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_LFE);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_BACK_LEFT);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_BACK_RIGHT);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_BACK_CENTER);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_SIDE_LEFT);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		ch = FAAD_GetChannelPos(ctx, GF_AUDIO_CH_SIDE_RIGHT);		if (ch>=0) { ctx->ch_reorder[idx] = ch; idx++; }		*outBufferLength = ctx->out_size;		if (sizeof(short) * ctx->info.samples > *outBufferLength) {			*outBufferLength = ctx->out_size = sizeof(short)*ctx->info.samples; 		}		return GF_BUFFER_TOO_SMALL;	}	if (sizeof(short) * ctx->info.samples > *outBufferLength) {		*outBufferLength = sizeof(short)*ctx->info.samples; 		return GF_BUFFER_TOO_SMALL;	} 	/*we assume left/right order*/	if (ctx->num_channels<=2) {		memcpy(outBuffer, buffer, sizeof(short)* ctx->info.samples);		*outBufferLength = sizeof(short)*ctx->info.samples;		return GF_OK;	}	conv_in = (unsigned short *) buffer;	conv_out = (unsigned short *) outBuffer;	for (i=0; i<ctx->info.samples; i+=ctx->info.channels) {		for (j=0; j<ctx->info.channels; j++) {			conv_out[i + j] = conv_in[i + ctx->ch_reorder[j]];		}	}	*outBufferLength = sizeof(short)*ctx->info.samples;	return GF_OK;}static const char *FAAD_GetCodecName(GF_BaseDecoder *ifcg){	FAADCTX();	if (ctx->is_sbr) return "FAAD2 " FAAD2_VERSION " SBR mode";	return "FAAD2 " FAAD2_VERSION;}static Bool FAAD_CanHandleStream(GF_BaseDecoder *dec, u32 StreamType, u32 ObjectType, char *decSpecInfo, u32 decSpecInfoSize, u32 PL){	GF_M4ADecSpecInfo a_cfg;	/*audio decs*/		if (StreamType != GF_STREAM_AUDIO) return 0;	if (!decSpecInfoSize || !decSpecInfo) return 0;	switch (ObjectType) {	/*MPEG2 aac*/	case 0x66:	case 0x67:	case 0x68:	/*MPEG4 aac*/	case 0x40: 		break;	/*cap query*/	case 0:		return 1;	default:		return 0;	}	if (gf_m4a_get_config((unsigned char *) decSpecInfo, decSpecInfoSize, &a_cfg) != GF_OK) return 0;	/*BSAC not supported*/	if (a_cfg.base_object_type == GF_M4A_ER_BSAC) return 0;	return 1;}GF_BaseDecoder *NewFAADDec(){	GF_MediaDecoder *ifce;	FAADDec *dec;	GF_SAFEALLOC(ifce, GF_MediaDecoder);	GF_SAFEALLOC(dec, FAADDec);	GF_REGISTER_MODULE_INTERFACE(ifce, GF_MEDIA_DECODER_INTERFACE, "FAAD2 Decoder", "gpac distribution")	ifce->privateStack = dec;	/*setup our own interface*/		ifce->AttachStream = FAAD_AttachStream;	ifce->DetachStream = FAAD_DetachStream;	ifce->GetCapabilities = FAAD_GetCapabilities;	ifce->SetCapabilities = FAAD_SetCapabilities;	ifce->ProcessData = FAAD_ProcessData;	ifce->CanHandleStream = FAAD_CanHandleStream;	ifce->GetName = FAAD_GetCodecName;	return (GF_BaseDecoder *) ifce;}void DeleteFAADDec(GF_BaseDecoder *ifcg){	FAADCTX();	if (ctx->codec) faacDecClose(ctx->codec);	free(ctx);	free(ifcg);}#endif

⌨️ 快捷键说明

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