X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Fdecoder.c;h=9c0aa3dab3dbd9996994ca42f8c06878d3b18f8a;hb=c20f0e81f033223e2ec2066b5c9a9c10a2b97e6e;hp=b795c7cba52cf2dc83746825f299d1d80332e4ca;hpb=c5c06b64c806052086e5772d64e540a8db7e4a9b;p=vlc diff --git a/src/input/decoder.c b/src/input/decoder.c index b795c7cba5..9c0aa3dab3 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include @@ -75,7 +75,7 @@ static void vout_del_buffer( decoder_t *, picture_t * ); 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 subpicture_t *spu_new_buffer( decoder_t *, const subpicture_updater_t * ); static void spu_del_buffer( decoder_t *, subpicture_t * ); struct decoder_owner_sys_t @@ -213,13 +213,15 @@ void decoder_DeleteAudioBuffer( decoder_t *p_decoder, aout_buffer_t *p_buffer ) p_decoder->pf_aout_buffer_del( p_decoder, p_buffer ); } -subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder ) +subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder, + const subpicture_updater_t *p_dyn ) { - subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder ); + subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder, p_dyn ); if( !p_subpicture ) msg_Warn( p_decoder, "can't get output subpicture" ); return p_subpicture; } + void decoder_DeleteSubpicture( decoder_t *p_decoder, subpicture_t *p_subpicture ) { p_decoder->pf_spu_buffer_del( p_decoder, p_subpicture ); @@ -286,7 +288,6 @@ decoder_t *input_DecoderNew( input_thread_t *p_input, DecoderUnsupportedCodec( p_dec, fmt->i_codec ); DeleteDecoder( p_dec ); - vlc_object_release( p_dec ); return NULL; } @@ -304,7 +305,6 @@ decoder_t *input_DecoderNew( input_thread_t *p_input, msg_Err( p_dec, "cannot spawn decoder thread" ); module_unneed( p_dec, p_dec->p_module ); DeleteDecoder( p_dec ); - vlc_object_release( p_dec ); return NULL; } @@ -346,11 +346,8 @@ void input_DecoderDelete( decoder_t *p_dec ) input_DecoderSetCcState( p_dec, false, i ); } - /* Delete decoder configuration */ + /* Delete decoder */ DeleteDecoder( p_dec ); - - /* Delete the decoder */ - vlc_object_release( p_dec ); } /** @@ -373,7 +370,11 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace ) if( !p_owner->b_buffering ) block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX ); } - else if( block_FifoSize( p_owner->p_fifo ) > 50000000 /* 50 MB */ ) +#ifdef __arm__ + else if( block_FifoSize( p_owner->p_fifo ) > 50*1024*1024 /* 50 MiB */ ) +#else + else if( block_FifoSize( p_owner->p_fifo ) > 400*1024*1024 /* 400 MiB, ie ~ 50mb/s for 60s */ ) +#endif { /* FIXME: ideally we would check the time amount of data * in the FIFO instead of its size. */ @@ -387,10 +388,19 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace ) bool input_DecoderIsEmpty( decoder_t * p_dec ) { - assert( !p_dec->p_owner->b_buffering ); + decoder_owner_sys_t *p_owner = p_dec->p_owner; + assert( !p_owner->b_buffering ); - /* FIXME that's not really true */ - return block_FifoCount( p_dec->p_owner->p_fifo ) <= 0; + bool b_empty = block_FifoCount( p_dec->p_owner->p_fifo ) <= 0; + if( b_empty ) + { + vlc_mutex_lock( &p_owner->lock ); + /* TODO audio support */ + if( p_dec->fmt_out.i_cat == VIDEO_ES && p_owner->p_vout ) + b_empty = vout_IsEmpty( p_owner->p_vout ); + vlc_mutex_unlock( &p_owner->lock ); + } + return b_empty; } void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] ) @@ -436,7 +446,6 @@ int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel ) { DecoderUnsupportedCodec( p_dec, fcc[i_channel] ); DeleteDecoder( p_cc ); - vlc_object_release( p_cc ); return VLC_EGENERIC; } p_cc->p_owner->p_clock = p_owner->p_clock; @@ -459,7 +468,6 @@ int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel ) vlc_object_kill( p_cc ); module_unneed( p_cc, p_cc->p_module ); DeleteDecoder( p_cc ); - vlc_object_release( p_cc ); } } return VLC_SUCCESS; @@ -620,6 +628,26 @@ bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_me return b_changed; } +size_t input_DecoderGetFifoSize( decoder_t *p_dec ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + + return block_FifoSize( p_owner->p_fifo ); +} + +void input_DecoderGetObjects( decoder_t *p_dec, + vout_thread_t **pp_vout, aout_instance_t **pp_aout ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + + vlc_mutex_lock( &p_owner->lock ); + if( pp_vout ) + *pp_vout = p_owner->p_vout ? vlc_object_hold( p_owner->p_vout ) : NULL; + if( pp_aout ) + *pp_aout = p_owner->p_aout ? vlc_object_hold( p_owner->p_aout ) : NULL; + vlc_mutex_unlock( &p_owner->lock ); +} + /***************************************************************************** * Internal functions *****************************************************************************/ @@ -659,7 +687,7 @@ static int DecoderGetDisplayRate( decoder_t *p_dec ) /* */ static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec ) { - msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n" + msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'. " "VLC probably does not support this sound or video format.", (char*)&codec ); dialog_Fatal( p_dec, _("No suitable decoder module"), @@ -685,7 +713,8 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, decoder_owner_sys_t *p_owner; es_format_t null_es_format; - p_dec = vlc_object_create( p_input, VLC_OBJECT_DECODER ); + p_dec = vlc_custom_create( p_input, sizeof( *p_dec ), VLC_OBJECT_DECODER, + "decoder" ); if( p_dec == NULL ) return NULL; @@ -760,7 +789,8 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized ) { p_dec->p_owner->p_packetizer = - vlc_object_create( p_input, VLC_OBJECT_DECODER ); + vlc_custom_create( p_input, sizeof( decoder_t ), + VLC_OBJECT_DECODER, "packetizer" ); if( p_dec->p_owner->p_packetizer ) { es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_in, @@ -778,7 +808,6 @@ static decoder_t * CreateDecoder( input_thread_t *p_input, if( !p_dec->p_owner->p_packetizer->p_module ) { es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in ); - vlc_object_detach( p_dec->p_owner->p_packetizer ); vlc_object_release( p_dec->p_owner->p_packetizer ); } } @@ -1071,6 +1100,35 @@ static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1, } } +/** + * If *pb_reject, it does nothing, otherwise it waits for the given + * deadline or a flush request (in which case it set *pi_reject to true. + */ +static void DecoderWaitDate( decoder_t *p_dec, + bool *pb_reject, mtime_t i_deadline ) +{ + decoder_owner_sys_t *p_owner = p_dec->p_owner; + + if( *pb_reject || i_deadline < 0 ) + return; + + for( ;; ) + { + vlc_mutex_lock( &p_owner->lock ); + if( p_owner->b_flushing || p_dec->b_die ) + { + *pb_reject = true; + vlc_mutex_unlock( &p_owner->lock ); + break; + } + int i_ret = vlc_cond_timedwait( &p_owner->wait_request, &p_owner->lock, + i_deadline ); + vlc_mutex_unlock( &p_owner->lock ); + if( i_ret ) + break; + } +} + static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio, int *pi_played_sum, int *pi_lost_sum ) { @@ -1079,7 +1137,7 @@ static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio, aout_input_t *p_aout_input = p_owner->p_aout_input; /* */ - if( p_audio->start_date <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify audio_output/* + if( p_audio->i_pts <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify audio_output/* { msg_Warn( p_dec, "non-dated audio buffer received" ); *pi_lost_sum += 1; @@ -1099,7 +1157,7 @@ static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio, p_owner->buffer.i_count++; if( p_owner->buffer.i_count > DECODER_MAX_BUFFERING_COUNT || - p_audio->start_date - p_owner->buffer.p_audio->start_date > DECODER_MAX_BUFFERING_AUDIO_DURATION ) + p_audio->i_pts - p_owner->buffer.p_audio->i_pts > DECODER_MAX_BUFFERING_AUDIO_DURATION ) { p_owner->buffer.b_full = true; vlc_cond_signal( &p_owner->wait_acknowledge ); @@ -1132,34 +1190,22 @@ static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio, } /* */ - const bool b_dated = p_audio->start_date > VLC_TS_INVALID; + const bool b_dated = p_audio->i_pts > VLC_TS_INVALID; int i_rate = INPUT_RATE_DEFAULT; - DecoderFixTs( p_dec, &p_audio->start_date, &p_audio->end_date, NULL, + DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length, &i_rate, AOUT_MAX_ADVANCE_TIME, false ); vlc_mutex_unlock( &p_owner->lock ); if( !p_aout || !p_aout_input || - p_audio->start_date <= VLC_TS_INVALID || + p_audio->i_pts <= VLC_TS_INVALID || i_rate < INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE || i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE ) b_reject = true; - /* Do not wait against unprotected date */ - const mtime_t i_deadline = p_audio->start_date - AOUT_MAX_PREPARE_TIME; - while( !b_reject && i_deadline > mdate() ) - { - vlc_mutex_lock( &p_owner->lock ); - if( p_owner->b_flushing || p_dec->b_die ) - { - b_reject = true; - vlc_mutex_unlock( &p_owner->lock ); - break; - } - vlc_cond_timedwait( &p_owner->wait_request, &p_owner->lock, i_deadline ); - vlc_mutex_unlock( &p_owner->lock ); - } + DecoderWaitDate( p_dec, &b_reject, + p_audio->i_pts - AOUT_MAX_PREPARE_TIME ); if( !b_reject ) { @@ -1215,7 +1261,7 @@ static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block ) i_decoded++; if( p_owner->i_preroll_end > VLC_TS_INVALID && - p_aout_buf->start_date < p_owner->i_preroll_end ) + p_aout_buf->i_pts < p_owner->i_preroll_end ) { aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf ); continue; @@ -1253,6 +1299,7 @@ static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc ) decoder_owner_sys_t *p_owner = p_dec->p_owner; block_t *p_cc; bool pb_present[4]; + bool b_processed = false; int i; int i_cc_decoder; @@ -1284,8 +1331,12 @@ static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc ) else DecoderProcess( p_owner->cc.pp_decoder[i], p_cc ); i_cc_decoder--; + b_processed = true; } vlc_mutex_unlock( &p_owner->lock ); + + if( !b_processed ) + block_Release( p_cc ); } static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, @@ -1299,7 +1350,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, { msg_Warn( p_vout, "non-dated video buffer received" ); *pi_lost_sum += 1; - vout_DropPicture( p_vout, p_picture ); + vout_ReleasePicture( p_vout, p_picture ); return; } @@ -1380,7 +1431,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, vout_Flush( p_vout, p_picture->date ); p_owner->i_last_rate = i_rate; } - vout_DisplayPicture( p_vout, p_picture ); + vout_PutPicture( p_vout, p_picture ); } else { @@ -1390,7 +1441,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture, msg_Warn( p_vout, "non-dated video buffer received" ); *pi_lost_sum += 1; - vout_DropPicture( p_vout, p_picture ); + vout_ReleasePicture( p_vout, p_picture ); } int i_tmp_display; int i_tmp_lost; @@ -1426,7 +1477,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) if( p_dec->b_die ) { /* It prevent freezing VLC in case of broken decoder */ - vout_DropPicture( p_vout, p_pic ); + vout_ReleasePicture( p_vout, p_pic ); if( p_block ) block_Release( p_block ); break; @@ -1436,7 +1487,7 @@ static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ) if( p_owner->i_preroll_end > VLC_TS_INVALID && p_pic->date < p_owner->i_preroll_end ) { - vout_DropPicture( p_vout, p_pic ); + vout_ReleasePicture( p_vout, p_pic ); continue; } @@ -1478,7 +1529,7 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic, vout_thread_t *p_vout = p_owner->p_spu_vout; /* */ - if( p_subpic->i_start <= VLC_TS_INVALID ) + if( p_subpic->i_start <= VLC_TS_INVALID && !b_telx ) { msg_Warn( p_dec, "non-dated spu buffer received" ); subpicture_Delete( p_subpic ); @@ -1535,8 +1586,14 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic, vlc_mutex_unlock( &p_owner->lock ); + if( p_subpic->i_start <= VLC_TS_INVALID ) + b_reject = true; + + DecoderWaitDate( p_dec, &b_reject, + p_subpic->i_start - SPU_MAX_PREPARE_TIME ); + if( !b_reject ) - spu_DisplaySubpicture( p_vout->p_spu, p_subpic ); + spu_DisplaySubpicture( vout_GetSpu( p_vout ), p_subpic ); else subpicture_Delete( p_subpic ); @@ -1637,7 +1694,9 @@ static void DecoderFlushBuffering( decoder_t *p_dec ) p_owner->buffer.i_count--; if( p_owner->p_vout ) - vout_DropPicture( p_owner->p_vout, p_picture ); + { + vout_ReleasePicture( p_owner->p_vout, p_picture ); + } if( !p_owner->buffer.p_picture ) p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture; @@ -1695,8 +1754,7 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block ) p_owner->sout.i_id = p_dec->fmt_in.i_id; if( p_dec->fmt_in.psz_language ) { - if( p_owner->sout.psz_language ) - free( p_owner->sout.psz_language ); + free( p_owner->sout.psz_language ); p_owner->sout.psz_language = strdup( p_dec->fmt_in.psz_language ); } @@ -1877,8 +1935,8 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush p_vout = input_resource_HoldVout( p_input->p->p_resource ); if( p_vout && p_owner->p_spu_vout == p_vout ) - spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, - p_owner->i_spu_channel ); + spu_ClearChannel( vout_GetSpu( p_vout ), + p_owner->i_spu_channel ); if( p_vout ) vlc_object_release( p_vout ); @@ -2017,9 +2075,7 @@ static void DeleteDecoder( decoder_t * p_dec ) { /* Hack to make sure all the the pictures are freed by the decoder * and that the vout is not paused anymore */ - vout_FixLeaks( p_owner->p_vout, true ); - if( p_owner->b_paused ) - vout_ChangePause( p_owner->p_vout, false, mdate() ); + vout_Reset( p_owner->p_vout ); /* */ input_resource_RequestVout( p_owner->p_input->p->p_resource, p_owner->p_vout, NULL, true ); @@ -2042,7 +2098,7 @@ static void DeleteDecoder( decoder_t * p_dec ) if( p_vout ) { if( p_owner->p_spu_vout == p_vout ) - spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, p_owner->i_spu_channel ); + spu_ClearChannel( vout_GetSpu( p_vout ), p_owner->i_spu_channel ); vlc_object_release( p_vout ); } } @@ -2063,7 +2119,6 @@ static void DeleteDecoder( decoder_t * p_dec ) es_format_Clean( &p_owner->p_packetizer->fmt_out ); if( p_owner->p_packetizer->p_description ) vlc_meta_Delete( p_owner->p_packetizer->p_description ); - vlc_object_detach( p_owner->p_packetizer ); vlc_object_release( p_owner->p_packetizer ); } @@ -2071,7 +2126,7 @@ static void DeleteDecoder( decoder_t * p_dec ) vlc_cond_destroy( &p_owner->wait_request ); vlc_mutex_destroy( &p_owner->lock ); - vlc_object_detach( p_dec ); + vlc_object_release( p_dec ); free( p_owner ); } @@ -2136,7 +2191,7 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) if( p_owner->p_aout_input == NULL ) { - const int i_force_dolby = config_GetInt( p_dec, "force-dolby-surround" ); + const int i_force_dolby = var_InheritInteger( p_dec, "force-dolby-surround" ); audio_sample_format_t format; aout_input_t *p_aout_input; aout_instance_t *p_aout; @@ -2204,9 +2259,6 @@ static void aout_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer ) p_owner->p_aout_input, p_buffer ); } - -int vout_CountPictureAvailable( vout_thread_t *p_vout ); - static picture_t *vout_new_buffer( decoder_t *p_dec ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; @@ -2215,7 +2267,8 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) p_dec->fmt_out.video.i_width != p_owner->video.i_width || p_dec->fmt_out.video.i_height != p_owner->video.i_height || p_dec->fmt_out.video.i_chroma != p_owner->video.i_chroma || - p_dec->fmt_out.video.i_aspect != p_owner->video.i_aspect ) + (int64_t)p_dec->fmt_out.video.i_sar_num * p_owner->video.i_sar_den != + (int64_t)p_dec->fmt_out.video.i_sar_den * p_owner->video.i_sar_num ) { vout_thread_t *p_vout; @@ -2250,19 +2303,19 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) var_CreateGetBool( p_dec, "hdtv-fix" ) ) { p_dec->fmt_out.video.i_visible_height = 1080; - p_dec->fmt_out.video.i_sar_num *= 135; - p_dec->fmt_out.video.i_sar_den *= 136; + if( !(p_dec->fmt_out.video.i_sar_num % 136)) + { + p_dec->fmt_out.video.i_sar_num *= 135; + p_dec->fmt_out.video.i_sar_den *= 136; + } msg_Warn( p_dec, "Fixing broken HDTV stream (display_height=1088)"); } if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den ) { - p_dec->fmt_out.video.i_sar_num = p_dec->fmt_out.video.i_aspect * - p_dec->fmt_out.video.i_visible_height; - - p_dec->fmt_out.video.i_sar_den = VOUT_ASPECT_FACTOR * - p_dec->fmt_out.video.i_visible_width; + p_dec->fmt_out.video.i_sar_num = 1; + p_dec->fmt_out.video.i_sar_den = 1; } vlc_ureduce( &p_dec->fmt_out.video.i_sar_num, @@ -2298,35 +2351,18 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) p_dec->b_error = true; return NULL; } - - if( p_owner->video.i_rmask ) - p_owner->p_vout->render.i_rmask = p_owner->video.i_rmask; - if( p_owner->video.i_gmask ) - p_owner->p_vout->render.i_gmask = p_owner->video.i_gmask; - if( p_owner->video.i_bmask ) - p_owner->p_vout->render.i_bmask = p_owner->video.i_bmask; } /* Get a new picture */ for( ;; ) { - picture_t *p_picture; - if( p_dec->b_die || p_dec->b_error ) return NULL; - /* The video filter chain required that there is always 1 free buffer - * that it will use as temporary one. It will release the temporary - * buffer once its work is done, so this check is safe even if we don't - * lock around both count() and create(). - */ - if( vout_CountPictureAvailable( p_owner->p_vout ) >= 2 ) - { - p_picture = vout_CreatePicture( p_owner->p_vout, 0, 0, 0 ); - if( p_picture ) - return p_picture; - } + picture_t *p_picture = vout_GetPicture( p_owner->p_vout ); + if( p_picture ) + return p_picture; if( DecoderIsFlushing( p_dec ) ) return NULL; @@ -2335,7 +2371,7 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) DecoderSignalBuffering( p_dec, true ); /* Check the decoder doesn't leak pictures */ - vout_FixLeaks( p_owner->p_vout, false ); + vout_FixLeaks( p_owner->p_vout ); /* FIXME add a vout_WaitPictureAvailable (timedwait) */ msleep( VOUT_OUTMEM_SLEEP ); @@ -2344,20 +2380,21 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic ) { - vout_DropPicture( p_dec->p_owner->p_vout, p_pic ); + vout_ReleasePicture( p_dec->p_owner->p_vout, p_pic ); } static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic ) { - vout_LinkPicture( p_dec->p_owner->p_vout, p_pic ); + vout_HoldPicture( p_dec->p_owner->p_vout, p_pic ); } static void vout_unlink_picture( decoder_t *p_dec, picture_t *p_pic ) { - vout_UnlinkPicture( p_dec->p_owner->p_vout, p_pic ); + vout_ReleasePicture( p_dec->p_owner->p_vout, p_pic ); } -static subpicture_t *spu_new_buffer( decoder_t *p_dec ) +static subpicture_t *spu_new_buffer( decoder_t *p_dec, + const subpicture_updater_t *p_updater ) { decoder_owner_sys_t *p_owner = p_dec->p_owner; vout_thread_t *p_vout = NULL; @@ -2390,13 +2427,12 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec ) vlc_mutex_unlock( &p_owner->lock ); - spu_Control( p_vout->p_spu, SPU_CHANNEL_REGISTER, - &p_owner->i_spu_channel ); + p_owner->i_spu_channel = spu_RegisterChannel( vout_GetSpu( p_vout ) ); p_owner->i_spu_order = 0; p_owner->p_spu_vout = p_vout; } - p_subpic = subpicture_New(); + p_subpic = subpicture_New( p_updater ); if( p_subpic ) { p_subpic->i_channel = p_owner->i_spu_channel;