Commit 9925a34e authored by Rafaël Carré's avatar Rafaël Carré

Simplify FLAC extradata (streaminfo) parsing

Prefer the shorter version (avcodec/avformat support both)
parent 6c41d370
...@@ -76,15 +76,11 @@ static void InitDecoderConfig( decoder_t *p_dec, AVCodecContext *p_context ) ...@@ -76,15 +76,11 @@ static void InitDecoderConfig( decoder_t *p_dec, AVCodecContext *p_context )
if( p_dec->fmt_in.i_extra > 0 ) if( p_dec->fmt_in.i_extra > 0 )
{ {
const uint8_t * const p_src = p_dec->fmt_in.p_extra; const uint8_t * const p_src = p_dec->fmt_in.p_extra;
int i_offset;
int i_size;
if( p_dec->fmt_in.i_codec == VLC_CODEC_FLAC ) int i_offset = 0;
{ int i_size = p_dec->fmt_in.i_extra;
i_offset = 8;
i_size = p_dec->fmt_in.i_extra - 8; if( p_dec->fmt_in.i_codec == VLC_CODEC_ALAC )
}
else if( p_dec->fmt_in.i_codec == VLC_CODEC_ALAC )
{ {
static const uint8_t p_pattern[] = { 0, 0, 0, 36, 'a', 'l', 'a', 'c' }; static const uint8_t p_pattern[] = { 0, 0, 0, 36, 'a', 'l', 'a', 'c' };
/* Find alac atom XXX it is a bit ugly */ /* Find alac atom XXX it is a bit ugly */
...@@ -97,11 +93,6 @@ static void InitDecoderConfig( decoder_t *p_dec, AVCodecContext *p_context ) ...@@ -97,11 +93,6 @@ static void InitDecoderConfig( decoder_t *p_dec, AVCodecContext *p_context )
if( i_size < 36 ) if( i_size < 36 )
i_size = 0; i_size = 0;
} }
else
{
i_offset = 0;
i_size = p_dec->fmt_in.i_extra;
}
if( i_size > 0 ) if( i_size > 0 )
{ {
......
...@@ -822,41 +822,16 @@ int OpenEncoder( vlc_object_t *p_this ) ...@@ -822,41 +822,16 @@ int OpenEncoder( vlc_object_t *p_this )
av_dict_free(&options); av_dict_free(&options);
if( i_codec_id == AV_CODEC_ID_FLAC ) p_enc->fmt_out.i_extra = p_context->extradata_size;
if( p_enc->fmt_out.i_extra )
{ {
p_enc->fmt_out.i_extra = 4 + 1 + 3 + p_context->extradata_size;
p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra ); p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
if( p_enc->fmt_out.p_extra ) if ( p_enc->fmt_out.p_extra == NULL )
{ {
uint8_t *p = p_enc->fmt_out.p_extra; goto error;
p[0] = 0x66; /* f */
p[1] = 0x4C; /* L */
p[2] = 0x61; /* a */
p[3] = 0x43; /* C */
p[4] = 0x80; /* streaminfo block, last block before audio */
p[5] = ( p_context->extradata_size >> 16 ) & 0xff;
p[6] = ( p_context->extradata_size >> 8 ) & 0xff;
p[7] = ( p_context->extradata_size ) & 0xff;
memcpy( &p[8], p_context->extradata, p_context->extradata_size );
}
else
{
p_enc->fmt_out.i_extra = 0;
}
}
else
{
p_enc->fmt_out.i_extra = p_context->extradata_size;
if( p_enc->fmt_out.i_extra )
{
p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
if ( p_enc->fmt_out.p_extra == NULL )
{
goto error;
}
memcpy( p_enc->fmt_out.p_extra, p_context->extradata,
p_enc->fmt_out.i_extra );
} }
memcpy( p_enc->fmt_out.p_extra, p_context->extradata,
p_enc->fmt_out.i_extra );
} }
p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER; p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
......
...@@ -386,7 +386,7 @@ static void ProcessHeader( decoder_t *p_dec ) ...@@ -386,7 +386,7 @@ static void ProcessHeader( decoder_t *p_dec )
memcpy( p_sys->p_block->p_buffer + 8, p_dec->fmt_in.p_extra, i_extra ); memcpy( p_sys->p_block->p_buffer + 8, p_dec->fmt_in.p_extra, i_extra );
memcpy( p_sys->p_block->p_buffer, "fLaC", 4); memcpy( p_sys->p_block->p_buffer, "fLaC", 4);
uint8_t *p = p_sys->p_block->p_buffer; uint8_t *p = p_sys->p_block->p_buffer;
p[4] = 0; /* STREAMINFO */ p[4] = 0x80 | 0; /* STREAMINFO faked as last block */
p[5] = 0; p[5] = 0;
p[6] = 0; p[6] = 0;
p[7] = 34; /* block size */ p[7] = 34; /* block size */
...@@ -396,7 +396,7 @@ static void ProcessHeader( decoder_t *p_dec ) ...@@ -396,7 +396,7 @@ static void ProcessHeader( decoder_t *p_dec )
memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra, i_extra ); memcpy( p_sys->p_block->p_buffer, p_dec->fmt_in.p_extra, i_extra );
break; break;
default: default:
msg_Err(p_dec, "Invalid flac header size %zu\n", i_extra); msg_Err(p_dec, "Invalid flac header size %zu", i_extra);
return; return;
} }
FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac ); FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
...@@ -547,7 +547,7 @@ struct encoder_sys_t ...@@ -547,7 +547,7 @@ struct encoder_sys_t
mtime_t i_pts; mtime_t i_pts;
}; };
#define STREAMINFO_SIZE 38 #define STREAMINFO_SIZE 34
static block_t *Encode( encoder_t *, block_t * ); static block_t *Encode( encoder_t *, block_t * );
...@@ -572,14 +572,9 @@ EncoderWriteCallback( const FLAC__StreamEncoder *encoder, ...@@ -572,14 +572,9 @@ EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
msg_Dbg( p_enc, "Writing STREAMINFO: %zu", bytes ); msg_Dbg( p_enc, "Writing STREAMINFO: %zu", bytes );
/* Backup the STREAMINFO metadata block */ /* Backup the STREAMINFO metadata block */
p_enc->fmt_out.i_extra = STREAMINFO_SIZE + 4; p_enc->fmt_out.i_extra = STREAMINFO_SIZE;
p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE + 4 ); p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE );
memcpy( p_enc->fmt_out.p_extra, "fLaC", 4 ); memcpy(p_enc->fmt_out.p_extra, buffer + 4, STREAMINFO_SIZE );
memcpy( ((uint8_t *)p_enc->fmt_out.p_extra) + 4, buffer,
STREAMINFO_SIZE );
/* Fake this as the last metadata block */
((uint8_t*)p_enc->fmt_out.p_extra)[4] |= 0x80;
} }
p_sys->i_headers++; p_sys->i_headers++;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include "../../codec/avcodec/avcommon.h" #include "../../codec/avcodec/avcommon.h"
//#define AVFORMAT_DEBUG 1 #define AVFORMAT_DEBUG 1
static const char *const ppsz_mux_options[] = { static const char *const ppsz_mux_options[] = {
"mux", "options", NULL "mux", "options", NULL
......
...@@ -91,7 +91,7 @@ struct demux_sys_t ...@@ -91,7 +91,7 @@ struct demux_sys_t
int i_cover_score; int i_cover_score;
}; };
#define STREAMINFO_SIZE 38 #define STREAMINFO_SIZE 34
#define FLAC_PACKET_SIZE 16384 #define FLAC_PACKET_SIZE 16384
/***************************************************************************** /*****************************************************************************
...@@ -146,7 +146,6 @@ static int Open( vlc_object_t * p_this ) ...@@ -146,7 +146,6 @@ static int Open( vlc_object_t * p_this )
/* Load the FLAC packetizer */ /* Load the FLAC packetizer */
/* Store STREAMINFO for the decoder and packetizer */ /* Store STREAMINFO for the decoder and packetizer */
p_streaminfo[4] |= 0x80; /* Fake this as the last metadata block */
es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_FLAC ); es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_FLAC );
fmt.i_extra = i_streaminfo; fmt.i_extra = i_streaminfo;
fmt.p_extra = p_streaminfo; fmt.p_extra = p_streaminfo;
...@@ -448,12 +447,11 @@ static int ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami ...@@ -448,12 +447,11 @@ static int ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami
s->i_byte_offset = 0; s->i_byte_offset = 0;
TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s ); TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
static const uint8_t marker[4] = { 'f', 'L', 'a', 'C' };
uint8_t header[4]; uint8_t header[4];
if( stream_Read( p_demux->s, header, 4) < 4) if( stream_Read( p_demux->s, header, 4) < 4)
return VLC_EGENERIC; return VLC_EGENERIC;
if (memcmp(header, marker, 4)) if (memcmp(header, "fLaC", 4))
return VLC_EGENERIC; return VLC_EGENERIC;
b_last = 0; b_last = 0;
...@@ -471,27 +469,25 @@ static int ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami ...@@ -471,27 +469,25 @@ static int ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami
if( i_type == META_STREAMINFO && !*pp_streaminfo ) if( i_type == META_STREAMINFO && !*pp_streaminfo )
{ {
if( i_len != (STREAMINFO_SIZE - 4) ) { if( i_len != STREAMINFO_SIZE ) {
msg_Err( p_demux, "invalid size %d for a STREAMINFO metadata block", i_len ); msg_Err( p_demux, "invalid size %d for a STREAMINFO metadata block", i_len );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
i_peek = stream_Peek( p_demux->s, &p_peek, STREAMINFO_SIZE);
if( i_peek == STREAMINFO_SIZE)
*pi_streaminfo = STREAMINFO_SIZE + 4; *pi_streaminfo = STREAMINFO_SIZE;
*pp_streaminfo = malloc( STREAMINFO_SIZE + 4 ); *pp_streaminfo = malloc( STREAMINFO_SIZE);
if( *pp_streaminfo == NULL ) if( *pp_streaminfo == NULL )
return VLC_EGENERIC; return VLC_EGENERIC;
if( stream_Read( p_demux->s, &(*pp_streaminfo)[4], STREAMINFO_SIZE ) != STREAMINFO_SIZE ) if( stream_Read( p_demux->s, NULL, 4) < 4)
return VLC_EGENERIC;
if( stream_Read( p_demux->s, *pp_streaminfo, STREAMINFO_SIZE ) != STREAMINFO_SIZE )
{ {
msg_Err( p_demux, "failed to read STREAMINFO metadata block" ); msg_Err( p_demux, "failed to read STREAMINFO metadata block" );
free( *pp_streaminfo ); free( *pp_streaminfo );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
memcpy(*pp_streaminfo, marker, 4);
/* */ /* */
ParseStreamInfo( &i_sample_rate, &i_sample_count, *pp_streaminfo ); ParseStreamInfo( &i_sample_rate, &i_sample_count, *pp_streaminfo );
if( i_sample_rate > 0 ) if( i_sample_rate > 0 )
...@@ -531,10 +527,8 @@ static int ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami ...@@ -531,10 +527,8 @@ static int ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami
} }
static void ParseStreamInfo( int *pi_rate, int64_t *pi_count, uint8_t *p_data ) static void ParseStreamInfo( int *pi_rate, int64_t *pi_count, uint8_t *p_data )
{ {
const int i_skip = 4+4; *pi_rate = GetDWBE(&p_data[4+6]) >> 12;
*pi_count = GetQWBE(&p_data[4+6]) & ((INT64_C(1)<<36)-1);
*pi_rate = GetDWBE(&p_data[i_skip+4+6]) >> 12;
*pi_count = GetQWBE(&p_data[i_skip+4+6]) & ((INT64_C(1)<<36)-1);
} }
static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, int i_data, static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, int i_data,
......
...@@ -1416,7 +1416,7 @@ int32_t matroska_segment_c::TrackInit( mkv_track_t * p_tk ) ...@@ -1416,7 +1416,7 @@ int32_t matroska_segment_c::TrackInit( mkv_track_t * p_tk )
else if( !strcmp( p_tk->psz_codec, "A_FLAC" ) ) else if( !strcmp( p_tk->psz_codec, "A_FLAC" ) )
{ {
p_tk->fmt.i_codec = VLC_CODEC_FLAC; p_tk->fmt.i_codec = VLC_CODEC_FLAC;
fill_extra_data( p_tk, 0 ); fill_extra_data( p_tk, 8 );
} }
else if( !strcmp( p_tk->psz_codec, "A_VORBIS" ) ) else if( !strcmp( p_tk->psz_codec, "A_VORBIS" ) )
{ {
......
...@@ -2068,30 +2068,28 @@ static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream, ...@@ -2068,30 +2068,28 @@ static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes ); bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
bs_read( &s, 1 ); bs_read( &s, 1 );
if( p_oggpacket->bytes > 0 && bs_read( &s, 7 ) == 0 ) if( p_oggpacket->bytes > 0 && bs_read( &s, 7 ) != 0 )
{ {
if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ ) msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
{ return;
bs_skip( &s, 80 ); }
p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i", if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
p_stream->fmt.audio.i_channels, (int)p_stream->f_rate ); {
} bs_skip( &s, 80 );
else p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
{ p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
}
/* Fake this as the last metadata block */ msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
*((uint8_t*)p_oggpacket->packet) |= 0x80; p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
} }
else else
{ {
/* This ain't a STREAMINFO metadata */ msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
} }
/* Fake this as the last metadata block */
*((uint8_t*)p_oggpacket->packet) |= 0x80;
} }
static void Ogg_ReadKateHeader( logical_stream_t *p_stream, static void Ogg_ReadKateHeader( logical_stream_t *p_stream,
......
...@@ -779,11 +779,24 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux ) ...@@ -779,11 +779,24 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux )
msg_Dbg( p_mux, "writing extra data" ); msg_Dbg( p_mux, "writing extra data" );
op.bytes = p_input->p_fmt->i_extra; op.bytes = p_input->p_fmt->i_extra;
op.packet = p_input->p_fmt->p_extra; op.packet = p_input->p_fmt->p_extra;
uint8_t flac_streaminfo[34 + 4];
if( p_stream->i_fourcc == VLC_CODEC_FLAC ) if( p_stream->i_fourcc == VLC_CODEC_FLAC )
{ {
/* Skip the flac stream marker */ if (op.bytes == 42 && !memcmp(op.packet, "fLaC", 4)) {
op.bytes -= 4; op.bytes -= 4;
op.packet+= 4; memcpy(flac_streaminfo, op.packet + 4, 38);
op.packet = flac_streaminfo;
} else if (op.bytes == 34) {
op.bytes += 4;
memcpy(flac_streaminfo + 4, op.packet, 34);
flac_streaminfo[0] = 0x80; /* last block, streaminfo */
flac_streaminfo[1] = 0;
flac_streaminfo[2] = 0;
flac_streaminfo[3] = 34; /* block size */
op.packet = flac_streaminfo;
} else {
msg_Err(p_mux, "Invalid FLAC streaminfo (%d bytes)", op.bytes);
}
} }
op.b_o_s = 0; op.b_o_s = 0;
op.e_o_s = 0; op.e_o_s = 0;
......
...@@ -170,11 +170,18 @@ static void ProcessHeader( decoder_t *p_dec ) ...@@ -170,11 +170,18 @@ static void ProcessHeader( decoder_t *p_dec )
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
bs_t bs; bs_t bs;
int i_extra = p_dec->fmt_in.i_extra;
char *p_extra = p_dec->fmt_in.p_extra;
if( p_dec->fmt_in.i_extra < 8 + 14 ) if (i_extra > 8 && !memcmp(p_extra, "fLaC", 4)) {
i_extra -= 8;
p_extra += 8;
}
if( p_dec->fmt_in.i_extra < 14 )
return; return;
bs_init( &bs, (uint8_t*)p_dec->fmt_in.p_extra + 8, p_dec->fmt_in.i_extra - 8 ); bs_init( &bs, p_extra, i_extra);
p_sys->stream_info.min_blocksize = bs_read( &bs, 16 ); p_sys->stream_info.min_blocksize = bs_read( &bs, 16 );
p_sys->stream_info.max_blocksize = bs_read( &bs, 16 ); p_sys->stream_info.max_blocksize = bs_read( &bs, 16 );
...@@ -188,11 +195,9 @@ static void ProcessHeader( decoder_t *p_dec ) ...@@ -188,11 +195,9 @@ static void ProcessHeader( decoder_t *p_dec )
p_sys->b_stream_info = true; p_sys->b_stream_info = true;
p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.i_extra = i_extra;
p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, i_extra );
p_dec->fmt_out.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_extra, i_extra );
memcpy( p_dec->fmt_out.p_extra,
p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
} }
/* */ /* */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment