[Spice-devel] [RFC v2 1/5] gstreamer-encoder: Use a dmabuf allocator for a valid fd
Vivek Kasireddy
vivek.kasireddy at intel.com
Mon Jan 23 08:41:19 UTC 2023
If a valid dmabuf fd is shared with the encoder, then this patch
enables the creation of Gst memory with the fd as the source by
using a dmabuf allocator. This patch also adds code to invoke
any registered callbacks after the Gst memory object is no longer
in use by the pipeline.
Cc: Gerd Hoffmann <kraxel at redhat.com>
Cc: Marc-André Lureau <marcandre.lureau at redhat.com>
Cc: Dongwon Kim <dongwon.kim at intel.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy at intel.com>
---
meson.build | 2 +-
server/gstreamer-encoder.c | 48 +++++++++++++++++++++++++++++++++++---
server/video-encoder.h | 7 ++++++
3 files changed, 53 insertions(+), 4 deletions(-)
diff --git a/meson.build b/meson.build
index ef8b41ad..d66fac10 100644
--- a/meson.build
+++ b/meson.build
@@ -131,7 +131,7 @@ endforeach
spice_server_has_gstreamer = false
spice_server_gst_version = get_option('gstreamer')
if spice_server_gst_version != 'no'
- gst_deps = ['gstreamer', 'gstreamer-base', 'gstreamer-app', 'gstreamer-video']
+ gst_deps = ['gstreamer', 'gstreamer-base', 'gstreamer-app', 'gstreamer-video', 'gstreamer-allocators']
foreach dep : gst_deps
dep = '@0 at -@1@'.format(dep, spice_server_gst_version)
spice_server_deps += dependency(dep)
diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index 5ea11f4b..f590a495 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -22,6 +22,7 @@
#include <pthread.h>
#include <gst/gst.h>
+#include <gst/allocators/gstdmabuf.h>
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
#include <gst/video/video.h>
@@ -298,6 +299,8 @@ typedef struct SpiceGstEncoder {
/* How many frames were dropped by the server since the last encoded frame. */
uint32_t server_drops;
+
+ GstAllocator *allocator;
} SpiceGstEncoder;
@@ -335,8 +338,12 @@ static inline double get_mbps(uint64_t bit_rate)
*/
static uint32_t get_source_fps(const SpiceGstEncoder *encoder)
{
- return encoder->cbs.get_source_fps ?
- encoder->cbs.get_source_fps(encoder->cbs.opaque) : SPICE_GST_DEFAULT_FPS;
+ uint32_t source_fps = 0;
+
+ if (encoder->cbs.get_source_fps) {
+ source_fps = encoder->cbs.get_source_fps(encoder->cbs.opaque);
+ }
+ return source_fps ? source_fps : SPICE_GST_DEFAULT_FPS;
}
static uint32_t get_network_latency(const SpiceGstEncoder *encoder)
@@ -1346,6 +1353,23 @@ static void unmap_and_release_memory(GstMapInfo *map, GstBuffer *buffer)
gst_buffer_unref(buffer);
}
+static void bitmap_wrapper_weak_unref(BitmapWrapper *wrapper,
+ GstMiniObject *obj)
+{
+ VideoEncoder *encoder = &wrapper->encoder->base;
+
+ if (g_atomic_int_dec_and_test(&wrapper->refs)) {
+ g_async_queue_push(wrapper->encoder->unused_bitmap_opaques,
+ wrapper->opaque);
+ g_free(wrapper);
+ }
+ if (encoder->dmabuf_data) {
+ encoder->dmabuf_data->notify_mem_free(encoder->dmabuf_data->opaque);
+ g_free(encoder->dmabuf_data);
+ encoder->dmabuf_data = NULL;
+ }
+}
+
/* A helper for spice_gst_encoder_encode_frame() */
static VideoEncodeResults
push_raw_frame(SpiceGstEncoder *encoder,
@@ -1367,7 +1391,23 @@ push_raw_frame(SpiceGstEncoder *encoder,
uint32_t skip_lines = top_down ? src->top : bitmap->y - (src->bottom - 0);
uint32_t chunk_offset = bitmap->stride * skip_lines;
- if (stream_stride != bitmap->stride) {
+ if (encoder->base.dmabuf_data) {
+ GstMemory *mem = NULL;
+ BitmapWrapper *wrapper = NULL;
+ int fd = encoder->base.dmabuf_data->dmabuf_fd;
+
+ mem = gst_dmabuf_allocator_alloc_with_flags(encoder->allocator,
+ fd, stream_stride * height,
+ GST_FD_MEMORY_FLAG_DONT_CLOSE);
+ if (!mem) {
+ return VIDEO_ENCODER_FRAME_UNSUPPORTED;
+ }
+ gst_buffer_append_memory(buffer, mem);
+ wrapper = bitmap_wrapper_new(encoder, bitmap_opaque);
+ gst_mini_object_weak_ref(GST_MINI_OBJECT(mem),
+ (GstMiniObjectNotify)bitmap_wrapper_weak_unref,
+ wrapper);
+ } else if (stream_stride != bitmap->stride) {
/* We have to do a line-by-line copy because for each we have to
* leave out pixels on the left or right.
*/
@@ -1456,6 +1496,7 @@ static void spice_gst_encoder_destroy(VideoEncoder *video_encoder)
{
SpiceGstEncoder *encoder = (SpiceGstEncoder*)video_encoder;
+ gst_object_unref(encoder->allocator);
free_pipeline(encoder);
pthread_mutex_destroy(&encoder->outbuf_mutex);
pthread_cond_destroy(&encoder->outbuf_cond);
@@ -1772,6 +1813,7 @@ VideoEncoder *gstreamer_encoder_new(SpiceVideoCodecType codec_type,
encoder->bitmap_ref = bitmap_ref;
encoder->bitmap_unref = bitmap_unref;
encoder->format = GSTREAMER_FORMAT_INVALID;
+ encoder->allocator = gst_dmabuf_allocator_new();
pthread_mutex_init(&encoder->outbuf_mutex, NULL);
pthread_cond_init(&encoder->outbuf_cond, NULL);
diff --git a/server/video-encoder.h b/server/video-encoder.h
index d5bc0a68..03a6f34d 100644
--- a/server/video-encoder.h
+++ b/server/video-encoder.h
@@ -56,6 +56,12 @@ typedef struct VideoEncoderStats {
double avg_quality;
} VideoEncoderStats;
+typedef struct VideoEncoderDmabufData {
+ int32_t dmabuf_fd;
+ void *opaque;
+ void (*notify_mem_free)(void *opaque);
+} VideoEncoderDmabufData;
+
typedef struct VideoEncoder VideoEncoder;
struct VideoEncoder {
/* Releases the video encoder's resources */
@@ -142,6 +148,7 @@ struct VideoEncoder {
/* The codec being used by the video encoder */
SpiceVideoCodecType codec_type;
+ VideoEncoderDmabufData *dmabuf_data;
};
--
2.37.2
More information about the Spice-devel
mailing list