Statistics
| Branch: | Revision:

ffmpeg / libavcodec / libvorbis.c @ 6f1af735

History | View | Annotate | Download (11.6 KB)

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 St, Fifth Floor, Boston, MA  02110-1301  USA
19
 */
20

    
21
/**
22
 * @file oggvorbis.c
23
 * Ogg Vorbis codec support via libvorbisenc.
24
 * @author Mark Hills <mark@pogo.org.uk>
25
 */
26

    
27
#include <vorbis/vorbisenc.h>
28

    
29
#include "avcodec.h"
30
#include "bytestream.h"
31

    
32
#undef NDEBUG
33
#include <assert.h>
34

    
35
#define OGGVORBIS_FRAME_SIZE 64
36

    
37
#define BUFFER_SIZE (1024*64)
38

    
39
typedef struct OggVorbisContext {
40
    vorbis_info vi ;
41
    vorbis_dsp_state vd ;
42
    vorbis_block vb ;
43
    uint8_t buffer[BUFFER_SIZE];
44
    int buffer_index;
45

    
46
    /* decoder */
47
    vorbis_comment vc ;
48
    ogg_packet op;
49
} OggVorbisContext ;
50

    
51

    
52
static int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
53
    double cfreq;
54

    
55
    if(avccontext->flags & CODEC_FLAG_QSCALE) {
56
        /* variable bitrate */
57
        if(vorbis_encode_setup_vbr(vi, avccontext->channels,
58
                avccontext->sample_rate,
59
                avccontext->global_quality / (float)FF_QP2LAMBDA))
60
            return -1;
61
    } else {
62
        /* constant bitrate */
63
        if(vorbis_encode_setup_managed(vi, avccontext->channels,
64
                avccontext->sample_rate, -1, avccontext->bit_rate, -1))
65
            return -1;
66

    
67
#ifdef OGGVORBIS_VBR_BY_ESTIMATE
68
        /* variable bitrate by estimate */
69
        if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL))
70
            return -1;
71
#endif
72
    }
73

    
74
    /* cutoff frequency */
75
    if(avccontext->cutoff > 0) {
76
        cfreq = avccontext->cutoff / 1000.0;
77
        if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))
78
            return -1;
79
    }
80

    
81
    return vorbis_encode_setup_init(vi);
82
}
83

    
84
static int oggvorbis_encode_init(AVCodecContext *avccontext) {
85
    OggVorbisContext *context = avccontext->priv_data ;
86
    ogg_packet header, header_comm, header_code;
87
    uint8_t *p;
88
    unsigned int offset, len;
89

    
90
    vorbis_info_init(&context->vi) ;
91
    if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
92
        av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed") ;
93
        return -1 ;
94
    }
95
    vorbis_analysis_init(&context->vd, &context->vi) ;
96
    vorbis_block_init(&context->vd, &context->vb) ;
97

    
98
    vorbis_comment_init(&context->vc);
99
    vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT) ;
100

    
101
    vorbis_analysis_headerout(&context->vd, &context->vc, &header,
102
                                &header_comm, &header_code);
103

    
104
    len = header.bytes + header_comm.bytes +  header_code.bytes;
105
    avccontext->extradata_size= 64 + len + len/255;
106
    p = avccontext->extradata= av_mallocz(avccontext->extradata_size);
107
    p[0] = 2;
108
    offset = 1;
109
    offset += av_xiphlacing(&p[offset], header.bytes);
110
    offset += av_xiphlacing(&p[offset], header_comm.bytes);
111
    memcpy(&p[offset], header.packet, header.bytes);
112
    offset += header.bytes;
113
    memcpy(&p[offset], header_comm.packet, header_comm.bytes);
114
    offset += header_comm.bytes;
115
    memcpy(&p[offset], header_code.packet, header_code.bytes);
116
    offset += header_code.bytes;
117
    avccontext->extradata_size = offset;
118
    avccontext->extradata= av_realloc(avccontext->extradata, avccontext->extradata_size);
119

    
120
/*    vorbis_block_clear(&context->vb);
121
    vorbis_dsp_clear(&context->vd);
122
    vorbis_info_clear(&context->vi);*/
123
    vorbis_comment_clear(&context->vc);
124

    
125
    avccontext->frame_size = OGGVORBIS_FRAME_SIZE ;
126

    
127
    avccontext->coded_frame= avcodec_alloc_frame();
128
    avccontext->coded_frame->key_frame= 1;
129

    
130
    return 0 ;
131
}
132

    
133

    
134
static int oggvorbis_encode_frame(AVCodecContext *avccontext,
135
                                  unsigned char *packets,
136
                           int buf_size, void *data)
137
{
138
    OggVorbisContext *context = avccontext->priv_data ;
139
    float **buffer ;
140
    ogg_packet op ;
141
    signed short *audio = data ;
142
    int l, samples = data ? OGGVORBIS_FRAME_SIZE : 0;
143

    
144
    buffer = vorbis_analysis_buffer(&context->vd, samples) ;
145

    
146
    if(context->vi.channels == 1) {
147
        for(l = 0 ; l < samples ; l++)
148
            buffer[0][l]=audio[l]/32768.f;
149
    } else {
150
        for(l = 0 ; l < samples ; l++){
151
            buffer[0][l]=audio[l*2]/32768.f;
152
            buffer[1][l]=audio[l*2+1]/32768.f;
153
        }
154
    }
155

    
156
    vorbis_analysis_wrote(&context->vd, samples) ;
157

    
158
    while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) {
159
        vorbis_analysis(&context->vb, NULL);
160
        vorbis_bitrate_addblock(&context->vb) ;
161

    
162
        while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
163
            /* i'd love to say the following line is a hack, but sadly it's
164
             * not, apparently the end of stream decision is in libogg. */
165
            if(op.bytes==1)
166
                continue;
167
            memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet));
168
            context->buffer_index += sizeof(ogg_packet);
169
            memcpy(context->buffer + context->buffer_index, op.packet, op.bytes);
170
            context->buffer_index += op.bytes;
171
//            av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes);
172
        }
173
    }
174

    
175
    l=0;
176
    if(context->buffer_index){
177
        ogg_packet *op2= (ogg_packet*)context->buffer;
178
        op2->packet = context->buffer + sizeof(ogg_packet);
179

    
180
        l=  op2->bytes;
181
        avccontext->coded_frame->pts= av_rescale_q(op2->granulepos, (AVRational){1, avccontext->sample_rate}, avccontext->time_base);
182
        //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate
183

    
184
        memcpy(packets, op2->packet, l);
185
        context->buffer_index -= l + sizeof(ogg_packet);
186
        memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index);
187
//        av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l);
188
    }
189

    
190
    return l;
191
}
192

    
193

    
194
static int oggvorbis_encode_close(AVCodecContext *avccontext) {
195
    OggVorbisContext *context = avccontext->priv_data ;
196
/*  ogg_packet op ; */
197

    
198
    vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */
199

    
200
    vorbis_block_clear(&context->vb);
201
    vorbis_dsp_clear(&context->vd);
202
    vorbis_info_clear(&context->vi);
203

    
204
    av_freep(&avccontext->coded_frame);
205
    av_freep(&avccontext->extradata);
206

    
207
    return 0 ;
208
}
209

    
210

    
211
AVCodec libvorbis_encoder = {
212
    "libvorbis",
213
    CODEC_TYPE_AUDIO,
214
    CODEC_ID_VORBIS,
215
    sizeof(OggVorbisContext),
216
    oggvorbis_encode_init,
217
    oggvorbis_encode_frame,
218
    oggvorbis_encode_close,
219
    .capabilities= CODEC_CAP_DELAY,
220
} ;
221

    
222
static int oggvorbis_decode_init(AVCodecContext *avccontext) {
223
    OggVorbisContext *context = avccontext->priv_data ;
224
    uint8_t *p= avccontext->extradata;
225
    int i, hsizes[3];
226
    unsigned char *headers[3], *extradata = avccontext->extradata;
227

    
228
    vorbis_info_init(&context->vi) ;
229
    vorbis_comment_init(&context->vc) ;
230

    
231
    if(! avccontext->extradata_size || ! p) {
232
        av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
233
        return -1;
234
    }
235

    
236
    if(p[0] == 0 && p[1] == 30) {
237
        for(i = 0; i < 3; i++){
238
            hsizes[i] = bytestream_get_be16(&p);
239
            headers[i] = p;
240
            p += hsizes[i];
241
        }
242
    } else if(*p == 2) {
243
        unsigned int offset = 1;
244
        p++;
245
        for(i=0; i<2; i++) {
246
            hsizes[i] = 0;
247
            while((*p == 0xFF) && (offset < avccontext->extradata_size)) {
248
                hsizes[i] += 0xFF;
249
                offset++;
250
                p++;
251
            }
252
            if(offset >= avccontext->extradata_size - 1) {
253
                av_log(avccontext, AV_LOG_ERROR,
254
                       "vorbis header sizes damaged\n");
255
                return -1;
256
            }
257
            hsizes[i] += *p;
258
            offset++;
259
            p++;
260
        }
261
        hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset;
262
#if 0
263
        av_log(avccontext, AV_LOG_DEBUG,
264
               "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
265
               hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size);
266
#endif
267
        headers[0] = extradata + offset;
268
        headers[1] = extradata + offset + hsizes[0];
269
        headers[2] = extradata + offset + hsizes[0] + hsizes[1];
270
    } else {
271
        av_log(avccontext, AV_LOG_ERROR,
272
               "vorbis initial header len is wrong: %d\n", *p);
273
        return -1;
274
    }
275

    
276
    for(i=0; i<3; i++){
277
        context->op.b_o_s= i==0;
278
        context->op.bytes = hsizes[i];
279
        context->op.packet = headers[i];
280
        if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
281
            av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
282
            return -1;
283
        }
284
    }
285

    
286
    avccontext->channels = context->vi.channels;
287
    avccontext->sample_rate = context->vi.rate;
288
    avccontext->time_base= (AVRational){1, avccontext->sample_rate};
289

    
290
    vorbis_synthesis_init(&context->vd, &context->vi);
291
    vorbis_block_init(&context->vd, &context->vb);
292

    
293
    return 0 ;
294
}
295

    
296

    
297
static inline int conv(int samples, float **pcm, char *buf, int channels) {
298
    int i, j, val ;
299
    ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
300
    float *mono ;
301

    
302
    for(i = 0 ; i < channels ; i++){
303
        ptr = &data[i];
304
        mono = pcm[i] ;
305

    
306
        for(j = 0 ; j < samples ; j++) {
307

    
308
            val = mono[j] * 32767.f;
309

    
310
            if(val > 32767) val = 32767 ;
311
            if(val < -32768) val = -32768 ;
312

    
313
            *ptr = val ;
314
            ptr += channels;
315
        }
316
    }
317

    
318
    return 0 ;
319
}
320

    
321

    
322
static int oggvorbis_decode_frame(AVCodecContext *avccontext,
323
                        void *data, int *data_size,
324
                        uint8_t *buf, int buf_size)
325
{
326
    OggVorbisContext *context = avccontext->priv_data ;
327
    float **pcm ;
328
    ogg_packet *op= &context->op;
329
    int samples, total_samples, total_bytes;
330

    
331
    if(!buf_size){
332
    //FIXME flush
333
        return 0;
334
    }
335

    
336
    op->packet = buf;
337
    op->bytes  = buf_size;
338

    
339
//    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);
340

    
341
/*    for(i=0; i<op->bytes; i++)
342
      av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
343
    av_log(avccontext, AV_LOG_DEBUG, "\n");*/
344

    
345
    if(vorbis_synthesis(&context->vb, op) == 0)
346
        vorbis_synthesis_blockin(&context->vd, &context->vb) ;
347

    
348
    total_samples = 0 ;
349
    total_bytes = 0 ;
350

    
351
    while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
352
        conv(samples, pcm, (char*)data + total_bytes, context->vi.channels) ;
353
        total_bytes += samples * 2 * context->vi.channels ;
354
        total_samples += samples ;
355
        vorbis_synthesis_read(&context->vd, samples) ;
356
    }
357

    
358
    *data_size = total_bytes ;
359
    return buf_size ;
360
}
361

    
362

    
363
static int oggvorbis_decode_close(AVCodecContext *avccontext) {
364
    OggVorbisContext *context = avccontext->priv_data ;
365

    
366
    vorbis_info_clear(&context->vi) ;
367
    vorbis_comment_clear(&context->vc) ;
368

    
369
    return 0 ;
370
}
371

    
372

    
373
AVCodec libvorbis_decoder = {
374
    "libvorbis",
375
    CODEC_TYPE_AUDIO,
376
    CODEC_ID_VORBIS,
377
    sizeof(OggVorbisContext),
378
    oggvorbis_decode_init,
379
    NULL,
380
    oggvorbis_decode_close,
381
    oggvorbis_decode_frame,
382
    .capabilities= CODEC_CAP_DELAY,
383
} ;