1 /*****************************************************************************
2 * flac.c: flac decoder/encoder module making use of libflac
3 *****************************************************************************
4 * Copyright (C) 1999-2001 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 * Sigmund Augdal Helberg <dnumgis@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_codec.h>
38 #include <stream_decoder.h>
39 #include <stream_encoder.h>
41 #include <vlc_block_helper.h>
44 #if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 8
45 # define USE_NEW_FLAC_API
48 /*****************************************************************************
49 * decoder_sys_t : FLAC decoder descriptor
50 *****************************************************************************/
54 * Input/Output properties
57 aout_buffer_t *p_aout_buffer;
63 FLAC__StreamDecoder *p_flac;
64 FLAC__StreamMetadata_StreamInfo stream_info;
68 static const int pi_channels_maps[9] =
72 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
73 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
74 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
75 | AOUT_CHAN_REARRIGHT,
76 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
77 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
78 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
79 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
80 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
81 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT
82 | AOUT_CHAN_MIDDLERIGHT,
83 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
84 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
88 /*****************************************************************************
90 *****************************************************************************/
91 static int OpenDecoder ( vlc_object_t * );
92 static void CloseDecoder ( vlc_object_t * );
94 static int OpenEncoder ( vlc_object_t * );
95 static void CloseEncoder ( vlc_object_t * );
97 static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
99 static FLAC__StreamDecoderReadStatus
100 DecoderReadCallback( const FLAC__StreamDecoder *decoder,
101 FLAC__byte buffer[], unsigned *bytes, void *client_data );
103 static FLAC__StreamDecoderWriteStatus
104 DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
105 const FLAC__Frame *frame,
106 const FLAC__int32 *const buffer[], void *client_data );
108 static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
109 const FLAC__StreamMetadata *metadata,
111 static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,
112 FLAC__StreamDecoderErrorStatus status,
115 static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
116 const int *pi_order, int i_nb_channels, int i_samples );
117 static void Interleave24( int8_t *p_out, const int32_t * const *pp_in,
118 const int *pi_order, int i_nb_channels, int i_samples );
119 static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
120 const int *pi_order, int i_nb_channels, int i_samples );
122 static void decoder_state_error( decoder_t *p_dec,
123 FLAC__StreamDecoderState state );
125 /*****************************************************************************
127 *****************************************************************************/
130 set_category( CAT_INPUT )
131 set_subcategory( SUBCAT_INPUT_ACODEC )
132 add_shortcut( "flac" )
134 set_description( N_("Flac audio decoder") )
135 set_capability( "decoder", 100 )
136 set_callbacks( OpenDecoder, CloseDecoder )
139 add_shortcut( "flac" )
140 set_description( N_("Flac audio encoder") )
141 set_capability( "encoder", 100 )
142 set_callbacks( OpenEncoder, CloseEncoder )
146 /*****************************************************************************
147 * OpenDecoder: probe the decoder and return score
148 *****************************************************************************/
149 static int OpenDecoder( vlc_object_t *p_this )
151 decoder_t *p_dec = (decoder_t*)p_this;
152 decoder_sys_t *p_sys;
154 if( p_dec->fmt_in.i_codec != VLC_CODEC_FLAC )
159 /* Allocate the memory needed to store the decoder's structure */
160 if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
164 p_sys->b_stream_info = false;
165 p_sys->p_block = NULL;
167 /* Take care of flac init */
168 if( !(p_sys->p_flac = FLAC__stream_decoder_new()) )
170 msg_Err( p_dec, "FLAC__stream_decoder_new() failed" );
175 #ifdef USE_NEW_FLAC_API
176 if( FLAC__stream_decoder_init_stream( p_sys->p_flac,
182 DecoderWriteCallback,
183 DecoderMetadataCallback,
184 DecoderErrorCallback,
186 != FLAC__STREAM_DECODER_INIT_STATUS_OK )
188 msg_Err( p_dec, "FLAC__stream_decoder_init_stream() failed" );
189 FLAC__stream_decoder_delete( p_sys->p_flac );
194 FLAC__stream_decoder_set_read_callback( p_sys->p_flac,
195 DecoderReadCallback );
196 FLAC__stream_decoder_set_write_callback( p_sys->p_flac,
197 DecoderWriteCallback );
198 FLAC__stream_decoder_set_metadata_callback( p_sys->p_flac,
199 DecoderMetadataCallback );
200 FLAC__stream_decoder_set_error_callback( p_sys->p_flac,
201 DecoderErrorCallback );
202 FLAC__stream_decoder_set_client_data( p_sys->p_flac, p_dec );
204 FLAC__stream_decoder_init( p_sys->p_flac );
207 /* Set output properties */
208 p_dec->fmt_out.i_cat = AUDIO_ES;
209 p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
212 p_dec->pf_decode_audio = DecodeBlock;
215 p_dec->b_need_packetized = true;
220 /*****************************************************************************
221 * CloseDecoder: flac decoder destruction
222 *****************************************************************************/
223 static void CloseDecoder( vlc_object_t *p_this )
225 decoder_t *p_dec = (decoder_t *)p_this;
226 decoder_sys_t *p_sys = p_dec->p_sys;
228 FLAC__stream_decoder_finish( p_sys->p_flac );
229 FLAC__stream_decoder_delete( p_sys->p_flac );
232 block_Release( p_sys->p_block );
236 /*****************************************************************************
237 * ProcessHeader: process Flac header.
238 *****************************************************************************/
239 static void ProcessHeader( decoder_t *p_dec )
241 decoder_sys_t *p_sys = p_dec->p_sys;
243 if( !p_dec->fmt_in.i_extra )
246 /* Decode STREAMINFO */
247 msg_Dbg( p_dec, "decode STREAMINFO" );
248 p_sys->p_block = block_New( p_dec, p_dec->fmt_in.i_extra );
249 memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra,
250 p_dec->fmt_in.i_extra );
251 FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
252 msg_Dbg( p_dec, "STREAMINFO decoded" );
255 /****************************************************************************
256 * DecodeBlock: the whole thing
257 ****************************************************************************/
258 static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
260 decoder_sys_t *p_sys = p_dec->p_sys;
262 if( !pp_block || !*pp_block )
264 if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
266 block_Release( *pp_block );
270 if( !p_sys->b_stream_info )
271 ProcessHeader( p_dec );
273 p_sys->p_block = *pp_block;
276 if( p_sys->p_block->i_pts > VLC_TS_INVALID &&
277 p_sys->p_block->i_pts != date_Get( &p_sys->end_date ) )
278 date_Set( &p_sys->end_date, p_sys->p_block->i_pts );
280 p_sys->p_aout_buffer = 0;
282 if( !FLAC__stream_decoder_process_single( p_sys->p_flac ) )
284 decoder_state_error( p_dec,
285 FLAC__stream_decoder_get_state( p_sys->p_flac ) );
286 FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
289 /* If the decoder is in the "aborted" state,
290 * FLAC__stream_decoder_process_single() won't return an error. */
291 if( FLAC__stream_decoder_get_state(p_dec->p_sys->p_flac)
292 == FLAC__STREAM_DECODER_ABORTED )
294 FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
297 block_Release( p_sys->p_block );
298 p_sys->p_block = NULL;
300 return p_sys->p_aout_buffer;
303 /*****************************************************************************
304 * DecoderReadCallback: called by libflac when it needs more data
305 *****************************************************************************/
306 static FLAC__StreamDecoderReadStatus
307 DecoderReadCallback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],
308 unsigned *bytes, void *client_data )
311 decoder_t *p_dec = (decoder_t *)client_data;
312 decoder_sys_t *p_sys = p_dec->p_sys;
314 if( p_sys->p_block && p_sys->p_block->i_buffer )
316 *bytes = __MIN(*bytes, (unsigned)p_sys->p_block->i_buffer);
317 memcpy( buffer, p_sys->p_block->p_buffer, *bytes );
318 p_sys->p_block->i_buffer -= *bytes;
319 p_sys->p_block->p_buffer += *bytes;
324 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
327 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
330 /*****************************************************************************
331 * DecoderWriteCallback: called by libflac to output decoded samples
332 *****************************************************************************/
333 static FLAC__StreamDecoderWriteStatus
334 DecoderWriteCallback( const FLAC__StreamDecoder *decoder,
335 const FLAC__Frame *frame,
336 const FLAC__int32 *const buffer[], void *client_data )
338 /* XXX it supposes our internal format is WG4 */
339 static const int ppi_reorder[1+8][8] = {
346 { 0, 1, 4, 5, 2, 3 },
348 { 0, 1, 6, 4, 5, 2, 3 }, /* 7.0 Unspecified by flac, but following SMPTE */
349 { 0, 1, 6, 7, 4, 5, 2, 3 }, /* 7.1 Unspecified by flac, but following SMPTE */
353 decoder_t *p_dec = (decoder_t *)client_data;
354 decoder_sys_t *p_sys = p_dec->p_sys;
356 if( p_dec->fmt_out.audio.i_channels <= 0 ||
357 p_dec->fmt_out.audio.i_channels > 8 )
358 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
359 if( date_Get( &p_sys->end_date ) <= VLC_TS_INVALID )
360 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
362 const int * const pi_reorder = ppi_reorder[p_dec->fmt_out.audio.i_channels];
364 p_sys->p_aout_buffer =
365 decoder_NewAudioBuffer( p_dec, frame->header.blocksize );
367 if( p_sys->p_aout_buffer == NULL )
368 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
370 switch( frame->header.bits_per_sample )
373 Interleave16( (int16_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
374 frame->header.channels, frame->header.blocksize );
377 Interleave24( (int8_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
378 frame->header.channels, frame->header.blocksize );
381 Interleave32( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer, pi_reorder,
382 frame->header.channels, frame->header.blocksize );
385 /* Date management (already done by packetizer) */
386 p_sys->p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
387 p_sys->p_aout_buffer->i_length =
388 date_Increment( &p_sys->end_date, frame->header.blocksize ) -
389 p_sys->p_aout_buffer->i_pts;
391 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
394 /*****************************************************************************
395 * DecoderMetadataCallback: called by libflac to when it encounters metadata
396 *****************************************************************************/
397 static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
398 const FLAC__StreamMetadata *metadata,
402 decoder_t *p_dec = (decoder_t *)client_data;
403 decoder_sys_t *p_sys = p_dec->p_sys;
405 if( p_dec->pf_decode_audio )
407 switch( metadata->data.stream_info.bits_per_sample )
410 p_dec->fmt_out.i_codec = VLC_CODEC_S8;
413 p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
416 p_dec->fmt_out.i_codec = VLC_CODEC_S24N;
419 msg_Dbg( p_dec, "strange bit/sample value: %d",
420 metadata->data.stream_info.bits_per_sample );
421 p_dec->fmt_out.i_codec = VLC_CODEC_FI32;
426 /* Setup the format */
427 p_dec->fmt_out.audio.i_rate = metadata->data.stream_info.sample_rate;
428 p_dec->fmt_out.audio.i_channels = metadata->data.stream_info.channels;
429 p_dec->fmt_out.audio.i_physical_channels =
430 p_dec->fmt_out.audio.i_original_channels =
431 pi_channels_maps[metadata->data.stream_info.channels];
432 p_dec->fmt_out.audio.i_bitspersample =
433 metadata->data.stream_info.bits_per_sample;
435 msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
436 p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
437 p_dec->fmt_out.audio.i_bitspersample );
439 p_sys->b_stream_info = true;
440 p_sys->stream_info = metadata->data.stream_info;
442 date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
443 date_Set( &p_sys->end_date, VLC_TS_INVALID );
446 /*****************************************************************************
447 * DecoderErrorCallback: called when the libflac decoder encounters an error
448 *****************************************************************************/
449 static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,
450 FLAC__StreamDecoderErrorStatus status,
454 decoder_t *p_dec = (decoder_t *)client_data;
458 case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
459 msg_Warn( p_dec, "an error in the stream caused the decoder to "
460 "lose synchronization." );
462 case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
463 msg_Err( p_dec, "the decoder encountered a corrupted frame header." );
465 case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
466 msg_Err( p_dec, "frame's data did not match the CRC in the "
470 msg_Err( p_dec, "got decoder error: %d", status );
473 FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );
477 /*****************************************************************************
478 * Interleave: helper function to interleave channels
479 *****************************************************************************/
480 static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,
481 const int pi_index[],
482 int i_nb_channels, int i_samples )
485 for ( j = 0; j < i_samples; j++ )
487 for ( i = 0; i < i_nb_channels; i++ )
489 p_out[j * i_nb_channels + i] = pp_in[pi_index[i]][j];
494 static void Interleave24( int8_t *p_out, const int32_t * const *pp_in,
495 const int pi_index[],
496 int i_nb_channels, int i_samples )
499 for ( j = 0; j < i_samples; j++ )
501 for ( i = 0; i < i_nb_channels; i++ )
503 const int i_index = pi_index[i];
504 #ifdef WORDS_BIGENDIAN
505 p_out[3*(j * i_nb_channels + i)+0] = (pp_in[i_index][j] >> 16) & 0xff;
506 p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i_index][j] >> 8 ) & 0xff;
507 p_out[3*(j * i_nb_channels + i)+2] = (pp_in[i_index][j] >> 0 ) & 0xff;
509 p_out[3*(j * i_nb_channels + i)+2] = (pp_in[i_index][j] >> 16) & 0xff;
510 p_out[3*(j * i_nb_channels + i)+1] = (pp_in[i_index][j] >> 8 ) & 0xff;
511 p_out[3*(j * i_nb_channels + i)+0] = (pp_in[i_index][j] >> 0 ) & 0xff;
517 static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,
518 const int pi_index[],
519 int i_nb_channels, int i_samples )
522 for ( j = 0; j < i_samples; j++ )
524 for ( i = 0; i < i_nb_channels; i++ )
526 p_out[j * i_nb_channels + i] = (int32_t)(pp_in[pi_index[i]][j]);
531 /*****************************************************************************
532 * decoder_state_error: print meaningful error messages
533 *****************************************************************************/
534 static void decoder_state_error( decoder_t *p_dec,
535 FLAC__StreamDecoderState state )
539 case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
540 msg_Dbg( p_dec, "the decoder is ready to search for metadata." );
542 case FLAC__STREAM_DECODER_READ_METADATA:
543 msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
544 "reading metadata." );
546 case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
547 msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
548 "searching for the frame sync code." );
550 case FLAC__STREAM_DECODER_READ_FRAME:
551 msg_Dbg( p_dec, "the decoder is ready to or is in the process of "
552 "reading a frame." );
554 case FLAC__STREAM_DECODER_END_OF_STREAM:
555 msg_Dbg( p_dec, "the decoder has reached the end of the stream." );
557 #ifdef USE_NEW_FLAC_API
558 case FLAC__STREAM_DECODER_OGG_ERROR:
559 msg_Err( p_dec, "error occurred in the Ogg layer." );
561 case FLAC__STREAM_DECODER_SEEK_ERROR:
562 msg_Err( p_dec, "error occurred while seeking." );
565 case FLAC__STREAM_DECODER_ABORTED:
566 msg_Warn( p_dec, "the decoder was aborted by the read callback." );
568 #ifndef USE_NEW_FLAC_API
569 case FLAC__STREAM_DECODER_UNPARSEABLE_STREAM:
570 msg_Warn( p_dec, "the decoder encountered reserved fields in use "
574 case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
575 msg_Err( p_dec, "error when allocating memory." );
577 #ifndef USE_NEW_FLAC_API
578 case FLAC__STREAM_DECODER_ALREADY_INITIALIZED:
579 msg_Err( p_dec, "FLAC__stream_decoder_init() was called when the "
580 "decoder was already initialized, usually because "
581 "FLAC__stream_decoder_finish() was not called." );
583 case FLAC__STREAM_DECODER_INVALID_CALLBACK:
584 msg_Err( p_dec, "FLAC__stream_decoder_init() was called without "
585 "all callbacks being set." );
588 case FLAC__STREAM_DECODER_UNINITIALIZED:
589 msg_Err( p_dec, "decoder in uninitialized state." );
592 msg_Warn(p_dec, "unknown error" );
596 /*****************************************************************************
597 * encoder_sys_t : flac encoder descriptor
598 *****************************************************************************/
609 FLAC__int32 *p_buffer;
610 unsigned int i_buffer;
617 FLAC__StreamEncoder *p_flac;
618 FLAC__StreamMetadata_StreamInfo stream_info;
626 #define STREAMINFO_SIZE 38
628 static block_t *Encode( encoder_t *, aout_buffer_t * );
630 static FLAC__StreamEncoderWriteStatus
631 EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
632 const FLAC__byte buffer[],
633 unsigned bytes, unsigned samples,
634 unsigned current_frame, void *client_data );
636 static void EncoderMetadataCallback( const FLAC__StreamEncoder *encoder,
637 const FLAC__StreamMetadata *metadata,
640 /*****************************************************************************
641 * OpenEncoder: probe the encoder and return score
642 *****************************************************************************/
643 static int OpenEncoder( vlc_object_t *p_this )
645 encoder_t *p_enc = (encoder_t *)p_this;
646 encoder_sys_t *p_sys;
648 if( p_enc->fmt_out.i_codec != VLC_CODEC_FLAC &&
654 /* Allocate the memory needed to store the decoder's structure */
655 if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
657 p_enc->p_sys = p_sys;
658 p_enc->pf_encode_audio = Encode;
659 p_enc->fmt_out.i_codec = VLC_CODEC_FLAC;
661 p_sys->i_headers = 0;
664 p_sys->i_samples_delay = 0;
666 /* Create flac encoder */
667 if( !(p_sys->p_flac = FLAC__stream_encoder_new()) )
669 msg_Err( p_enc, "FLAC__stream_encoder_new() failed" );
674 FLAC__stream_encoder_set_streamable_subset( p_sys->p_flac, 1 );
675 FLAC__stream_encoder_set_channels( p_sys->p_flac,
676 p_enc->fmt_in.audio.i_channels );
677 FLAC__stream_encoder_set_sample_rate( p_sys->p_flac,
678 p_enc->fmt_in.audio.i_rate );
679 FLAC__stream_encoder_set_bits_per_sample( p_sys->p_flac, 16 );
680 p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
682 /* Get and store the STREAMINFO metadata block as a p_extra */
685 #ifdef USE_NEW_FLAC_API
686 if( FLAC__stream_encoder_init_stream( p_sys->p_flac,
687 EncoderWriteCallback,
690 EncoderMetadataCallback,
692 != FLAC__STREAM_ENCODER_INIT_STATUS_OK )
694 msg_Err( p_enc, "FLAC__stream_encoder_init_stream() failed" );
695 FLAC__stream_encoder_delete( p_sys->p_flac );
700 FLAC__stream_encoder_set_write_callback( p_sys->p_flac,
701 EncoderWriteCallback );
702 FLAC__stream_encoder_set_metadata_callback( p_sys->p_flac,
703 EncoderMetadataCallback );
704 FLAC__stream_encoder_set_client_data( p_sys->p_flac, p_enc );
706 FLAC__stream_encoder_init( p_sys->p_flac );
712 /****************************************************************************
713 * Encode: the whole thing
714 ****************************************************************************
715 * This function spits out ogg packets.
716 ****************************************************************************/
717 static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
719 encoder_sys_t *p_sys = p_enc->p_sys;
723 p_sys->i_pts = p_aout_buf->i_pts -
724 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
725 (mtime_t)p_enc->fmt_in.audio.i_rate;
727 p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
729 /* Convert samples to FLAC__int32 */
730 if( p_sys->i_buffer < p_aout_buf->i_buffer * 2 )
733 xrealloc( p_sys->p_buffer, p_aout_buf->i_buffer * 2 );
734 p_sys->i_buffer = p_aout_buf->i_buffer * 2;
737 for( i = 0 ; i < p_aout_buf->i_buffer / 2 ; i++ )
739 p_sys->p_buffer[i]= ((int16_t *)p_aout_buf->p_buffer)[i];
742 FLAC__stream_encoder_process_interleaved( p_sys->p_flac, p_sys->p_buffer,
743 p_aout_buf->i_nb_samples );
745 p_chain = p_sys->p_chain;
751 /*****************************************************************************
752 * CloseEncoder: encoder destruction
753 *****************************************************************************/
754 static void CloseEncoder( vlc_object_t *p_this )
756 encoder_t *p_enc = (encoder_t *)p_this;
757 encoder_sys_t *p_sys = p_enc->p_sys;
759 FLAC__stream_encoder_delete( p_sys->p_flac );
761 free( p_sys->p_buffer );
765 /*****************************************************************************
766 * EncoderMetadataCallback: called by libflac to output metadata
767 *****************************************************************************/
768 static void EncoderMetadataCallback( const FLAC__StreamEncoder *encoder,
769 const FLAC__StreamMetadata *metadata,
773 encoder_t *p_enc = (encoder_t *)client_data;
775 msg_Err( p_enc, "MetadataCallback: %i", metadata->type );
779 /*****************************************************************************
780 * EncoderWriteCallback: called by libflac to output encoded samples
781 *****************************************************************************/
782 static FLAC__StreamEncoderWriteStatus
783 EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
784 const FLAC__byte buffer[],
785 unsigned bytes, unsigned samples,
786 unsigned current_frame, void *client_data )
788 VLC_UNUSED(encoder); VLC_UNUSED(current_frame);
789 encoder_t *p_enc = (encoder_t *)client_data;
790 encoder_sys_t *p_sys = p_enc->p_sys;
795 if( p_sys->i_headers == 1 )
797 msg_Dbg( p_enc, "Writing STREAMINFO: %i", bytes );
799 /* Backup the STREAMINFO metadata block */
800 p_enc->fmt_out.i_extra = STREAMINFO_SIZE + 4;
801 p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE + 4 );
802 memcpy( p_enc->fmt_out.p_extra, "fLaC", 4 );
803 memcpy( ((uint8_t *)p_enc->fmt_out.p_extra) + 4, buffer,
806 /* Fake this as the last metadata block */
807 ((uint8_t*)p_enc->fmt_out.p_extra)[4] |= 0x80;
810 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
813 p_block = block_New( p_enc, bytes );
814 memcpy( p_block->p_buffer, buffer, bytes );
816 p_block->i_dts = p_block->i_pts = p_sys->i_pts;
818 p_sys->i_samples_delay -= samples;
820 p_block->i_length = (mtime_t)1000000 *
821 (mtime_t)samples / (mtime_t)p_enc->fmt_in.audio.i_rate;
824 p_sys->i_pts += p_block->i_length;
826 block_ChainAppend( &p_sys->p_chain, p_block );
828 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;