vlc | branch: master | Romain Vimont <[email protected]> | Thu Jun 13 16:17:14 2019 +0200| [a2bc9e15516093162da31c09546880b7aaaa6f0b] | committer: Thomas Guillem
decoder: remove input thread and ES dependency As suggested by Rémi: > the decoder should use opaque callbacks provided by the ES out rather > than "see" the input and the ES. <https://mailman.videolan.org/pipermail/vlc-devel/2019-May/125088.html> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=a2bc9e15516093162da31c09546880b7aaaa6f0b --- src/input/decoder.c | 118 ++++++++++++++-------------------------- src/input/decoder.h | 28 +++++++++- src/input/es_out.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 213 insertions(+), 85 deletions(-) diff --git a/src/input/decoder.c b/src/input/decoder.c index 3b19b51d66..638dac21e8 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -45,10 +45,8 @@ #include "audio_output/aout_internal.h" #include "stream_output/stream_output.h" -#include "input_internal.h" #include "../clock/clock.h" #include "decoder.h" -#include "event.h" #include "resource.h" #include "../video_output/vout_internal.h" @@ -66,11 +64,12 @@ enum reload struct decoder_owner { decoder_t dec; - input_thread_t *p_input; - vlc_es_id_t *id; input_resource_t*p_resource; vlc_clock_t *p_clock; + const struct input_decoder_callbacks *cbs; + void *cbs_userdata; + ssize_t i_spu_channel; int64_t i_spu_order; @@ -156,6 +155,11 @@ struct decoder_owner #define DECODER_SPU_VOUT_WAIT_DURATION VLC_TICK_FROM_MS(200) #define BLOCK_FLAG_CORE_PRIVATE_RELOADED (1 << BLOCK_FLAG_CORE_PRIVATE_SHIFT) +#define decoder_Notify(decoder_priv, event, ...) \ + if (decoder_priv->cbs && decoder_priv->cbs->event) \ + decoder_priv->cbs->event(&decoder_priv->dec, __VA_ARGS__, \ + decoder_priv->cbs_userdata); + static inline struct decoder_owner *dec_get_owner( decoder_t *p_dec ) { return container_of( p_dec, struct decoder_owner, dec ); @@ -542,13 +546,8 @@ static int vout_update_format( decoder_t *p_dec ) .dpb_size = dpb_size + p_dec->i_extra_picture_buffers + 1, .mouse_event = MouseEvent, .mouse_opaque = p_dec } ); - if (p_vout && p_owner->p_input) - input_SendEventVout(p_owner->p_input, - &(struct vlc_input_event_vout) { - .action = VLC_INPUT_EVENT_VOUT_ADDED, - .vout = p_vout, - .id = p_owner->id, - }); + if (p_vout) + decoder_Notify(p_owner, on_vout_added, p_vout); vlc_mutex_lock( &p_owner->lock ); p_owner->p_vout = p_vout; @@ -664,12 +663,11 @@ static int DecoderGetInputAttachments( decoder_t *p_dec, int *pi_attachment ) { struct decoder_owner *p_owner = dec_get_owner( p_dec ); - input_thread_t *p_input = p_owner->p_input; - - if( unlikely(p_input == NULL) ) + if (!p_owner->cbs || !p_owner->cbs->get_attachments) return VLC_ENOOBJ; - int ret = input_GetAttachments( p_input, ppp_attachment ); + int ret = p_owner->cbs->get_attachments(p_dec, ppp_attachment, + p_owner->cbs_userdata); if (ret < 0) return VLC_EGENERIC; *pi_attachment = ret; @@ -1059,13 +1057,8 @@ discard: static void DecoderUpdateStatVideo( struct decoder_owner *p_owner, unsigned decoded, unsigned lost ) { - input_thread_t *p_input = p_owner->p_input; unsigned displayed = 0; - /* Update ugly stat */ - if( p_input == NULL ) - return; - if( p_owner->p_vout != NULL ) { unsigned vout_lost = 0; @@ -1074,17 +1067,7 @@ static void DecoderUpdateStatVideo( struct decoder_owner *p_owner, lost += vout_lost; } - struct input_stats *stats = input_priv(p_input)->stats; - - if( stats != NULL ) - { - atomic_fetch_add_explicit(&stats->decoded_video, decoded, - memory_order_relaxed); - atomic_fetch_add_explicit(&stats->lost_pictures, lost, - memory_order_relaxed); - atomic_fetch_add_explicit(&stats->displayed_pictures, displayed, - memory_order_relaxed); - } + decoder_Notify(p_owner, on_new_video_stats, decoded, lost, displayed); } static void DecoderQueueVideo( decoder_t *p_dec, picture_t *p_pic ) @@ -1119,11 +1102,7 @@ static void DecoderQueueThumbnail( decoder_t *p_dec, picture_t *p_pic ) struct decoder_owner *p_owner = dec_get_owner( p_dec ); if( p_owner->b_first ) { - assert(p_owner->p_input); - input_SendEvent(p_owner->p_input, &(struct vlc_input_event) { - .type = INPUT_EVENT_THUMBNAIL_READY, - .thumbnail = p_pic - }); + decoder_Notify(p_owner, on_thumbnail_ready, p_pic); p_owner->b_first = false; } picture_Release( p_pic ); @@ -1209,13 +1188,8 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio, static void DecoderUpdateStatAudio( struct decoder_owner *p_owner, unsigned decoded, unsigned lost ) { - input_thread_t *p_input = p_owner->p_input; unsigned played = 0; - /* Update ugly stat */ - if( p_input == NULL ) - return; - if( p_owner->p_aout != NULL ) { unsigned aout_lost; @@ -1224,17 +1198,7 @@ static void DecoderUpdateStatAudio( struct decoder_owner *p_owner, lost += aout_lost; } - struct input_stats *stats = input_priv(p_input)->stats; - - if( stats != NULL ) - { - atomic_fetch_add_explicit(&stats->lost_abuffers, lost, - memory_order_relaxed); - atomic_fetch_add_explicit(&stats->played_abuffers, played, - memory_order_relaxed); - atomic_fetch_add_explicit(&stats->decoded_audio, decoded, - memory_order_relaxed); - } + decoder_Notify(p_owner, on_new_audio_stats, decoded, lost, played); } static void DecoderQueueAudio( decoder_t *p_dec, block_t *p_aout_buf ) @@ -1782,10 +1746,11 @@ static const struct decoder_owner_callbacks dec_spu_cbs = * \return the decoder object */ static decoder_t * CreateDecoder( vlc_object_t *p_parent, - input_thread_t *p_input, vlc_es_id_t *id, const es_format_t *fmt, vlc_clock_t *p_clock, input_resource_t *p_resource, - sout_instance_t *p_sout ) + sout_instance_t *p_sout, bool b_thumbnailing, + const struct input_decoder_callbacks *cbs, + void *cbs_userdata ) { decoder_t *p_dec; struct decoder_owner *p_owner; @@ -1795,11 +1760,11 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent, return NULL; p_dec = &p_owner->dec; - p_owner->id = id; p_owner->p_clock = p_clock; p_owner->i_preroll_end = (vlc_tick_t)INT64_MIN; - p_owner->p_input = p_input; p_owner->p_resource = p_resource; + p_owner->cbs = cbs; + p_owner->cbs_userdata = cbs_userdata; p_owner->p_aout = NULL; p_owner->p_vout = NULL; p_owner->i_spu_channel = -1; @@ -1872,7 +1837,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent, switch( fmt->i_cat ) { case VIDEO_ES: - if( !p_input || !input_priv( p_input )->b_thumbnailing ) + if( !b_thumbnailing ) p_dec->cbs = &dec_video_cbs; else p_dec->cbs = &dec_thumbnailer_cbs; @@ -1974,13 +1939,7 @@ static void DeleteDecoder( decoder_t * p_dec ) /* Reset the cancel state that was set before joining the decoder * thread */ vout_Cancel(vout, false); - if (p_owner->p_input) - input_SendEventVout(p_owner->p_input, - &(struct vlc_input_event_vout) { - .action = VLC_INPUT_EVENT_VOUT_DELETED, - .vout = vout, - .id = p_owner->id, - }); + decoder_Notify(p_owner, on_vout_deleted, vout); input_resource_PutVout(p_owner->p_resource, vout); } break; @@ -2038,17 +1997,19 @@ static void DecoderUnsupportedCodec( decoder_t *p_dec, const es_format_t *fmt, b } /* TODO: pass p_sout through p_resource? -- Courmisch */ -static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input, - vlc_es_id_t *id, const es_format_t *fmt, +static decoder_t *decoder_New( vlc_object_t *p_parent, const es_format_t *fmt, vlc_clock_t *p_clock, input_resource_t *p_resource, - sout_instance_t *p_sout ) + sout_instance_t *p_sout, bool thumbnailing, + const struct input_decoder_callbacks *cbs, + void *userdata) { decoder_t *p_dec = NULL; const char *psz_type = p_sout ? N_("packetizer") : N_("decoder"); int i_priority; /* Create the decoder configuration structure */ - p_dec = CreateDecoder( p_parent, p_input, id, fmt, p_clock, p_resource, p_sout ); + p_dec = CreateDecoder( p_parent, fmt, p_clock, p_resource, p_sout, + thumbnailing, cbs, userdata ); if( p_dec == NULL ) { msg_Err( p_parent, "could not create %s", psz_type ); @@ -2107,13 +2068,14 @@ static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input, * \param p_es the es descriptor * \return the spawned decoder object */ -decoder_t *input_DecoderNew( input_thread_t *p_input, vlc_es_id_t *id, - es_format_t *fmt, vlc_clock_t *p_clock, - sout_instance_t *p_sout ) +decoder_t *input_DecoderNew( vlc_object_t *parent, es_format_t *fmt, + vlc_clock_t *p_clock, input_resource_t *resource, + sout_instance_t *p_sout, bool thumbnailing, + const struct input_decoder_callbacks *cbs, + void *cbs_userdata) { - assert(p_input && id); - return decoder_New( VLC_OBJECT(p_input), p_input, id, fmt, p_clock, - input_priv(p_input)->p_resource, p_sout ); + return decoder_New( parent, fmt, p_clock, resource, p_sout, thumbnailing, + cbs, cbs_userdata ); } /** @@ -2122,7 +2084,8 @@ decoder_t *input_DecoderNew( input_thread_t *p_input, vlc_es_id_t *id, decoder_t *input_DecoderCreate( vlc_object_t *p_parent, const es_format_t *fmt, input_resource_t *p_resource ) { - return decoder_New( p_parent, NULL, NULL, fmt, NULL, p_resource, NULL ); + return decoder_New( p_parent, fmt, NULL, p_resource, NULL, false, NULL, + NULL ); } @@ -2342,8 +2305,9 @@ int input_DecoderSetCcState( decoder_t *p_dec, vlc_fourcc_t codec, es_format_Init( &fmt, SPU_ES, codec ); fmt.subs.cc.i_channel = i_channel; fmt.subs.cc.i_reorder_depth = p_owner->cc.desc.i_reorder_depth; - p_cc = input_DecoderNew( p_owner->p_input, p_owner->id, &fmt, - p_owner->p_clock, p_owner->p_sout ); + p_cc = input_DecoderNew( VLC_OBJECT(p_dec), &fmt, p_owner->p_clock, + p_owner->p_resource, p_owner->p_sout, false, + NULL, NULL ); if( !p_cc ) { msg_Err( p_dec, "could not create decoder" ); diff --git a/src/input/decoder.h b/src/input/decoder.h index fbb266e139..a259152a23 100644 --- a/src/input/decoder.h +++ b/src/input/decoder.h @@ -28,8 +28,32 @@ #include <vlc_codec.h> #include <vlc_mouse.h> -decoder_t *input_DecoderNew( input_thread_t *, vlc_es_id_t *, es_format_t *, - vlc_clock_t *, sout_instance_t * ) VLC_USED; +struct input_decoder_callbacks { + /* notifications */ + void (*on_vout_added)(decoder_t *decoder, vout_thread_t *vout, + void *userdata); + void (*on_vout_deleted)(decoder_t *decoder, vout_thread_t *vout, + void *userdata); + void (*on_thumbnail_ready)(decoder_t *decoder, picture_t *pic, + void *userdata); + + void (*on_new_video_stats)(decoder_t *decoder, unsigned decoded, + unsigned lost, unsigned displayed, + void *userdata); + void (*on_new_audio_stats)(decoder_t *decoder, unsigned decoded, + unsigned lost, unsigned played, void *userdata); + + /* requests */ + int (*get_attachments)(decoder_t *decoder, + input_attachment_t ***ppp_attachment, + void *userdata); +}; + +decoder_t *input_DecoderNew( vlc_object_t *parent, es_format_t *, vlc_clock_t *, + input_resource_t *, sout_instance_t *, + bool thumbnailing, + const struct input_decoder_callbacks *cbs, + void *userdata ) VLC_USED; /** * This function changes the pause state. diff --git a/src/input/es_out.c b/src/input/es_out.c index 981160479e..567d4257c9 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -259,6 +259,138 @@ static inline int EsOutGetClosedCaptionsChannel( const es_format_t *p_fmt ) for( int fetes_i=0; fetes_i<2; fetes_i++ ) \ vlc_list_foreach( pos, (!fetes_i ? &p_sys->es : &p_sys->es_slaves), node ) +static vlc_es_id_t * +FindEsIdFromDecoder(es_out_sys_t *p_sys, decoder_t *decoder) +{ + es_out_id_t *es; + foreach_es_then_es_slaves(es) + if (es->p_dec == decoder) + return &es->id; + return NULL; +} + +static void +decoder_on_vout_added(decoder_t *decoder, vout_thread_t *vout, void *userdata) +{ + es_out_sys_t *priv = userdata; + if (!priv->p_input) + return; + + vlc_es_id_t *id = FindEsIdFromDecoder(priv, decoder); + assert(id); + + struct vlc_input_event_vout event = { + .action = VLC_INPUT_EVENT_VOUT_ADDED, + .vout = vout, + .id = id, + }; + + input_SendEventVout(priv->p_input, &event); +} + +static void +decoder_on_vout_deleted(decoder_t *decoder, vout_thread_t *vout, void *userdata) +{ + es_out_sys_t *priv = userdata; + if (!priv->p_input) + return; + + vlc_es_id_t *id = FindEsIdFromDecoder(priv, decoder); + assert(id); + + struct vlc_input_event_vout event = { + .action = VLC_INPUT_EVENT_VOUT_DELETED, + .vout = vout, + .id = id, + }; + + input_SendEventVout(priv->p_input, &event); +} + +static void +decoder_on_thumbnail_ready(decoder_t *decoder, picture_t *pic, void *userdata) +{ + es_out_sys_t *priv = userdata; + if (!priv->p_input) + return; + + vlc_es_id_t *id = FindEsIdFromDecoder(priv, decoder); + assert(id); + + struct vlc_input_event event = { + .type = INPUT_EVENT_THUMBNAIL_READY, + .thumbnail = pic, + }; + + input_SendEvent(priv->p_input, &event); +} + +static void +decoder_on_new_video_stats(decoder_t *decoder, unsigned decoded, unsigned lost, + unsigned displayed, void *userdata) +{ + (void) decoder; + + es_out_sys_t *priv = userdata; + if (!priv->p_input) + return; + + struct input_stats *stats = input_priv(priv->p_input)->stats; + if (!stats) + return; + + atomic_fetch_add_explicit(&stats->decoded_video, decoded, + memory_order_relaxed); + atomic_fetch_add_explicit(&stats->lost_pictures, lost, + memory_order_relaxed); + atomic_fetch_add_explicit(&stats->displayed_pictures, displayed, + memory_order_relaxed); +} + +static void +decoder_on_new_audio_stats(decoder_t *decoder, unsigned decoded, unsigned lost, + unsigned played, void *userdata) +{ + (void) decoder; + + es_out_sys_t *priv = userdata; + if (!priv->p_input) + return; + + struct input_stats *stats = input_priv(priv->p_input)->stats; + if (!stats) + return; + + atomic_fetch_add_explicit(&stats->decoded_audio, decoded, + memory_order_relaxed); + atomic_fetch_add_explicit(&stats->lost_abuffers, lost, + memory_order_relaxed); + atomic_fetch_add_explicit(&stats->played_abuffers, played, + memory_order_relaxed); +} + +static int +decoder_get_attachments(decoder_t *decoder, + input_attachment_t ***ppp_attachment, + void *userdata) +{ + (void) decoder; + + es_out_sys_t *priv = userdata; + if (!priv->p_input) + return -1; + + return input_GetAttachments(priv->p_input, ppp_attachment); +} + +static const struct input_decoder_callbacks decoder_cbs = { + .on_vout_added = decoder_on_vout_added, + .on_vout_deleted = decoder_on_vout_deleted, + .on_thumbnail_ready = decoder_on_thumbnail_ready, + .on_new_video_stats = decoder_on_new_video_stats, + .on_new_audio_stats = decoder_on_new_audio_stats, + .get_attachments = decoder_get_attachments, +}; /***************************************************************************** * Es category specific structs @@ -640,8 +772,12 @@ static int EsOutSetRecord( es_out_t *out, bool b_record ) if( !p_es->p_dec ) continue; - p_es->p_dec_record = input_DecoderNew( p_input, &p_es->id, &p_es->fmt, - NULL, p_sys->p_sout_record ); + p_es->p_dec_record = + input_DecoderNew( VLC_OBJECT(p_input), &p_es->fmt, NULL, + input_priv(p_input)->p_resource, + p_sys->p_sout_record, false, + &decoder_cbs, p_sys ); + if( p_es->p_dec_record && p_sys->b_buffering ) input_DecoderStartWait( p_es->p_dec_record ); } @@ -1844,8 +1980,10 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es ) if( !p_es->p_clock ) return; - dec = input_DecoderNew( p_input, &p_es->id, &p_es->fmt, p_es->p_clock, - input_priv(p_input)->p_sout ); + input_thread_private_t *priv = input_priv(p_input); + dec = input_DecoderNew( VLC_OBJECT(p_input), &p_es->fmt, p_es->p_clock, + priv->p_resource, priv->p_sout, + priv->b_thumbnailing, &decoder_cbs, p_sys ); if( dec != NULL ) { input_DecoderChangeRate( dec, p_sys->rate ); @@ -1855,8 +1993,10 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es ) if( !p_es->p_master && p_sys->p_sout_record ) { - p_es->p_dec_record = input_DecoderNew( p_input, &p_es->id, &p_es->fmt, - NULL, p_sys->p_sout_record ); + p_es->p_dec_record = + input_DecoderNew( VLC_OBJECT(p_input), &p_es->fmt, NULL, + priv->p_resource, p_sys->p_sout_record, false, + &decoder_cbs, p_sys ); if( p_es->p_dec_record && p_sys->b_buffering ) input_DecoderStartWait( p_es->p_dec_record ); } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
