Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] mtk-vcodec: use V4L2_DEC_CMD_STOP to implement flush

Also remove the code using size-0 OUTPUT buffer to flush.

Signed-off-by: Tiffany Lin <tiffany.lin@mediatek.com>
Signed-off-by: Wu-Cheng Li <wuchengli@chromium.org>
Reviewed-by: Kuang-che Wu <kcwu@chromium.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Tiffany Lin and committed by
Mauro Carvalho Chehab
4865fffa 974eadf1

+117 -50
+101 -50
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
··· 351 351 dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); 352 352 dst_buf_info = container_of(dst_vb2_v4l2, struct mtk_video_dec_buf, vb); 353 353 354 - buf.va = vb2_plane_vaddr(src_buf, 0); 355 - buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); 356 - buf.size = (size_t)src_buf->planes[0].bytesused; 357 - if (!buf.va) { 358 - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); 359 - mtk_v4l2_err("[%d] id=%d src_addr is NULL!!", 360 - ctx->id, src_buf->index); 361 - return; 362 - } 363 - 364 354 pfb = &dst_buf_info->frame_buffer; 365 355 pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); 366 356 pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); ··· 361 371 pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz; 362 372 pfb->status = 0; 363 373 mtk_v4l2_debug(3, "===>[%d] vdec_if_decode() ===>", ctx->id); 364 - mtk_v4l2_debug(3, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", 365 - ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf); 366 374 367 375 mtk_v4l2_debug(3, 368 376 "id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad Size=%zx", ··· 369 381 &pfb->base_c.dma_addr, pfb->base_y.size); 370 382 371 383 if (src_buf_info->lastframe) { 372 - /* update src buf status */ 384 + mtk_v4l2_debug(1, "Got empty flush input buffer."); 373 385 src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); 374 - src_buf_info->lastframe = false; 375 - v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); 376 386 377 387 /* update dst buf status */ 378 388 dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); 389 + mutex_lock(&ctx->lock); 379 390 dst_buf_info->used = false; 391 + mutex_unlock(&ctx->lock); 380 392 381 393 vdec_if_decode(ctx, NULL, NULL, &res_chg); 382 394 clean_display_buffer(ctx); 383 395 vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 0, 0); 384 396 vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 1, 0); 397 + dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST; 385 398 v4l2_m2m_buf_done(&dst_buf_info->vb, VB2_BUF_STATE_DONE); 386 399 clean_free_buffer(ctx); 387 400 v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); 388 401 return; 389 402 } 403 + buf.va = vb2_plane_vaddr(src_buf, 0); 404 + buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); 405 + buf.size = (size_t)src_buf->planes[0].bytesused; 406 + if (!buf.va) { 407 + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); 408 + mtk_v4l2_err("[%d] id=%d src_addr is NULL!!", 409 + ctx->id, src_buf->index); 410 + return; 411 + } 412 + mtk_v4l2_debug(3, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", 413 + ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf); 390 414 dst_buf_info->vb.vb2_buf.timestamp 391 415 = src_buf_info->vb.vb2_buf.timestamp; 392 416 dst_buf_info->vb.timecode ··· 412 412 413 413 if (ret) { 414 414 mtk_v4l2_err( 415 - " <===[%d], src_buf[%d]%d sz=0x%zx pts=%llu dst_buf[%d] vdec_if_decode() ret=%d res_chg=%d===>", 415 + " <===[%d], src_buf[%d] sz=0x%zx pts=%llu dst_buf[%d] vdec_if_decode() ret=%d res_chg=%d===>", 416 416 ctx->id, 417 417 src_buf->index, 418 - src_buf_info->lastframe, 419 418 buf.size, 420 419 src_buf_info->vb.vb2_buf.timestamp, 421 420 dst_buf->index, ··· 453 454 mtk_vdec_queue_res_chg_event(ctx); 454 455 } 455 456 v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); 457 + } 458 + 459 + static int vidioc_try_decoder_cmd(struct file *file, void *priv, 460 + struct v4l2_decoder_cmd *cmd) 461 + { 462 + switch (cmd->cmd) { 463 + case V4L2_DEC_CMD_STOP: 464 + case V4L2_DEC_CMD_START: 465 + if (cmd->flags != 0) { 466 + mtk_v4l2_err("cmd->flags=%u", cmd->flags); 467 + return -EINVAL; 468 + } 469 + break; 470 + default: 471 + return -EINVAL; 472 + } 473 + return 0; 474 + } 475 + 476 + 477 + static int vidioc_decoder_cmd(struct file *file, void *priv, 478 + struct v4l2_decoder_cmd *cmd) 479 + { 480 + struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); 481 + struct vb2_queue *src_vq, *dst_vq; 482 + int ret; 483 + 484 + ret = vidioc_try_decoder_cmd(file, priv, cmd); 485 + if (ret) 486 + return ret; 487 + 488 + mtk_v4l2_debug(1, "decoder cmd=%u", cmd->cmd); 489 + dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, 490 + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 491 + switch (cmd->cmd) { 492 + case V4L2_DEC_CMD_STOP: 493 + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, 494 + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 495 + if (!vb2_is_streaming(src_vq)) { 496 + mtk_v4l2_debug(1, "Output stream is off. No need to flush."); 497 + return 0; 498 + } 499 + if (!vb2_is_streaming(dst_vq)) { 500 + mtk_v4l2_debug(1, "Capture stream is off. No need to flush."); 501 + return 0; 502 + } 503 + v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb); 504 + v4l2_m2m_try_schedule(ctx->m2m_ctx); 505 + break; 506 + 507 + case V4L2_DEC_CMD_START: 508 + vb2_clear_last_buffer_dequeued(dst_vq); 509 + break; 510 + 511 + default: 512 + return -EINVAL; 513 + } 514 + 515 + return 0; 456 516 } 457 517 458 518 void mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx) ··· 579 521 struct v4l2_buffer *buf) 580 522 { 581 523 struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv); 582 - struct vb2_queue *vq; 583 - struct vb2_buffer *vb; 584 - struct mtk_video_dec_buf *mtkbuf; 585 - struct vb2_v4l2_buffer *vb2_v4l2; 586 524 587 525 if (ctx->state == MTK_STATE_ABORT) { 588 526 mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error", 589 527 ctx->id); 590 528 return -EIO; 591 - } 592 - 593 - vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type); 594 - if (buf->index >= vq->num_buffers) { 595 - mtk_v4l2_debug(1, "buffer index %d out of range", buf->index); 596 - return -EINVAL; 597 - } 598 - vb = vq->bufs[buf->index]; 599 - vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf); 600 - mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb); 601 - 602 - if ((buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && 603 - (buf->m.planes[0].bytesused == 0)) { 604 - mtkbuf->lastframe = true; 605 - mtk_v4l2_debug(1, "[%d] (%d) id=%d lastframe=%d (%d,%d, %d) vb=%p", 606 - ctx->id, buf->type, buf->index, 607 - mtkbuf->lastframe, buf->bytesused, 608 - buf->m.planes[0].bytesused, buf->length, 609 - vb); 610 529 } 611 530 612 531 return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); ··· 1102 1067 int ret = 0; 1103 1068 unsigned int dpbsize = 1; 1104 1069 struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); 1105 - struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb, 1106 - struct vb2_v4l2_buffer, vb2_buf); 1107 - struct mtk_video_dec_buf *buf = container_of(vb2_v4l2, 1108 - struct mtk_video_dec_buf, vb); 1070 + struct vb2_v4l2_buffer *vb2_v4l2 = NULL; 1071 + struct mtk_video_dec_buf *buf = NULL; 1109 1072 1110 1073 mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p", 1111 1074 ctx->id, vb->vb2_queue->type, ··· 1112 1079 * check if this buffer is ready to be used after decode 1113 1080 */ 1114 1081 if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 1082 + vb2_v4l2 = to_vb2_v4l2_buffer(vb); 1083 + buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb); 1115 1084 mutex_lock(&ctx->lock); 1116 1085 if (buf->used == false) { 1117 - v4l2_m2m_buf_queue(ctx->m2m_ctx, 1118 - to_vb2_v4l2_buffer(vb)); 1086 + v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); 1119 1087 buf->queued_in_vb2 = true; 1120 1088 buf->queued_in_v4l2 = true; 1121 1089 buf->ready_to_display = false; ··· 1129 1095 return; 1130 1096 } 1131 1097 1132 - v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); 1098 + v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb)); 1133 1099 1134 1100 if (ctx->state != MTK_STATE_INIT) { 1135 1101 mtk_v4l2_debug(3, "[%d] already init driver %d", ··· 1140 1106 src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); 1141 1107 if (!src_buf) { 1142 1108 mtk_v4l2_err("No src buffer"); 1109 + return; 1110 + } 1111 + vb2_v4l2 = to_vb2_v4l2_buffer(src_buf); 1112 + buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb); 1113 + if (buf->lastframe) { 1114 + /* This shouldn't happen. Just in case. */ 1115 + mtk_v4l2_err("Invalid flush buffer."); 1116 + v4l2_m2m_src_buf_remove(ctx->m2m_ctx); 1143 1117 return; 1144 1118 } 1145 1119 ··· 1266 1224 ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt); 1267 1225 1268 1226 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 1269 - while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) 1270 - v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf), 1271 - VB2_BUF_STATE_ERROR); 1227 + while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx))) { 1228 + struct vb2_v4l2_buffer *vb2_v4l2 = 1229 + to_vb2_v4l2_buffer(src_buf); 1230 + struct mtk_video_dec_buf *buf_info = container_of( 1231 + vb2_v4l2, struct mtk_video_dec_buf, vb); 1232 + if (!buf_info->lastframe) 1233 + v4l2_m2m_buf_done(vb2_v4l2, 1234 + VB2_BUF_STATE_ERROR); 1235 + } 1272 1236 return; 1273 1237 } 1274 1238 ··· 1454 1406 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 1455 1407 .vidioc_g_selection = vidioc_vdec_g_selection, 1456 1408 .vidioc_s_selection = vidioc_vdec_s_selection, 1409 + 1410 + .vidioc_decoder_cmd = vidioc_decoder_cmd, 1411 + .vidioc_try_decoder_cmd = vidioc_try_decoder_cmd, 1457 1412 }; 1458 1413 1459 1414 int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+14
drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
··· 105 105 { 106 106 struct mtk_vcodec_dev *dev = video_drvdata(file); 107 107 struct mtk_vcodec_ctx *ctx = NULL; 108 + struct mtk_video_dec_buf *mtk_buf = NULL; 108 109 int ret = 0; 110 + struct vb2_queue *src_vq; 109 111 110 112 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 111 113 if (!ctx) 112 114 return -ENOMEM; 115 + mtk_buf = kzalloc(sizeof(*mtk_buf), GFP_KERNEL); 116 + if (!mtk_buf) { 117 + kfree(ctx); 118 + return -ENOMEM; 119 + } 113 120 114 121 mutex_lock(&dev->dev_mutex); 122 + ctx->empty_flush_buf = mtk_buf; 115 123 ctx->id = dev->id_counter++; 116 124 v4l2_fh_init(&ctx->fh, video_devdata(file)); 117 125 file->private_data = &ctx->fh; ··· 143 135 ret); 144 136 goto err_m2m_ctx_init; 145 137 } 138 + src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, 139 + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 140 + ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq; 141 + ctx->empty_flush_buf->lastframe = true; 146 142 mtk_vcodec_dec_set_default_params(ctx); 147 143 148 144 if (v4l2_fh_is_singular(&ctx->fh)) { ··· 185 173 err_ctrls_setup: 186 174 v4l2_fh_del(&ctx->fh); 187 175 v4l2_fh_exit(&ctx->fh); 176 + kfree(ctx->empty_flush_buf); 188 177 kfree(ctx); 189 178 mutex_unlock(&dev->dev_mutex); 190 179 ··· 216 203 v4l2_ctrl_handler_free(&ctx->ctrl_hdl); 217 204 218 205 list_del_init(&ctx->list); 206 + kfree(ctx->empty_flush_buf); 219 207 kfree(ctx); 220 208 mutex_unlock(&dev->dev_mutex); 221 209 return 0;
+2
drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
··· 254 254 * @decode_work: worker for the decoding 255 255 * @encode_work: worker for the encoding 256 256 * @last_decoded_picinfo: pic information get from latest decode 257 + * @empty_flush_buf: a fake size-0 capture buffer that indicates flush 257 258 * 258 259 * @colorspace: enum v4l2_colorspace; supplemental to pixelformat 259 260 * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding ··· 292 291 struct work_struct decode_work; 293 292 struct work_struct encode_work; 294 293 struct vdec_pic_info last_decoded_picinfo; 294 + struct mtk_video_dec_buf *empty_flush_buf; 295 295 296 296 enum v4l2_colorspace colorspace; 297 297 enum v4l2_ycbcr_encoding ycbcr_enc;