Commit 492dfdd5 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

decoder: separate aout initialization from buffer allocation

This has two benefits:
 - allow zero copy in audio decoders,
 - allow negotiation of the output formats (potentially for S/PDIF).
parent fc297771
...@@ -108,9 +108,8 @@ struct decoder_t ...@@ -108,9 +108,8 @@ struct decoder_t
*/ */
int i_extra_picture_buffers; int i_extra_picture_buffers;
/* Audio output callbacks /* Audio output callbacks */
* XXX use decoder_NewAudioBuffer/decoder_DeleteAudioBuffer */ int (*pf_aout_format_update)( decoder_t * );
block_t *(*pf_aout_buffer_new)( decoder_t *, int );
/* SPU output callbacks /* SPU output callbacks
* XXX use decoder_NewSubpicture and decoder_DeleteSubpicture */ * XXX use decoder_NewSubpicture and decoder_DeleteSubpicture */
...@@ -204,6 +203,19 @@ VLC_API void decoder_LinkPicture( decoder_t *, picture_t * ); ...@@ -204,6 +203,19 @@ VLC_API void decoder_LinkPicture( decoder_t *, picture_t * );
*/ */
VLC_API void decoder_UnlinkPicture( decoder_t *, picture_t * ); VLC_API void decoder_UnlinkPicture( decoder_t *, picture_t * );
/**
* This function notifies the audio output pipeline of a new audio output
* format (fmt_out.audio). If there is currently no audio output or if the
* audio output format has changed, a new audio output will be set up.
* @return 0 if the audio output is working, -1 if not. */
static inline int decoder_UpdateAudioFormat( decoder_t *dec )
{
if( dec->pf_aout_format_update != NULL )
return dec->pf_aout_format_update( dec );
else
return -1;
}
/** /**
* This function will return a new audio buffer usable by a decoder as an * This function will return a new audio buffer usable by a decoder as an
* output buffer. You have to release it using decoder_DeleteAudioBuffer * output buffer. You have to release it using decoder_DeleteAudioBuffer
......
...@@ -46,30 +46,10 @@ static const int pi_channels_maps[6] = ...@@ -46,30 +46,10 @@ static const int pi_channels_maps[6] =
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
}; };
static block_t *audio_new_buffer( decoder_t *p_dec, int i_samples ) static int audio_update_format( decoder_t *p_dec )
{ {
block_t *p_block; aout_FormatPrepare( &p_dec->fmt_out.audio );
int i_size; return 0;
if( p_dec->fmt_out.audio.i_bitspersample )
{
i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 *
p_dec->fmt_out.audio.i_channels;
}
else if( p_dec->fmt_out.audio.i_bytes_per_frame &&
p_dec->fmt_out.audio.i_frame_length )
{
i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame /
p_dec->fmt_out.audio.i_frame_length;
}
else
{
i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels;
}
p_block = block_Alloc( i_size );
p_block->i_nb_samples = i_samples;
return p_block;
} }
int transcode_audio_new( sout_stream_t *p_stream, int transcode_audio_new( sout_stream_t *p_stream,
...@@ -87,7 +67,7 @@ int transcode_audio_new( sout_stream_t *p_stream, ...@@ -87,7 +67,7 @@ int transcode_audio_new( sout_stream_t *p_stream,
id->p_decoder->fmt_out.i_extra = 0; id->p_decoder->fmt_out.i_extra = 0;
id->p_decoder->fmt_out.p_extra = 0; id->p_decoder->fmt_out.p_extra = 0;
id->p_decoder->pf_decode_audio = NULL; id->p_decoder->pf_decode_audio = NULL;
id->p_decoder->pf_aout_buffer_new = audio_new_buffer; id->p_decoder->pf_aout_format_update = audio_update_format;
/* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */ /* id->p_decoder->p_cfg = p_sys->p_audio_cfg; */
id->p_decoder->p_module = id->p_decoder->p_module =
......
...@@ -69,13 +69,11 @@ static void DecoderFlushBuffering( decoder_t * ); ...@@ -69,13 +69,11 @@ static void DecoderFlushBuffering( decoder_t * );
static void DecoderUnsupportedCodec( decoder_t *, vlc_fourcc_t ); static void DecoderUnsupportedCodec( decoder_t *, vlc_fourcc_t );
/* Buffers allocation callbacks for the decoders */ /* Buffers allocation callbacks for the decoders */
static block_t *aout_new_buffer( decoder_t *, int );
static picture_t *vout_new_buffer( decoder_t * ); static picture_t *vout_new_buffer( decoder_t * );
static void vout_del_buffer( decoder_t *, picture_t * ); static void vout_del_buffer( decoder_t *, picture_t * );
static void vout_link_picture( decoder_t *, picture_t * ); static void vout_link_picture( decoder_t *, picture_t * );
static void vout_unlink_picture( decoder_t *, picture_t * ); static void vout_unlink_picture( decoder_t *, picture_t * );
static int aout_update_format( decoder_t * );
static subpicture_t *spu_new_buffer( decoder_t *, const subpicture_updater_t * ); static subpicture_t *spu_new_buffer( decoder_t *, const subpicture_updater_t * );
static void spu_del_buffer( decoder_t *, subpicture_t * ); static void spu_del_buffer( decoder_t *, subpicture_t * );
...@@ -206,11 +204,20 @@ void decoder_UnlinkPicture( decoder_t *p_decoder, picture_t *p_picture ) ...@@ -206,11 +204,20 @@ void decoder_UnlinkPicture( decoder_t *p_decoder, picture_t *p_picture )
p_decoder->pf_picture_unlink( p_decoder, p_picture ); p_decoder->pf_picture_unlink( p_decoder, p_picture );
} }
block_t *decoder_NewAudioBuffer( decoder_t *p_decoder, int i_size ) block_t *decoder_NewAudioBuffer( decoder_t *dec, int samples )
{ {
if( !p_decoder->pf_aout_buffer_new ) if( decoder_UpdateAudioFormat( dec ) )
return NULL; return NULL;
return p_decoder->pf_aout_buffer_new( p_decoder, i_size );
size_t length = samples * dec->fmt_out.audio.i_bytes_per_frame
/ dec->fmt_out.audio.i_frame_length;
block_t *block = block_Alloc( length );
if( likely(block != NULL) )
{
block->i_nb_samples = samples;
block->i_pts = block->i_length = 0;
}
return block;
} }
subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder, subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder,
...@@ -795,7 +802,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent, ...@@ -795,7 +802,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
} }
/* Set buffers allocation callbacks for the decoders */ /* Set buffers allocation callbacks for the decoders */
p_dec->pf_aout_buffer_new = aout_new_buffer; p_dec->pf_aout_format_update = aout_update_format;
p_dec->pf_vout_buffer_new = vout_new_buffer; p_dec->pf_vout_buffer_new = vout_new_buffer;
p_dec->pf_vout_buffer_del = vout_del_buffer; p_dec->pf_vout_buffer_del = vout_del_buffer;
p_dec->pf_picture_link = vout_link_picture; p_dec->pf_picture_link = vout_link_picture;
...@@ -2177,7 +2184,7 @@ static vout_thread_t *aout_request_vout( void *p_private, ...@@ -2177,7 +2184,7 @@ static vout_thread_t *aout_request_vout( void *p_private,
return p_vout; return p_vout;
} }
static block_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) static int aout_update_format( decoder_t *p_dec )
{ {
decoder_owner_sys_t *p_owner = p_dec->p_owner; decoder_owner_sys_t *p_owner = p_dec->p_owner;
block_t *p_buffer; block_t *p_buffer;
...@@ -2207,6 +2214,7 @@ static block_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) ...@@ -2207,6 +2214,7 @@ static block_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec; p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
p_owner->audio = p_dec->fmt_out.audio; p_owner->audio = p_dec->fmt_out.audio;
aout_FormatPrepare( &p_owner->audio );
memcpy( &format, &p_owner->audio, sizeof( audio_sample_format_t ) ); memcpy( &format, &p_owner->audio, sizeof( audio_sample_format_t ) );
if( i_force_dolby && if( i_force_dolby &&
...@@ -2232,7 +2240,6 @@ static block_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) ...@@ -2232,7 +2240,6 @@ static block_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
p_aout = input_resource_GetAout( p_owner->p_resource ); p_aout = input_resource_GetAout( p_owner->p_resource );
if( p_aout ) if( p_aout )
{ {
aout_FormatPrepare( &format );
if( aout_DecNew( p_aout, &format, if( aout_DecNew( p_aout, &format,
&p_dec->fmt_out.audio_replay_gain, &p_dec->fmt_out.audio_replay_gain,
&request_vout ) ) &request_vout ) )
...@@ -2258,23 +2265,14 @@ static block_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) ...@@ -2258,23 +2265,14 @@ static block_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
{ {
msg_Err( p_dec, "failed to create audio output" ); msg_Err( p_dec, "failed to create audio output" );
p_dec->b_error = true; p_dec->b_error = true;
return NULL; return -1;
} }
aout_FormatPrepare( &p_owner->audio );
p_dec->fmt_out.audio.i_bytes_per_frame = p_dec->fmt_out.audio.i_bytes_per_frame =
p_owner->audio.i_bytes_per_frame; p_owner->audio.i_bytes_per_frame;
p_dec->fmt_out.audio.i_frame_length = p_owner->audio.i_frame_length;
} }
return 0;
size_t length = i_samples * p_owner->audio.i_bytes_per_frame
/ p_owner->audio.i_frame_length;
block_t *block = block_Alloc( length );
if( likely(block != NULL) )
{
block->i_nb_samples = i_samples;
block->i_pts = block->i_length = 0;
}
return block;
} }
static picture_t *vout_new_buffer( decoder_t *p_dec ) static picture_t *vout_new_buffer( decoder_t *p_dec )
......
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