| @@ -40,6 +40,7 @@ typedef struct ProgressListener { · 39 unmodified lines |
| 40 | } ProgressListener; | 40 | } ProgressListener; |
| 41 | | 41 | |
| 42 | typedef enum VVCTaskStage { | 42 | typedef enum VVCTaskStage { |
| | 43 | VVC_TASK_STAGE_INIT, // for CTU(0, 0) only |
| 43 | VVC_TASK_STAGE_PARSE, | 44 | VVC_TASK_STAGE_PARSE, |
| 44 | VVC_TASK_STAGE_INTER, | 45 | VVC_TASK_STAGE_INTER, |
| 45 | VVC_TASK_STAGE_RECON, | 46 | VVC_TASK_STAGE_RECON, |
| @@ -175,10 +176,14 @@ static int task_has_target_score(VVCTask *t, const VVCTaskStage stage, const uin · 129 unmodified lines |
| 175 | uint8_t target = 0; | 176 | uint8_t target = 0; |
| 176 | VVCFrameContext *fc = t->fc; | 177 | VVCFrameContext *fc = t->fc; |
| 177 | | 178 | |
| | 179 | if (stage == VVC_TASK_STAGE_INIT) |
| | 180 | return 1; |
| | 181 | |
| 178 | if (stage == VVC_TASK_STAGE_PARSE) { | 182 | if (stage == VVC_TASK_STAGE_PARSE) { |
| 179 | const H266RawSPS *rsps = fc->ps.sps->r; | 183 | const H266RawSPS *rsps = fc->ps.sps->r; |
| 180 | const int wpp = rsps->sps_entropy_coding_sync_enabled_flag && !is_first_row(fc, t->rx, t->ry); | 184 | const int wpp = rsps->sps_entropy_coding_sync_enabled_flag && !is_first_row(fc, t->rx, t->ry); |
| 181 | target = 2 + wpp - 1; //left parse + colocation + wpp - no previous stage | 185 | const int no_prev_stage = t->rs > 0; |
| | 186 | target = 2 + wpp - no_prev_stage; //left parse + colocation + wpp - no_prev_stage |
| 182 | } else if (stage == VVC_TASK_STAGE_INTER) { | 187 | } else if (stage == VVC_TASK_STAGE_INTER) { |
| 183 | target = atomic_load(&t->target_inter_score); | 188 | target = atomic_load(&t->target_inter_score); |
| 184 | } else { | 189 | } else { |
| @@ -399,6 +404,55 @@ static int task_priority_higher(const AVTask *_a, const AVTask *_b) · 214 unmodified lines |
| 399 | return a->ry < b->ry; | 404 | return a->ry < b->ry; |
| 400 | } | 405 | } |
| 401 | | 406 | |
| | 407 | static void check_colocation(VVCContext *s, VVCTask *t) |
| | 408 | { |
| | 409 | const VVCFrameContext *fc = t->fc; |
| | 410 | |
| | 411 | if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag || fc->ps.sps->r->sps_sbtmvp_enabled_flag) { |
| | 412 | VVCFrame *col = fc->ref->collocated_ref; |
| | 413 | const int first_col = t->rx == fc->ps.pps->ctb_to_col_bd[t->rx]; |
| | 414 | if (col && first_col) { |
| | 415 | //we depend on bottom and right boundary, do not - 1 for y |
| | 416 | const int y = (t->ry << fc->ps.sps->ctb_log2_size_y); |
| | 417 | add_progress_listener(col, &t->col_listener, t, s, VVC_PROGRESS_MV, y); |
| | 418 | return; |
| | 419 | } |
| | 420 | } |
| | 421 | frame_thread_add_score(s, fc->ft, t->rx, t->ry, VVC_TASK_STAGE_PARSE); |
| | 422 | } |
| | 423 | |
| | 424 | static void submit_entry_point(VVCContext *s, VVCFrameThread *ft, SliceContext *sc, EntryPoint *ep) |
| | 425 | { |
| | 426 | const int rs = sc->sh.ctb_addr_in_curr_slice[ep->ctu_start]; |
| | 427 | VVCTask *t = ft->tasks + rs; |
| | 428 | |
| | 429 | frame_thread_add_score(s, ft, t->rx, t->ry, VVC_TASK_STAGE_PARSE); |
| | 430 | } |
| | 431 | |
| | 432 | static int run_init(VVCContext *s, VVCLocalContext *lc, VVCTask *t) |
| | 433 | { |
| | 434 | VVCFrameContext *fc = lc->fc; |
| | 435 | VVCFrameThread *ft = fc->ft; |
| | 436 | const int ret = ff_vvc_per_frame_init(fc); |
| | 437 | |
| | 438 | if (ret < 0) |
| | 439 | return ret; |
| | 440 | |
| | 441 | for (int i = 0; i < fc->nb_slices; i++) { |
| | 442 | SliceContext *sc = fc->slices[i]; |
| | 443 | for (int j = 0; j < sc->nb_eps; j++) { |
| | 444 | EntryPoint *ep = sc->eps + j; |
| | 445 | for (int k = ep->ctu_start; k < ep->ctu_end; k++) { |
| | 446 | const int rs = sc->sh.ctb_addr_in_curr_slice[k]; |
| | 447 | VVCTask *t = ft->tasks + rs; |
| | 448 | check_colocation(s, t); |
| | 449 | } |
| | 450 | submit_entry_point(s, ft, sc, ep); |
| | 451 | } |
| | 452 | } |
| | 453 | return 0; |
| | 454 | } |
| | 455 | |
| 402 | static void report_frame_progress(VVCFrameContext *fc, | 456 | static void report_frame_progress(VVCFrameContext *fc, |
| 403 | const int ry, const VVCProgress idx) | 457 | const int ry, const VVCProgress idx) |
| 404 | { | 458 | { |
| @@ -547,6 +601,7 @@ static int run_alf(VVCContext *s, VVCLocalContext *lc, VVCTask *t) · 142 unmodified lines |
| 547 | #define VVC_THREAD_DEBUG | 601 | #define VVC_THREAD_DEBUG |
| 548 | #ifdef VVC_THREAD_DEBUG | 602 | #ifdef VVC_THREAD_DEBUG |
| 549 | const static char* task_name[] = { | 603 | const static char* task_name[] = { |
| | 604 | "INIT", |
| 550 | "P", | 605 | "P", |
| 551 | "I", | 606 | "I", |
| 552 | "R", | 607 | "R", |
| @@ -567,6 +622,7 @@ static void task_run_stage(VVCTask *t, VVCContext *s, VVCLocalContext *lc) · 14 unmodified lines |
| 567 | VVCFrameThread *ft = fc->ft; | 622 | VVCFrameThread *ft = fc->ft; |
| 568 | const VVCTaskStage stage = t->stage; | 623 | const VVCTaskStage stage = t->stage; |
| 569 | static const run_func run[] = { | 624 | static const run_func run[] = { |
| | 625 | run_init, |
| 570 | run_parse, | 626 | run_parse, |
| 571 | run_inter, | 627 | run_inter, |
| 572 | run_recon, | 628 | run_recon, |
| @@ -726,7 +782,7 @@ int ff_vvc_frame_thread_init(VVCFrameContext *fc) · 153 unmodified lines |
| 726 | | 782 | |
| 727 | for (int rs = 0; rs < ft->ctu_count; rs++) { | 783 | for (int rs = 0; rs < ft->ctu_count; rs++) { |
| 728 | VVCTask *t = ft->tasks + rs; | 784 | VVCTask *t = ft->tasks + rs; |
| 729 | task_init(t, VVC_TASK_STAGE_PARSE, fc, rs % ft->ctu_width, rs / ft->ctu_width); | 785 | task_init(t, rs ? VVC_TASK_STAGE_PARSE : VVC_TASK_STAGE_INIT, fc, rs % ft->ctu_width, rs / ft->ctu_width); |
| 730 | } | 786 | } |
| 731 | | 787 | |
| 732 | memset(&ft->row_progress[0], 0, sizeof(ft->row_progress)); | 788 | memset(&ft->row_progress[0], 0, sizeof(ft->row_progress)); |
| @@ -745,59 +801,25 @@ fail: · 12 unmodified lines |
| 745 | return AVERROR(ENOMEM); | 801 | return AVERROR(ENOMEM); |
| 746 | } | 802 | } |
| 747 | | 803 | |
| 748 | static void check_colocation(VVCContext *s, VVCTask *t) | | |
| 749 | { | | |
| 750 | const VVCFrameContext *fc = t->fc; | | |
| 751 | | | |
| 752 | if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag || fc->ps.sps->r->sps_sbtmvp_enabled_flag) { | | |
| 753 | VVCFrame *col = fc->ref->collocated_ref; | | |
| 754 | const int first_col = t->rx == fc->ps.pps->ctb_to_col_bd[t->rx]; | | |
| 755 | if (col && first_col) { | | |
| 756 | //we depend on bottom and right boundary, do not - 1 for y | | |
| 757 | const int y = (t->ry << fc->ps.sps->ctb_log2_size_y); | | |
| 758 | add_progress_listener(col, &t->col_listener, t, s, VVC_PROGRESS_MV, y); | | |
| 759 | return; | | |
| 760 | } | | |
| 761 | } | | |
| 762 | frame_thread_add_score(s, fc->ft, t->rx, t->ry, VVC_TASK_STAGE_PARSE); | | |
| 763 | } | | |
| 764 | | | |
| 765 | static void submit_entry_point(VVCContext *s, VVCFrameThread *ft, SliceContext *sc, EntryPoint *ep) | | |
| 766 | { | | |
| 767 | const int rs = sc->sh.ctb_addr_in_curr_slice[ep->ctu_start]; | | |
| 768 | VVCTask *t = ft->tasks + rs; | | |
| 769 | | | |
| 770 | frame_thread_add_score(s, ft, t->rx, t->ry, VVC_TASK_STAGE_PARSE); | | |
| 771 | } | | |
| 772 | | | |
| 773 | int ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc) | 804 | int ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc) |
| 774 | { | 805 | { |
| 775 | VVCFrameThread *ft = fc->ft; | 806 | VVCFrameThread *ft = fc->ft; |
| 776 | | 807 | |
| 777 | // We'll handle this in two passes: | 808 | for (int i = 0; i < fc->nb_slices; i++) { |
| 778 | // Pass 0 to initialize tasks with parser, this will help detect bit stream error | 809 | SliceContext *sc = fc->slices[i]; |
| 779 | // Pass 1 to shedule location check and submit the entry point | 810 | for (int j = 0; j < sc->nb_eps; j++) { |
| 780 | for (int pass = 0; pass < 2; pass++) { | 811 | EntryPoint *ep = sc->eps + j; |
| 781 | for (int i = 0; i < fc->nb_slices; i++) { | 812 | for (int k = ep->ctu_start; k < ep->ctu_end; k++) { |
| 782 | SliceContext *sc = fc->slices[i]; | 813 | const int rs = sc->sh.ctb_addr_in_curr_slice[k]; |
| 783 | for (int j = 0; j < sc->nb_eps; j++) { | 814 | VVCTask *t = ft->tasks + rs; |
| 784 | EntryPoint *ep = sc->eps + j; | 815 | const int ret = task_init_parse(t, sc, ep, k); |
| 785 | for (int k = ep->ctu_start; k < ep->ctu_end; k++) { | 816 | if (ret < 0) |
| 786 | const int rs = sc->sh.ctb_addr_in_curr_slice[k]; | 817 | return ret; |
| 787 | VVCTask *t = ft->tasks + rs; | | |
| 788 | if (pass) { | | |
| 789 | check_colocation(s, t); | | |
| 790 | } else { | | |
| 791 | const int ret = task_init_parse(t, sc, ep, k); | | |
| 792 | if (ret < 0) | | |
| 793 | return ret; | | |
| 794 | } | | |
| 795 | } | | |
| 796 | if (pass) | | |
| 797 | submit_entry_point(s, ft, sc, ep); | | |
| 798 | } | 818 | } |
| 799 | } | 819 | } |
| 800 | } | 820 | } |
| | 821 | frame_thread_add_score(s, ft, 0, 0, VVC_TASK_STAGE_INIT); |
| | 822 | |
| 801 | return 0; | 823 | return 0; |
| 802 | } | 824 | } |
| 803 | | 825 | |