* $Id$
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
- * Gildas Bazin <gbazin@netcourrier.com>
+ * Gildas Bazin <gbazin@videolan.org>
* Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
static void vout_link_picture( decoder_t *, picture_t * );
static void vout_unlink_picture( decoder_t *, picture_t * );
+static subpicture_t *spu_new_buffer( decoder_t * );
+static void spu_del_buffer( decoder_t *, subpicture_t * );
+
static es_format_t null_es_format = {0};
struct decoder_owner_sys_t
vout_thread_t *p_vout;
+ vout_thread_t *p_spu_vout;
+ int i_spu_channel;
+
sout_instance_t *p_sout;
sout_packetizer_input_t *p_sout_input;
}
else
{
- if( p_dec->b_error || p_block->i_buffer <= 0 )
+ if( p_dec->b_error || (p_block && p_block->i_buffer <= 0) )
{
- block_Release( p_block );
+ if( p_block ) block_Release( p_block );
}
else
{
p_dec->p_owner->p_aout = NULL;
p_dec->p_owner->p_aout_input = NULL;
p_dec->p_owner->p_vout = NULL;
+ p_dec->p_owner->p_spu_vout = NULL;
+ p_dec->p_owner->i_spu_channel = 0;
p_dec->p_owner->p_sout = p_input->p_sout;
p_dec->p_owner->p_sout_input = NULL;
p_dec->p_owner->p_packetizer = NULL;
-
/* decoder fifo */
if( ( p_dec->p_owner->p_fifo = block_FifoNew( p_dec ) ) == NULL )
{
msg_Err( p_dec, "out of memory" );
return NULL;
}
+
/* Set buffers allocation callbacks for the decoders */
p_dec->pf_aout_buffer_new = aout_new_buffer;
p_dec->pf_aout_buffer_del = aout_del_buffer;
p_dec->pf_vout_buffer_del = vout_del_buffer;
p_dec->pf_picture_link = vout_link_picture;
p_dec->pf_picture_unlink = vout_unlink_picture;
+ p_dec->pf_spu_buffer_new = spu_new_buffer;
+ p_dec->pf_spu_buffer_del = spu_del_buffer;
vlc_object_attach( p_dec, p_input );
*/
static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
{
- if( p_block->i_buffer <= 0 )
+ int i_rate = p_block ? p_block->i_rate : 1000;
+
+ if( p_block && p_block->i_buffer <= 0 )
{
block_Release( p_block );
return VLC_SUCCESS;
{
block_t *p_sout_block;
- while( (p_sout_block = p_dec->pf_packetize( p_dec, &p_block )) )
+ while( ( p_sout_block =
+ p_dec->pf_packetize( p_dec, p_block ? &p_block : 0 ) ) )
{
if( !p_dec->p_owner->p_sout_input )
{
es_format_Copy( &p_dec->p_owner->sout, &p_dec->fmt_out );
- p_dec->p_owner->sout.i_group =p_dec->fmt_in.i_group;
+ p_dec->p_owner->sout.i_group = p_dec->fmt_in.i_group;
p_dec->p_owner->sout.i_id = p_dec->fmt_in.i_id;
if( p_dec->fmt_in.psz_language )
{
while( p_sout_block )
{
- block_t *p_next = p_sout_block->p_next;
+ block_t *p_next = p_sout_block->p_next;
p_sout_block->p_next = NULL;
+ p_sout_block->i_rate = i_rate;
sout_InputSendBuffer( p_dec->p_owner->p_sout_input,
p_sout_block );
while( (p_packetized_block =
p_packetizer->pf_packetize( p_packetizer, &p_block )) )
{
- while( (p_aout_buf =
- p_dec->pf_decode_audio( p_dec, &p_packetized_block )) )
+ while( p_packetized_block )
{
- aout_DecPlay( p_dec->p_owner->p_aout,
- p_dec->p_owner->p_aout_input, p_aout_buf );
+ block_t *p_next = p_packetized_block->p_next;
+ p_packetized_block->p_next = NULL;
+ p_packetized_block->i_rate = i_rate;
+
+ while( (p_aout_buf = p_dec->pf_decode_audio( p_dec,
+ &p_packetized_block )) )
+ {
+ aout_DecPlay( p_dec->p_owner->p_aout,
+ p_dec->p_owner->p_aout_input,
+ p_aout_buf );
+ }
+
+ p_packetized_block = p_next;
}
}
}
while( (p_packetized_block =
p_packetizer->pf_packetize( p_packetizer, &p_block )) )
{
- while( (p_pic =
- p_dec->pf_decode_video( p_dec, &p_packetized_block )) )
+ while( p_packetized_block )
{
- vout_DatePicture( p_dec->p_owner->p_vout, p_pic,
- p_pic->date );
- vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
+ block_t *p_next = p_packetized_block->p_next;
+ p_packetized_block->p_next = NULL;
+ p_packetized_block->i_rate = i_rate;
+
+ while( (p_pic = p_dec->pf_decode_video( p_dec,
+ &p_packetized_block )) )
+ {
+ vout_DatePicture( p_dec->p_owner->p_vout, p_pic,
+ p_pic->date );
+ vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
+ }
+
+ p_packetized_block = p_next;
}
}
}
}
else if( p_dec->fmt_in.i_cat == SPU_ES )
{
- p_dec->pf_decode_sub( p_dec, &p_block );
+ vout_thread_t *p_vout;
+ subpicture_t *p_spu;
+ while( (p_spu = p_dec->pf_decode_sub( p_dec, &p_block ) ) )
+ {
+ p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ if( p_vout )
+ {
+ vout_DisplaySubPicture( p_vout, p_spu );
+ vlc_object_release( p_vout );
+ }
+ }
}
else
{
*/
static void DeleteDecoder( decoder_t * p_dec )
{
- vlc_object_detach( p_dec );
-
msg_Dbg( p_dec, "killing decoder fourcc `%4.4s', %d PES in FIFO",
(char*)&p_dec->fmt_in.i_codec,
p_dec->p_owner->p_fifo->i_depth );
block_FifoEmpty( p_dec->p_owner->p_fifo );
block_FifoRelease( p_dec->p_owner->p_fifo );
- /* Cleanup */
+ /* Cleanup */
if( p_dec->p_owner->p_aout_input )
aout_DecDelete( p_dec->p_owner->p_aout, p_dec->p_owner->p_aout_input );
es_format_Clean( &p_dec->p_owner->sout );
}
+ if( p_dec->fmt_in.i_cat == SPU_ES )
+ {
+ vout_thread_t *p_vout;
+
+ p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ if( p_vout )
+ {
+ vout_ClearOSDChannel( p_vout, p_dec->p_owner->i_spu_channel );
+ vlc_object_release( p_vout );
+ }
+ }
+
es_format_Clean( &p_dec->fmt_in );
es_format_Clean( &p_dec->fmt_out );
vlc_object_destroy( p_dec->p_owner->p_packetizer );
}
+ vlc_object_detach( p_dec );
+
free( p_dec->p_owner );
}
p_dec->b_error = VLC_TRUE;
return NULL;
}
+
+ if( p_sys->video.i_rmask )
+ p_sys->p_vout->render.i_rmask = p_sys->video.i_rmask;
+ if( p_sys->video.i_gmask )
+ p_sys->p_vout->render.i_gmask = p_sys->video.i_gmask;
+ if( p_sys->video.i_bmask )
+ p_sys->p_vout->render.i_bmask = p_sys->video.i_bmask;
}
/* Get a new picture */
{
vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic );
}
+
+static subpicture_t *spu_new_buffer( decoder_t *p_dec )
+{
+ decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
+ vout_thread_t *p_vout = NULL;
+ subpicture_t *p_spu;
+ int i_attempts = 30;
+
+ while( i_attempts-- )
+ {
+ if( p_dec->b_die || p_dec->b_error ) break;
+
+ p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
+ if( p_vout ) break;
+
+ msleep( VOUT_DISPLAY_DELAY );
+ }
+
+ if( !p_vout )
+ {
+ msg_Warn( p_dec, "no vout found, dropping subpicture" );
+ return NULL;
+ }
+
+ if( p_sys->p_spu_vout != p_vout )
+ {
+ p_sys->i_spu_channel =
+ vout_RegisterOSDChannel( p_vout );
+ p_sys->p_spu_vout = p_vout;
+ }
+
+ p_spu = vout_CreateSubPicture( p_vout, p_sys->i_spu_channel,
+ MEMORY_SUBPICTURE );
+
+ vlc_object_release( p_vout );
+
+ return p_spu;
+}
+
+static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_spu )
+{
+ vout_DestroySubPicture( p_dec->p_owner->p_vout, p_spu );
+}