media: mfc: DRV4.0: support encoder DRC
authorAyoung Sim <a.sim@samsung.com>
Tue, 17 Apr 2018 06:29:01 +0000 (15:29 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Tue, 29 May 2018 06:59:18 +0000 (15:59 +0900)
We support the DRC(Dynamic Resolution Change) using LASE_SEQ command.
So we can start from SEQ_START without CLOSE/OPEN.

Change-Id: I92a8e0e5beb889837164b3fb8917c74ec5b31ee9
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_cmd.c
drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c
drivers/media/platform/exynos/mfc/s5p_mfc_irq.c
drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c
drivers/media/platform/exynos/mfc/s5p_mfc_opr.c
drivers/media/platform/exynos/mfc/s5p_mfc_reg.c

index 03c2610a6b9451c49007f9a900a1b428570d3115..aee117835eaa18c2eacb6baf0821aef820e76d40 100644 (file)
@@ -441,6 +441,7 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
        }
 
        s5p_mfc_mem_ion_free(dev, &ctx->codec_buf);
+       ctx->codec_buffer_allocated = 0;
        mfc_debug(2, "Release the codec buffer\n");
 }
 
index 3d2614c8c83a2f2f043f17220de3b4a8e93603e7..af09a6c9f848595f48e0570057e066ff43eb430c 100644 (file)
@@ -264,10 +264,11 @@ int s5p_mfc_cmd_enc_init_buffers(struct s5p_mfc_ctx *ctx)
                return -EINVAL;
        }
 
-       /* Header was generated now starting processing
+       /*
+        * Header was generated now starting processing
         * First set the reference frame buffers
         */
-       if (!ctx->codec_buf.dma_buf) {
+       if (!ctx->codec_buffer_allocated) {
                mfc_info_ctx("there isn't codec buffer, re-alloc!\n");
                ret = s5p_mfc_alloc_codec_buffers(ctx);
                if (ret) {
index 219e59905660fb38dce545cf92b08f52fb1dcaa2..743132ead2fcb9be1685ea305532a58adaa969f3 100644 (file)
@@ -463,10 +463,12 @@ static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
 
        mfc_enc_check_format(ctx);
 
-       if ((ctx->state == MFCINST_RUNNING)
-               && (((ctx->old_img_width != 0) && (ctx->old_img_width != ctx->img_width))
-               || ((ctx->old_img_height != 0) && (ctx->old_img_height != ctx->img_height)))) {
-               ctx->enc_drc_flag = 1;
+       if (ctx->state == MFCINST_RUNNING) {
+               s5p_mfc_change_state(ctx, MFCINST_GOT_INST);
+               mfc_info_ctx("Enc resolution is changed\n");
+               if (((ctx->old_img_width != 0) && (ctx->old_img_width != ctx->img_width))
+                               || ((ctx->old_img_height != 0) && (ctx->old_img_height != ctx->img_height)))
+                       ctx->enc_drc_flag = 1;
        }
 
        mfc_info_ctx("Enc input pixelformat : %s\n", ctx->src_fmt->name);
index efe7a187e24cf2d4217c3214dee9993a81d88578..db868b3a155eba78071708bc4157e102d39e64a0 100644 (file)
@@ -356,6 +356,29 @@ static void s5p_mfc_enc_stop_streaming(struct vb2_queue *q)
                        index++;
                }
        } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (ctx->state == MFCINST_FREE) {
+                       mfc_debug(2, "already closed\n");
+               } else {
+                       s5p_mfc_change_state(ctx, MFCINST_FINISHING);
+                       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+
+                       while (s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED)) {
+                               ret = s5p_mfc_just_run(dev, ctx->num);
+                               if (ret) {
+                                       mfc_err_ctx("Failed to run MFC.\n");
+                                       break;
+                               }
+                               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET)) {
+                                       mfc_err_ctx("Waiting for LAST_SEQ timed out\n");
+                                       break;
+                               }
+                               if (ctx->state == MFCINST_RUNNING) {
+                                       mfc_debug(2, "all encoded buffers out\n");
+                                       break;
+                               }
+                       }
+               }
+
                s5p_mfc_move_all_bufs(&ctx->buf_queue_lock, &ctx->src_buf_queue,
                                &ctx->ref_buf_queue, MFC_QUEUE_ADD_BOTTOM);
                s5p_mfc_cleanup_enc_src_queue(ctx);
@@ -377,8 +400,6 @@ static void s5p_mfc_enc_stop_streaming(struct vb2_queue *q)
        s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
        s5p_mfc_release_hwlock_ctx(ctx);
 
-       if (s5p_mfc_enc_ctx_ready(ctx))
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
        if (s5p_mfc_is_work_to_do(dev))
                queue_work(dev->butler_wq, &dev->butler_work);
 }
index c986b6dcb8380d1fbda5c78f3ad5d06a485bfa0e..c457efb3b72e90730a00d5f04159865845f75118 100644 (file)
@@ -808,8 +808,7 @@ static void mfc_handle_stream_input(struct s5p_mfc_ctx *ctx, int slice_type)
 
        raw = &ctx->raw_buf;
 
-       if (!ctx->enc_res_change_re_input && slice_type >= 0 &&
-                       ctx->state != MFCINST_FINISHING) {
+       if (!ctx->enc_res_change_re_input && slice_type >= 0) {
                if (ctx->state == MFCINST_RUNNING_NO_OUTPUT ||
                        ctx->state == MFCINST_RUNNING_BUF_FULL)
                        s5p_mfc_change_state(ctx, MFCINST_RUNNING);
@@ -885,21 +884,6 @@ static void mfc_handle_stream_input(struct s5p_mfc_ctx *ctx, int slice_type)
                                }
                        }
                }
-       } else if (ctx->state == MFCINST_FINISHING) {
-               src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
-                               &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-               if (!src_mb) {
-                       mfc_err_ctx("no src buffers.\n");
-                       return;
-               }
-
-               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
-               /* encoder src buffer CFW UNPROT */
-               if (ctx->is_drm) {
-                       index = src_mb->vb.vb2_buf.index;
-                       s5p_mfc_raw_unprotect(ctx, src_mb, index);
-               }
        }
 }
 
@@ -910,8 +894,7 @@ static void mfc_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type,
        struct s5p_mfc_buf *dst_mb;
        unsigned int index;
 
-       if (strm_size > 0 || ctx->state == MFCINST_FINISHING
-                         || ctx->state == MFCINST_RUNNING_BUF_FULL) {
+       if (strm_size > 0 || ctx->state == MFCINST_RUNNING_BUF_FULL) {
                /* at least one more dest. buffers exist always  */
                dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
                                &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
@@ -955,12 +938,6 @@ static void mfc_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type,
                if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
                        mfc_err_ctx("failed in get_buf_ctrls_val\n");
 
-               if (strm_size == 0 && ctx->state == MFCINST_FINISHING)
-                       call_cop(ctx, get_buf_update_val, ctx,
-                               &ctx->dst_ctrls[index],
-                               V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-                               enc->stored_tag);
-
                vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
 
                /* encoder dst buffer CFW UNPROT */
@@ -1230,7 +1207,6 @@ static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx)
                                p->codec.bpg.thumb_size,
                                p->codec.bpg.exif_size);
        } else {
-               /* TODO: is there other case? */
                if ((p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) ||
                        (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY)) {
                        dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
@@ -1249,7 +1225,6 @@ static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx)
 
                                s5p_mfc_stream_unprotect(ctx, dst_mb, index);
                        }
-
                }
        }
 
@@ -1259,6 +1234,14 @@ static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx)
        /* If the ROI is enabled at SEQ_START, clear ROI_ENABLE bit */
        s5p_mfc_clear_roi_enable(dev);
 
+       if (!ctx->codec_buffer_allocated) {
+               mfc_debug(2, "previous codec buffer is exist\n");
+
+               if (dev->has_mmcache && dev->mmcache.is_on_status)
+                       s5p_mfc_invalidate_mmcache(dev);
+
+               s5p_mfc_release_codec_buffers(ctx);
+       }
        ret = s5p_mfc_alloc_codec_buffers(ctx);
        if (ret) {
                mfc_err_ctx("Failed to allocate encoding buffers.\n");
@@ -1481,9 +1464,16 @@ static int mfc_irq_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned in
        case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
        case S5P_FIMV_R2H_CMD_FIELD_DONE_RET:
        case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
-       case S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET:
        case S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET:
                return mfc_handle_done_frame(ctx, reason, err);
+       case S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET:
+               if (ctx->type == MFCINST_ENCODER) {
+                       mfc_handle_stream(ctx);
+                       s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+               } else if (ctx->type == MFCINST_DECODER) {
+                       return mfc_handle_done_frame(ctx, reason, err);
+               }
+               break;
        case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
                if (ctx->type == MFCINST_ENCODER) {
                        if (ctx->otf_handle) {
index 29dbf9c968876e4c266f24ffbf51bc1331dede52..f38ab5c1eb60a1acbb5e15468bd2864be6a4892a 100644 (file)
@@ -1087,12 +1087,6 @@ static void mfc_nal_q_handle_stream(struct s5p_mfc_ctx *ctx, EncoderOutputStr *p
                        mfc_err_ctx("NAL Q: failed in get_buf_ctrls_val in nal q\n");
 
                vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-       } else if (strm_size == 0) {
-               dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
-               if (!dst_mb)
-                       mfc_err_dev("NAL Q: no dst buffers\n");
-               else
-                       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
        }
 
        mfc_debug_leave();
index e20f7a0c35a8fa4e0355efaf8d2a815be8f982f3..9006a54b21297ea83c1860da93b94fa0ef9f9fcd 100644 (file)
@@ -304,18 +304,11 @@ int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
 
 int s5p_mfc_run_enc_last_frames(struct s5p_mfc_ctx *ctx)
 {
-       struct s5p_mfc_buf *src_mb, *dst_mb;
+       struct s5p_mfc_buf *dst_mb;
        struct s5p_mfc_raw_info *raw;
 
        raw = &ctx->raw_buf;
 
-       /* Get the next source buffer */
-       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-       if (!src_mb) {
-               mfc_debug(2, "no src buffers.\n");
-               return -EAGAIN;
-       }
-
        dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED);
        if (!dst_mb) {
                mfc_debug(2, "no dst buffers.\n");
index aee8f0ebad27253261f6e3bab4bad53212a3b8e0..abec9c910e53c1fc83d1f6307db2318f4bcbf2a1 100644 (file)
@@ -268,7 +268,7 @@ int s5p_mfc_set_enc_codec_buffers(struct s5p_mfc_ctx *ctx)
        buf_addr1 += enc->tmv_buffer_size >> 1;
        buf_size1 -= enc->tmv_buffer_size;
 
-       mfc_debug(2, "Buf1: 0x%p, buf_size1: %d (ref frames %d)\n",
+       mfc_debug(2, "Buf1 end: 0x%p, buf_size1: %d (ref frames %d)\n",
                        (void *)buf_addr1, buf_size1, ctx->dpb_count);
        if (buf_size1 < 0) {
                mfc_debug(2, "Not enough memory has been allocated.\n");