.. | .. |
---|
495 | 495 | vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) |
---|
496 | 496 | { |
---|
497 | 497 | struct venus_inst *inst = to_inst(file); |
---|
| 498 | + struct vb2_queue *dst_vq; |
---|
498 | 499 | struct hfi_frame_data fdata = {0}; |
---|
499 | 500 | int ret; |
---|
500 | 501 | |
---|
.. | .. |
---|
518 | 519 | |
---|
519 | 520 | ret = hfi_session_process_buf(inst, &fdata); |
---|
520 | 521 | |
---|
521 | | - if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING) |
---|
| 522 | + if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING) { |
---|
522 | 523 | inst->codec_state = VENUS_DEC_STATE_DRAIN; |
---|
| 524 | + inst->drain_active = true; |
---|
| 525 | + } |
---|
| 526 | + } else if (cmd->cmd == V4L2_DEC_CMD_START && |
---|
| 527 | + inst->codec_state == VENUS_DEC_STATE_STOPPED) { |
---|
| 528 | + dst_vq = v4l2_m2m_get_vq(inst->fh.m2m_ctx, |
---|
| 529 | + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); |
---|
| 530 | + vb2_clear_last_buffer_dequeued(dst_vq); |
---|
| 531 | + |
---|
| 532 | + inst->codec_state = VENUS_DEC_STATE_DECODING; |
---|
523 | 533 | } |
---|
524 | 534 | |
---|
525 | 535 | unlock: |
---|
.. | .. |
---|
636 | 646 | { |
---|
637 | 647 | struct venus_core *core = inst->core; |
---|
638 | 648 | struct hfi_enable en = { .enable = 1 }; |
---|
| 649 | + struct hfi_buffer_requirements bufreq; |
---|
639 | 650 | u32 width = inst->out_width; |
---|
640 | 651 | u32 height = inst->out_height; |
---|
641 | 652 | u32 out_fmt, out2_fmt; |
---|
.. | .. |
---|
711 | 722 | } |
---|
712 | 723 | |
---|
713 | 724 | if (IS_V3(core) || IS_V4(core)) { |
---|
| 725 | + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq); |
---|
| 726 | + if (ret) |
---|
| 727 | + return ret; |
---|
| 728 | + |
---|
| 729 | + if (bufreq.size > inst->output_buf_size) |
---|
| 730 | + return -EINVAL; |
---|
| 731 | + |
---|
| 732 | + if (inst->dpb_fmt) { |
---|
| 733 | + ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT2, |
---|
| 734 | + &bufreq); |
---|
| 735 | + if (ret) |
---|
| 736 | + return ret; |
---|
| 737 | + |
---|
| 738 | + if (bufreq.size > inst->output2_buf_size) |
---|
| 739 | + return -EINVAL; |
---|
| 740 | + } |
---|
| 741 | + |
---|
714 | 742 | if (inst->output2_buf_size) { |
---|
715 | 743 | ret = venus_helper_set_bufsize(inst, |
---|
716 | 744 | inst->output2_buf_size, |
---|
.. | .. |
---|
916 | 944 | return 0; |
---|
917 | 945 | |
---|
918 | 946 | reconfigure: |
---|
919 | | - ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, true); |
---|
920 | | - if (ret) |
---|
921 | | - return ret; |
---|
922 | | - |
---|
923 | 947 | ret = vdec_output_conf(inst); |
---|
924 | 948 | if (ret) |
---|
925 | 949 | return ret; |
---|
.. | .. |
---|
947 | 971 | |
---|
948 | 972 | venus_pm_load_scale(inst); |
---|
949 | 973 | |
---|
| 974 | + inst->next_buf_last = false; |
---|
| 975 | + |
---|
950 | 976 | ret = hfi_session_continue(inst); |
---|
951 | 977 | if (ret) |
---|
952 | 978 | goto free_dpb_bufs; |
---|
953 | 979 | |
---|
954 | 980 | inst->codec_state = VENUS_DEC_STATE_DECODING; |
---|
955 | 981 | |
---|
| 982 | + if (inst->drain_active) |
---|
| 983 | + inst->codec_state = VENUS_DEC_STATE_DRAIN; |
---|
| 984 | + |
---|
956 | 985 | inst->streamon_cap = 1; |
---|
957 | 986 | inst->sequence_cap = 0; |
---|
958 | 987 | inst->reconfig = false; |
---|
| 988 | + inst->drain_active = false; |
---|
959 | 989 | |
---|
960 | 990 | return 0; |
---|
961 | 991 | |
---|
.. | .. |
---|
971 | 1001 | |
---|
972 | 1002 | if (inst->codec_state == VENUS_DEC_STATE_SEEK) { |
---|
973 | 1003 | ret = venus_helper_process_initial_out_bufs(inst); |
---|
974 | | - inst->codec_state = VENUS_DEC_STATE_DECODING; |
---|
| 1004 | + if (inst->next_buf_last) |
---|
| 1005 | + inst->codec_state = VENUS_DEC_STATE_DRC; |
---|
| 1006 | + else |
---|
| 1007 | + inst->codec_state = VENUS_DEC_STATE_DECODING; |
---|
975 | 1008 | goto done; |
---|
976 | 1009 | } |
---|
977 | 1010 | |
---|
.. | .. |
---|
987 | 1020 | venus_helper_init_instance(inst); |
---|
988 | 1021 | inst->sequence_out = 0; |
---|
989 | 1022 | inst->reconfig = false; |
---|
| 1023 | + inst->next_buf_last = false; |
---|
990 | 1024 | |
---|
991 | 1025 | ret = vdec_set_properties(inst); |
---|
992 | 1026 | if (ret) |
---|
.. | .. |
---|
1076 | 1110 | ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true); |
---|
1077 | 1111 | fallthrough; |
---|
1078 | 1112 | case VENUS_DEC_STATE_DRAIN: |
---|
1079 | | - vdec_cancel_dst_buffers(inst); |
---|
1080 | 1113 | inst->codec_state = VENUS_DEC_STATE_STOPPED; |
---|
| 1114 | + inst->drain_active = false; |
---|
| 1115 | + fallthrough; |
---|
| 1116 | + case VENUS_DEC_STATE_SEEK: |
---|
| 1117 | + vdec_cancel_dst_buffers(inst); |
---|
1081 | 1118 | break; |
---|
1082 | 1119 | case VENUS_DEC_STATE_DRC: |
---|
1083 | | - WARN_ON(1); |
---|
1084 | | - fallthrough; |
---|
1085 | | - case VENUS_DEC_STATE_DRC_FLUSH_DONE: |
---|
| 1120 | + ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, true); |
---|
1086 | 1121 | inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP; |
---|
1087 | 1122 | venus_helper_free_dpb_bufs(inst); |
---|
1088 | 1123 | break; |
---|
.. | .. |
---|
1101 | 1136 | case VENUS_DEC_STATE_DECODING: |
---|
1102 | 1137 | case VENUS_DEC_STATE_DRAIN: |
---|
1103 | 1138 | case VENUS_DEC_STATE_STOPPED: |
---|
| 1139 | + case VENUS_DEC_STATE_DRC: |
---|
1104 | 1140 | ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true); |
---|
1105 | 1141 | inst->codec_state = VENUS_DEC_STATE_SEEK; |
---|
1106 | 1142 | break; |
---|
.. | .. |
---|
1206 | 1242 | static void vdec_vb2_buf_queue(struct vb2_buffer *vb) |
---|
1207 | 1243 | { |
---|
1208 | 1244 | struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue); |
---|
| 1245 | + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
---|
| 1246 | + static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS }; |
---|
1209 | 1247 | |
---|
1210 | 1248 | vdec_pm_get_put(inst); |
---|
| 1249 | + |
---|
| 1250 | + mutex_lock(&inst->lock); |
---|
| 1251 | + |
---|
| 1252 | + if (inst->next_buf_last && V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) && |
---|
| 1253 | + inst->codec_state == VENUS_DEC_STATE_DRC) { |
---|
| 1254 | + vbuf->flags |= V4L2_BUF_FLAG_LAST; |
---|
| 1255 | + vbuf->sequence = inst->sequence_cap++; |
---|
| 1256 | + vbuf->field = V4L2_FIELD_NONE; |
---|
| 1257 | + vb2_set_plane_payload(vb, 0, 0); |
---|
| 1258 | + v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); |
---|
| 1259 | + v4l2_event_queue_fh(&inst->fh, &eos); |
---|
| 1260 | + inst->next_buf_last = false; |
---|
| 1261 | + mutex_unlock(&inst->lock); |
---|
| 1262 | + return; |
---|
| 1263 | + } |
---|
| 1264 | + |
---|
| 1265 | + mutex_unlock(&inst->lock); |
---|
1211 | 1266 | |
---|
1212 | 1267 | venus_helper_vb2_buf_queue(vb); |
---|
1213 | 1268 | } |
---|
.. | .. |
---|
1252 | 1307 | vb->timestamp = timestamp_us * NSEC_PER_USEC; |
---|
1253 | 1308 | vbuf->sequence = inst->sequence_cap++; |
---|
1254 | 1309 | |
---|
1255 | | - if (inst->last_buf == vb) { |
---|
1256 | | - inst->last_buf = NULL; |
---|
1257 | | - vbuf->flags |= V4L2_BUF_FLAG_LAST; |
---|
1258 | | - vb2_set_plane_payload(vb, 0, 0); |
---|
1259 | | - vb->timestamp = 0; |
---|
1260 | | - } |
---|
1261 | | - |
---|
1262 | 1310 | if (vbuf->flags & V4L2_BUF_FLAG_LAST) { |
---|
1263 | 1311 | const struct v4l2_event ev = { .type = V4L2_EVENT_EOS }; |
---|
1264 | 1312 | |
---|
1265 | 1313 | v4l2_event_queue_fh(&inst->fh, &ev); |
---|
1266 | 1314 | |
---|
1267 | | - if (inst->codec_state == VENUS_DEC_STATE_DRAIN) |
---|
| 1315 | + if (inst->codec_state == VENUS_DEC_STATE_DRAIN) { |
---|
| 1316 | + inst->drain_active = false; |
---|
1268 | 1317 | inst->codec_state = VENUS_DEC_STATE_STOPPED; |
---|
| 1318 | + } |
---|
1269 | 1319 | } |
---|
1270 | 1320 | |
---|
1271 | 1321 | if (!bytesused) |
---|
.. | .. |
---|
1321 | 1371 | dev_dbg(dev, VDBGM "event %s sufficient resources (%ux%u)\n", |
---|
1322 | 1372 | sufficient ? "" : "not", ev_data->width, ev_data->height); |
---|
1323 | 1373 | |
---|
1324 | | - if (sufficient) { |
---|
1325 | | - hfi_session_continue(inst); |
---|
1326 | | - } else { |
---|
1327 | | - switch (inst->codec_state) { |
---|
1328 | | - case VENUS_DEC_STATE_INIT: |
---|
1329 | | - inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP; |
---|
1330 | | - break; |
---|
1331 | | - case VENUS_DEC_STATE_DECODING: |
---|
1332 | | - inst->codec_state = VENUS_DEC_STATE_DRC; |
---|
1333 | | - break; |
---|
1334 | | - default: |
---|
1335 | | - break; |
---|
1336 | | - } |
---|
| 1374 | + switch (inst->codec_state) { |
---|
| 1375 | + case VENUS_DEC_STATE_INIT: |
---|
| 1376 | + inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP; |
---|
| 1377 | + break; |
---|
| 1378 | + case VENUS_DEC_STATE_DECODING: |
---|
| 1379 | + case VENUS_DEC_STATE_DRAIN: |
---|
| 1380 | + inst->codec_state = VENUS_DEC_STATE_DRC; |
---|
| 1381 | + break; |
---|
| 1382 | + default: |
---|
| 1383 | + break; |
---|
1337 | 1384 | } |
---|
1338 | 1385 | |
---|
1339 | 1386 | /* |
---|
.. | .. |
---|
1342 | 1389 | * itself doesn't mark the last decoder output buffer with HFI EOS flag. |
---|
1343 | 1390 | */ |
---|
1344 | 1391 | |
---|
1345 | | - if (!sufficient && inst->codec_state == VENUS_DEC_STATE_DRC) { |
---|
1346 | | - struct vb2_v4l2_buffer *last; |
---|
| 1392 | + if (inst->codec_state == VENUS_DEC_STATE_DRC) { |
---|
1347 | 1393 | int ret; |
---|
1348 | 1394 | |
---|
1349 | | - last = v4l2_m2m_last_dst_buf(inst->m2m_ctx); |
---|
1350 | | - if (last) |
---|
1351 | | - inst->last_buf = &last->vb2_buf; |
---|
| 1395 | + inst->next_buf_last = true; |
---|
1352 | 1396 | |
---|
1353 | 1397 | ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, false); |
---|
1354 | 1398 | if (ret) |
---|
1355 | 1399 | dev_dbg(dev, VDBGH "flush output error %d\n", ret); |
---|
1356 | 1400 | } |
---|
1357 | 1401 | |
---|
| 1402 | + inst->next_buf_last = true; |
---|
1358 | 1403 | inst->reconfig = true; |
---|
1359 | 1404 | v4l2_event_queue_fh(&inst->fh, &ev); |
---|
1360 | 1405 | wake_up(&inst->reconf_wait); |
---|
.. | .. |
---|
1397 | 1442 | |
---|
1398 | 1443 | static void vdec_flush_done(struct venus_inst *inst) |
---|
1399 | 1444 | { |
---|
1400 | | - if (inst->codec_state == VENUS_DEC_STATE_DRC) |
---|
1401 | | - inst->codec_state = VENUS_DEC_STATE_DRC_FLUSH_DONE; |
---|
| 1445 | + dev_dbg(inst->core->dev_dec, VDBGH "flush done\n"); |
---|
1402 | 1446 | } |
---|
1403 | 1447 | |
---|
1404 | 1448 | static const struct hfi_inst_ops vdec_hfi_ops = { |
---|