2 * Copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <vorbis/vorbisenc.h>
24 #include "bytestream.h"
27 typedef struct OggVorbisDecContext
{
28 vorbis_info vi
; /**< vorbis_info used during init */
29 vorbis_dsp_state vd
; /**< DSP state used for analysis */
30 vorbis_block vb
; /**< vorbis_block used for analysis */
31 vorbis_comment vc
; /**< VorbisComment info */
32 ogg_packet op
; /**< ogg packet */
33 } OggVorbisDecContext
;
35 static int oggvorbis_decode_init(AVCodecContext
*avccontext
) {
36 OggVorbisDecContext
*context
= avccontext
->priv_data
;
37 uint8_t *p
= avccontext
->extradata
;
39 unsigned char *headers
[3], *extradata
= avccontext
->extradata
;
41 vorbis_info_init(&context
->vi
) ;
42 vorbis_comment_init(&context
->vc
) ;
44 if(! avccontext
->extradata_size
|| ! p
) {
45 av_log(avccontext
, AV_LOG_ERROR
, "vorbis extradata absent\n");
49 if(p
[0] == 0 && p
[1] == 30) {
50 for(i
= 0; i
< 3; i
++){
51 hsizes
[i
] = bytestream_get_be16((const uint8_t **)&p
);
56 unsigned int offset
= 1;
60 while((*p
== 0xFF) && (offset
< avccontext
->extradata_size
)) {
65 if(offset
>= avccontext
->extradata_size
- 1) {
66 av_log(avccontext
, AV_LOG_ERROR
,
67 "vorbis header sizes damaged\n");
74 hsizes
[2] = avccontext
->extradata_size
- hsizes
[0]-hsizes
[1]-offset
;
76 av_log(avccontext
, AV_LOG_DEBUG
,
77 "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
78 hsizes
[0], hsizes
[1], hsizes
[2], avccontext
->extradata_size
);
80 headers
[0] = extradata
+ offset
;
81 headers
[1] = extradata
+ offset
+ hsizes
[0];
82 headers
[2] = extradata
+ offset
+ hsizes
[0] + hsizes
[1];
84 av_log(avccontext
, AV_LOG_ERROR
,
85 "vorbis initial header len is wrong: %d\n", *p
);
90 context
->op
.b_o_s
= i
==0;
91 context
->op
.bytes
= hsizes
[i
];
92 context
->op
.packet
= headers
[i
];
93 if(vorbis_synthesis_headerin(&context
->vi
, &context
->vc
, &context
->op
)<0){
94 av_log(avccontext
, AV_LOG_ERROR
, "%d. vorbis header damaged\n", i
+1);
99 avccontext
->channels
= context
->vi
.channels
;
100 avccontext
->sample_rate
= context
->vi
.rate
;
101 avccontext
->sample_fmt
= AV_SAMPLE_FMT_S16
;
102 avccontext
->time_base
= (AVRational
){1, avccontext
->sample_rate
};
104 vorbis_synthesis_init(&context
->vd
, &context
->vi
);
105 vorbis_block_init(&context
->vd
, &context
->vb
);
111 static inline int conv(int samples
, float **pcm
, char *buf
, int channels
) {
113 ogg_int16_t
*ptr
, *data
= (ogg_int16_t
*)buf
;
116 for(i
= 0 ; i
< channels
; i
++){
120 for(j
= 0 ; j
< samples
; j
++) {
121 *ptr
= av_clip_int16(mono
[j
] * 32767.f
);
129 static int oggvorbis_decode_frame(AVCodecContext
*avccontext
, void *data
,
130 int *got_frame_ptr
, AVPacket
*avpkt
)
132 OggVorbisDecContext
*context
= avccontext
->priv_data
;
133 AVFrame
*frame
= data
;
135 ogg_packet
*op
= &context
->op
;
136 int samples
, total_samples
, total_bytes
;
145 frame
->nb_samples
= 8192*4;
146 if ((ret
= ff_get_buffer(avccontext
, frame
, 0)) < 0)
148 output
= (int16_t *)frame
->data
[0];
151 op
->packet
= avpkt
->data
;
152 op
->bytes
= avpkt
->size
;
154 // 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);
156 /* for(i=0; i<op->bytes; i++)
157 av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
158 av_log(avccontext, AV_LOG_DEBUG, "\n");*/
160 if(vorbis_synthesis(&context
->vb
, op
) == 0)
161 vorbis_synthesis_blockin(&context
->vd
, &context
->vb
) ;
166 while((samples
= vorbis_synthesis_pcmout(&context
->vd
, &pcm
)) > 0) {
167 conv(samples
, pcm
, (char*)output
+ total_bytes
, context
->vi
.channels
) ;
168 total_bytes
+= samples
* 2 * context
->vi
.channels
;
169 total_samples
+= samples
;
170 vorbis_synthesis_read(&context
->vd
, samples
) ;
173 frame
->nb_samples
= total_samples
;
174 *got_frame_ptr
= total_samples
> 0;
179 static int oggvorbis_decode_close(AVCodecContext
*avccontext
) {
180 OggVorbisDecContext
*context
= avccontext
->priv_data
;
182 vorbis_info_clear(&context
->vi
) ;
183 vorbis_comment_clear(&context
->vc
) ;
189 AVCodec ff_libvorbis_decoder
= {
191 .long_name
= NULL_IF_CONFIG_SMALL("libvorbis"),
192 .type
= AVMEDIA_TYPE_AUDIO
,
193 .id
= AV_CODEC_ID_VORBIS
,
194 .priv_data_size
= sizeof(OggVorbisDecContext
),
195 .init
= oggvorbis_decode_init
,
196 .decode
= oggvorbis_decode_frame
,
197 .close
= oggvorbis_decode_close
,
198 .capabilities
= CODEC_CAP_DELAY
,