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

📄 vorbis_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 / XIPH.org 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 "ogg_in.h"#ifdef GPAC_HAS_VORBIS#include <vorbis/codec.h>typedef struct{    vorbis_info vi;	vorbis_dsp_state vd;	vorbis_block vb;    vorbis_comment vc;    ogg_packet op;	u16 ES_ID;	Bool has_reconfigured;} VorbDec;#define VORBISCTX() VorbDec *ctx = (VorbDec *) ((OGGWraper *)ifcg->privateStack)->opaquestatic GF_Err VORB_AttachStream(GF_BaseDecoder *ifcg, u16 ES_ID, char *decSpecInfo, u32 decSpecInfoSize, u16 DependsOnES_ID, u32 objectTypeIndication, Bool UpStream){    ogg_packet oggpacket;	GF_BitStream *bs;	VORBISCTX();	if (ctx->ES_ID) return GF_BAD_PARAM;		if (!decSpecInfo || !decSpecInfoSize) return GF_NON_COMPLIANT_BITSTREAM;	if (objectTypeIndication != GPAC_OGG_MEDIA_OTI) return GF_NON_COMPLIANT_BITSTREAM;	if ((decSpecInfoSize<9) || strncmp(&decSpecInfo[3], "vorbis", 6)) return GF_NON_COMPLIANT_BITSTREAM;	ctx->ES_ID = ES_ID;    vorbis_info_init(&ctx->vi);    vorbis_comment_init(&ctx->vc);	oggpacket.granulepos = -1;	oggpacket.b_o_s = 1;	oggpacket.e_o_s = 0;	oggpacket.packetno = 0;	bs = gf_bs_new(decSpecInfo, decSpecInfoSize, GF_BITSTREAM_READ);	while (gf_bs_available(bs)) {		oggpacket.bytes = gf_bs_read_u16(bs);		oggpacket.packet = malloc(sizeof(char) * oggpacket.bytes);		gf_bs_read_data(bs, oggpacket.packet, oggpacket.bytes);		if (vorbis_synthesis_headerin(&ctx->vi, &ctx->vc, &oggpacket) < 0 ) {			free(oggpacket.packet);			gf_bs_del(bs);			return GF_NON_COMPLIANT_BITSTREAM;		}		free(oggpacket.packet);	}	vorbis_synthesis_init(&ctx->vd, &ctx->vi);	vorbis_block_init(&ctx->vd, &ctx->vb); 	gf_bs_del(bs);	return GF_OK;}static GF_Err VORB_DetachStream(GF_BaseDecoder *ifcg, u16 ES_ID){	VORBISCTX();	if (ctx->ES_ID != ES_ID) return GF_BAD_PARAM;	vorbis_block_clear(&ctx->vb); 	vorbis_dsp_clear(&ctx->vd);    vorbis_info_clear(&ctx->vi);    vorbis_comment_clear(&ctx->vc);	ctx->ES_ID = 0;	return GF_OK;}static GF_Err VORB_GetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability *capability){	VORBISCTX();	switch (capability->CapCode) {	case GF_CODEC_RESILIENT:		capability->cap.valueInt = 1;		break;	case GF_CODEC_OUTPUT_SIZE:		capability->cap.valueInt = vorbis_info_blocksize(&ctx->vi, 1) * 2 * ctx->vi.channels;		break;	case GF_CODEC_SAMPLERATE:		capability->cap.valueInt = ctx->vi.rate;		break;	case GF_CODEC_NB_CHAN:		capability->cap.valueInt = ctx->vi.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 = ctx->vi.rate / 4 / vorbis_info_blocksize(&ctx->vi, 0);		/*blocks are not of fixed size, so indicate a default CM size*/		//capability->cap.valueInt = 12 * vorbis_info_blocksize(&ctx->vi, 1) / vorbis_info_blocksize(&ctx->vi, 0);		break;	case GF_CODEC_CU_DURATION:		/*this CANNOT work with vorbis, blocks are not of fixed size*/		capability->cap.valueInt = 0;		break;	case GF_CODEC_PADDING_BYTES:		capability->cap.valueInt = 0;		break;	case GF_CODEC_CHANNEL_CONFIG:		switch (ctx->vi.channels) {		case 1: capability->cap.valueInt = GF_AUDIO_CH_FRONT_CENTER; break;		case 2:			capability->cap.valueInt = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT;			break;		case 3:			capability->cap.valueInt = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT | GF_AUDIO_CH_FRONT_CENTER;			break;		case 4:			capability->cap.valueInt = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT | GF_AUDIO_CH_BACK_LEFT | GF_AUDIO_CH_BACK_RIGHT;			break;		case 5:			capability->cap.valueInt = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT | GF_AUDIO_CH_FRONT_CENTER | GF_AUDIO_CH_BACK_LEFT | GF_AUDIO_CH_BACK_RIGHT;			break;		case 6:			capability->cap.valueInt = GF_AUDIO_CH_FRONT_LEFT | GF_AUDIO_CH_FRONT_RIGHT | GF_AUDIO_CH_FRONT_CENTER | GF_AUDIO_CH_BACK_LEFT | GF_AUDIO_CH_BACK_RIGHT | GF_AUDIO_CH_LFE;			break;		}		break;	default:		capability->cap.valueInt = 0;		break;	}	return GF_OK;}static GF_Err VORB_SetCapabilities(GF_BaseDecoder *ifcg, GF_CodecCapability capability){	/*return unsupported to avoid confusion by the player (like SR changing ...) */	return GF_NOT_SUPPORTED;}static GFINLINE void vorbis_to_intern(u32 samples, Float **pcm, char *buf, u32 channels) {	u32 i, j;	s32 val;	ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;	Float *mono;     for (i=0 ; i<channels ; i++) {		ptr = &data[i];		if (channels>2) {			/*center is third in gpac*/			if (i==1) ptr = &data[2];			/*right is 2nd in gpac*/			else if (i==2) ptr = &data[1];			/*LFE is 4th in gpac*/			if ((channels==6) && (i>3)) {				if (i==6) ptr = &data[4];	/*LFE*/				else ptr = &data[i+1];	/*back l/r*/			}		}		mono = pcm[i];		for (j=0; j<samples; j++) { 			val = (s32) (mono[j] * 32767.f);			if (val > 32767) val = 32767;			if (val < -32768) val = -32768;			*ptr = val;			ptr += channels;		}    }    }static GF_Err VORB_ProcessData(GF_MediaDecoder *ifcg, 		char *inBuffer, u32 inBufferLength,		u16 ES_ID,		char *outBuffer, u32 *outBufferLength,		u8 PaddingBits, u32 mmlevel){	ogg_packet op;    Float **pcm;    u32 samples, total_samples, total_bytes;	VORBISCTX();	/*not using scalabilty*/	assert(ctx->ES_ID == ES_ID);	op.granulepos = -1;	op.b_o_s = 0;	op.e_o_s = 0;	op.packetno = 0;    op.packet = inBuffer;    op.bytes = inBufferLength;	*outBufferLength = 0;	if (vorbis_synthesis(&ctx->vb, &op) == 0) 		vorbis_synthesis_blockin(&ctx->vd, &ctx->vb) ;	/*trust vorbis max block info*/	total_samples = 0;	total_bytes = 0;	while ((samples = vorbis_synthesis_pcmout(&ctx->vd, &pcm)) > 0) {		vorbis_to_intern(samples, pcm, (char*) outBuffer + total_bytes, ctx->vi.channels);		total_bytes += samples * 2 * ctx->vi.channels;		total_samples += samples;		vorbis_synthesis_read(&ctx->vd, samples);	}	*outBufferLength = total_bytes;   	return GF_OK;}static const char *VORB_GetCodecName(GF_BaseDecoder *dec){	return "Vorbis Decoder";}u32 NewVorbisDecoder(GF_BaseDecoder *ifcd){	VorbDec *dec;	GF_SAFEALLOC(dec, VorbDec);	((OGGWraper *)ifcd->privateStack)->opaque = dec;	((OGGWraper *)ifcd->privateStack)->type = OGG_VORBIS;	/*setup our own interface*/		ifcd->AttachStream = VORB_AttachStream;	ifcd->DetachStream = VORB_DetachStream;	ifcd->GetCapabilities = VORB_GetCapabilities;	ifcd->SetCapabilities = VORB_SetCapabilities;	((GF_MediaDecoder*)ifcd)->ProcessData = VORB_ProcessData;	ifcd->GetName = VORB_GetCodecName;	return 1;}void DeleteVorbisDecoder(GF_BaseDecoder *ifcg){	VORBISCTX();	free(ctx);}#endif

⌨️ 快捷键说明

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