}
}
-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)) {
case V4L2_PIX_FMT_411SP:
extsize = basesize / 2;
quadsize = basesize / 4;
+ if (bdecoder)
+ padsize = quadsize + 32;
break;
case V4L2_PIX_FMT_NV16:
extsize = basesize;
}
}
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;
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++)
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;
}
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;
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
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;
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);
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;
}
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;
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;
}
}
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) {
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);
}
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) {
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;
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;
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;
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;
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;
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;
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);
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.
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 {
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);
}
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);