diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml new file mode 100644 index 0000000000..8d57dd882d --- /dev/null +++ b/.github/workflows/makefile.yml @@ -0,0 +1,107 @@ +name: test +run-name: ${{ github.workflow }} - ${{ github.sha }} +on: + push: + branches: [ main, up ] + pull_request: + branches: [ main, up ] + workflow_dispatch: + + +jobs: + ffvvc-test: + name: ffvvc-test / ${{ matrix.os.name }}/${{ matrix.compiler.name }}/${{ matrix.assembler.name }} + env: + configure_flags: --enable-ffmpeg --disable-everything --enable-decoder=vvc --enable-parser=vvc --enable-demuxer=vvc --enable-protocol=file,pipe --enable-encoder=rawvideo,wrapped_avframe --enable-muxer=rawvideo,md5,null + strategy: + fail-fast: false + matrix: + os: + - { name: linux, runner: ubuntu-latest, shell: bash, runner_threads: 4 } + - { name: windows, runner: windows-latest, shell: 'msys2 {0}', runner_threads: 1 } + compiler: + - { name: gcc, flags: --cc=gcc } + - { name: clang, flags: --cc=clang } + - { name: msvc, flags: --toolchain=msvc } + - { name: clang-usan, flags: '--toolchain=clang-usan --disable-optimizations' } + - { name: clang-asan, flags: '--toolchain=clang-asan --disable-optimizations' } + assembler: + - { name: no asm, flags: --disable-asm } + - { name: yasm, flags: --as=yasm } + - { name: nasm, flags: --as=nasm } + exclude: + # GitHub's Actions runners do not support AVX2. + - os: { name: linux, runner: ubuntu-latest, shell: bash, runner_threads: 4} + compiler: { name: msvc, flags: --toolchain=msvc } + - os: { name: linux, runner: ubuntu-latest, shell: bash, runner_threads: 4 } + assembler: { name: yasm, flags: --as=yasm } + - os: { name: linux, runner: ubuntu-latest, shell: bash, runner_threads: 4 } + assembler: { name: nasm, flags: --as=nasm } + # Address sanitizer cannot be run with handwritten assembly. + - compiler: { name: clang-asan, flags: '--toolchain=clang-asan --disable-optimizations' } + assembler: { name: nasm, flags: --as=nasm } + - compiler: { name: clang-asan, flags: '--toolchain=clang-asan --disable-optimizations' } + assembler: { name: yasm, flags: --as=yasm } + # Windows only supports MSVC. + - os: { name: windows, runner: windows-latest, shell: 'msys2 {0}', runner_threads: 1 } + compiler: { name: gcc, flags: --cc=gcc } + - os: { name: windows, runner: windows-latest, shell: 'msys2 {0}', runner_threads: 1 } + compiler: { name: clang, flags: --cc=clang } + - os: { name: windows, runner: windows-latest, shell: 'msys2 {0}', runner_threads: 1 } + compiler: { name: clang-usan, flags: '--toolchain=clang-usan --disable-optimizations' } + - os: { name: windows, runner: windows-latest, shell: 'msys2 {0}', runner_threads: 1 } + compiler: { name: clang-asan, flags: '--toolchain=clang-asan --disable-optimizations' } + + runs-on: ${{ matrix.os.runner }} + defaults: + run: + shell: ${{ matrix.os.shell }} + + steps: + - name: Get MSVC + if: ${{ matrix.compiler.name == 'msvc' && matrix.os.name == 'windows' }} + uses: ilammy/msvc-dev-cmd@v1 + + - name: Set up MSYS2 + if: ${{ matrix.os.shell == 'msys2 {0}' }} + uses: msys2/setup-msys2@v2 + with: + release: false + msystem: UCRT64 + path-type: inherit + install: >- + make + diffutils + + - name: Setup python package + run: python3 -m pip install tqdm pyyaml + + - name: Get assembler + if: ${{ matrix.os.shell == 'msys2 {0}' && matrix.assembler.name != 'no asm' }} + run: pacman --noconfirm -S ${{ matrix.assembler.name }} + + - name: Get source + uses: actions/checkout@v3 + with: + path: FFmpeg + + - name: Configure + run: cd FFmpeg && ./configure ${{ matrix.compiler.flags }} ${{ matrix.assembler.flags }} ${{ env.configure_flags }} || (tail ffbuild/config.log; false) + + - name: Build + run: cd FFmpeg && make -j8 + + - name: Get tests + uses: actions/checkout@v3 + with: + repository: ffvvc/tests + path: tests + + - name: Unit test + run: python3 tests/tools/ffmpeg.py --threads ${{ matrix.os.runner_threads }} --ffmpeg-path=./FFmpeg/ffmpeg tests/conformance/passed + + - name: Check ASM + run: cd FFmpeg && make checkasm -j && ./tests/checkasm/checkasm + + - name: Negative test + run: python3 tests/tools/ffmpeg.py --threads ${{ matrix.os.runner_threads }} --ffmpeg-path=./FFmpeg/ffmpeg tests/conformance/failed || true diff --git a/libavcodec/cbs_h266_syntax_template.c b/libavcodec/cbs_h266_syntax_template.c index 49fb12ba77..9fa7e0eec8 100644 --- a/libavcodec/cbs_h266_syntax_template.c +++ b/libavcodec/cbs_h266_syntax_template.c @@ -2118,9 +2118,12 @@ static int FUNC(pps) (CodedBitstreamContext *ctx, RWContext *rw, } else { if (current->pps_no_pic_partition_flag) infer(pps_num_slices_in_pic_minus1, 0); - else if (current->pps_single_slice_per_subpic_flag) + else if (current->pps_single_slice_per_subpic_flag) { + for (i = 0; i <= sps->sps_num_subpics_minus1; i++) + current->num_slices_in_subpic[i] = 1; infer(pps_num_slices_in_pic_minus1, sps->sps_num_subpics_minus1); + } // else? } if (!current->pps_rect_slice_flag || @@ -3219,19 +3222,27 @@ static int FUNC(slice_header) (CodedBitstreamContext *ctx, RWContext *rw, flag(sh_cabac_init_flag); else infer(sh_cabac_init_flag, 0); - if (ph->ph_temporal_mvp_enabled_flag && !pps->pps_rpl_info_in_ph_flag) { - if (current->sh_slice_type == VVC_SLICE_TYPE_B) - flag(sh_collocated_from_l0_flag); - else - infer(sh_collocated_from_l0_flag, 1); - if ((current->sh_collocated_from_l0_flag && - current->num_ref_idx_active[0] > 1) || - (!current->sh_collocated_from_l0_flag && - current->num_ref_idx_active[1] > 1)) { - unsigned int idx = current->sh_collocated_from_l0_flag ? 0 : 1; - ue(sh_collocated_ref_idx, 0, current->num_ref_idx_active[idx] - 1); + if (ph->ph_temporal_mvp_enabled_flag) { + if (!pps->pps_rpl_info_in_ph_flag) { + if (current->sh_slice_type == VVC_SLICE_TYPE_B) + flag(sh_collocated_from_l0_flag); + else + infer(sh_collocated_from_l0_flag, 1); + if ((current->sh_collocated_from_l0_flag && + current->num_ref_idx_active[0] > 1) || + (!current->sh_collocated_from_l0_flag && + current->num_ref_idx_active[1] > 1)) { + unsigned int idx = current->sh_collocated_from_l0_flag ? 0 : 1; + ue(sh_collocated_ref_idx, 0, current->num_ref_idx_active[idx] - 1); + } else { + infer(sh_collocated_ref_idx, 0); + } } else { - infer(sh_collocated_ref_idx, 0); + if (current->sh_slice_type == VVC_SLICE_TYPE_B) + infer(sh_collocated_from_l0_flag, ph->ph_collocated_from_l0_flag); + else + infer(sh_collocated_from_l0_flag, 1); + infer(sh_collocated_ref_idx, ph->ph_collocated_ref_idx); } } if (!pps->pps_wp_info_in_ph_flag && diff --git a/libavcodec/vvc/vvc_ctu.c b/libavcodec/vvc/vvc_ctu.c index 75b9e73ae3..519bd1ba76 100644 --- a/libavcodec/vvc/vvc_ctu.c +++ b/libavcodec/vvc/vvc_ctu.c @@ -87,10 +87,10 @@ static int get_qp_y_pred(const VVCLocalContext *lc) const int min_cb_width = fc->ps.pps->min_cb_width; const int x_cb = cu->x0 >> sps->min_cb_log2_size_y; const int y_cb = cu->y0 >> sps->min_cb_log2_size_y; - const int x_ctb = cu->x0 >> ctb_log2_size; - const int y_ctb = cu->y0 >> ctb_log2_size; - const int in_same_ctb_a = ((xQg - 1) >> ctb_log2_size) == x_ctb && (yQg >> ctb_log2_size) == y_ctb; - const int in_same_ctb_b = (xQg >> ctb_log2_size) == x_ctb && ((yQg - 1) >> ctb_log2_size) == y_ctb; + const int rx = cu->x0 >> ctb_log2_size; + const int ry = cu->y0 >> ctb_log2_size; + const int in_same_ctb_a = ((xQg - 1) >> ctb_log2_size) == rx && (yQg >> ctb_log2_size) == ry; + const int in_same_ctb_b = (xQg >> ctb_log2_size) == rx && ((yQg - 1) >> ctb_log2_size) == ry; int qPy_pred, qPy_a, qPy_b; if (lc->na.cand_up) { @@ -2493,6 +2493,10 @@ void ff_vvc_decode_neighbour(VVCLocalContext *lc, const int x_ctb, const int y_c lc->boundary_flags |= BOUNDARY_UPPER_TILE; if (ry > 0 && fc->tab.slice_idx[rs] != fc->tab.slice_idx[rs - fc->ps.pps->ctb_width]) lc->boundary_flags |= BOUNDARY_UPPER_SLICE; + if (fc->ps.sps->r->sps_subpic_ctu_top_left_x[lc->sc->sh.r->curr_subpic_idx] == rx) + lc->boundary_flags |= BOUNDARY_LEFT_SUBPIC; + if (fc->ps.sps->r->sps_subpic_ctu_top_left_y[lc->sc->sh.r->curr_subpic_idx] == ry) + lc->boundary_flags |= BOUNDARY_UPPER_SUBPIC; lc->ctb_left_flag = rx > 0 && !(lc->boundary_flags & BOUNDARY_LEFT_TILE); lc->ctb_up_flag = ry > 0 && !(lc->boundary_flags & BOUNDARY_UPPER_TILE) && !(lc->boundary_flags & BOUNDARY_UPPER_SLICE); lc->ctb_up_right_flag = lc->ctb_up_flag && (fc->ps.pps->ctb_to_col_bd[rx] == fc->ps.pps->ctb_to_col_bd[rx + 1]) && diff --git a/libavcodec/vvc/vvc_ctu.h b/libavcodec/vvc/vvc_ctu.h index 8020e184c5..460dbdba59 100644 --- a/libavcodec/vvc/vvc_ctu.h +++ b/libavcodec/vvc/vvc_ctu.h @@ -421,8 +421,10 @@ typedef struct VVCLocalContext { #define BOUNDARY_LEFT_SLICE (1 << 0) #define BOUNDARY_LEFT_TILE (1 << 1) -#define BOUNDARY_UPPER_SLICE (1 << 2) -#define BOUNDARY_UPPER_TILE (1 << 3) +#define BOUNDARY_LEFT_SUBPIC (1 << 2) +#define BOUNDARY_UPPER_SLICE (1 << 3) +#define BOUNDARY_UPPER_TILE (1 << 4) +#define BOUNDARY_UPPER_SUBPIC (1 << 5) /* properties of the boundary of the current CTB for the purposes * of the deblocking filter */ int boundary_flags; diff --git a/libavcodec/vvc/vvc_filter.c b/libavcodec/vvc/vvc_filter.c index dded447bfa..de0816619b 100644 --- a/libavcodec/vvc/vvc_filter.c +++ b/libavcodec/vvc/vvc_filter.c @@ -99,7 +99,7 @@ static void copy_vert(uint8_t *dst, const uint8_t *src, const int pixel_shift, c static void copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const ptrdiff_t src_stride, const int x, const int y, const int width, const int height, - const int c_idx, const int x_ctb, const int y_ctb, const int top) + const int c_idx, const int rx, const int ry, const int top) { const int ps = fc->ps.sps->pixel_shift; const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx]; @@ -107,16 +107,16 @@ static void copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, if (top) { /* top */ - memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb) * w + x) << ps), + memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry) * w + x) << ps), src, width << ps); } else { /* bottom */ - memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 1) * w + x) << ps), + memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry + 1) * w + x) << ps), src + src_stride * (height - 1), width << ps); /* copy vertical edges */ - copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb) * h + y) << ps), src, ps, height, 1 << ps, src_stride); - copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << ps), src + ((width - 1) << ps), ps, height, 1 << ps, src_stride); + copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx) * h + y) << ps), src, ps, height, 1 << ps, src_stride); + copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx + 1) * h + y) << ps), src + ((width - 1) << ps), ps, height, 1 << ps, src_stride); } } @@ -157,56 +157,62 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y) const int ctb_size_y = fc->ps.sps->ctb_size_y; static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8 }; int c_idx; - int edges[4]; // 0 left 1 top 2 right 3 bottom - const int x_ctb = x >> fc->ps.sps->ctb_log2_size_y; - const int y_ctb = y >> fc->ps.sps->ctb_log2_size_y; - const SAOParams *sao = &CTB(fc->tab.sao, x_ctb, y_ctb); + const int rx = x >> fc->ps.sps->ctb_log2_size_y; + const int ry = y >> fc->ps.sps->ctb_log2_size_y; + int edges[4] = { !rx, !ry, rx == fc->ps.pps->ctb_width - 1, ry == fc->ps.pps->ctb_height - 1 }; + const SAOParams *sao = &CTB(fc->tab.sao, rx, ry); // flags indicating unfilterable edges uint8_t vert_edge[] = { 0, 0 }; uint8_t horiz_edge[] = { 0, 0 }; uint8_t diag_edge[] = { 0, 0, 0, 0 }; + uint8_t tile_edge[] = { 0, 0, 0, 0 }; + uint8_t subpic_edge[] = { 0, 0, 0, 0 }; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; const uint8_t lfase = fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag; const uint8_t no_tile_filter = fc->ps.pps->r->num_tiles_in_pic > 1 && !fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag; - const uint8_t restore = no_tile_filter || !lfase; - uint8_t left_tile_edge = 0; - uint8_t right_tile_edge = 0; - uint8_t up_tile_edge = 0; - uint8_t bottom_tile_edge = 0; - - edges[LEFT] = x_ctb == 0; - edges[TOP] = y_ctb == 0; - edges[RIGHT] = x_ctb == fc->ps.pps->ctb_width - 1; - edges[BOTTOM] = y_ctb == fc->ps.pps->ctb_height - 1; + const uint8_t no_subpic_filter = fc->ps.sps->r->sps_num_subpics_minus1 && + !fc->ps.sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx]; + const uint8_t restore = no_subpic_filter || no_tile_filter || !lfase; if (restore) { if (!edges[LEFT]) { - left_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_col_bd[x_ctb] == x_ctb; - vert_edge[0] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb - 1, y_ctb)) || left_tile_edge; + tile_edge[LEFT] = no_tile_filter && fc->ps.pps->ctb_to_col_bd[rx] == rx; + subpic_edge[LEFT] = no_subpic_filter && fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] == rx; + vert_edge[0] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx - 1, ry)) || tile_edge[LEFT] || subpic_edge[LEFT]; } if (!edges[RIGHT]) { - right_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_col_bd[x_ctb] != fc->ps.pps->ctb_to_col_bd[x_ctb + 1]; - vert_edge[1] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb)) || right_tile_edge; + tile_edge[RIGHT] = no_tile_filter && fc->ps.pps->ctb_to_col_bd[rx] != fc->ps.pps->ctb_to_col_bd[rx + 1]; + subpic_edge[RIGHT] = no_subpic_filter && + fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] + fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx; + vert_edge[1] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry)) || tile_edge[RIGHT] || subpic_edge[RIGHT]; } if (!edges[TOP]) { - up_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_row_bd[y_ctb] == y_ctb; - horiz_edge[0] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb, y_ctb - 1)) || up_tile_edge; + tile_edge[TOP] = no_tile_filter && fc->ps.pps->ctb_to_row_bd[ry] == ry; + subpic_edge[TOP] = no_subpic_filter && fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] == ry; + horiz_edge[0] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx, ry - 1)) || tile_edge[TOP] || subpic_edge[TOP]; } if (!edges[BOTTOM]) { - bottom_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_row_bd[y_ctb] != fc->ps.pps->ctb_to_row_bd[y_ctb + 1]; - horiz_edge[1] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb, y_ctb + 1)) || bottom_tile_edge; + tile_edge[BOTTOM] = no_tile_filter && fc->ps.pps->ctb_to_row_bd[ry] != fc->ps.pps->ctb_to_row_bd[ry + 1]; + subpic_edge[BOTTOM] = no_subpic_filter && + fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] + fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry; + horiz_edge[1] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx, ry + 1)) || tile_edge[BOTTOM] || subpic_edge[BOTTOM]; } if (!edges[LEFT] && !edges[TOP]) { - diag_edge[0] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb - 1, y_ctb - 1)) || left_tile_edge || up_tile_edge; + diag_edge[0] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx - 1, ry - 1)) || + tile_edge[LEFT] || tile_edge[TOP] || subpic_edge[LEFT] || subpic_edge[TOP]; } if (!edges[TOP] && !edges[RIGHT]) { - diag_edge[1] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb - 1)) || right_tile_edge || up_tile_edge; + diag_edge[1] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry - 1)) || + tile_edge[RIGHT] || tile_edge[TOP] || subpic_edge[TOP] || subpic_edge[RIGHT]; } if (!edges[RIGHT] && !edges[BOTTOM]) { - diag_edge[2] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb + 1)) || right_tile_edge || bottom_tile_edge; + diag_edge[2] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry + 1)) || + tile_edge[RIGHT] || tile_edge[BOTTOM] || subpic_edge[RIGHT] || subpic_edge[BOTTOM]; } if (!edges[LEFT] && !edges[BOTTOM]) { - diag_edge[3] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb - 1, y_ctb + 1)) || left_tile_edge || bottom_tile_edge; + diag_edge[3] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx - 1, ry + 1)) || + tile_edge[LEFT] || tile_edge[BOTTOM] || subpic_edge[LEFT] || subpic_edge[BOTTOM]; } } @@ -245,7 +251,7 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y) int pos = 0; dst1 = dst - dst_stride - (left << sh); - src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb - 1) * w + x0 - left) << sh); + src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry - 1) * w + x0 - left) << sh); if (left) { copy_pixel(dst1, src1, sh); pos += (1 << sh); @@ -264,7 +270,7 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y) int pos = 0; dst1 = dst + height * dst_stride - (left << sh); - src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 2) * w + x0 - left) << sh); + src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry + 2) * w + x0 - left) << sh); if (left) { copy_pixel(dst1, src1, sh); pos += (1 << sh); @@ -277,12 +283,12 @@ void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y) } if (!edges[LEFT]) { copy_vert(dst - (1 << sh), - fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb - 1) * h + y0) << sh), + fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx - 1) * h + y0) << sh), sh, height, dst_stride, 1 << sh); } if (!edges[RIGHT]) { copy_vert(dst + (width << sh), - fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 2) * h + y0) << sh), + fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx + 2) * h + y0) << sh), sh, height, dst_stride, 1 << sh); } @@ -528,8 +534,39 @@ static av_always_inline int deblock_bs(const VVCLocalContext *lc, return boundary_strength(lc, mvf_q, mvf_p, rpl_p); } +static int deblock_is_boundary(const VVCLocalContext *lc, const int boundary, + const int pos, const int rs, const int vertical) +{ + const VVCFrameContext *fc = lc->fc; + const H266RawSPS *rsps = fc->ps.sps->r; + const H266RawPPS *rpps = fc->ps.pps->r; + int flag; + if (boundary && (pos % fc->ps.sps->ctb_size_y) == 0) { + flag = vertical ? BOUNDARY_LEFT_SLICE : BOUNDARY_UPPER_SLICE; + if (lc->boundary_flags & flag && + !rpps->pps_loop_filter_across_slices_enabled_flag) + return 0; + + flag = vertical ? BOUNDARY_LEFT_TILE : BOUNDARY_UPPER_TILE; + if (lc->boundary_flags & flag && + !rpps->pps_loop_filter_across_tiles_enabled_flag) + return 0; + + flag = vertical ? BOUNDARY_LEFT_SUBPIC : BOUNDARY_UPPER_SUBPIC; + if (lc->boundary_flags & flag) { + const int q_rs = rs - (vertical ? 1 : fc->ps.pps->ctb_width); + const SliceContext *q_slice = lc->fc->slices[lc->fc->tab.slice_idx[q_rs]]; + + if (!rsps->sps_loop_filter_across_subpic_enabled_flag[q_slice->sh.r->curr_subpic_idx] || + !rsps->sps_loop_filter_across_subpic_enabled_flag[lc->sc->sh.r->curr_subpic_idx]) + return 0; + } + } + return boundary; +} + static void vvc_deblock_bs_luma_vertical(const VVCLocalContext *lc, - const int x0, const int y0, const int width, const int height) + const int x0, const int y0, const int width, const int height, const int rs) { const VVCFrameContext *fc = lc->fc; const MvField *tab_mvf = fc->tab.mvf; @@ -554,15 +591,7 @@ static void vvc_deblock_bs_luma_vertical(const VVCLocalContext *lc, } // bs for vertical TU boundaries - boundary_left = x0 > 0 && !(x0 & 3); - if (boundary_left && - ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag && - lc->boundary_flags & BOUNDARY_LEFT_SLICE && - (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) || - (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag && - lc->boundary_flags & BOUNDARY_LEFT_TILE && - (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0))) - boundary_left = 0; + boundary_left = deblock_is_boundary(lc, x0 > 0 && !(x0 & 3), x0, rs, 1); if (boundary_left) { const RefPicList *rpl_left = @@ -586,7 +615,7 @@ static void vvc_deblock_bs_luma_vertical(const VVCLocalContext *lc, } static void vvc_deblock_bs_luma_horizontal(const VVCLocalContext *lc, - const int x0, const int y0, const int width, const int height) + const int x0, const int y0, const int width, const int height, const int rs) { const VVCFrameContext *fc = lc->fc; const MvField *tab_mvf = fc->tab.mvf; @@ -610,15 +639,7 @@ static void vvc_deblock_bs_luma_horizontal(const VVCLocalContext *lc, has_horizontal_sb = cb_height > 8; } - boundary_upper = y0 > 0 && !(y0 & 3); - if (boundary_upper && - ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag && - lc->boundary_flags & BOUNDARY_UPPER_SLICE && - (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) || - (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag && - lc->boundary_flags & BOUNDARY_UPPER_TILE && - (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0))) - boundary_upper = 0; + boundary_upper = deblock_is_boundary(lc, y0 > 0 && !(y0 & 3), y0, rs, 0); if (boundary_upper) { const RefPicList *rpl_top = @@ -643,21 +664,11 @@ static void vvc_deblock_bs_luma_horizontal(const VVCLocalContext *lc, } static void vvc_deblock_bs_chroma_vertical(const VVCLocalContext *lc, - const int x0, const int y0, const int width, const int height) + const int x0, const int y0, const int width, const int height, const int rs) { const VVCFrameContext *fc = lc->fc; - int boundary_left; - - // bs for vertical TU boundaries - boundary_left = x0 > 0 && !(x0 & ((CHROMA_GRID << fc->ps.sps->hshift[1]) - 1)); - if (boundary_left && - ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag && - lc->boundary_flags & BOUNDARY_LEFT_SLICE && - (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) || - (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag && - lc->boundary_flags & BOUNDARY_LEFT_TILE && - (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0))) - boundary_left = 0; + const int boundary_left = deblock_is_boundary(lc, + x0 > 0 && !(x0 & ((CHROMA_GRID << fc->ps.sps->hshift[CHROMA]) - 1)), x0, rs, 1); if (boundary_left) { for (int i = 0; i < height; i += 2) { @@ -671,20 +682,11 @@ static void vvc_deblock_bs_chroma_vertical(const VVCLocalContext *lc, } static void vvc_deblock_bs_chroma_horizontal(const VVCLocalContext *lc, - const int x0, const int y0, const int width, const int height) + const int x0, const int y0, const int width, const int height, const int rs) { const VVCFrameContext *fc = lc->fc; - int boundary_upper; - - boundary_upper = y0 > 0 && !(y0 & ((CHROMA_GRID << fc->ps.sps->vshift[1]) - 1)); - if (boundary_upper && - ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag && - lc->boundary_flags & BOUNDARY_UPPER_SLICE && - (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) || - (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag && - lc->boundary_flags & BOUNDARY_UPPER_TILE && - (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0))) - boundary_upper = 0; + const int boundary_upper = deblock_is_boundary(lc, + y0 > 0 && !(y0 & ((CHROMA_GRID << fc->ps.sps->vshift[CHROMA]) - 1)), y0, rs, 0); if (boundary_upper) { for (int i = 0; i < width; i += 2) { @@ -698,9 +700,9 @@ static void vvc_deblock_bs_chroma_horizontal(const VVCLocalContext *lc, } typedef void (*deblock_bs_fn)(const VVCLocalContext *lc, const int x0, const int y0, - const int width, const int height); + const int width, const int height, const int rs); -static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int y0, const int vertical) +static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int y0, const int rs, const int vertical) { const VVCFrameContext *fc = lc->fc; const VVCSPS *sps = fc->ps.sps; @@ -721,7 +723,7 @@ static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int y0 const int off = y * fc->ps.pps->min_tu_width + x; if ((fc->tab.tb_pos_x0[is_chroma][off] >> MIN_TU_LOG2) == x && (fc->tab.tb_pos_y0[is_chroma][off] >> MIN_TU_LOG2) == y) { deblock_bs[vertical][is_chroma](lc, x << MIN_TU_LOG2, y << MIN_TU_LOG2, - fc->tab.tb_width[is_chroma][off] << hs, fc->tab.tb_height[is_chroma][off] << vs); + fc->tab.tb_width[is_chroma][off] << hs, fc->tab.tb_height[is_chroma][off] << vs, rs); } } } @@ -805,7 +807,7 @@ static int get_qp(const VVCFrameContext *fc, const uint8_t *src, const int x, co return get_qp_c(fc, x, y, c_idx, vertical); } -void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0) +void ff_vvc_deblock_vertical(const VVCLocalContext *lc, const int x0, const int y0, const int rs) { VVCFrameContext *fc = lc->fc; const VVCSPS *sps = fc->ps.sps; @@ -820,11 +822,9 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0) const int ctb_log2_size_y = fc->ps.sps->ctb_log2_size_y; int x_end, y_end; const int ctb_size = 1 << ctb_log2_size_y; - const int ctb = (x0 >> ctb_log2_size_y) + - (y0 >> ctb_log2_size_y) * fc->ps.pps->ctb_width; - const DBParams *params = fc->tab.deblock + ctb; + const DBParams *params = fc->tab.deblock + rs; - vvc_deblock_bs(lc, x0, y0, 1); + vvc_deblock_bs(lc, x0, y0, rs, 1); x_end = x0 + ctb_size; if (x_end > fc->ps.pps->width) @@ -875,7 +875,7 @@ void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0) } } -void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0) +void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, const int x0, const int y0, const int rs) { VVCFrameContext *fc = lc->fc; const VVCSPS *sps = fc->ps.sps; @@ -890,11 +890,9 @@ void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0) const int ctb_log2_size_y = fc->ps.sps->ctb_log2_size_y; int x_end, y_end; const int ctb_size = 1 << ctb_log2_size_y; - const int ctb = (x0 >> ctb_log2_size_y) + - (y0 >> ctb_log2_size_y) * fc->ps.pps->ctb_width; - const DBParams *params = fc->tab.deblock + ctb; + const DBParams *params = fc->tab.deblock + rs; - vvc_deblock_bs(lc, x0, y0, 0); + vvc_deblock_bs(lc, x0, y0, rs, 0); x_end = x0 + ctb_size; if (x_end > fc->ps.pps->width) @@ -994,7 +992,7 @@ static void alf_extend_horz(uint8_t *dst, const uint8_t *src, } static void alf_copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const ptrdiff_t src_stride, - const int x, const int y, const int width, const int height, const int x_ctb, const int y_ctb, const int c_idx) + const int x, const int y, const int width, const int height, const int rx, const int ry, const int c_idx) { const int ps = fc->ps.sps->pixel_shift; const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx]; @@ -1005,12 +1003,12 @@ static void alf_copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const pt /* copy horizontal edges */ for (int i = 0; i < FF_ARRAY_ELEMS(offset_h); i++) { - alf_copy_border(fc->tab.alf_pixel_buffer_h[c_idx][i] + ((border_pixels * y_ctb * w + x)<< ps), + alf_copy_border(fc->tab.alf_pixel_buffer_h[c_idx][i] + ((border_pixels * ry * w + x)<< ps), src + offset_h[i] * src_stride, ps, width, border_pixels, w << ps, src_stride); } /* copy vertical edges */ for (int i = 0; i < FF_ARRAY_ELEMS(offset_v); i++) { - alf_copy_border(fc->tab.alf_pixel_buffer_v[c_idx][i] + ((h * x_ctb + y) * (border_pixels << ps)), + alf_copy_border(fc->tab.alf_pixel_buffer_v[c_idx][i] + ((h * rx + y) * (border_pixels << ps)), src + (offset_v[i] << ps), ps, border_pixels, height, border_pixels << ps, src_stride); } } @@ -1050,7 +1048,7 @@ static void alf_fill_border_v(uint8_t *dst, const ptrdiff_t dst_stride, const ui } static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t *_src, const int x, const int y, - const int x_ctb, const int y_ctb, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride, + const int rx, const int ry, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx, const int *edges) { const int ps = fc->ps.sps->pixel_shift; @@ -1062,23 +1060,23 @@ static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t copy_ctb(_dst, _src, width << ps, height, dst_stride, src_stride); //top - src = fc->tab.alf_pixel_buffer_h[c_idx][1] + (((border_pixels * w) << ps) * (y_ctb - 1) + (x << ps)); + src = fc->tab.alf_pixel_buffer_h[c_idx][1] + (((border_pixels * w) << ps) * (ry - 1) + (x << ps)); dst = _dst - border_pixels * dst_stride; alf_fill_border_h(dst, dst_stride, src, w << ps, _dst, width, border_pixels, ps, edges[TOP]); //bottom - src = fc->tab.alf_pixel_buffer_h[c_idx][0] + (((border_pixels * w) << ps) * (y_ctb + 1) + (x << ps)); + src = fc->tab.alf_pixel_buffer_h[c_idx][0] + (((border_pixels * w) << ps) * (ry + 1) + (x << ps)); dst = _dst + height * dst_stride; alf_fill_border_h(dst, dst_stride, src, w << ps, _dst + (height - 1) * dst_stride, width, border_pixels, ps, edges[BOTTOM]); //left - src = fc->tab.alf_pixel_buffer_v[c_idx][1] + (h * (x_ctb - 1) + y - border_pixels) * (border_pixels << ps); + src = fc->tab.alf_pixel_buffer_v[c_idx][1] + (h * (rx - 1) + y - border_pixels) * (border_pixels << ps); dst = _dst - (border_pixels << ps) - border_pixels * dst_stride; alf_fill_border_v(dst, dst_stride, src, dst + (border_pixels << ps), border_pixels, height, ps, edges, edges[LEFT]); //right - src = fc->tab.alf_pixel_buffer_v[c_idx][0] + (h * (x_ctb + 1) + y - border_pixels) * (border_pixels << ps); + src = fc->tab.alf_pixel_buffer_v[c_idx][0] + (h * (rx + 1) + y - border_pixels) * (border_pixels << ps); dst = _dst + (width << ps) - border_pixels * dst_stride; alf_fill_border_v(dst, dst_stride, src, dst - (1 << ps), border_pixels, height, ps, edges, edges[RIGHT]); } @@ -1177,8 +1175,8 @@ static void alf_filter_cc(VVCLocalContext *lc, uint8_t *dst, const uint8_t *luma void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const int x0, const int y0) { VVCFrameContext *fc = lc->fc; - const int x_ctb = x0 >> fc->ps.sps->ctb_log2_size_y; - const int y_ctb = y0 >> fc->ps.sps->ctb_log2_size_y; + const int rx = x0 >> fc->ps.sps->ctb_log2_size_y; + const int ry = y0 >> fc->ps.sps->ctb_log2_size_y; const int ctb_size_y = fc->ps.sps->ctb_size_y; const int ps = fc->ps.sps->pixel_shift; const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1; @@ -1194,36 +1192,45 @@ void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const int x0, const int y0) const int src_stride = fc->frame->linesize[c_idx]; uint8_t* src = &fc->frame->data[c_idx][y * src_stride + (x << ps)]; - alf_copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, x_ctb, y_ctb, c_idx); + alf_copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, rx, ry, c_idx); } } void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0) { VVCFrameContext *fc = lc->fc; + const VVCSPS *sps = fc->ps.sps; const VVCPPS *pps = fc->ps.pps; - const int x_ctb = x0 >> fc->ps.sps->ctb_log2_size_y; - const int y_ctb = y0 >> fc->ps.sps->ctb_log2_size_y; + const int rx = x0 >> fc->ps.sps->ctb_log2_size_y; + const int ry = y0 >> fc->ps.sps->ctb_log2_size_y; const int ctb_size_y = fc->ps.sps->ctb_size_y; const int ps = fc->ps.sps->pixel_shift; const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps; const int padded_offset = padded_stride * ALF_PADDING_SIZE + (ALF_PADDING_SIZE << ps); const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1; - ALFParams *alf = &CTB(fc->tab.alf, x_ctb, y_ctb); - int edges[MAX_EDGES] = { x_ctb == 0, y_ctb == 0, x_ctb == pps->ctb_width - 1, y_ctb == pps->ctb_height - 1 }; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; + ALFParams *alf = &CTB(fc->tab.alf, rx, ry); + int edges[MAX_EDGES] = { rx == 0, ry == 0, rx == pps->ctb_width - 1, ry == pps->ctb_height - 1 }; if (!pps->r->pps_loop_filter_across_tiles_enabled_flag) { edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_TILE); edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_TILE); - edges[RIGHT] = edges[RIGHT] || pps->ctb_to_col_bd[x_ctb] != pps->ctb_to_col_bd[x_ctb + 1]; - edges[BOTTOM] = edges[BOTTOM] || pps->ctb_to_row_bd[y_ctb] != pps->ctb_to_row_bd[y_ctb + 1]; + edges[RIGHT] = edges[RIGHT] || pps->ctb_to_col_bd[rx] != pps->ctb_to_col_bd[rx + 1]; + edges[BOTTOM] = edges[BOTTOM] || pps->ctb_to_row_bd[ry] != pps->ctb_to_row_bd[ry + 1]; } if (!pps->r->pps_loop_filter_across_slices_enabled_flag) { edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_SLICE); edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_SLICE); - edges[RIGHT] = edges[RIGHT] || CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb); - edges[BOTTOM] = edges[BOTTOM] || CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb, y_ctb + 1); + edges[RIGHT] = edges[RIGHT] || CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry); + edges[BOTTOM] = edges[BOTTOM] || CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx, ry + 1); + } + + if (!sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx]) { + edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_SUBPIC); + edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_SUBPIC); + edges[RIGHT] = edges[RIGHT] || fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] + fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx; + edges[BOTTOM] = edges[BOTTOM] || fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] + fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry; } for (int c_idx = 0; c_idx < c_end; c_idx++) { @@ -1243,7 +1250,7 @@ void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0) if (alf->ctb_flag[c_idx] || (!c_idx && (alf->ctb_cc_idc[0] || alf->ctb_cc_idc[1]))) { padded = (c_idx ? lc->alf_buffer_chroma : lc->alf_buffer_luma) + padded_offset; - alf_prepare_buffer(fc, padded, src, x, y, x_ctb, y_ctb, width, height, + alf_prepare_buffer(fc, padded, src, x, y, rx, ry, width, height, padded_stride, src_stride, c_idx, edges); } if (alf->ctb_flag[c_idx]) { diff --git a/libavcodec/vvc/vvc_filter.h b/libavcodec/vvc/vvc_filter.h index 2ae4c33e2d..9597437d83 100644 --- a/libavcodec/vvc/vvc_filter.h +++ b/libavcodec/vvc/vvc_filter.h @@ -38,16 +38,18 @@ void ff_vvc_lmcs_filter(const VVCLocalContext *lc, const int x0, const int y0); * @param lc local context for CTU * @param x0 x position for the CTU * @param y0 y position for the CTU + * @param rs raster position for the CTU */ -void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0); +void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0, int rs); /** * horizontal deblock filter for the CTU * @param lc local context for CTU * @param x0 x position for the CTU * @param y0 y position for the CTU + * @param rs raster position for the CTU */ -void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0); +void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0, int rs); /** * sao filter for the CTU diff --git a/libavcodec/vvc/vvc_inter.c b/libavcodec/vvc/vvc_inter.c index c5629f7f6f..1a87cb71cf 100644 --- a/libavcodec/vvc/vvc_inter.c +++ b/libavcodec/vvc/vvc_inter.c @@ -30,14 +30,34 @@ #define PROF_TEMP_OFFSET (MAX_PB_SIZE + 32) static const int bcw_w_lut[] = {4, 5, 3, 10, -2}; -static int emulated_edge(const VVCFrameContext *fc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, - const int x_off, const int y_off, const int block_w, const int block_h, const int is_luma) +static void subpic_offset(int *x_off, int *y_off, + const VVCSPS *sps, const VVCPPS *pps, const int subpic_idx, const int is_luma) { - const int extra_before = is_luma ? LUMA_EXTRA_BEFORE : CHROMA_EXTRA_BEFORE; - const int extra_after = is_luma ? LUMA_EXTRA_AFTER : CHROMA_EXTRA_AFTER; - const int extra = is_luma ? LUMA_EXTRA : CHROMA_EXTRA; - const int pic_width = is_luma ? fc->ps.pps->width : (fc->ps.pps->width >> fc->ps.sps->hshift[1]); - const int pic_height = is_luma ? fc->ps.pps->height : (fc->ps.pps->height >> fc->ps.sps->vshift[1]); + *x_off -= pps->subpic_x[subpic_idx] >> sps->hshift[!is_luma]; + *y_off -= pps->subpic_y[subpic_idx] >> sps->vshift[!is_luma]; +} + +static void subpic_width_height(int *pic_width, int *pic_height, + const VVCSPS *sps, const VVCPPS *pps, const int subpic_idx, const int is_luma) +{ + *pic_width = pps->subpic_width[subpic_idx] >> sps->hshift[!is_luma]; + *pic_height = pps->subpic_height[subpic_idx] >> sps->vshift[!is_luma]; +} + +static int emulated_edge(const VVCLocalContext *lc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, + int x_off, int y_off, const int block_w, const int block_h, const int is_luma) +{ + const VVCFrameContext *fc = lc->fc; + const VVCSPS *sps = fc->ps.sps; + const VVCPPS *pps = fc->ps.pps; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; + const int extra_before = is_luma ? LUMA_EXTRA_BEFORE : CHROMA_EXTRA_BEFORE; + const int extra_after = is_luma ? LUMA_EXTRA_AFTER : CHROMA_EXTRA_AFTER; + const int extra = is_luma ? LUMA_EXTRA : CHROMA_EXTRA; + int pic_width, pic_height; + + subpic_offset(&x_off, &y_off, sps, pps, subpic_idx, is_luma); + subpic_width_height(&pic_width, &pic_height, sps, pps, subpic_idx, is_luma); if (x_off < extra_before || y_off < extra_before || x_off >= pic_width - block_w - extra_after || @@ -57,14 +77,21 @@ static int emulated_edge(const VVCFrameContext *fc, uint8_t *dst, const uint8_t return 0; } -static void emulated_edge_dmvr(const VVCFrameContext *fc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, - const int x_sb, const int y_sb, const int x_off, const int y_off, const int block_w, const int block_h, const int is_luma) +static void emulated_edge_dmvr(const VVCLocalContext *lc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, + int x_sb, int y_sb, int x_off, int y_off, const int block_w, const int block_h, const int is_luma) { - const int extra_before = is_luma ? LUMA_EXTRA_BEFORE : CHROMA_EXTRA_BEFORE; - const int extra_after = is_luma ? LUMA_EXTRA_AFTER : CHROMA_EXTRA_AFTER; - const int extra = is_luma ? LUMA_EXTRA : CHROMA_EXTRA; - const int pic_width = is_luma ? fc->ps.pps->width : (fc->ps.pps->width >> fc->ps.sps->hshift[1]); - const int pic_height = is_luma ? fc->ps.pps->height : (fc->ps.pps->height >> fc->ps.sps->vshift[1]); + const VVCFrameContext *fc = lc->fc; + const VVCSPS *sps = fc->ps.sps; + const VVCPPS *pps = fc->ps.pps; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; + const int extra_before = is_luma ? LUMA_EXTRA_BEFORE : CHROMA_EXTRA_BEFORE; + const int extra_after = is_luma ? LUMA_EXTRA_AFTER : CHROMA_EXTRA_AFTER; + const int extra = is_luma ? LUMA_EXTRA : CHROMA_EXTRA; + int pic_width, pic_height; + + subpic_offset(&x_off, &y_off, sps, pps, subpic_idx, is_luma); + subpic_offset(&x_sb, &y_sb, sps, pps, subpic_idx, is_luma); + subpic_width_height(&pic_width, &pic_height, sps, pps, subpic_idx, is_luma); if (x_off < extra_before || y_off < extra_before || x_off >= pic_width - block_w - extra_after || @@ -88,11 +115,17 @@ static void emulated_edge_dmvr(const VVCFrameContext *fc, uint8_t *dst, const ui } } -static void emulated_edge_bilinear(const VVCFrameContext *fc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, - const int x_off, const int y_off, const int block_w, const int block_h) +static void emulated_edge_bilinear(const VVCLocalContext *lc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, + int x_off, int y_off, const int block_w, const int block_h) { - int pic_width = fc->ps.pps->width; - int pic_height = fc->ps.pps->height; + const VVCFrameContext *fc = lc->fc; + const VVCSPS *sps = fc->ps.sps; + const VVCPPS *pps = fc->ps.pps; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; + int pic_width, pic_height; + + subpic_offset(&x_off, &y_off, sps, pps, subpic_idx, 1); + subpic_width_height(&pic_width, &pic_height, sps, pps, subpic_idx, 1); if (x_off < BILINEAR_EXTRA_BEFORE || y_off < BILINEAR_EXTRA_BEFORE || x_off >= pic_width - block_w - BILINEAR_EXTRA_AFTER || @@ -111,19 +144,19 @@ static void emulated_edge_bilinear(const VVCFrameContext *fc, uint8_t *dst, cons #define EMULATED_EDGE_LUMA(dst, src, src_stride, x_off, y_off) \ - emulated_edge(fc, dst, src, src_stride, x_off, y_off, block_w, block_h, 1) + emulated_edge(lc, dst, src, src_stride, x_off, y_off, block_w, block_h, 1) #define EMULATED_EDGE_CHROMA(dst, src, src_stride, x_off, y_off) \ - emulated_edge(fc, dst, src, src_stride, x_off, y_off, block_w, block_h, 0) + emulated_edge(lc, dst, src, src_stride, x_off, y_off, block_w, block_h, 0) #define EMULATED_EDGE_DMVR_LUMA(dst, src, src_stride, x_sb, y_sb, x_off, y_off) \ - emulated_edge_dmvr(fc, dst, src, src_stride, x_sb, y_sb, x_off, y_off, block_w, block_h, 1) + emulated_edge_dmvr(lc, dst, src, src_stride, x_sb, y_sb, x_off, y_off, block_w, block_h, 1) #define EMULATED_EDGE_DMVR_CHROMA(dst, src, src_stride, x_sb, y_sb, x_off, y_off) \ - emulated_edge_dmvr(fc, dst, src, src_stride, x_sb, y_sb, x_off, y_off, block_w, block_h, 0) + emulated_edge_dmvr(lc, dst, src, src_stride, x_sb, y_sb, x_off, y_off, block_w, block_h, 0) #define EMULATED_EDGE_BILINEAR(dst, src, src_stride, x_off, y_off) \ - emulated_edge_bilinear(fc, dst, src, src_stride, x_off, y_off, pred_w, pred_h) + emulated_edge_bilinear(lc, dst, src, src_stride, x_off, y_off, pred_w, pred_h) // part of 8.5.6.6 Weighted sample prediction process static int derive_weight_uni(int *denom, int *wx, int *ox, diff --git a/libavcodec/vvc/vvc_mvs.c b/libavcodec/vvc/vvc_mvs.c index 6398fd3571..37a2d0a228 100644 --- a/libavcodec/vvc/vvc_mvs.c +++ b/libavcodec/vvc/vvc_mvs.c @@ -125,7 +125,7 @@ int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc) const RefPicList *rpl = lc->sc->rpl; for (j = 0; j < 2; j++) { - for (i = 0; i < rpl[j].nb_refs; i++) { + for (i = 0; i < lc->sc->sh.r->num_ref_idx_active[j]; i++) { if (rpl[j].list[i] > lc->fc->ps.ph.poc) { check_diffpicount++; break; @@ -200,10 +200,12 @@ static int derive_temporal_colocated_mvs(const VVCLocalContext *lc, MvField temp static int temporal_luma_motion_vector(const VVCLocalContext *lc, const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag) { - const VVCFrameContext *fc = lc->fc; - const VVCSPS *sps = fc->ps.sps; - const CodingUnit *cu = lc->cu; - int x, y, colPic, availableFlagLXCol = 0; + const VVCFrameContext *fc = lc->fc; + const VVCSPS *sps = fc->ps.sps; + const VVCPPS *pps = fc->ps.pps; + const CodingUnit *cu = lc->cu; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; + int x, y, x_end, y_end, colPic, availableFlagLXCol = 0; int min_pu_width = fc->ps.pps->min_pu_width; VVCFrame *ref = fc->ref->collocated_ref; MvField *tab_mvf; @@ -224,10 +226,12 @@ static int temporal_luma_motion_vector(const VVCLocalContext *lc, x = cu->x0 + cu->cb_width; y = cu->y0 + cu->cb_height; + x_end = pps->subpic_x[subpic_idx] + pps->subpic_width[subpic_idx]; + y_end = pps->subpic_y[subpic_idx] + pps->subpic_height[subpic_idx]; + if (tab_mvf && (cu->y0 >> sps->ctb_log2_size_y) == (y >> sps->ctb_log2_size_y) && - y < fc->ps.pps->height && - x < fc->ps.pps->width) { + x < x_end && y < y_end) { x &= ~7; y &= ~7; temp_col = TAB_MVF(x, y); @@ -991,13 +995,18 @@ static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct Mv return 1; } -static av_always_inline void sb_clip_location(const VVCFrameContext *fc, +static av_always_inline void sb_clip_location(const VVCLocalContext *lc, const int x_ctb, const int y_ctb, const Mv* temp_mv, int *x, int *y) { - const VVCPPS *pps = fc->ps.pps; - const int ctb_log2_size = fc->ps.sps->ctb_log2_size_y; - *y = av_clip(*y + temp_mv->y, y_ctb, FFMIN(pps->height - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7; - *x = av_clip(*x + temp_mv->x, x_ctb, FFMIN(pps->width - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7; + const VVCFrameContext *fc = lc->fc; + const VVCPPS *pps = fc->ps.pps; + const int ctb_log2_size = fc->ps.sps->ctb_log2_size_y; + const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; + const int x_end = pps->subpic_x[subpic_idx] + pps->subpic_width[subpic_idx]; + const int y_end = pps->subpic_y[subpic_idx] + pps->subpic_height[subpic_idx]; + + *x = av_clip(*x + temp_mv->x, x_ctb, FFMIN(x_end - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7; + *y = av_clip(*y + temp_mv->y, y_ctb, FFMIN(y_end - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7; } static void sb_temproal_luma_motion(const VVCLocalContext *lc, @@ -1015,7 +1024,7 @@ static void sb_temproal_luma_motion(const VVCLocalContext *lc, int colPic = ref->poc; int X = 0; - sb_clip_location(fc, x_ctb, y_ctb, temp_mv, &x, &y); + sb_clip_location(lc, x_ctb, y_ctb, temp_mv, &x, &y); temp_col = TAB_MVF(x, y); mvLXCol = mv + 0; diff --git a/libavcodec/vvc/vvc_ps.c b/libavcodec/vvc/vvc_ps.c index 7972803da6..d1d6be390a 100644 --- a/libavcodec/vvc/vvc_ps.c +++ b/libavcodec/vvc/vvc_ps.c @@ -319,43 +319,120 @@ static void tile_xy(int *tile_x, int *tile_y, const int tile_idx, const VVCPPS * *tile_y = tile_idx / pps->r->num_tile_columns; } -static void ctu_xy(int *ctu_x, int *ctu_y, const int tile_x, const int tile_y, const VVCPPS *pps) +static void ctu_xy(int *rx, int *ry, const int tile_x, const int tile_y, const VVCPPS *pps) { - *ctu_x = pps->col_bd[tile_x]; - *ctu_y = pps->row_bd[tile_y]; + *rx = pps->col_bd[tile_x]; + *ry = pps->row_bd[tile_y]; } -static int ctu_rs(const int ctu_x, const int ctu_y, const VVCPPS *pps) +static int ctu_rs(const int rx, const int ry, const VVCPPS *pps) { - return pps->ctb_width * ctu_y + ctu_x; + return pps->ctb_width * ry + rx; } -static int pps_add_ctus(VVCPPS *pps, int *off, const int ctu_x, const int ctu_y, +static int pps_add_ctus(VVCPPS *pps, int *off, const int rx, const int ry, const int w, const int h) { int start = *off; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { - pps->ctb_addr_in_slice[*off] = ctu_rs(ctu_x + x, ctu_y + y, pps); + pps->ctb_addr_in_slice[*off] = ctu_rs(rx + x, ry + y, pps); (*off)++; } } return *off - start; } +static void pps_single_slice_picture(VVCPPS *pps, int *off) +{ + for (int j = 0; j < pps->r->num_tile_rows; j++) { + for (int i = 0; i < pps->r->num_tile_columns; i++) { + pps->num_ctus_in_slice[0] = pps_add_ctus(pps, off, + pps->col_bd[i], pps->row_bd[j], + pps->r->col_width_val[i], pps->r->row_height_val[j]); + } + } +} + +static void subpic_tiles(int *tile_x, int *tile_y, int *tile_x_end, int *tile_y_end, + const VVCSPS *sps, const VVCPPS *pps, const int i) +{ + const int rx = sps->r->sps_subpic_ctu_top_left_x[i]; + const int ry = sps->r->sps_subpic_ctu_top_left_y[i]; + + *tile_x = *tile_y = 0; + + while (pps->col_bd[*tile_x] != rx) + (*tile_x)++; + + while (pps->row_bd[*tile_y] != ry) + (*tile_y)++; + + *tile_x_end = (*tile_x); + *tile_y_end = (*tile_y); + + while (pps->col_bd[*tile_x_end] < rx + sps->r->sps_subpic_width_minus1[i] + 1) + (*tile_x_end)++; + + while (pps->row_bd[*tile_y_end] < ry + sps->r->sps_subpic_height_minus1[i] + 1) + (*tile_y_end)++; +} + +static void pps_subpic_less_than_one_tile_slice(VVCPPS *pps, const VVCSPS *sps, const int i, const int tx, const int ty, int *off) +{ + pps->num_ctus_in_slice[i] = pps_add_ctus(pps, off, + pps->col_bd[tx], pps->row_bd[ty], + pps->r->col_width_val[tx], sps->r->sps_subpic_height_minus1[i] + 1); +} + +static void pps_subpic_multi_tiles_slice(VVCPPS *pps, const int tile_x, const int tile_y, const int x_end, const int y_end, const int i, int *off) +{ + for (int ty = tile_y; ty < y_end; ty++) { + for (int tx = tile_x; tx < x_end; tx++) { + pps->num_ctus_in_slice[i] += pps_add_ctus(pps, off, + pps->col_bd[tx], pps->row_bd[ty], + pps->r->col_width_val[tx], pps->r->row_height_val[ty]); + } + } +} + +static void pps_subpic_slice(VVCPPS *pps, const VVCSPS *sps, const int i, int *off) +{ + int tx, ty, x_end, y_end; + + pps->slice_start_offset[i] = *off; + pps->num_ctus_in_slice[i] = 0; + + subpic_tiles(&tx, &ty, &x_end, &y_end, sps, pps, i); + if (ty + 1 == y_end && sps->r->sps_subpic_height_minus1[i] + 1 < pps->r->row_height_val[ty]) + pps_subpic_less_than_one_tile_slice(pps, sps, i, tx, ty, off); + else + pps_subpic_multi_tiles_slice(pps, tx, ty, x_end, y_end, i, off); +} + +static void pps_single_slice_per_subpic(VVCPPS *pps, const VVCSPS *sps, int *off) +{ + if (!sps->r->sps_subpic_info_present_flag) { + pps_single_slice_picture(pps, off); + } else { + for (int i = 0; i < pps->r->pps_num_slices_in_pic_minus1 + 1; i++) + pps_subpic_slice(pps, sps, i, off); + } +} + static int pps_one_tile_slices(VVCPPS *pps, const int tile_idx, int i, int *off) { const H266RawPPS *r = pps->r; - int ctu_x, ctu_y, ctu_y_end, tile_x, tile_y; + int rx, ry, ctu_y_end, tile_x, tile_y; tile_xy(&tile_x, &tile_y, tile_idx, pps); - ctu_xy(&ctu_x, &ctu_y, tile_x, tile_y, pps); - ctu_y_end = ctu_y + r->row_height_val[tile_y]; - while (ctu_y < ctu_y_end) { + ctu_xy(&rx, &ry, tile_x, tile_y, pps); + ctu_y_end = ry + r->row_height_val[tile_y]; + while (ry < ctu_y_end) { pps->slice_start_offset[i] = *off; - pps->num_ctus_in_slice[i] = pps_add_ctus(pps, off, ctu_x, ctu_y, + pps->num_ctus_in_slice[i] = pps_add_ctus(pps, off, rx, ry, r->col_width_val[tile_x], r->slice_height_in_ctus[i]); - ctu_y += r->slice_height_in_ctus[i++]; + ry += r->slice_height_in_ctus[i++]; } i--; return i; @@ -364,32 +441,36 @@ static int pps_one_tile_slices(VVCPPS *pps, const int tile_idx, int i, int *off) static void pps_multi_tiles_slice(VVCPPS *pps, const int tile_idx, const int i, int *off) { const H266RawPPS *r = pps->r; - int ctu_x, ctu_y,tile_x, tile_y; + int rx, ry, tile_x, tile_y; tile_xy(&tile_x, &tile_y, tile_idx, pps); pps->slice_start_offset[i] = *off; pps->num_ctus_in_slice[i] = 0; for (int ty = tile_y; ty <= tile_y + r->pps_slice_height_in_tiles_minus1[i]; ty++) { for (int tx = tile_x; tx <= tile_x + r->pps_slice_width_in_tiles_minus1[i]; tx++) { - ctu_xy(&ctu_x, &ctu_y, tx, ty, pps); - pps->num_ctus_in_slice[i] += pps_add_ctus(pps, off, ctu_x, ctu_y, + ctu_xy(&rx, &ry, tx, ty, pps); + pps->num_ctus_in_slice[i] += pps_add_ctus(pps, off, rx, ry, r->col_width_val[tx], r->row_height_val[ty]); } } } -static void pps_rect_slice(VVCPPS* pps) +static void pps_rect_slice(VVCPPS *pps, const VVCSPS *sps) { - const H266RawPPS* r = pps->r; + const H266RawPPS *r = pps->r; int tile_idx = 0, off = 0; + if (r->pps_single_slice_per_subpic_flag) { + pps_single_slice_per_subpic(pps, sps, &off); + return; + } + for (int i = 0; i < r->pps_num_slices_in_pic_minus1 + 1; i++) { if (!r->pps_slice_width_in_tiles_minus1[i] && !r->pps_slice_height_in_tiles_minus1[i]) { i = pps_one_tile_slices(pps, tile_idx, i, &off); } else { pps_multi_tiles_slice(pps, tile_idx, i, &off); - } tile_idx = next_tile_idx(tile_idx, i, r); } @@ -398,24 +479,24 @@ static void pps_rect_slice(VVCPPS* pps) static void pps_no_rect_slice(VVCPPS* pps) { const H266RawPPS* r = pps->r; - int ctu_x, ctu_y, off = 0; + int rx, ry, off = 0; for (int tile_y = 0; tile_y < r->num_tile_rows; tile_y++) { for (int tile_x = 0; tile_x < r->num_tile_columns; tile_x++) { - ctu_xy(&ctu_x, &ctu_y, tile_x, tile_y, pps); - pps_add_ctus(pps, &off, ctu_x, ctu_y, r->col_width_val[tile_x], r->row_height_val[tile_y]); + ctu_xy(&rx, &ry, tile_x, tile_y, pps); + pps_add_ctus(pps, &off, rx, ry, r->col_width_val[tile_x], r->row_height_val[tile_y]); } } } -static int pps_slice_map(VVCPPS *pps) +static int pps_slice_map(VVCPPS *pps, const VVCSPS *sps) { pps->ctb_addr_in_slice = av_calloc(pps->ctb_count, sizeof(*pps->ctb_addr_in_slice)); if (!pps->ctb_addr_in_slice) return AVERROR(ENOMEM); if (pps->r->pps_rect_slice_flag) - pps_rect_slice(pps); + pps_rect_slice(pps, sps); else pps_no_rect_slice(pps); @@ -430,6 +511,24 @@ static void pps_ref_wraparound_offset(VVCPPS *pps, const VVCSPS *sps) pps->ref_wraparound_offset = (pps->width / sps->min_cb_size_y) - r->pps_pic_width_minus_wraparound_offset; } +static void pps_subpic(VVCPPS *pps, const VVCSPS *sps) +{ + const H266RawSPS *rsps = sps->r; + for (int i = 0; i < rsps->sps_num_subpics_minus1 + 1; i++) { + if (rsps->sps_subpic_treated_as_pic_flag[i]) { + pps->subpic_x[i] = rsps->sps_subpic_ctu_top_left_x[i] << sps->ctb_log2_size_y; + pps->subpic_y[i] = rsps->sps_subpic_ctu_top_left_y[i] << sps->ctb_log2_size_y; + pps->subpic_width[i] = FFMIN(pps->width - pps->subpic_x[i], (rsps->sps_subpic_width_minus1[i] + 1) << sps->ctb_log2_size_y); + pps->subpic_height[i] = FFMIN(pps->height - pps->subpic_y[i], (rsps->sps_subpic_height_minus1[i] + 1) << sps->ctb_log2_size_y); + } else { + pps->subpic_x[i] = 0; + pps->subpic_y[i] = 0; + pps->subpic_width[i] = pps->width; + pps->subpic_height[i] = pps->height; + } + } +} + static int pps_derive(VVCPPS *pps, const VVCSPS *sps) { int ret; @@ -441,11 +540,12 @@ static int pps_derive(VVCPPS *pps, const VVCSPS *sps) if (ret < 0) return ret; - ret = pps_slice_map(pps); + ret = pps_slice_map(pps, sps); if (ret < 0) return ret; pps_ref_wraparound_offset(pps, sps); + pps_subpic(pps, sps); return 0; } diff --git a/libavcodec/vvc/vvc_ps.h b/libavcodec/vvc/vvc_ps.h index 1164d0eab6..35b46e234b 100644 --- a/libavcodec/vvc/vvc_ps.h +++ b/libavcodec/vvc/vvc_ps.h @@ -127,6 +127,10 @@ typedef struct VVCPPS { uint16_t ref_wraparound_offset; ///< PpsRefWraparoundOffset + uint16_t subpic_x[VVC_MAX_SLICES]; ///< SubpicLeftBoundaryPos + uint16_t subpic_y[VVC_MAX_SLICES]; ///< SubpicTopBoundaryPos + uint16_t subpic_width[VVC_MAX_SLICES]; + uint16_t subpic_height[VVC_MAX_SLICES]; } VVCPPS; #define MAX_WEIGHTS 15 diff --git a/libavcodec/vvc/vvc_thread.c b/libavcodec/vvc/vvc_thread.c index 31c931f050..8f23b8138b 100644 --- a/libavcodec/vvc/vvc_thread.c +++ b/libavcodec/vvc/vvc_thread.c @@ -416,7 +416,6 @@ static int run_parse(VVCContext *s, VVCLocalContext *lc, VVCTask *t) const int rs = t->rs; const CTU *ctu = fc->tab.ctus + rs; - lc->sc = t->sc; lc->ep = t->ep; ret = ff_vvc_coding_tree_unit(lc, t->ctu_idx, rs, t->rx, t->ry); @@ -432,15 +431,9 @@ static int run_parse(VVCContext *s, VVCLocalContext *lc, VVCTask *t) static int run_inter(VVCContext *s, VVCLocalContext *lc, VVCTask *t) { VVCFrameContext *fc = lc->fc; - VVCFrameThread *ft = fc->ft; - const int rs = t->ry * ft->ctu_width + t->rx; - const CTU *ctu = fc->tab.ctus + rs; - const int slice_idx = fc->tab.slice_idx[rs]; + const CTU *ctu = fc->tab.ctus + t->rs; - if (slice_idx != -1) { - lc->sc = fc->slices[slice_idx]; - ff_vvc_predict_inter(lc, rs); - } + ff_vvc_predict_inter(lc, t->rs); if (ctu->has_dmvr) report_frame_progress(fc, t->ry, VVC_PROGRESS_MV); @@ -450,14 +443,7 @@ static int run_inter(VVCContext *s, VVCLocalContext *lc, VVCTask *t) static int run_recon(VVCContext *s, VVCLocalContext *lc, VVCTask *t) { - VVCFrameContext *fc = lc->fc; - const int rs = t->rs; - const int slice_idx = fc->tab.slice_idx[rs]; - - if (slice_idx != -1) { - lc->sc = fc->slices[slice_idx]; - ff_vvc_reconstruct(lc, rs, t->rx, t->ry); - } + ff_vvc_reconstruct(lc, t->rs, t->rx, t->ry); return 0; } @@ -469,13 +455,8 @@ static int run_lmcs(VVCContext *s, VVCLocalContext *lc, VVCTask *t) const int ctu_size = ft->ctu_size; const int x0 = t->rx * ctu_size; const int y0 = t->ry * ctu_size; - const int rs = t->ry * ft->ctu_width + t->rx; - const int slice_idx = fc->tab.slice_idx[rs]; - if (slice_idx != -1) { - lc->sc = fc->slices[slice_idx]; - ff_vvc_lmcs_filter(lc, x0, y0); - } + ff_vvc_lmcs_filter(lc, x0, y0); return 0; } @@ -484,18 +465,13 @@ static int run_deblock_v(VVCContext *s, VVCLocalContext *lc, VVCTask *t) { VVCFrameContext *fc = lc->fc; VVCFrameThread *ft = fc->ft; - const int rs = t->ry * ft->ctu_width + t->rx; const int ctb_size = ft->ctu_size; const int x0 = t->rx * ctb_size; const int y0 = t->ry * ctb_size; - const int slice_idx = fc->tab.slice_idx[rs]; - if (slice_idx != -1) { - lc->sc = fc->slices[slice_idx]; - if (!lc->sc->sh.r->sh_deblocking_filter_disabled_flag) { - ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, rs); - ff_vvc_deblock_vertical(lc, x0, y0); - } + if (!lc->sc->sh.r->sh_deblocking_filter_disabled_flag) { + ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, t->rs); + ff_vvc_deblock_vertical(lc, x0, y0, t->rs); } return 0; @@ -506,20 +482,15 @@ static int run_deblock_h(VVCContext *s, VVCLocalContext *lc, VVCTask *t) VVCFrameContext *fc = lc->fc; VVCFrameThread *ft = fc->ft; const int ctb_size = ft->ctu_size; - const int rs = t->ry * ft->ctu_width + t->rx; const int x0 = t->rx * ctb_size; const int y0 = t->ry * ctb_size; - const int slice_idx = fc->tab.slice_idx[rs]; - if (slice_idx != -1) { - lc->sc = fc->slices[slice_idx]; - if (!lc->sc->sh.r->sh_deblocking_filter_disabled_flag) { - ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, rs); - ff_vvc_deblock_horizontal(lc, x0, y0); - } - if (fc->ps.sps->r->sps_sao_enabled_flag) - ff_vvc_sao_copy_ctb_to_hv(lc, t->rx, t->ry, t->ry == ft->ctu_height - 1); + if (!lc->sc->sh.r->sh_deblocking_filter_disabled_flag) { + ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, t->rs); + ff_vvc_deblock_horizontal(lc, x0, y0, t->rs); } + if (fc->ps.sps->r->sps_sao_enabled_flag) + ff_vvc_sao_copy_ctb_to_hv(lc, t->rx, t->ry, t->ry == ft->ctu_height - 1); return 0; } @@ -528,13 +499,12 @@ static int run_sao(VVCContext *s, VVCLocalContext *lc, VVCTask *t) { VVCFrameContext *fc = lc->fc; VVCFrameThread *ft = fc->ft; - const int rs = t->ry * fc->ps.pps->ctb_width + t->rx; const int ctb_size = ft->ctu_size; const int x0 = t->rx * ctb_size; const int y0 = t->ry * ctb_size; if (fc->ps.sps->r->sps_sao_enabled_flag) { - ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, rs); + ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, t->rs); ff_vvc_sao_filter(lc, x0, y0); } @@ -553,12 +523,8 @@ static int run_alf(VVCContext *s, VVCLocalContext *lc, VVCTask *t) const int y0 = t->ry * ctu_size; if (fc->ps.sps->r->sps_alf_enabled_flag) { - const int slice_idx = CTB(fc->tab.slice_idx, t->rx, t->ry); - if (slice_idx != -1) { - lc->sc = fc->slices[slice_idx]; - ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, t->rs); - ff_vvc_alf_filter(lc, x0, y0); - } + ff_vvc_decode_neighbour(lc, x0, y0, t->rx, t->ry, t->rs); + ff_vvc_alf_filter(lc, x0, y0); } report_frame_progress(fc, t->ry, VVC_PROGRESS_PIXEL); @@ -602,6 +568,8 @@ static void task_run_stage(VVCTask *t, VVCContext *s, VVCLocalContext *lc) av_log(s->avctx, AV_LOG_DEBUG, "frame %5d, %s(%3d, %3d)\r\n", (int)t->fc->decode_order, task_name[stage], t->rx, t->ry); #endif + lc->sc = t->sc; + if (!atomic_load(&ft->ret)) { if ((ret = run[stage](s, lc, t)) < 0) { #ifdef COMPAT_ATOMICS_WIN32_STDATOMIC_H