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

media: vicodec: use v4l2-mem2mem draining, stopped and next-buf-is-last states handling

Use the previously introduced v4l2-mem2mem core APIs to handle the drainig,
stopped and next-buf-is-last states.

With these changes, the v4l2-compliance still passes with the following
commands :
>>>><><><><><><><><><><><><><><><><>< 15.53 fps
15.53 fps
><><><><><><><><><><><><>< 13.99 fps
13.99 fps
><><><><><><><><><><><>< 13.52 fps
13.52 fps
><><><><><><><><><><><><>< 13.41 fps
13.41 fps
><><><><><><><><><><><><>< 13.21 fps
13.21 fps
><><><><><><><><><><><>< 13.09 fps
13.09 fps
><><><><><><><
STOP ENCODER
<<<
EOS EVENT

v4l2-compliance SHA: 7ead0e1856b89f2e19369af452bb03fd0cd16793, 64 bits
[...]
Total for vicodec device /dev/video0: 50, Succeeded: 50, Failed: 0, Warnings: 0

The full output is available at [1]

v4l2-compliance SHA: 7ead0e1856b89f2e19369af452bb03fd0cd16793, 64 bits
[...]
Total for vicodec device /dev/video1: 50, Succeeded: 50, Failed: 0, Warnings: 0

The full output is available at [2]

No functional changes should be noticed.

[1] https://termbin.com/25nn
[2] https://termbin.com/dza4

Suggested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Suggested-by: Maxime Jourdan <mjourdan@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Neil Armstrong and committed by
Mauro Carvalho Chehab
d4d137de 2b48e113

+51 -109
+51 -109
drivers/media/platform/vicodec/vicodec-core.c
··· 117 117 struct vicodec_dev *dev; 118 118 bool is_enc; 119 119 bool is_stateless; 120 - bool is_draining; 121 - bool next_is_last; 122 - bool has_stopped; 123 120 spinlock_t *lock; 124 121 125 122 struct v4l2_ctrl_handler hdl; 126 - 127 - struct vb2_v4l2_buffer *last_src_buf; 128 123 129 124 /* Source and destination queue data */ 130 125 struct vicodec_q_data q_data[2]; ··· 426 431 v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); 427 432 428 433 spin_lock(ctx->lock); 429 - if (!ctx->comp_has_next_frame && src_buf == ctx->last_src_buf) { 434 + if (!ctx->comp_has_next_frame && 435 + v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) { 430 436 dst_buf->flags |= V4L2_BUF_FLAG_LAST; 431 437 v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 432 - ctx->is_draining = false; 433 - ctx->has_stopped = true; 438 + v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx); 434 439 } 435 440 if (ctx->is_enc || ctx->is_stateless) { 436 441 src_buf->sequence = q_src->sequence++; ··· 581 586 unsigned int max_to_copy; 582 587 unsigned int comp_frame_size; 583 588 584 - if (ctx->has_stopped) 585 - return 0; 586 589 if (ctx->source_changed) 587 590 return 0; 588 591 if (ctx->is_stateless || ctx->is_enc || ctx->comp_has_frame) ··· 600 607 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) { 601 608 state = get_next_header(ctx, &p, p_src + sz - p); 602 609 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) { 603 - if (ctx->is_draining && src_buf == ctx->last_src_buf) 610 + if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, 611 + src_buf)) 604 612 return 1; 605 613 job_remove_src_buf(ctx, state); 606 614 goto restart; ··· 630 636 p += copy; 631 637 ctx->comp_size += copy; 632 638 if (ctx->comp_size < max_to_copy) { 633 - if (ctx->is_draining && src_buf == ctx->last_src_buf) 639 + if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, 640 + src_buf)) 634 641 return 1; 635 642 job_remove_src_buf(ctx, state); 636 643 goto restart; ··· 1214 1219 return 0; 1215 1220 } 1216 1221 1217 - static int vicodec_mark_last_buf(struct vicodec_ctx *ctx) 1218 - { 1219 - struct vb2_v4l2_buffer *next_dst_buf; 1220 - int ret = 0; 1221 - 1222 - spin_lock(ctx->lock); 1223 - if (ctx->is_draining) { 1224 - ret = -EBUSY; 1225 - goto unlock; 1226 - } 1227 - if (ctx->has_stopped) 1228 - goto unlock; 1229 - 1230 - ctx->last_src_buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx); 1231 - ctx->is_draining = true; 1232 - if (ctx->last_src_buf) 1233 - goto unlock; 1234 - 1235 - next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 1236 - if (!next_dst_buf) { 1237 - ctx->next_is_last = true; 1238 - goto unlock; 1239 - } 1240 - 1241 - next_dst_buf->flags |= V4L2_BUF_FLAG_LAST; 1242 - vb2_buffer_done(&next_dst_buf->vb2_buf, VB2_BUF_STATE_DONE); 1243 - ctx->is_draining = false; 1244 - ctx->has_stopped = true; 1245 - v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 1246 - 1247 - unlock: 1248 - spin_unlock(ctx->lock); 1249 - return ret; 1250 - } 1251 - 1252 1222 static int vicodec_encoder_cmd(struct file *file, void *fh, 1253 1223 struct v4l2_encoder_cmd *ec) 1254 1224 { ··· 1228 1268 !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q)) 1229 1269 return 0; 1230 1270 1231 - if (ec->cmd == V4L2_ENC_CMD_STOP) 1232 - return vicodec_mark_last_buf(ctx); 1233 - ret = 0; 1234 - spin_lock(ctx->lock); 1235 - if (ctx->is_draining) { 1236 - ret = -EBUSY; 1237 - } else if (ctx->has_stopped) { 1238 - ctx->has_stopped = false; 1271 + ret = v4l2_m2m_ioctl_encoder_cmd(file, fh, ec); 1272 + if (ret < 0) 1273 + return ret; 1274 + 1275 + if (ec->cmd == V4L2_ENC_CMD_STOP && 1276 + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) 1277 + v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 1278 + 1279 + if (ec->cmd == V4L2_ENC_CMD_START && 1280 + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) 1239 1281 vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q); 1240 - } 1241 - spin_unlock(ctx->lock); 1242 - return ret; 1282 + 1283 + return 0; 1243 1284 } 1244 1285 1245 1286 static int vicodec_decoder_cmd(struct file *file, void *fh, ··· 1257 1296 !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q)) 1258 1297 return 0; 1259 1298 1260 - if (dc->cmd == V4L2_DEC_CMD_STOP) 1261 - return vicodec_mark_last_buf(ctx); 1262 - ret = 0; 1263 - spin_lock(ctx->lock); 1264 - if (ctx->is_draining) { 1265 - ret = -EBUSY; 1266 - } else if (ctx->has_stopped) { 1267 - ctx->has_stopped = false; 1299 + ret = v4l2_m2m_ioctl_decoder_cmd(file, fh, dc); 1300 + if (ret < 0) 1301 + return ret; 1302 + 1303 + if (dc->cmd == V4L2_DEC_CMD_STOP && 1304 + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) 1305 + v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 1306 + 1307 + if (dc->cmd == V4L2_DEC_CMD_START && 1308 + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) 1268 1309 vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q); 1269 - } 1270 - spin_unlock(ctx->lock); 1271 - return ret; 1310 + 1311 + return 0; 1272 1312 } 1273 1313 1274 1314 static int vicodec_enum_framesizes(struct file *file, void *fh, ··· 1442 1480 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, 1443 1481 }; 1444 1482 1445 - if (vb2_is_streaming(vq_cap)) { 1446 - if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) && 1447 - ctx->next_is_last) { 1448 - unsigned int i; 1483 + if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) && 1484 + vb2_is_streaming(vb->vb2_queue) && 1485 + v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) { 1486 + unsigned int i; 1449 1487 1450 - for (i = 0; i < vb->num_planes; i++) 1451 - vb->planes[i].bytesused = 0; 1452 - vbuf->flags = V4L2_BUF_FLAG_LAST; 1453 - vbuf->field = V4L2_FIELD_NONE; 1454 - vbuf->sequence = get_q_data(ctx, vb->vb2_queue->type)->sequence++; 1455 - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); 1456 - ctx->is_draining = false; 1457 - ctx->has_stopped = true; 1458 - ctx->next_is_last = false; 1459 - v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 1460 - return; 1461 - } 1488 + for (i = 0; i < vb->num_planes; i++) 1489 + vb->planes[i].bytesused = 0; 1490 + 1491 + vbuf->field = V4L2_FIELD_NONE; 1492 + vbuf->sequence = 1493 + get_q_data(ctx, vb->vb2_queue->type)->sequence++; 1494 + 1495 + v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf); 1496 + v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 1497 + return; 1462 1498 } 1463 1499 1464 1500 /* buf_queue handles only the first source change event */ ··· 1569 1609 chroma_div = info->width_div * info->height_div; 1570 1610 q_data->sequence = 0; 1571 1611 1572 - if (V4L2_TYPE_IS_OUTPUT(q->type)) 1573 - ctx->last_src_buf = NULL; 1612 + v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q); 1574 1613 1575 1614 state->gop_cnt = 0; 1576 1615 ··· 1648 1689 1649 1690 vicodec_return_bufs(q, VB2_BUF_STATE_ERROR); 1650 1691 1651 - if (V4L2_TYPE_IS_OUTPUT(q->type)) { 1652 - if (ctx->is_draining) { 1653 - struct vb2_v4l2_buffer *next_dst_buf; 1692 + v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q); 1654 1693 1655 - spin_lock(ctx->lock); 1656 - ctx->last_src_buf = NULL; 1657 - next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); 1658 - if (!next_dst_buf) { 1659 - ctx->next_is_last = true; 1660 - } else { 1661 - next_dst_buf->flags |= V4L2_BUF_FLAG_LAST; 1662 - vb2_buffer_done(&next_dst_buf->vb2_buf, VB2_BUF_STATE_DONE); 1663 - ctx->is_draining = false; 1664 - ctx->has_stopped = true; 1665 - v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 1666 - } 1667 - spin_unlock(ctx->lock); 1668 - } 1669 - } else { 1670 - ctx->is_draining = false; 1671 - ctx->has_stopped = false; 1672 - ctx->next_is_last = false; 1673 - } 1694 + if (V4L2_TYPE_IS_OUTPUT(q->type) && 1695 + v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) 1696 + v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event); 1697 + 1674 1698 if (!ctx->is_enc && V4L2_TYPE_IS_OUTPUT(q->type)) 1675 1699 ctx->first_source_change_sent = false; 1676 1700