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
;
38 int i
, hsizes
[3], ret
;
39 unsigned char *headers
[3], *extradata
= avccontext
->extradata
;
41 if(! avccontext
->extradata_size
|| ! p
) {
42 av_log(avccontext
, AV_LOG_ERROR
, "vorbis extradata absent\n");
43 return AVERROR(EINVAL
);
46 vorbis_info_init(&context
->vi
) ;
47 vorbis_comment_init(&context
->vc
) ;
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");
68 ret
= AVERROR_INVALIDDATA
;
75 hsizes
[2] = avccontext
->extradata_size
- hsizes
[0]-hsizes
[1]-offset
;
77 av_log(avccontext
, AV_LOG_DEBUG
,
78 "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
79 hsizes
[0], hsizes
[1], hsizes
[2], avccontext
->extradata_size
);
81 headers
[0] = extradata
+ offset
;
82 headers
[1] = extradata
+ offset
+ hsizes
[0];
83 headers
[2] = extradata
+ offset
+ hsizes
[0] + hsizes
[1];
85 av_log(avccontext
, AV_LOG_ERROR
,
86 "vorbis initial header len is wrong: %d\n", *p
);
87 ret
= AVERROR_INVALIDDATA
;
92 context
->op
.b_o_s
= i
==0;
93 context
->op
.bytes
= hsizes
[i
];
94 context
->op
.packet
= headers
[i
];
95 if(vorbis_synthesis_headerin(&context
->vi
, &context
->vc
, &context
->op
)<0){
96 av_log(avccontext
, AV_LOG_ERROR
, "%d. vorbis header damaged\n", i
+1);
97 ret
= AVERROR_INVALIDDATA
;
102 avccontext
->channels
= context
->vi
.channels
;
103 avccontext
->sample_rate
= context
->vi
.rate
;
104 avccontext
->sample_fmt
= AV_SAMPLE_FMT_S16
;
105 avccontext
->time_base
= (AVRational
){1, avccontext
->sample_rate
};
107 vorbis_synthesis_init(&context
->vd
, &context
->vi
);
108 vorbis_block_init(&context
->vd
, &context
->vb
);
113 vorbis_info_clear(&context
->vi
);
114 vorbis_comment_clear(&context
->vc
) ;
119 static inline int conv(int samples
, float **pcm
, char *buf
, int channels
) {
121 ogg_int16_t
*ptr
, *data
= (ogg_int16_t
*)buf
;
124 for(i
= 0 ; i
< channels
; i
++){
128 for(j
= 0 ; j
< samples
; j
++) {
129 *ptr
= av_clip_int16(mono
[j
] * 32767.f
);
137 static int oggvorbis_decode_frame(AVCodecContext
*avccontext
, void *data
,
138 int *got_frame_ptr
, AVPacket
*avpkt
)
140 OggVorbisDecContext
*context
= avccontext
->priv_data
;
141 AVFrame
*frame
= data
;
143 ogg_packet
*op
= &context
->op
;
144 int samples
, total_samples
, total_bytes
;
153 frame
->nb_samples
= 8192*4;
154 if ((ret
= ff_get_buffer(avccontext
, frame
, 0)) < 0)
156 output
= (int16_t *)frame
->data
[0];
159 op
->packet
= avpkt
->data
;
160 op
->bytes
= avpkt
->size
;
162 // 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);
164 /* for(i=0; i<op->bytes; i++)
165 av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
166 av_log(avccontext, AV_LOG_DEBUG, "\n");*/
168 if(vorbis_synthesis(&context
->vb
, op
) == 0)
169 vorbis_synthesis_blockin(&context
->vd
, &context
->vb
) ;
174 while((samples
= vorbis_synthesis_pcmout(&context
->vd
, &pcm
)) > 0) {
175 conv(samples
, pcm
, (char*)output
+ total_bytes
, context
->vi
.channels
) ;
176 total_bytes
+= samples
* 2 * context
->vi
.channels
;
177 total_samples
+= samples
;
178 vorbis_synthesis_read(&context
->vd
, samples
) ;
181 frame
->nb_samples
= total_samples
;
182 *got_frame_ptr
= total_samples
> 0;
187 static int oggvorbis_decode_close(AVCodecContext
*avccontext
) {
188 OggVorbisDecContext
*context
= avccontext
->priv_data
;
190 vorbis_info_clear(&context
->vi
) ;
191 vorbis_comment_clear(&context
->vc
) ;
197 AVCodec ff_libvorbis_decoder
= {
199 .long_name
= NULL_IF_CONFIG_SMALL("libvorbis"),
200 .type
= AVMEDIA_TYPE_AUDIO
,
201 .id
= AV_CODEC_ID_VORBIS
,
202 .priv_data_size
= sizeof(OggVorbisDecContext
),
203 .init
= oggvorbis_decode_init
,
204 .decode
= oggvorbis_decode_frame
,
205 .close
= oggvorbis_decode_close
,
206 .capabilities
= CODEC_CAP_DELAY
,