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是否有效,可能导致链接失败或崩溃。
修复方案
- 修改
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)); } }
- 调整资源释放顺序(更符合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
相关产品推荐
相关产品推荐

