diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 0bc6a0f6e2..9e352a612a 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -680,8 +680,9 @@ OBJS-$(CONFIG_LIBUTVIDEO_ENCODER) += libutvideoenc.o OBJS-$(CONFIG_LIBVO_AACENC_ENCODER) += libvo-aacenc.o mpeg4audio.o \ audio_frame_queue.o OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER) += libvo-amrwbenc.o -OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbis.o audio_frame_queue.o \ - vorbis_data.o vorbis_parser.o +OBJS-$(CONFIG_LIBVORBIS_DECODER) += libvorbisdec.o +OBJS-$(CONFIG_LIBVORBIS_ENCODER) += libvorbisenc.o audio_frame_queue.o \ + vorbis_data.o vorbis_parser.o xiph.o OBJS-$(CONFIG_LIBVPX_DECODER) += libvpxdec.o OBJS-$(CONFIG_LIBVPX_ENCODER) += libvpxenc.o OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o diff --git a/libavcodec/libvorbisdec.c b/libavcodec/libvorbisdec.c new file mode 100644 index 0000000000..b9e5fe1232 --- /dev/null +++ b/libavcodec/libvorbisdec.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2002 Mark Hills + * + * This file is part of FFmpeg. + * + * FFmpeg 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.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "avcodec.h" +#include "bytestream.h" + +typedef struct OggVorbisDecContext { + AVFrame frame; + vorbis_info vi; /**< vorbis_info used during init */ + vorbis_dsp_state vd; /**< DSP state used for analysis */ + vorbis_block vb; /**< vorbis_block used for analysis */ + vorbis_comment vc; /**< VorbisComment info */ + ogg_packet op; /**< ogg packet */ +} OggVorbisDecContext; + +static int oggvorbis_decode_init(AVCodecContext *avccontext) { + OggVorbisDecContext *context = avccontext->priv_data ; + uint8_t *p= avccontext->extradata; + int i, hsizes[3]; + unsigned char *headers[3], *extradata = avccontext->extradata; + + vorbis_info_init(&context->vi) ; + vorbis_comment_init(&context->vc) ; + + if(! avccontext->extradata_size || ! p) { + av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n"); + return -1; + } + + if(p[0] == 0 && p[1] == 30) { + for(i = 0; i < 3; i++){ + hsizes[i] = bytestream_get_be16(&p); + headers[i] = p; + p += hsizes[i]; + } + } else if(*p == 2) { + unsigned int offset = 1; + p++; + for(i=0; i<2; i++) { + hsizes[i] = 0; + while((*p == 0xFF) && (offset < avccontext->extradata_size)) { + hsizes[i] += 0xFF; + offset++; + p++; + } + if(offset >= avccontext->extradata_size - 1) { + av_log(avccontext, AV_LOG_ERROR, + "vorbis header sizes damaged\n"); + return -1; + } + hsizes[i] += *p; + offset++; + p++; + } + hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset; +#if 0 + av_log(avccontext, AV_LOG_DEBUG, + "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n", + hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size); +#endif + headers[0] = extradata + offset; + headers[1] = extradata + offset + hsizes[0]; + headers[2] = extradata + offset + hsizes[0] + hsizes[1]; + } else { + av_log(avccontext, AV_LOG_ERROR, + "vorbis initial header len is wrong: %d\n", *p); + return -1; + } + + for(i=0; i<3; i++){ + context->op.b_o_s= i==0; + context->op.bytes = hsizes[i]; + context->op.packet = headers[i]; + if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){ + av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1); + return -1; + } + } + + avccontext->channels = context->vi.channels; + avccontext->sample_rate = context->vi.rate; + avccontext->time_base= (AVRational){1, avccontext->sample_rate}; + + vorbis_synthesis_init(&context->vd, &context->vi); + vorbis_block_init(&context->vd, &context->vb); + + return 0 ; +} + + +static inline int conv(int samples, float **pcm, char *buf, int channels) { + int i, j; + ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ; + float *mono ; + + for(i = 0 ; i < channels ; i++){ + ptr = &data[i]; + mono = pcm[i] ; + + for(j = 0 ; j < samples ; j++) { + *ptr = av_clip_int16(mono[j] * 32767.f); + ptr += channels; + } + } + + return 0 ; +} + +static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data, + int *got_frame_ptr, AVPacket *avpkt) +{ + OggVorbisDecContext *context = avccontext->priv_data ; + float **pcm ; + ogg_packet *op= &context->op; + int samples, total_samples, total_bytes; + int ret; + int16_t *output; + + if(!avpkt->size){ + //FIXME flush + return 0; + } + + context->frame.nb_samples = 8192*4; + if ((ret = avccontext->get_buffer(avccontext, &context->frame)) < 0) { + av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n"); + return ret; + } + output = (int16_t *)context->frame.data[0]; + + + op->packet = avpkt->data; + op->bytes = avpkt->size; + +// av_log(avccontext, AV_LOG_DEBUG, "%d %d %d %"PRId64" %"PRId64" %d %d\n", op->bytes, op->b_o_s, op->e_o_s, op->granulepos, op->packetno, buf_size, context->vi.rate); + +/* for(i=0; ibytes; i++) + av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]); + av_log(avccontext, AV_LOG_DEBUG, "\n");*/ + + if(vorbis_synthesis(&context->vb, op) == 0) + vorbis_synthesis_blockin(&context->vd, &context->vb) ; + + total_samples = 0 ; + total_bytes = 0 ; + + while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) { + conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ; + total_bytes += samples * 2 * context->vi.channels ; + total_samples += samples ; + vorbis_synthesis_read(&context->vd, samples) ; + } + + context->frame.nb_samples = total_samples; + *got_frame_ptr = 1; + *(AVFrame *)data = context->frame; + return avpkt->size; +} + + +static int oggvorbis_decode_close(AVCodecContext *avccontext) { + OggVorbisDecContext *context = avccontext->priv_data ; + + vorbis_info_clear(&context->vi) ; + vorbis_comment_clear(&context->vc) ; + + return 0 ; +} + + +AVCodec ff_libvorbis_decoder = { + .name = "libvorbis", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_VORBIS, + .priv_data_size = sizeof(OggVorbisDecContext), + .init = oggvorbis_decode_init, + .decode = oggvorbis_decode_frame, + .close = oggvorbis_decode_close, + .capabilities = CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("libvorbis"), +}; diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbisenc.c similarity index 69% rename from libavcodec/libvorbis.c rename to libavcodec/libvorbisenc.c index 1324e49e87..7422a35b18 100644 --- a/libavcodec/libvorbis.c +++ b/libavcodec/libvorbisenc.c @@ -1,5 +1,5 @@ /* - * copyright (c) 2002 Mark Hills + * Copyright (c) 2002 Mark Hills * * This file is part of FFmpeg. * @@ -18,19 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/** - * @file - * Vorbis encoding support via libvorbisenc. - * @author Mark Hills - */ - #include #include "libavutil/fifo.h" #include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" -#include "bytestream.h" #include "internal.h" #include "vorbis.h" #include "vorbis_parser.h" @@ -47,7 +40,7 @@ #define BUFFER_SIZE (1024 * 64) -typedef struct OggVorbisContext { +typedef struct OggVorbisEncContext { AVClass *av_class; /**< class for AVOptions */ AVFrame frame; vorbis_info vi; /**< vorbis_info used during init */ @@ -57,14 +50,13 @@ typedef struct OggVorbisContext { int eof; /**< end-of-file flag */ int dsp_initialized; /**< vd has been initialized */ vorbis_comment vc; /**< VorbisComment info */ - ogg_packet op; /**< ogg packet */ double iblock; /**< impulse block bias option */ VorbisParseContext vp; /**< parse context to get durations */ AudioFrameQueue afq; /**< frame queue for timestamps */ -} OggVorbisContext; +} OggVorbisEncContext; static const AVOption options[] = { - { "iblock", "Sets the impulse block bias", offsetof(OggVorbisContext, iblock), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, -15, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "iblock", "Sets the impulse block bias", offsetof(OggVorbisEncContext, iblock), AV_OPT_TYPE_DOUBLE, { .dbl = 0 }, -15, 0, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, { NULL } }; @@ -89,7 +81,7 @@ static int vorbis_error_to_averror(int ov_err) static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avctx) { - OggVorbisContext *s = avctx->priv_data; + OggVorbisEncContext *s = avctx->priv_data; double cfreq; int ret; @@ -180,7 +172,7 @@ static int xiph_len(int l) static av_cold int oggvorbis_encode_close(AVCodecContext *avctx) { - OggVorbisContext *s = avctx->priv_data; + OggVorbisEncContext *s = avctx->priv_data; /* notify vorbisenc this is EOF */ if (s->dsp_initialized) @@ -202,7 +194,7 @@ static av_cold int oggvorbis_encode_close(AVCodecContext *avctx) static av_cold int oggvorbis_encode_init(AVCodecContext *avctx) { - OggVorbisContext *s = avctx->priv_data; + OggVorbisEncContext *s = avctx->priv_data; ogg_packet header, header_comm, header_code; uint8_t *p; unsigned int offset; @@ -289,7 +281,7 @@ error: static int oggvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { - OggVorbisContext *s = avctx->priv_data; + OggVorbisEncContext *s = avctx->priv_data; ogg_packet op; int ret, duration; @@ -381,180 +373,14 @@ AVCodec ff_libvorbis_encoder = { .name = "libvorbis", .type = AVMEDIA_TYPE_AUDIO, .id = CODEC_ID_VORBIS, - .priv_data_size = sizeof(OggVorbisContext), + .priv_data_size = sizeof(OggVorbisEncContext), .init = oggvorbis_encode_init, .encode2 = oggvorbis_encode_frame, .close = oggvorbis_encode_close, .capabilities = CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, - .long_name = NULL_IF_CONFIG_SMALL("libvorbis Vorbis"), + .long_name = NULL_IF_CONFIG_SMALL("libvorbis"), .priv_class = &class, .defaults = defaults, }; - -static int oggvorbis_decode_init(AVCodecContext *avccontext) { - OggVorbisContext *context = avccontext->priv_data ; - uint8_t *p= avccontext->extradata; - int i, hsizes[3]; - unsigned char *headers[3], *extradata = avccontext->extradata; - - vorbis_info_init(&context->vi) ; - vorbis_comment_init(&context->vc) ; - - if(! avccontext->extradata_size || ! p) { - av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n"); - return -1; - } - - if(p[0] == 0 && p[1] == 30) { - for(i = 0; i < 3; i++){ - hsizes[i] = bytestream_get_be16(&p); - headers[i] = p; - p += hsizes[i]; - } - } else if(*p == 2) { - unsigned int offset = 1; - p++; - for(i=0; i<2; i++) { - hsizes[i] = 0; - while((*p == 0xFF) && (offset < avccontext->extradata_size)) { - hsizes[i] += 0xFF; - offset++; - p++; - } - if(offset >= avccontext->extradata_size - 1) { - av_log(avccontext, AV_LOG_ERROR, - "vorbis header sizes damaged\n"); - return -1; - } - hsizes[i] += *p; - offset++; - p++; - } - hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset; -#if 0 - av_log(avccontext, AV_LOG_DEBUG, - "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n", - hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size); -#endif - headers[0] = extradata + offset; - headers[1] = extradata + offset + hsizes[0]; - headers[2] = extradata + offset + hsizes[0] + hsizes[1]; - } else { - av_log(avccontext, AV_LOG_ERROR, - "vorbis initial header len is wrong: %d\n", *p); - return -1; - } - - for(i=0; i<3; i++){ - context->op.b_o_s= i==0; - context->op.bytes = hsizes[i]; - context->op.packet = headers[i]; - if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){ - av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1); - return -1; - } - } - - avccontext->channels = context->vi.channels; - avccontext->sample_rate = context->vi.rate; - avccontext->time_base= (AVRational){1, avccontext->sample_rate}; - - vorbis_synthesis_init(&context->vd, &context->vi); - vorbis_block_init(&context->vd, &context->vb); - - return 0 ; -} - - -static inline int conv(int samples, float **pcm, char *buf, int channels) { - int i, j; - ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ; - float *mono ; - - for(i = 0 ; i < channels ; i++){ - ptr = &data[i]; - mono = pcm[i] ; - - for(j = 0 ; j < samples ; j++) { - *ptr = av_clip_int16(mono[j] * 32767.f); - ptr += channels; - } - } - - return 0 ; -} - -static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data, - int *got_frame_ptr, AVPacket *avpkt) -{ - OggVorbisContext *context = avccontext->priv_data ; - float **pcm ; - ogg_packet *op= &context->op; - int samples, total_samples, total_bytes; - int ret; - int16_t *output; - - if(!avpkt->size){ - //FIXME flush - return 0; - } - - context->frame.nb_samples = 8192*4; - if ((ret = avccontext->get_buffer(avccontext, &context->frame)) < 0) { - av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n"); - return ret; - } - output = (int16_t *)context->frame.data[0]; - - - op->packet = avpkt->data; - op->bytes = avpkt->size; - -// av_log(avccontext, AV_LOG_DEBUG, "%d %d %d %"PRId64" %"PRId64" %d %d\n", op->bytes, op->b_o_s, op->e_o_s, op->granulepos, op->packetno, buf_size, context->vi.rate); - -/* for(i=0; ibytes; i++) - av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]); - av_log(avccontext, AV_LOG_DEBUG, "\n");*/ - - if(vorbis_synthesis(&context->vb, op) == 0) - vorbis_synthesis_blockin(&context->vd, &context->vb) ; - - total_samples = 0 ; - total_bytes = 0 ; - - while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) { - conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ; - total_bytes += samples * 2 * context->vi.channels ; - total_samples += samples ; - vorbis_synthesis_read(&context->vd, samples) ; - } - - context->frame.nb_samples = total_samples; - *got_frame_ptr = 1; - *(AVFrame *)data = context->frame; - return avpkt->size; -} - - -static int oggvorbis_decode_close(AVCodecContext *avccontext) { - OggVorbisContext *context = avccontext->priv_data ; - - vorbis_info_clear(&context->vi) ; - vorbis_comment_clear(&context->vc) ; - - return 0 ; -} - - -AVCodec ff_libvorbis_decoder = { - .name = "libvorbis", - .type = AVMEDIA_TYPE_AUDIO, - .id = CODEC_ID_VORBIS, - .priv_data_size = sizeof(OggVorbisContext), - .init = oggvorbis_decode_init, - .decode = oggvorbis_decode_frame, - .close = oggvorbis_decode_close, - .capabilities = CODEC_CAP_DELAY, -} ;