📄 vorbis_dec.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 + -