]> git.sesse.net Git - vlc/blob - modules/codec/flac.c
mediacodec: fix warning
[vlc] / modules / codec / flac.c
1 /*****************************************************************************
2  * flac.c: flac decoder/encoder module making use of libflac
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *          Sigmund Augdal Helberg <dnumgis@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 /* workaround libflac overriding assert.h system header */
30 #define assert(x) do {} while(0)
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38 #include <vlc_codec.h>
39
40 #ifdef _WIN32
41 # define FLAC__NO_DLL
42 #endif
43
44 #include <FLAC/stream_decoder.h>
45 #include <FLAC/stream_encoder.h>
46
47 #include <vlc_block_helper.h>
48 #include <vlc_bits.h>
49
50 #if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 8
51 #   define USE_NEW_FLAC_API
52 #endif
53
54 /*****************************************************************************
55  * decoder_sys_t : FLAC decoder descriptor
56  *****************************************************************************/
57 struct decoder_sys_t
58 {
59     /*
60      * Input/Output properties
61      */
62     block_t *p_block;
63     block_t *p_aout_buffer;
64     date_t   end_date;
65
66     /*
67      * FLAC properties
68      */
69     FLAC__StreamDecoder *p_flac;
70     FLAC__StreamMetadata_StreamInfo stream_info;
71     bool b_stream_info;
72 };
73
74 static const int pi_channels_maps[9] =
75 {
76     0,
77     AOUT_CHAN_CENTER,
78     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     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
85      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
86     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
87      | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT| AOUT_CHAN_MIDDLERIGHT
88      | AOUT_CHAN_LFE,
89     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
90      | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
91      | AOUT_CHAN_LFE
92 };
93
94 /*****************************************************************************
95  * Local prototypes
96  *****************************************************************************/
97 static int  OpenDecoder   ( vlc_object_t * );
98 static void CloseDecoder  ( vlc_object_t * );
99
100 #ifdef ENABLE_SOUT
101 static int OpenEncoder   ( vlc_object_t * );
102 static void CloseEncoder ( vlc_object_t * );
103 #endif
104
105 static block_t *DecodeBlock( decoder_t *, block_t ** );
106
107 /*****************************************************************************
108  * Module descriptor
109  *****************************************************************************/
110 vlc_module_begin ()
111
112     set_category( CAT_INPUT )
113     set_subcategory( SUBCAT_INPUT_ACODEC )
114     add_shortcut( "flac" )
115
116     set_description( N_("Flac audio decoder") )
117     set_capability( "decoder", 100 )
118     set_callbacks( OpenDecoder, CloseDecoder )
119
120 #ifdef ENABLE_SOUT
121     add_submodule ()
122     add_shortcut( "flac" )
123     set_description( N_("Flac audio encoder") )
124     set_capability( "encoder", 100 )
125     set_callbacks( OpenEncoder, CloseEncoder )
126 #endif
127
128 vlc_module_end ()
129
130 /*****************************************************************************
131  * Interleave: helper function to interleave channels
132  *****************************************************************************/
133 static void Interleave( int32_t *p_out, const int32_t * const *pp_in,
134                         const unsigned char *restrict pi_index, unsigned i_nb_channels,
135                         unsigned i_samples, unsigned bits )
136 {
137     unsigned shift = 32 - bits;
138
139     for( unsigned j = 0; j < i_samples; j++ )
140         for( unsigned i = 0; i < i_nb_channels; i++ )
141         {
142             union { int32_t i; uint32_t u; } spl;
143
144             spl.u = ((uint32_t)pp_in[pi_index[i]][j]) << shift;
145             p_out[j * i_nb_channels + i] = spl.i;
146         }
147 }
148
149 /*****************************************************************************
150  * DecoderWriteCallback: called by libflac to output decoded samples
151  *****************************************************************************/
152 static FLAC__StreamDecoderWriteStatus
153 DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
154                       const FLAC__Frame *frame,
155                       const FLAC__int32 *const buffer[], void *client_data )
156 {
157     /* XXX it supposes our internal format is WG4 */
158     static const unsigned char ppi_reorder[1+8][8] = {
159         { },
160         { 0, },
161         { 0, 1 },
162         { 0, 1, 2 },
163         { 0, 1, 2, 3 },
164         { 0, 1, 3, 4, 2 },
165         { 0, 1, 4, 5, 2, 3 },
166         { 0, 1, 5, 6, 4, 2, 3 },
167         { 0, 1, 6, 7, 4, 5, 2, 3 },
168     };
169
170     VLC_UNUSED(decoder);
171     decoder_t *p_dec = (decoder_t *)client_data;
172     decoder_sys_t *p_sys = p_dec->p_sys;
173
174     if( p_dec->fmt_out.audio.i_channels <= 0 ||
175         p_dec->fmt_out.audio.i_channels > 8 )
176         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
177     if( date_Get( &p_sys->end_date ) <= VLC_TS_INVALID )
178         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
179
180     const unsigned char *pi_reorder = ppi_reorder[p_dec->fmt_out.audio.i_channels];
181
182     p_sys->p_aout_buffer =
183         decoder_NewAudioBuffer( p_dec, frame->header.blocksize );
184
185     if( p_sys->p_aout_buffer == NULL )
186         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
187
188     Interleave( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
189                  frame->header.channels, frame->header.blocksize,
190                  frame->header.bits_per_sample );
191
192     /* Date management (already done by packetizer) */
193     p_sys->p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
194     p_sys->p_aout_buffer->i_length =
195         date_Increment( &p_sys->end_date, frame->header.blocksize ) -
196         p_sys->p_aout_buffer->i_pts;
197
198     return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
199 }
200
201 /*****************************************************************************
202  * DecoderReadCallback: called by libflac when it needs more data
203  *****************************************************************************/
204 static FLAC__StreamDecoderReadStatus
205 DecoderReadCallback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],
206                      size_t *bytes, void *client_data )
207 {
208     VLC_UNUSED(decoder);
209     decoder_t *p_dec = (decoder_t *)client_data;
210     decoder_sys_t *p_sys = p_dec->p_sys;
211
212     if( p_sys->p_block && p_sys->p_block->i_buffer )
213     {
214         *bytes = __MIN(*bytes, p_sys->p_block->i_buffer);
215         memcpy( buffer, p_sys->p_block->p_buffer, *bytes );
216         p_sys->p_block->i_buffer -= *bytes;
217         p_sys->p_block->p_buffer += *bytes;
218     }
219     else
220     {
221         *bytes = 0;
222         return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
223     }
224
225     return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
226 }
227
228 /*****************************************************************************
229  * DecoderMetadataCallback: called by libflac to when it encounters metadata
230  *****************************************************************************/
231 static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
232                                      const FLAC__StreamMetadata *metadata,
233                                      void *client_data )
234 {
235     VLC_UNUSED(decoder);
236     decoder_t *p_dec = (decoder_t *)client_data;
237     decoder_sys_t *p_sys = p_dec->p_sys;
238
239     /* Setup the format */
240     p_dec->fmt_out.audio.i_rate     = metadata->data.stream_info.sample_rate;
241     p_dec->fmt_out.audio.i_channels = metadata->data.stream_info.channels;
242     p_dec->fmt_out.audio.i_physical_channels =
243         p_dec->fmt_out.audio.i_original_channels =
244             pi_channels_maps[metadata->data.stream_info.channels];
245     if (!p_dec->fmt_out.audio.i_bitspersample)
246         p_dec->fmt_out.audio.i_bitspersample =
247             metadata->data.stream_info.bits_per_sample;
248
249     msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
250              p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
251              p_dec->fmt_out.audio.i_bitspersample );
252
253     p_sys->b_stream_info = true;
254     p_sys->stream_info = metadata->data.stream_info;
255
256     date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
257     date_Set( &p_sys->end_date, VLC_TS_INVALID );
258 }
259
260 /*****************************************************************************
261  * DecoderErrorCallback: called when the libflac decoder encounters an error
262  *****************************************************************************/
263 static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,
264                                   FLAC__StreamDecoderErrorStatus status,
265                                   void *client_data )
266 {
267     VLC_UNUSED(decoder);
268     decoder_t *p_dec = (decoder_t *)client_data;
269
270     switch( status )
271     {
272     case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
273         msg_Warn( p_dec, "an error in the stream caused the decoder to "
274                  "lose synchronization." );
275         break;
276     case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
277         msg_Err( p_dec, "the decoder encountered a corrupted frame header." );
278         break;
279     case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
280         msg_Err( p_dec, "frame's data did not match the CRC in the "
281                  "footer." );
282         break;
283     case FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM:
284         msg_Err( p_dec, "The decoder encountered reserved fields in use in "
285                  "the stream." );
286         break;
287     default:
288         msg_Err( p_dec, "got decoder error: %d", status );
289     }
290
291     FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
292     return;
293 }
294 /*****************************************************************************
295  * OpenDecoder: probe the decoder and return score
296  *****************************************************************************/
297 static int OpenDecoder( vlc_object_t *p_this )
298 {
299     decoder_t *p_dec = (decoder_t*)p_this;
300     decoder_sys_t *p_sys;
301
302     if( p_dec->fmt_in.i_codec != VLC_CODEC_FLAC )
303     {
304         return VLC_EGENERIC;
305     }
306
307     /* Allocate the memory needed to store the decoder's structure */
308     if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
309         return VLC_ENOMEM;
310
311     /* Misc init */
312     p_sys->b_stream_info = false;
313     p_sys->p_block = NULL;
314
315     /* Take care of flac init */
316     if( !(p_sys->p_flac = FLAC__stream_decoder_new()) )
317     {
318         msg_Err( p_dec, "FLAC__stream_decoder_new() failed" );
319         free( p_sys );
320         return VLC_EGENERIC;
321     }
322
323 #ifdef USE_NEW_FLAC_API
324     if( FLAC__stream_decoder_init_stream( p_sys->p_flac,
325                                           DecoderReadCallback,
326                                           NULL,
327                                           NULL,
328                                           NULL,
329                                           NULL,
330                                           DecoderWriteCallback,
331                                           DecoderMetadataCallback,
332                                           DecoderErrorCallback,
333                                           p_dec )
334         != FLAC__STREAM_DECODER_INIT_STATUS_OK )
335     {
336         msg_Err( p_dec, "FLAC__stream_decoder_init_stream() failed" );
337         FLAC__stream_decoder_delete( p_sys->p_flac );
338         free( p_sys );
339         return VLC_EGENERIC;
340     }
341 #else
342     FLAC__stream_decoder_set_read_callback( p_sys->p_flac,
343                                             DecoderReadCallback );
344     FLAC__stream_decoder_set_write_callback( p_sys->p_flac,
345                                              DecoderWriteCallback );
346     FLAC__stream_decoder_set_metadata_callback( p_sys->p_flac,
347                                                 DecoderMetadataCallback );
348     FLAC__stream_decoder_set_error_callback( p_sys->p_flac,
349                                              DecoderErrorCallback );
350     FLAC__stream_decoder_set_client_data( p_sys->p_flac, p_dec );
351
352     FLAC__stream_decoder_init( p_sys->p_flac );
353 #endif
354
355     /* Set output properties */
356     p_dec->fmt_out.i_cat = AUDIO_ES;
357     p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
358
359     /* Set callbacks */
360     p_dec->pf_decode_audio = DecodeBlock;
361
362     /* */
363     p_dec->b_need_packetized = true;
364
365     return VLC_SUCCESS;
366 }
367
368 /*****************************************************************************
369  * CloseDecoder: flac decoder destruction
370  *****************************************************************************/
371 static void CloseDecoder( vlc_object_t *p_this )
372 {
373     decoder_t *p_dec = (decoder_t *)p_this;
374     decoder_sys_t *p_sys = p_dec->p_sys;
375
376     FLAC__stream_decoder_finish( p_sys->p_flac );
377     FLAC__stream_decoder_delete( p_sys->p_flac );
378
379     if( p_sys->p_block )
380         block_Release( p_sys->p_block );
381     free( p_sys );
382 }
383
384 /*****************************************************************************
385  * ProcessHeader: process Flac header.
386  *****************************************************************************/
387 static void ProcessHeader( decoder_t *p_dec )
388 {
389     decoder_sys_t *p_sys = p_dec->p_sys;
390
391     if( !p_dec->fmt_in.i_extra )
392         return;
393
394     /* Decode STREAMINFO */
395     msg_Dbg( p_dec, "decode STREAMINFO" );
396     size_t i_extra = p_dec->fmt_in.i_extra;
397     static const char header[4] = { 'f', 'L', 'a', 'C' };
398
399     if (i_extra > 42 && !memcmp(p_dec->fmt_in.p_extra, header, 4))
400         i_extra = 42;
401     else if (i_extra > 34 && memcmp(p_dec->fmt_in.p_extra, header, 4))
402         i_extra = 34;
403
404     switch (i_extra) {
405     case 34:
406         p_sys->p_block = block_Alloc( 8 + i_extra );
407         if( p_sys->p_block == NULL ) return;
408         memcpy( p_sys->p_block->p_buffer + 8, p_dec->fmt_in.p_extra, i_extra );
409         memcpy( p_sys->p_block->p_buffer, header, 4);
410         uint8_t *p = p_sys->p_block->p_buffer;
411         p[4] = 0x80 | 0; /* STREAMINFO faked as last block */
412         p[5] = 0;
413         p[6] = 0;
414         p[7] = 34; /* block size */
415         break;
416     case 42:
417         p_sys->p_block = block_Alloc( i_extra );
418         if( p_sys->p_block == NULL ) return;
419         memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra, i_extra );
420         break;
421     default:
422         msg_Err(p_dec, "Invalid flac header size %zu", i_extra);
423         return;
424     }
425     FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
426     msg_Dbg( p_dec, "STREAMINFO decoded" );
427
428     block_Release( p_sys->p_block );
429     p_sys->p_block = NULL;
430 }
431
432 /*****************************************************************************
433  * decoder_state_error: print meaningful error messages
434  *****************************************************************************/
435 static void decoder_state_error( decoder_t *p_dec,
436                                  FLAC__StreamDecoderState state )
437 {
438     switch ( state )
439     {
440     case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
441         msg_Dbg( p_dec, "the decoder is ready to search for metadata." );
442         break;
443     case FLAC__STREAM_DECODER_READ_METADATA:
444         msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
445                  "reading metadata." );
446         break;
447     case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
448         msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
449                  "searching for the frame sync code." );
450         break;
451     case FLAC__STREAM_DECODER_READ_FRAME:
452         msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
453                  "reading a frame." );
454         break;
455     case FLAC__STREAM_DECODER_END_OF_STREAM:
456         msg_Dbg( p_dec, "the decoder has reached the end of the stream." );
457         break;
458 #ifdef USE_NEW_FLAC_API
459     case FLAC__STREAM_DECODER_OGG_ERROR:
460         msg_Err( p_dec, "error occurred in the Ogg layer." );
461         break;
462     case FLAC__STREAM_DECODER_SEEK_ERROR:
463         msg_Err( p_dec, "error occurred while seeking." );
464         break;
465 #endif
466     case FLAC__STREAM_DECODER_ABORTED:
467         msg_Warn( p_dec, "the decoder was aborted by the read callback." );
468         break;
469 #ifndef USE_NEW_FLAC_API
470     case FLAC__STREAM_DECODER_UNPARSEABLE_STREAM:
471         msg_Warn( p_dec, "the decoder encountered reserved fields in use "
472                  "in the stream." );
473         break;
474 #endif
475     case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
476         msg_Err( p_dec, "error when allocating memory." );
477         break;
478 #ifndef USE_NEW_FLAC_API
479     case FLAC__STREAM_DECODER_ALREADY_INITIALIZED:
480         msg_Err( p_dec, "FLAC__stream_decoder_init() was called when the "
481                  "decoder was already initialized, usually because "
482                  "FLAC__stream_decoder_finish() was not called." );
483         break;
484     case FLAC__STREAM_DECODER_INVALID_CALLBACK:
485         msg_Err( p_dec, "FLAC__stream_decoder_init() was called without "
486                  "all callbacks being set." );
487         break;
488 #endif
489     case FLAC__STREAM_DECODER_UNINITIALIZED:
490         msg_Err( p_dec, "decoder in uninitialized state." );
491         break;
492     default:
493         msg_Warn(p_dec, "unknown error" );
494     }
495 }
496
497 /****************************************************************************
498  * DecodeBlock: the whole thing
499  ****************************************************************************/
500 static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
501 {
502     decoder_sys_t *p_sys = p_dec->p_sys;
503
504     if( !pp_block || !*pp_block )
505         return NULL;
506     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
507     {
508         block_Release( *pp_block );
509         return NULL;
510     }
511
512     if( !p_sys->b_stream_info )
513         ProcessHeader( p_dec );
514
515     p_sys->p_block = *pp_block;
516     *pp_block = NULL;
517
518     if( p_sys->p_block->i_pts > VLC_TS_INVALID &&
519         p_sys->p_block->i_pts != date_Get( &p_sys->end_date ) )
520         date_Set( &p_sys->end_date, p_sys->p_block->i_pts );
521
522     p_sys->p_aout_buffer = 0;
523
524     if( !FLAC__stream_decoder_process_single( p_sys->p_flac ) )
525     {
526         decoder_state_error( p_dec,
527                              FLAC__stream_decoder_get_state( p_sys->p_flac ) );
528         FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
529     }
530
531     /* If the decoder is in the "aborted" state,
532      * FLAC__stream_decoder_process_single() won't return an error. */
533     switch ( FLAC__stream_decoder_get_state(p_dec->p_sys->p_flac) )
534     {
535         case FLAC__STREAM_DECODER_ABORTED:
536             FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
537             break;
538         case FLAC__STREAM_DECODER_END_OF_STREAM:
539             FLAC__stream_decoder_reset( p_dec->p_sys->p_flac );
540             break;
541         default:
542             break;
543     }
544
545     block_Release( p_sys->p_block );
546     p_sys->p_block = NULL;
547
548     return p_sys->p_aout_buffer;
549 }
550
551 #ifdef ENABLE_SOUT
552
553 /*****************************************************************************
554  * encoder_sys_t : flac encoder descriptor
555  *****************************************************************************/
556 struct encoder_sys_t
557 {
558     /*
559      * Input properties
560      */
561     int i_headers;
562
563     int i_samples_delay;
564
565     FLAC__int32 *p_buffer;
566     unsigned int i_buffer;
567
568     block_t *p_chain;
569
570     /*
571      * FLAC properties
572      */
573     FLAC__StreamEncoder *p_flac;
574     FLAC__StreamMetadata_StreamInfo stream_info;
575
576     /*
577      * Common properties
578      */
579     mtime_t i_pts;
580 };
581
582 #define STREAMINFO_SIZE 34
583
584 static block_t *Encode( encoder_t *, block_t * );
585
586 /*****************************************************************************
587  * EncoderWriteCallback: called by libflac to output encoded samples
588  *****************************************************************************/
589 static FLAC__StreamEncoderWriteStatus
590 EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
591                       const FLAC__byte buffer[],
592                       size_t bytes, unsigned samples,
593                       unsigned current_frame, void *client_data )
594 {
595     VLC_UNUSED(encoder); VLC_UNUSED(current_frame);
596     encoder_t *p_enc = (encoder_t *)client_data;
597     encoder_sys_t *p_sys = p_enc->p_sys;
598     block_t *p_block;
599
600     if( samples == 0 )
601     {
602         if( p_sys->i_headers == 1 )
603         {
604             msg_Dbg( p_enc, "Writing STREAMINFO: %zu", bytes );
605
606             /* Backup the STREAMINFO metadata block */
607             p_enc->fmt_out.i_extra = STREAMINFO_SIZE + 8;
608             p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE + 8);
609             memcpy(p_enc->fmt_out.p_extra, "fLaC", 4);
610             memcpy((uint8_t*)p_enc->fmt_out.p_extra + 4, buffer, STREAMINFO_SIZE );
611             /* Fake this as the last metadata block */
612             ((uint8_t*)p_enc->fmt_out.p_extra)[4] |= 0x80;
613         }
614         p_sys->i_headers++;
615         return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
616     }
617
618     p_block = block_Alloc( bytes );
619     memcpy( p_block->p_buffer, buffer, bytes );
620
621     p_block->i_dts = p_block->i_pts = p_sys->i_pts;
622
623     p_sys->i_samples_delay -= samples;
624
625     p_block->i_length = (mtime_t)1000000 *
626         (mtime_t)samples / (mtime_t)p_enc->fmt_in.audio.i_rate;
627
628     /* Update pts */
629     p_sys->i_pts += p_block->i_length;
630
631     block_ChainAppend( &p_sys->p_chain, p_block );
632
633     return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
634 }
635 /*****************************************************************************
636  * EncoderMetadataCallback: called by libflac to output metadata
637  *****************************************************************************/
638 static void EncoderMetadataCallback( const FLAC__StreamEncoder *encoder,
639                                      const FLAC__StreamMetadata *metadata,
640                                      void *client_data )
641 {
642     VLC_UNUSED(encoder);
643     encoder_t *p_enc = (encoder_t *)client_data;
644
645     msg_Err( p_enc, "MetadataCallback: %i", metadata->type );
646     return;
647 }
648
649 /*****************************************************************************
650  * OpenEncoder: probe the encoder and return score
651  *****************************************************************************/
652 static int OpenEncoder( vlc_object_t *p_this )
653 {
654     encoder_t *p_enc = (encoder_t *)p_this;
655     encoder_sys_t *p_sys;
656
657     if( p_enc->fmt_out.i_codec != VLC_CODEC_FLAC &&
658         !p_enc->b_force )
659     {
660         return VLC_EGENERIC;
661     }
662
663     /* Allocate the memory needed to store the decoder's structure */
664     if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
665         return VLC_ENOMEM;
666     p_enc->p_sys = p_sys;
667     p_enc->pf_encode_audio = Encode;
668     p_enc->fmt_out.i_codec = VLC_CODEC_FLAC;
669
670     p_sys->i_headers = 0;
671     p_sys->p_buffer = 0;
672     p_sys->i_buffer = 0;
673     p_sys->i_samples_delay = 0;
674
675     /* Create flac encoder */
676     if( !(p_sys->p_flac = FLAC__stream_encoder_new()) )
677     {
678         msg_Err( p_enc, "FLAC__stream_encoder_new() failed" );
679         free( p_sys );
680         return VLC_EGENERIC;
681     }
682
683     FLAC__stream_encoder_set_streamable_subset( p_sys->p_flac, 1 );
684     FLAC__stream_encoder_set_channels( p_sys->p_flac,
685                                        p_enc->fmt_in.audio.i_channels );
686     FLAC__stream_encoder_set_sample_rate( p_sys->p_flac,
687                                           p_enc->fmt_in.audio.i_rate );
688     FLAC__stream_encoder_set_bits_per_sample( p_sys->p_flac, 16 );
689     p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
690
691     /* Get and store the STREAMINFO metadata block as a p_extra */
692     p_sys->p_chain = 0;
693
694 #ifdef USE_NEW_FLAC_API
695     if( FLAC__stream_encoder_init_stream( p_sys->p_flac,
696                                           EncoderWriteCallback,
697                                           NULL,
698                                           NULL,
699                                           EncoderMetadataCallback,
700                                           p_enc )
701         != FLAC__STREAM_ENCODER_INIT_STATUS_OK )
702     {
703         msg_Err( p_enc, "FLAC__stream_encoder_init_stream() failed" );
704         FLAC__stream_encoder_delete( p_sys->p_flac );
705         free( p_sys );
706         return VLC_EGENERIC;
707     }
708 #else
709     FLAC__stream_encoder_set_write_callback( p_sys->p_flac,
710         EncoderWriteCallback );
711     FLAC__stream_encoder_set_metadata_callback( p_sys->p_flac,
712         EncoderMetadataCallback );
713     FLAC__stream_encoder_set_client_data( p_sys->p_flac, p_enc );
714
715     FLAC__stream_encoder_init( p_sys->p_flac );
716 #endif
717
718     return VLC_SUCCESS;
719 }
720
721 /****************************************************************************
722  * Encode: the whole thing
723  ****************************************************************************
724  * This function spits out ogg packets.
725  ****************************************************************************/
726 static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
727 {
728     encoder_sys_t *p_sys = p_enc->p_sys;
729     block_t *p_chain;
730     unsigned int i;
731
732     /* FIXME: p_aout_buf is NULL when it's time to flush*/
733     if( unlikely( !p_aout_buf ) ) return NULL;
734
735     p_sys->i_pts = p_aout_buf->i_pts -
736                 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
737                 (mtime_t)p_enc->fmt_in.audio.i_rate;
738
739     p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
740
741     /* Convert samples to FLAC__int32 */
742     if( p_sys->i_buffer < p_aout_buf->i_buffer * sizeof(FLAC__int32) )
743     {
744         p_sys->p_buffer =
745             xrealloc( p_sys->p_buffer, p_aout_buf->i_buffer * sizeof(FLAC__int32) );
746         p_sys->i_buffer = p_aout_buf->i_buffer * 2;
747     }
748
749     for( i = 0 ; i < p_aout_buf->i_buffer / 2 ; i++ )
750     {
751         p_sys->p_buffer[i]= ((int16_t *)p_aout_buf->p_buffer)[i];
752     }
753
754     FLAC__stream_encoder_process_interleaved( p_sys->p_flac, p_sys->p_buffer,
755                                               p_aout_buf->i_nb_samples );
756
757     p_chain = p_sys->p_chain;
758     p_sys->p_chain = 0;
759
760     return p_chain;
761 }
762
763 /*****************************************************************************
764  * CloseEncoder: encoder destruction
765  *****************************************************************************/
766 static void CloseEncoder( vlc_object_t *p_this )
767 {
768     encoder_t *p_enc = (encoder_t *)p_this;
769     encoder_sys_t *p_sys = p_enc->p_sys;
770
771     FLAC__stream_encoder_delete( p_sys->p_flac );
772
773     free( p_sys->p_buffer );
774     free( p_sys );
775 }
776 #endif