Commit afcb6711 authored by Michael Niedermayer's avatar Michael Niedermayer

Revert "Remove libvorbis Vorbis decoding support. Our native decoder is complete"

Its useful to support the official decoder for comparission and debugging.

This reverts commit f9def9cc.

Conflicts:

	Changelog
	configure
	libavcodec/allcodecs.c
	libavcodec/libvorbis.c
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 7c7c5b24
......@@ -198,7 +198,7 @@ External library support:
--enable-libv4l2 enable libv4l2/v4l-utils [no]
--enable-libvo-aacenc enable AAC encoding via libvo-aacenc [no]
--enable-libvo-amrwbenc enable AMR-WB encoding via libvo-amrwbenc [no]
--enable-libvorbis enable Vorbis encoding via libvorbis,
--enable-libvorbis enable Vorbis en/decoding via libvorbis,
native implementation exists [no]
--enable-libvpx enable VP8 support via libvpx [no]
--enable-libx264 enable H.264 encoding via x264 [no]
......@@ -1578,6 +1578,7 @@ libstagefright_h264_decoder_deps="libstagefright_h264"
libtheora_encoder_deps="libtheora"
libvo_aacenc_encoder_deps="libvo_aacenc"
libvo_amrwbenc_encoder_deps="libvo_amrwbenc"
libvorbis_decoder_deps="libvorbis"
libvorbis_encoder_deps="libvorbis"
libvpx_decoder_deps="libvpx"
libvpx_encoder_deps="libvpx"
......
......@@ -420,7 +420,7 @@ void avcodec_register_all(void)
REGISTER_ENCDEC (LIBUTVIDEO, libutvideo);
REGISTER_ENCODER (LIBVO_AACENC, libvo_aacenc);
REGISTER_ENCODER (LIBVO_AMRWBENC, libvo_amrwbenc);
REGISTER_ENCODER (LIBVORBIS, libvorbis);
REGISTER_ENCDEC (LIBVORBIS, libvorbis);
REGISTER_ENCDEC (LIBVPX, libvpx);
REGISTER_ENCODER (LIBX264, libx264);
REGISTER_ENCODER (LIBX264RGB, libx264rgb);
......
......@@ -49,6 +49,7 @@
typedef struct OggVorbisContext {
AVClass *av_class; /**< class for AVOptions */
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 */
......@@ -390,3 +391,170 @@ AVCodec ff_libvorbis_encoder = {
.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; i<op->bytes; 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,
} ;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment