]> git.sesse.net Git - vlc/blob - modules/codec/speex.c
lua/intf: Fix a memleak.
[vlc] / modules / codec / speex.c
1 /*****************************************************************************
2  * speex.c: speex decoder/packetizer/encoder module making use of libspeex.
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_input.h>
34 #include <vlc_codec.h>
35 #include <vlc_aout.h>
36
37 #include <ogg/ogg.h>
38 #include <speex/speex.h>
39 #include <speex/speex_header.h>
40 #include <speex/speex_stereo.h>
41 #include <speex/speex_callbacks.h>
42
43 #include <assert.h>
44
45 /*****************************************************************************
46  * decoder_sys_t : speex decoder descriptor
47  *****************************************************************************/
48 struct decoder_sys_t
49 {
50     /* Module mode */
51     bool b_packetizer;
52
53     /*
54      * Input properties
55      */
56     int i_headers;
57     int i_frame_in_packet;
58
59     /*
60      * Speex properties
61      */
62     SpeexBits bits;
63     SpeexHeader *p_header;
64     SpeexStereoState stereo;
65     void *p_state;
66     unsigned int rtp_rate;
67
68     /*
69      * Common properties
70      */
71     audio_date_t end_date;
72
73 };
74
75 static int pi_channels_maps[6] =
76 {
77     0,
78     AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
79     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
80     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
81      | AOUT_CHAN_REARRIGHT,
82     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
83      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
84 };
85
86 /****************************************************************************
87  * Local prototypes
88  ****************************************************************************/
89 static int  OpenDecoder   ( vlc_object_t * );
90 static int  OpenPacketizer( vlc_object_t * );
91 static void CloseDecoder  ( vlc_object_t * );
92
93 static void *DecodeBlock  ( decoder_t *, block_t ** );
94 static aout_buffer_t *DecodeRtpSpeexPacket( decoder_t *, block_t **);
95 static int  ProcessHeaders( decoder_t * );
96 static int  ProcessInitialHeader ( decoder_t *, ogg_packet * );
97 static void *ProcessPacket( decoder_t *, ogg_packet *, block_t ** );
98
99 static aout_buffer_t *DecodePacket( decoder_t *, ogg_packet * );
100 static block_t *SendPacket( decoder_t *, block_t * );
101
102 static void ParseSpeexComments( decoder_t *, ogg_packet * );
103
104 static int OpenEncoder   ( vlc_object_t * );
105 static void CloseEncoder ( vlc_object_t * );
106 static block_t *Encode   ( encoder_t *, aout_buffer_t * );
107
108 /*****************************************************************************
109  * Module descriptor
110  *****************************************************************************/
111 vlc_module_begin();
112     set_category( CAT_INPUT );
113     set_subcategory( SUBCAT_INPUT_ACODEC );
114
115     set_description( N_("Speex audio decoder") );
116     set_capability( "decoder", 100 );
117     set_callbacks( OpenDecoder, CloseDecoder );
118
119     add_submodule();
120     set_description( N_("Speex audio packetizer") );
121     set_capability( "packetizer", 100 );
122     set_callbacks( OpenPacketizer, CloseDecoder );
123
124     add_submodule();
125     set_description( N_("Speex audio encoder") );
126     set_capability( "encoder", 100 );
127     set_callbacks( OpenEncoder, CloseEncoder );
128 vlc_module_end();
129
130 /*****************************************************************************
131  * OpenDecoder: probe the decoder and return score
132  *****************************************************************************/
133 static int OpenDecoder( vlc_object_t *p_this )
134 {
135     decoder_t *p_dec = (decoder_t*)p_this;
136     decoder_sys_t *p_sys = p_dec->p_sys;
137
138     if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','x',' ') 
139         && p_dec->fmt_in.i_codec != VLC_FOURCC('s', 'p', 'x', 'r') )
140     {
141         return VLC_EGENERIC;
142     }
143
144     /* Allocate the memory needed to store the decoder's structure */
145     if( ( p_dec->p_sys = p_sys =
146           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
147         return VLC_ENOMEM;
148     p_dec->p_sys->bits.buf_size = 0;
149     p_dec->p_sys->b_packetizer = false;
150     p_dec->p_sys->rtp_rate = p_dec->fmt_in.audio.i_rate;
151
152     aout_DateSet( &p_sys->end_date, 0 );
153
154     /* Set output properties */
155     p_dec->fmt_out.i_cat = AUDIO_ES;
156     p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
157
158     /*
159       Set callbacks
160       If the codec is spxr then this decoder is 
161       being invoked on a Speex stream arriving via RTP. 
162       A special decoder callback is used.
163     */
164     if (p_dec->fmt_in.i_codec == VLC_FOURCC('s', 'p', 'x', 'r'))
165     {
166         msg_Dbg( p_dec, "Using RTP version of Speex decoder @ rate %d.", 
167             p_dec->fmt_in.audio.i_rate );
168         p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
169             DecodeRtpSpeexPacket;
170     }
171     else
172     {
173         p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
174             DecodeBlock;
175     }
176     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
177         DecodeBlock;
178
179     p_sys->i_headers = 0;
180     p_sys->p_state = NULL;
181     p_sys->p_header = NULL;
182     p_sys->i_frame_in_packet = 0;
183
184     return VLC_SUCCESS;
185 }
186
187 static int OpenPacketizer( vlc_object_t *p_this )
188 {
189     decoder_t *p_dec = (decoder_t*)p_this;
190
191     int i_ret = OpenDecoder( p_this );
192
193     if( i_ret == VLC_SUCCESS )
194     {
195         p_dec->p_sys->b_packetizer = true;
196         p_dec->fmt_out.i_codec = VLC_FOURCC('s','p','x',' ');
197     }
198
199     return i_ret;
200 }
201
202 /****************************************************************************
203  * DecodeBlock: the whole thing
204  ****************************************************************************
205  * This function must be fed with ogg packets.
206  ****************************************************************************/
207 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
208 {
209     decoder_sys_t *p_sys = p_dec->p_sys;
210     ogg_packet oggpacket;
211
212     if( !pp_block ) return NULL;
213
214     if( *pp_block )
215     {
216         /* Block to Ogg packet */
217         oggpacket.packet = (*pp_block)->p_buffer;
218         oggpacket.bytes = (*pp_block)->i_buffer;
219     }
220     else
221     {
222         if( p_sys->b_packetizer ) return NULL;
223
224         /* Block to Ogg packet */
225         oggpacket.packet = NULL;
226         oggpacket.bytes = 0;
227     }
228
229     oggpacket.granulepos = -1;
230     oggpacket.b_o_s = 0;
231     oggpacket.e_o_s = 0;
232     oggpacket.packetno = 0;
233
234     /* Check for headers */
235     if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
236     {
237         p_sys->i_headers = 2;
238     }
239     else if( oggpacket.bytes && p_sys->i_headers < 2 )
240     {
241         uint8_t *p_extra;
242
243         p_dec->fmt_in.p_extra =
244             realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra +
245                      oggpacket.bytes + 2 );
246         p_extra = ((uint8_t *)p_dec->fmt_in.p_extra) + p_dec->fmt_in.i_extra;
247         *(p_extra++) = oggpacket.bytes >> 8;
248         *(p_extra++) = oggpacket.bytes & 0xFF;
249
250         memcpy( p_extra, oggpacket.packet, oggpacket.bytes );
251         p_dec->fmt_in.i_extra += oggpacket.bytes + 2;
252
253         block_Release( *pp_block );
254         p_sys->i_headers++;
255         return NULL;
256     }
257
258     if( p_sys->i_headers == 2 )
259     {
260         if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
261         {
262             p_sys->i_headers = 0;
263             p_dec->fmt_in.i_extra = 0;
264             block_Release( *pp_block );
265             return NULL;
266         }
267         else p_sys->i_headers++;
268     }
269
270     return ProcessPacket( p_dec, &oggpacket, pp_block );
271 }
272
273 /*****************************************************************************
274  * ProcessHeaders: process Speex headers.
275  *****************************************************************************/
276 static int ProcessHeaders( decoder_t *p_dec )
277 {
278     decoder_sys_t *p_sys = p_dec->p_sys;
279     ogg_packet oggpacket;
280     uint8_t *p_extra;
281     int i_extra;
282
283     if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
284
285     oggpacket.granulepos = -1;
286     oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
287     oggpacket.e_o_s = 0;
288     oggpacket.packetno = 0;
289     p_extra = p_dec->fmt_in.p_extra;
290     i_extra = p_dec->fmt_in.i_extra;
291
292     /* Take care of the initial Vorbis header */
293     oggpacket.bytes = *(p_extra++) << 8;
294     oggpacket.bytes |= (*(p_extra++) & 0xFF);
295     oggpacket.packet = p_extra;
296     p_extra += oggpacket.bytes;
297     i_extra -= (oggpacket.bytes + 2);
298     if( i_extra < 0 )
299     {
300         msg_Err( p_dec, "header data corrupted");
301         return VLC_EGENERIC;
302     }
303
304     /* Take care of the initial Speex header */
305     if( ProcessInitialHeader( p_dec, &oggpacket ) != VLC_SUCCESS )
306     {
307         msg_Err( p_dec, "initial Speex header is corrupted" );
308         return VLC_EGENERIC;
309     }
310
311     /* The next packet in order is the comments header */
312     oggpacket.b_o_s = 0;
313     oggpacket.bytes = *(p_extra++) << 8;
314     oggpacket.bytes |= (*(p_extra++) & 0xFF);
315     oggpacket.packet = p_extra;
316     p_extra += oggpacket.bytes;
317     i_extra -= (oggpacket.bytes + 2);
318     if( i_extra < 0 )
319     {
320         msg_Err( p_dec, "header data corrupted");
321         return VLC_EGENERIC;
322     }
323
324     ParseSpeexComments( p_dec, &oggpacket );
325
326     if( p_sys->b_packetizer )
327     {
328         p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
329         p_dec->fmt_out.p_extra =
330             realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
331         memcpy( p_dec->fmt_out.p_extra,
332                 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
333     }
334
335     return VLC_SUCCESS;
336 }
337
338 /*****************************************************************************
339  * ProcessInitialHeader: processes the inital Speex header packet.
340  *****************************************************************************/
341 static int ProcessInitialHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
342 {
343     decoder_sys_t *p_sys = p_dec->p_sys;
344
345     void *p_state;
346     SpeexHeader *p_header;
347     const SpeexMode *p_mode;
348     SpeexCallback callback;
349
350     p_sys->p_header = p_header =
351         speex_packet_to_header( (char *)p_oggpacket->packet,
352                                 p_oggpacket->bytes );
353     if( !p_header )
354     {
355         msg_Err( p_dec, "cannot read Speex header" );
356         return VLC_EGENERIC;
357     }
358     if( p_header->mode >= SPEEX_NB_MODES || p_header->mode < 0 )
359     {
360         msg_Err( p_dec, "mode number %d does not (yet/any longer) exist in "
361                  "this version of libspeex.", p_header->mode );
362         return VLC_EGENERIC;
363     }
364
365     p_mode = speex_mode_list[p_header->mode];
366     if( p_mode == NULL )
367         return VLC_EGENERIC;
368
369     if( p_header->speex_version_id > 1 )
370     {
371         msg_Err( p_dec, "this file was encoded with Speex bit-stream "
372                  "version %d which is not supported by this decoder.",
373                  p_header->speex_version_id );
374         return VLC_EGENERIC;
375     }
376
377     if( p_mode->bitstream_version < p_header->mode_bitstream_version )
378     {
379         msg_Err( p_dec, "file encoded with a newer version of Speex." );
380         return VLC_EGENERIC;
381     }
382     if( p_mode->bitstream_version > p_header->mode_bitstream_version )
383     {
384         msg_Err( p_dec, "file encoded with an older version of Speex." );
385         return VLC_EGENERIC;
386     }
387
388     msg_Dbg( p_dec, "Speex %d Hz audio using %s mode %s%s",
389              p_header->rate, p_mode->modeName,
390              ( p_header->nb_channels == 1 ) ? " (mono" : " (stereo",
391              p_header->vbr ? ", VBR)" : ")" );
392
393     /* Take care of speex decoder init */
394     speex_bits_init( &p_sys->bits );
395     p_sys->p_state = p_state = speex_decoder_init( p_mode );
396     if( !p_state )
397     {
398         msg_Err( p_dec, "decoder initialization failed" );
399         return VLC_EGENERIC;
400     }
401
402     if( p_header->nb_channels == 2 )
403     {
404         SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
405         p_sys->stereo = stereo;
406         callback.callback_id = SPEEX_INBAND_STEREO;
407         callback.func = speex_std_stereo_request_handler;
408         callback.data = &p_sys->stereo;
409         speex_decoder_ctl( p_state, SPEEX_SET_HANDLER, &callback );
410     }
411     if( p_header->nb_channels <= 0 ||
412         p_header->nb_channels > 5 )
413     {
414         msg_Err( p_dec, "invalid number of channels (not between 1 and 5): %i",
415                  p_header->nb_channels );
416         return VLC_EGENERIC;
417     }
418
419     /* Setup the format */
420     p_dec->fmt_out.audio.i_physical_channels =
421         p_dec->fmt_out.audio.i_original_channels =
422             pi_channels_maps[p_header->nb_channels];
423     p_dec->fmt_out.audio.i_channels = p_header->nb_channels;
424     p_dec->fmt_out.audio.i_rate = p_header->rate;
425
426     aout_DateInit( &p_sys->end_date, p_header->rate );
427
428     return VLC_SUCCESS;
429 }
430
431 /*****************************************************************************
432  * ProcessPacket: processes a Speex packet.
433  *****************************************************************************/
434 static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
435                             block_t **pp_block )
436 {
437     decoder_sys_t *p_sys = p_dec->p_sys;
438     block_t *p_block = *pp_block;
439
440     /* Date management */
441     if( p_block && p_block->i_pts > 0 && 
442         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
443     {
444         aout_DateSet( &p_sys->end_date, p_block->i_pts );
445     }
446
447     if( !aout_DateGet( &p_sys->end_date ) )
448     {
449         /* We've just started the stream, wait for the first PTS. */
450         if( p_block ) block_Release( p_block );
451         return NULL;
452     }
453
454     *pp_block = NULL; /* To avoid being fed the same packet again */
455
456     if( p_sys->b_packetizer )
457     {
458         if ( p_sys->p_header->frames_per_packet > 1 )
459         {
460             short *p_frame_holder = NULL;
461             int i_bits_before = 0, i_bits_after = 0, i_bytes_in_speex_frame = 0,
462                 i_pcm_output_size = 0, i_bits_in_speex_frame = 0;
463             block_t *p_new_block = NULL;
464
465             i_pcm_output_size = p_sys->p_header->frame_size;
466             p_frame_holder = (short*)malloc( sizeof(short)*i_pcm_output_size );
467
468             speex_bits_read_from( &p_sys->bits, (char*)p_oggpacket->packet,
469                 p_oggpacket->bytes);
470             i_bits_before = speex_bits_remaining( &p_sys->bits );
471             speex_decode_int(p_sys->p_state, &p_sys->bits, p_frame_holder);
472             i_bits_after = speex_bits_remaining( &p_sys->bits );
473
474             i_bits_in_speex_frame = i_bits_before - i_bits_after;
475             i_bytes_in_speex_frame = ( i_bits_in_speex_frame + 
476                 (8 - (i_bits_in_speex_frame % 8)) )
477                 / 8;
478
479             p_new_block = block_New( p_dec, i_bytes_in_speex_frame );
480             memset( p_new_block->p_buffer, 0xff, i_bytes_in_speex_frame );
481
482             /*
483              * Copy the first frame in this packet to a new packet.
484              */
485             speex_bits_rewind( &p_sys->bits );
486             speex_bits_write( &p_sys->bits, 
487                 (char*)p_new_block->p_buffer, 
488                     (int)i_bytes_in_speex_frame );
489
490             /*
491              * Move the remaining part of the original packet (subsequent
492              * frames, if there are any) into the beginning 
493              * of the original packet so
494              * they are preserved following the realloc. 
495              * Note: Any bits that
496              * remain in the initial packet
497              * are "filler" if they do not constitute
498              * an entire byte. 
499              */
500             if ( i_bits_after > 7 )
501             {
502                 /* round-down since we rounded-up earlier (to include
503                  * the speex terminator code. 
504                  */
505                 i_bytes_in_speex_frame--;
506                 speex_bits_write( &p_sys->bits, 
507                         (char*)p_block->p_buffer, 
508                         p_block->i_buffer - i_bytes_in_speex_frame );
509             p_block = block_Realloc( p_block, 
510                     0, 
511                         p_block->i_buffer-i_bytes_in_speex_frame );
512                 *pp_block = p_block;
513             }
514             else
515             {
516                 speex_bits_reset( &p_sys->bits );
517             }
518
519             free( p_frame_holder );
520             return SendPacket( p_dec, p_new_block);
521         }
522         else
523         {
524             return SendPacket( p_dec, p_block );
525         }
526     }
527     else
528     {
529         aout_buffer_t *p_aout_buffer;
530
531         if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 )
532             p_aout_buffer = DecodePacket( p_dec, p_oggpacket );
533         else
534             p_aout_buffer = NULL; /* Skip headers */
535
536         if( p_block ) block_Release( p_block );
537         return p_aout_buffer;
538     }
539 }
540
541 static aout_buffer_t *DecodeRtpSpeexPacket( decoder_t *p_dec, block_t **pp_block )
542 {
543     block_t *p_speex_bit_block = *pp_block;
544     decoder_sys_t *p_sys = p_dec->p_sys;
545     aout_buffer_t *p_aout_buffer;
546     int i_decode_ret;
547     unsigned int i_speex_frame_size;
548
549     if ( !p_speex_bit_block || p_speex_bit_block->i_pts == 0 ) return NULL;
550
551     /* 
552       If the SpeexBits buffer size is 0 (a default value),
553       we know that a proper initialization has not yet been done.
554     */
555     if ( p_sys->bits.buf_size==0 )
556     {
557         p_sys->p_header = (SpeexHeader *)malloc(sizeof(SpeexHeader));
558         if ( !p_sys->p_header )
559         {
560             msg_Err( p_dec, "Could not allocate a Speex header.");
561             return NULL;
562         }
563         speex_init_header( p_sys->p_header,p_sys->rtp_rate,1,&speex_nb_mode );
564         speex_bits_init( &p_sys->bits );
565         p_sys->p_state = speex_decoder_init( &speex_nb_mode );
566         if ( !p_sys->p_state )
567         {
568             msg_Err( p_dec, "Could not allocate a Speex decoder." );
569             free( p_sys->p_header );
570             return NULL;
571         }
572
573         /*
574           Assume that variable bit rate is enabled. Also assume
575           that there is only one frame per packet. 
576         */
577         p_sys->p_header->vbr = 1;
578         p_sys->p_header->frames_per_packet = 1;
579
580         p_dec->fmt_out.audio.i_channels = p_sys->p_header->nb_channels;
581         p_dec->fmt_out.audio.i_physical_channels = 
582         p_dec->fmt_out.audio.i_original_channels = 
583             pi_channels_maps[p_sys->p_header->nb_channels];
584         p_dec->fmt_out.audio.i_rate = p_sys->p_header->rate;
585
586         if ( speex_mode_query( &speex_nb_mode, 
587             SPEEX_MODE_FRAME_SIZE, 
588             &i_speex_frame_size ) )
589         {
590             msg_Err( p_dec, "Could not determine the frame size." );
591             speex_decoder_destroy( p_sys->p_state );
592             free( p_sys->p_header );
593             return NULL;
594         }
595         p_dec->fmt_out.audio.i_bytes_per_frame = i_speex_frame_size;
596
597         aout_DateInit(&p_sys->end_date, p_sys->p_header->rate);
598     }
599
600     /* 
601       If the SpeexBits are initialized but there is 
602       still no header, an error must be thrown.
603     */
604     if ( !p_sys->p_header )
605     {
606         msg_Err( p_dec, "There is no valid Speex header found." );
607         return NULL;
608     }
609     *pp_block = NULL;
610
611     if ( !aout_DateGet( &p_sys->end_date ) )
612         aout_DateSet( &p_sys->end_date, p_speex_bit_block->i_dts );
613
614     /*
615       Ask for a new audio output buffer and make sure
616       we get one. 
617     */
618     p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, 
619         p_sys->p_header->frame_size );
620     if ( !p_aout_buffer || p_aout_buffer->i_nb_bytes == 0 )
621     {
622         msg_Err(p_dec, "Oops: No new buffer was returned!");
623         return NULL;
624     }
625
626     /*
627       Read the Speex payload into the SpeexBits buffer.
628     */
629     speex_bits_read_from( &p_sys->bits, 
630         (char*)p_speex_bit_block->p_buffer, 
631         p_speex_bit_block->i_buffer );
632     
633     /* 
634       Decode the input and ensure that no errors 
635       were encountered.
636     */
637     i_decode_ret = speex_decode_int( p_sys->p_state, &p_sys->bits, 
638             (int16_t*)p_aout_buffer->p_buffer );
639     if ( i_decode_ret < 0 )
640     {
641         msg_Err( p_dec, "Decoding failed. Perhaps we have a bad stream?" );
642         return NULL;
643     }
644
645     /* 
646       Handle date management on the audio output buffer. 
647     */
648     p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
649     p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date, 
650         p_sys->p_header->frame_size );
651     
652     
653     p_sys->i_frame_in_packet++;
654     block_Release( p_speex_bit_block );
655
656     return p_aout_buffer;
657 }
658
659 /*****************************************************************************
660  * DecodePacket: decodes a Speex packet.
661  *****************************************************************************/
662 static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
663 {
664     decoder_sys_t *p_sys = p_dec->p_sys;
665
666     if( p_oggpacket->bytes )
667     {
668         /* Copy Ogg packet to Speex bitstream */
669         speex_bits_read_from( &p_sys->bits, (char *)p_oggpacket->packet,
670                               p_oggpacket->bytes );
671         p_sys->i_frame_in_packet = 0;
672     }
673
674     /* Decode one frame at a time */
675     if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet )
676     {
677         aout_buffer_t *p_aout_buffer;
678         if( p_sys->p_header->frame_size == 0 )
679             return NULL;
680
681         p_aout_buffer =
682             p_dec->pf_aout_buffer_new( p_dec, p_sys->p_header->frame_size );
683         if( !p_aout_buffer )
684         {
685             return NULL;
686         }
687
688         switch( speex_decode_int( p_sys->p_state, &p_sys->bits,
689                                   (int16_t *)p_aout_buffer->p_buffer ) )
690         {
691             case -2:
692                 msg_Err( p_dec, "decoding error: corrupted stream?" );
693             case -1: /* End of stream */
694                 return NULL;
695         }
696
697         if( speex_bits_remaining( &p_sys->bits ) < 0 )
698         {
699             msg_Err( p_dec, "decoding overflow: corrupted stream?" );
700         }
701
702         if( p_sys->p_header->nb_channels == 2 )
703             speex_decode_stereo_int( (int16_t *)p_aout_buffer->p_buffer,
704                                      p_sys->p_header->frame_size,
705                                      &p_sys->stereo );
706
707         /* Date management */
708         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
709         p_aout_buffer->end_date =
710             aout_DateIncrement( &p_sys->end_date, p_sys->p_header->frame_size );
711
712         p_sys->i_frame_in_packet++;
713
714         return p_aout_buffer;
715     }
716     else
717     {
718         return NULL;
719     }
720 }
721
722 /*****************************************************************************
723  * SendPacket: send an ogg packet to the stream output.
724  *****************************************************************************/
725 static block_t *SendPacket( decoder_t *p_dec, block_t *p_block )
726 {
727     decoder_sys_t *p_sys = p_dec->p_sys;
728
729     /* Date management */
730     p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
731
732     if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 )
733     {
734         p_block->i_length =
735             aout_DateIncrement( &p_sys->end_date,
736                                 p_sys->p_header->frame_size ) -
737             p_block->i_pts;
738     }
739     else
740         p_block->i_length = 0;
741
742     return p_block;
743 }
744
745 /*****************************************************************************
746  * ParseSpeexComments: FIXME should be done in demuxer
747  *****************************************************************************/
748 #define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
749                            ((buf[base+2]<<16)&0xff0000)| \
750                            ((buf[base+1]<<8)&0xff00)| \
751                             (buf[base]&0xff))
752
753 static void ParseSpeexComments( decoder_t *p_dec, ogg_packet *p_oggpacket )
754 {
755     input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
756     decoder_sys_t *p_sys = p_dec->p_sys;
757
758     char *p_buf = (char *)p_oggpacket->packet;
759     const SpeexMode *p_mode;
760     int i_len;
761
762     if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
763
764     assert( p_sys->p_header->mode < SPEEX_NB_MODES );
765
766     p_mode = speex_mode_list[p_sys->p_header->mode];
767     assert( p_mode != NULL );
768
769     input_Control( p_input, INPUT_ADD_INFO, _("Speex comment"), _("Mode"),
770                    "%s%s", p_mode->modeName,
771                    p_sys->p_header->vbr ? " VBR" : "" );
772
773     if( p_oggpacket->bytes < 8 )
774     {
775         msg_Err( p_dec, "invalid/corrupted comments" );
776         return;
777     }
778
779     i_len = readint( p_buf, 0 ); p_buf += 4;
780     if( i_len > p_oggpacket->bytes - 4 )
781     {
782         msg_Err( p_dec, "invalid/corrupted comments" );
783         return;
784     }
785
786     input_Control( p_input, INPUT_ADD_INFO, _("Speex comment"), p_buf, "" );
787
788     /* TODO: finish comments parsing */
789 }
790
791 /*****************************************************************************
792  * CloseDecoder: speex decoder destruction
793  *****************************************************************************/
794 static void CloseDecoder( vlc_object_t *p_this )
795 {
796     decoder_t * p_dec = (decoder_t *)p_this;
797     decoder_sys_t *p_sys = p_dec->p_sys;
798
799     if( p_sys->p_state )
800     {
801         speex_decoder_destroy( p_sys->p_state );
802         speex_bits_destroy( &p_sys->bits );
803     }
804
805     free( p_sys->p_header );
806     free( p_sys );
807 }
808
809 /*****************************************************************************
810  * encoder_sys_t: encoder descriptor
811  *****************************************************************************/
812 #define MAX_FRAME_SIZE  2000
813 #define MAX_FRAME_BYTES 2000
814
815 struct encoder_sys_t
816 {
817     /*
818      * Input properties
819      */
820     char *p_buffer;
821     char p_buffer_out[MAX_FRAME_BYTES];
822
823     /*
824      * Speex properties
825      */
826     SpeexBits bits;
827     SpeexHeader header;
828     SpeexStereoState stereo;
829     void *p_state;
830
831     int i_frames_per_packet;
832     int i_frames_in_packet;
833
834     int i_frame_length;
835     int i_samples_delay;
836     int i_frame_size;
837
838     /*
839      * Common properties
840      */
841     mtime_t i_pts;
842 };
843
844 /*****************************************************************************
845  * OpenEncoder: probe the encoder and return score
846  *****************************************************************************/
847 static int OpenEncoder( vlc_object_t *p_this )
848 {
849     encoder_t *p_enc = (encoder_t *)p_this;
850     encoder_sys_t *p_sys;
851     const SpeexMode *p_speex_mode = &speex_nb_mode;
852     int i_quality, i;
853     const char *pp_header[2];
854     int pi_header[2];
855     uint8_t *p_extra;
856
857     if( p_enc->fmt_out.i_codec != VLC_FOURCC('s','p','x',' ') &&
858         !p_enc->b_force )
859     {
860         return VLC_EGENERIC;
861     }
862
863     /* Allocate the memory needed to store the decoder's structure */
864     if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
865         return VLC_ENOMEM;
866     p_enc->p_sys = p_sys;
867     p_enc->pf_encode_audio = Encode;
868     p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE;
869     p_enc->fmt_out.i_codec = VLC_FOURCC('s','p','x',' ');
870
871     speex_init_header( &p_sys->header, p_enc->fmt_in.audio.i_rate,
872                        1, p_speex_mode );
873
874     p_sys->header.frames_per_packet = 1;
875     p_sys->header.vbr = 1;
876     p_sys->header.nb_channels = p_enc->fmt_in.audio.i_channels;
877
878     /* Create a new encoder state in narrowband mode */
879     p_sys->p_state = speex_encoder_init( p_speex_mode );
880
881     /* Set the quality to 8 (15 kbps) */
882     i_quality = 8;
883     speex_encoder_ctl( p_sys->p_state, SPEEX_SET_QUALITY, &i_quality );
884
885     /*Initialization of the structure that holds the bits*/
886     speex_bits_init( &p_sys->bits );
887
888     p_sys->i_frames_in_packet = 0;
889     p_sys->i_samples_delay = 0;
890     p_sys->i_pts = 0;
891
892     speex_encoder_ctl( p_sys->p_state, SPEEX_GET_FRAME_SIZE,
893                        &p_sys->i_frame_length );
894
895     p_sys->i_frame_size = p_sys->i_frame_length *
896         sizeof(int16_t) * p_enc->fmt_in.audio.i_channels;
897     p_sys->p_buffer = malloc( p_sys->i_frame_size );
898
899     /* Create and store headers */
900     pp_header[0] = speex_header_to_packet( &p_sys->header, &pi_header[0] );
901     pp_header[1] = "ENCODER=VLC media player";
902     pi_header[1] = sizeof("ENCODER=VLC media player");
903
904     p_enc->fmt_out.i_extra = 3 * 2 + pi_header[0] + pi_header[1];
905     p_extra = p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
906     for( i = 0; i < 2; i++ )
907     {
908         *(p_extra++) = pi_header[i] >> 8;
909         *(p_extra++) = pi_header[i] & 0xFF;
910         memcpy( p_extra, pp_header[i], pi_header[i] );
911         p_extra += pi_header[i];
912     }
913
914     msg_Dbg( p_enc, "encoding: frame size:%d, channels:%d, samplerate:%d",
915              p_sys->i_frame_size, p_enc->fmt_in.audio.i_channels,
916              p_enc->fmt_in.audio.i_rate );
917
918     return VLC_SUCCESS;
919 }
920
921 /****************************************************************************
922  * Encode: the whole thing
923  ****************************************************************************
924  * This function spits out ogg packets.
925  ****************************************************************************/
926 static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
927 {
928     encoder_sys_t *p_sys = p_enc->p_sys;
929     block_t *p_block, *p_chain = NULL;
930
931     unsigned char *p_buffer = p_aout_buf->p_buffer;
932     int i_samples = p_aout_buf->i_nb_samples;
933     int i_samples_delay = p_sys->i_samples_delay;
934
935     p_sys->i_pts = p_aout_buf->start_date -
936                 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
937                 (mtime_t)p_enc->fmt_in.audio.i_rate;
938
939     p_sys->i_samples_delay += i_samples;
940
941     while( p_sys->i_samples_delay >= p_sys->i_frame_length )
942     {
943         int16_t *p_samples;
944         int i_out;
945
946         if( i_samples_delay )
947         {
948             /* Take care of the left-over from last time */
949             int i_delay_size = i_samples_delay * 2 *
950                                  p_enc->fmt_in.audio.i_channels;
951             int i_size = p_sys->i_frame_size - i_delay_size;
952
953             p_samples = (int16_t *)p_sys->p_buffer;
954             memcpy( p_sys->p_buffer + i_delay_size, p_buffer, i_size );
955             p_buffer -= i_delay_size;
956             i_samples += i_samples_delay;
957             i_samples_delay = 0;
958         }
959         else
960         {
961             p_samples = (int16_t *)p_buffer;
962         }
963
964         /* Encode current frame */
965         if( p_enc->fmt_in.audio.i_channels == 2 )
966             speex_encode_stereo_int( p_samples, p_sys->i_frame_length,
967                                      &p_sys->bits );
968
969 #if 0
970         if( p_sys->preprocess )
971             speex_preprocess( p_sys->preprocess, p_samples, NULL );
972 #endif
973
974         speex_encode_int( p_sys->p_state, p_samples, &p_sys->bits );
975
976         p_buffer += p_sys->i_frame_size;
977         p_sys->i_samples_delay -= p_sys->i_frame_length;
978         i_samples -= p_sys->i_frame_length;
979
980         p_sys->i_frames_in_packet++;
981
982         if( p_sys->i_frames_in_packet < p_sys->header.frames_per_packet )
983             continue;
984
985         p_sys->i_frames_in_packet = 0;
986
987         speex_bits_insert_terminator( &p_sys->bits );
988         i_out = speex_bits_write( &p_sys->bits, p_sys->p_buffer_out,
989                                   MAX_FRAME_BYTES );
990         speex_bits_reset( &p_sys->bits );
991
992         p_block = block_New( p_enc, i_out );
993         memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );
994
995         p_block->i_length = (mtime_t)1000000 *
996             (mtime_t)p_sys->i_frame_length * p_sys->header.frames_per_packet /
997             (mtime_t)p_enc->fmt_in.audio.i_rate;
998
999         p_block->i_dts = p_block->i_pts = p_sys->i_pts;
1000
1001         /* Update pts */
1002         p_sys->i_pts += p_block->i_length;
1003         block_ChainAppend( &p_chain, p_block );
1004
1005     }
1006
1007     /* Backup the remaining raw samples */
1008     if( i_samples )
1009     {
1010         memcpy( p_sys->p_buffer + i_samples_delay * 2 *
1011                 p_enc->fmt_in.audio.i_channels, p_buffer,
1012                 i_samples * 2 * p_enc->fmt_in.audio.i_channels );
1013     }
1014
1015     return p_chain;
1016 }
1017
1018 /*****************************************************************************
1019  * CloseEncoder: encoder destruction
1020  *****************************************************************************/
1021 static void CloseEncoder( vlc_object_t *p_this )
1022 {
1023     encoder_t *p_enc = (encoder_t *)p_this;
1024     encoder_sys_t *p_sys = p_enc->p_sys;
1025
1026     speex_encoder_destroy( p_sys->p_state );
1027     speex_bits_destroy( &p_sys->bits );
1028
1029     free( p_sys->p_buffer );
1030     free( p_sys );
1031 }