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);
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);
}
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);
}
int img_width;
int img_height;
+ int crop_width;
+ int crop_height;
+ int crop_left;
+ int crop_top;
int dpb_count;
int buf_stride;
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),
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;
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)
{
.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,
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 */
(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;
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);
}
/* 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 */
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 */
#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