*****************************************************************************/
vlc_module_begin();
+ set_category( CAT_INPUT );
+ set_subcategory( SUBCAT_INPUT_ACODEC );
+
set_description( _("Flac audio decoder") );
set_capability( "decoder", 100 );
set_callbacks( OpenDecoder, CloseDecoder );
p_dec->pf_decode_audio = DecodeBlock;
p_dec->pf_packetize = PacketizeBlock;
- /* Decode STREAMINFO */
- msg_Dbg( p_dec, "decode STREAMINFO" );
- p_sys->p_block = block_New( p_dec, p_dec->fmt_in.i_extra );
- memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra,
- p_dec->fmt_in.i_extra );
- FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
- msg_Dbg( p_dec, "STREAMINFO decoded" );
-
return VLC_SUCCESS;
}
static int OpenPacketizer( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*)p_this;
+ int i_ret;
+
+ /* Hmmm, mem leak ?*/
+ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
- int i_ret = OpenDecoder( p_this );
+ i_ret = OpenDecoder( p_this );
- if( i_ret != VLC_SUCCESS ) return i_ret;
+ /* Set output properties */
+ p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','a','c');
- es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
+ if( i_ret != VLC_SUCCESS ) return i_ret;
return i_ret;
}
+/*****************************************************************************
+ * ProcessHeader: processe Flac header.
+ *****************************************************************************/
+static void ProcessHeader( decoder_t *p_dec )
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ if( !p_dec->fmt_in.i_extra ) return;
+
+ /* Decode STREAMINFO */
+ msg_Dbg( p_dec, "decode STREAMINFO" );
+ p_sys->p_block = block_New( p_dec, p_dec->fmt_in.i_extra );
+ memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra,
+ p_dec->fmt_in.i_extra );
+ FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
+ msg_Dbg( p_dec, "STREAMINFO decoded" );
+
+ if( !p_sys->b_stream_info ) return;
+
+ if( p_dec->fmt_out.i_codec == VLC_FOURCC('f','l','a','c') )
+ {
+ p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
+ p_dec->fmt_out.p_extra =
+ realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
+ memcpy( p_dec->fmt_out.p_extra,
+ p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
+ }
+}
+
/****************************************************************************
* PacketizeBlock: the whole thing
****************************************************************************
if( !pp_block || !*pp_block ) return NULL;
+ if( !p_sys->b_stream_info ) ProcessHeader( p_dec );
+
if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
{
/* We've just started the stream, wait for the first PTS. */
block_Release( *pp_block );
return NULL;
}
+ else if( !aout_DateGet( &p_sys->end_date ) )
+ {
+ /* The first PTS is as good as anything else. */
+ aout_DateSet( &p_sys->end_date, (*pp_block)->i_pts );
+ }
- if( (*pp_block)->i_flags&BLOCK_FLAG_DISCONTINUITY )
+ if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
{
p_sys->i_state = STATE_NOSYNC;
}
{
p_dec->fmt_out.audio.i_rate = p_sys->i_rate;
aout_DateInit( &p_sys->end_date, p_sys->i_rate );
- p_dec->fmt_out.audio.i_rate = p_sys->i_rate;
}
p_sys->i_state = STATE_NEXT_SYNC;
p_sys->i_frame_size = 1;
/* Need more data */
return NULL;
}
- break;
case STATE_SEND_DATA:
p_sout_block = block_New( p_dec, p_sys->i_frame_size );