Commit 535be4f6 authored by Gildas Bazin's avatar Gildas Bazin

* include/vlc_es_out.h, src/input/es_out.c: added an ES_OUT_SET_FMT control.

* modules/demux/ogg.c, modules/demux/mkv.cpp:
  - store the vorbis/theora/speex headers in fmt.p_extra.
  - this change simplifies the code quite a bit and is a lot cleaner.
* modules/codec/vorbis.c, theora.c, speex.c, flac.c:
  - get the headers from fmt_in.p_extra or from the bitstream if empty.
* modules/mux/ogg.c:
  - recontstruct the headers from fmt.p_extra.
parent e96986fe
......@@ -2,7 +2,7 @@
* vlc_es_out.h
*****************************************************************************
* Copyright (C) 1999-2004 VideoLAN
* $Id: ninput.h 7930 2004-06-07 18:23:15Z fenrir $
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -62,6 +62,9 @@ enum es_out_query_e
ES_OUT_SET_PCR, /* arg1=int64_t i_pcr(microsecond!) (using default group 0)*/
ES_OUT_SET_GROUP_PCR, /* arg1= int i_group, arg2=int64_t i_pcr(microsecond!)*/
ES_OUT_RESET_PCR, /* no arg */
/* Try not to use this one as it is a bit hacky */
ES_OUT_SET_FMT /* arg1= es_out_id_t* arg2=es_format_t* */
};
struct es_out_t
......
......@@ -215,14 +215,6 @@ static int OpenDecoder( vlc_object_t *p_this )
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;
}
......@@ -236,11 +228,43 @@ static int OpenPacketizer( vlc_object_t *p_this )
i_ret = OpenDecoder( p_this );
/* Set output properties */
p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','a','c');
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
****************************************************************************
......@@ -254,6 +278,8 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
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. */
......
......@@ -82,7 +82,8 @@ static int OpenPacketizer( vlc_object_t * );
static void CloseDecoder ( vlc_object_t * );
static void *DecodeBlock ( decoder_t *, block_t ** );
static int ProcessHeader ( decoder_t *, ogg_packet * );
static int ProcessHeaders( decoder_t * );
static int ProcessInitialHeader ( decoder_t *, ogg_packet * );
static void *ProcessPacket( decoder_t *, ogg_packet *, block_t ** );
static aout_buffer_t *DecodePacket( decoder_t *, ogg_packet * );
......@@ -202,37 +203,116 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
oggpacket.e_o_s = 0;
oggpacket.packetno = 0;
if( p_sys->i_headers == 0 )
/* Check for headers */
if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
{
/* Take care of the initial Speex header */
if( ProcessHeader( p_dec, &oggpacket ) != VLC_SUCCESS )
/* Headers already available as extra data */
p_sys->i_headers = 2;
}
else if( oggpacket.bytes && p_sys->i_headers < 2 )
{
/* Backup headers as extra data */
uint8_t *p_extra;
p_dec->fmt_in.p_extra =
realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra +
oggpacket.bytes + 2 );
p_extra = p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra;
*(p_extra++) = oggpacket.bytes >> 8;
*(p_extra++) = oggpacket.bytes & 0xFF;
memcpy( p_extra, oggpacket.packet, oggpacket.bytes );
p_dec->fmt_in.i_extra += oggpacket.bytes + 2;
block_Release( *pp_block );
p_sys->i_headers++;
return NULL;
}
if( p_sys->i_headers == 2 )
{
if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
{
msg_Err( p_dec, "initial Speex header is corrupted" );
p_sys->i_headers = 0;
p_dec->fmt_in.i_extra = 0;
block_Release( *pp_block );
return NULL;
}
else p_sys->i_headers++;
}
p_sys->i_headers++;
return ProcessPacket( p_dec, &oggpacket, pp_block );
}
/*****************************************************************************
* ProcessHeaders: process Speex headers.
*****************************************************************************/
static int ProcessHeaders( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket;
uint8_t *p_extra;
int i_extra;
if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
return ProcessPacket( p_dec, &oggpacket, pp_block );
oggpacket.granulepos = -1;
oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
oggpacket.e_o_s = 0;
oggpacket.packetno = 0;
p_extra = p_dec->fmt_in.p_extra;
i_extra = p_dec->fmt_in.i_extra;
/* Take care of the initial Vorbis header */
oggpacket.bytes = *(p_extra++) << 8;
oggpacket.bytes |= (*(p_extra++) & 0xFF);
oggpacket.packet = p_extra;
p_extra += oggpacket.bytes;
i_extra -= (oggpacket.bytes + 2);
if( i_extra < 0 )
{
msg_Err( p_dec, "header data corrupted");
return VLC_EGENERIC;
}
if( p_sys->i_headers == 1 )
/* Take care of the initial Speex header */
if( ProcessInitialHeader( p_dec, &oggpacket ) != VLC_SUCCESS )
{
/* The next packet in order is the comments header */
ParseSpeexComments( p_dec, &oggpacket );
p_sys->i_headers++;
msg_Err( p_dec, "initial Speex header is corrupted" );
return VLC_EGENERIC;
}
/* The next packet in order is the comments header */
oggpacket.b_o_s = 0;
oggpacket.bytes = *(p_extra++) << 8;
oggpacket.bytes |= (*(p_extra++) & 0xFF);
oggpacket.packet = p_extra;
p_extra += oggpacket.bytes;
i_extra -= (oggpacket.bytes + 2);
if( i_extra < 0 )
{
msg_Err( p_dec, "header data corrupted");
return VLC_EGENERIC;
}
ParseSpeexComments( p_dec, &oggpacket );
return ProcessPacket( p_dec, &oggpacket, pp_block );
if( p_sys->b_packetizer )
{
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 );
}
return ProcessPacket( p_dec, &oggpacket, pp_block );
return VLC_SUCCESS;
}
/*****************************************************************************
* ProcessHeader: processes the inital Speex header packet.
* ProcessInitialHeader: processes the inital Speex header packet.
*****************************************************************************/
static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
static int ProcessInitialHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
{
decoder_sys_t *p_sys = p_dec->p_sys;
......@@ -350,10 +430,7 @@ static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
else
p_aout_buffer = NULL; /* Skip headers */
if( p_block )
{
block_Release( p_block );
}
if( p_block ) block_Release( p_block );
return p_aout_buffer;
}
}
......@@ -463,6 +540,8 @@ static void ParseSpeexComments( decoder_t *p_dec, ogg_packet *p_oggpacket )
const SpeexMode *p_mode;
int i_len;
if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
p_mode = speex_mode_list[p_sys->p_header->mode];
input_Control( p_input, INPUT_ADD_INFO, _("Speex comment"), _("Mode"),
......@@ -603,9 +682,8 @@ static int OpenEncoder( vlc_object_t *p_this )
pp_header[1] = "ENCODER=VLC media player";
pi_header[1] = sizeof("ENCODER=VLC media player");
p_enc->fmt_out.i_extra = 1 + 3 * 2 + pi_header[0] + pi_header[1];
p_enc->fmt_out.i_extra = 3 * 2 + pi_header[0] + pi_header[1];
p_extra = p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
*(p_extra++) = 2; /* number of headers */
for( i = 0; i < 2; i++ )
{
*(p_extra++) = pi_header[i] >> 8;
......
This diff is collapsed.
......@@ -101,6 +101,7 @@ static int OpenPacketizer( vlc_object_t * );
static void CloseDecoder ( vlc_object_t * );
static void *DecodeBlock ( decoder_t *, block_t ** );
static int ProcessHeaders( decoder_t * );
static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
static aout_buffer_t *DecodePacket ( decoder_t *, ogg_packet * );
......@@ -268,80 +269,153 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
oggpacket.e_o_s = 0;
oggpacket.packetno = 0;
if( p_sys->i_headers == 0 )
/* Check for headers */
if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
{
/* Take care of the initial Vorbis header */
/* Headers already available as extra data */
p_sys->i_headers = 3;
}
else if( oggpacket.bytes && p_sys->i_headers < 3 )
{
/* Backup headers as extra data */
uint8_t *p_extra;
p_dec->fmt_in.p_extra =
realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra +
oggpacket.bytes + 2 );
p_extra = p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra;
*(p_extra++) = oggpacket.bytes >> 8;
*(p_extra++) = oggpacket.bytes & 0xFF;
oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc,
&oggpacket ) < 0 )
memcpy( p_extra, oggpacket.packet, oggpacket.bytes );
p_dec->fmt_in.i_extra += oggpacket.bytes + 2;
block_Release( *pp_block );
p_sys->i_headers++;
return NULL;
}
if( p_sys->i_headers == 3 )
{
if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
{
msg_Err( p_dec, "this bitstream does not contain Vorbis "
"audio data.");
p_sys->i_headers = 0;
p_dec->fmt_in.i_extra = 0;
block_Release( *pp_block );
return NULL;
}
p_sys->i_headers++;
else p_sys->i_headers++;
}
/* Setup the format */
p_dec->fmt_out.audio.i_rate = p_sys->vi.rate;
p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;
p_dec->fmt_out.audio.i_physical_channels =
p_dec->fmt_out.audio.i_original_channels =
pi_channels_maps[p_sys->vi.channels];
p_dec->fmt_out.i_bitrate = p_sys->vi.bitrate_nominal;
return ProcessPacket( p_dec, &oggpacket, pp_block );
}
aout_DateInit( &p_sys->end_date, p_sys->vi.rate );
/*****************************************************************************
* ProcessHeaders: process Vorbis headers.
*****************************************************************************/
static int ProcessHeaders( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
ogg_packet oggpacket;
uint8_t *p_extra;
int i_extra;
msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",
p_sys->vi.channels, p_sys->vi.rate,
p_sys->vi.bitrate_nominal );
if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
return ProcessPacket( p_dec, &oggpacket, pp_block );
oggpacket.granulepos = -1;
oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
oggpacket.e_o_s = 0;
oggpacket.packetno = 0;
p_extra = p_dec->fmt_in.p_extra;
i_extra = p_dec->fmt_in.i_extra;
/* Take care of the initial Vorbis header */
oggpacket.bytes = *(p_extra++) << 8;
oggpacket.bytes |= (*(p_extra++) & 0xFF);
oggpacket.packet = p_extra;
p_extra += oggpacket.bytes;
i_extra -= (oggpacket.bytes + 2);
if( i_extra < 0 )
{
msg_Err( p_dec, "header data corrupted");
return VLC_EGENERIC;
}
if( p_sys->i_headers == 1 )
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
{
/* The next packet in order is the comments header */
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
< 0 )
{
msg_Err( p_dec, "2nd Vorbis header is corrupted" );
block_Release( *pp_block );
return NULL;
}
p_sys->i_headers++;
msg_Err( p_dec, "this bitstream does not contain Vorbis audio data");
return VLC_EGENERIC;
}
ParseVorbisComments( p_dec );
/* Setup the format */
p_dec->fmt_out.audio.i_rate = p_sys->vi.rate;
p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;
p_dec->fmt_out.audio.i_physical_channels =
p_dec->fmt_out.audio.i_original_channels =
pi_channels_maps[p_sys->vi.channels];
p_dec->fmt_out.i_bitrate = p_sys->vi.bitrate_nominal;
aout_DateInit( &p_sys->end_date, p_sys->vi.rate );
aout_DateSet( &p_sys->end_date, 0 );
return ProcessPacket( p_dec, &oggpacket, pp_block );
msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",
p_sys->vi.channels, p_sys->vi.rate, p_sys->vi.bitrate_nominal );
/* The next packet in order is the comments header */
oggpacket.b_o_s = 0;
oggpacket.bytes = *(p_extra++) << 8;
oggpacket.bytes |= (*(p_extra++) & 0xFF);
oggpacket.packet = p_extra;
p_extra += oggpacket.bytes;
i_extra -= (oggpacket.bytes + 2);
if( i_extra < 0 )
{
msg_Err( p_dec, "header data corrupted");
return VLC_EGENERIC;
}
if( p_sys->i_headers == 2 )
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
{
/* The next packet in order is the codebooks header
We need to watch out that this packet is not missing as a
missing or corrupted header is fatal. */
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
< 0 )
{
msg_Err( p_dec, "3rd Vorbis header is corrupted" );
block_Release( *pp_block );
return NULL;
}
p_sys->i_headers++;
msg_Err( p_dec, "2nd Vorbis header is corrupted" );
return VLC_EGENERIC;
}
ParseVorbisComments( p_dec );
/* The next packet in order is the codebooks header
* We need to watch out that this packet is not missing as a
* missing or corrupted header is fatal. */
oggpacket.bytes = *(p_extra++) << 8;
oggpacket.bytes |= (*(p_extra++) & 0xFF);
oggpacket.packet = p_extra;
i_extra -= (oggpacket.bytes + 2);
if( i_extra < 0 )
{
msg_Err( p_dec, "header data corrupted");
return VLC_EGENERIC;
}
if( !p_sys->b_packetizer )
{
/* Initialize the Vorbis packet->PCM decoder */
vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
vorbis_block_init( &p_sys->vd, &p_sys->vb );
}
if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
{
msg_Err( p_dec, "3rd Vorbis header is corrupted" );
return VLC_EGENERIC;
}
return ProcessPacket( p_dec, &oggpacket, pp_block );
if( !p_sys->b_packetizer )
{
/* Initialize the Vorbis packet->PCM decoder */
vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
vorbis_block_init( &p_sys->vd, &p_sys->vb );
}
else
{
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 );
}
return ProcessPacket( p_dec, &oggpacket, pp_block );
return VLC_SUCCESS;
}
/*****************************************************************************
......@@ -382,10 +456,7 @@ static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
else
p_aout_buffer = NULL;
if( p_block )
{
block_Release( p_block );
}
if( p_block ) block_Release( p_block );
return p_aout_buffer;
}
}
......@@ -479,9 +550,12 @@ static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
static void ParseVorbisComments( decoder_t *p_dec )
{
input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
int i = 0;
char *psz_name, *psz_value, *psz_comment;
while ( i < p_dec->p_sys->vc.comments )
int i = 0;
if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
while( i < p_dec->p_sys->vc.comments )
{
psz_comment = strdup( p_dec->p_sys->vc.user_comments[i] );
if( !psz_comment )
......@@ -600,7 +674,7 @@ static int OpenEncoder( vlc_object_t *p_this )
p_enc->p_sys = p_sys;
p_enc->pf_encode_audio = Encode;
p_enc->fmt_in.i_codec = VLC_FOURCC('f','l','3','2');
p_enc->fmt_in.i_codec = AUDIO_FMT_S16_NE;
p_enc->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
......@@ -677,10 +751,9 @@ static int OpenEncoder( vlc_object_t *p_this )
/* Create and store headers */
vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
&header[0], &header[1], &header[2]);
p_enc->fmt_out.i_extra = 1 + 3 * 2 + header[0].bytes +
p_enc->fmt_out.i_extra = 3 * 2 + header[0].bytes +
header[1].bytes + header[2].bytes;
p_extra = p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
*(p_extra++) = 3; /* number of headers */
for( i = 0; i < 3; i++ )
{
*(p_extra++) = header[i].bytes >> 8;
......
......@@ -535,9 +535,41 @@ static int Open( vlc_object_t * p_this )
}
else if( !strcmp( tk.psz_codec, "A_VORBIS" ) )
{
int i, i_offset = 1, i_size[3], i_extra;
uint8_t *p_extra;
tk.fmt.i_codec = VLC_FOURCC( 'v', 'o', 'r', 'b' );
tk.i_data_init = tk.i_extra_data;
tk.p_data_init = tk.p_extra_data;
/* Split the 3 headers */
if( tk.p_extra_data[0] != 0x02 )
msg_Err( p_demux, "invalid vorbis header" );
for( i = 0; i < 2; i++ )
{
i_size[i] = 0;
while( i_offset < tk.i_extra_data )
{
i_size[i] += tk.p_extra_data[i_offset];
if( tk.p_extra_data[i_offset++] != 0xff ) break;
}
}
i_size[0] = __MIN(i_size[0], tk.i_extra_data - i_offset);
i_size[1] = __MIN(i_size[1], tk.i_extra_data -i_offset -i_size[0]);
i_size[2] = tk.i_extra_data - i_offset - i_size[0] - i_size[1];
tk.fmt.i_extra = 3 * 2 + i_size[0] + i_size[1] + i_size[2];
tk.fmt.p_extra = malloc( tk.fmt.i_extra );
p_extra = (uint8_t *)tk.fmt.p_extra; i_extra = 0;
for( i = 0; i < 3; i++ )
{
*(p_extra++) = i_size[i] >> 8;
*(p_extra++) = i_size[i] & 0xFF;
memcpy( p_extra, tk.p_extra_data + i_offset + i_extra,
i_size[i] );
p_extra += i_size[i];
i_extra += i_size[i];
}
}
else if( !strncmp( tk.psz_codec, "A_AAC/MPEG2/", strlen( "A_AAC/MPEG2/" ) ) ||
!strncmp( tk.psz_codec, "A_AAC/MPEG4/", strlen( "A_AAC/MPEG4/" ) ) )
......@@ -915,7 +947,8 @@ static block_t *MemToBlock( demux_t *p_demux, uint8_t *p_mem, int i_mem)
return p_block;
}
static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts, mtime_t i_duration )
static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts,
mtime_t i_duration )
{
demux_sys_t *p_sys = p_demux->p_sys;
......@@ -951,59 +984,8 @@ static void BlockDecode( demux_t *p_demux, KaxBlock *block, mtime_t i_pts, mtime
block_t *p_init;
msg_Dbg( p_demux, "sending header (%d bytes)", tk.i_data_init );
if( tk.fmt.i_codec == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
{
int i;
int i_offset = 1;
int i_size[3];
/* XXX hack split the 3 headers */
if( tk.p_data_init[0] != 0x02 )
{
msg_Err( p_demux, "invalid vorbis header" );
}
for( i = 0; i < 2; i++ )
{
i_size[i] = 0;
while( i_offset < tk.i_data_init )
{
i_size[i] += tk.p_data_init[i_offset];
if( tk.p_data_init[i_offset++] != 0xff )
{
break;
}
}
}
i_size[0] = __MIN( i_size[0], tk.i_data_init - i_offset );
i_size[1] = __MIN( i_size[1], tk.i_data_init - i_offset - i_size[0] );
i_size[2] = tk.i_data_init - i_offset - i_size[0] - i_size[1];
p_init = MemToBlock( p_demux, &tk.p_data_init[i_offset], i_size[0] );
if( p_init )
{
es_out_Send( p_demux->out, tk.p_es, p_init );
}
p_init = MemToBlock( p_demux, &tk.p_data_init[i_offset+i_size[0]], i_size[1] );
if( p_init )
{
es_out_Send( p_demux->out, tk.p_es, p_init );
}
p_init = MemToBlock( p_demux, &tk.p_data_init[i_offset+i_size[0]+i_size[1]], i_size[2] );
if( p_init )
{
es_out_Send( p_demux->out, tk.p_es, p_init );
}
}
else
{
p_init = MemToBlock( p_demux, tk.p_data_init, tk.i_data_init );
if( p_init )
{
es_out_Send( p_demux->out, tk.p_es, p_init );
}
}
p_init = MemToBlock( p_demux, tk.p_data_init, tk.i_data_init );
if( p_init ) es_out_Send( p_demux->out, tk.p_es, p_init );
}
tk.b_inited = VLC_TRUE;
......
This diff is collapsed.
......@@ -5,7 +5,7 @@
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
* Gildas Bazin <gbazin@videolan.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -146,10 +146,7 @@ static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
if( p_mux->pp_inputs[i]->p_fmt->i_cat == SPU_ES &&
p_fifo->i_depth == 0 ) continue;
if( p_fifo->i_depth > 2 ||
/* Special case for SPUs */
( p_mux->pp_inputs[i]->p_fmt->i_cat == SPU_ES &&
p_fifo->i_depth > 0 ) )
if( p_fifo->i_depth )
{
block_t *p_buf;
......@@ -160,11 +157,8 @@ static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
i_stream = i;
}
}
else
{
// wait that all fifo have at least 3 packets (3 vorbis headers)
return -1;
}
else return -1;
}
if( pi_stream )
{
......@@ -196,9 +190,6 @@ typedef struct
oggds_header_t *p_oggds_header;
block_t *pp_sout_headers[3];
int i_sout_headers;
} ogg_stream_t;
struct sout_mux_sys_t
......@@ -336,7 +327,6 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
p_stream->i_serial_no = p_sys->i_next_serial_no++;
p_stream->i_packet_no = 0;
p_stream->i_sout_headers = 0;
p_stream->p_oggds_header = 0;
switch( p_input->p_fmt->i_cat )
......@@ -437,7 +427,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
if( p_input->p_fmt->i_extra )
{
memcpy( &p_stream->p_oggds_header[1],
p_input->p_fmt->p_extra, p_input->p_fmt->i_extra );
p_input->p_fmt->p_extra, p_input->p_fmt->i_extra );
}
memcpy( p_stream->p_oggds_header->stream_type, "audio", 5 );
......@@ -506,8 +496,6 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
/* flush all remaining data */
if( p_input->p_sys )
{
int i;
if( !p_stream->b_new &&
( p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ) ) )
{
......@@ -515,12 +503,6 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
sout_AccessOutWrite( p_mux->p_access, p_og );
}
for( i = 0; i < p_stream->i_sout_headers; i++ )
{
block_Release( p_stream->pp_sout_headers[i] );
p_stream->i_sout_headers = 0;
}
/* move input in delete queue */
if( !p_stream->b_new )
{
......@@ -601,13 +583,15 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
block_t *p_hdr = NULL;
block_t *p_og = NULL;
ogg_packet op;
int i;
uint8_t *p_extra;
int i, i_extra;
/* Write header for each stream. All b_o_s (beginning of stream) packets
* must appear first in the ogg stream so we take care of them first. */
for( i = 0; i < p_mux->i_nb_inputs; i++ )
{
ogg_stream_t *p_stream = (ogg_stream_t*)p_mux->pp_inputs[i]->p_sys;
sout_input_t *p_input = p_mux->pp_inputs[i];
ogg_stream_t *p_stream = (ogg_stream_t*)p_input->p_sys;
p_stream->b_new = VLC_FALSE;
msg_Dbg( p_mux, "creating header for %4.4s",
......@@ -620,25 +604,26 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ||
p_stream->i_fourcc == VLC_FOURCC( 't', 'h', 'e', 'o' ) )
{
/* Special case, headers are already there in the
* incoming stream or we backed them up earlier */
/* first packet in order: vorbis/speex/theora info */
if( !p_stream->i_sout_headers )
/* First packet in order: vorbis/speex/theora info */
p_extra = p_input->p_fmt->p_extra;
i_extra = p_input->p_fmt->i_extra;
op.bytes = *(p_extra++) << 8;
op.bytes |= (*(p_extra++) & 0xFF);
op.packet = p_extra;
i_extra -= (op.bytes + 2);
if( i_extra < 0 )
{
p_og = block_FifoGet( p_mux->pp_inputs[i]->p_fifo );
op.packet = p_og->p_buffer;
op.bytes = p_og->i_buffer;
op.b_o_s = 1;
op.e_o_s = 0;
op.granulepos = 0;
op.packetno = p_stream->i_packet_no++;
ogg_stream_packetin( &p_stream->os, &op );
p_stream->pp_sout_headers[0] =
OggStreamFlush( p_mux, &p_stream->os, 0 );
p_stream->i_sout_headers++;
msg_Err( p_mux, "header data corrupted");
op.bytes += i_extra;
}
p_og = block_Duplicate( p_stream->pp_sout_headers[0] );
op.b_o_s = 1;
op.e_o_s = 0;
op.granulepos = 0;
op.packetno = p_stream->i_packet_no++;
ogg_stream_packetin( &p_stream->os, &op );
p_og = OggStreamFlush( p_mux, &p_stream->os, 0 );
/* Get keyframe_granule_shift for theora granulepos calculation */
if( p_stream->i_fourcc == VLC_FOURCC( 't', 'h', 'e', 'o' ) )
......@@ -687,7 +672,8 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
/* Take care of the non b_o_s headers */
for( i = 0; i < p_mux->i_nb_inputs; i++ )
{
ogg_stream_t *p_stream = (ogg_stream_t*)p_mux->pp_inputs[i]->p_sys;
sout_input_t *p_input = p_mux->pp_inputs[i];
ogg_stream_t *p_stream = (ogg_stream_t*)p_input->p_sys;
if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) ||
p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ||
......@@ -695,26 +681,40 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
{
/* Special case, headers are already there in the incoming stream.
* We need to gather them an mark them as headers. */
int j;
for( j = 0; j < 2; j++ )
int j = 2;
if( p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ) j = 1;
p_extra = p_input->p_fmt->p_extra;
i_extra = p_input->p_fmt->i_extra;
/* Skip 1 header */
op.bytes = *(p_extra++) << 8;
op.bytes |= (*(p_extra++) & 0xFF);
op.packet = p_extra;
p_extra += op.bytes;
i_extra -= (op.bytes + 2);
while( j-- )
{
if( p_stream->i_sout_headers < j + 2 )
op.bytes = *(p_extra++) << 8;
op.bytes |= (*(p_extra++) & 0xFF);
op.packet = p_extra;
p_extra += op.bytes;
i_extra -= (op.bytes + 2);
if( i_extra < 0 )
{
/* next packets in order: comments and codebooks */
p_og = block_FifoGet( p_mux->pp_inputs[i]->p_fifo );
op.packet = p_og->p_buffer;
op.bytes = p_og->i_buffer;
op.b_o_s = 0;
op.e_o_s = 0;
op.granulepos = 0;
op.packetno = p_stream->i_packet_no++;
ogg_stream_packetin( &p_stream->os, &op );
p_stream->pp_sout_headers[j+1] =
OggStreamFlush( p_mux, &p_stream->os, 0 );
p_stream->i_sout_headers++;
msg_Err( p_mux, "header data corrupted");
op.bytes += i_extra;
}
p_og = block_Duplicate( p_stream->pp_sout_headers[j+1] );
op.b_o_s = 0;
op.e_o_s = 0;
op.granulepos = 0;
op.packetno = p_stream->i_packet_no++;
ogg_stream_packetin( &p_stream->os, &op );
p_og = OggStreamFlush( p_mux, &p_stream->os, 0 );
block_ChainAppend( &p_hdr, p_og );
}
}
......@@ -741,13 +741,13 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
/* Special case for mp4v and flac */
if( ( p_stream->i_fourcc == VLC_FOURCC( 'm', 'p', '4', 'v' ) ||
p_stream->i_fourcc == VLC_FOURCC( 'f', 'l', 'a', 'c' ) ) &&
p_mux->pp_inputs[i]->p_fmt->i_extra )
p_input->p_fmt->i_extra )
{
/* Send a packet with the VOL data for mp4v
* or STREAMINFO for flac */
msg_Dbg( p_mux, "writing extra data" );
op.bytes = p_mux->pp_inputs[i]->p_fmt->i_extra;
op.packet = p_mux->pp_inputs[i]->p_fmt->p_extra;
op.bytes = p_input->p_fmt->i_extra;
op.packet = p_input->p_fmt->p_extra;
if( p_stream->i_fourcc == VLC_FOURCC( 'f', 'l', 'a', 'c' ) )
{
/* Skip the flac stream marker */
......
......@@ -991,6 +991,30 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
return VLC_EGENERIC;
}
case ES_OUT_SET_FMT:
{
/* This ain't pretty but is need by some demuxers (eg. Ogg )
* to update the p_extra data */
es = (es_out_id_t*) va_arg( args, es_out_id_t * );
es_format_t *p_fmt = (es_format_t*) va_arg( args, es_format_t * );
if( es == NULL || !es->p_dec ) return VLC_EGENERIC;
if( p_fmt->i_extra )
{
es->fmt.i_extra = p_fmt->i_extra;
es->fmt.p_extra = realloc( es->fmt.p_extra, p_fmt->i_extra );
memcpy( es->fmt.p_extra, p_fmt->p_extra, p_fmt->i_extra );
es->p_dec->fmt_in.i_extra = p_fmt->i_extra;
es->p_dec->fmt_in.p_extra =
realloc( es->p_dec->fmt_in.p_extra, p_fmt->i_extra );
memcpy( es->p_dec->fmt_in.p_extra,
p_fmt->p_extra, p_fmt->i_extra );
}
return VLC_SUCCESS;
}
default:
msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
return VLC_EGENERIC;
......
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