3 * Ogg Vorbis codec support via libvorbisenc.
4 * @author Mark Hills <mark@pogo.org.uk>
7 #include <vorbis/vorbisenc.h>
14 #define OGGVORBIS_FRAME_SIZE 64
16 #define BUFFER_SIZE (1024*64)
18 typedef struct OggVorbisContext
{
22 uint8_t buffer
[BUFFER_SIZE
];
31 static int oggvorbis_init_encoder(vorbis_info
*vi
, AVCodecContext
*avccontext
) {
34 if(avccontext
->flags
& CODEC_FLAG_QSCALE
) {
35 /* variable bitrate */
36 if(vorbis_encode_setup_vbr(vi
, avccontext
->channels
,
37 avccontext
->sample_rate
,
38 avccontext
->global_quality
/ (float)FF_QP2LAMBDA
))
41 /* constant bitrate */
42 if(vorbis_encode_setup_managed(vi
, avccontext
->channels
,
43 avccontext
->sample_rate
, -1, avccontext
->bit_rate
, -1))
46 #ifdef OGGVORBIS_VBR_BY_ESTIMATE
47 /* variable bitrate by estimate */
48 if(vorbis_encode_ctl(vi
, OV_ECTL_RATEMANAGE_AVG
, NULL
))
53 /* cutoff frequency */
54 if(avccontext
->cutoff
> 0) {
55 cfreq
= avccontext
->cutoff
/ 1000.0;
56 if(vorbis_encode_ctl(vi
, OV_ECTL_LOWPASS_SET
, &cfreq
))
60 return vorbis_encode_setup_init(vi
);
63 static int oggvorbis_encode_init(AVCodecContext
*avccontext
) {
64 OggVorbisContext
*context
= avccontext
->priv_data
;
65 ogg_packet header
, header_comm
, header_code
;
67 unsigned int offset
, len
;
69 vorbis_info_init(&context
->vi
) ;
70 if(oggvorbis_init_encoder(&context
->vi
, avccontext
) < 0) {
71 av_log(avccontext
, AV_LOG_ERROR
, "oggvorbis_encode_init: init_encoder failed") ;
74 vorbis_analysis_init(&context
->vd
, &context
->vi
) ;
75 vorbis_block_init(&context
->vd
, &context
->vb
) ;
77 vorbis_comment_init(&context
->vc
);
78 vorbis_comment_add_tag(&context
->vc
, "encoder", LIBAVCODEC_IDENT
) ;
80 vorbis_analysis_headerout(&context
->vd
, &context
->vc
, &header
,
81 &header_comm
, &header_code
);
83 len
= header
.bytes
+ header_comm
.bytes
+ header_code
.bytes
;
84 avccontext
->extradata_size
= 64 + len
+ len
/255;
85 p
= avccontext
->extradata
= av_mallocz(avccontext
->extradata_size
);
88 offset
+= av_xiphlacing(&p
[offset
], header
.bytes
);
89 offset
+= av_xiphlacing(&p
[offset
], header_comm
.bytes
);
90 memcpy(&p
[offset
], header
.packet
, header
.bytes
);
91 offset
+= header
.bytes
;
92 memcpy(&p
[offset
], header_comm
.packet
, header_comm
.bytes
);
93 offset
+= header_comm
.bytes
;
94 memcpy(&p
[offset
], header_code
.packet
, header_code
.bytes
);
95 offset
+= header_code
.bytes
;
96 avccontext
->extradata_size
= offset
;
97 avccontext
->extradata
= av_realloc(avccontext
->extradata
, avccontext
->extradata_size
);
99 /* vorbis_block_clear(&context->vb);
100 vorbis_dsp_clear(&context->vd);
101 vorbis_info_clear(&context->vi);*/
102 vorbis_comment_clear(&context
->vc
);
104 avccontext
->frame_size
= OGGVORBIS_FRAME_SIZE
;
106 avccontext
->coded_frame
= avcodec_alloc_frame();
107 avccontext
->coded_frame
->key_frame
= 1;
113 static int oggvorbis_encode_frame(AVCodecContext
*avccontext
,
114 unsigned char *packets
,
115 int buf_size
, void *data
)
117 OggVorbisContext
*context
= avccontext
->priv_data
;
120 signed short *audio
= data
;
121 int l
, samples
= data
? OGGVORBIS_FRAME_SIZE
: 0;
123 buffer
= vorbis_analysis_buffer(&context
->vd
, samples
) ;
125 if(context
->vi
.channels
== 1) {
126 for(l
= 0 ; l
< samples
; l
++)
127 buffer
[0][l
]=audio
[l
]/32768.f
;
129 for(l
= 0 ; l
< samples
; l
++){
130 buffer
[0][l
]=audio
[l
*2]/32768.f
;
131 buffer
[1][l
]=audio
[l
*2+1]/32768.f
;
135 vorbis_analysis_wrote(&context
->vd
, samples
) ;
137 while(vorbis_analysis_blockout(&context
->vd
, &context
->vb
) == 1) {
138 vorbis_analysis(&context
->vb
, NULL
);
139 vorbis_bitrate_addblock(&context
->vb
) ;
141 while(vorbis_bitrate_flushpacket(&context
->vd
, &op
)) {
142 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
144 memcpy(context
->buffer
+ context
->buffer_index
, &op
, sizeof(ogg_packet
));
145 context
->buffer_index
+= sizeof(ogg_packet
);
146 memcpy(context
->buffer
+ context
->buffer_index
, op
.packet
, op
.bytes
);
147 context
->buffer_index
+= op
.bytes
;
148 // av_log(avccontext, AV_LOG_DEBUG, "e%d / %d\n", context->buffer_index, op.bytes);
153 if(context
->buffer_index
){
154 ogg_packet
*op2
= (ogg_packet
*)context
->buffer
;
155 op2
->packet
= context
->buffer
+ sizeof(ogg_packet
);
158 avccontext
->coded_frame
->pts
= av_rescale_q(op2
->granulepos
, (AVRational
){1, avccontext
->sample_rate
}, avccontext
->time_base
);
159 //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate
161 memcpy(packets
, op2
->packet
, l
);
162 context
->buffer_index
-= l
+ sizeof(ogg_packet
);
163 memcpy(context
->buffer
, context
->buffer
+ l
+ sizeof(ogg_packet
), context
->buffer_index
);
164 // av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l);
171 static int oggvorbis_encode_close(AVCodecContext
*avccontext
) {
172 OggVorbisContext
*context
= avccontext
->priv_data
;
173 /* ogg_packet op ; */
175 vorbis_analysis_wrote(&context
->vd
, 0) ; /* notify vorbisenc this is EOF */
177 vorbis_block_clear(&context
->vb
);
178 vorbis_dsp_clear(&context
->vd
);
179 vorbis_info_clear(&context
->vi
);
181 av_freep(&avccontext
->coded_frame
);
182 av_freep(&avccontext
->extradata
);
188 AVCodec oggvorbis_encoder
= {
192 sizeof(OggVorbisContext
),
193 oggvorbis_encode_init
,
194 oggvorbis_encode_frame
,
195 oggvorbis_encode_close
,
196 .capabilities
= CODEC_CAP_DELAY
,
199 static int oggvorbis_decode_init(AVCodecContext
*avccontext
) {
200 OggVorbisContext
*context
= avccontext
->priv_data
;
201 uint8_t *p
= avccontext
->extradata
;
203 unsigned char *headers
[3], *extradata
= avccontext
->extradata
;
205 vorbis_info_init(&context
->vi
) ;
206 vorbis_comment_init(&context
->vc
) ;
208 if(! avccontext
->extradata_size
|| ! p
) {
209 av_log(avccontext
, AV_LOG_ERROR
, "vorbis extradata absent\n");
213 if(p
[0] == 0 && p
[1] == 30) {
214 for(i
= 0; i
< 3; i
++){
215 hsizes
[i
] = *p
++ << 8;
221 unsigned int offset
= 1;
225 while((*p
== 0xFF) && (offset
< avccontext
->extradata_size
)) {
230 if(offset
>= avccontext
->extradata_size
- 1) {
231 av_log(avccontext
, AV_LOG_ERROR
,
232 "vorbis header sizes damaged\n");
239 hsizes
[2] = avccontext
->extradata_size
- hsizes
[0]-hsizes
[1]-offset
;
241 av_log(avccontext
, AV_LOG_DEBUG
,
242 "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
243 hsizes
[0], hsizes
[1], hsizes
[2], avccontext
->extradata_size
);
245 headers
[0] = extradata
+ offset
;
246 headers
[1] = extradata
+ offset
+ hsizes
[0];
247 headers
[2] = extradata
+ offset
+ hsizes
[0] + hsizes
[1];
249 av_log(avccontext
, AV_LOG_ERROR
,
250 "vorbis initial header len is wrong: %d\n", *p
);
255 context
->op
.b_o_s
= i
==0;
256 context
->op
.bytes
= hsizes
[i
];
257 context
->op
.packet
= headers
[i
];
258 if(vorbis_synthesis_headerin(&context
->vi
, &context
->vc
, &context
->op
)<0){
259 av_log(avccontext
, AV_LOG_ERROR
, "%d. vorbis header damaged\n", i
+1);
264 avccontext
->channels
= context
->vi
.channels
;
265 avccontext
->sample_rate
= context
->vi
.rate
;
266 avccontext
->time_base
= (AVRational
){1, avccontext
->sample_rate
};
268 vorbis_synthesis_init(&context
->vd
, &context
->vi
);
269 vorbis_block_init(&context
->vd
, &context
->vb
);
275 static inline int conv(int samples
, float **pcm
, char *buf
, int channels
) {
277 ogg_int16_t
*ptr
, *data
= (ogg_int16_t
*)buf
;
280 for(i
= 0 ; i
< channels
; i
++){
284 for(j
= 0 ; j
< samples
; j
++) {
286 val
= mono
[j
] * 32767.f
;
288 if(val
> 32767) val
= 32767 ;
289 if(val
< -32768) val
= -32768 ;
300 static int oggvorbis_decode_frame(AVCodecContext
*avccontext
,
301 void *data
, int *data_size
,
302 uint8_t *buf
, int buf_size
)
304 OggVorbisContext
*context
= avccontext
->priv_data
;
306 ogg_packet
*op
= &context
->op
;
307 int samples
, total_samples
, total_bytes
;
315 op
->bytes
= buf_size
;
317 // 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);
319 /* for(i=0; i<op->bytes; i++)
320 av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
321 av_log(avccontext, AV_LOG_DEBUG, "\n");*/
323 if(vorbis_synthesis(&context
->vb
, op
) == 0)
324 vorbis_synthesis_blockin(&context
->vd
, &context
->vb
) ;
329 while((samples
= vorbis_synthesis_pcmout(&context
->vd
, &pcm
)) > 0) {
330 conv(samples
, pcm
, (char*)data
+ total_bytes
, context
->vi
.channels
) ;
331 total_bytes
+= samples
* 2 * context
->vi
.channels
;
332 total_samples
+= samples
;
333 vorbis_synthesis_read(&context
->vd
, samples
) ;
336 *data_size
= total_bytes
;
341 static int oggvorbis_decode_close(AVCodecContext
*avccontext
) {
342 OggVorbisContext
*context
= avccontext
->priv_data
;
344 vorbis_info_clear(&context
->vi
) ;
345 vorbis_comment_clear(&context
->vc
) ;
351 AVCodec oggvorbis_decoder
= {
355 sizeof(OggVorbisContext
),
356 oggvorbis_decode_init
,
358 oggvorbis_decode_close
,
359 oggvorbis_decode_frame
,
360 .capabilities
= CODEC_CAP_DELAY
,