| .. | .. |
|---|
| 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 = { |
|---|