diff --git a/server/dcc-send.cpp b/server/dcc-send.cpp index 25108c11..31c37dc6 100644 --- a/server/dcc-send.cpp +++ b/server/dcc-send.cpp @@ -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); diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c index 8fcfc34b..f34f37e2 100644 --- a/server/gstreamer-encoder.c +++ b/server/gstreamer-encoder.c @@ -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); diff --git a/server/video-encoder.h b/server/video-encoder.h index b1ec63ee..57d9b9b9 100644 --- a/server/video-encoder.h +++ b/server/video-encoder.h @@ -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; diff --git a/server/video-stream.cpp b/server/video-stream.cpp index 6048dd60..798b7206 100644 --- a/server/video-stream.cpp +++ b/server/video-stream.cpp @@ -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. */ diff --git a/server/video-stream.h b/server/video-stream.h index d3f25bb3..62229c8c 100644 --- a/server/video-stream.h +++ b/server/video-stream.h @@ -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;