Statistics
| Branch: | Revision:

ffmpeg / libavcodec / oggvorbis.c @ 1b245cc2

History | View | Annotate | Download (6.11 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 <time.h>
8
9
#include <vorbis/vorbisenc.h>
10
11
#include "avcodec.h"
12
#include "oggvorbis.h"
13
14
#define OGGVORBIS_FRAME_SIZE 1024
15
16
17
typedef struct OggVorbisContext {
18
    vorbis_info vi ;
19
    vorbis_dsp_state vd ;
20
    vorbis_block vb ;
21 3aca208a Mark Hills
22
    /* decoder */
23
    vorbis_comment vc ;
24 81e0d0b4 Mark Hills
} OggVorbisContext ;
25
26
27
int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
28 c55427f8 Mark Hills
29
#ifdef OGGVORBIS_VBR_BY_ESTIMATE
30
    /* variable bitrate by estimate */
31
32
    return (vorbis_encode_setup_managed(vi, avccontext->channels,
33
              avccontext->sample_rate, -1, avccontext->bit_rate, -1) ||
34
            vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL) ||
35
            vorbis_encode_setup_init(vi)) ;
36
#else
37
    /* constant bitrate */
38 81e0d0b4 Mark Hills
39
    return vorbis_encode_init(vi, avccontext->channels,
40
                  avccontext->sample_rate, -1, avccontext->bit_rate, -1) ;
41 c55427f8 Mark Hills
#endif
42 81e0d0b4 Mark Hills
}
43
44
45
static int oggvorbis_encode_init(AVCodecContext *avccontext) {
46
    OggVorbisContext *context = avccontext->priv_data ;
47
48
    vorbis_info_init(&context->vi) ;
49
    if(oggvorbis_init_encoder(&context->vi, avccontext) < 0) {
50
        fprintf(stderr, "oggvorbis_encode_init: init_encoder failed") ;
51
        return -1 ;
52
    }
53
    vorbis_analysis_init(&context->vd, &context->vi) ;
54
    vorbis_block_init(&context->vd, &context->vb) ;
55
56
    avccontext->frame_size = OGGVORBIS_FRAME_SIZE ;
57 492cd3a9 Michael Niedermayer
 
58
    avccontext->coded_frame= avcodec_alloc_frame();
59
    avccontext->coded_frame->key_frame= 1;
60 81e0d0b4 Mark Hills
    
61
    return 0 ;
62
}
63
64
65 3aca208a Mark Hills
static int oggvorbis_encode_frame(AVCodecContext *avccontext,
66
                                  unsigned char *packets,
67 81e0d0b4 Mark Hills
                           int buf_size, void *data)
68
{
69
    OggVorbisContext *context = avccontext->priv_data ;
70
    float **buffer ;
71
    ogg_packet op ;
72
    signed char *audio = data ;
73 3aca208a Mark Hills
    int l, samples = OGGVORBIS_FRAME_SIZE ;
74 81e0d0b4 Mark Hills
75
    buffer = vorbis_analysis_buffer(&context->vd, samples) ;
76
77
    if(context->vi.channels == 1) {
78
        for(l = 0 ; l < samples ; l++)
79
            buffer[0][l]=((audio[l*2+1]<<8)|(0x00ff&(int)audio[l*2]))/32768.f;
80
    } else {
81
        for(l = 0 ; l < samples ; l++){
82
            buffer[0][l]=((audio[l*4+1]<<8)|(0x00ff&(int)audio[l*4]))/32768.f;
83
            buffer[1][l]=((audio[l*4+3]<<8)|(0x00ff&(int)audio[l*4+2]))/32768.f;
84
        }
85
    }
86
    
87
    vorbis_analysis_wrote(&context->vd, samples) ; 
88
89
    l = 0 ;
90
91
    while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) {
92
        vorbis_analysis(&context->vb, NULL);
93
        vorbis_bitrate_addblock(&context->vb) ;
94
95
        while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
96
            memcpy(packets + l, &op, sizeof(ogg_packet)) ;
97
            memcpy(packets + l + sizeof(ogg_packet), op.packet, op.bytes) ;
98
            l += sizeof(ogg_packet) + op.bytes ;
99
        }
100
    }
101
102
    return l ;
103
}
104
105
106 3aca208a Mark Hills
static int oggvorbis_encode_close(AVCodecContext *avccontext) {
107 81e0d0b4 Mark Hills
    OggVorbisContext *context = avccontext->priv_data ;
108
/*  ogg_packet op ; */
109
    
110
    vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */
111
112
    /* We need to write all the remaining packets into the stream
113
     * on closing */
114
    
115 3aca208a Mark Hills
    fprintf(stderr, "fixme: not all packets written on oggvorbis_encode_close()\n") ;
116
117 81e0d0b4 Mark Hills
/*
118
    while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
119
        memcpy(packets + l, &op, sizeof(ogg_packet)) ;
120
        memcpy(packets + l + sizeof(ogg_packet), op.packet, op.bytes) ;
121
        l += sizeof(ogg_packet) + op.bytes ;        
122
    }
123
*/
124
125
    vorbis_block_clear(&context->vb);
126
    vorbis_dsp_clear(&context->vd);
127
    vorbis_info_clear(&context->vi);
128 492cd3a9 Michael Niedermayer
129
    av_freep(&avccontext->coded_frame);
130 81e0d0b4 Mark Hills
  
131
    return 0 ;
132
}
133
134
135
AVCodec oggvorbis_encoder = {
136
    "vorbis",
137
    CODEC_TYPE_AUDIO,
138
    CODEC_ID_VORBIS,
139
    sizeof(OggVorbisContext),
140
    oggvorbis_encode_init,
141
    oggvorbis_encode_frame,
142
    oggvorbis_encode_close
143 3aca208a Mark Hills
} ;
144
145
146
static int oggvorbis_decode_init(AVCodecContext *avccontext) {
147
    OggVorbisContext *context = avccontext->priv_data ;
148
149
    vorbis_info_init(&context->vi) ;
150
    vorbis_comment_init(&context->vc) ;
151
152
    return 0 ;
153
}
154
155
156
static inline int conv(int samples, float **pcm, char *buf, int channels) {
157
    int i, j, val ;
158
    ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
159
    float *mono ;
160
 
161
    for(i = 0 ; i < channels ; i++){
162
        ptr = &data[i];
163
        mono = pcm[i] ;
164
        
165
        for(j = 0 ; j < samples ; j++) {
166
            
167
            val = mono[j] * 32767.f;
168
            
169
            if(val > 32767) val = 32767 ;
170
            if(val < -32768) val = -32768 ;
171
                       
172
            *ptr = val ;
173
            ptr += channels;
174
        }
175
    }
176
    
177
    return 0 ;
178
}
179
           
180
        
181
static int oggvorbis_decode_frame(AVCodecContext *avccontext,
182
                        void *data, int *data_size,
183 0c1a9eda Zdenek Kabelac
                        uint8_t *buf, int buf_size)
184 3aca208a Mark Hills
{
185
    OggVorbisContext *context = avccontext->priv_data ;
186
    ogg_packet *op = (ogg_packet*)buf ;
187
    float **pcm ;
188
    int samples, total_samples, total_bytes ;
189
 
190
    op->packet = (char*)op + sizeof(ogg_packet) ; /* correct data pointer */
191
192
    if(op->packetno < 3) {
193
        vorbis_synthesis_headerin(&context->vi, &context->vc, op) ;
194
        return buf_size ;
195
    }
196
197
    if(op->packetno == 3) {
198
        fprintf(stderr, "vorbis_decode: %d channel, %ldHz, encoder `%s'\n",
199
                context->vi.channels, context->vi.rate, context->vc.vendor);
200 81e0d0b4 Mark Hills
201 3aca208a Mark Hills
        avccontext->channels = context->vi.channels ;
202
        avccontext->sample_rate = context->vi.rate ;
203
        
204
        vorbis_synthesis_init(&context->vd, &context->vi) ;
205
        vorbis_block_init(&context->vd, &context->vb); 
206
    }
207
208
    if(vorbis_synthesis(&context->vb, op) == 0)
209
        vorbis_synthesis_blockin(&context->vd, &context->vb) ;
210
    
211
    total_samples = 0 ;
212
    total_bytes = 0 ;
213
214
    while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
215
        conv(samples, pcm, (char*)data + total_bytes, context->vi.channels) ;
216
        total_bytes += samples * 2 * context->vi.channels ;
217
        total_samples += samples ;
218
        vorbis_synthesis_read(&context->vd, samples) ;
219
    }
220
221
    *data_size = total_bytes ;   
222
    return buf_size ;
223
}
224 81e0d0b4 Mark Hills
225 3aca208a Mark Hills
226
static int oggvorbis_decode_close(AVCodecContext *avccontext) {
227
    OggVorbisContext *context = avccontext->priv_data ;
228
   
229
    vorbis_info_clear(&context->vi) ;
230
    vorbis_comment_clear(&context->vc) ;
231
232
    return 0 ;
233
}
234
235
236
AVCodec oggvorbis_decoder = {
237
    "vorbis",
238
    CODEC_TYPE_AUDIO,
239
    CODEC_ID_VORBIS,
240
    sizeof(OggVorbisContext),
241
    oggvorbis_decode_init,
242
    NULL,
243
    oggvorbis_decode_close,
244
    oggvorbis_decode_frame,
245
} ;