@@ -239,6 +239,49 @@ gboolean check_pipeline_dot_data(GstElement *pipeline) {
239239 return G_SOURCE_CONTINUE;
240240}
241241
242+ static GstPadProbeReturn caps_probe_cb (GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
243+ // 1. Check if the data in the probe is an event
244+ GstEvent *event = gst_pad_probe_info_get_event (info);
245+
246+ // 2. We only care about the CAPS event
247+ if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) {
248+ return GST_PAD_PROBE_OK;
249+ }
250+
251+ // 3. Extract the actual Caps from the event
252+ GstCaps *caps;
253+ gst_event_parse_caps (event, &caps);
254+
255+ // 4. Extract metadata (Width, Height, Format)
256+ GstStructure *s = gst_caps_get_structure (caps, 0 );
257+
258+ gint width, height;
259+ gboolean res = gst_structure_get_int (s, " width" , &width);
260+ if (!res) {
261+ g_print (" Could not get width from caps.\n " );
262+ return GST_PAD_PROBE_OK;
263+ }
264+
265+ res = gst_structure_get_int (s, " height" , &height);
266+ if (!res) {
267+ g_print (" Could not get height from caps.\n " );
268+ return GST_PAD_PROBE_OK;
269+ }
270+
271+ gint numerator, denominator;
272+ res = gst_structure_get_fraction (s, " framerate" , &numerator, &denominator);
273+ if (!res) {
274+ g_print (" Could not get framerate from caps.\n " );
275+ return GST_PAD_PROBE_OK;
276+ }
277+
278+ GuiInterface::Instance ().EmitDecoderReady (width, height, (gdouble)numerator / denominator, " Software" );
279+
280+ // Usually, you only need to catch the initial caps once.
281+ // Return REMOVE to detach the probe and save CPU cycles.
282+ return GST_PAD_PROBE_REMOVE;
283+ }
284+
242285void GstDecoder::create_pipeline (const std::string &codec, bool force_sw_decoding) {
243286 if (pipeline_) {
244287 return ;
@@ -253,9 +296,9 @@ void GstDecoder::create_pipeline(const std::string &codec, bool force_sw_decodin
253296 sw_dec = " avdec_h265" ;
254297 }
255298
256- std::string decoder = " decodebin3 name=decbin ! " ;
299+ std::string decoder = " decodebin3 name=dec ! " ;
257300 if (force_sw_decoding) {
258- decoder = sw_dec + " name=decbin max-threads=1 lowres=0 skip-frame=0 ! " ;
301+ decoder = sw_dec + " name=dec max-threads=1 lowres=0 skip-frame=0 ! " ;
259302 }
260303
261304 gchar *pipeline_str = g_strdup_printf (
@@ -296,8 +339,8 @@ void GstDecoder::create_pipeline(const std::string &codec, bool force_sw_decodin
296339 gst_bus_add_watch (bus, gst_bus_cb, pipeline_);
297340 gst_clear_object (&bus);
298341
299- {
300- GstElement *decodebin3 = gst_bin_get_by_name (GST_BIN (pipeline_), " decbin " );
342+ if (!force_sw_decoding) {
343+ GstElement *decodebin3 = gst_bin_get_by_name (GST_BIN (pipeline_), " dec " );
301344 if (!decodebin3) {
302345 GuiInterface::Instance ().PutLog (LogLevel::Error, " Could not find decodebin3 element" );
303346 return ;
@@ -306,6 +349,14 @@ void GstDecoder::create_pipeline(const std::string &codec, bool force_sw_decodin
306349 g_signal_connect (decodebin3, " pad-added" , G_CALLBACK (on_decodebin3_pad_added), this );
307350
308351 gst_object_unref (decodebin3);
352+ } else {
353+ GstElement *dec = gst_bin_get_by_name (GST_BIN (pipeline_), " dec" );
354+ GstPad *src_pad = gst_element_get_static_pad (dec, " src" );
355+
356+ // We use GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM to catch events flowing from decoder -> sink.
357+ gst_pad_add_probe (src_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, (GstPadProbeCallback)caps_probe_cb, NULL , NULL );
358+
359+ gst_object_unref (src_pad);
309360 }
310361
311362 {
0 commit comments