/work/libde265/libde265/image.h
Line | Count | Source |
1 | | /* |
2 | | * H.265 video codec. |
3 | | * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de> |
4 | | * |
5 | | * This file is part of libde265. |
6 | | * |
7 | | * libde265 is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation, either version 3 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * libde265 is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libde265. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #ifndef DE265_IMAGE_H |
22 | | #define DE265_IMAGE_H |
23 | | |
24 | | #ifdef HAVE_CONFIG_H |
25 | | #include <config.h> |
26 | | #endif |
27 | | |
28 | | #include <assert.h> |
29 | | #include <stddef.h> |
30 | | #include <stdint.h> |
31 | | #include <stdlib.h> |
32 | | #include <string.h> |
33 | | #include <limits> |
34 | | #include <memory> |
35 | | |
36 | | #include "libde265/de265.h" |
37 | | #include "libde265/sps.h" |
38 | | #include "libde265/pps.h" |
39 | | #include "libde265/motion.h" |
40 | | #include "libde265/threads.h" |
41 | | #include "libde265/slice.h" |
42 | | #include "libde265/nal.h" |
43 | | |
44 | | struct en265_encoder_context; |
45 | | |
46 | | enum PictureState { |
47 | | UnusedForReference, |
48 | | UsedForShortTermReference, |
49 | | UsedForLongTermReference |
50 | | }; |
51 | | |
52 | | |
53 | | /* TODO: |
54 | | At INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE images, we can check the SEI hash, whether |
55 | | the output image is correct despite the faulty reference, and set the state back to correct. |
56 | | */ |
57 | | constexpr uint8_t INTEGRITY_CORRECT = 0; |
58 | | constexpr uint8_t INTEGRITY_UNAVAILABLE_REFERENCE = 1; |
59 | | constexpr uint8_t INTEGRITY_NOT_DECODED = 2; |
60 | | constexpr uint8_t INTEGRITY_DECODING_ERRORS = 3; |
61 | | constexpr uint8_t INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE = 4; |
62 | | |
63 | | constexpr uint8_t SEI_HASH_UNCHECKED = 0; |
64 | | constexpr uint8_t SEI_HASH_CORRECT = 1; |
65 | | constexpr uint8_t SEI_HASH_INCORRECT = 2; |
66 | | |
67 | | constexpr uint8_t TU_FLAG_NONZERO_COEFF = (1<<7); |
68 | | constexpr uint8_t TU_FLAG_SPLIT_TRANSFORM_MASK = 0x1F; |
69 | | |
70 | | constexpr uint8_t DEBLOCK_FLAG_VERTI = (1<<4); |
71 | | constexpr uint8_t DEBLOCK_FLAG_HORIZ = (1<<5); |
72 | | constexpr uint8_t DEBLOCK_PB_EDGE_VERTI = (1<<6); |
73 | | constexpr uint8_t DEBLOCK_PB_EDGE_HORIZ = (1<<7); |
74 | | constexpr uint8_t DEBLOCK_BS_MASK = 0x03; |
75 | | |
76 | | constexpr int CTB_PROGRESS_NONE = 0; |
77 | | constexpr int CTB_PROGRESS_PREFILTER = 1; |
78 | | constexpr int CTB_PROGRESS_DEBLK_V = 2; |
79 | | constexpr int CTB_PROGRESS_DEBLK_H = 3; |
80 | | constexpr int CTB_PROGRESS_SAO = 4; |
81 | | |
82 | | class decoder_context; |
83 | | |
84 | | template <class DataUnit> class MetaDataArray |
85 | | { |
86 | | public: |
87 | 125k | MetaDataArray() = default; MetaDataArray<CTB_info>::MetaDataArray() Line | Count | Source | 87 | 17.8k | MetaDataArray() = default; |
MetaDataArray<CB_ref_info>::MetaDataArray() Line | Count | Source | 87 | 17.8k | MetaDataArray() = default; |
MetaDataArray<PBMotion>::MetaDataArray() Line | Count | Source | 87 | 17.8k | MetaDataArray() = default; |
MetaDataArray<unsigned char>::MetaDataArray() Line | Count | Source | 87 | 71.4k | MetaDataArray() = default; |
|
88 | 125k | ~MetaDataArray() { free(data); }MetaDataArray<CTB_info>::~MetaDataArray() Line | Count | Source | 88 | 17.8k | ~MetaDataArray() { free(data); } |
MetaDataArray<CB_ref_info>::~MetaDataArray() Line | Count | Source | 88 | 17.8k | ~MetaDataArray() { free(data); } |
MetaDataArray<PBMotion>::~MetaDataArray() Line | Count | Source | 88 | 17.8k | ~MetaDataArray() { free(data); } |
MetaDataArray<unsigned char>::~MetaDataArray() Line | Count | Source | 88 | 71.4k | ~MetaDataArray() { free(data); } |
|
89 | | |
90 | 79.8k | LIBDE265_CHECK_RESULT bool alloc(int w,int h, uint8_t _log2unitSize) { |
91 | 79.8k | int size = w*h; |
92 | | |
93 | 79.8k | if (size != data_size) { |
94 | 79.8k | free(data); |
95 | 79.8k | data = (DataUnit*)calloc(size, sizeof(DataUnit)); |
96 | 79.8k | if (data == nullptr) { |
97 | 0 | data_size = 0; |
98 | 0 | return false; |
99 | 0 | } |
100 | 79.8k | data_size = size; |
101 | 79.8k | } |
102 | | |
103 | 79.8k | width_in_units = w; |
104 | 79.8k | height_in_units = h; |
105 | | |
106 | 79.8k | log2unitSize = _log2unitSize; |
107 | | |
108 | 79.8k | return data != nullptr; |
109 | 79.8k | } MetaDataArray<unsigned char>::alloc(int, int, unsigned char) Line | Count | Source | 90 | 45.5k | LIBDE265_CHECK_RESULT bool alloc(int w,int h, uint8_t _log2unitSize) { | 91 | 45.5k | int size = w*h; | 92 | | | 93 | 45.5k | if (size != data_size) { | 94 | 45.5k | free(data); | 95 | 45.5k | data = (DataUnit*)calloc(size, sizeof(DataUnit)); | 96 | 45.5k | if (data == nullptr) { | 97 | 0 | data_size = 0; | 98 | 0 | return false; | 99 | 0 | } | 100 | 45.5k | data_size = size; | 101 | 45.5k | } | 102 | | | 103 | 45.5k | width_in_units = w; | 104 | 45.5k | height_in_units = h; | 105 | | | 106 | 45.5k | log2unitSize = _log2unitSize; | 107 | | | 108 | 45.5k | return data != nullptr; | 109 | 45.5k | } |
MetaDataArray<CB_ref_info>::alloc(int, int, unsigned char) Line | Count | Source | 90 | 11.4k | LIBDE265_CHECK_RESULT bool alloc(int w,int h, uint8_t _log2unitSize) { | 91 | 11.4k | int size = w*h; | 92 | | | 93 | 11.4k | if (size != data_size) { | 94 | 11.4k | free(data); | 95 | 11.4k | data = (DataUnit*)calloc(size, sizeof(DataUnit)); | 96 | 11.4k | if (data == nullptr) { | 97 | 0 | data_size = 0; | 98 | 0 | return false; | 99 | 0 | } | 100 | 11.4k | data_size = size; | 101 | 11.4k | } | 102 | | | 103 | 11.4k | width_in_units = w; | 104 | 11.4k | height_in_units = h; | 105 | | | 106 | 11.4k | log2unitSize = _log2unitSize; | 107 | | | 108 | 11.4k | return data != nullptr; | 109 | 11.4k | } |
MetaDataArray<PBMotion>::alloc(int, int, unsigned char) Line | Count | Source | 90 | 11.4k | LIBDE265_CHECK_RESULT bool alloc(int w,int h, uint8_t _log2unitSize) { | 91 | 11.4k | int size = w*h; | 92 | | | 93 | 11.4k | if (size != data_size) { | 94 | 11.4k | free(data); | 95 | 11.4k | data = (DataUnit*)calloc(size, sizeof(DataUnit)); | 96 | 11.4k | if (data == nullptr) { | 97 | 0 | data_size = 0; | 98 | 0 | return false; | 99 | 0 | } | 100 | 11.4k | data_size = size; | 101 | 11.4k | } | 102 | | | 103 | 11.4k | width_in_units = w; | 104 | 11.4k | height_in_units = h; | 105 | | | 106 | 11.4k | log2unitSize = _log2unitSize; | 107 | | | 108 | 11.4k | return data != nullptr; | 109 | 11.4k | } |
MetaDataArray<CTB_info>::alloc(int, int, unsigned char) Line | Count | Source | 90 | 11.4k | LIBDE265_CHECK_RESULT bool alloc(int w,int h, uint8_t _log2unitSize) { | 91 | 11.4k | int size = w*h; | 92 | | | 93 | 11.4k | if (size != data_size) { | 94 | 11.4k | free(data); | 95 | 11.4k | data = (DataUnit*)calloc(size, sizeof(DataUnit)); | 96 | 11.4k | if (data == nullptr) { | 97 | 0 | data_size = 0; | 98 | 0 | return false; | 99 | 0 | } | 100 | 11.4k | data_size = size; | 101 | 11.4k | } | 102 | | | 103 | 11.4k | width_in_units = w; | 104 | 11.4k | height_in_units = h; | 105 | | | 106 | 11.4k | log2unitSize = _log2unitSize; | 107 | | | 108 | 11.4k | return data != nullptr; | 109 | 11.4k | } |
|
110 | | |
111 | 26.1k | void clear() { |
112 | 26.1k | if (data) memset(data, 0, sizeof(DataUnit) * data_size); |
113 | 26.1k | } MetaDataArray<CB_ref_info>::clear() Line | Count | Source | 111 | 6.54k | void clear() { | 112 | 6.54k | if (data) memset(data, 0, sizeof(DataUnit) * data_size); | 113 | 6.54k | } |
MetaDataArray<unsigned char>::clear() Line | Count | Source | 111 | 13.0k | void clear() { | 112 | 13.0k | if (data) memset(data, 0, sizeof(DataUnit) * data_size); | 113 | 13.0k | } |
MetaDataArray<CTB_info>::clear() Line | Count | Source | 111 | 6.54k | void clear() { | 112 | 6.54k | if (data) memset(data, 0, sizeof(DataUnit) * data_size); | 113 | 6.54k | } |
|
114 | | |
115 | 412M | const DataUnit& get(int x,int y) const { |
116 | 412M | int unitX = x>>log2unitSize; |
117 | 412M | int unitY = y>>log2unitSize; |
118 | | |
119 | 412M | assert(unitX >= 0 && unitX < width_in_units); |
120 | 412M | assert(unitY >= 0 && unitY < height_in_units); |
121 | | |
122 | 412M | return data[ unitX + unitY*width_in_units ]; |
123 | 412M | } MetaDataArray<CB_ref_info>::get(int, int) const Line | Count | Source | 115 | 295M | const DataUnit& get(int x,int y) const { | 116 | 295M | int unitX = x>>log2unitSize; | 117 | 295M | int unitY = y>>log2unitSize; | 118 | | | 119 | 295M | assert(unitX >= 0 && unitX < width_in_units); | 120 | 295M | assert(unitY >= 0 && unitY < height_in_units); | 121 | | | 122 | 295M | return data[ unitX + unitY*width_in_units ]; | 123 | 295M | } |
MetaDataArray<unsigned char>::get(int, int) const Line | Count | Source | 115 | 63.0M | const DataUnit& get(int x,int y) const { | 116 | 63.0M | int unitX = x>>log2unitSize; | 117 | 63.0M | int unitY = y>>log2unitSize; | 118 | | | 119 | 63.0M | assert(unitX >= 0 && unitX < width_in_units); | 120 | 63.0M | assert(unitY >= 0 && unitY < height_in_units); | 121 | | | 122 | 63.0M | return data[ unitX + unitY*width_in_units ]; | 123 | 63.0M | } |
MetaDataArray<CTB_info>::get(int, int) const Line | Count | Source | 115 | 46.0M | const DataUnit& get(int x,int y) const { | 116 | 46.0M | int unitX = x>>log2unitSize; | 117 | 46.0M | int unitY = y>>log2unitSize; | 118 | | | 119 | 46.0M | assert(unitX >= 0 && unitX < width_in_units); | 120 | 46.0M | assert(unitY >= 0 && unitY < height_in_units); | 121 | | | 122 | 45.9M | return data[ unitX + unitY*width_in_units ]; | 123 | 46.0M | } |
MetaDataArray<PBMotion>::get(int, int) const Line | Count | Source | 115 | 7.96M | const DataUnit& get(int x,int y) const { | 116 | 7.96M | int unitX = x>>log2unitSize; | 117 | 7.96M | int unitY = y>>log2unitSize; | 118 | | | 119 | 7.96M | assert(unitX >= 0 && unitX < width_in_units); | 120 | 7.96M | assert(unitY >= 0 && unitY < height_in_units); | 121 | | | 122 | 7.96M | return data[ unitX + unitY*width_in_units ]; | 123 | 7.96M | } |
|
124 | | |
125 | 11.9M | DataUnit& get(int x,int y) { |
126 | 11.9M | int unitX = x>>log2unitSize; |
127 | 11.9M | int unitY = y>>log2unitSize; |
128 | | |
129 | 11.9M | assert(unitX >= 0 && unitX < width_in_units); |
130 | 11.9M | assert(unitY >= 0 && unitY < height_in_units); |
131 | | |
132 | 11.8M | return data[ unitX + unitY*width_in_units ]; |
133 | 11.9M | } MetaDataArray<CTB_info>::get(int, int) Line | Count | Source | 125 | 1.18M | DataUnit& get(int x,int y) { | 126 | 1.18M | int unitX = x>>log2unitSize; | 127 | 1.18M | int unitY = y>>log2unitSize; | 128 | | | 129 | 1.18M | assert(unitX >= 0 && unitX < width_in_units); | 130 | 1.18M | assert(unitY >= 0 && unitY < height_in_units); | 131 | | | 132 | 1.18M | return data[ unitX + unitY*width_in_units ]; | 133 | 1.18M | } |
MetaDataArray<CB_ref_info>::get(int, int) Line | Count | Source | 125 | 8.87M | DataUnit& get(int x,int y) { | 126 | 8.87M | int unitX = x>>log2unitSize; | 127 | 8.87M | int unitY = y>>log2unitSize; | 128 | | | 129 | 8.87M | assert(unitX >= 0 && unitX < width_in_units); | 130 | 8.87M | assert(unitY >= 0 && unitY < height_in_units); | 131 | | | 132 | 8.87M | return data[ unitX + unitY*width_in_units ]; | 133 | 8.87M | } |
MetaDataArray<unsigned char>::get(int, int) Line | Count | Source | 125 | 1.83M | DataUnit& get(int x,int y) { | 126 | 1.83M | int unitX = x>>log2unitSize; | 127 | 1.83M | int unitY = y>>log2unitSize; | 128 | | | 129 | 1.83M | assert(unitX >= 0 && unitX < width_in_units); | 130 | 1.83M | assert(unitY >= 0 && unitY < height_in_units); | 131 | | | 132 | 1.83M | return data[ unitX + unitY*width_in_units ]; | 133 | 1.83M | } |
|
134 | | |
135 | | void set(int x,int y, const DataUnit& d) { |
136 | | int unitX = x>>log2unitSize; |
137 | | int unitY = y>>log2unitSize; |
138 | | |
139 | | assert(unitX >= 0 && unitX < width_in_units); |
140 | | assert(unitY >= 0 && unitY < height_in_units); |
141 | | |
142 | | data[ unitX + unitY*width_in_units ] = d; |
143 | | } |
144 | | |
145 | 205M | DataUnit& operator[](int idx) { return data[idx]; }MetaDataArray<unsigned char>::operator[](int) Line | Count | Source | 145 | 163M | DataUnit& operator[](int idx) { return data[idx]; } |
MetaDataArray<CB_ref_info>::operator[](int) Line | Count | Source | 145 | 33.8M | DataUnit& operator[](int idx) { return data[idx]; } |
MetaDataArray<CTB_info>::operator[](int) Line | Count | Source | 145 | 715k | DataUnit& operator[](int idx) { return data[idx]; } |
MetaDataArray<PBMotion>::operator[](int) Line | Count | Source | 145 | 7.88M | DataUnit& operator[](int idx) { return data[idx]; } |
|
146 | 213M | const DataUnit& operator[](int idx) const { return data[idx]; }MetaDataArray<CB_ref_info>::operator[](int) const Line | Count | Source | 146 | 10.2M | const DataUnit& operator[](int idx) const { return data[idx]; } |
MetaDataArray<unsigned char>::operator[](int) const Line | Count | Source | 146 | 77.0M | const DataUnit& operator[](int idx) const { return data[idx]; } |
MetaDataArray<CTB_info>::operator[](int) const Line | Count | Source | 146 | 126M | const DataUnit& operator[](int idx) const { return data[idx]; } |
|
147 | | |
148 | 773 | int size() const { return data_size; } |
149 | | |
150 | | // private: |
151 | | DataUnit* data = nullptr; |
152 | | int data_size = 0; |
153 | | uint8_t log2unitSize = 0; |
154 | | int width_in_units = 0; |
155 | | int height_in_units = 0; |
156 | | }; |
157 | | |
158 | | |
159 | | |
160 | | struct CTB_info { |
161 | | uint16_t SliceAddrRS; |
162 | | uint16_t SliceHeaderIndex; // index into array to slice header for this CTB |
163 | | |
164 | | sao_info saoInfo; |
165 | | bool deblock; // this CTB has to be deblocked |
166 | | |
167 | | // The following flag helps to quickly check whether we have to |
168 | | // check all conditions in the SAO filter or whether we can skip them. |
169 | | bool has_pcm_or_cu_transquant_bypass; // pcm or transquant_bypass is used in this CTB |
170 | | }; |
171 | | |
172 | | |
173 | | struct CB_ref_info { |
174 | | uint8_t log2CbSize : 3; /* [0;6] (1<<log2CbSize) = 64 |
175 | | This is only set in the top-left corner of the CB. |
176 | | The other values should be zero. |
177 | | TODO: in the encoder, we have to clear to zero. |
178 | | Used in deblocking and QP-scale decoding */ |
179 | | uint8_t PartMode : 3; // (enum PartMode) [0;7] set only in top-left of CB |
180 | | // Used for spatial merging candidates in current frame |
181 | | // and for deriving interSplitFlag in decoding. |
182 | | |
183 | | uint8_t ctDepth : 2; // [0:3]? (for CTB size 64: 0:64, 1:32, 2:16, 3:8) |
184 | | // Used for decoding/encoding split_cu flag. |
185 | | |
186 | | // --- byte boundary --- |
187 | | uint8_t PredMode : 2; // (enum PredMode) [0;2] must be saved for past images |
188 | | // Used in motion decoding. |
189 | | uint8_t pcm_flag : 1; // Stored for intra-prediction / SAO |
190 | | uint8_t cu_transquant_bypass : 1; // Stored for SAO |
191 | | // note: 4 bits left |
192 | | |
193 | | // --- byte boundary --- |
194 | | int8_t QP_Y; // Stored for QP prediction |
195 | | }; |
196 | | |
197 | | |
198 | | |
199 | | |
200 | | struct de265_image { |
201 | | de265_image(); |
202 | | ~de265_image(); |
203 | | |
204 | | |
205 | | de265_error alloc_image(int w,int h, de265_chroma c, |
206 | | std::shared_ptr<const seq_parameter_set> sps, |
207 | | bool allocMetadata, |
208 | | decoder_context* dctx, |
209 | | //class encoder_context* ectx, |
210 | | de265_PTS pts, void* user_data, |
211 | | bool useCustomAllocFunctions); |
212 | | |
213 | | //de265_error alloc_encoder_data(const seq_parameter_set* sps); |
214 | | |
215 | 0 | bool is_allocated() const { return pixels[0] != nullptr; } |
216 | | |
217 | | void release(); |
218 | | |
219 | | void set_headers(std::shared_ptr<video_parameter_set> _vps, |
220 | | std::shared_ptr<seq_parameter_set> _sps, |
221 | 6.54k | std::shared_ptr<pic_parameter_set> _pps) { |
222 | 6.54k | vps = _vps; |
223 | 6.54k | sps = _sps; |
224 | 6.54k | pps = _pps; |
225 | 6.54k | } |
226 | | |
227 | | void fill_image(int y,int u,int v); |
228 | | void fill_plane(int channel, int value); |
229 | | de265_error copy_image(const de265_image* src); |
230 | | void copy_lines_from(const de265_image* src, int first, int end); |
231 | | void exchange_pixel_data_with(de265_image&); |
232 | | |
233 | 7.34k | uint32_t get_ID() const { return ID; } |
234 | | |
235 | | |
236 | 1.87M | /* */ uint8_t* get_image_plane(int cIdx) { return pixels[cIdx]; } |
237 | 19.3M | const uint8_t* get_image_plane(int cIdx) const { return pixels[cIdx]; } |
238 | | |
239 | | void set_image_plane(int cIdx, uint8_t* mem, ptrdiff_t stride, void *userdata); |
240 | | |
241 | | uint8_t* get_image_plane_at_pos(int cIdx, int xpos,int ypos) |
242 | 0 | { |
243 | 0 | ptrdiff_t stride = get_image_stride(cIdx); |
244 | 0 | return pixels[cIdx] + xpos + ypos*stride; |
245 | 0 | } |
246 | | |
247 | | |
248 | | /// xpos;ypos in actual plane resolution |
249 | | template <class pixel_t> |
250 | | pixel_t* get_image_plane_at_pos_NEW(int cIdx, int xpos,int ypos) |
251 | 51.1M | { |
252 | 51.1M | ptrdiff_t stride = get_image_stride(cIdx); |
253 | 51.1M | return (pixel_t*)(pixels[cIdx] + (xpos + ypos*stride)*sizeof(pixel_t)); |
254 | 51.1M | } unsigned short* de265_image::get_image_plane_at_pos_NEW<unsigned short>(int, int, int) Line | Count | Source | 251 | 4.61M | { | 252 | 4.61M | ptrdiff_t stride = get_image_stride(cIdx); | 253 | 4.61M | return (pixel_t*)(pixels[cIdx] + (xpos + ypos*stride)*sizeof(pixel_t)); | 254 | 4.61M | } |
unsigned char* de265_image::get_image_plane_at_pos_NEW<unsigned char>(int, int, int) Line | Count | Source | 251 | 46.5M | { | 252 | 46.5M | ptrdiff_t stride = get_image_stride(cIdx); | 253 | 46.5M | return (pixel_t*)(pixels[cIdx] + (xpos + ypos*stride)*sizeof(pixel_t)); | 254 | 46.5M | } |
|
255 | | |
256 | | const uint8_t* get_image_plane_at_pos(int cIdx, int xpos,int ypos) const |
257 | 0 | { |
258 | 0 | ptrdiff_t stride = get_image_stride(cIdx); |
259 | 0 | return pixels[cIdx] + xpos + ypos*stride; |
260 | 0 | } |
261 | | |
262 | | void* get_image_plane_at_pos_any_depth(int cIdx, int xpos,int ypos) |
263 | 2.75M | { |
264 | 2.75M | ptrdiff_t stride = get_image_stride(cIdx); |
265 | 2.75M | return pixels[cIdx] + ((xpos + ypos*stride) << bpp_shift[cIdx]); |
266 | 2.75M | } |
267 | | |
268 | | const void* get_image_plane_at_pos_any_depth(int cIdx, int xpos,int ypos) const |
269 | 0 | { |
270 | 0 | ptrdiff_t stride = get_image_stride(cIdx); |
271 | 0 | return pixels[cIdx] + ((xpos + ypos*stride) << bpp_shift[cIdx]); |
272 | 0 | } |
273 | | |
274 | | /* Number of pixels in one row (not number of bytes). |
275 | | */ |
276 | | ptrdiff_t get_image_stride(int cIdx) const |
277 | 100M | { |
278 | 100M | if (cIdx==0) return stride; |
279 | 40.2M | else return chroma_stride; |
280 | 100M | } |
281 | | |
282 | 1.04M | ptrdiff_t get_luma_stride() const { return stride; } |
283 | 2.09M | ptrdiff_t get_chroma_stride() const { return chroma_stride; } |
284 | | |
285 | 1.56M | int get_width (int cIdx=0) const { return cIdx==0 ? width : chroma_width; } |
286 | 1.56M | int get_height(int cIdx=0) const { return cIdx==0 ? height : chroma_height; } |
287 | | |
288 | 7.11M | de265_chroma get_chroma_format() const { return chroma_format; } |
289 | | |
290 | 59.3M | int get_bit_depth(int cIdx) const { |
291 | 59.3M | if (cIdx==0) return sps->BitDepth_Y; |
292 | 25.5M | else return sps->BitDepth_C; |
293 | 59.3M | } |
294 | | |
295 | 62.1k | int get_bytes_per_pixel(int cIdx) const { |
296 | 62.1k | return (get_bit_depth(cIdx)+7)/8; |
297 | 62.1k | } |
298 | | |
299 | 30.5M | bool high_bit_depth(int cIdx) const { |
300 | 30.5M | return get_bit_depth(cIdx)>8; |
301 | 30.5M | } |
302 | | |
303 | 8.05k | bool can_be_released() const { return PicOutputFlag==false && PicState==UnusedForReference; } |
304 | | |
305 | | |
306 | 6.60k | void add_slice_segment_header(slice_segment_header* shdr) { |
307 | 6.60k | shdr->slice_index = slices.size(); |
308 | 6.60k | slices.push_back(shdr); |
309 | 6.60k | } |
310 | | |
311 | | |
312 | | bool available_zscan(int xCurr,int yCurr, int xN,int yN) const; |
313 | | |
314 | | bool available_pred_blk(int xC,int yC, int nCbS, |
315 | | int xP, int yP, int nPbW, int nPbH, int partIdx, |
316 | | int xN,int yN) const; |
317 | | |
318 | | |
319 | | static de265_image_allocation default_image_allocation; |
320 | | |
321 | 0 | void printBlk(const char* title, int x0,int y0,int blkSize,int cIdx) const { |
322 | 0 | ::printBlk(title, get_image_plane_at_pos(cIdx,x0,y0), |
323 | 0 | blkSize, get_image_stride(cIdx)); |
324 | 0 | } |
325 | | |
326 | | private: |
327 | | uint32_t ID = std::numeric_limits<uint32_t>::max(); |
328 | | |
329 | | uint8_t* pixels[3] = { nullptr, nullptr, nullptr }; |
330 | | uint8_t bpp_shift[3] = {}; // 0 for 8 bit, 1 for 16 bit |
331 | | |
332 | | de265_chroma chroma_format = de265_chroma_mono; |
333 | | |
334 | | int width = 0, height = 0; // size in luma pixels |
335 | | |
336 | | int chroma_width = 0, chroma_height = 0; |
337 | | ptrdiff_t stride = 0, chroma_stride = 0; |
338 | | |
339 | | public: |
340 | | uint8_t BitDepth_Y = 0, BitDepth_C = 0; |
341 | | uint8_t SubWidthC = 0, SubHeightC = 0; |
342 | | std::vector<slice_segment_header*> slices; |
343 | | |
344 | | public: |
345 | | |
346 | | // --- conformance cropping window --- |
347 | | |
348 | | uint8_t* pixels_confwin[3] = { nullptr, nullptr, nullptr }; |
349 | | |
350 | | int width_confwin = 0, height_confwin = 0; |
351 | | int chroma_width_confwin = 0, chroma_height_confwin = 0; |
352 | | |
353 | | // --- decoding info --- |
354 | | |
355 | | // If PicOutputFlag==false && PicState==UnusedForReference, image buffer is free. |
356 | | |
357 | | int picture_order_cnt_lsb = -1; // undefined |
358 | | int PicOrderCntVal = -1; // undefined |
359 | | PictureState PicState = UnusedForReference; |
360 | | bool PicOutputFlag = false; |
361 | | |
362 | | uint32_t removed_at_picture_id = 0; // picture not used, so we can assume it has been removed |
363 | | |
364 | 6.39k | const video_parameter_set& get_vps() const { return *vps; } |
365 | 187M | const seq_parameter_set& get_sps() const { return *sps; } |
366 | 103M | const pic_parameter_set& get_pps() const { return *pps; } |
367 | | |
368 | 6.43k | bool has_vps() const { return vps != nullptr; } |
369 | 0 | bool has_sps() const { return sps != nullptr; } |
370 | 0 | bool has_pps() const { return pps != nullptr; } |
371 | | |
372 | 4.44k | std::shared_ptr<const seq_parameter_set> get_shared_sps() { return sps; } |
373 | | |
374 | | //std::shared_ptr<const seq_parameter_set> get_shared_sps() const { return sps; } |
375 | | //std::shared_ptr<const pic_parameter_set> get_shared_pps() const { return pps; } |
376 | | |
377 | | decoder_context* decctx = nullptr; |
378 | | |
379 | 773 | [[nodiscard]] uint32_t number_of_ctbs() const { return static_cast<uint32_t>(ctb_info.size()); } |
380 | | |
381 | | private: |
382 | | // The image also keeps a reference to VPS/SPS/PPS, because when decoding is delayed, |
383 | | // the currently active parameter sets in the decctx might already have been replaced |
384 | | // with new parameters. |
385 | | std::shared_ptr<const video_parameter_set> vps; |
386 | | std::shared_ptr<const seq_parameter_set> sps; // the SPS used for decoding this image |
387 | | std::shared_ptr<const pic_parameter_set> pps; // the PPS used for decoding this image |
388 | | |
389 | | MetaDataArray<CTB_info> ctb_info; |
390 | | MetaDataArray<CB_ref_info> cb_info; |
391 | | MetaDataArray<PBMotion> pb_info; |
392 | | MetaDataArray<uint8_t> intraPredMode; |
393 | | MetaDataArray<uint8_t> intraPredModeC; |
394 | | MetaDataArray<uint8_t> tu_info; |
395 | | MetaDataArray<uint8_t> deblk_info; |
396 | | |
397 | | template<typename Func> |
398 | 20.4M | void set_cb_blk(int x, int y, int log2BlkWidth, Func setter) { |
399 | 20.4M | int cbX = x >> cb_info.log2unitSize; |
400 | 20.4M | int cbY = y >> cb_info.log2unitSize; |
401 | 20.4M | int width = 1 << (log2BlkWidth - cb_info.log2unitSize); |
402 | 42.9M | for (int cby=cbY;cby<cbY+width;cby++) |
403 | 53.4M | for (int cbx=cbX;cbx<cbX+width;cbx++) |
404 | 30.9M | setter(cb_info[ cbx + cby*cb_info.width_in_units ]); |
405 | 20.4M | } void de265_image::set_cb_blk<de265_image::set_pred_mode(int, int, int, PredMode)::{lambda(CB_ref_info&)#1}>(int, int, int, de265_image::set_pred_mode(int, int, int, PredMode)::{lambda(CB_ref_info&)#1})Line | Count | Source | 398 | 4.47M | void set_cb_blk(int x, int y, int log2BlkWidth, Func setter) { | 399 | 4.47M | int cbX = x >> cb_info.log2unitSize; | 400 | 4.47M | int cbY = y >> cb_info.log2unitSize; | 401 | 4.47M | int width = 1 << (log2BlkWidth - cb_info.log2unitSize); | 402 | 9.40M | for (int cby=cbY;cby<cbY+width;cby++) | 403 | 11.7M | for (int cbx=cbX;cbx<cbX+width;cbx++) | 404 | 6.79M | setter(cb_info[ cbx + cby*cb_info.width_in_units ]); | 405 | 4.47M | } |
void de265_image::set_cb_blk<de265_image::set_pcm_flag(int, int, int, unsigned char)::{lambda(CB_ref_info&)#1}>(int, int, int, de265_image::set_pcm_flag(int, int, int, unsigned char)::{lambda(CB_ref_info&)#1})Line | Count | Source | 398 | 372 | void set_cb_blk(int x, int y, int log2BlkWidth, Func setter) { | 399 | 372 | int cbX = x >> cb_info.log2unitSize; | 400 | 372 | int cbY = y >> cb_info.log2unitSize; | 401 | 372 | int width = 1 << (log2BlkWidth - cb_info.log2unitSize); | 402 | 793 | for (int cby=cbY;cby<cbY+width;cby++) | 403 | 970 | for (int cbx=cbX;cbx<cbX+width;cbx++) | 404 | 549 | setter(cb_info[ cbx + cby*cb_info.width_in_units ]); | 405 | 372 | } |
void de265_image::set_cb_blk<de265_image::set_cu_transquant_bypass(int, int, int, unsigned char)::{lambda(CB_ref_info&)#1}>(int, int, int, de265_image::set_cu_transquant_bypass(int, int, int, unsigned char)::{lambda(CB_ref_info&)#1})Line | Count | Source | 398 | 803k | void set_cb_blk(int x, int y, int log2BlkWidth, Func setter) { | 399 | 803k | int cbX = x >> cb_info.log2unitSize; | 400 | 803k | int cbY = y >> cb_info.log2unitSize; | 401 | 803k | int width = 1 << (log2BlkWidth - cb_info.log2unitSize); | 402 | 1.70M | for (int cby=cbY;cby<cbY+width;cby++) | 403 | 2.20M | for (int cbx=cbX;cbx<cbX+width;cbx++) | 404 | 1.31M | setter(cb_info[ cbx + cby*cb_info.width_in_units ]); | 405 | 803k | } |
void de265_image::set_cb_blk<de265_image::set_log2CbSize(int, int, int, bool)::{lambda(CB_ref_info&)#1}>(int, int, int, de265_image::set_log2CbSize(int, int, int, bool)::{lambda(CB_ref_info&)#1})Line | Count | Source | 398 | 4.48M | void set_cb_blk(int x, int y, int log2BlkWidth, Func setter) { | 399 | 4.48M | int cbX = x >> cb_info.log2unitSize; | 400 | 4.48M | int cbY = y >> cb_info.log2unitSize; | 401 | 4.48M | int width = 1 << (log2BlkWidth - cb_info.log2unitSize); | 402 | 9.42M | for (int cby=cbY;cby<cbY+width;cby++) | 403 | 11.7M | for (int cbx=cbX;cbx<cbX+width;cbx++) | 404 | 6.80M | setter(cb_info[ cbx + cby*cb_info.width_in_units ]); | 405 | 4.48M | } |
void de265_image::set_cb_blk<de265_image::set_ctDepth(int, int, int, int)::{lambda(CB_ref_info&)#1}>(int, int, int, de265_image::set_ctDepth(int, int, int, int)::{lambda(CB_ref_info&)#1})Line | Count | Source | 398 | 4.49M | void set_cb_blk(int x, int y, int log2BlkWidth, Func setter) { | 399 | 4.49M | int cbX = x >> cb_info.log2unitSize; | 400 | 4.49M | int cbY = y >> cb_info.log2unitSize; | 401 | 4.49M | int width = 1 << (log2BlkWidth - cb_info.log2unitSize); | 402 | 9.43M | for (int cby=cbY;cby<cbY+width;cby++) | 403 | 11.7M | for (int cbx=cbX;cbx<cbX+width;cbx++) | 404 | 6.80M | setter(cb_info[ cbx + cby*cb_info.width_in_units ]); | 405 | 4.49M | } |
void de265_image::set_cb_blk<de265_image::set_QPY(int, int, int, int)::{lambda(CB_ref_info&)#1}>(int, int, int, de265_image::set_QPY(int, int, int, int)::{lambda(CB_ref_info&)#1})Line | Count | Source | 398 | 6.18M | void set_cb_blk(int x, int y, int log2BlkWidth, Func setter) { | 399 | 6.18M | int cbX = x >> cb_info.log2unitSize; | 400 | 6.18M | int cbY = y >> cb_info.log2unitSize; | 401 | 6.18M | int width = 1 << (log2BlkWidth - cb_info.log2unitSize); | 402 | 12.9M | for (int cby=cbY;cby<cbY+width;cby++) | 403 | 16.0M | for (int cbx=cbX;cbx<cbX+width;cbx++) | 404 | 9.25M | setter(cb_info[ cbx + cby*cb_info.width_in_units ]); | 405 | 6.18M | } |
|
406 | | |
407 | 4.51M | void clear_tb_blk(int x, int y, int log2BlkWidth) { |
408 | 4.51M | int tuX = x >> tu_info.log2unitSize; |
409 | 4.51M | int tuY = y >> tu_info.log2unitSize; |
410 | 4.51M | int width = 1 << (log2BlkWidth - tu_info.log2unitSize); |
411 | 14.3M | for (int tuy=tuY;tuy<tuY+width;tuy++) |
412 | 37.0M | for (int tux=tuX;tux<tuX+width;tux++) |
413 | 27.1M | tu_info[ tux + tuy*tu_info.width_in_units ] = 0; |
414 | 4.51M | } |
415 | | |
416 | | public: |
417 | | // --- meta information --- |
418 | | |
419 | | de265_PTS pts = 0; |
420 | | void* user_data = nullptr; |
421 | | void* plane_user_data[3] = { nullptr, nullptr, nullptr }; |
422 | | de265_image_allocation image_allocation_functions; // the functions used for memory allocation |
423 | | |
424 | | /* |
425 | | void (*encoder_image_release_func)(en265_encoder_context*, |
426 | | de265_image*, |
427 | | void* userdata); |
428 | | */ |
429 | | |
430 | | uint8_t integrity = INTEGRITY_NOT_DECODED; /* Whether an error occurred while the image was decoded. |
431 | | When generated, this is initialized to INTEGRITY_CORRECT, |
432 | | and changed on decoding errors. |
433 | | */ |
434 | | bool sei_hash_check_result = false; |
435 | | |
436 | | nal_header nal_hdr; |
437 | | |
438 | | // --- multi core --- |
439 | | |
440 | | de265_progress_lock* ctb_progress = nullptr; // ctb_info_size |
441 | | |
442 | 6.43k | void mark_all_CTB_progress(int progress) { |
443 | 605k | for (int i=0;i<ctb_info.data_size;i++) { |
444 | 599k | ctb_progress[i].set_progress(progress); |
445 | 599k | } |
446 | 6.43k | } |
447 | | |
448 | | |
449 | | void thread_start(int nThreads); |
450 | | void thread_run(const thread_task*); |
451 | | void thread_blocks(); |
452 | | void thread_unblocks(); |
453 | | /* NOTE: you should not access any data in the thread_task after |
454 | | calling this, as this function may unlock other threads that |
455 | | will push this image to the output queue and free all decoder data. */ |
456 | | void thread_finishes(const thread_task*); |
457 | | |
458 | | void wait_for_progress(thread_task* task, int ctbx,int ctby, int progress); |
459 | | void wait_for_progress(thread_task* task, int ctbAddrRS, int progress); |
460 | | |
461 | | void wait_for_completion(); // block until image is decoded by background threads |
462 | | bool debug_is_completed() const; |
463 | 2.48k | int num_threads_active() const { return nThreadsRunning + nThreadsBlocked; } // for debug only |
464 | | |
465 | | //private: |
466 | | int nThreadsQueued = 0; |
467 | | int nThreadsRunning = 0; |
468 | | int nThreadsBlocked = 0; |
469 | | int nThreadsFinished = 0; |
470 | | int nThreadsTotal = 0; |
471 | | |
472 | | // ALIGNED_8(de265_sync_int tasks_pending); // number of tasks pending to complete decoding |
473 | | std::mutex mutex; |
474 | | std::condition_variable finished_cond; |
475 | | |
476 | | public: |
477 | | |
478 | | /* Clear all CTB/CB/PB decoding data of this image. |
479 | | All CTB's processing states are set to 'unprocessed'. |
480 | | */ |
481 | | void clear_metadata(); |
482 | | |
483 | | |
484 | | // --- CB metadata access --- |
485 | | |
486 | | void set_pred_mode(int x,int y, int log2BlkWidth, PredMode mode) |
487 | 4.47M | { |
488 | 6.79M | set_cb_blk(x,y,log2BlkWidth, [mode](CB_ref_info& cb){ cb.PredMode = mode; }); |
489 | 4.47M | } |
490 | | |
491 | | void fill_pred_mode(PredMode mode) |
492 | 4.87k | { |
493 | 3.15M | for (int i=0;i<cb_info.data_size;i++) |
494 | 3.15M | { cb_info[i].PredMode = MODE_INTRA; } |
495 | 4.87k | } |
496 | | |
497 | | PredMode get_pred_mode(int x,int y) const |
498 | 132M | { |
499 | 132M | return (PredMode)cb_info.get(x,y).PredMode; |
500 | 132M | } |
501 | | |
502 | | uint8_t get_cu_skip_flag(int x,int y) const |
503 | 1.37M | { |
504 | 1.37M | return get_pred_mode(x,y)==MODE_SKIP; |
505 | 1.37M | } |
506 | | |
507 | | void set_pcm_flag(int x,int y, int log2BlkWidth, uint8_t value=1) |
508 | 372 | { |
509 | 549 | set_cb_blk(x,y,log2BlkWidth, [value](CB_ref_info& cb){ cb.pcm_flag = value; }); |
510 | | |
511 | | // TODO: in the encoder, we somewhere have to clear this |
512 | 372 | ctb_info.get(x,y).has_pcm_or_cu_transquant_bypass = true; |
513 | 372 | } |
514 | | |
515 | | int get_pcm_flag(int x,int y) const |
516 | 23.5M | { |
517 | 23.5M | return cb_info.get(x,y).pcm_flag; |
518 | 23.5M | } |
519 | | |
520 | | void set_cu_transquant_bypass(int x,int y, int log2BlkWidth, uint8_t value=1) |
521 | 803k | { |
522 | 1.31M | set_cb_blk(x,y,log2BlkWidth, [value](CB_ref_info& cb){ cb.cu_transquant_bypass = value; }); |
523 | | |
524 | | // TODO: in the encoder, we somewhere have to clear this |
525 | 803k | ctb_info.get(x,y).has_pcm_or_cu_transquant_bypass = true; |
526 | 803k | } |
527 | | |
528 | | int get_cu_transquant_bypass(int x,int y) const |
529 | 74.5M | { |
530 | 74.5M | return cb_info.get(x,y).cu_transquant_bypass; |
531 | 74.5M | } |
532 | | |
533 | | void set_log2CbSize(int x0, int y0, int log2CbSize, bool fill) |
534 | 4.48M | { |
535 | | // In theory, we could assume that remaining cb_info blocks are initialized to zero. |
536 | | // But in corrupted streams, slices may overlap and set contradicting log2CbSizes. |
537 | | // We also need this for encoding. |
538 | 4.48M | if (fill) { |
539 | 6.79M | set_cb_blk(x0,y0,log2CbSize, [](CB_ref_info& cb){ cb.log2CbSize = 0; }); |
540 | 4.48M | } |
541 | | |
542 | 4.48M | cb_info.get(x0,y0).log2CbSize = log2CbSize; |
543 | 4.48M | } |
544 | | |
545 | | int get_log2CbSize(int x0, int y0) const |
546 | 6.18M | { |
547 | 6.18M | return cb_info.get(x0,y0).log2CbSize; |
548 | 6.18M | } |
549 | | |
550 | | // coordinates in CB units |
551 | | int get_log2CbSize_cbUnits(int xCb, int yCb) const |
552 | 10.2M | { |
553 | 10.2M | return cb_info[ xCb + yCb*cb_info.width_in_units ].log2CbSize; |
554 | 10.2M | } |
555 | | |
556 | | void set_PartMode(int x,int y, PartMode mode) |
557 | 4.47M | { |
558 | 4.47M | cb_info.get(x,y).PartMode = mode; |
559 | 4.47M | } |
560 | | |
561 | | PartMode get_PartMode(int x,int y) const |
562 | 16.0M | { |
563 | 16.0M | return (PartMode)cb_info.get(x,y).PartMode; |
564 | 16.0M | } |
565 | | |
566 | | void set_ctDepth(int x,int y, int log2BlkWidth, int depth) |
567 | 4.49M | { |
568 | 6.80M | set_cb_blk(x,y,log2BlkWidth, [depth](CB_ref_info& cb){ cb.ctDepth = depth; }); |
569 | 4.49M | } |
570 | | |
571 | | int get_ctDepth(int x,int y) const |
572 | 2.84M | { |
573 | 2.84M | return cb_info.get(x,y).ctDepth; |
574 | 2.84M | } |
575 | | |
576 | | void set_QPY(int x,int y, int log2BlkWidth, int QP_Y) |
577 | 6.18M | { |
578 | 9.25M | set_cb_blk(x,y,log2BlkWidth, [QP_Y](CB_ref_info& cb){ cb.QP_Y = QP_Y; }); |
579 | 6.18M | } |
580 | | |
581 | | int get_QPY(int x0,int y0) const |
582 | 54.4M | { |
583 | 54.4M | return cb_info.get(x0,y0).QP_Y; |
584 | 54.4M | } |
585 | | |
586 | | // --- TU metadata access --- |
587 | | |
588 | | void set_split_transform_flag(int x0,int y0,int trafoDepth) |
589 | 1.83M | { |
590 | 1.83M | tu_info.get(x0,y0) |= (1<<trafoDepth); |
591 | 1.83M | } |
592 | | |
593 | | void clear_split_transform_flags(int x0,int y0,int log2CbSize) |
594 | 4.51M | { |
595 | 4.51M | clear_tb_blk(x0,y0,log2CbSize); |
596 | 4.51M | } |
597 | | |
598 | | int get_split_transform_flag(int x0,int y0,int trafoDepth) const |
599 | 11.7M | { |
600 | 11.7M | return (tu_info.get(x0,y0) & (1<<trafoDepth)); |
601 | 11.7M | } |
602 | | |
603 | | void set_nonzero_coefficient(int x,int y, int log2TrafoSize) |
604 | 8.62M | { |
605 | 8.62M | const int tuX = x >> tu_info.log2unitSize; |
606 | 8.62M | const int tuY = y >> tu_info.log2unitSize; |
607 | 8.62M | const int width = 1 << (log2TrafoSize - tu_info.log2unitSize); |
608 | | |
609 | 19.6M | for (int tuy=tuY;tuy<tuY+width;tuy++) |
610 | 28.9M | for (int tux=tuX;tux<tuX+width;tux++) |
611 | 17.8M | { |
612 | 17.8M | tu_info[ tux + tuy*tu_info.width_in_units ] |= TU_FLAG_NONZERO_COEFF; |
613 | 17.8M | } |
614 | 8.62M | } |
615 | | |
616 | | int get_nonzero_coefficient(int x,int y) const |
617 | 7.16M | { |
618 | 7.16M | return tu_info.get(x,y) & TU_FLAG_NONZERO_COEFF; |
619 | 7.16M | } |
620 | | |
621 | | |
622 | | // --- intraPredMode metadata access --- |
623 | | |
624 | | IntraPredMode get_IntraPredMode(int x,int y) const |
625 | 31.6M | { |
626 | 31.6M | uint8_t ipm = intraPredMode.get(x,y); |
627 | | |
628 | | // sanitize values if IPM is uninitialized (because of earlier read error) |
629 | 31.6M | if (ipm > 34) { |
630 | 0 | ipm = 0; |
631 | 0 | } |
632 | | |
633 | 31.6M | return static_cast<IntraPredMode>(ipm); |
634 | 31.6M | } |
635 | | |
636 | | IntraPredMode get_IntraPredMode_atIndex(int idx) const |
637 | 15.7M | { |
638 | 15.7M | uint8_t ipm = intraPredMode[idx]; |
639 | 15.7M | if (ipm > 34) { ipm = 0; } |
640 | 15.7M | return static_cast<IntraPredMode>(ipm); |
641 | 15.7M | } |
642 | | |
643 | | void set_IntraPredMode(int PUidx,int log2blkSize, IntraPredMode mode) |
644 | 8.63M | { |
645 | 8.63M | int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize); |
646 | | |
647 | 19.7M | for (int y=0;y<pbSize;y++) |
648 | 30.4M | for (int x=0;x<pbSize;x++) |
649 | 19.2M | intraPredMode[PUidx + x + y*intraPredMode.width_in_units] = mode; |
650 | 8.63M | } |
651 | | |
652 | | void set_IntraPredMode(int x0,int y0,int log2blkSize, |
653 | | IntraPredMode mode) |
654 | 0 | { |
655 | 0 | int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize); |
656 | 0 | int PUidx = (x0>>sps->Log2MinPUSize) + (y0>>sps->Log2MinPUSize)*sps->PicWidthInMinPUs; |
657 | 0 |
|
658 | 0 | for (int y=0;y<pbSize;y++) |
659 | 0 | for (int x=0;x<pbSize;x++) { |
660 | 0 | assert(x < sps->PicWidthInMinPUs); |
661 | 0 | assert(y < sps->PicHeightInMinPUs); |
662 | 0 |
|
663 | 0 | int idx = PUidx + x + y*intraPredMode.width_in_units; |
664 | 0 | assert(idx<intraPredMode.data_size); |
665 | 0 | intraPredMode[idx] = mode; |
666 | 0 | } |
667 | 0 | } |
668 | | |
669 | | |
670 | | IntraPredMode get_IntraPredModeC(int x,int y) const |
671 | 13.8M | { |
672 | 13.8M | return (IntraPredMode)(intraPredModeC.get(x,y) & 0x3f); |
673 | 13.8M | } |
674 | | |
675 | | bool is_IntraPredModeC_Mode4(int x,int y) const |
676 | 0 | { |
677 | 0 | return intraPredModeC.get(x,y) & 0x80; |
678 | 0 | } |
679 | | |
680 | | void set_IntraPredModeC(int x0,int y0,int log2blkSize, IntraPredMode mode, |
681 | | bool is_mode4) |
682 | 3.73M | { |
683 | 3.73M | uint8_t combinedValue = mode; |
684 | 3.73M | if (is_mode4) combinedValue |= 0x80; |
685 | | |
686 | 3.73M | int pbSize = 1<<(log2blkSize - intraPredMode.log2unitSize); |
687 | 3.73M | int PUidx = (x0>>sps->Log2MinPUSize) + (y0>>sps->Log2MinPUSize)*sps->PicWidthInMinPUs; |
688 | | |
689 | 11.6M | for (int y=0;y<pbSize;y++) |
690 | 27.2M | for (int x=0;x<pbSize;x++) { |
691 | 19.3M | assert(x<sps->PicWidthInMinPUs); |
692 | 19.3M | assert(y<sps->PicHeightInMinPUs); |
693 | | |
694 | 19.3M | int idx = PUidx + x + y*intraPredModeC.width_in_units; |
695 | 19.3M | assert(idx<intraPredModeC.data_size); |
696 | 19.3M | intraPredModeC[idx] = combinedValue; |
697 | 19.3M | } |
698 | 3.73M | } |
699 | | |
700 | | |
701 | | |
702 | | // --- CTB metadata access --- |
703 | | |
704 | | // address of first CTB in slice |
705 | | void set_SliceAddrRS(int ctbX, int ctbY, int SliceAddrRS) |
706 | 385k | { |
707 | 385k | if (ctbX >= ctb_info.width_in_units || ctbY >= ctb_info.height_in_units) { |
708 | 0 | return; |
709 | 0 | } |
710 | | |
711 | 385k | int idx = ctbX + ctbY*ctb_info.width_in_units; |
712 | 385k | ctb_info[idx].SliceAddrRS = SliceAddrRS; |
713 | 385k | } |
714 | | |
715 | | int get_SliceAddrRS(int ctbX, int ctbY) const |
716 | 103M | { |
717 | 103M | return ctb_info[ctbX + ctbY*ctb_info.width_in_units].SliceAddrRS; |
718 | 103M | } |
719 | | |
720 | | int get_SliceAddrRS_atCtbRS(int ctbRS) const |
721 | 22.9M | { |
722 | 22.9M | return ctb_info[ctbRS].SliceAddrRS; |
723 | 22.9M | } |
724 | | |
725 | | |
726 | | void set_SliceHeaderIndex(int x, int y, int SliceHeaderIndex) |
727 | 385k | { |
728 | 385k | ctb_info.get(x,y).SliceHeaderIndex = SliceHeaderIndex; |
729 | 385k | } |
730 | | |
731 | | uint16_t get_SliceHeaderIndex(int x, int y) const |
732 | 39.9M | { |
733 | 39.9M | return ctb_info.get(x,y).SliceHeaderIndex; |
734 | 39.9M | } |
735 | | |
736 | | uint16_t get_SliceHeaderIndexCtb(int ctbX, int ctbY) const |
737 | 332k | { |
738 | 332k | return ctb_info[ctbX + ctbY*ctb_info.width_in_units].SliceHeaderIndex; |
739 | 332k | } |
740 | | |
741 | | uint16_t get_SliceHeaderIndex_atIndex(int ctb) const |
742 | 8 | { |
743 | 8 | return ctb_info[ctb].SliceHeaderIndex; |
744 | 8 | } |
745 | | |
746 | | bool is_SliceHeader_available(int x,int y) const |
747 | 6.36M | { |
748 | 6.36M | uint16_t idx = ctb_info.get(x,y).SliceHeaderIndex; |
749 | 6.36M | return idx < slices.size(); |
750 | 6.36M | } |
751 | | |
752 | | slice_segment_header* get_SliceHeader(int x, int y) |
753 | 16.1M | { |
754 | 16.1M | uint16_t idx = get_SliceHeaderIndex(x,y); |
755 | 16.1M | if (idx >= slices.size()) { return nullptr; } |
756 | 16.1M | return slices[idx]; |
757 | 16.1M | } |
758 | | |
759 | | slice_segment_header* get_SliceHeaderCtb(int ctbX, int ctbY) |
760 | 332k | { |
761 | 332k | uint16_t idx = get_SliceHeaderIndexCtb(ctbX,ctbY); |
762 | 332k | if (idx >= slices.size()) { return nullptr; } |
763 | 332k | return slices[idx]; |
764 | 332k | } |
765 | | |
766 | | const slice_segment_header* get_SliceHeaderCtb(int ctbX, int ctbY) const |
767 | 0 | { |
768 | 0 | uint16_t idx = get_SliceHeaderIndexCtb(ctbX,ctbY); |
769 | 0 | if (idx >= slices.size()) { return nullptr; } |
770 | 0 | return slices[idx]; |
771 | 0 | } |
772 | | |
773 | | void set_sao_info(int ctbX,int ctbY,const sao_info* saoinfo) |
774 | 291k | { |
775 | 291k | sao_info* sao = &ctb_info[ctbX + ctbY*ctb_info.width_in_units].saoInfo; |
776 | | |
777 | 291k | memcpy(sao, |
778 | 291k | saoinfo, |
779 | 291k | sizeof(sao_info)); |
780 | 291k | } |
781 | | |
782 | | const sao_info* get_sao_info(int ctbX,int ctbY) const |
783 | 950k | { |
784 | 950k | return &ctb_info[ctbX + ctbY*ctb_info.width_in_units].saoInfo; |
785 | 950k | } |
786 | | |
787 | | |
788 | | void set_CtbDeblockFlag(int ctbX, int ctbY, bool flag) |
789 | 39.9k | { |
790 | 39.9k | int idx = ctbX + ctbY*ctb_info.width_in_units; |
791 | 39.9k | ctb_info[idx].deblock = flag; |
792 | 39.9k | } |
793 | | |
794 | | bool get_CtbDeblockFlag(int ctbX, int ctbY) const |
795 | 39.9k | { |
796 | 39.9k | return ctb_info[ctbX + ctbY*ctb_info.width_in_units].deblock; |
797 | 39.9k | } |
798 | | |
799 | | |
800 | | bool get_CTB_has_pcm_or_cu_transquant_bypass(int ctbX,int ctbY) const |
801 | 409k | { |
802 | 409k | int idx = ctbX + ctbY*ctb_info.width_in_units; |
803 | 409k | return ctb_info[idx].has_pcm_or_cu_transquant_bypass; |
804 | 409k | } |
805 | | |
806 | | |
807 | | |
808 | | // --- DEBLK metadata access --- |
809 | | |
810 | 235k | int get_deblk_width() const { return deblk_info.width_in_units; } |
811 | 240k | int get_deblk_height() const { return deblk_info.height_in_units; } |
812 | | |
813 | | void set_deblk_flags(int x0,int y0, uint8_t flags) |
814 | 55.8M | { |
815 | 55.8M | const int xd = x0/4; |
816 | 55.8M | const int yd = y0/4; |
817 | | |
818 | 55.8M | if (xd<deblk_info.width_in_units && |
819 | 55.8M | yd<deblk_info.height_in_units) { |
820 | 55.8M | deblk_info[xd + yd*deblk_info.width_in_units] |= flags; |
821 | 55.8M | } |
822 | 55.8M | } |
823 | | |
824 | | uint8_t get_deblk_flags(int x0,int y0) const |
825 | 27.9M | { |
826 | 27.9M | const int xd = x0/4; |
827 | 27.9M | const int yd = y0/4; |
828 | | |
829 | 27.9M | return deblk_info[xd + yd*deblk_info.width_in_units]; |
830 | 27.9M | } |
831 | | |
832 | | void set_deblk_bS(int x0,int y0, uint8_t bS) |
833 | 27.9M | { |
834 | 27.9M | uint8_t* data = &deblk_info[x0/4 + y0/4*deblk_info.width_in_units]; |
835 | 27.9M | *data &= ~DEBLOCK_BS_MASK; |
836 | 27.9M | *data |= bS; |
837 | 27.9M | } |
838 | | |
839 | | uint8_t get_deblk_bS(int x0,int y0) const |
840 | 34.8M | { |
841 | 34.8M | return deblk_info[x0/4 + y0/4*deblk_info.width_in_units] & DEBLOCK_BS_MASK; |
842 | 34.8M | } |
843 | | |
844 | | |
845 | | // --- PB metadata access --- |
846 | | |
847 | | const PBMotion& get_mv_info(int x,int y) const |
848 | 7.96M | { |
849 | 7.96M | return pb_info.get(x,y); |
850 | 7.96M | } |
851 | | |
852 | | void set_mv_info(int x,int y, int nPbW,int nPbH, const PBMotion& mv); |
853 | | |
854 | | // --- value logging --- |
855 | | |
856 | | void printBlk(int x0,int y0, int cIdx, int log2BlkSize); |
857 | | }; |
858 | | |
859 | | |
860 | | #endif |