linuxOS_AP06/buildroot/package/gstreamer1/gst1-plugins-bad/0038-kmssink-Support-scaling-in-modesetting.patch
2025-06-03 12:28:32 +08:00

323 lines
9.6 KiB
Diff

From a244a8f4ab162a8c24ea8cf71c74484e88b459a7 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Thu, 15 Sep 2022 18:01:12 +0800
Subject: [PATCH 38/48] kmssink: Support scaling in modesetting
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
sys/kms/gstkmssink.c | 131 +++++++++++++++++++++++++++++--------------
sys/kms/gstkmssink.h | 1 +
2 files changed, 90 insertions(+), 42 deletions(-)
diff --git a/sys/kms/gstkmssink.c b/sys/kms/gstkmssink.c
index 88fc30d..c2a889d 100644
--- a/sys/kms/gstkmssink.c
+++ b/sys/kms/gstkmssink.c
@@ -79,6 +79,7 @@ static GstFlowReturn gst_kms_sink_show_frame (GstVideoSink * vsink,
GstBuffer * buf);
static void gst_kms_sink_video_overlay_init (GstVideoOverlayInterface * iface);
static void gst_kms_sink_drain (GstKMSSink * self);
+static gboolean gst_kms_sink_calculate_display_ratio (GstKMSSink * self, GstVideoInfo * vinfo, gint * scaled_width, gint * scaled_height);
#define parent_class gst_kms_sink_parent_class
G_DEFINE_TYPE_WITH_CODE (GstKMSSink, gst_kms_sink, GST_TYPE_VIDEO_SINK,
@@ -581,12 +582,13 @@ find_plane_for_crtc (int fd, drmModeRes * res, drmModePlaneRes * pres,
plane = drmModeGetPlane (fd, pres->planes[i]);
plane_type = drm_plane_get_type (fd, plane);
- /* Check unused possible planes */
- if (plane->possible_crtcs & (1 << pipe) && !plane->fb_id) {
+ /* Check possible planes */
+ if (plane->possible_crtcs & (1 << pipe)) {
if (plane->plane_id == preferred)
return plane;
- if (!fallback && plane_type == DRM_PLANE_TYPE_OVERLAY) {
+ if (!fallback && !plane->fb_id &&
+ plane_type == DRM_PLANE_TYPE_OVERLAY) {
/* Fallback to the first unused overlay plane */
fallback = plane->plane_id;
}
@@ -594,7 +596,7 @@ find_plane_for_crtc (int fd, drmModeRes * res, drmModePlaneRes * pres,
drmModeFreePlane (plane);
}
- if (fallback)
+ if (!preferred && fallback)
return drmModeGetPlane (fd, fallback);
return NULL;
@@ -832,13 +834,15 @@ configure_mode_setting (GstKMSSink * self, GstVideoInfo * vinfo)
drmModeConnector *conn;
int err;
gint i;
- drmModeModeInfo *mode;
+ drmModeModeInfo *mode, *preferred;
guint32 fb_id;
GstKMSMemory *kmsmem;
+ GstVideoInfo *info;
ret = FALSE;
conn = NULL;
mode = NULL;
+ preferred = NULL;
kmsmem = NULL;
if (self->conn_id < 0)
@@ -846,33 +850,55 @@ configure_mode_setting (GstKMSSink * self, GstVideoInfo * vinfo)
GST_INFO_OBJECT (self, "configuring mode setting");
- ensure_kms_allocator (self);
- kmsmem = (GstKMSMemory *) gst_kms_allocator_bo_alloc (self->allocator, vinfo);
- if (!kmsmem)
- goto bo_failed;
- fb_id = kmsmem->fb_id;
-
conn = drmModeGetConnector (self->fd, self->conn_id);
if (!conn)
goto connector_failed;
for (i = 0; i < conn->count_modes; i++) {
- if (conn->modes[i].vdisplay == GST_VIDEO_INFO_HEIGHT (vinfo) &&
- conn->modes[i].hdisplay == GST_VIDEO_INFO_WIDTH (vinfo)) {
+ if (!preferred && (conn->modes[i].type & DRM_MODE_TYPE_PREFERRED))
+ preferred = &conn->modes[i];
+
+ if (!mode && conn->modes[i].vdisplay == GST_VIDEO_INFO_HEIGHT (vinfo) &&
+ conn->modes[i].hdisplay == GST_VIDEO_INFO_WIDTH (vinfo))
mode = &conn->modes[i];
- break;
- }
}
+
+ if (preferred && (self->can_scale || !mode))
+ mode = preferred;
+
+ /* Fallback to the latest mode */
+ if (!mode && conn->count_modes)
+ mode = &conn->modes[conn->count_modes - 1];
+
if (!mode)
goto mode_failed;
+ info = gst_video_info_new ();
+ gst_video_info_set_format (info, GST_VIDEO_FORMAT_BGRx,
+ mode->hdisplay, mode->vdisplay);
+ ensure_kms_allocator (self);
+ kmsmem = (GstKMSMemory *) gst_kms_allocator_bo_alloc (self->allocator, info);
+ gst_video_info_free (info);
+
+ if (!kmsmem)
+ goto bo_failed;
+ fb_id = kmsmem->fb_id;
+
err = drmModeSetCrtc (self->fd, self->crtc_id, fb_id, 0, 0,
(uint32_t *) & self->conn_id, 1, mode);
if (err)
goto modesetting_failed;
+ self->hdisplay = mode->hdisplay;
+ self->vdisplay = mode->vdisplay;
+
g_clear_pointer (&self->tmp_kmsmem, gst_memory_unref);
self->tmp_kmsmem = (GstMemory *) kmsmem;
+ kmsmem = NULL;
+
+ if (!gst_kms_sink_calculate_display_ratio (self, vinfo,
+ &GST_VIDEO_SINK_WIDTH (self), &GST_VIDEO_SINK_HEIGHT (self)))
+ goto no_disp_ratio;
ret = TRUE;
@@ -880,6 +906,10 @@ bail:
if (conn)
drmModeFreeConnector (conn);
+ if (kmsmem)
+ gst_memory_unref ((GstMemory *) kmsmem);
+
+ self->mode_valid = ret;
return ret;
/* ERRORS */
@@ -904,6 +934,11 @@ modesetting_failed:
GST_ERROR_OBJECT (self, "Failed to set mode: %s", g_strerror (errno));
goto bail;
}
+no_disp_ratio:
+ {
+ GST_ERROR_OBJECT (self, "Error calculating the output display ratio of the video.");
+ goto bail;
+ }
}
static void
@@ -1040,7 +1075,7 @@ ensure_allowed_caps (GstKMSSink * self, drmModeConnector * conn,
format = gst_video_format_to_string (fmt);
- if (mode) {
+ if (mode && !self->can_scale) {
caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, format,
"width", G_TYPE_INT, mode->hdisplay,
@@ -1338,6 +1373,8 @@ gst_kms_sink_start (GstBaseSink * bsink)
self->modesetting_enabled = TRUE;
}
+ self->mode_valid = !self->modesetting_enabled;
+
if (crtc->mode_valid && self->modesetting_enabled && self->restore_crtc) {
self->saved_crtc = (drmModeCrtc *) crtc;
}
@@ -1376,13 +1413,6 @@ gst_kms_sink_start (GstBaseSink * bsink)
self->hdisplay = crtc->mode.hdisplay;
self->vdisplay = crtc->mode.vdisplay;
- if (self->render_rect.w == 0 || self->render_rect.h == 0) {
- self->render_rect.x = 0;
- self->render_rect.y = 0;
- self->render_rect.w = self->hdisplay;
- self->render_rect.h = self->vdisplay;
- }
-
self->pending_rect = self->render_rect;
GST_OBJECT_UNLOCK (self);
@@ -1744,9 +1774,6 @@ gst_kms_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
self->pool = NULL;
}
- if (self->modesetting_enabled && !configure_mode_setting (self, &vinfo))
- goto modesetting_failed;
-
GST_OBJECT_LOCK (self);
if (self->reconfigure) {
self->reconfigure = FALSE;
@@ -1781,13 +1808,6 @@ no_disp_ratio:
return FALSE;
}
-modesetting_failed:
- {
- GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, (NULL),
- ("failed to configure video mode"));
- return FALSE;
- }
-
}
static gboolean
@@ -2249,6 +2269,16 @@ gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
GST_TRACE_OBJECT (self, "displaying fb %d", fb_id);
GST_OBJECT_LOCK (self);
+
+retry_set_plane:
+ if (self->modesetting_enabled && !self->mode_valid) {
+ if (!configure_mode_setting (self, vinfo))
+ goto modesetting_failed;
+
+ src.w = GST_VIDEO_SINK_WIDTH (self);
+ src.h = GST_VIDEO_SINK_HEIGHT (self);
+ }
+
if ((crop = gst_buffer_get_video_crop_meta (buffer))) {
GstVideoInfo cropped_vinfo = *vinfo;
@@ -2263,10 +2293,9 @@ gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
src.y = crop->y;
}
- dst.w = self->render_rect.w;
- dst.h = self->render_rect.h;
+ dst.w = self->render_rect.w ?: self->hdisplay;
+ dst.h = self->render_rect.h ?: self->vdisplay;
-retry_set_plane:
gst_video_sink_center_rect (src, dst, &result, self->can_scale);
result.x += self->render_rect.x;
@@ -2291,11 +2320,6 @@ retry_set_plane:
goto sync_frame;
}
- /* to make sure it can be show when driver don't support scale */
- if (!self->can_scale) {
- src.w = result.w;
- src.h = result.h;
- }
#ifdef HAVE_DRM_HDR
/* Send the HDR infoframes if appropriate */
gst_kms_push_hdr_infoframe (self, FALSE);
@@ -2305,6 +2329,12 @@ retry_set_plane:
/* The AFBC's width should align to 4 */
src.w &= ~3;
+ /* to make sure it can be show when driver don't support scale */
+ if (!self->can_scale) {
+ src.w = result.w = MIN (src.w, result.w);
+ src.h = result.h = MIN (src.h, result.h);
+ }
+
GST_TRACE_OBJECT (self,
"drmModeSetPlane at (%i,%i) %ix%i sourcing at (%i,%i) %ix%i",
result.x, result.y, result.w, result.h, src.x, src.y, src.w, src.h);
@@ -2315,7 +2345,17 @@ retry_set_plane:
src.x << 16, src.y << 16, src.w << 16, src.h << 16);
if (ret) {
if (self->can_scale) {
+ GST_WARNING_OBJECT (self, "unable to scale on plane %d", self->plane_id);
self->can_scale = FALSE;
+
+ if (self->modesetting_enabled) {
+ if (!configure_mode_setting (self, vinfo))
+ goto modesetting_failed;
+
+ src.w = GST_VIDEO_SINK_WIDTH (self);
+ src.h = GST_VIDEO_SINK_HEIGHT (self);
+ }
+
goto retry_set_plane;
}
goto set_plane_failed;
@@ -2335,7 +2375,9 @@ sync_frame:
self->last_height = GST_VIDEO_SINK_HEIGHT (self);
self->last_vinfo = self->vinfo;
}
- g_clear_pointer (&self->tmp_kmsmem, gst_memory_unref);
+
+ if (self->tmp_kmsmem && self->plane_id == self->primary_plane_id)
+ g_clear_pointer (&self->tmp_kmsmem, gst_memory_unref);
GST_OBJECT_UNLOCK (self);
res = GST_FLOW_OK;
@@ -2350,6 +2392,11 @@ buffer_invalid:
GST_ERROR_OBJECT (self, "invalid buffer: it doesn't have a fb id");
goto bail;
}
+modesetting_failed:
+ {
+ GST_ERROR_OBJECT (self, "failed to configure video mode");
+ goto bail;
+ }
set_plane_failed:
{
GST_OBJECT_UNLOCK (self);
diff --git a/sys/kms/gstkmssink.h b/sys/kms/gstkmssink.h
index 5ce1e55..0d3374d 100644
--- a/sys/kms/gstkmssink.h
+++ b/sys/kms/gstkmssink.h
@@ -76,6 +76,7 @@ struct _GstKMSSink {
gboolean can_scale;
gboolean modesetting_enabled;
+ gboolean mode_valid;
gboolean restore_crtc;
GstStructure *connector_props;
GstStructure *plane_props;
--
2.20.1