diff options
author | Tim Blechmann <tim@klingt.org> | 2024-04-23 20:10:29 +0800 |
---|---|---|
committer | Tim Blechmann <tim@klingt.org> | 2024-04-26 08:00:47 +0800 |
commit | b8d296c8df903bb09c8a546f160616431c0cbb62 (patch) | |
tree | 629e0af6d1bd2e80dbe5048c42034248c55d383c | |
parent | 18f699b667982b60fbd7d3adc539cde81e742c2b (diff) |
GStreamer: reference counting cleanups
Simplify reference counting by using handle types
Pick-to: 6.5 6.7
Change-Id: I78788cb73e9597dc9fcd37d86d4ae179dea7bdbf
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
12 files changed, 83 insertions, 60 deletions
diff --git a/src/plugins/multimedia/gstreamer/common/qgst.cpp b/src/plugins/multimedia/gstreamer/common/qgst.cpp index 83d95a9e2..ebcc278d7 100644 --- a/src/plugins/multimedia/gstreamer/common/qgst.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgst.cpp @@ -482,6 +482,14 @@ QGstCaps QGstCaps::fromCameraFormat(const QCameraFormat &format) return caps; } +QGstCaps QGstCaps::copy() const +{ + return QGstCaps{ + gst_caps_copy(caps()), + QGstCaps::HasRef, + }; +} + QGstCaps::MemoryFormat QGstCaps::memoryFormat() const { auto *features = gst_caps_get_features(get(), 0); diff --git a/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h b/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h index b72e92db1..c37ac5971 100644 --- a/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h +++ b/src/plugins/multimedia/gstreamer/common/qgst_handle_types_p.h @@ -46,7 +46,7 @@ struct QSharedHandle : private QUniqueHandle<HandleTraits> } QSharedHandle(const QSharedHandle &o) - : QSharedHandle{ + : BaseClass{ HandleTraits::ref(o.get()), } { @@ -238,6 +238,7 @@ using QUniqueGstStructureHandle = QUniqueHandle<QGstImpl::QUniqueGstStructureHan using QUniqueGStringHandle = QUniqueHandle<QGstImpl::QUniqueGStringHandleTraits>; using QUniqueGErrorHandle = QUniqueHandle<QGstImpl::QUniqueGErrorHandleTraits>; using QFileDescriptorHandle = QUniqueHandle<QGstImpl::QFileDescriptorHandleTraits>; +using QGstBufferHandle = QGstImpl::QGstMiniObjectHandleHelper<GstBuffer>::SharedHandle; using QGstContextHandle = QGstImpl::QGstMiniObjectHandleHelper<GstContext>::UniqueHandle; using QGstGstDateTimeHandle = QGstImpl::QGstMiniObjectHandleHelper<GstDateTime>::SharedHandle; using QGstPluginFeatureHandle = QGstImpl::QGstHandleHelper<GstPluginFeature>::SharedHandle; diff --git a/src/plugins/multimedia/gstreamer/common/qgst_p.h b/src/plugins/multimedia/gstreamer/common/qgst_p.h index ab264f552..d569a743d 100644 --- a/src/plugins/multimedia/gstreamer/common/qgst_p.h +++ b/src/plugins/multimedia/gstreamer/common/qgst_p.h @@ -333,6 +333,8 @@ public: static QGstCaps create(); static QGstCaps fromCameraFormat(const QCameraFormat &format); + + QGstCaps copy() const; }; template <> diff --git a/src/plugins/multimedia/gstreamer/common/qgstreamerbufferprobe.cpp b/src/plugins/multimedia/gstreamer/common/qgstreamerbufferprobe.cpp index 341cb69b3..9cba810db 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstreamerbufferprobe.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgstreamerbufferprobe.cpp @@ -3,6 +3,8 @@ #include <common/qgstreamerbufferprobe_p.h> +#include <common/qgst_p.h> + QT_BEGIN_NAMESPACE QGstreamerBufferProbe::QGstreamerBufferProbe(Flags flags) @@ -14,10 +16,14 @@ QGstreamerBufferProbe::~QGstreamerBufferProbe() = default; void QGstreamerBufferProbe::addProbeToPad(GstPad *pad, bool downstream) { - if (GstCaps *caps = gst_pad_get_current_caps(pad)) { - probeCaps(caps); - gst_caps_unref(caps); - } + QGstCaps caps{ + gst_pad_get_current_caps(pad), + QGstCaps::HasRef, + }; + + if (caps) + probeCaps(caps.caps()); + if (m_flags & ProbeCaps) { m_capsProbeId = gst_pad_add_probe( pad, diff --git a/src/plugins/multimedia/gstreamer/common/qgstutils.cpp b/src/plugins/multimedia/gstreamer/common/qgstutils.cpp index d3d5f6124..40fb4b6f7 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstutils.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgstutils.cpp @@ -115,7 +115,7 @@ QList<QAudioFormat::SampleFormat> QGValue::getSampleFormats() const return formats; } -void QGstUtils::setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer) +void QGstUtils::setFrameTimeStampsFromBuffer(QVideoFrame *frame, GstBuffer *buffer) { using namespace std::chrono; using namespace std::chrono_literals; diff --git a/src/plugins/multimedia/gstreamer/common/qgstutils_p.h b/src/plugins/multimedia/gstreamer/common/qgstutils_p.h index 4141ae0bf..c65fcf090 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstutils_p.h +++ b/src/plugins/multimedia/gstreamer/common/qgstutils_p.h @@ -31,7 +31,7 @@ QAudioFormat audioFormatForSample(GstSample *sample); QAudioFormat audioFormatForCaps(const QGstCaps &caps); QGstCaps capsForAudioFormat(const QAudioFormat &format); -void setFrameTimeStamps(QVideoFrame *frame, GstBuffer *buffer); +void setFrameTimeStampsFromBuffer(QVideoFrame *frame, GstBuffer *buffer); } // namespace QGstUtils GList *qt_gst_video_sinks(); diff --git a/src/plugins/multimedia/gstreamer/common/qgstvideobuffer.cpp b/src/plugins/multimedia/gstreamer/common/qgstvideobuffer.cpp index 101d56af6..6552786bb 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstvideobuffer.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgstvideobuffer.cpp @@ -51,18 +51,19 @@ QT_BEGIN_NAMESPACE #define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */ #define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */ -QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, QGstreamerVideoSink *sink, - const QVideoFrameFormat &frameFormat, +QGstVideoBuffer::QGstVideoBuffer(QGstBufferHandle buffer, const GstVideoInfo &info, + QGstreamerVideoSink *sink, const QVideoFrameFormat &frameFormat, QGstCaps::MemoryFormat format) - : QAbstractVideoBuffer((sink && sink->rhi() && format != QGstCaps::CpuMemory) ? - QVideoFrame::RhiTextureHandle : QVideoFrame::NoHandle, sink ? sink->rhi() : nullptr) - , memoryFormat(format) - , m_frameFormat(frameFormat) - , m_rhi(sink ? sink->rhi() : nullptr) - , m_videoInfo(info) - , m_buffer(buffer) + : QAbstractVideoBuffer((sink && sink->rhi() && format != QGstCaps::CpuMemory) + ? QVideoFrame::RhiTextureHandle + : QVideoFrame::NoHandle, + sink ? sink->rhi() : nullptr), + memoryFormat(format), + m_frameFormat(frameFormat), + m_rhi(sink ? sink->rhi() : nullptr), + m_videoInfo(info), + m_buffer(std::move(buffer)) { - gst_buffer_ref(m_buffer); if (sink) { eglDisplay = sink->eglDisplay(); eglImageTargetTexture2D = sink->eglImageTargetTexture2D(); @@ -76,8 +77,6 @@ QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, QG QGstVideoBuffer::~QGstVideoBuffer() { unmap(); - - gst_buffer_unref(m_buffer); } @@ -96,7 +95,7 @@ QAbstractVideoBuffer::MapData QGstVideoBuffer::map(QVideoFrame::MapMode mode) return mapData; if (m_videoInfo.finfo->n_planes == 0) { // Encoded - if (gst_buffer_map(m_buffer, &m_frame.map[0], flags)) { + if (gst_buffer_map(m_buffer.get(), &m_frame.map[0], flags)) { mapData.nPlanes = 1; mapData.bytesPerLine[0] = -1; mapData.size[0] = m_frame.map[0].size; @@ -104,7 +103,7 @@ QAbstractVideoBuffer::MapData QGstVideoBuffer::map(QVideoFrame::MapMode mode) m_mode = mode; } - } else if (gst_video_frame_map(&m_frame, &m_videoInfo, m_buffer, flags)) { + } else if (gst_video_frame_map(&m_frame, &m_videoInfo, m_buffer.get(), flags)) { mapData.nPlanes = GST_VIDEO_FRAME_N_PLANES(&m_frame); for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES(&m_frame); ++i) { @@ -122,7 +121,7 @@ void QGstVideoBuffer::unmap() { if (m_mode != QVideoFrame::NotMapped) { if (m_videoInfo.finfo->n_planes == 0) - gst_buffer_unmap(m_buffer, &m_frame.map[0]); + gst_buffer_unmap(m_buffer.get(), &m_frame.map[0]); else gst_video_frame_unmap(&m_frame); } @@ -258,9 +257,10 @@ private: std::unique_ptr<QRhiTexture> m_textures[QVideoTextureHelper::TextureDescription::maxPlanes]; }; - -static GlTextures mapFromGlTexture(GstBuffer *buffer, GstVideoFrame &frame, GstVideoInfo &videoInfo) +static GlTextures mapFromGlTexture(const QGstBufferHandle &bufferHandle, GstVideoFrame &frame, + GstVideoInfo &videoInfo) { + GstBuffer *buffer = bufferHandle.get(); auto *mem = GST_GL_BASE_MEMORY_CAST(gst_buffer_peek_memory(buffer, 0)); if (!mem) return {}; @@ -293,10 +293,12 @@ static GlTextures mapFromGlTexture(GstBuffer *buffer, GstVideoFrame &frame, GstV } #if GST_GL_HAVE_PLATFORM_EGL && QT_CONFIG(linux_dmabuf) -static GlTextures mapFromDmaBuffer(QRhi *rhi, GstBuffer *buffer, GstVideoFrame &frame, - GstVideoInfo &videoInfo, Qt::HANDLE eglDisplay, - QFunctionPointer eglImageTargetTexture2D) +static GlTextures mapFromDmaBuffer(QRhi *rhi, const QGstBufferHandle &bufferHandle, + GstVideoFrame &frame, GstVideoInfo &videoInfo, + Qt::HANDLE eglDisplay, QFunctionPointer eglImageTargetTexture2D) { + GstBuffer *buffer = bufferHandle.get(); + Q_ASSERT(gst_is_dmabuf_memory(gst_buffer_peek_memory(buffer, 0))); Q_ASSERT(eglDisplay); Q_ASSERT(eglImageTargetTexture2D); @@ -377,14 +379,15 @@ std::unique_ptr<QVideoFrameTextures> QGstVideoBuffer::mapTextures(QRhi *rhi) #if QT_CONFIG(gstreamer_gl) GlTextures textures = {}; - if (memoryFormat == QGstCaps::GLTexture) { + if (memoryFormat == QGstCaps::GLTexture) textures = mapFromGlTexture(m_buffer, m_frame, m_videoInfo); - } -#if GST_GL_HAVE_PLATFORM_EGL && QT_CONFIG(linux_dmabuf) - else if (memoryFormat == QGstCaps::DMABuf) { - textures = mapFromDmaBuffer(m_rhi, m_buffer, m_frame, m_videoInfo, eglDisplay, eglImageTargetTexture2D); - } -#endif + +# if GST_GL_HAVE_PLATFORM_EGL && QT_CONFIG(linux_dmabuf) + else if (memoryFormat == QGstCaps::DMABuf) + textures = mapFromDmaBuffer(m_rhi, m_buffer, m_frame, m_videoInfo, eglDisplay, + eglImageTargetTexture2D); + +# endif if (textures.count > 0) return std::make_unique<QGstQVideoFrameTextures>(rhi, QSize{m_videoInfo.width, m_videoInfo.height}, m_frameFormat.pixelFormat(), textures); diff --git a/src/plugins/multimedia/gstreamer/common/qgstvideobuffer_p.h b/src/plugins/multimedia/gstreamer/common/qgstvideobuffer_p.h index 27567c9f7..151927d3d 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstvideobuffer_p.h +++ b/src/plugins/multimedia/gstreamer/common/qgstvideobuffer_p.h @@ -30,12 +30,10 @@ class QOpenGLContext; class QGstVideoBuffer final : public QAbstractVideoBuffer { public: - - QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, QGstreamerVideoSink *sink, + QGstVideoBuffer(QGstBufferHandle buffer, const GstVideoInfo &info, QGstreamerVideoSink *sink, const QVideoFrameFormat &frameFormat, QGstCaps::MemoryFormat format); ~QGstVideoBuffer(); - GstBuffer *buffer() const { return m_buffer; } QVideoFrame::MapMode mapMode() const override; MapData map(QVideoFrame::MapMode mode) override; @@ -49,7 +47,7 @@ private: QRhi *m_rhi = nullptr; mutable GstVideoInfo m_videoInfo; mutable GstVideoFrame m_frame{}; - GstBuffer *m_buffer = nullptr; + const QGstBufferHandle m_buffer; QVideoFrame::MapMode m_mode = QVideoFrame::NotMapped; Qt::HANDLE eglDisplay = nullptr; QFunctionPointer eglImageTargetTexture2D = nullptr; diff --git a/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink.cpp b/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink.cpp index ec4cbb468..4e9619b11 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink.cpp @@ -177,7 +177,7 @@ void QGstVideoRenderer::flush() QMutexLocker locker(&m_mutex); m_flush = true; - m_renderBuffer = nullptr; + m_renderBuffer = {}; m_renderCondition.wakeAll(); notify(); @@ -189,11 +189,14 @@ GstFlowReturn QGstVideoRenderer::render(GstBuffer *buffer) qCDebug(qLcGstVideoRenderer) << "QGstVideoRenderer::render"; m_renderReturn = GST_FLOW_OK; - m_renderBuffer = buffer; + m_renderBuffer = QGstBufferHandle{ + buffer, + QGstBufferHandle::NeedsRef, + }; waitForAsyncEvent(&locker, &m_renderCondition, 300); - m_renderBuffer = nullptr; + m_renderBuffer = {}; return m_renderReturn; } @@ -353,19 +356,17 @@ bool QGstVideoRenderer::handleEvent(QMutexLocker<QMutex> *locker) } } else if (m_renderBuffer) { - GstBuffer *buffer = m_renderBuffer; - m_renderBuffer = nullptr; + QGstBufferHandle buffer = std::move(m_renderBuffer); m_renderReturn = GST_FLOW_ERROR; qCDebug(qLcGstVideoRenderer) << "QGstVideoRenderer::handleEvent(renderBuffer)" << m_active << m_sink; if (m_active && m_sink) { - gst_buffer_ref(buffer); locker->unlock(); m_flushed = false; - GstVideoCropMeta *meta = gst_buffer_get_video_crop_meta(buffer); + GstVideoCropMeta *meta = gst_buffer_get_video_crop_meta(buffer.get()); if (meta) { QRect vp(meta->x, meta->y, meta->width, meta->height); if (m_format.viewport() != vp) { @@ -381,7 +382,7 @@ bool QGstVideoRenderer::handleEvent(QMutexLocker<QMutex> *locker) } else { QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, m_videoInfo, m_sink, m_format, memoryFormat); QVideoFrame frame(videoBuffer, m_format); - QGstUtils::setFrameTimeStamps(&frame, buffer); + QGstUtils::setFrameTimeStampsFromBuffer(&frame, buffer.get()); frame.setMirrored(m_frameMirrored); frame.setRotation(m_frameRotationAngle); @@ -389,8 +390,6 @@ bool QGstVideoRenderer::handleEvent(QMutexLocker<QMutex> *locker) m_sink->setVideoFrame(frame); } - gst_buffer_unref(buffer); - locker->relock(); m_renderReturn = GST_FLOW_OK; diff --git a/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink_p.h b/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink_p.h index e381e48e1..99d1b0ac8 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink_p.h +++ b/src/plugins/multimedia/gstreamer/common/qgstvideorenderersink_p.h @@ -77,7 +77,7 @@ private: const QGstCaps m_surfaceCaps; QGstCaps m_startCaps; - GstBuffer *m_renderBuffer = nullptr; + QGstBufferHandle m_renderBuffer; bool m_notified = false; bool m_stop = false; diff --git a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp index cb1d174cd..6e518e9fb 100644 --- a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp +++ b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamerimagecapture.cpp @@ -145,15 +145,15 @@ int QGstreamerImageCapture::doCapture(const QString &fileName) void QGstreamerImageCapture::setResolution(const QSize &resolution) { - auto padCaps = QGstCaps(gst_pad_get_current_caps(bin.staticPad("sink").pad()), QGstCaps::HasRef); + QGstCaps padCaps = bin.staticPad("sink").currentCaps(); if (padCaps.isNull()) { qDebug() << "Camera not ready"; return; } - auto caps = QGstCaps(gst_caps_copy(padCaps.caps()), QGstCaps::HasRef); - if (caps.isNull()) { + QGstCaps caps = padCaps.copy(); + if (caps.isNull()) return; - } + gst_caps_set_simple(caps.caps(), "width", G_TYPE_INT, resolution.width(), "height", G_TYPE_INT, resolution.height(), nullptr); filter.set("caps", caps); @@ -165,12 +165,16 @@ bool QGstreamerImageCapture::probeBuffer(GstBuffer *buffer) return false; qCDebug(qLcImageCaptureGst) << "probe buffer"; + QGstBufferHandle bufferHandle{ + buffer, + QGstBufferHandle::NeedsRef, + }; + passImage = false; emit readyForCaptureChanged(isReadyForCapture()); - auto caps = QGstCaps(gst_pad_get_current_caps(bin.staticPad("sink").pad()), QGstCaps::HasRef); - + QGstCaps caps = bin.staticPad("sink").currentCaps(); auto memoryFormat = caps.memoryFormat(); GstVideoInfo previewInfo; @@ -180,7 +184,9 @@ bool QGstreamerImageCapture::probeBuffer(GstBuffer *buffer) std::tie(fmt, previewInfo) = std::move(*optionalFormatAndVideoInfo); auto *sink = m_session->gstreamerVideoSink(); - auto *gstBuffer = new QGstVideoBuffer(buffer, previewInfo, sink, fmt, memoryFormat); + auto *gstBuffer = new QGstVideoBuffer{ + std::move(bufferHandle), previewInfo, sink, fmt, memoryFormat, + }; QVideoFrame frame(gstBuffer, fmt); QImage img = frame.toImage(); if (img.isNull()) { diff --git a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp index 839187a9d..0574a1f1a 100644 --- a/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp +++ b/src/plugins/multimedia/gstreamer/mediacapture/qgstreamermediacapture.cpp @@ -198,12 +198,12 @@ void QGstreamerMediaCapture::linkEncoder(QGstPad audioSink, QGstPad videoSink) { gstPipeline.modifyPipelineWhileNotRunning([&] { if (!gstVideoTee.isNull() && !videoSink.isNull()) { - auto caps = gst_pad_get_current_caps(gstVideoTee.sink().pad()); + QGstCaps caps = gstVideoTee.sink().currentCaps(); encoderVideoCapsFilter = QGstElement::createFromFactory("capsfilter", "encoderVideoCapsFilter"); Q_ASSERT(encoderVideoCapsFilter); - encoderVideoCapsFilter.set("caps", QGstCaps(caps, QGstCaps::HasRef)); + encoderVideoCapsFilter.set("caps", caps); gstPipeline.add(encoderVideoCapsFilter); @@ -213,12 +213,12 @@ void QGstreamerMediaCapture::linkEncoder(QGstPad audioSink, QGstPad videoSink) } if (!gstAudioTee.isNull() && !audioSink.isNull()) { - auto caps = gst_pad_get_current_caps(gstAudioTee.sink().pad()); + QGstCaps caps = gstAudioTee.sink().currentCaps(); encoderAudioCapsFilter = QGstElement::createFromFactory("capsfilter", "encoderAudioCapsFilter"); Q_ASSERT(encoderAudioCapsFilter); - encoderAudioCapsFilter.set("caps", QGstCaps(caps, QGstCaps::HasRef)); + encoderAudioCapsFilter.set("caps", caps); gstPipeline.add(encoderAudioCapsFilter); |