diff options
author | Mark Hills <mark@pogo.org.uk> | 2002-11-22 07:27:13 +0000 |
---|---|---|
committer | Zdenek Kabelac <kabi@informatics.muni.cz> | 2002-11-22 07:27:13 +0000 |
commit | 3aca208a7b5084a6202e44a82baeaac0026f3dce (patch) | |
tree | 8460dbd82aa40191885696ba08936f15e68ac9d3 /libavcodec/oggvorbis.c | |
parent | 9a7b310d06502c2af068b98bbaf23f8d6d3989e8 (diff) | |
download | ffmpeg-3aca208a7b5084a6202e44a82baeaac0026f3dce.tar.gz |
* Ogg/Vorbis patch by Mark Hills
Originally committed as revision 1268 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/oggvorbis.c')
-rw-r--r-- | libavcodec/oggvorbis.c | 131 |
1 files changed, 111 insertions, 20 deletions
diff --git a/libavcodec/oggvorbis.c b/libavcodec/oggvorbis.c index 5b241ed4f1..1d046a3bb2 100644 --- a/libavcodec/oggvorbis.c +++ b/libavcodec/oggvorbis.c @@ -17,22 +17,16 @@ typedef struct OggVorbisContext { vorbis_info vi ; vorbis_dsp_state vd ; vorbis_block vb ; + + /* decoder */ + vorbis_comment vc ; } OggVorbisContext ; int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) { - if(avccontext->quality) { /* VBR requested */ - - fprintf(stderr, "init_encode: channels=%d quality=%d\n", - avccontext->channels, avccontext->quality) ; - + if(avccontext->quality) /* VBR requested */ return vorbis_encode_init_vbr(vi, avccontext->channels, avccontext->sample_rate, (float)avccontext->quality / 1000) ; - } - - fprintf(stderr, "init_encoder: channels=%d bitrate=%d tolerance=%d\n", - avccontext->channels, avccontext->bit_rate, - avccontext->bit_rate_tolerance) ; return vorbis_encode_init(vi, avccontext->channels, avccontext->sample_rate, -1, avccontext->bit_rate, -1) ; @@ -42,15 +36,11 @@ int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) { static int oggvorbis_encode_init(AVCodecContext *avccontext) { OggVorbisContext *context = avccontext->priv_data ; - fprintf(stderr, "oggvorbis_encode_init\n") ; - vorbis_info_init(&context->vi) ; - if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) { fprintf(stderr, "oggvorbis_encode_init: init_encoder failed") ; return -1 ; } - vorbis_analysis_init(&context->vd, &context->vi) ; vorbis_block_init(&context->vd, &context->vb) ; @@ -60,14 +50,15 @@ static int oggvorbis_encode_init(AVCodecContext *avccontext) { } -int oggvorbis_encode_frame(AVCodecContext *avccontext, unsigned char *packets, +static int oggvorbis_encode_frame(AVCodecContext *avccontext, + unsigned char *packets, int buf_size, void *data) { OggVorbisContext *context = avccontext->priv_data ; float **buffer ; ogg_packet op ; signed char *audio = data ; - int l, samples = buf_size / 16 ; /* samples = OGGVORBIS_FRAME_SIZE */ ; + int l, samples = OGGVORBIS_FRAME_SIZE ; buffer = vorbis_analysis_buffer(&context->vd, samples) ; @@ -100,17 +91,17 @@ int oggvorbis_encode_frame(AVCodecContext *avccontext, unsigned char *packets, } -int oggvorbis_encode_close(AVCodecContext *avccontext) { +static int oggvorbis_encode_close(AVCodecContext *avccontext) { OggVorbisContext *context = avccontext->priv_data ; /* ogg_packet op ; */ - fprintf(stderr, "oggvorbis_encode_close\n") ; - vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */ /* We need to write all the remaining packets into the stream * on closing */ + fprintf(stderr, "fixme: not all packets written on oggvorbis_encode_close()\n") ; + /* while(vorbis_bitrate_flushpacket(&context->vd, &op)) { memcpy(packets + l, &op, sizeof(ogg_packet)) ; @@ -135,6 +126,106 @@ AVCodec oggvorbis_encoder = { oggvorbis_encode_init, oggvorbis_encode_frame, oggvorbis_encode_close -}; +} ; + + +static int oggvorbis_decode_init(AVCodecContext *avccontext) { + OggVorbisContext *context = avccontext->priv_data ; + + vorbis_info_init(&context->vi) ; + vorbis_comment_init(&context->vc) ; + + return 0 ; +} + + +static inline int conv(int samples, float **pcm, char *buf, int channels) { + int i, j, val ; + 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++) { + + val = mono[j] * 32767.f; + + if(val > 32767) val = 32767 ; + if(val < -32768) val = -32768 ; + + *ptr = val ; + ptr += channels; + } + } + + return 0 ; +} + + +static int oggvorbis_decode_frame(AVCodecContext *avccontext, + void *data, int *data_size, + UINT8 *buf, int buf_size) +{ + OggVorbisContext *context = avccontext->priv_data ; + ogg_packet *op = (ogg_packet*)buf ; + float **pcm ; + int samples, total_samples, total_bytes ; + + op->packet = (char*)op + sizeof(ogg_packet) ; /* correct data pointer */ + + if(op->packetno < 3) { + vorbis_synthesis_headerin(&context->vi, &context->vc, op) ; + return buf_size ; + } + + if(op->packetno == 3) { + fprintf(stderr, "vorbis_decode: %d channel, %ldHz, encoder `%s'\n", + context->vi.channels, context->vi.rate, context->vc.vendor); + avccontext->channels = context->vi.channels ; + avccontext->sample_rate = context->vi.rate ; + + vorbis_synthesis_init(&context->vd, &context->vi) ; + vorbis_block_init(&context->vd, &context->vb); + } + + 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*)data + total_bytes, context->vi.channels) ; + total_bytes += samples * 2 * context->vi.channels ; + total_samples += samples ; + vorbis_synthesis_read(&context->vd, samples) ; + } + + *data_size = total_bytes ; + return buf_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 oggvorbis_decoder = { + "vorbis", + CODEC_TYPE_AUDIO, + CODEC_ID_VORBIS, + sizeof(OggVorbisContext), + oggvorbis_decode_init, + NULL, + oggvorbis_decode_close, + oggvorbis_decode_frame, +} ; |