Skip to content

Commit 150fa79

Browse files
committed
Fix gstreamer video info update under forced software decoding
1 parent 55052cf commit 150fa79

File tree

1 file changed

+55
-4
lines changed

1 file changed

+55
-4
lines changed

src/player/gst/gst_decoder.cpp

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
242285
void 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

Comments
 (0)