1*4882a593SmuzhiyunFrom d1f8653d907d5a6b96dbe7e287a35cbc595a24f2 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: =?UTF-8?q?St=C3=A9phane=20Cerveau?= <scerveau@collabora.com> 3*4882a593SmuzhiyunDate: Mon, 9 Aug 2021 18:02:57 +0200 4*4882a593SmuzhiyunSubject: [PATCH 03/14] playbin: do not drain on first EOS 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunIn a case of audio/video media, the decodebin 7*4882a593Smuzhiyunshould wait for each branch to be on EOS before 8*4882a593Smuzhiyundraining the others. 9*4882a593Smuzhiyun 10*4882a593SmuzhiyunA new signal "wait-on-eos" has been implemented 11*4882a593Smuzhiyunfor (uri)decodebin to tell that an EOS has been 12*4882a593Smuzhiyunreceived on a branch. 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunIn the case of playbin2, it will compare 15*4882a593Smuzhiyunthe nb of active pads with the nb of EOS received 16*4882a593Smuzhiyunand decodebin will start to drain all the active pads when the nb 17*4882a593Smuzhiyunof EOS is equal to active pads (active combiners). 18*4882a593Smuzhiyun--- 19*4882a593Smuzhiyun gst/playback/gstdecodebin2.c | 37 ++++++++++++++++++++++++++++++++++ 20*4882a593Smuzhiyun gst/playback/gstplaybin2.c | 31 ++++++++++++++++++++++++++++ 21*4882a593Smuzhiyun gst/playback/gsturidecodebin.c | 32 +++++++++++++++++++++++++++++ 22*4882a593Smuzhiyun 3 files changed, 100 insertions(+) 23*4882a593Smuzhiyun 24*4882a593Smuzhiyundiff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c 25*4882a593Smuzhiyunindex 1849714..b84a30d 100644 26*4882a593Smuzhiyun--- a/gst/playback/gstdecodebin2.c 27*4882a593Smuzhiyun+++ b/gst/playback/gstdecodebin2.c 28*4882a593Smuzhiyun@@ -163,6 +163,9 @@ struct _GstDecodeBin 29*4882a593Smuzhiyun GMutex expose_lock; /* Protects exposal and removal of groups */ 30*4882a593Smuzhiyun GstDecodeChain *decode_chain; /* Top level decode chain */ 31*4882a593Smuzhiyun guint nbpads; /* unique identifier for source pads */ 32*4882a593Smuzhiyun+ guint nbpads_eos; /* number of pads in EOS */ 33*4882a593Smuzhiyun+ gboolean wait_on_eos; /* wait EOS on other pads */ 34*4882a593Smuzhiyun+ GCond eos_cond; /* condition to block the pad in EOS */ 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun GMutex factories_lock; 37*4882a593Smuzhiyun guint32 factories_cookie; /* Cookie from last time when factories was updated */ 38*4882a593Smuzhiyun@@ -224,6 +227,8 @@ struct _GstDecodeBinClass 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun /* fired when the last group is drained */ 41*4882a593Smuzhiyun void (*drained) (GstElement * element); 42*4882a593Smuzhiyun+ /* emitted when an EOS is received */ 43*4882a593Smuzhiyun+ gboolean (*wait_on_eos) (GstElement * element, guint eos_received); 44*4882a593Smuzhiyun }; 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun /* signals */ 47*4882a593Smuzhiyun@@ -236,6 +241,7 @@ enum 48*4882a593Smuzhiyun SIGNAL_AUTOPLUG_SORT, 49*4882a593Smuzhiyun SIGNAL_AUTOPLUG_QUERY, 50*4882a593Smuzhiyun SIGNAL_DRAINED, 51*4882a593Smuzhiyun+ SIGNAL_WAIT_ON_EOS, 52*4882a593Smuzhiyun LAST_SIGNAL 53*4882a593Smuzhiyun }; 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun@@ -870,6 +876,20 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass) 56*4882a593Smuzhiyun G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, drained), 57*4882a593Smuzhiyun NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE); 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun+ /** 60*4882a593Smuzhiyun+ * GstDecodeBin::wait-on-eos 61*4882a593Smuzhiyun+ * @bin: The decodebin 62*4882a593Smuzhiyun+ * @nb_eos: the number of EOS received 63*4882a593Smuzhiyun+ * 64*4882a593Smuzhiyun+ * This signal is emitted once decodebin has received an EOS. 65*4882a593Smuzhiyun+ * 66*4882a593Smuzhiyun+ * Since: 1.20 67*4882a593Smuzhiyun+ */ 68*4882a593Smuzhiyun+ gst_decode_bin_signals[SIGNAL_WAIT_ON_EOS] = 69*4882a593Smuzhiyun+ g_signal_new ("wait-on-eos", G_TYPE_FROM_CLASS (klass), 70*4882a593Smuzhiyun+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, wait_on_eos), 71*4882a593Smuzhiyun+ NULL, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_UINT); 72*4882a593Smuzhiyun+ 73*4882a593Smuzhiyun g_object_class_install_property (gobject_klass, PROP_CAPS, 74*4882a593Smuzhiyun g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.", 75*4882a593Smuzhiyun GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 76*4882a593Smuzhiyun@@ -1111,6 +1131,7 @@ gst_decode_bin_init (GstDecodeBin * decode_bin) 77*4882a593Smuzhiyun gst_object_unref (pad); 78*4882a593Smuzhiyun } 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun+ g_cond_init (&decode_bin->eos_cond); 81*4882a593Smuzhiyun g_mutex_init (&decode_bin->expose_lock); 82*4882a593Smuzhiyun decode_bin->decode_chain = NULL; 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun@@ -1177,6 +1198,7 @@ gst_decode_bin_finalize (GObject * object) 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun decode_bin = GST_DECODE_BIN (object); 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun+ g_cond_clear (&decode_bin->eos_cond); 89*4882a593Smuzhiyun g_mutex_clear (&decode_bin->expose_lock); 90*4882a593Smuzhiyun g_mutex_clear (&decode_bin->dyn_lock); 91*4882a593Smuzhiyun g_mutex_clear (&decode_bin->subtitle_lock); 92*4882a593Smuzhiyun@@ -4285,6 +4307,17 @@ gst_decode_pad_handle_eos (GstDecodePad * pad) 93*4882a593Smuzhiyun } 94*4882a593Smuzhiyun 95*4882a593Smuzhiyun EXPOSE_LOCK (dbin); 96*4882a593Smuzhiyun+ dbin->nbpads_eos++; 97*4882a593Smuzhiyun+ g_signal_emit (G_OBJECT (dbin), 98*4882a593Smuzhiyun+ gst_decode_bin_signals[SIGNAL_WAIT_ON_EOS], 0, dbin->nbpads_eos, 99*4882a593Smuzhiyun+ &dbin->wait_on_eos); 100*4882a593Smuzhiyun+ g_cond_broadcast (&dbin->eos_cond); 101*4882a593Smuzhiyun+ GST_DEBUG_OBJECT (dbin, "dbin->nbpads_eos %u wait_on_eos %u", 102*4882a593Smuzhiyun+ dbin->nbpads_eos, dbin->wait_on_eos); 103*4882a593Smuzhiyun+ 104*4882a593Smuzhiyun+ while (dbin->wait_on_eos) 105*4882a593Smuzhiyun+ g_cond_wait (&dbin->eos_cond, &dbin->expose_lock); 106*4882a593Smuzhiyun+ 107*4882a593Smuzhiyun if (dbin->decode_chain) { 108*4882a593Smuzhiyun drain_and_switch_chains (dbin->decode_chain, pad, &last_group, &drained, 109*4882a593Smuzhiyun &switched); 110*4882a593Smuzhiyun@@ -5326,6 +5359,10 @@ unblock_pads (GstDecodeBin * dbin) 111*4882a593Smuzhiyun GST_DEBUG_OBJECT (dpad, "unblocked"); 112*4882a593Smuzhiyun gst_object_unref (dpad); 113*4882a593Smuzhiyun } 114*4882a593Smuzhiyun+ dbin->nbpads = 0; 115*4882a593Smuzhiyun+ dbin->nbpads_eos = 0; 116*4882a593Smuzhiyun+ dbin->wait_on_eos = FALSE; 117*4882a593Smuzhiyun+ g_cond_broadcast (&dbin->eos_cond); 118*4882a593Smuzhiyun } 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun static void 121*4882a593Smuzhiyundiff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c 122*4882a593Smuzhiyunindex 51751ff..4098fb9 100644 123*4882a593Smuzhiyun--- a/gst/playback/gstplaybin2.c 124*4882a593Smuzhiyun+++ b/gst/playback/gstplaybin2.c 125*4882a593Smuzhiyun@@ -337,6 +337,7 @@ struct _GstSourceGroup 126*4882a593Smuzhiyun gulong notify_source_id; 127*4882a593Smuzhiyun gulong source_setup_id; 128*4882a593Smuzhiyun gulong drained_id; 129*4882a593Smuzhiyun+ gulong wait_on_eos_id; 130*4882a593Smuzhiyun gulong autoplug_factories_id; 131*4882a593Smuzhiyun gulong autoplug_select_id; 132*4882a593Smuzhiyun gulong autoplug_continue_id; 133*4882a593Smuzhiyun@@ -3932,6 +3933,30 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group) 134*4882a593Smuzhiyun group->pending_about_to_finish = TRUE; 135*4882a593Smuzhiyun } 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun+static gboolean 138*4882a593Smuzhiyun+wait_on_eos_cb (GstElement * decodebin, guint eos_received, 139*4882a593Smuzhiyun+ GstSourceGroup * group) 140*4882a593Smuzhiyun+{ 141*4882a593Smuzhiyun+ GstPlayBin *playbin = group->playbin; 142*4882a593Smuzhiyun+ int i; 143*4882a593Smuzhiyun+ guint active_pads = 0; 144*4882a593Smuzhiyun+ 145*4882a593Smuzhiyun+ for (i = 0; i < PLAYBIN_STREAM_LAST; i++) { 146*4882a593Smuzhiyun+ GstSourceCombine *combine = &group->combiner[i]; 147*4882a593Smuzhiyun+ if (combine->has_active_pad) 148*4882a593Smuzhiyun+ active_pads++; 149*4882a593Smuzhiyun+ } 150*4882a593Smuzhiyun+ 151*4882a593Smuzhiyun+ GST_DEBUG_OBJECT (playbin, 152*4882a593Smuzhiyun+ "%d eos received in group with uri %s, active pads %d", eos_received, 153*4882a593Smuzhiyun+ group->uri, active_pads); 154*4882a593Smuzhiyun+ 155*4882a593Smuzhiyun+ if (eos_received < active_pads) 156*4882a593Smuzhiyun+ return TRUE; 157*4882a593Smuzhiyun+ 158*4882a593Smuzhiyun+ return FALSE; 159*4882a593Smuzhiyun+} 160*4882a593Smuzhiyun+ 161*4882a593Smuzhiyun /* Like gst_element_factory_can_sink_any_caps() but doesn't 162*4882a593Smuzhiyun * allow ANY caps on the sinkpad template */ 163*4882a593Smuzhiyun static gboolean 164*4882a593Smuzhiyun@@ -5401,6 +5426,10 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target) 165*4882a593Smuzhiyun group->drained_id = 166*4882a593Smuzhiyun g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb), 167*4882a593Smuzhiyun group); 168*4882a593Smuzhiyun+ /* is called when the uridecodebin received an EOS */ 169*4882a593Smuzhiyun+ group->wait_on_eos_id = 170*4882a593Smuzhiyun+ g_signal_connect (uridecodebin, "wait-on-eos", 171*4882a593Smuzhiyun+ G_CALLBACK (wait_on_eos_cb), group); 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun /* will be called when a new media type is found. We return a list of decoders 174*4882a593Smuzhiyun * including sinks for decodebin to try */ 175*4882a593Smuzhiyun@@ -5574,6 +5603,7 @@ error_cleanup: 176*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->notify_source_id); 177*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->source_setup_id); 178*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->drained_id); 179*4882a593Smuzhiyun+ REMOVE_SIGNAL (group->uridecodebin, group->wait_on_eos_id); 180*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id); 181*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id); 182*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->autoplug_continue_id); 183*4882a593Smuzhiyun@@ -5663,6 +5693,7 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group) 184*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->notify_source_id); 185*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->source_setup_id); 186*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->drained_id); 187*4882a593Smuzhiyun+ REMOVE_SIGNAL (group->uridecodebin, group->wait_on_eos_id); 188*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id); 189*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id); 190*4882a593Smuzhiyun REMOVE_SIGNAL (group->uridecodebin, group->autoplug_continue_id); 191*4882a593Smuzhiyundiff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c 192*4882a593Smuzhiyunindex a128d92..7031600 100644 193*4882a593Smuzhiyun--- a/gst/playback/gsturidecodebin.c 194*4882a593Smuzhiyun+++ b/gst/playback/gsturidecodebin.c 195*4882a593Smuzhiyun@@ -148,6 +148,8 @@ struct _GstURIDecodeBinClass 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun /* emitted when all data is decoded */ 198*4882a593Smuzhiyun void (*drained) (GstElement * element); 199*4882a593Smuzhiyun+ /* emitted when an EOS is received */ 200*4882a593Smuzhiyun+ gboolean (*wait_on_eos) (GstElement * element, guint eos_received); 201*4882a593Smuzhiyun }; 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%u", 204*4882a593Smuzhiyun@@ -171,6 +173,7 @@ enum 205*4882a593Smuzhiyun SIGNAL_AUTOPLUG_QUERY, 206*4882a593Smuzhiyun SIGNAL_DRAINED, 207*4882a593Smuzhiyun SIGNAL_SOURCE_SETUP, 208*4882a593Smuzhiyun+ SIGNAL_WAIT_ON_EOS, 209*4882a593Smuzhiyun LAST_SIGNAL 210*4882a593Smuzhiyun }; 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun@@ -713,6 +716,19 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass) 213*4882a593Smuzhiyun G_SIGNAL_RUN_LAST, 214*4882a593Smuzhiyun G_STRUCT_OFFSET (GstURIDecodeBinClass, drained), NULL, NULL, NULL, 215*4882a593Smuzhiyun G_TYPE_NONE, 0, G_TYPE_NONE); 216*4882a593Smuzhiyun+ /** 217*4882a593Smuzhiyun+ * GstURIDecodeBin::wait-on-eos 218*4882a593Smuzhiyun+ * @bin: The decodebin 219*4882a593Smuzhiyun+ * @nb_eos: the number of EOS received 220*4882a593Smuzhiyun+ * 221*4882a593Smuzhiyun+ * This signal is emitted once decodebin has received an EOS. 222*4882a593Smuzhiyun+ * 223*4882a593Smuzhiyun+ * Since: 1.20 224*4882a593Smuzhiyun+ */ 225*4882a593Smuzhiyun+ gst_uri_decode_bin_signals[SIGNAL_WAIT_ON_EOS] = 226*4882a593Smuzhiyun+ g_signal_new ("wait-on-eos", G_TYPE_FROM_CLASS (klass), 227*4882a593Smuzhiyun+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, wait_on_eos), 228*4882a593Smuzhiyun+ NULL, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_UINT); 229*4882a593Smuzhiyun 230*4882a593Smuzhiyun /** 231*4882a593Smuzhiyun * GstURIDecodeBin::source-setup: 232*4882a593Smuzhiyun@@ -1838,6 +1854,20 @@ proxy_drained_signal (GstElement * decodebin, GstURIDecodeBin * dec) 233*4882a593Smuzhiyun g_signal_emit (dec, gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL); 234*4882a593Smuzhiyun } 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun+ 237*4882a593Smuzhiyun+static gboolean 238*4882a593Smuzhiyun+proxy_wait_on_eos_signal (GstElement * decodebin, guint eos_received, 239*4882a593Smuzhiyun+ GstURIDecodeBin * dec) 240*4882a593Smuzhiyun+{ 241*4882a593Smuzhiyun+ gboolean result; 242*4882a593Smuzhiyun+ 243*4882a593Smuzhiyun+ g_signal_emit (dec, gst_uri_decode_bin_signals[SIGNAL_WAIT_ON_EOS], 0, 244*4882a593Smuzhiyun+ eos_received, &result); 245*4882a593Smuzhiyun+ GST_DEBUG_OBJECT (dec, "wait-on-eos returned %d", result); 246*4882a593Smuzhiyun+ 247*4882a593Smuzhiyun+ return result; 248*4882a593Smuzhiyun+} 249*4882a593Smuzhiyun+ 250*4882a593Smuzhiyun /* make a decodebin and connect to all the signals */ 251*4882a593Smuzhiyun static GstElement * 252*4882a593Smuzhiyun make_decoder (GstURIDecodeBin * decoder) 253*4882a593Smuzhiyun@@ -1881,6 +1911,8 @@ make_decoder (GstURIDecodeBin * decoder) 254*4882a593Smuzhiyun G_CALLBACK (proxy_autoplug_query_signal), decoder); 255*4882a593Smuzhiyun g_signal_connect (decodebin, "drained", 256*4882a593Smuzhiyun G_CALLBACK (proxy_drained_signal), decoder); 257*4882a593Smuzhiyun+ g_signal_connect (decodebin, "wait-on-eos", 258*4882a593Smuzhiyun+ G_CALLBACK (proxy_wait_on_eos_signal), decoder); 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun /* set up callbacks to create the links between decoded data 261*4882a593Smuzhiyun * and video/audio/subtitle rendering/output. */ 262*4882a593Smuzhiyun-- 263*4882a593Smuzhiyun2.20.1 264*4882a593Smuzhiyun 265