media: mfc: DRV4.0: supports the encoder crop option
authorAyoung Sim <a.sim@samsung.com>
Tue, 17 Apr 2018 10:21:22 +0000 (19:21 +0900)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:22:22 +0000 (20:22 +0300)
Change-Id: I180f95791d35418053775713aa1456e648c5bf0a
Signed-off-by: Ayoung Sim <a.sim@samsung.com>
drivers/media/platform/exynos/mfc/s5p_mfc_buf.c
drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h
drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.c
drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c
drivers/media/platform/exynos/mfc/s5p_mfc_otf.c
drivers/media/platform/exynos/mfc/s5p_mfc_regs_v10.h

index b30f3e132026d023eab1136fa1641f0b0fdd959d..03c2610a6b9451c49007f9a900a1b428570d3115 100644 (file)
@@ -284,17 +284,17 @@ static void mfc_calc_enc_codec_buffer_size(struct s5p_mfc_ctx *ctx)
        enc = ctx->enc_priv;
        enc->tmv_buffer_size = 0;
 
-       mb_width = WIDTH_MB(ctx->img_width);
-       mb_height = HEIGHT_MB(ctx->img_height);
+       mb_width = WIDTH_MB(ctx->crop_width);
+       mb_height = HEIGHT_MB(ctx->crop_height);
 
-       lcu_width = ENC_LCU_WIDTH(ctx->img_width);
-       lcu_height = ENC_LCU_HEIGHT(ctx->img_height);
+       lcu_width = ENC_LCU_WIDTH(ctx->crop_width);
+       lcu_height = ENC_LCU_HEIGHT(ctx->crop_height);
 
        /* default recon buffer size, it can be changed in case of 422, 10bit */
        enc->luma_dpb_size =
-               ALIGN(ENC_LUMA_DPB_SIZE(ctx->img_width, ctx->img_height), 64);
+               ALIGN(ENC_LUMA_DPB_SIZE(ctx->crop_width, ctx->crop_height), 64);
        enc->chroma_dpb_size =
-               ALIGN(ENC_CHROMA_DPB_SIZE(ctx->img_width, ctx->img_height), 64);
+               ALIGN(ENC_CHROMA_DPB_SIZE(ctx->crop_width, ctx->crop_height), 64);
        mfc_debug(2, "recon luma size: %zu chroma size: %zu\n",
                        enc->luma_dpb_size, enc->chroma_dpb_size);
 
@@ -337,9 +337,9 @@ static void mfc_calc_enc_codec_buffer_size(struct s5p_mfc_ctx *ctx)
        case S5P_FIMV_CODEC_VP9_ENC:
                if (ctx->is_10bit || ctx->is_422format) {
                        enc->luma_dpb_size =
-                               ALIGN(ENC_VP9_LUMA_DPB_10B_SIZE(ctx->img_width, ctx->img_height), 64);
+                               ALIGN(ENC_VP9_LUMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
                        enc->chroma_dpb_size =
-                               ALIGN(ENC_VP9_CHROMA_DPB_10B_SIZE(ctx->img_width, ctx->img_height), 64);
+                               ALIGN(ENC_VP9_CHROMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
                        mfc_debug(2, "VP9 10bit recon luma size: %zu chroma size: %zu\n",
                                        enc->luma_dpb_size, enc->chroma_dpb_size);
                }
@@ -356,9 +356,9 @@ static void mfc_calc_enc_codec_buffer_size(struct s5p_mfc_ctx *ctx)
        case S5P_FIMV_CODEC_BPG_ENC:
                if (ctx->is_10bit || ctx->is_422format) {
                        enc->luma_dpb_size =
-                               ALIGN(ENC_HEVC_LUMA_DPB_10B_SIZE(ctx->img_width, ctx->img_height), 64);
+                               ALIGN(ENC_HEVC_LUMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
                        enc->chroma_dpb_size =
-                               ALIGN(ENC_HEVC_CHROMA_DPB_10B_SIZE(ctx->img_width, ctx->img_height), 64);
+                               ALIGN(ENC_HEVC_CHROMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
                        mfc_debug(2, "HEVC 10bit or 422 recon luma size: %zu chroma size: %zu\n",
                                        enc->luma_dpb_size, enc->chroma_dpb_size);
                }
index ea2428195cbc5f8140166e5a02a57314317cd63b..cb7b389d1c1c9303285aaa5e525a745d1959f760 100644 (file)
@@ -1288,6 +1288,10 @@ struct s5p_mfc_ctx {
 
        int img_width;
        int img_height;
+       int crop_width;
+       int crop_height;
+       int crop_left;
+       int crop_top;
        int dpb_count;
        int buf_stride;
 
index 03a98b7759fd3432ac410694f4fbf23055d1efd6..a2b5d7fd4f2c6ede1347feab1c7c0bc08d82a86c 100644 (file)
@@ -67,9 +67,10 @@ static int mfc_info_show(struct seq_file *s, void *unused)
                        else
                                codec_name = ctx->dst_fmt->name;
 
-                       seq_printf(s, "[CTX:%d] codec: %s(%s), width: %d, height: %d, state: %d\n",
+                       seq_printf(s, "[CTX:%d] codec: %s(%s), width: %d, height: %d, crop: %d %d %d %d, state: %d\n",
                                ctx->num, ctx->type == MFCINST_DECODER ? "DEC" : "ENC", codec_name,
-                               ctx->img_width, ctx->img_height, ctx->state);
+                               ctx->img_width, ctx->img_height, ctx->crop_width, ctx->crop_height,
+                               ctx->crop_left, ctx->crop_top, ctx->state);
                        seq_printf(s, "        queue(src: %d, dst: %d, src_nal: %d, dst_nal: %d, ref: %d)\n",
                                s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
                                s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
index 511233e0bf99808f28e79e52984b6f5b0bdd308a..219e59905660fb38dce545cf92b08f52fb1dcaa2 100644 (file)
@@ -473,6 +473,12 @@ static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
        mfc_info_ctx("fmt - w: %d, h: %d, stride: %d\n",
                        pix_fmt_mp->width, pix_fmt_mp->height, ctx->buf_stride);
 
+       /*
+        * It should be keep till buffer size and stride was calculated.
+        * And it can be changed to real encoding size, if user call the s_crop.
+        */
+       ctx->crop_width = ctx->img_width;
+       ctx->crop_height = ctx->img_height;
        s5p_mfc_enc_calc_src_size(ctx);
 
        ctx->output_state = QUEUE_FREE;
@@ -481,6 +487,64 @@ static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
        return 0;
 }
 
+static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+
+       mfc_debug_enter();
+
+       cr->c.left = ctx->crop_left;
+       cr->c.top = ctx->crop_top;
+       cr->c.width = ctx->crop_width;
+       cr->c.height = ctx->crop_height;
+
+       mfc_debug(3, "enc crop w: %d, h: %d, offset l: %d t: %d\n",
+                       ctx->crop_width, ctx->crop_height, ctx->crop_left, ctx->crop_top);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+
+       mfc_debug_enter();
+
+       if (cr->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_err_ctx("not supported type (It can only in the source)\n");
+               return -EINVAL;
+       }
+
+       if (cr->c.left < 0 || cr->c.top < 0) {
+               mfc_err_ctx("crop position is negative\n");
+               return -EINVAL;
+       }
+
+       if ((cr->c.height > ctx->img_height) || (cr->c.top > ctx->img_height) ||
+                       (cr->c.width > ctx->img_width) || (cr->c.left > ctx->img_width) ||
+                       (cr->c.left <= (ctx->img_width - cr->c.width)) ||
+                       (cr->c.top <= (ctx->img_height - cr->c.height))) {
+               mfc_err_ctx("Out of crop range: (%d,%d,%d,%d) from %dx%d\n",
+                               cr->c.left, cr->c.top, cr->c.width, cr->c.height,
+                               ctx->img_width, ctx->img_height);
+               return -EINVAL;
+       }
+
+       ctx->crop_top = cr->c.top;
+       ctx->crop_left = cr->c.left;
+       ctx->crop_height = cr->c.height;
+       ctx->crop_width = cr->c.width;
+
+       mfc_debug(3, "enc original: %dx%d, crop: %dx%d, offset l: %d t: %d\n",
+                       ctx->img_width, ctx->img_height,
+                       ctx->crop_width, ctx->crop_height,
+                       ctx->crop_left, ctx->crop_top);
+
+       return 0;
+}
+
 static int vidioc_reqbufs(struct file *file, void *priv,
                                          struct v4l2_requestbuffers *reqbufs)
 {
@@ -1906,6 +1970,8 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
        .vidioc_try_fmt_vid_out_mplane  = vidioc_try_fmt,
        .vidioc_s_fmt_vid_cap_mplane    = vidioc_s_fmt_vid_cap_mplane,
        .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out_mplane,
+       .vidioc_g_crop                  = vidioc_g_crop,
+       .vidioc_s_crop                  = vidioc_s_crop,
        .vidioc_reqbufs                 = vidioc_reqbufs,
        .vidioc_querybuf                = vidioc_querybuf,
        .vidioc_qbuf                    = vidioc_qbuf,
index 77ea7292c26ec34d19bcd701e62c09ef0a9b7741..b913f3e6cda6cdd1003d87180651bb8120442b74 100644 (file)
@@ -187,15 +187,15 @@ static void mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
        mfc_set_default_params(ctx);
 
        /* width */
-       MFC_WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH); /* 16 align */
+       MFC_WRITEL(ctx->crop_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
        /* height */
-       MFC_WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT); /* 16 align */
-       /** cropped width */
-       MFC_WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
-       /** cropped height */
-       MFC_WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
-       /** cropped offset */
-       MFC_WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET);
+       MFC_WRITEL(ctx->crop_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
+       /* cropped offset */
+       reg |= (ctx->crop_left & S5P_FIMV_E_FRAME_CROP_OFFSET_MASK)
+               << S5P_FIMV_E_FRAME_CROP_OFFSET_LEFT;
+       reg |= (ctx->crop_top & S5P_FIMV_E_FRAME_CROP_OFFSET_MASK)
+               << S5P_FIMV_E_FRAME_CROP_OFFSET_TOP;
+       MFC_WRITEL(reg, S5P_FIMV_E_FRAME_CROP_OFFSET);
 
        /* multi-slice control */
        /* multi-slice MB number or bit size */
@@ -207,7 +207,7 @@ static void mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
                        (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)){
                enc->slice_size.bits = p->slice_bit;
        } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW) {
-               enc->slice_size.mb = p->slice_mb_row * ((ctx->img_width + 15) / 16);
+               enc->slice_size.mb = p->slice_mb_row * ((ctx->crop_width + 15) / 16);
        } else {
                enc->slice_size.mb = 0;
                enc->slice_size.bits = 0;
@@ -523,12 +523,9 @@ void s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
        reg |= ((p_264->vui_enable & 0x1) << 30);
        MFC_WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
 
-       /** height */
-       if (p_264->interlace) {
-               MFC_WRITEL(ctx->img_height >> 1, S5P_FIMV_E_FRAME_HEIGHT); /* 32 align */
-               /** cropped height */
-               MFC_WRITEL(ctx->img_height >> 1, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
-       }
+       /* cropped height */
+       if (p_264->interlace)
+               MFC_WRITEL(ctx->crop_height >> 1, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
 
        /* loopfilter alpha offset */
        reg = MFC_READL(S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
@@ -1163,7 +1160,7 @@ void s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx)
        }
 
        /* UHD encoding case */
-       if ((ctx->img_width == 3840) && (ctx->img_height == 2160)) {
+       if (IS_UHD_RES(ctx)) {
                p_hevc->level = 51;
                p_hevc->tier_flag = 0;
        /* this tier_flag can be changed */
index dfdfa876596b9134a6689ea5df1604492b6cce1e..4797ae3d7a69bf59fbe81be61cbca19a2380abc2 100644 (file)
@@ -68,6 +68,8 @@ static int mfc_otf_set_buf_info(struct s5p_mfc_ctx *ctx)
        ctx->raw_buf.num_planes = ctx->src_fmt->num_planes;
        ctx->img_width = buf_info->width;
        ctx->img_height = buf_info->height;
+       ctx->crop_width = buf_info->width;
+       ctx->crop_height = buf_info->height;
        ctx->buf_stride = ALIGN(ctx->img_width, 16);
 
        /* calculate source size */
index 3679d1e28045b6156fb8d12e7958aeda2d262026..25039c8e459f84241506f0d68f17fe2583c632b6 100644 (file)
 #define S5P_FIMV_D_DECODED_CHROMA_ADDR                         0xF64C
 
 /* Encoder Registers */
-#define S5P_FIMV_E_FRAME_WIDTH                                 0xF770
-#define S5P_FIMV_E_FRAME_HEIGHT                                        0xF774
 #define S5P_FIMV_E_CROPPED_FRAME_WIDTH                         0xF778
 #define S5P_FIMV_E_CROPPED_FRAME_HEIGHT                                0xF77C
 #define S5P_FIMV_E_FRAME_CROP_OFFSET                           0xF780
 #define S5P_FIMV_D_BLACK_BAR_IMAGE_H_MASK              0xFFFF
 
 
+/* 0xF780:  S5P_FIMV_E_FRAME_CROP_OFFSET */
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_TOP               16
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_LEFT              0
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_MASK              0x3FFF
+
+
 /* 0xF784: S5P_FIMV_E_ENC_OPTIONS */
 #define S5P_FIMV_E_ENC_OPT_FRAME_SKIP_EN_MASK          0x3
 #define S5P_FIMV_E_ENC_OPT_SEQ_HEADER_CONTROL_MASK     0x1