12c6bd1893365521caa413d26d6d0cc6d365c9f7
[vlc.git] / modules / codec / araw.c
1 /*****************************************************************************
2  * araw.c: Pseudo audio decoder; for raw pcm data
3  *****************************************************************************
4  * Copyright (C) 2001, 2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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
30 /*****************************************************************************
31  * Module descriptor
32  *****************************************************************************/
33 static int  DecoderOpen ( vlc_object_t * );
34 static void DecoderClose( vlc_object_t * );
35
36 static int  EncoderOpen ( vlc_object_t * );
37 static void EncoderClose( vlc_object_t * );
38
39 vlc_module_begin();
40     /* audio decoder module */
41     set_description( _("Raw/Log Audio decoder") );
42     set_capability( "decoder", 100 );
43     set_callbacks( DecoderOpen, DecoderClose );
44
45     /* audio encoder submodule */
46     add_submodule();
47     set_description( _("Raw audio encoder") );
48     set_capability( "encoder", 150 );
49     set_callbacks( EncoderOpen, EncoderClose );
50 vlc_module_end();
51
52 /*****************************************************************************
53  * Local prototypes
54  *****************************************************************************/
55 static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
56 static block_t *EncoderEncode( encoder_t *, aout_buffer_t * );
57
58 struct decoder_sys_t
59 {
60     int16_t *p_logtos16;  /* used with m/alaw to int16_t */
61
62     audio_date_t end_date;
63 };
64
65 static int pi_channels_maps[9] =
66 {
67     0,
68     AOUT_CHAN_CENTER,
69     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
70     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER,
71     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
72      | AOUT_CHAN_REARRIGHT,
73     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
74      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
75     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
76      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
77     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
78      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
79      | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
80     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
81      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
82      | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE
83 };
84
85 static int16_t ulawtos16[256] =
86 {
87     -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
88     -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
89     -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
90     -11900, -11388, -10876, -10364,  -9852,  -9340,  -8828,  -8316,
91      -7932,  -7676,  -7420,  -7164,  -6908,  -6652,  -6396,  -6140,
92      -5884,  -5628,  -5372,  -5116,  -4860,  -4604,  -4348,  -4092,
93      -3900,  -3772,  -3644,  -3516,  -3388,  -3260,  -3132,  -3004,
94      -2876,  -2748,  -2620,  -2492,  -2364,  -2236,  -2108,  -1980,
95      -1884,  -1820,  -1756,  -1692,  -1628,  -1564,  -1500,  -1436,
96      -1372,  -1308,  -1244,  -1180,  -1116,  -1052,   -988,   -924,
97       -876,   -844,   -812,   -780,   -748,   -716,   -684,   -652,
98       -620,   -588,   -556,   -524,   -492,   -460,   -428,   -396,
99       -372,   -356,   -340,   -324,   -308,   -292,   -276,   -260,
100       -244,   -228,   -212,   -196,   -180,   -164,   -148,   -132,
101       -120,   -112,   -104,    -96,    -88,    -80,    -72,    -64,
102        -56,    -48,    -40,    -32,    -24,    -16,     -8,      0,
103      32124,  31100,  30076,  29052,  28028,  27004,  25980,  24956,
104      23932,  22908,  21884,  20860,  19836,  18812,  17788,  16764,
105      15996,  15484,  14972,  14460,  13948,  13436,  12924,  12412,
106      11900,  11388,  10876,  10364,   9852,   9340,   8828,   8316,
107       7932,   7676,   7420,   7164,   6908,   6652,   6396,   6140,
108       5884,   5628,   5372,   5116,   4860,   4604,   4348,   4092,
109       3900,   3772,   3644,   3516,   3388,   3260,   3132,   3004,
110       2876,   2748,   2620,   2492,   2364,   2236,   2108,   1980,
111       1884,   1820,   1756,   1692,   1628,   1564,   1500,   1436,
112       1372,   1308,   1244,   1180,   1116,   1052,    988,    924,
113        876,    844,    812,    780,    748,    716,    684,    652,
114        620,    588,    556,    524,    492,    460,    428,    396,
115        372,    356,    340,    324,    308,    292,    276,    260,
116        244,    228,    212,    196,    180,    164,    148,    132,
117        120,    112,    104,     96,     88,     80,     72,     64,
118         56,     48,     40,     32,     24,     16,      8,      0
119 };
120
121 static int16_t alawtos16[256] =
122 {
123      -5504,  -5248,  -6016,  -5760,  -4480,  -4224,  -4992,  -4736,
124      -7552,  -7296,  -8064,  -7808,  -6528,  -6272,  -7040,  -6784,
125      -2752,  -2624,  -3008,  -2880,  -2240,  -2112,  -2496,  -2368,
126      -3776,  -3648,  -4032,  -3904,  -3264,  -3136,  -3520,  -3392,
127     -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
128     -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
129     -11008, -10496, -12032, -11520,  -8960,  -8448,  -9984,  -9472,
130     -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
131       -344,   -328,   -376,   -360,   -280,   -264,   -312,   -296,
132       -472,   -456,   -504,   -488,   -408,   -392,   -440,   -424,
133        -88,    -72,   -120,   -104,    -24,     -8,    -56,    -40,
134       -216,   -200,   -248,   -232,   -152,   -136,   -184,   -168,
135      -1376,  -1312,  -1504,  -1440,  -1120,  -1056,  -1248,  -1184,
136      -1888,  -1824,  -2016,  -1952,  -1632,  -1568,  -1760,  -1696,
137       -688,   -656,   -752,   -720,   -560,   -528,   -624,   -592,
138       -944,   -912,  -1008,   -976,   -816,   -784,   -880,   -848,
139       5504,   5248,   6016,   5760,   4480,   4224,   4992,   4736,
140       7552,   7296,   8064,   7808,   6528,   6272,   7040,   6784,
141       2752,   2624,   3008,   2880,   2240,   2112,   2496,   2368,
142       3776,   3648,   4032,   3904,   3264,   3136,   3520,   3392,
143      22016,  20992,  24064,  23040,  17920,  16896,  19968,  18944,
144      30208,  29184,  32256,  31232,  26112,  25088,  28160,  27136,
145      11008,  10496,  12032,  11520,   8960,   8448,   9984,   9472,
146      15104,  14592,  16128,  15616,  13056,  12544,  14080,  13568,
147        344,    328,    376,    360,    280,    264,    312,    296,
148        472,    456,    504,    488,    408,    392,    440,    424,
149         88,     72,    120,    104,     24,      8,     56,     40,
150        216,    200,    248,    232,    152,    136,    184,    168,
151       1376,   1312,   1504,   1440,   1120,   1056,   1248,   1184,
152       1888,   1824,   2016,   1952,   1632,   1568,   1760,   1696,
153        688,    656,    752,    720,    560,    528,    624,    592,
154        944,    912,   1008,    976,    816,    784,    880,    848
155 };
156
157 /*****************************************************************************
158  * DecoderOpen: probe the decoder and return score
159  *****************************************************************************/
160 static int DecoderOpen( vlc_object_t *p_this )
161 {
162     decoder_t *p_dec = (decoder_t*)p_this;
163     decoder_sys_t *p_sys;
164
165     switch( p_dec->fmt_in.i_codec )
166     {
167     /* from wav/avi/asf file */
168     case VLC_FOURCC('a','r','a','w'):
169     case VLC_FOURCC('a','f','l','t'):
170     /* _signed_ big endian samples (mov)*/
171     case VLC_FOURCC('t','w','o','s'):
172     /* _signed_ little endian samples (mov)*/
173     case VLC_FOURCC('s','o','w','t'):
174
175     case VLC_FOURCC('a','l','a','w'):
176     case VLC_FOURCC('u','l','a','w'):
177     case VLC_FOURCC('m','l','a','w'):
178
179     case VLC_FOURCC('f','l','6','4'):
180     case VLC_FOURCC('f','l','3','2'):
181     case VLC_FOURCC('s','3','2','l'):
182     case VLC_FOURCC('s','3','2','b'):
183     case VLC_FOURCC('s','2','4','l'):
184     case VLC_FOURCC('s','2','4','b'):
185     case VLC_FOURCC('s','1','6','l'):
186     case VLC_FOURCC('s','1','6','b'):
187     case VLC_FOURCC('s','8',' ',' '):
188     case VLC_FOURCC('u','8',' ',' '):
189         break;
190
191     default:
192         return VLC_EGENERIC;
193     }
194
195     if( p_dec->fmt_in.audio.i_channels <= 0 ||
196         p_dec->fmt_in.audio.i_channels > 8 )
197     {
198         msg_Err( p_dec, "bad channels count (1-8)" );
199         return VLC_EGENERIC;
200     }
201
202     if( p_dec->fmt_in.audio.i_rate <= 0 )
203     {
204         msg_Err( p_dec, "bad samplerate" );
205         return VLC_EGENERIC;
206     }
207
208     /* Allocate the memory needed to store the decoder's structure */
209     if( ( p_dec->p_sys = p_sys =
210           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
211     {
212         msg_Err( p_dec, "out of memory" );
213         return VLC_EGENERIC;
214     }
215
216     p_sys->p_logtos16 = NULL;
217
218     msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d",
219              p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
220              p_dec->fmt_in.audio.i_bitspersample );
221
222     if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'f', 'l', '6', '4' ) )
223     {
224         p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
225         p_dec->fmt_in.audio.i_bitspersample = 64;
226     }
227     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'f', 'l', '3', '2' ) )
228     {
229         p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
230         p_dec->fmt_in.audio.i_bitspersample = 32;
231     }
232     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', '3', '2', 'l' ) ||
233              p_dec->fmt_in.i_codec == VLC_FOURCC( 's', '3', '2', 'b' ) )
234     {
235         p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
236         p_dec->fmt_in.audio.i_bitspersample = 32;
237     }
238     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', '2', '4', 'l' ) ||
239              p_dec->fmt_in.i_codec == VLC_FOURCC( 's', '2', '4', 'b' ) )
240     {
241         p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
242         p_dec->fmt_in.audio.i_bitspersample = 24;
243     }
244     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', '1', '6', 'l' ) ||
245              p_dec->fmt_in.i_codec == VLC_FOURCC( 's', '1', '6', 'b' ) )
246     {
247         p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
248         p_dec->fmt_in.audio.i_bitspersample = 16;
249     }
250     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', '8', ' ', ' ' ) ||
251              p_dec->fmt_in.i_codec == VLC_FOURCC( 'u', '8', ' ', ' ' ) )
252     {
253         p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
254         p_dec->fmt_in.audio.i_bitspersample = 8;
255     }
256     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'f', 'l', 't' ) )
257     {
258         switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
259         {
260         case 4:
261             p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
262             break;
263         case 8:
264             p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','6','4');
265             break;
266         default:
267             msg_Err( p_dec, "bad parameters(bits/sample)" );
268             return VLC_EGENERIC;
269         }
270     }
271     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
272     {
273         switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
274         {
275         case 1:
276             p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' ');
277             break;
278         case 2:
279             p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
280             break;
281         case 3:
282             p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
283             break;
284         case 4:
285             p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
286             break;
287         default:
288             msg_Err( p_dec, "bad parameters(bits/sample)" );
289             return VLC_EGENERIC;
290         }
291     }
292     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 't', 'w', 'o', 's' ) )
293     {
294         switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
295         {
296         case 1:
297             p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
298             break;
299         case 2:
300             p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
301             break;
302         case 3:
303             p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
304             break;
305         case 4:
306             p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b');
307             break;
308         default:
309             msg_Err( p_dec, "bad parameters(bits/sample)" );
310             return VLC_EGENERIC;
311         }
312     }
313     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'o', 'w', 't' ) )
314     {
315         switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
316         {
317         case 1:
318             p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
319             break;
320         case 2:
321             p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
322             break;
323         case 3:
324             p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
325             break;
326         case 4:
327             p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
328             break;
329         default:
330             msg_Err( p_dec, "bad parameters(bits/sample)" );
331             return VLC_EGENERIC;
332         }
333     }
334     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'l', 'a', 'w' ) )
335     {
336         p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
337         p_sys->p_logtos16  = alawtos16;
338         p_dec->fmt_in.audio.i_bitspersample = 8;
339     }
340     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'u', 'l', 'a', 'w' ) ||
341              p_dec->fmt_in.i_codec == VLC_FOURCC( 'm', 'l', 'a', 'w' ) )
342     {
343         p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
344         p_sys->p_logtos16  = ulawtos16;
345         p_dec->fmt_in.audio.i_bitspersample = 8;
346     }
347
348     /* Set output properties */
349     p_dec->fmt_out.i_cat = AUDIO_ES;
350     p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
351     p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
352     p_dec->fmt_out.audio.i_bitspersample = p_dec->fmt_in.audio.i_bitspersample;
353     p_dec->fmt_out.audio.i_physical_channels =
354         p_dec->fmt_out.audio.i_original_channels =
355             pi_channels_maps[p_dec->fmt_in.audio.i_channels];
356     if( p_dec->fmt_in.audio.i_physical_channels )
357         p_dec->fmt_out.audio.i_physical_channels =
358             p_dec->fmt_in.audio.i_physical_channels;
359     if( p_dec->fmt_in.audio.i_original_channels )
360         p_dec->fmt_out.audio.i_original_channels =
361             p_dec->fmt_in.audio.i_original_channels;
362
363     if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'l', 'a', 'w' ) ||
364         p_dec->fmt_in.i_codec == VLC_FOURCC( 'u', 'l', 'a', 'w' ) ||
365         p_dec->fmt_in.i_codec == VLC_FOURCC( 'm', 'l', 'a', 'w' ) )
366     {
367         p_dec->fmt_out.audio.i_bitspersample = 16;
368     }
369
370     aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
371     aout_DateSet( &p_sys->end_date, 0 );
372
373     p_dec->pf_decode_audio = DecodeBlock;
374
375     return VLC_SUCCESS;
376 }
377
378 /****************************************************************************
379  * DecodeBlock: the whole thing
380  ****************************************************************************
381  * This function must be fed with whole samples (see nBlockAlign).
382  ****************************************************************************/
383 static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
384 {
385     decoder_sys_t *p_sys = p_dec->p_sys;
386     block_t *p_block;
387     aout_buffer_t *p_out;
388     int i_samples;
389
390     if( !pp_block || !*pp_block ) return NULL;
391
392     p_block = *pp_block;
393
394     if( p_block->i_pts != 0 &&
395         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
396     {
397         aout_DateSet( &p_sys->end_date, p_block->i_pts );
398     }
399     else if( !aout_DateGet( &p_sys->end_date ) )
400     {
401         /* We've just started the stream, wait for the first PTS. */
402         block_Release( p_block );
403         return NULL;
404     }
405
406     /* Don't re-use the same pts twice */
407     p_block->i_pts = 0;
408
409     i_samples = p_block->i_buffer * 8 / p_dec->fmt_in.audio.i_bitspersample /
410         p_dec->fmt_in.audio.i_channels;
411
412     if( i_samples <= 0 )
413     {
414         block_Release( p_block );
415         return NULL;
416     }
417
418     /* Create chunks of max 1024 samples */
419     i_samples = __MIN( i_samples, 1024 );
420
421     p_out = p_dec->pf_aout_buffer_new( p_dec, i_samples );
422     if( p_out == NULL )
423     {
424         block_Release( p_block );
425         return NULL;
426     }
427
428     p_out->start_date = aout_DateGet( &p_sys->end_date );
429     p_out->end_date   = aout_DateIncrement( &p_sys->end_date, i_samples );
430
431     if( p_sys->p_logtos16 )
432     {
433         int16_t *s = (int16_t*)p_out->p_buffer;
434         unsigned int i;
435
436         for( i = 0; i < p_out->i_nb_bytes / 2; i++ )
437         {
438             *s++ = p_sys->p_logtos16[*p_block->p_buffer++];
439             p_block->i_buffer--;
440         }
441     }
442     else
443     {
444         memcpy( p_out->p_buffer, p_block->p_buffer, p_out->i_nb_bytes );
445         p_block->p_buffer += p_out->i_nb_bytes;
446         p_block->i_buffer -= p_out->i_nb_bytes;
447     }
448
449     return p_out;
450 }
451
452 /*****************************************************************************
453  * DecoderClose: decoder destruction
454  *****************************************************************************/
455 static void DecoderClose( vlc_object_t *p_this )
456 {
457     decoder_t *p_dec = (decoder_t *)p_this;
458
459     free( p_dec->p_sys );
460 }
461
462 /*****************************************************************************
463  * EncoderOpen:
464  *****************************************************************************/
465 static int EncoderOpen( vlc_object_t *p_this )
466 {
467     encoder_t *p_enc = (encoder_t *)p_this;
468
469     if( p_enc->fmt_out.i_codec == VLC_FOURCC('u','8',' ',' ') ||
470         p_enc->fmt_out.i_codec == VLC_FOURCC('s','8',' ',' ') )
471     {
472         p_enc->fmt_out.audio.i_bitspersample = 8;
473     }
474     else if( p_enc->fmt_out.i_codec == VLC_FOURCC('u','1','6','l') ||
475              p_enc->fmt_out.i_codec == VLC_FOURCC('u','1','6','b') ||
476              p_enc->fmt_out.i_codec == VLC_FOURCC('s','1','6','l') ||
477              p_enc->fmt_out.i_codec == VLC_FOURCC('s','1','6','b') )
478     {
479         p_enc->fmt_out.audio.i_bitspersample = 16;
480     }
481     else if( p_enc->fmt_out.i_codec == VLC_FOURCC('u','2','4','l') ||
482              p_enc->fmt_out.i_codec == VLC_FOURCC('u','2','4','b') ||
483              p_enc->fmt_out.i_codec == VLC_FOURCC('s','2','4','l') ||
484              p_enc->fmt_out.i_codec == VLC_FOURCC('s','2','4','b') )
485     {
486         p_enc->fmt_out.audio.i_bitspersample = 24;
487     }
488     else if( p_enc->fmt_out.i_codec == VLC_FOURCC('u','3','2','l') ||
489              p_enc->fmt_out.i_codec == VLC_FOURCC('u','3','2','b') ||
490              p_enc->fmt_out.i_codec == VLC_FOURCC('s','3','2','l') ||
491              p_enc->fmt_out.i_codec == VLC_FOURCC('s','3','2','b') ||
492              p_enc->fmt_out.i_codec == VLC_FOURCC('f','i','3','2') ||
493              p_enc->fmt_out.i_codec == VLC_FOURCC('f','l','3','2') )
494     {
495         p_enc->fmt_out.audio.i_bitspersample = 32;
496     }
497     else if( p_enc->fmt_out.i_codec == VLC_FOURCC('f','l','6','4') )
498     {
499         p_enc->fmt_out.audio.i_bitspersample = 64;
500     }
501     else
502     {
503         return VLC_EGENERIC;
504     }
505
506     p_enc->p_sys = NULL;
507     p_enc->pf_encode_audio = EncoderEncode;
508     p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec;
509
510     return VLC_SUCCESS;
511 }
512
513 /*****************************************************************************
514  * EncoderClose:
515  *****************************************************************************/
516 static void EncoderClose ( vlc_object_t *p_this )
517 {
518     return;
519 }
520
521 /*****************************************************************************
522  * EncoderEncode:
523  *****************************************************************************/
524 static block_t *EncoderEncode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
525 {
526     block_t *p_block = NULL;
527
528     if( !p_aout_buf || !p_aout_buf->i_nb_bytes ) return NULL;
529
530     if( ( p_block = block_New( p_enc, p_aout_buf->i_nb_bytes ) ) )
531     {
532         memcpy( p_block->p_buffer, p_aout_buf->p_buffer,
533                 p_aout_buf->i_nb_bytes );
534     }
535
536     if( p_block )
537     {
538         p_block->i_dts = p_block->i_pts = p_aout_buf->start_date;
539         p_block->i_length = (int64_t)p_aout_buf->i_nb_samples *
540             (int64_t)1000000 / p_enc->fmt_in.audio.i_rate;
541     }
542
543     return p_block;
544 }