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 )
if( p_dec->fmt_in.i_extra > 0 )
{
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 )
{
i_offset = 8;
i_size = p_dec->fmt_in.i_extra - 8;
}
else if( p_dec->fmt_in.i_codec == VLC_CODEC_ALAC )
int i_offset = 0;
int i_size = p_dec->fmt_in.i_extra;
if( p_dec->fmt_in.i_codec == VLC_CODEC_ALAC )
{
static const uint8_t p_pattern[] = { 0, 0, 0, 36, 'a', 'l', 'a', 'c' };
/* Find alac atom XXX it is a bit ugly */
......@@ -97,11 +93,6 @@ static void InitDecoderConfig( decoder_t *p_dec, AVCodecContext *p_context )
if( i_size < 36 )
i_size = 0;
}
else
{
i_offset = 0;
i_size = p_dec->fmt_in.i_extra;
}
if( i_size > 0 )
{
......
......@@ -822,41 +822,16 @@ int OpenEncoder( vlc_object_t *p_this )
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 );
if( p_enc->fmt_out.p_extra )
if ( p_enc->fmt_out.p_extra == NULL )
{
uint8_t *p = p_enc->fmt_out.p_extra;
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 );
goto error;
}
memcpy( p_enc->fmt_out.p_extra, p_context->extradata,
p_enc->fmt_out.i_extra );
}
p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
......
......@@ -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, "fLaC", 4);
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[6] = 0;
p[7] = 34; /* block size */
......@@ -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 );
break;
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;
}
FLAC__stream_decoder_process_until_end_of_metadata( p_sys->p_flac );
......@@ -547,7 +547,7 @@ struct encoder_sys_t
mtime_t i_pts;
};
#define STREAMINFO_SIZE 38
#define STREAMINFO_SIZE 34
static block_t *Encode( encoder_t *, block_t * );
......@@ -572,14 +572,9 @@ EncoderWriteCallback( const FLAC__StreamEncoder *encoder,
msg_Dbg( p_enc, "Writing STREAMINFO: %zu", bytes );
/* Backup the STREAMINFO metadata block */
p_enc->fmt_out.i_extra = STREAMINFO_SIZE + 4;
p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE + 4 );
memcpy( p_enc->fmt_out.p_extra, "fLaC", 4 );
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_enc->fmt_out.i_extra = STREAMINFO_SIZE;
p_enc->fmt_out.p_extra = xmalloc( STREAMINFO_SIZE );
memcpy(p_enc->fmt_out.p_extra, buffer + 4, STREAMINFO_SIZE );
}
p_sys->i_headers++;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
......
......@@ -40,7 +40,7 @@
#include "../../codec/avcodec/avcommon.h"
//#define AVFORMAT_DEBUG 1
#define AVFORMAT_DEBUG 1
static const char *const ppsz_mux_options[] = {
"mux", "options", NULL
......
......@@ -91,7 +91,7 @@ struct demux_sys_t
int i_cover_score;
};
#define STREAMINFO_SIZE 38
#define STREAMINFO_SIZE 34
#define FLAC_PACKET_SIZE 16384
/*****************************************************************************
......@@ -146,7 +146,6 @@ static int Open( vlc_object_t * p_this )
/* Load the FLAC 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 );
fmt.i_extra = i_streaminfo;
fmt.p_extra = p_streaminfo;
......@@ -448,12 +447,11 @@ static int ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streami
s->i_byte_offset = 0;
TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
static const uint8_t marker[4] = { 'f', 'L', 'a', 'C' };
uint8_t header[4];
if( stream_Read( p_demux->s, header, 4) < 4)
return VLC_EGENERIC;
if (memcmp(header, marker, 4))
if (memcmp(header, "fLaC", 4))
return VLC_EGENERIC;
b_last = 0;
......@@ -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_len != (STREAMINFO_SIZE - 4) ) {
if( i_len != STREAMINFO_SIZE ) {
msg_Err( p_demux, "invalid size %d for a STREAMINFO metadata block", i_len );
return VLC_EGENERIC;
}
i_peek = stream_Peek( p_demux->s, &p_peek, STREAMINFO_SIZE);
if( i_peek == STREAMINFO_SIZE)
*pi_streaminfo = STREAMINFO_SIZE + 4;
*pp_streaminfo = malloc( STREAMINFO_SIZE + 4 );
*pi_streaminfo = STREAMINFO_SIZE;
*pp_streaminfo = malloc( STREAMINFO_SIZE);
if( *pp_streaminfo == NULL )
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" );
free( *pp_streaminfo );
return VLC_EGENERIC;
}
memcpy(*pp_streaminfo, marker, 4);
/* */
ParseStreamInfo( &i_sample_rate, &i_sample_count, *pp_streaminfo );
if( i_sample_rate > 0 )
......@@ -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 )
{
const int i_skip = 4+4;
*pi_rate = GetDWBE(&p_data[i_skip+4+6]) >> 12;
*pi_count = GetQWBE(&p_data[i_skip+4+6]) & ((INT64_C(1)<<36)-1);
*pi_rate = GetDWBE(&p_data[4+6]) >> 12;
*pi_count = GetQWBE(&p_data[4+6]) & ((INT64_C(1)<<36)-1);
}
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 )
else if( !strcmp( p_tk->psz_codec, "A_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" ) )
{
......
......@@ -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_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*/ )
{
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, "Invalid FLAC STREAMINFO metadata" );
return;
}
msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
}
else
{
msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
}
if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
{
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;
/* Fake this as the last metadata block */
*((uint8_t*)p_oggpacket->packet) |= 0x80;
msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
}
else
{
/* This ain't a STREAMINFO metadata */
msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
}
/* Fake this as the last metadata block */
*((uint8_t*)p_oggpacket->packet) |= 0x80;
}
static void Ogg_ReadKateHeader( logical_stream_t *p_stream,
......
......@@ -779,11 +779,24 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux )
msg_Dbg( p_mux, "writing extra data" );
op.bytes = p_input->p_fmt->i_extra;
op.packet = p_input->p_fmt->p_extra;
uint8_t flac_streaminfo[34 + 4];
if( p_stream->i_fourcc == VLC_CODEC_FLAC )
{
/* Skip the flac stream marker */
op.bytes -= 4;
op.packet+= 4;
if (op.bytes == 42 && !memcmp(op.packet, "fLaC", 4)) {
op.bytes -= 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.e_o_s = 0;
......
......@@ -170,11 +170,18 @@ static void ProcessHeader( decoder_t *p_dec )
decoder_sys_t *p_sys = p_dec->p_sys;
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;
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.max_blocksize = bs_read( &bs, 16 );
......@@ -188,11 +195,9 @@ static void ProcessHeader( decoder_t *p_dec )
p_sys->b_stream_info = true;
p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
p_dec->fmt_out.p_extra = xrealloc( 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 );
p_dec->fmt_out.i_extra = i_extra;
p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, i_extra );
memcpy( p_dec->fmt_out.p_extra, p_extra, 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