gstreamer-encoder: add multi-plane support for gstreamer-encoder

This commit is contained in:
Michael Scherle 2025-06-11 10:33:23 +02:00
parent c464464005
commit a12e52aaf7
5 changed files with 34 additions and 19 deletions

View File

@ -1793,19 +1793,28 @@ static void red_marshall_gl_draw_stream(DisplayChannelClient *dcc,
return;
}
/* TODO: add support for it */
if (scanout->num_planes > 1) {
spice_warning("Video encoder Does not support multi plane");
if (scanout->num_planes > 4) {
spice_warning("Video encoder does not support more than 4 planes");
red_qxl_put_gl_scanout(qxl, scanout);
delete dmabuf_data;
return;
}
dmabuf_data->drm_dma_buf_fd = dup(scanout->fd[0]);
for (int i = 0; i < scanout->num_planes; i++) {
if (scanout->fd[i] < 0) {
spice_warning("Invalid fd for scanout plane %d", i);
red_qxl_put_gl_scanout(qxl, scanout);
delete dmabuf_data;
return;
}
dmabuf_data->drm_dma_buf_fd[i] = scanout->fd[i];
dmabuf_data->stride[i] = (int)scanout->stride[i];
dmabuf_data->offset[i] = (size_t)scanout->offset[i];
}
dmabuf_data->num_planes = scanout->num_planes;
dmabuf_data->drm_fourcc_format = scanout->fourcc;
dmabuf_data->width = stream->width;
dmabuf_data->height = stream->height;
dmabuf_data->stride = stream->stride;
dmabuf_data->dcc = dcc;
dmabuf_data->free = red_free_cb;
red_qxl_put_gl_scanout(qxl, scanout);

View File

@ -1855,22 +1855,28 @@ spice_gst_encoder_encode_dmabuf(VideoEncoder *video_encoder,
return rc;
}
gsize size = dmabuf_data->stride * dmabuf_data->height;
uint64_t start = spice_get_monotonic_time_ns();
GstBuffer *buffer;
GstMemory *mem;
*outbuf = NULL;
rc = VIDEO_ENCODER_FRAME_UNSUPPORTED;
mem = gst_dmabuf_allocator_alloc(encoder->allocator,
dmabuf_data->drm_dma_buf_fd,
size);
if (!mem) {
return rc;
}
buffer = gst_buffer_new();
gst_buffer_append_memory(buffer, mem);
gst_mini_object_weak_ref(GST_MINI_OBJECT(mem),
for (int i = 0; i < dmabuf_data->num_planes; i++) {
gsize size = dmabuf_data->stride[i] * dmabuf_data->height;
GstMemory *mem
= gst_dmabuf_allocator_alloc_with_flags(encoder->allocator,
dmabuf_data->drm_dma_buf_fd[i],
size,
GST_FD_MEMORY_FLAG_DONT_CLOSE);
if (!mem) {
gst_buffer_unref(buffer);
return rc;
}
gst_buffer_append_memory(buffer, mem);
}
gst_mini_object_weak_ref(GST_MINI_OBJECT(buffer),
(GstMiniObjectNotify)spice_gst_mem_free_cb,
dmabuf_data);
GstFlowReturn ret = gst_app_src_push_buffer(encoder->appsrc, buffer);

View File

@ -57,10 +57,12 @@ typedef struct VideoEncoderStats {
} VideoEncoderStats;
typedef struct VideoEncoderDmabufData {
int drm_dma_buf_fd;
int drm_dma_buf_fd[4];
int num_planes;
uint32_t width;
uint32_t height;
uint32_t stride;
int stride[4];
size_t offset[4];
uint32_t drm_fourcc_format;
void (*free)(struct VideoEncoderDmabufData*);
} VideoEncoderDmabufData;

View File

@ -478,7 +478,6 @@ bool display_channel_create_gl_draw_stream(DisplayChannel *display)
ret = true;
display_channel_init_stream(display, stream, nullptr, &dest_area);
stream->top_down = (scanout->flags & SPICE_GL_SCANOUT_FLAGS_Y0TOP) ? 0 : 1;
stream->stride = scanout->stride[0];
/* This is the upper bound; it should be possible to stream at 60 FPS
* with a hardware based encoder.
*/

View File

@ -112,7 +112,6 @@ struct VideoStream {
red_time_t last_time;
int width;
int height;
uint32_t stride;
SpiceRect dest_area;
int top_down;
VideoStream *next;