/work/svt-av1/Source/Lib/Codec/coding_unit.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright(c) 2019 Intel Corporation |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license. |
10 | | */ |
11 | | |
12 | | #include <stdlib.h> |
13 | | #include <stdint.h> |
14 | | |
15 | | #include "pcs.h" |
16 | | #include "utility.h" |
17 | | #include "enc_mode_config.h" |
18 | | |
19 | 5.93k | void svt_aom_largest_coding_unit_dctor(EbPtr p) { |
20 | | // av1xd / final_blk_arr / ptree are borrowed from per-PCS pools (freed in the PCS dctor). |
21 | 5.93k | (void)p; |
22 | 5.93k | } |
23 | | |
24 | 504k | static void setup_ptree(PARTITION_TREE* pc_tree, int index, BlockSize bsize, const int min_sq_size) { |
25 | 504k | pc_tree->bsize = bsize; |
26 | 504k | pc_tree->index = index; |
27 | | |
28 | | // If applicable, add split depths |
29 | 504k | const int sq_size = block_size_wide[bsize]; |
30 | 504k | if (sq_size > min_sq_size) { |
31 | 124k | const BlockSize subsize = get_partition_subsize(bsize, PARTITION_SPLIT); |
32 | 124k | const int sq_subsize = block_size_wide[subsize]; |
33 | 124k | int blocks_per_subdepth = (sq_subsize / min_sq_size) * (sq_subsize / min_sq_size); |
34 | 124k | int blocks_to_skip = 0; |
35 | | |
36 | 285k | for (int i = min_sq_size; i <= sq_subsize; i <<= 1, blocks_per_subdepth >>= 2) { |
37 | 160k | blocks_to_skip += blocks_per_subdepth; |
38 | 160k | } |
39 | | |
40 | 623k | for (int i = 0; i < SUB_PARTITIONS_SPLIT; ++i) { |
41 | 498k | pc_tree->sub_tree[i] = pc_tree + i * blocks_to_skip + 1; |
42 | 498k | setup_ptree(pc_tree->sub_tree[i], i, subsize, min_sq_size); |
43 | 498k | } |
44 | 124k | } |
45 | 504k | } |
46 | | |
47 | | /* |
48 | | Tasks & Questions |
49 | | -Need a GetEmptyChain function for testing sub partitions. Tie it to an Itr? |
50 | | -How many empty CUs do we need? We need to have enough for the max CU count AND |
51 | | enough for temp storage when calculating a subdivision. |
52 | | -Where do we store temp reconstructed picture data while deciding to subdivide or not? |
53 | | -Need a ReconPicture for each candidate. |
54 | | -I don't see a way around doing the copies in temp memory and then copying it in... |
55 | | */ |
56 | | EbErrorType svt_aom_largest_coding_unit_ctor(SuperBlock* larget_coding_unit_ptr, uint8_t sb_size_pix, |
57 | | uint16_t sb_origin_x, uint16_t sb_origin_y, uint16_t sb_index, |
58 | 5.93k | EncMode enc_mode, bool rtc, bool allintra, PictureControlSet* pcs) { |
59 | 5.93k | larget_coding_unit_ptr->dctor = svt_aom_largest_coding_unit_dctor; |
60 | | |
61 | | // ************ SB *************** |
62 | | // Which borderLargestCuSize is not a power of two |
63 | | |
64 | | // Which borderLargestCuSize is not a power of two |
65 | 5.93k | larget_coding_unit_ptr->pcs = pcs; |
66 | | |
67 | 5.93k | larget_coding_unit_ptr->org_x = sb_origin_x; |
68 | 5.93k | larget_coding_unit_ptr->org_y = sb_origin_y; |
69 | | |
70 | 5.93k | larget_coding_unit_ptr->index = sb_index; |
71 | 5.93k | bool disallow_sub_8x8_nsq = true; |
72 | 5.93k | bool disallow_sub_16x16_nsq = true; |
73 | 35.6k | for (uint8_t coeff_lvl = 0; coeff_lvl <= HIGH_LVL + 1; coeff_lvl++) { |
74 | 29.6k | uint8_t nsq_geom_lvl = allintra ? svt_aom_get_nsq_geom_level_allintra(enc_mode) |
75 | 29.6k | : rtc ? svt_aom_get_nsq_geom_level_rtc() |
76 | 0 | : svt_aom_get_nsq_geom_level_default(enc_mode, coeff_lvl); |
77 | | // nsq_geom_lvl level 0 means NSQ shapes are disallowed so don't adjust based on the level |
78 | 29.6k | if (nsq_geom_lvl) { |
79 | 0 | uint8_t allow_HVA_HVB, allow_HV4, min_nsq_bsize; |
80 | 0 | svt_aom_set_nsq_geom_ctrls(NULL, nsq_geom_lvl, &allow_HVA_HVB, &allow_HV4, &min_nsq_bsize); |
81 | 0 | if (min_nsq_bsize < 8) { |
82 | 0 | disallow_sub_8x8_nsq = false; |
83 | 0 | } |
84 | 0 | if (min_nsq_bsize < 16) { |
85 | 0 | disallow_sub_16x16_nsq = false; |
86 | 0 | } |
87 | 0 | } |
88 | 29.6k | } |
89 | 5.93k | bool disallow_4x4 = allintra ? svt_aom_get_disallow_4x4_allintra(enc_mode) |
90 | 5.93k | : rtc ? svt_aom_get_disallow_4x4_rtc() |
91 | 0 | : svt_aom_get_disallow_4x4_default(enc_mode); |
92 | 5.93k | bool disallow_8x8 = allintra ? svt_aom_get_disallow_8x8_allintra() |
93 | 5.93k | : rtc ? svt_aom_get_disallow_8x8_rtc(enc_mode, pcs->frame_width, pcs->frame_height) |
94 | 0 | : svt_aom_get_disallow_8x8_default(); |
95 | 5.93k | uint32_t tot_blk_num; |
96 | 5.93k | if (sb_size_pix == 128) { |
97 | 0 | if (disallow_8x8 && disallow_sub_16x16_nsq) { |
98 | 0 | tot_blk_num = 64; |
99 | 0 | } else if (disallow_8x8 || (disallow_4x4 && disallow_sub_8x8_nsq)) { |
100 | 0 | tot_blk_num = 256; |
101 | 0 | } else if (disallow_4x4) { |
102 | 0 | tot_blk_num = 512; |
103 | 0 | } else { |
104 | 0 | tot_blk_num = 1024; |
105 | 0 | } |
106 | 5.93k | } else if (disallow_8x8 && disallow_sub_16x16_nsq) { |
107 | 0 | tot_blk_num = 16; |
108 | 5.93k | } else if (disallow_8x8 || (disallow_4x4 && disallow_sub_8x8_nsq)) { |
109 | 5.93k | tot_blk_num = 64; |
110 | 5.93k | } else if (disallow_4x4) { |
111 | 0 | tot_blk_num = 128; |
112 | 0 | } else { |
113 | 0 | tot_blk_num = 256; |
114 | 0 | } |
115 | | // Do NOT initialize the final_blk_arr here |
116 | | // Malloc maximum but only initialize it only when actually used. |
117 | | // This will help to same actually memory usage |
118 | | // Alloc ptree, which is used to store final block data/mode info for the SB that is passed |
119 | | // from encdec to EC |
120 | 5.93k | uint8_t min_bsize = disallow_8x8 ? 16 : disallow_4x4 ? 8 : 4; |
121 | 5.93k | int blocks_per_depth = (sb_size_pix / min_bsize) * (sb_size_pix / min_bsize); |
122 | 5.93k | int blocks_to_alloc = 0; |
123 | | |
124 | 29.6k | for (int i = min_bsize; i <= sb_size_pix; i <<= 1, blocks_per_depth >>= 2) { |
125 | 23.7k | blocks_to_alloc += blocks_per_depth; |
126 | 23.7k | } |
127 | | // All SBs in a PCS resolve to identical tot_blk_num / blocks_to_alloc, so back the whole |
128 | | // sb_ptr_array with one allocation each (created on the first SB) and hand each SB a slice, |
129 | | // instead of 3 allocations per SB. |
130 | 5.93k | const uint16_t all_sb = pcs->sb_total_count; |
131 | 5.93k | if (sb_index == 0) { |
132 | | // This ctor is re-run per frame on the resize/superres path (superres_setup_child_pcs), |
133 | | // so free any pool from a prior setup before reallocating (NULL-safe on first use). |
134 | 448 | EB_FREE_ARRAY(pcs->sb_final_blk_arr_pool); |
135 | 448 | EB_FREE_ARRAY(pcs->sb_av1xd_pool); |
136 | 448 | EB_FREE_ARRAY(pcs->sb_ptree_pool); |
137 | 448 | EB_MALLOC_ARRAY(pcs->sb_final_blk_arr_pool, (size_t)all_sb * tot_blk_num); |
138 | 448 | EB_MALLOC_ARRAY(pcs->sb_av1xd_pool, all_sb); |
139 | 448 | EB_CALLOC_ARRAY(pcs->sb_ptree_pool, (size_t)all_sb * blocks_to_alloc); |
140 | 448 | } |
141 | 5.93k | larget_coding_unit_ptr->final_blk_arr = pcs->sb_final_blk_arr_pool + (size_t)sb_index * tot_blk_num; |
142 | 5.93k | larget_coding_unit_ptr->av1xd = pcs->sb_av1xd_pool + sb_index; |
143 | 5.93k | larget_coding_unit_ptr->ptree = pcs->sb_ptree_pool + (size_t)sb_index * blocks_to_alloc; |
144 | 5.93k | setup_ptree(larget_coding_unit_ptr->ptree, 0, sb_size_pix == 128 ? BLOCK_128X128 : BLOCK_64X64, min_bsize); |
145 | | |
146 | 5.93k | return EB_ErrorNone; |
147 | 5.93k | } |