我正在构建一个非常复杂的 gstreamer 应用程序,如果可能,它会尝试重用部分管道。无论如何,我怀疑管道没有正确清理,因为该过程不断堆积文件描述符并且不释放它们。
我怀疑重新计算的管道
GstElement
(以及随后的filesource
)以某种方式保持活动状态,因为我搞砸了重新计算。为了简化调试,有没有办法:
GstElement
的列表?一旦元素被添加到 bin 或管道责任由父级承担。如果父元素被正确销毁,那么该元素也将被销毁。
破坏管道你可以按照这个。
{
GstElement *pipeline = gst_pipeline_new ("mystuff")
.
.
.
// Do your stuff here
gst_element_send_event(GST_ELEMENT(pipeline), gst_event_new_eos());
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
gst_object_unref (pipeline);
}
如果您使用的是 C++,我建议使用简单的 RAII 包装器,这有助于资源生命周期管理。一个例子:
#include <gst/gst.h>
#include <memory>
#include <type_traits>
template <auto Fn>
using FunctionObj = std::integral_constant<decltype(Fn), Fn>;
template <typename T, auto Fun>
using ResourceReleasedByFunction = std::unique_ptr<T, FunctionObj<Fun>>;
template <typename T, auto Fun>
void AddressOfPtr(T* rsc) {
Fun(&rsc);
}
using ScopedGstElement = ResourceReleasedByFunction<GstElement, gst_object_unref>;
using ScopedGstCaps = ResourceReleasedByFunction<GstCaps, gst_caps_unref>;
using ScopedGstSample = ResourceReleasedByFunction<GstSample, gst_sample_unref>;
using ScopedGstBuffer = ResourceReleasedByFunction<GstBuffer, gst_buffer_unref>;
using ScopedGstPad = ResourceReleasedByFunction<GstPad, gst_object_unref>;
using ScopedGstBus = ResourceReleasedByFunction<GstBus, gst_object_unref>;
using ScopedGChar = ResourceReleasedByFunction<gchar, g_free>;
using ScopedGError = ResourceReleasedByFunction<GError, AddressOfPtr<GError, g_clear_error>>;
using ScopedGMainContext = ResourceReleasedByFunction<GMainContext, g_main_context_unref>;
using ScopedGMainLoop = ResourceReleasedByFunction<GMainLoop, g_main_loop_unref>;
用法示例:
ScopedGstElement pipeline{gst_pipeline_new("mypipeline")};
ScopedGstElement camerasource{gst_element_factory_make("v4l2src", "v4l2src")};
ScopedGstElement videoconvert{gst_element_factory_make("videoconvert", "videoscale")};
ScopedGstElement videosink{gst_element_factory_make("fakesink", "fakesink")};
gst_bin_add_many(GST_BIN(pipeline.get()), camerasource.release(), videoconvert.release(), videosink.release(), nullptr);
多亏了你不需要记得清理资源,甚至当你记得你可能会调用一个无效的函数,例如
gst_object_unref
而不是gst_buffer_unref
等