arm64: imx8mx: vpu: integrate vsi 20210416 release
authorZhou Peng <eagle.zhou@nxp.com>
Fri, 16 Apr 2021 10:49:24 +0000 (18:49 +0800)
committerZhou Peng <eagle.zhou@nxp.com>
Fri, 16 Apr 2021 11:15:25 +0000 (19:15 +0800)
- M865SW-738: VSI V4L2 Engineer release package 20210416
  M865SW-636: [VPU/V4L2] H264 decoder: Resolution change stream seek hang
  M865SW-696: [VPU/V4L2] VC8000E: Flush encoder then get V4L2_EVENT_CODEC_ERROR event
  M865SW-730: [VPU/V4L2] encoder: Android poll() waiting timeout at beginning
  M865SW-734: [VPU/V4L2] decoder: daemon occurs error when running unit test
  M865SW-697: [VPU/V4L2] encoder: the bitrate of encoding vp8 is not accurate
  M865SW-726: [VPU/V4L2] 8MM/8MP HEVC 10bit decoder: cannot play on Android

Signed-off-by: Zhou Peng <eagle.zhou@nxp.com>
(cherry picked from commit ddf936035cb532689a9442529089e648729ac378)

drivers/mxc/hantro_v4l2/vsi-v4l2-config.c
drivers/mxc/hantro_v4l2/vsi-v4l2-dec.c
drivers/mxc/hantro_v4l2/vsi-v4l2-enc.c
drivers/mxc/hantro_v4l2/vsi-v4l2-priv.h
drivers/mxc/hantro_v4l2/vsi-v4l2.c
drivers/mxc/hantro_v4l2/vsi-v4l2.h
drivers/mxc/hantro_v4l2/vsi-v4l2daemon.c

index f4dd17f..e29d8ca 100755 (executable)
@@ -975,10 +975,11 @@ static int get_fmtprofile(struct vsi_v4l2_mediacfg *pcfg)
        }
 }
 
-static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int width, int height, int planeno, int pixelWidth)
+static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int width, int height, int planeno, int bdecoder)
 {
        int totalsize = 0;
        int basesize = width * height, extsize = 0, quadsize = 0;
+       int padsize = 0;
 
        if (braw) {
                if (enc_isRGBformat(pixelformat)) {
@@ -998,6 +999,8 @@ static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int
                        case V4L2_PIX_FMT_411SP:
                                extsize = basesize / 2;
                                quadsize = basesize / 4;
+                               if (bdecoder)
+                                       padsize = quadsize + 32;
                                break;
                        case V4L2_PIX_FMT_NV16:
                                extsize = basesize;
@@ -1019,7 +1022,7 @@ static void verifyPlanesize(unsigned int psize[], int braw, int pixelformat, int
                        }
                }
                if (planeno == 1) {
-                       totalsize = basesize + extsize;
+                       totalsize = basesize + extsize + padsize;
                        psize[0] = max_t(int, PAGE_ALIGN(totalsize), psize[0]);
                } else if (planeno == 2) {
                        psize[0] = basesize;
@@ -1148,7 +1151,7 @@ static int vsiv4l2_setfmt_enc(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt)
        if (fmt->fmt.pix_mp.num_planes == userset_planeno) {
                for (i = 0; i < fmt->fmt.pix_mp.num_planes; i++)
                        psize[i] = fmt->fmt.pix_mp.plane_fmt[i].sizeimage;
-               verifyPlanesize(psize, braw, fmt->fmt.pix_mp.pixelformat, pcfg->bytesperline, fmt->fmt.pix_mp.height, userset_planeno, 8);
+               verifyPlanesize(psize, braw, fmt->fmt.pix_mp.pixelformat, pcfg->bytesperline, fmt->fmt.pix_mp.height, userset_planeno, 0);
        } else
                calcPlanesize(ctx, fmt->fmt.pix_mp.pixelformat, pcfg->bytesperline, fmt->fmt.pix_mp.height, psize, fmt->type, fmt->fmt.pix_mp.num_planes);
        for (i = 0; i < fmt->fmt.pix_mp.num_planes; i++)
@@ -1302,13 +1305,13 @@ static int vsiv4l2_decidepixeldepth(int pixelformat, int origdepth)
        case VSI_V4L2_DEC_PIX_FMT_411SP:
        case VSI_V4L2_DEC_PIX_FMT_422SP:
        case VSI_V4L2_DEC_PIX_FMT_444SP:
-       case VSI_V4L2_DECOUT_DTRC:
-       case VSI_V4L2_DECOUT_RFC:
                return 8;
        case VSI_V4L2_DECOUT_NV12_10BIT:
+               return 10;
        case VSI_V4L2_DECOUT_DTRC_10BIT:
        case VSI_V4L2_DECOUT_RFC_10BIT:
-               return 10;
+       case VSI_V4L2_DECOUT_DTRC:
+       case VSI_V4L2_DECOUT_RFC:
        default:
                return origdepth;
        }
@@ -1320,19 +1323,17 @@ static int vsiv4l2_setfmt_dec(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt)
        struct vsi_video_fmt *targetfmt;
        unsigned int *psize;
        int braw = brawfmt(ctx->flag, fmt->type);
-       int oldsize = 0;
 
        targetfmt = vsi_find_format(ctx, fmt);
        if (targetfmt == NULL)
                return -EINVAL;
        if (binputqueue(fmt->type))
                psize = pcfg->sizeimagesrc;
-       else {
+       else
                psize = pcfg->sizeimagedst;
-               oldsize = psize[0];
-       }
+
        v4l2_klog(LOGLVL_BRIEF, "%s:%d:%x:%d:%d:%d:%d", __func__,
-               fmt->type, fmt->fmt.pix.pixelformat, fmt->fmt.pix.width, fmt->fmt.pix.height, fmt->fmt.pix.bytesperline, oldsize);
+               fmt->type, fmt->fmt.pix.pixelformat, fmt->fmt.pix.width, fmt->fmt.pix.height, fmt->fmt.pix.bytesperline, psize[0]);
        if (binputqueue(fmt->type)) {
                pcfg->decparams.dec_info.io_buffer.srcwidth = fmt->fmt.pix.width;
                pcfg->decparams.dec_info.io_buffer.srcheight = fmt->fmt.pix.height;
@@ -1347,19 +1348,22 @@ static int vsiv4l2_setfmt_dec(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt)
                fmt->fmt.pix.height = pcfg->decparams.dec_info.io_buffer.output_height;
                pcfg->decparams.dec_info.io_buffer.outBufFormat = targetfmt->dec_fmt;
                pcfg->decparams.dec_info.io_buffer.outputPixelDepth =
-                       vsiv4l2_decidepixeldepth(targetfmt->dec_fmt, pcfg->decparams.dec_info.io_buffer.outputPixelDepth);
+                       vsiv4l2_decidepixeldepth(targetfmt->dec_fmt, pcfg->src_pixeldepth);
        }
-       pcfg->bytesperline = fmt->fmt.pix.bytesperline; /* for padding, zero if unused */
-       pcfg->bytesperline = ALIGN(pcfg->bytesperline, 16);
-       if (pcfg->bytesperline == 0)
-               pcfg->bytesperline = ALIGN(fmt->fmt.pix.width, 16);
-       fmt->fmt.pix.bytesperline = pcfg->bytesperline;
        psize[0] = fmt->fmt.pix.sizeimage;
-       verifyPlanesize(psize, braw, fmt->fmt.pix.pixelformat, pcfg->bytesperline, fmt->fmt.pix.height, 1,
-               !binputqueue(fmt->type) ? pcfg->decparams.dec_info.io_buffer.outputPixelDepth:8);
-       if (!binputqueue(fmt->type) && oldsize > psize[0])
-               psize[0] = oldsize;
-       fmt->fmt.pix.sizeimage = psize[0];
+       if (!binputqueue(fmt->type)) {
+               if (pcfg->decparams.dec_info.io_buffer.outputPixelDepth < pcfg->src_pixeldepth) {
+                       pcfg->bytesperline = fmt->fmt.pix.width * pcfg->decparams.dec_info.io_buffer.outputPixelDepth / 8;
+                       pcfg->bytesperline = ALIGN(pcfg->bytesperline, 16);
+                       if (fmt->fmt.pix.sizeimage * pcfg->src_pixeldepth <
+                               pcfg->decparams.dec_info.io_buffer.outputPixelDepth * pcfg->orig_dpbsize) {
+                               verifyPlanesize(psize, braw, fmt->fmt.pix.pixelformat, pcfg->bytesperline, fmt->fmt.pix.height, 1, 1);
+                               fmt->fmt.pix.sizeimage = psize[0];
+                       }
+               } else if (fmt->fmt.pix.sizeimage < pcfg->orig_dpbsize)
+                       fmt->fmt.pix.sizeimage = psize[0] = pcfg->orig_dpbsize;
+               fmt->fmt.pix.bytesperline = pcfg->bytesperline;
+       }
        if (binputqueue(fmt->type))
                pcfg->srcplanes = 1;
        else
@@ -1544,11 +1548,10 @@ static int vsiv4l2_getfmt_dec(struct vsi_v4l2_ctx *ctx, struct v4l2_format *fmt)
                fmt->fmt.pix.width = pcfg->decparams.dec_info.io_buffer.srcwidth;
                fmt->fmt.pix.height = pcfg->decparams.dec_info.io_buffer.srcheight;
                fmt->fmt.pix.pixelformat = find_local_dec_format(pcfg->decparams.dec_info.io_buffer.inputFormat, braw);
-               fmt->fmt.pix.bytesperline = pcfg->bytesperline;
        } else {
                fmt->fmt.pix.width = pcfg->decparams.dec_info.io_buffer.output_width;
                fmt->fmt.pix.height = pcfg->decparams.dec_info.io_buffer.output_height;
-               fmt->fmt.pix.bytesperline = pcfg->decparams.dec_info.io_buffer.output_wstride;
+               fmt->fmt.pix.bytesperline = pcfg->bytesperline;    //return latest value
                fmt->fmt.pix.pixelformat = find_local_dec_format(pcfg->decparams.dec_info.io_buffer.outBufFormat, braw);
        }
        fmt->fmt.pix.field = pcfg->field;
index 180dcc5..c06d27b 100755 (executable)
@@ -279,6 +279,7 @@ static int vsi_dec_streamon(struct file *filp, void *priv, enum v4l2_buf_type ty
                                vsi_dec_dec2drain(ctx);
                        if (test_bit(CTX_FLAG_ENDOFSTRM_BIT, &ctx->flag)) {
                                struct vb2_buffer       *vb = ctx->output_que.bufs[0];
+
                                vb->planes[0].bytesused = 0;
                                ctx->lastcapbuffer_idx = 0;
                                vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
@@ -310,7 +311,8 @@ static int vsi_dec_checkctx_srcbuf(struct vsi_v4l2_ctx *ctx)
 
 static int vsi_checkctx_capoffdone(struct vsi_v4l2_ctx *ctx)
 {
-       if (test_and_clear_bit(CTX_FLAG_STREAMOFFDONE, &ctx->flag))
+       if (test_and_clear_bit(CTX_FLAG_STREAMOFFDONE, &ctx->flag)
+               ||  ctx->error < 0)
                return 1;
        return 0;
 }
@@ -325,6 +327,8 @@ static void vsi_dec_update_reso(struct vsi_v4l2_ctx *ctx)
        pcfg->decparams.dec_info.io_buffer.output_width = pcfg->decparams_bkup.io_buffer.output_width;
        pcfg->decparams.dec_info.io_buffer.output_height = pcfg->decparams_bkup.io_buffer.output_height;
        pcfg->decparams.dec_info.io_buffer.output_wstride = pcfg->decparams_bkup.io_buffer.output_wstride;
+       pcfg->bytesperline = pcfg->decparams_bkup.io_buffer.output_wstride;
+       pcfg->orig_dpbsize = pcfg->sizeimagedst_bkup;
        pcfg->src_pixeldepth = pcfg->decparams_bkup.dec_info.dec_info.bit_depth;
        pcfg->minbuf_4output = pcfg->minbuf_4capture = pcfg->minbuf_4output_bkup;
        pcfg->sizeimagedst[0] = pcfg->sizeimagedst_bkup;
@@ -617,13 +621,13 @@ static int vsi_dec_subscribe_event(
 static int vsi_dec_handlestop_unspec(struct vsi_v4l2_ctx *ctx)
 {
        //some unexpected condition fro CTS, not quite conformant to spec
-        if ((ctx->status == VSI_STATUS_INIT && !test_bit(CTX_FLAG_DAEMONLIVE_BIT, &ctx->flag)) ||
+       if ((ctx->status == VSI_STATUS_INIT && !test_bit(CTX_FLAG_DAEMONLIVE_BIT, &ctx->flag)) ||
                ctx->status == DEC_STATUS_STOPPED) {
                clear_bit(CTX_FLAG_PRE_DRAINING_BIT, &ctx->flag);
                vsi_v4l2_sendeos(ctx);
                return 0;
        }
-        if (ctx->status == DEC_STATUS_SEEK && !test_bit(CTX_FLAG_SRCBUF_BIT, &ctx->flag)) {
+       if (ctx->status == DEC_STATUS_SEEK && !test_bit(CTX_FLAG_SRCBUF_BIT, &ctx->flag)) {
                vsi_v4l2_sendeos(ctx);
                return 0;
        }
@@ -1146,8 +1150,7 @@ static __poll_t vsi_dec_poll(struct file *file, poll_table *wait)
        }
        if (vb2_is_streaming(&ctx->output_que))
                ret |= vb2_poll(&ctx->output_que, file, wait);
-       if (vb2_is_streaming(&ctx->input_que))
-               ret |= vb2_poll(&ctx->input_que, file, wait);
+       ret |= vb2_poll(&ctx->input_que, file, wait);
 
        /*recheck for poll hang*/
        if (ret == 0) {
index 8c39351..69b15d4 100755 (executable)
@@ -695,10 +695,8 @@ static void vsi_enc_buf_queue(struct vb2_buffer *vb)
        vsibuf = vb_to_vsibuf(vb);
        if (!binputqueue(vq->type))
                list_add_tail(&vsibuf->list, &ctx->output_list);
-       else {
+       else
                list_add_tail(&vsibuf->list, &ctx->input_list);
-               ctx->queued_srcnum++;
-       }
        ret = vsiv4l2_execcmd(ctx, V4L2_DAEMON_VIDIOC_BUF_RDY, vb);
 }
 
@@ -1390,10 +1388,8 @@ static __poll_t vsi_enc_poll(struct file *file, poll_table *wait)
                v4l2_klog(LOGLVL_BRIEF, "%s event", __func__);
                ret |= POLLPRI;
        }
-       if (vb2_is_streaming(&ctx->output_que))
-               ret |= vb2_poll(&ctx->output_que, file, wait);
-       if (vb2_is_streaming(&ctx->input_que))
-               ret |= vb2_poll(&ctx->input_que, file, wait);
+       ret |= vb2_poll(&ctx->output_que, file, wait);
+       ret |= vb2_poll(&ctx->input_que, file, wait);
 
        /*recheck for poll hang*/
        if (ret == 0) {
index d88fa6e..bfd1fd3 100755 (executable)
@@ -212,6 +212,7 @@ struct vsi_v4l2_mediacfg {
        u32 infmt_fourcc;
        u32 outfmt_fourcc;
        u32 src_pixeldepth;     //dec only
+       u32 orig_dpbsize;       //dec only
        /*profiles for each format is put here instead of encparams to save some transfer data*/
        s32 profile_h264;
        s32 profile_hevc;
@@ -314,8 +315,8 @@ struct vsi_v4l2_ctx {
        u32 rfc_luma_offset[VIDEO_MAX_FRAME];
        u32 rfc_chroma_offset[VIDEO_MAX_FRAME];
        s32 queued_srcnum;
-       u32 buffed_capnum;
-       u32 buffed_cropcapnum;
+       s32 buffed_capnum;
+       s32 buffed_cropcapnum;
        u32 lastcapbuffer_idx;  //latest received capture buffer index
 
        struct vsi_v4l2_mediacfg mediacfg;
@@ -481,6 +482,7 @@ static inline int update_and_removecropinfo(struct vsi_v4l2_ctx *ctx)
                pcfg->decparams.dec_info.io_buffer.output_width = crop->frame_width;
                pcfg->decparams.dec_info.io_buffer.output_height = crop->frame_height;
                pcfg->decparams.dec_info.io_buffer.output_wstride = crop->pic_wstride;
+               pcfg->bytesperline = crop->pic_wstride;
                pcfg->decparams.dec_info.dec_info.frame_width = crop->frame_width;
                pcfg->decparams.dec_info.dec_info.frame_height = crop->frame_height;
                pcfg->decparams.dec_info.dec_info.visible_rect.left = crop->left;
index ac111bb..2bce2b5 100755 (executable)
@@ -306,9 +306,9 @@ int vsi_v4l2_notify_reschange(struct vsi_v4l2_msg *pmsg)
                        return -EBUSY;
                v4l2_klog(LOGLVL_BRIEF, "%lx sending event res change:%d, delay=%d", ctx->ctxid, ctx->status,
                        (ctx->status == DEC_STATUS_DECODING || ctx->status == DEC_STATUS_DRAINING) && !list_empty(&ctx->output_que.done_list));
-               v4l2_klog(LOGLVL_BRIEF, "reso=%d:%d,bitdepth=%d,dpb=%d:%d,orig yuvfmt=%d",
-                       decinfo->frame_width, decinfo->frame_height, decinfo->bit_depth, decinfo->needed_dpb_nums,
-                       decinfo->dpb_buffer_size, decinfo->src_pix_fmt);
+               v4l2_klog(LOGLVL_BRIEF, "reso=%d:%d,bitdepth=%d,stride=%d,dpb=%d:%d,orig yuvfmt=%d",
+                       decinfo->frame_width, decinfo->frame_height, decinfo->bit_depth, pmsg->params.dec_params.io_buffer.output_wstride,
+                       decinfo->needed_dpb_nums, decinfo->dpb_buffer_size, decinfo->src_pix_fmt);
                if ((ctx->status == DEC_STATUS_DECODING || ctx->status == DEC_STATUS_DRAINING)
                        && !list_empty(&ctx->output_que.done_list)) {
                        pcfg->decparams_bkup.dec_info = pmsg->params.dec_params.dec_info;
@@ -327,6 +327,8 @@ int vsi_v4l2_notify_reschange(struct vsi_v4l2_msg *pmsg)
                        pcfg->decparams.dec_info.io_buffer.output_width = pmsg->params.dec_params.dec_info.io_buffer.output_width;
                        pcfg->decparams.dec_info.io_buffer.output_height = pmsg->params.dec_params.dec_info.io_buffer.output_height;
                        pcfg->decparams.dec_info.io_buffer.output_wstride = pmsg->params.dec_params.dec_info.io_buffer.output_wstride;
+                       pcfg->bytesperline = pmsg->params.dec_params.dec_info.io_buffer.output_wstride;
+                       pcfg->orig_dpbsize = decinfo->dpb_buffer_size;
                        pcfg->src_pixeldepth = decinfo->bit_depth;
                        pcfg->minbuf_4output =
                                pcfg->minbuf_4capture = pmsg->params.dec_params.dec_info.dec_info.needed_dpb_nums;
@@ -423,6 +425,7 @@ int vsi_v4l2_handle_cropchange(struct vsi_v4l2_msg *pmsg)
                        pcfg->decparams.dec_info.io_buffer.output_height = pmsg->params.dec_params.pic_info.pic_info.height;
                        pcfg->decparams.dec_info.io_buffer.output_wstride = pmsg->params.dec_params.pic_info.pic_info.pic_wstride;
                        pcfg->decparams.dec_info.dec_info.frame_width = pmsg->params.dec_params.pic_info.pic_info.width;
+                       pcfg->bytesperline = pmsg->params.dec_params.pic_info.pic_info.pic_wstride;
                        pcfg->decparams.dec_info.dec_info.frame_height = pmsg->params.dec_params.pic_info.pic_info.height;
                        pcfg->decparams.dec_info.dec_info.visible_rect.left = pmsg->params.dec_params.pic_info.pic_info.crop_left;
                        pcfg->decparams.dec_info.dec_info.visible_rect.top = pmsg->params.dec_params.pic_info.pic_info.crop_top;
@@ -483,11 +486,6 @@ int vsi_v4l2_bufferdone(struct vsi_v4l2_msg *pmsg)
        if (outbufidx >= 0 && outbufidx < ctx->output_que.num_buffers) {
                if (mutex_lock_interruptible(&ctx->ctxlock))
                        return -EBUSY;
-               if (isencoder(ctx)) {
-                       ctx->queued_srcnum--;
-                       if (ctx->queued_srcnum < 0)
-                               ctx->queued_srcnum = 0;
-               }
                if (!inst_isactive(ctx)) {
                        if (!vb2_is_streaming(&ctx->output_que))
                                v4l2_klog(LOGLVL_ERROR, "%lx ignore dst buffer %d in state %d", ctx->ctxid, outbufidx, ctx->status);
index 20b0f66..b4b1d90 100755 (executable)
@@ -102,7 +102,9 @@ enum v4l2_daemon_cmd_id {
        V4L2_DAEMON_VIDIOC_STREAMON = 0,//for streamon and start
        V4L2_DAEMON_VIDIOC_BUF_RDY,
        V4L2_DAEMON_VIDIOC_CMD_STOP, //this is for flush.
-       V4L2_DAEMON_VIDIOC_STREAMOFF,//for encoder, 4 cmd is enough.
+       V4L2_DAEMON_VIDIOC_STREAMOFF,   //enc destroy
+       V4L2_DAEMON_VIDIOC_ENC_RESET,   //enc reset, as in spec
+       //above are enc cmds
 
        V4L2_DAEMON_VIDIOC_FAKE,//fake command.
 
index 62d43d1..b450208 100755 (executable)
@@ -398,7 +398,8 @@ static void format_bufinfo_dec(struct vsi_v4l2_ctx *ctx, struct vsi_v4l2_msg *pm
                decbufinfo->busOutBuf = busaddr[0] + buf->planes[0].data_offset;
                decbufinfo->OutBufSize = ctx->outbuflen[buf->index];//ctx->mediacfg.sizeimagedst[0];
                decbufinfo->bytesused = buf->planes[0].bytesused;
-               if ((ctx->mediacfg.src_pixeldepth == ctx->mediacfg.decparams.dec_info.io_buffer.outputPixelDepth)
+               if (((ctx->mediacfg.src_pixeldepth == ctx->mediacfg.decparams.dec_info.io_buffer.outputPixelDepth)
+                       && ctx->mediacfg.src_pixeldepth != 16)  //p010 can only set by user, not from ctrl sw
                        || !test_bit(CTX_FLAG_SRCCHANGED_BIT, &ctx->flag))
                        pmsg->params.dec_params.io_buffer.outputPixelDepth = DEFAULT_PIXELDEPTH;
        } else {
@@ -492,7 +493,7 @@ tail:
        if (ctx) {
                if (ret < 0) {
                        vsi_set_ctx_error(ctx, ret);
-                       v4l2_klog(LOGLVL_ERROR, "%lx fail to communicate with daemon, error=%d", ctx->ctxid, ret);
+                       v4l2_klog(LOGLVL_ERROR, "%lx fail to communicate with daemon, error=%d, cmd=%d", ctx->ctxid, ret, id);
                } else
                        set_bit(CTX_FLAG_DAEMONLIVE_BIT, &ctx->flag);
        }
@@ -665,16 +666,16 @@ static ssize_t v4l2_msg_write(struct file *fh, const char __user *buf, size_t si
                vsi_handle_daemonmsg(pmsg);
                kfree(pmsg);
                return size;
-       } else {
-               if (mutex_lock_interruptible(&ret_lock)) {
-                       kfree(pmsg);
-                       return size;
-               }
-               ret = idr_alloc(retarray, (void *)pmsg, 1, 0, GFP_KERNEL);
-               mutex_unlock(&ret_lock);
-               if (ret < 0)
-                       kfree(pmsg);
        }
+       if (mutex_lock_interruptible(&ret_lock)) {
+               kfree(pmsg);
+               return size;
+       }
+       ret = idr_alloc(retarray, (void *)pmsg, 1, 0, GFP_KERNEL);
+       mutex_unlock(&ret_lock);
+       if (ret < 0)
+               kfree(pmsg);
+
 error:
        if (ret >= 0)
                wake_up_interruptible_all(&ret_queue);