1 /*
2 * Copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
3 *
4 * This file is part of FFmpeg.
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <vorbis/vorbisenc.h>
22
23 #include "avcodec.h"
24 #include "bytestream.h"
25 #include "codec_internal.h"
26 #include "internal.h"
27
28 typedef struct OggVorbisDecContext {
29 vorbis_info vi; /**< vorbis_info used during init */
30 vorbis_dsp_state vd; /**< DSP state used for analysis */
31 vorbis_block vb; /**< vorbis_block used for analysis */
32 vorbis_comment vc; /**< VorbisComment info */
33 ogg_packet op; /**< ogg packet */
34 } OggVorbisDecContext;
35
36 static int oggvorbis_decode_close(AVCodecContext *avccontext);
37
oggvorbis_decode_init(AVCodecContext *avccontext)38 static int oggvorbis_decode_init(AVCodecContext *avccontext) {
39 OggVorbisDecContext *context = avccontext->priv_data ;
40 uint8_t *p= avccontext->extradata;
41 int i, hsizes[3], ret;
42 unsigned char *headers[3], *extradata = avccontext->extradata;
43
44 if(! avccontext->extradata_size || ! p) {
45 av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
46 return AVERROR(EINVAL);
47 }
48
49 vorbis_info_init(&context->vi) ;
50 vorbis_comment_init(&context->vc) ;
51
52 if(p[0] == 0 && p[1] == 30) {
53 int sizesum = 0;
54 for(i = 0; i < 3; i++){
55 hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
56 sizesum += 2 + hsizes[i];
57 if (sizesum > avccontext->extradata_size) {
58 av_log(avccontext, AV_LOG_ERROR, "vorbis extradata too small\n");
59 ret = AVERROR_INVALIDDATA;
60 goto error;
61 }
62
63 headers[i] = p;
64 p += hsizes[i];
65 }
66 } else if(*p == 2) {
67 unsigned int offset = 1;
68 unsigned int sizesum = 1;
69 p++;
70 for(i=0; i<2; i++) {
71 hsizes[i] = 0;
72 while((*p == 0xFF) && (sizesum < avccontext->extradata_size)) {
73 hsizes[i] += 0xFF;
74 offset++;
75 sizesum += 1 + 0xFF;
76 p++;
77 }
78 hsizes[i] += *p;
79 offset++;
80 sizesum += 1 + *p;
81 if(sizesum > avccontext->extradata_size) {
82 av_log(avccontext, AV_LOG_ERROR,
83 "vorbis header sizes damaged\n");
84 ret = AVERROR_INVALIDDATA;
85 goto error;
86 }
87 p++;
88 }
89 hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset;
90 #if 0
91 av_log(avccontext, AV_LOG_DEBUG,
92 "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
93 hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size);
94 #endif
95 headers[0] = extradata + offset;
96 headers[1] = extradata + offset + hsizes[0];
97 headers[2] = extradata + offset + hsizes[0] + hsizes[1];
98 } else {
99 av_log(avccontext, AV_LOG_ERROR,
100 "vorbis initial header len is wrong: %d\n", *p);
101 ret = AVERROR_INVALIDDATA;
102 goto error;
103 }
104
105 for(i=0; i<3; i++){
106 context->op.b_o_s= i==0;
107 context->op.bytes = hsizes[i];
108 context->op.packet = headers[i];
109 if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
110 av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
111 ret = AVERROR_INVALIDDATA;
112 goto error;
113 }
114 }
115
116 av_channel_layout_uninit(&avccontext->ch_layout);
117 avccontext->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
118 avccontext->ch_layout.nb_channels = context->vi.channels;
119 avccontext->sample_rate = context->vi.rate;
120 avccontext->sample_fmt = AV_SAMPLE_FMT_S16;
121 avccontext->time_base= (AVRational){1, avccontext->sample_rate};
122
123 vorbis_synthesis_init(&context->vd, &context->vi);
124 vorbis_block_init(&context->vd, &context->vb);
125
126 return 0 ;
127
128 error:
129 oggvorbis_decode_close(avccontext);
130 return ret;
131 }
132
133
conv(int samples, float **pcm, char *buf, int channels)134 static inline int conv(int samples, float **pcm, char *buf, int channels) {
135 int i, j;
136 ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
137 float *mono ;
138
139 for(i = 0 ; i < channels ; i++){
140 ptr = &data[i];
141 mono = pcm[i] ;
142
143 for(j = 0 ; j < samples ; j++) {
144 *ptr = av_clip_int16(mono[j] * 32767.f);
145 ptr += channels;
146 }
147 }
148
149 return 0 ;
150 }
151
oggvorbis_decode_frame(AVCodecContext *avccontext, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt)152 static int oggvorbis_decode_frame(AVCodecContext *avccontext, AVFrame *frame,
153 int *got_frame_ptr, AVPacket *avpkt)
154 {
155 OggVorbisDecContext *context = avccontext->priv_data ;
156 float **pcm ;
157 ogg_packet *op= &context->op;
158 int samples, total_samples, total_bytes;
159 int ret;
160 int16_t *output;
161
162 if(!avpkt->size){
163 //FIXME flush
164 return 0;
165 }
166
167 frame->nb_samples = 8192*4;
168 if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0)
169 return ret;
170 output = (int16_t *)frame->data[0];
171
172
173 op->packet = avpkt->data;
174 op->bytes = avpkt->size;
175
176 // 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);
177
178 /* for(i=0; i<op->bytes; i++)
179 av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
180 av_log(avccontext, AV_LOG_DEBUG, "\n");*/
181
182 if(vorbis_synthesis(&context->vb, op) == 0)
183 vorbis_synthesis_blockin(&context->vd, &context->vb) ;
184
185 total_samples = 0 ;
186 total_bytes = 0 ;
187
188 while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
189 conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ;
190 total_bytes += samples * 2 * context->vi.channels ;
191 total_samples += samples ;
192 vorbis_synthesis_read(&context->vd, samples) ;
193 }
194
195 frame->nb_samples = total_samples;
196 *got_frame_ptr = total_samples > 0;
197 return avpkt->size;
198 }
199
200
oggvorbis_decode_close(AVCodecContext *avccontext)201 static int oggvorbis_decode_close(AVCodecContext *avccontext) {
202 OggVorbisDecContext *context = avccontext->priv_data ;
203
204 vorbis_block_clear(&context->vb);
205 vorbis_dsp_clear(&context->vd);
206 vorbis_info_clear(&context->vi) ;
207 vorbis_comment_clear(&context->vc) ;
208
209 return 0 ;
210 }
211
212
213 const FFCodec ff_libvorbis_decoder = {
214 .p.name = "libvorbis",
215 .p.long_name = NULL_IF_CONFIG_SMALL("libvorbis"),
216 .p.type = AVMEDIA_TYPE_AUDIO,
217 .p.id = AV_CODEC_ID_VORBIS,
218 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF,
219 .priv_data_size = sizeof(OggVorbisDecContext),
220 .init = oggvorbis_decode_init,
221 FF_CODEC_DECODE_CB(oggvorbis_decode_frame),
222 .close = oggvorbis_decode_close,
223 };
224