You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GStreamer视频播放器出现g_object_unref断言失败问题求助

GStreamer视频播放器g_object_unref断言失败问题排查

问题描述

使用C语言基于GStreamer实现视频播放器,程序可正常运行,但出现如下错误:

(drmDemo:871): GLib-GObject-CRITICAL **: 14:14:57.520: g_object_unref: assertion 'G_IS_OBJECT (object)' failed.

代码实现

static void linkElements(GstElement* element, GstPad* sourcePad, gpointer sinkElement)
{
    GstPad* sinkPad=gst_element_get_static_pad((GstElement*)sinkElement, "sink");
    gst_pad_link(sourcePad,sinkPad);
    gst_object_unref(sinkPad);
}

int MyTest(int argc, char** argv)
{
    GstElement *pipeline;
    GstElement *source, *demuxer, *queue, *parser, *decoder, *converter, *sink;

    GstBus *bus;
    GstMessage *msg;
    GstStateChangeReturn ret;
    gboolean terminate = FALSE;
    int retval = 0;

    /* Initialize GStreamer */
    gst_init(&argc, &argv);

    /* Create the elements */
    source = gst_element_factory_make("filesrc", "file-source");
    demuxer = gst_element_factory_make("qtdemux", "demuxer");
    queue = gst_element_factory_make("queue", "queue");
    parser = gst_element_factory_make("h264parse", "parser");
    decoder = gst_element_factory_make("mppvideodec", "decoder");
    converter = gst_element_factory_make("videoconvert", "converter");
    sink = gst_element_factory_make("waylandsink", "sink");

    /* Create the empty pipeline */
    pipeline = gst_pipeline_new("test-pipeline");

    /* Check creation */
    if (!pipeline || !source || !demuxer || !queue || !parser || !decoder || !converter || !sink) {
        g_printerr("Not all elements could be created.\n");
        goto out_return;
    }

    /* Set the location of the input file */
    g_object_set(G_OBJECT(source), "location", "13850_h264.mp4", NULL);

    /* Build the pipeline */
    gst_bin_add_many(GST_BIN(pipeline), source, demuxer, queue, parser, decoder, converter, sink, NULL);
    if (!gst_element_link(source, demuxer)) {
        g_printerr("Source and demuxer could not be linked.\n");
        retval = -1;
        goto out_unref;
    }
    if (!gst_element_link(queue, parser)) {
        g_printerr("Queue and parser could not be linked.\n");
        retval = -2;
        goto out_unref;
    }
    if (!gst_element_link(parser, decoder)) {
        g_printerr("Parser and decoder could not be linked.\n");
        retval = -3;
        goto out_unref;
    }
    if (!gst_element_link(decoder, converter)) {
        g_printerr("Decoder and converter could not be linked.\n");
        retval = -4;
        goto out_unref;
    }

    /* Manually connect the demuxer to the queue */
    g_signal_connect(demuxer, "pad-added", G_CALLBACK(linkElements), queue);

    if (!gst_element_link(converter, sink)) {
        g_printerr("Converter and sink could not be linked.\n");
        retval = -5;
        goto out_unref;
    }

    /* Set the pipeline to "playing" state */
    ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        g_printerr("Unable to set the pipeline to the playing state.\n");
        retval = -6;
        goto out_unref;
    }

    /* Bus */
    bus = gst_element_get_bus(pipeline);
    msg = gst_bus_timed_pop_filtered(
        bus, GST_CLOCK_TIME_NONE,
        GST_MESSAGE_ERROR | GST_MESSAGE_EOS
    );

    /* Parse message */
    if (msg != NULL)
    {
        GError *err;
        gchar *debug_info;

        switch (GST_MESSAGE_TYPE(msg))
        {
            case GST_MESSAGE_ERROR:
                gst_message_parse_error(msg, &err, &debug_info);

                g_printerr("Error received from element %s: %s\n",
                    GST_OBJECT_NAME (msg->src), err->message
                );
                g_printerr("Debugging information: %s\n",
                    debug_info ? debug_info : "none"
                );
                
                g_clear_error(&err);
                g_free(debug_info);
                break;
            case GST_MESSAGE_EOS:
                g_print("End-Of-Stream reached.\n");
                break;
            default:
                g_printerr("Unexpected message received.\n");
                break;
        }

        gst_object_unref(msg);
    }

printf("before unref\n");
    gst_object_unref(bus);
printf("unref bus\n");
    gst_element_set_state(pipeline, GST_STATE_NULL);
printf("set null\n");
out_unref:
    gst_object_unref(pipeline);
printf("unref pipeline\n");
out_return:
    return retval;
}

运行输出

mpp[871]: mpp_rt: NOT found ion allocator
mpp[871]: mpp_rt: found drm allocator
mpp[871]: mpp_info: mpp version: unknown mpp version for missing VCS info
mpp[871]: h264d_api: is_avcC=1
mpp[871]: hal_h264d_vdpu34x: control info: fmt 7, w 640, h 480
mpp[871]: mpp_buf_slot: set frame info: w  640 h  480 hor  640 ver  480
mpp[871]: mpp_dec: setting default w  640 h  480 h_str  640 v_str  480
End-Of-Stream reached.

(drmDemo:871): GLib-GObject-CRITICAL **: 14:14:57.520: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
before unref
unref bus
set null
unref pipeline

问题疑问

该unref异常是否由g_signal_connect引发,或是我在unref元素时操作有误?恳请提供解答或建议。


问题定位与修复

错误根源

这个断言错误和g_signal_connect无关,问题出在linkElements函数中:当gst_element_get_static_pad调用失败(比如无法找到指定名称的pad)时,会返回NULL,此时直接对NULL指针调用gst_object_unref就会触发G_IS_OBJECT (object)断言失败。

另外代码还存在潜在风险:调用gst_pad_link前未检查sinkPad是否有效,可能导致链接失败或崩溃。

修复方案

  1. 修改linkElements函数,增加空指针检查:
static void linkElements(GstElement* element, GstPad* sourcePad, gpointer sinkElement)
{
    GstPad* sinkPad = gst_element_get_static_pad((GstElement*)sinkElement, "sink");
    if (sinkPad != NULL) {
        gst_pad_link(sourcePad, sinkPad);
        gst_object_unref(sinkPad);
    } else {
        g_printerr("Failed to retrieve sink pad from element: %s\n", GST_OBJECT_NAME(sinkElement));
    }
}
  1. 调整资源释放顺序(更符合GStreamer最佳实践):
    将原代码中的释放顺序:
gst_object_unref(bus);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);

修改为:

gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(bus);
gst_object_unref(pipeline);

该调整不会直接修复当前错误,但能确保管道状态先重置,再释放相关资源,避免潜在的资源泄漏问题。


内容的提问来源于stack exchange,提问作者Chroluma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 17:11:11