# HG changeset patch # User kabi # Date 1037950033 0 # Node ID b0d29bf1cecd10418870700c8a4bb36566a31eab # Parent 34943cb0c2fbd0c42361ac37923a8ca74e44acd8 * Ogg/Vorbis patch by Mark Hills diff -r 34943cb0c2fb -r b0d29bf1cecd allcodecs.c --- a/allcodecs.c Fri Nov 22 07:24:28 2002 +0000 +++ b/allcodecs.c Fri Nov 22 07:27:13 2002 +0000 @@ -41,6 +41,7 @@ #endif #ifdef CONFIG_VORBIS register_avcodec(&oggvorbis_encoder); + register_avcodec(&oggvorbis_decoder); #endif register_avcodec(&mpeg1video_encoder); register_avcodec(&h263_encoder); diff -r 34943cb0c2fb -r b0d29bf1cecd avcodec.h --- a/avcodec.h Fri Nov 22 07:24:28 2002 +0000 +++ b/avcodec.h Fri Nov 22 07:27:13 2002 +0000 @@ -865,6 +865,7 @@ extern AVCodec mace3_decoder; extern AVCodec mace6_decoder; extern AVCodec huffyuv_decoder; +extern AVCodec oggvorbis_decoder; /* pcm codecs */ #define PCM_CODEC(id, name) \ diff -r 34943cb0c2fb -r b0d29bf1cecd oggvorbis.c --- a/oggvorbis.c Fri Nov 22 07:24:28 2002 +0000 +++ b/oggvorbis.c Fri Nov 22 07:27:13 2002 +0000 @@ -17,22 +17,16 @@ 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 @@ 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 @@ } -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_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 @@ 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, +} ;