]> git.sesse.net Git - vlc/blob - modules/codec/vorbis.c
Fixes + use new API for directory demuxer
[vlc] / modules / codec / vorbis.c
1 /*****************************************************************************
2  * vorbis.c: vorbis decoder/encoder/packetizer module making use of libvorbis.
3  *****************************************************************************
4  * Copyright (C) 2001-2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/decoder.h>
29 #include <vlc/input.h>
30 #include <vlc/sout.h>
31
32 #include <ogg/ogg.h>
33
34 #ifdef MODULE_NAME_IS_tremor
35 #include <tremor/ivorbiscodec.h>
36
37 #else
38 #include <vorbis/codec.h>
39
40 /* vorbis header */
41 #ifdef HAVE_VORBIS_VORBISENC_H
42 #   include <vorbis/vorbisenc.h>
43 #   ifndef OV_ECTL_RATEMANAGE_AVG
44 #       define OV_ECTL_RATEMANAGE_AVG 0x0
45 #   endif
46 #endif
47
48 #endif
49
50 /*****************************************************************************
51  * decoder_sys_t : vorbis decoder descriptor
52  *****************************************************************************/
53 struct decoder_sys_t
54 {
55     /* Module mode */
56     vlc_bool_t b_packetizer;
57
58     /*
59      * Input properties
60      */
61     int i_headers;
62
63     /*
64      * Vorbis properties
65      */
66     vorbis_info      vi; /* struct that stores all the static vorbis bitstream
67                             settings */
68     vorbis_comment   vc; /* struct that stores all the bitstream user
69                           * comments */
70     vorbis_dsp_state vd; /* central working state for the packet->PCM
71                           * decoder */
72     vorbis_block     vb; /* local working space for packet->PCM decode */
73
74     /*
75      * Common properties
76      */
77     audio_date_t end_date;
78     int          i_last_block_size;
79
80 };
81
82 static int pi_channels_maps[7] =
83 {
84     0,
85     AOUT_CHAN_CENTER,
86     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
87     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
88     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
89      | AOUT_CHAN_REARRIGHT,
90     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
91      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
92     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
93      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
94 };
95
96 /****************************************************************************
97  * Local prototypes
98  ****************************************************************************/
99 static int  OpenDecoder   ( vlc_object_t * );
100 static int  OpenPacketizer( vlc_object_t * );
101 static void CloseDecoder  ( vlc_object_t * );
102 static void *DecodeBlock  ( decoder_t *, block_t ** );
103
104 static int  ProcessHeaders( decoder_t * );
105 static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
106
107 static aout_buffer_t *DecodePacket  ( decoder_t *, ogg_packet * );
108 static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * );
109
110 static void ParseVorbisComments( decoder_t * );
111
112 #ifdef MODULE_NAME_IS_tremor
113 static void Interleave   ( int32_t *, const int32_t **, int, int );
114 #else
115 static void Interleave   ( float *, const float **, int, int );
116 #endif
117
118 #ifndef MODULE_NAME_IS_tremor
119 static int OpenEncoder   ( vlc_object_t * );
120 static void CloseEncoder ( vlc_object_t * );
121 static block_t *Encode   ( encoder_t *, aout_buffer_t * );
122 #endif
123
124 /*****************************************************************************
125  * Module descriptor
126  *****************************************************************************/
127 #define ENC_QUALITY_TEXT N_("Encoding quality")
128 #define ENC_QUALITY_LONGTEXT N_( \
129   "Allows you to specify a quality between 1 (low) and 10 (high), instead " \
130   "of specifying a particular bitrate. This will produce a VBR stream." )
131 #define ENC_MAXBR_TEXT N_("Maximum encoding bitrate")
132 #define ENC_MAXBR_LONGTEXT N_( \
133   "Allows you to specify a maximum bitrate in kbps. " \
134   "Useful for streaming applications." )
135 #define ENC_MINBR_TEXT N_("Minimum encoding bitrate")
136 #define ENC_MINBR_LONGTEXT N_( \
137   "Allows you to specify a minimum bitrate in kbps. " \
138   "Useful for encoding for a fixed-size channel." )
139 #define ENC_CBR_TEXT N_("CBR encoding")
140 #define ENC_CBR_LONGTEXT N_( \
141   "Allows you to force a constant bitrate encoding (CBR)." )
142
143 vlc_module_begin();
144
145     set_description( _("Vorbis audio decoder") );
146 #ifdef MODULE_NAME_IS_tremor
147     set_capability( "decoder", 90 );
148 #else
149     set_capability( "decoder", 100 );
150 #endif
151     set_callbacks( OpenDecoder, CloseDecoder );
152
153     add_submodule();
154     set_description( _("Vorbis audio packetizer") );
155     set_capability( "packetizer", 100 );
156     set_callbacks( OpenPacketizer, CloseDecoder );
157
158 #ifndef MODULE_NAME_IS_tremor
159 #   define ENC_CFG_PREFIX "sout-vorbis-"
160     add_submodule();
161     set_description( _("Vorbis audio encoder") );
162     set_capability( "encoder", 100 );
163     set_callbacks( OpenEncoder, CloseEncoder );
164
165     add_integer( ENC_CFG_PREFIX "quality", 3, NULL, ENC_QUALITY_TEXT,
166                  ENC_QUALITY_LONGTEXT, VLC_FALSE );
167     add_integer( ENC_CFG_PREFIX "max-bitrate", 0, NULL, ENC_MAXBR_TEXT,
168                  ENC_MAXBR_LONGTEXT, VLC_FALSE );
169     add_integer( ENC_CFG_PREFIX "min-bitrate", 0, NULL, ENC_MINBR_TEXT,
170                  ENC_MINBR_LONGTEXT, VLC_FALSE );
171     add_bool( ENC_CFG_PREFIX "cbr", 0, NULL, ENC_CBR_TEXT,
172                  ENC_CBR_LONGTEXT, VLC_FALSE );
173 #endif
174
175 vlc_module_end();
176
177 #ifndef MODULE_NAME_IS_tremor
178 static const char *ppsz_enc_options[] = {
179     "quality", "max-bitrate", "min-bitrate", "cbr", NULL
180 };
181 #endif
182
183 /*****************************************************************************
184  * OpenDecoder: probe the decoder and return score
185  *****************************************************************************/
186 static int OpenDecoder( vlc_object_t *p_this )
187 {
188     decoder_t *p_dec = (decoder_t*)p_this;
189     decoder_sys_t *p_sys;
190
191     if( p_dec->fmt_in.i_codec != VLC_FOURCC('v','o','r','b') )
192     {
193         return VLC_EGENERIC;
194     }
195
196     /* Allocate the memory needed to store the decoder's structure */
197     if( ( p_dec->p_sys = p_sys =
198           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
199     {
200         msg_Err( p_dec, "out of memory" );
201         return VLC_EGENERIC;
202     }
203
204     /* Misc init */
205     aout_DateSet( &p_sys->end_date, 0 );
206     p_sys->b_packetizer = VLC_FALSE;
207     p_sys->i_headers = 0;
208
209     /* Take care of vorbis init */
210     vorbis_info_init( &p_sys->vi );
211     vorbis_comment_init( &p_sys->vc );
212
213     /* Set output properties */
214     p_dec->fmt_out.i_cat = AUDIO_ES;
215 #ifdef MODULE_NAME_IS_tremor
216     p_dec->fmt_out.i_codec = VLC_FOURCC('f','i','3','2');
217 #else
218     p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
219 #endif
220
221     /* Set callbacks */
222     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
223         DecodeBlock;
224     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
225         DecodeBlock;
226
227     return VLC_SUCCESS;
228 }
229
230 static int OpenPacketizer( vlc_object_t *p_this )
231 {
232     decoder_t *p_dec = (decoder_t*)p_this;
233
234     int i_ret = OpenDecoder( p_this );
235
236     if( i_ret == VLC_SUCCESS )
237     {
238         p_dec->p_sys->b_packetizer = VLC_TRUE;
239         p_dec->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
240     }
241
242     return i_ret;
243 }
244
245 /****************************************************************************
246  * DecodeBlock: the whole thing
247  ****************************************************************************
248  * This function must be fed with ogg packets.
249  ****************************************************************************/
250 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
251 {
252     decoder_sys_t *p_sys = p_dec->p_sys;
253     ogg_packet oggpacket;
254
255     if( !pp_block ) return NULL;
256
257     if( *pp_block )
258     {
259         /* Block to Ogg packet */
260         oggpacket.packet = (*pp_block)->p_buffer;
261         oggpacket.bytes = (*pp_block)->i_buffer;
262     }
263     else
264     {
265         if( p_sys->b_packetizer ) return NULL;
266
267         /* Block to Ogg packet */
268         oggpacket.packet = NULL;
269         oggpacket.bytes = 0;
270     }
271
272     oggpacket.granulepos = -1;
273     oggpacket.b_o_s = 0;
274     oggpacket.e_o_s = 0;
275     oggpacket.packetno = 0;
276
277     /* Check for headers */
278     if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
279     {
280         /* Headers already available as extra data */
281         p_sys->i_headers = 3;
282     }
283     else if( oggpacket.bytes && p_sys->i_headers < 3 )
284     {
285         /* Backup headers as extra data */
286         uint8_t *p_extra;
287
288         p_dec->fmt_in.p_extra =
289             realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra +
290                      oggpacket.bytes + 2 );
291         p_extra = p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra;
292         *(p_extra++) = oggpacket.bytes >> 8;
293         *(p_extra++) = oggpacket.bytes & 0xFF;
294
295         memcpy( p_extra, oggpacket.packet, oggpacket.bytes );
296         p_dec->fmt_in.i_extra += oggpacket.bytes + 2;
297
298         block_Release( *pp_block );
299         p_sys->i_headers++;
300         return NULL;
301     }
302
303     if( p_sys->i_headers == 3 )
304     {
305         if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
306         {
307             p_sys->i_headers = 0;
308             p_dec->fmt_in.i_extra = 0;
309             block_Release( *pp_block );
310             return NULL;
311         }
312         else p_sys->i_headers++;
313     }
314
315     return ProcessPacket( p_dec, &oggpacket, pp_block );
316 }
317
318 /*****************************************************************************
319  * ProcessHeaders: process Vorbis headers.
320  *****************************************************************************/
321 static int ProcessHeaders( decoder_t *p_dec )
322 {
323     decoder_sys_t *p_sys = p_dec->p_sys;
324     ogg_packet oggpacket;
325     uint8_t *p_extra;
326     int i_extra;
327
328     if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
329
330     oggpacket.granulepos = -1;
331     oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
332     oggpacket.e_o_s = 0;
333     oggpacket.packetno = 0;
334     p_extra = p_dec->fmt_in.p_extra;
335     i_extra = p_dec->fmt_in.i_extra;
336
337     /* Take care of the initial Vorbis header */
338     oggpacket.bytes = *(p_extra++) << 8;
339     oggpacket.bytes |= (*(p_extra++) & 0xFF);
340     oggpacket.packet = p_extra;
341     p_extra += oggpacket.bytes;
342     i_extra -= (oggpacket.bytes + 2);
343     if( i_extra < 0 )
344     {
345         msg_Err( p_dec, "header data corrupted");
346         return VLC_EGENERIC;
347     }
348
349     if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
350     {
351         msg_Err( p_dec, "this bitstream does not contain Vorbis audio data");
352         return VLC_EGENERIC;
353     }
354
355     /* Setup the format */
356     p_dec->fmt_out.audio.i_rate     = p_sys->vi.rate;
357     p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;
358     p_dec->fmt_out.audio.i_physical_channels =
359         p_dec->fmt_out.audio.i_original_channels =
360             pi_channels_maps[p_sys->vi.channels];
361     p_dec->fmt_out.i_bitrate = p_sys->vi.bitrate_nominal;
362
363     aout_DateInit( &p_sys->end_date, p_sys->vi.rate );
364     aout_DateSet( &p_sys->end_date, 0 );
365
366     msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",
367              p_sys->vi.channels, p_sys->vi.rate, p_sys->vi.bitrate_nominal );
368
369     /* The next packet in order is the comments header */
370     oggpacket.b_o_s = 0;
371     oggpacket.bytes = *(p_extra++) << 8;
372     oggpacket.bytes |= (*(p_extra++) & 0xFF);
373     oggpacket.packet = p_extra;
374     p_extra += oggpacket.bytes;
375     i_extra -= (oggpacket.bytes + 2);
376     if( i_extra < 0 )
377     {
378         msg_Err( p_dec, "header data corrupted");
379         return VLC_EGENERIC;
380     }
381
382     if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
383     {
384         msg_Err( p_dec, "2nd Vorbis header is corrupted" );
385         return VLC_EGENERIC;
386     }
387     ParseVorbisComments( p_dec );
388
389     /* The next packet in order is the codebooks header
390      * We need to watch out that this packet is not missing as a
391      * missing or corrupted header is fatal. */
392     oggpacket.bytes = *(p_extra++) << 8;
393     oggpacket.bytes |= (*(p_extra++) & 0xFF);
394     oggpacket.packet = p_extra;
395     i_extra -= (oggpacket.bytes + 2);
396     if( i_extra < 0 )
397     {
398         msg_Err( p_dec, "header data corrupted");
399         return VLC_EGENERIC;
400     }
401
402     if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
403     {
404         msg_Err( p_dec, "3rd Vorbis header is corrupted" );
405         return VLC_EGENERIC;
406     }
407
408     if( !p_sys->b_packetizer )
409     {
410         /* Initialize the Vorbis packet->PCM decoder */
411         vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
412         vorbis_block_init( &p_sys->vd, &p_sys->vb );
413     }
414     else
415     {
416         p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
417         p_dec->fmt_out.p_extra =
418             realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
419         memcpy( p_dec->fmt_out.p_extra,
420                 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
421     }
422
423     return VLC_SUCCESS;
424 }
425
426 /*****************************************************************************
427  * ProcessPacket: processes a Vorbis packet.
428  *****************************************************************************/
429 static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
430                             block_t **pp_block )
431 {
432     decoder_sys_t *p_sys = p_dec->p_sys;
433     block_t *p_block = *pp_block;
434
435     /* Date management */
436     if( p_block && p_block->i_pts > 0 &&
437         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
438     {
439         aout_DateSet( &p_sys->end_date, p_block->i_pts );
440     }
441
442     if( !aout_DateGet( &p_sys->end_date ) )
443     {
444         /* We've just started the stream, wait for the first PTS. */
445         if( p_block ) block_Release( p_block );
446         return NULL;
447     }
448
449     *pp_block = NULL; /* To avoid being fed the same packet again */
450
451     if( p_sys->b_packetizer )
452     {
453         return SendPacket( p_dec, p_oggpacket, p_block );
454     }
455     else
456     {
457         aout_buffer_t *p_aout_buffer;
458
459         if( p_sys->i_headers >= 3 )
460             p_aout_buffer = DecodePacket( p_dec, p_oggpacket );
461         else
462             p_aout_buffer = NULL;
463
464         if( p_block ) block_Release( p_block );
465         return p_aout_buffer;
466     }
467 }
468
469 /*****************************************************************************
470  * DecodePacket: decodes a Vorbis packet.
471  *****************************************************************************/
472 static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
473 {
474     decoder_sys_t *p_sys = p_dec->p_sys;
475     int           i_samples;
476
477 #ifdef MODULE_NAME_IS_tremor
478     int32_t       **pp_pcm;
479 #else
480     float         **pp_pcm;
481 #endif
482
483     if( p_oggpacket->bytes &&
484         vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 )
485         vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb );
486
487     /* **pp_pcm is a multichannel float vector. In stereo, for
488      * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is
489      * the size of each channel. Convert the float values
490      * (-1.<=range<=1.) to whatever PCM format and write it out */
491
492     if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 )
493     {
494
495         aout_buffer_t *p_aout_buffer;
496
497         p_aout_buffer =
498             p_dec->pf_aout_buffer_new( p_dec, i_samples );
499
500         if( p_aout_buffer == NULL ) return NULL;
501
502         /* Interleave the samples */
503 #ifdef MODULE_NAME_IS_tremor
504         Interleave( (int32_t *)p_aout_buffer->p_buffer,
505                     (const int32_t **)pp_pcm, p_sys->vi.channels, i_samples );
506 #else
507         Interleave( (float *)p_aout_buffer->p_buffer,
508                     (const float **)pp_pcm, p_sys->vi.channels, i_samples );
509 #endif
510
511         /* Tell libvorbis how many samples we actually consumed */
512         vorbis_synthesis_read( &p_sys->vd, i_samples );
513
514         /* Date management */
515         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
516         p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
517                                                       i_samples );
518         return p_aout_buffer;
519     }
520     else
521     {
522         return NULL;
523     }
524 }
525
526 /*****************************************************************************
527  * SendPacket: send an ogg dated packet to the stream output.
528  *****************************************************************************/
529 static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
530                             block_t *p_block )
531 {
532     decoder_sys_t *p_sys = p_dec->p_sys;
533     int i_block_size, i_samples;
534
535     i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket );
536     if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
537     i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
538     p_sys->i_last_block_size = i_block_size;
539
540     /* Date management */
541     p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
542
543     if( p_sys->i_headers >= 3 )
544         p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) -
545             p_block->i_pts;
546     else
547         p_block->i_length = 0;
548
549     return p_block;
550 }
551
552 /*****************************************************************************
553  * ParseVorbisComments: FIXME should be done in demuxer
554  *****************************************************************************/
555 static void ParseVorbisComments( decoder_t *p_dec )
556 {
557     input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
558     char *psz_name, *psz_value, *psz_comment;
559     int i = 0;
560
561     if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
562
563     while( i < p_dec->p_sys->vc.comments )
564     {
565         psz_comment = strdup( p_dec->p_sys->vc.user_comments[i] );
566         if( !psz_comment )
567         {
568             msg_Warn( p_dec, "out of memory" );
569             break;
570         }
571         psz_name = psz_comment;
572         psz_value = strchr( psz_comment, '=' );
573         if( psz_value )
574         {
575             *psz_value = '\0';
576             psz_value++;
577             input_Control( p_input, INPUT_ADD_INFO, _("Vorbis comment"),
578                            psz_name, psz_value );
579             /* HACK, we should use meta */
580             if( strstr( psz_name, "artist" ) )
581             {
582                 input_Control( p_input, INPUT_ADD_INFO, _("Meta-information"),
583                                _("Artist"), psz_value );
584             }
585             else if( strstr( psz_name, "title" ) )
586             {
587                 p_input->input.p_item->psz_name = strdup( psz_value );
588             }
589         }
590         /* FIXME */
591         var_SetInteger( p_input, "item-change", p_input->input.p_item->i_id );
592         free( psz_comment );
593         i++;
594     }
595 }
596
597 /*****************************************************************************
598  * Interleave: helper function to interleave channels
599  *****************************************************************************/
600 static void Interleave(
601 #ifdef MODULE_NAME_IS_tremor
602                         int32_t *p_out, const int32_t **pp_in,
603 #else
604                         float *p_out, const float **pp_in,
605 #endif
606                         int i_nb_channels, int i_samples )
607 {
608     int i, j;
609
610     for ( j = 0; j < i_samples; j++ )
611     {
612         for ( i = 0; i < i_nb_channels; i++ )
613         {
614             p_out[j * i_nb_channels + i] = pp_in[i][j];
615         }
616     }
617 }
618
619 /*****************************************************************************
620  * CloseDecoder: vorbis decoder destruction
621  *****************************************************************************/
622 static void CloseDecoder( vlc_object_t *p_this )
623 {
624     decoder_t *p_dec = (decoder_t *)p_this;
625     decoder_sys_t *p_sys = p_dec->p_sys;
626
627     if( !p_sys->b_packetizer && p_sys->i_headers >= 3 )
628     {
629         vorbis_block_clear( &p_sys->vb );
630         vorbis_dsp_clear( &p_sys->vd );
631     }
632
633     vorbis_comment_clear( &p_sys->vc );
634     vorbis_info_clear( &p_sys->vi );  /* must be called last */
635
636     free( p_sys );
637 }
638
639 #if defined(HAVE_VORBIS_VORBISENC_H) && !defined(MODULE_NAME_IS_tremor)
640
641 /*****************************************************************************
642  * encoder_sys_t : vorbis encoder descriptor
643  *****************************************************************************/
644 struct encoder_sys_t
645 {
646     /*
647      * Vorbis properties
648      */
649     vorbis_info      vi; /* struct that stores all the static vorbis bitstream
650                             settings */
651     vorbis_comment   vc; /* struct that stores all the bitstream user
652                           * comments */
653     vorbis_dsp_state vd; /* central working state for the packet->PCM
654                           * decoder */
655     vorbis_block     vb; /* local working space for packet->PCM decode */
656
657     int i_last_block_size;
658     int i_samples_delay;
659     int i_channels;
660
661     /*
662      * Common properties
663      */
664     mtime_t i_pts;
665 };
666
667 /*****************************************************************************
668  * OpenEncoder: probe the encoder and return score
669  *****************************************************************************/
670 static int OpenEncoder( vlc_object_t *p_this )
671 {
672     encoder_t *p_enc = (encoder_t *)p_this;
673     encoder_sys_t *p_sys;
674     int i_quality, i_min_bitrate, i_max_bitrate, i;
675     ogg_packet header[3];
676     vlc_value_t val;
677     uint8_t *p_extra;
678
679     if( p_enc->fmt_out.i_codec != VLC_FOURCC('v','o','r','b') &&
680         !p_enc->b_force )
681     {
682         return VLC_EGENERIC;
683     }
684
685     /* Allocate the memory needed to store the decoder's structure */
686     if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
687     {
688         msg_Err( p_enc, "out of memory" );
689         return VLC_EGENERIC;
690     }
691     p_enc->p_sys = p_sys;
692
693     p_enc->pf_encode_audio = Encode;
694     p_enc->fmt_in.i_codec = VLC_FOURCC('f','l','3','2');
695     p_enc->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
696
697     sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
698
699     var_Get( p_enc, ENC_CFG_PREFIX "quality", &val );
700     i_quality = val.i_int;
701     if( i_quality > 10 ) i_quality = 10;
702     if( i_quality < 0 ) i_quality = 0;
703     var_Get( p_enc, ENC_CFG_PREFIX "cbr", &val );
704     if( val.b_bool ) i_quality = 0;
705     var_Get( p_enc, ENC_CFG_PREFIX "max-bitrate", &val );
706     i_max_bitrate = val.i_int;
707     var_Get( p_enc, ENC_CFG_PREFIX "min-bitrate", &val );
708     i_min_bitrate = val.i_int;
709
710     /* Initialize vorbis encoder */
711     vorbis_info_init( &p_sys->vi );
712
713     if( i_quality > 0 )
714     {
715         /* VBR mode */
716         if( vorbis_encode_setup_vbr( &p_sys->vi,
717               p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
718               i_quality * 0.1 ) )
719         {
720             vorbis_info_clear( &p_sys->vi );
721             free( p_enc->p_sys );
722             msg_Err( p_enc, "VBR mode initialisation failed" );
723             return VLC_EGENERIC;
724         }
725
726         /* Do we have optional hard quality restrictions? */
727         if( i_max_bitrate > 0 || i_min_bitrate > 0 )
728         {
729             struct ovectl_ratemanage_arg ai;
730             vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_GET, &ai );
731
732             ai.bitrate_hard_min = i_min_bitrate;
733             ai.bitrate_hard_max = i_max_bitrate;
734             ai.management_active = 1;
735
736             vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, &ai );
737
738         }
739         else
740         {
741             /* Turn off management entirely */
742             vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, NULL );
743         }
744     }
745     else
746     {
747         if( vorbis_encode_setup_managed( &p_sys->vi,
748               p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
749               i_min_bitrate > 0 ? i_min_bitrate * 1000: -1,
750               p_enc->fmt_out.i_bitrate,
751               i_max_bitrate > 0 ? i_max_bitrate * 1000: -1 ) )
752           {
753               vorbis_info_clear( &p_sys->vi );
754               msg_Err( p_enc, "CBR mode initialisation failed" );
755               free( p_enc->p_sys );
756               return VLC_EGENERIC;
757           }
758     }
759
760     vorbis_encode_setup_init( &p_sys->vi );
761
762     /* Add a comment */
763     vorbis_comment_init( &p_sys->vc);
764     vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player");
765
766     /* Set up the analysis state and auxiliary encoding storage */
767     vorbis_analysis_init( &p_sys->vd, &p_sys->vi );
768     vorbis_block_init( &p_sys->vd, &p_sys->vb );
769
770     /* Create and store headers */
771     vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
772                                &header[0], &header[1], &header[2]);
773     p_enc->fmt_out.i_extra = 3 * 2 + header[0].bytes +
774        header[1].bytes + header[2].bytes;
775     p_extra = p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
776     for( i = 0; i < 3; i++ )
777     {
778         *(p_extra++) = header[i].bytes >> 8;
779         *(p_extra++) = header[i].bytes & 0xFF;
780         memcpy( p_extra, header[i].packet, header[i].bytes );
781         p_extra += header[i].bytes;
782     }
783
784     p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
785     p_sys->i_last_block_size = 0;
786     p_sys->i_samples_delay = 0;
787     p_sys->i_pts = 0;
788
789     return VLC_SUCCESS;
790 }
791
792 /****************************************************************************
793  * Encode: the whole thing
794  ****************************************************************************
795  * This function spits out ogg packets.
796  ****************************************************************************/
797 static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
798 {
799     encoder_sys_t *p_sys = p_enc->p_sys;
800     ogg_packet oggpacket;
801     block_t *p_block, *p_chain = NULL;
802     float **buffer;
803     int i;
804     unsigned int j;
805
806     p_sys->i_pts = p_aout_buf->start_date -
807                 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
808                 (mtime_t)p_enc->fmt_in.audio.i_rate;
809
810     p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
811
812     buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples );
813
814     /* convert samples to float and uninterleave */
815     for( i = 0; i < p_sys->i_channels; i++ )
816     {
817         for( j = 0 ; j < p_aout_buf->i_nb_samples ; j++ )
818         {
819             buffer[i][j]= ((float *)p_aout_buf->p_buffer)
820                                     [j * p_sys->i_channels + i ];
821         }
822     }
823
824     vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples );
825
826     while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
827     {
828         int i_samples;
829
830         vorbis_analysis( &p_sys->vb, NULL );
831         vorbis_bitrate_addblock( &p_sys->vb );
832
833         while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) )
834         {
835             int i_block_size;
836             p_block = block_New( p_enc, oggpacket.bytes );
837             memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
838
839             i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket );
840
841             if( i_block_size < 0 ) i_block_size = 0;
842             i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
843             p_sys->i_last_block_size = i_block_size;
844
845             p_block->i_length = (mtime_t)1000000 *
846                 (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate;
847
848             p_block->i_dts = p_block->i_pts = p_sys->i_pts;
849
850             p_sys->i_samples_delay -= i_samples;
851
852             /* Update pts */
853             p_sys->i_pts += p_block->i_length;
854             block_ChainAppend( &p_chain, p_block );
855         }
856     }
857
858     return p_chain;
859 }
860
861 /*****************************************************************************
862  * CloseEncoder: vorbis encoder destruction
863  *****************************************************************************/
864 static void CloseEncoder( vlc_object_t *p_this )
865 {
866     encoder_t *p_enc = (encoder_t *)p_this;
867     encoder_sys_t *p_sys = p_enc->p_sys;
868
869     vorbis_block_clear( &p_sys->vb );
870     vorbis_dsp_clear( &p_sys->vd );
871     vorbis_comment_clear( &p_sys->vc );
872     vorbis_info_clear( &p_sys->vi );  /* must be called last */
873
874     free( p_sys );
875 }
876
877 #endif /* HAVE_VORBIS_VORBISENC_H && !MODULE_NAME_IS_tremor */