Statistics
| Branch: | Revision:

ffmpeg / libavcodec / oggvorbis.c @ da9c9637

History | View | Annotate | Download (8.39 KB)

1 983e3246 Michael Niedermayer
/**
2
 * @file oggvorbis.c
3
 * Ogg Vorbis codec support via libvorbisenc.
4
 * @author Mark Hills <mark@pogo.org.uk>
5 81e0d0b4 Mark Hills
 */
6
7
#include <vorbis/vorbisenc.h>
8
9
#include "avcodec.h"
10
11 3f4993f1 Michael Niedermayer
#undef NDEBUG
12
#include <assert.h>
13
14 6d8f985e Michael Niedermayer
#define OGGVORBIS_FRAME_SIZE 64
15 81e0d0b4 Mark Hills
16 6d8f985e Michael Niedermayer
#define BUFFER_SIZE (1024*64)
17 81e0d0b4 Mark Hills
18
typedef struct OggVorbisContext {
19
    vorbis_info vi ;
20
    vorbis_dsp_state vd ;
21
    vorbis_block vb ;
22 6d8f985e Michael Niedermayer
    uint8_t buffer[BUFFER_SIZE];
23
    int buffer_index;
24 3aca208a Mark Hills
25
    /* decoder */
26
    vorbis_comment vc ;
27 d76f581f Michael Niedermayer
    ogg_packet op;
28 81e0d0b4 Mark Hills
} OggVorbisContext ;
29
30
31 bbb77e7c Michael Niedermayer
static int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
32 c55427f8 Mark Hills
33
#ifdef OGGVORBIS_VBR_BY_ESTIMATE
34
    /* variable bitrate by estimate */
35
36
    return (vorbis_encode_setup_managed(vi, avccontext->channels,
37
              avccontext->sample_rate, -1, avccontext->bit_rate, -1) ||
38
            vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL) ||
39
            vorbis_encode_setup_init(vi)) ;
40
#else
41
    /* constant bitrate */
42 81e0d0b4 Mark Hills
43
    return vorbis_encode_init(vi, avccontext->channels,
44
                  avccontext->sample_rate, -1, avccontext->bit_rate, -1) ;
45 c55427f8 Mark Hills
#endif
46 81e0d0b4 Mark Hills
}
47
48
static int oggvorbis_encode_init(AVCodecContext *avccontext) {
49
    OggVorbisContext *context = avccontext->priv_data ;
50 bbb77e7c Michael Niedermayer
    ogg_packet header, header_comm, header_code;
51
    uint8_t *p;
52 81e0d0b4 Mark Hills
53
    vorbis_info_init(&context->vi) ;
54
    if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
55 9b879566 Michel Bardiaux
        av_log(avccontext, AV_LOG_ERROR, "oggvorbis_encode_init: init_encoder failed") ;
56 81e0d0b4 Mark Hills
        return -1 ;
57
    }
58
    vorbis_analysis_init(&context->vd, &context->vi) ;
59
    vorbis_block_init(&context->vd, &context->vb) ;
60
61 bbb77e7c Michael Niedermayer
    vorbis_comment_init(&context->vc);
62
    vorbis_comment_add_tag(&context->vc, "encoder", LIBAVCODEC_IDENT) ;
63
64
    vorbis_analysis_headerout(&context->vd, &context->vc, &header,
65
                                &header_comm, &header_code);
66
    
67
    avccontext->extradata_size= 3*2 + header.bytes + header_comm.bytes +  header_code.bytes;
68
    p= avccontext->extradata= av_mallocz(avccontext->extradata_size);
69
    
70
    *(p++) = header.bytes>>8;
71
    *(p++) = header.bytes&0xFF;
72
    memcpy(p, header.packet, header.bytes);
73
    p += header.bytes;
74
    
75
    *(p++) = header_comm.bytes>>8;
76
    *(p++) = header_comm.bytes&0xFF;
77
    memcpy(p, header_comm.packet, header_comm.bytes);
78
    p += header_comm.bytes;
79
    
80
    *(p++) = header_code.bytes>>8;
81
    *(p++) = header_code.bytes&0xFF;
82
    memcpy(p, header_code.packet, header_code.bytes);
83
                                
84
/*    vorbis_block_clear(&context->vb);
85
    vorbis_dsp_clear(&context->vd);
86
    vorbis_info_clear(&context->vi);*/
87
    vorbis_comment_clear(&context->vc);
88
       
89 81e0d0b4 Mark Hills
    avccontext->frame_size = OGGVORBIS_FRAME_SIZE ;
90 492cd3a9 Michael Niedermayer
 
91
    avccontext->coded_frame= avcodec_alloc_frame();
92
    avccontext->coded_frame->key_frame= 1;
93 81e0d0b4 Mark Hills
    
94
    return 0 ;
95
}
96
97
98 3aca208a Mark Hills
static int oggvorbis_encode_frame(AVCodecContext *avccontext,
99
                                  unsigned char *packets,
100 81e0d0b4 Mark Hills
                           int buf_size, void *data)
101
{
102
    OggVorbisContext *context = avccontext->priv_data ;
103
    float **buffer ;
104
    ogg_packet op ;
105
    signed char *audio = data ;
106 6f824977 Michael Niedermayer
    int l, samples = data ? OGGVORBIS_FRAME_SIZE : 0;
107 81e0d0b4 Mark Hills
108
    buffer = vorbis_analysis_buffer(&context->vd, samples) ;
109
110
    if(context->vi.channels == 1) {
111
        for(l = 0 ; l < samples ; l++)
112
            buffer[0][l]=((audio[l*2+1]<<8)|(0x00ff&(int)audio[l*2]))/32768.f;
113
    } else {
114
        for(l = 0 ; l < samples ; l++){
115
            buffer[0][l]=((audio[l*4+1]<<8)|(0x00ff&(int)audio[l*4]))/32768.f;
116
            buffer[1][l]=((audio[l*4+3]<<8)|(0x00ff&(int)audio[l*4+2]))/32768.f;
117
        }
118
    }
119
    
120
    vorbis_analysis_wrote(&context->vd, samples) ; 
121
122
    while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) {
123
        vorbis_analysis(&context->vb, NULL);
124
        vorbis_bitrate_addblock(&context->vb) ;
125
126
        while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
127 6f824977 Michael Niedermayer
            if(op.bytes==1) //id love to say this is a hack, bad sadly its not, appearently the end of stream decission is in libogg
128
                continue;
129 6d8f985e Michael Niedermayer
            memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet));
130
            context->buffer_index += sizeof(ogg_packet);
131
            memcpy(context->buffer + context->buffer_index, op.packet, op.bytes);
132
            context->buffer_index += op.bytes;
133
//            av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes);
134 81e0d0b4 Mark Hills
        }
135
    }
136
137 3f4993f1 Michael Niedermayer
    l=0;
138 6d8f985e Michael Niedermayer
    if(context->buffer_index){
139 bbb77e7c Michael Niedermayer
        ogg_packet *op2= (ogg_packet*)context->buffer;
140 6d8f985e Michael Niedermayer
        op2->packet = context->buffer + sizeof(ogg_packet);
141 3f4993f1 Michael Niedermayer
142 6f824977 Michael Niedermayer
        l=  op2->bytes;
143
        avccontext->coded_frame->pts= av_rescale(op2->granulepos, AV_TIME_BASE, avccontext->sample_rate);
144 3f4993f1 Michael Niedermayer
145 6f824977 Michael Niedermayer
        memcpy(packets, op2->packet, l);
146
        context->buffer_index -= l + sizeof(ogg_packet);
147
        memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index);
148 6d8f985e Michael Niedermayer
//        av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l);
149
    }
150
151 3f4993f1 Michael Niedermayer
    return l;
152 81e0d0b4 Mark Hills
}
153
154
155 3aca208a Mark Hills
static int oggvorbis_encode_close(AVCodecContext *avccontext) {
156 81e0d0b4 Mark Hills
    OggVorbisContext *context = avccontext->priv_data ;
157
/*  ogg_packet op ; */
158
    
159
    vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */
160
161
    vorbis_block_clear(&context->vb);
162
    vorbis_dsp_clear(&context->vd);
163
    vorbis_info_clear(&context->vi);
164 492cd3a9 Michael Niedermayer
165
    av_freep(&avccontext->coded_frame);
166 bbb77e7c Michael Niedermayer
    av_freep(&avccontext->extradata);
167 81e0d0b4 Mark Hills
  
168
    return 0 ;
169
}
170
171
172
AVCodec oggvorbis_encoder = {
173
    "vorbis",
174
    CODEC_TYPE_AUDIO,
175
    CODEC_ID_VORBIS,
176
    sizeof(OggVorbisContext),
177
    oggvorbis_encode_init,
178
    oggvorbis_encode_frame,
179 6f824977 Michael Niedermayer
    oggvorbis_encode_close,
180
    .capabilities= CODEC_CAP_DELAY,
181 3aca208a Mark Hills
} ;
182
183
184
static int oggvorbis_decode_init(AVCodecContext *avccontext) {
185
    OggVorbisContext *context = avccontext->priv_data ;
186 a03cbe5f Michael Niedermayer
    uint8_t *p= avccontext->extradata;
187
    int i;
188 3aca208a Mark Hills
189
    vorbis_info_init(&context->vi) ;
190
    vorbis_comment_init(&context->vc) ;
191 a03cbe5f Michael Niedermayer
192
    for(i=0; i<3; i++){
193
        context->op.b_o_s= i==0;
194
        context->op.bytes= *(p++)<<8;
195
        context->op.bytes+=*(p++);
196
        context->op.packet= p;
197
        p += context->op.bytes;
198
199
        if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
200
            av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
201
            return -1;
202
        }
203
    }
204
    avccontext->channels = context->vi.channels;
205
    avccontext->sample_rate = context->vi.rate;
206
207
    vorbis_synthesis_init(&context->vd, &context->vi);
208
    vorbis_block_init(&context->vd, &context->vb); 
209 3aca208a Mark Hills
210
    return 0 ;
211
}
212
213
214
static inline int conv(int samples, float **pcm, char *buf, int channels) {
215
    int i, j, val ;
216
    ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
217
    float *mono ;
218
 
219
    for(i = 0 ; i < channels ; i++){
220
        ptr = &data[i];
221
        mono = pcm[i] ;
222
        
223
        for(j = 0 ; j < samples ; j++) {
224
            
225
            val = mono[j] * 32767.f;
226
            
227
            if(val > 32767) val = 32767 ;
228
            if(val < -32768) val = -32768 ;
229
                       
230
            *ptr = val ;
231
            ptr += channels;
232
        }
233
    }
234
    
235
    return 0 ;
236
}
237
           
238
        
239
static int oggvorbis_decode_frame(AVCodecContext *avccontext,
240
                        void *data, int *data_size,
241 0c1a9eda Zdenek Kabelac
                        uint8_t *buf, int buf_size)
242 3aca208a Mark Hills
{
243
    OggVorbisContext *context = avccontext->priv_data ;
244
    float **pcm ;
245 d76f581f Michael Niedermayer
    ogg_packet *op= &context->op;    
246 8bfed902 Michael Niedermayer
    int samples, total_samples, total_bytes,i;
247 3aca208a Mark Hills
 
248 8bfed902 Michael Niedermayer
    if(!buf_size){
249
    //FIXME flush
250
        return 0;
251
    }
252
    
253 d76f581f Michael Niedermayer
    op->packet = buf;
254
    op->bytes  = buf_size;
255 3aca208a Mark Hills
256 8bfed902 Michael Niedermayer
//    av_log(avccontext, AV_LOG_DEBUG, "%d %d %d %lld %lld %d %d\n", op->bytes, op->b_o_s, op->e_o_s, op->granulepos, op->packetno, buf_size, context->vi.rate);
257
    
258
/*    for(i=0; i<op->bytes; i++)
259
      av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
260
    av_log(avccontext, AV_LOG_DEBUG, "\n");*/
261 3aca208a Mark Hills
262
    if(vorbis_synthesis(&context->vb, op) == 0)
263
        vorbis_synthesis_blockin(&context->vd, &context->vb) ;
264
    
265
    total_samples = 0 ;
266
    total_bytes = 0 ;
267
268
    while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
269
        conv(samples, pcm, (char*)data + total_bytes, context->vi.channels) ;
270
        total_bytes += samples * 2 * context->vi.channels ;
271
        total_samples += samples ;
272
        vorbis_synthesis_read(&context->vd, samples) ;
273
    }
274
275
    *data_size = total_bytes ;   
276
    return buf_size ;
277
}
278 81e0d0b4 Mark Hills
279 3aca208a Mark Hills
280
static int oggvorbis_decode_close(AVCodecContext *avccontext) {
281
    OggVorbisContext *context = avccontext->priv_data ;
282
   
283
    vorbis_info_clear(&context->vi) ;
284
    vorbis_comment_clear(&context->vc) ;
285
286
    return 0 ;
287
}
288
289
290
AVCodec oggvorbis_decoder = {
291
    "vorbis",
292
    CODEC_TYPE_AUDIO,
293
    CODEC_ID_VORBIS,
294
    sizeof(OggVorbisContext),
295
    oggvorbis_decode_init,
296
    NULL,
297
    oggvorbis_decode_close,
298
    oggvorbis_decode_frame,
299 6f824977 Michael Niedermayer
    .capabilities= CODEC_CAP_DELAY,
300 3aca208a Mark Hills
} ;