2 * Ogg Vorbis codec support via libvorbisenc
3 * Mark Hills <mark@pogo.org.uk>
8 #include <vorbis/vorbisenc.h>
11 #include "oggvorbis.h"
13 #define OGGVORBIS_FRAME_SIZE 1024
16 typedef struct OggVorbisContext
{
26 int oggvorbis_init_encoder(vorbis_info
*vi
, AVCodecContext
*avccontext
) {
28 #ifdef OGGVORBIS_VBR_BY_ESTIMATE
29 /* variable bitrate by estimate */
31 return (vorbis_encode_setup_managed(vi
, avccontext
->channels
,
32 avccontext
->sample_rate
, -1, avccontext
->bit_rate
, -1) ||
33 vorbis_encode_ctl(vi
, OV_ECTL_RATEMANAGE_AVG
, NULL
) ||
34 vorbis_encode_setup_init(vi
)) ;
36 /* constant bitrate */
38 return vorbis_encode_init(vi
, avccontext
->channels
,
39 avccontext
->sample_rate
, -1, avccontext
->bit_rate
, -1) ;
44 static int oggvorbis_encode_init(AVCodecContext
*avccontext
) {
45 OggVorbisContext
*context
= avccontext
->priv_data
;
47 vorbis_info_init(&context
->vi
) ;
48 if(oggvorbis_init_encoder(&context
->vi
, avccontext
) < 0) {
49 fprintf(stderr
, "oggvorbis_encode_init: init_encoder failed") ;
52 vorbis_analysis_init(&context
->vd
, &context
->vi
) ;
53 vorbis_block_init(&context
->vd
, &context
->vb
) ;
55 avccontext
->frame_size
= OGGVORBIS_FRAME_SIZE
;
57 avccontext
->coded_frame
= avcodec_alloc_frame();
58 avccontext
->coded_frame
->key_frame
= 1;
64 static int oggvorbis_encode_frame(AVCodecContext
*avccontext
,
65 unsigned char *packets
,
66 int buf_size
, void *data
)
68 OggVorbisContext
*context
= avccontext
->priv_data
;
71 signed char *audio
= data
;
72 int l
, samples
= OGGVORBIS_FRAME_SIZE
;
74 buffer
= vorbis_analysis_buffer(&context
->vd
, samples
) ;
76 if(context
->vi
.channels
== 1) {
77 for(l
= 0 ; l
< samples
; l
++)
78 buffer
[0][l
]=((audio
[l
*2+1]<<8)|(0x00ff&(int)audio
[l
*2]))/32768.f
;
80 for(l
= 0 ; l
< samples
; l
++){
81 buffer
[0][l
]=((audio
[l
*4+1]<<8)|(0x00ff&(int)audio
[l
*4]))/32768.f
;
82 buffer
[1][l
]=((audio
[l
*4+3]<<8)|(0x00ff&(int)audio
[l
*4+2]))/32768.f
;
86 vorbis_analysis_wrote(&context
->vd
, samples
) ;
90 while(vorbis_analysis_blockout(&context
->vd
, &context
->vb
) == 1) {
91 vorbis_analysis(&context
->vb
, NULL
);
92 vorbis_bitrate_addblock(&context
->vb
) ;
94 while(vorbis_bitrate_flushpacket(&context
->vd
, &op
)) {
95 memcpy(packets
+ l
, &op
, sizeof(ogg_packet
)) ;
96 memcpy(packets
+ l
+ sizeof(ogg_packet
), op
.packet
, op
.bytes
) ;
97 l
+= sizeof(ogg_packet
) + op
.bytes
;
105 static int oggvorbis_encode_close(AVCodecContext
*avccontext
) {
106 OggVorbisContext
*context
= avccontext
->priv_data
;
107 /* ogg_packet op ; */
109 vorbis_analysis_wrote(&context
->vd
, 0) ; /* notify vorbisenc this is EOF */
111 /* We need to write all the remaining packets into the stream
114 fprintf(stderr
, "fixme: not all packets written on oggvorbis_encode_close()\n") ;
117 while(vorbis_bitrate_flushpacket(&context->vd, &op)) {
118 memcpy(packets + l, &op, sizeof(ogg_packet)) ;
119 memcpy(packets + l + sizeof(ogg_packet), op.packet, op.bytes) ;
120 l += sizeof(ogg_packet) + op.bytes ;
124 vorbis_block_clear(&context
->vb
);
125 vorbis_dsp_clear(&context
->vd
);
126 vorbis_info_clear(&context
->vi
);
128 av_freep(&avccontext
->coded_frame
);
134 AVCodec oggvorbis_encoder
= {
138 sizeof(OggVorbisContext
),
139 oggvorbis_encode_init
,
140 oggvorbis_encode_frame
,
141 oggvorbis_encode_close
145 static int oggvorbis_decode_init(AVCodecContext
*avccontext
) {
146 OggVorbisContext
*context
= avccontext
->priv_data
;
148 vorbis_info_init(&context
->vi
) ;
149 vorbis_comment_init(&context
->vc
) ;
155 static inline int conv(int samples
, float **pcm
, char *buf
, int channels
) {
157 ogg_int16_t
*ptr
, *data
= (ogg_int16_t
*)buf
;
160 for(i
= 0 ; i
< channels
; i
++){
164 for(j
= 0 ; j
< samples
; j
++) {
166 val
= mono
[j
] * 32767.f
;
168 if(val
> 32767) val
= 32767 ;
169 if(val
< -32768) val
= -32768 ;
180 static int oggvorbis_decode_frame(AVCodecContext
*avccontext
,
181 void *data
, int *data_size
,
182 UINT8
*buf
, int buf_size
)
184 OggVorbisContext
*context
= avccontext
->priv_data
;
185 ogg_packet
*op
= (ogg_packet
*)buf
;
187 int samples
, total_samples
, total_bytes
;
189 op
->packet
= (char*)op
+ sizeof(ogg_packet
) ; /* correct data pointer */
191 if(op
->packetno
< 3) {
192 vorbis_synthesis_headerin(&context
->vi
, &context
->vc
, op
) ;
196 if(op
->packetno
== 3) {
197 fprintf(stderr
, "vorbis_decode: %d channel, %ldHz, encoder `%s'\n",
198 context
->vi
.channels
, context
->vi
.rate
, context
->vc
.vendor
);
200 avccontext
->channels
= context
->vi
.channels
;
201 avccontext
->sample_rate
= context
->vi
.rate
;
203 vorbis_synthesis_init(&context
->vd
, &context
->vi
) ;
204 vorbis_block_init(&context
->vd
, &context
->vb
);
207 if(vorbis_synthesis(&context
->vb
, op
) == 0)
208 vorbis_synthesis_blockin(&context
->vd
, &context
->vb
) ;
213 while((samples
= vorbis_synthesis_pcmout(&context
->vd
, &pcm
)) > 0) {
214 conv(samples
, pcm
, (char*)data
+ total_bytes
, context
->vi
.channels
) ;
215 total_bytes
+= samples
* 2 * context
->vi
.channels
;
216 total_samples
+= samples
;
217 vorbis_synthesis_read(&context
->vd
, samples
) ;
220 *data_size
= total_bytes
;
225 static int oggvorbis_decode_close(AVCodecContext
*avccontext
) {
226 OggVorbisContext
*context
= avccontext
->priv_data
;
228 vorbis_info_clear(&context
->vi
) ;
229 vorbis_comment_clear(&context
->vc
) ;
235 AVCodec oggvorbis_decoder
= {
239 sizeof(OggVorbisContext
),
240 oggvorbis_decode_init
,
242 oggvorbis_decode_close
,
243 oggvorbis_decode_frame
,