#include "internal.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 */
ogg_packet op; /**< ogg packet */
} OggVorbisDecContext;
+static int oggvorbis_decode_close(AVCodecContext *avccontext);
+
static int oggvorbis_decode_init(AVCodecContext *avccontext) {
OggVorbisDecContext *context = avccontext->priv_data ;
uint8_t *p= avccontext->extradata;
- int i, hsizes[3];
+ int i, hsizes[3], ret;
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;
+ return AVERROR(EINVAL);
}
+ vorbis_info_init(&context->vi) ;
+ vorbis_comment_init(&context->vc) ;
+
if(p[0] == 0 && p[1] == 30) {
for(i = 0; i < 3; i++){
hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
if(offset >= avccontext->extradata_size - 1) {
av_log(avccontext, AV_LOG_ERROR,
"vorbis header sizes damaged\n");
- return -1;
+ ret = AVERROR_INVALIDDATA;
+ goto error;
}
hsizes[i] += *p;
offset++;
} else {
av_log(avccontext, AV_LOG_ERROR,
"vorbis initial header len is wrong: %d\n", *p);
- return -1;
+ ret = AVERROR_INVALIDDATA;
+ goto error;
}
for(i=0; i<3; 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;
+ ret = AVERROR_INVALIDDATA;
+ goto error;
}
}
vorbis_block_init(&context->vd, &context->vb);
return 0 ;
+
+ error:
+ oggvorbis_decode_close(avccontext);
+ return ret;
}
int *got_frame_ptr, AVPacket *avpkt)
{
OggVorbisDecContext *context = avccontext->priv_data ;
+ AVFrame *frame = data;
float **pcm ;
ogg_packet *op= &context->op;
int samples, total_samples, total_bytes;
return 0;
}
- context->frame.nb_samples = 8192*4;
- if ((ret = ff_get_buffer(avccontext, &context->frame)) < 0) {
- av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n");
+ frame->nb_samples = 8192*4;
+ if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0)
return ret;
- }
- output = (int16_t *)context->frame.data[0];
+ output = (int16_t *)frame->data[0];
op->packet = avpkt->data;
vorbis_synthesis_read(&context->vd, samples) ;
}
- context->frame.nb_samples = total_samples;
- *got_frame_ptr = 1;
- *(AVFrame *)data = context->frame;
+ frame->nb_samples = total_samples;
+ *got_frame_ptr = total_samples > 0;
return avpkt->size;
}
static int oggvorbis_decode_close(AVCodecContext *avccontext) {
OggVorbisDecContext *context = avccontext->priv_data ;
+ vorbis_block_clear(&context->vb);
+ vorbis_dsp_clear(&context->vd);
vorbis_info_clear(&context->vi) ;
vorbis_comment_clear(&context->vc) ;
AVCodec ff_libvorbis_decoder = {
.name = "libvorbis",
+ .long_name = NULL_IF_CONFIG_SMALL("libvorbis"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_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"),
+ .capabilities = AV_CODEC_CAP_DELAY,
};