/src/libultrahdr/lib/include/ultrahdr/ultrahdrcommon.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2023 The Android Open Source Project |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #ifndef ULTRAHDR_ULTRAHDRCOMMON_H |
18 | | #define ULTRAHDR_ULTRAHDRCOMMON_H |
19 | | |
20 | | //#define LOG_NDEBUG 0 |
21 | | |
22 | | #ifdef UHDR_ENABLE_GLES |
23 | | #include <EGL/egl.h> |
24 | | #include <GLES3/gl3.h> |
25 | | #endif |
26 | | |
27 | | #include <cstdint> |
28 | | #include <deque> |
29 | | #include <map> |
30 | | #include <memory> |
31 | | #include <string> |
32 | | #include <vector> |
33 | | |
34 | | #include "ultrahdr_api.h" |
35 | | |
36 | | // =============================================================================================== |
37 | | // Function Macros |
38 | | // =============================================================================================== |
39 | | |
40 | | #ifdef __ANDROID__ |
41 | | |
42 | | #ifdef LOG_NDEBUG |
43 | | #include "android/log.h" |
44 | | |
45 | | #ifndef LOG_TAG |
46 | | #define LOG_TAG "UHDR" |
47 | | #endif |
48 | | |
49 | | #ifndef ALOGD |
50 | | #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) |
51 | | #endif |
52 | | |
53 | | #ifndef ALOGE |
54 | | #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) |
55 | | #endif |
56 | | |
57 | | #ifndef ALOGI |
58 | | #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) |
59 | | #endif |
60 | | |
61 | | #ifndef ALOGV |
62 | | #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) |
63 | | #endif |
64 | | |
65 | | #ifndef ALOGW |
66 | | #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) |
67 | | #endif |
68 | | |
69 | | #else |
70 | | |
71 | | #define ALOGD(...) ((void)0) |
72 | | #define ALOGE(...) ((void)0) |
73 | | #define ALOGI(...) ((void)0) |
74 | | #define ALOGV(...) ((void)0) |
75 | | #define ALOGW(...) ((void)0) |
76 | | |
77 | | #endif |
78 | | |
79 | | #else |
80 | | |
81 | | #ifdef LOG_NDEBUG |
82 | | #include <cstdio> |
83 | | |
84 | | #define ALOGD(...) \ |
85 | | do { \ |
86 | | fprintf(stderr, __VA_ARGS__); \ |
87 | | fprintf(stderr, "\n"); \ |
88 | | } while (0) |
89 | | |
90 | | #define ALOGE(...) \ |
91 | | do { \ |
92 | | fprintf(stderr, __VA_ARGS__); \ |
93 | | fprintf(stderr, "\n"); \ |
94 | | } while (0) |
95 | | |
96 | | #define ALOGI(...) \ |
97 | | do { \ |
98 | | fprintf(stdout, __VA_ARGS__); \ |
99 | | fprintf(stdout, "\n"); \ |
100 | | } while (0) |
101 | | |
102 | | #define ALOGV(...) \ |
103 | | do { \ |
104 | | fprintf(stdout, __VA_ARGS__); \ |
105 | | fprintf(stdout, "\n"); \ |
106 | | } while (0) |
107 | | |
108 | | #define ALOGW(...) \ |
109 | | do { \ |
110 | | fprintf(stderr, __VA_ARGS__); \ |
111 | | fprintf(stderr, "\n"); \ |
112 | | } while (0) |
113 | | |
114 | | #else |
115 | | |
116 | 338 | #define ALOGD(...) ((void)0) |
117 | 41.2k | #define ALOGE(...) ((void)0) |
118 | | #define ALOGI(...) ((void)0) |
119 | 76.8k | #define ALOGV(...) ((void)0) |
120 | 285 | #define ALOGW(...) ((void)0) |
121 | | |
122 | | #endif |
123 | | |
124 | | #endif |
125 | | |
126 | 51.6k | #define ALIGNM(x, m) ((((x) + ((m)-1)) / (m)) * (m)) |
127 | | |
128 | | #define UHDR_ERR_CHECK(x) \ |
129 | 375k | { \ |
130 | 375k | uhdr_error_info_t status = (x); \ |
131 | 375k | if (status.error_code != UHDR_CODEC_OK) { \ |
132 | 16.2k | return status; \ |
133 | 16.2k | } \ |
134 | 375k | } |
135 | | |
136 | | #if defined(_MSC_VER) |
137 | | #define FORCE_INLINE __forceinline |
138 | | #define INLINE __inline |
139 | | #else |
140 | | #define FORCE_INLINE __inline__ __attribute__((always_inline)) |
141 | | #define INLINE inline |
142 | | #endif |
143 | | |
144 | | // '__has_attribute' macro was introduced by clang. later picked up by gcc. |
145 | | // If not supported by the current toolchain, define it to zero. |
146 | | #ifndef __has_attribute |
147 | | #define __has_attribute(x) 0 |
148 | | #endif |
149 | | |
150 | | // Disables undefined behavior analysis for a function. |
151 | | // GCC 4.9+ uses __attribute__((no_sanitize_undefined)) |
152 | | // clang uses __attribute__((no_sanitize("undefined"))) |
153 | | #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409) |
154 | | #define UHDR_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined)) |
155 | | #elif __has_attribute(no_sanitize) |
156 | | #define UHDR_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined"))) |
157 | | #else |
158 | | #define UHDR_NO_SANITIZE_UNDEFINED |
159 | | #endif |
160 | | |
161 | | static const uhdr_error_info_t g_no_error = {UHDR_CODEC_OK, 0, ""}; |
162 | | |
163 | | namespace ultrahdr { |
164 | | |
165 | | // =============================================================================================== |
166 | | // Globals |
167 | | // =============================================================================================== |
168 | | extern const int kMinWidth, kMinHeight; |
169 | | extern const int kMaxWidth, kMaxHeight; |
170 | | |
171 | | // =============================================================================================== |
172 | | // Structure Definitions |
173 | | // =============================================================================================== |
174 | | |
175 | | /**\brief uhdr memory block */ |
176 | | typedef struct uhdr_memory_block { |
177 | | uhdr_memory_block(size_t capacity); |
178 | | |
179 | | std::unique_ptr<uint8_t[]> m_buffer; /**< data */ |
180 | | size_t m_capacity; /**< capacity */ |
181 | | } uhdr_memory_block_t; /**< alias for struct uhdr_memory_block */ |
182 | | |
183 | | /**\brief extended raw image descriptor */ |
184 | | typedef struct uhdr_raw_image_ext : uhdr_raw_image_t { |
185 | | uhdr_raw_image_ext(uhdr_img_fmt_t fmt, uhdr_color_gamut_t cg, uhdr_color_transfer_t ct, |
186 | | uhdr_color_range_t range, unsigned w, unsigned h, unsigned align_stride_to); |
187 | | |
188 | | private: |
189 | | std::unique_ptr<ultrahdr::uhdr_memory_block> m_block; |
190 | | } uhdr_raw_image_ext_t; /**< alias for struct uhdr_raw_image_ext */ |
191 | | |
192 | | /**\brief extended compressed image descriptor */ |
193 | | typedef struct uhdr_compressed_image_ext : uhdr_compressed_image_t { |
194 | | uhdr_compressed_image_ext(uhdr_color_gamut_t cg, uhdr_color_transfer_t ct, |
195 | | uhdr_color_range_t range, size_t sz); |
196 | | |
197 | | private: |
198 | | std::unique_ptr<ultrahdr::uhdr_memory_block> m_block; |
199 | | } uhdr_compressed_image_ext_t; /**< alias for struct uhdr_compressed_image_ext */ |
200 | | |
201 | | /*!\brief forward declaration for image effect descriptor */ |
202 | | typedef struct uhdr_effect_desc uhdr_effect_desc_t; |
203 | | |
204 | | /**\brief Gain map metadata. */ |
205 | | typedef struct uhdr_gainmap_metadata_ext : uhdr_gainmap_metadata { |
206 | 22.0k | uhdr_gainmap_metadata_ext() {} |
207 | | |
208 | 0 | uhdr_gainmap_metadata_ext(std::string ver) : version(ver) {} |
209 | | |
210 | | uhdr_gainmap_metadata_ext(uhdr_gainmap_metadata& metadata, std::string ver) |
211 | 0 | : uhdr_gainmap_metadata_ext(ver) { |
212 | 0 | std::copy(metadata.max_content_boost, metadata.max_content_boost + 3, max_content_boost); |
213 | 0 | std::copy(metadata.min_content_boost, metadata.min_content_boost + 3, min_content_boost); |
214 | 0 | std::copy(metadata.gamma, metadata.gamma + 3, gamma); |
215 | 0 | std::copy(metadata.offset_sdr, metadata.offset_sdr + 3, offset_sdr); |
216 | 0 | std::copy(metadata.offset_hdr, metadata.offset_hdr + 3, offset_hdr); |
217 | 0 | hdr_capacity_min = metadata.hdr_capacity_min; |
218 | 0 | hdr_capacity_max = metadata.hdr_capacity_max; |
219 | 0 | use_base_cg = metadata.use_base_cg; |
220 | 0 | } |
221 | | |
222 | 1.26k | bool are_all_channels_identical() const { |
223 | 1.26k | return max_content_boost[0] == max_content_boost[1] && |
224 | 1.26k | max_content_boost[0] == max_content_boost[2] && |
225 | 1.26k | min_content_boost[0] == min_content_boost[1] && |
226 | 1.26k | min_content_boost[0] == min_content_boost[2] && gamma[0] == gamma[1] && |
227 | 1.26k | gamma[0] == gamma[2] && offset_sdr[0] == offset_sdr[1] && |
228 | 1.26k | offset_sdr[0] == offset_sdr[2] && offset_hdr[0] == offset_hdr[1] && |
229 | 1.26k | offset_hdr[0] == offset_hdr[2]; |
230 | 1.26k | } |
231 | | |
232 | | std::string version; /**< Ultra HDR format version */ |
233 | | } uhdr_gainmap_metadata_ext_t; /**< alias for struct uhdr_gainmap_metadata */ |
234 | | |
235 | | #ifdef UHDR_ENABLE_GLES |
236 | | |
237 | | typedef enum uhdr_effect_shader { |
238 | | UHDR_MIR_HORZ, |
239 | | UHDR_MIR_VERT, |
240 | | UHDR_ROT_90, |
241 | | UHDR_ROT_180, |
242 | | UHDR_ROT_270, |
243 | | UHDR_CROP, |
244 | | UHDR_RESIZE, |
245 | | } uhdr_effect_shader_t; |
246 | | |
247 | | /**\brief OpenGL context */ |
248 | | typedef struct uhdr_opengl_ctxt { |
249 | | // EGL Context |
250 | | EGLDisplay mEGLDisplay; /**< EGL display connection */ |
251 | | EGLContext mEGLContext; /**< EGL rendering context */ |
252 | | EGLSurface mEGLSurface; /**< EGL surface for rendering */ |
253 | | EGLConfig mEGLConfig; /**< EGL frame buffer configuration */ |
254 | | |
255 | | // GLES Context |
256 | | GLuint mQuadVAO, mQuadVBO, mQuadEBO; /**< GL objects */ |
257 | | GLuint mShaderProgram[UHDR_RESIZE + 1]; /**< Shader programs */ |
258 | | GLuint mDecodedImgTexture, mGainmapImgTexture; /**< GL Textures */ |
259 | | uhdr_error_info_t mErrorStatus; /**< Context status */ |
260 | | |
261 | | uhdr_opengl_ctxt(); |
262 | | ~uhdr_opengl_ctxt(); |
263 | | |
264 | | /*!\brief Initializes the OpenGL context. Mainly it prepares EGL. We want a GLES3.0 context and a |
265 | | * surface that supports pbuffer. Once this is done and surface is made current, the gl state is |
266 | | * initialized |
267 | | * |
268 | | * \return none |
269 | | */ |
270 | | void init_opengl_ctxt(); |
271 | | |
272 | | /*!\brief This method is used to compile a shader |
273 | | * |
274 | | * \param[in] type shader type |
275 | | * \param[in] source shader source code |
276 | | * |
277 | | * \return GLuint #shader_id if operation succeeds, 0 otherwise. |
278 | | */ |
279 | | GLuint compile_shader(GLenum type, const char* source); |
280 | | |
281 | | /*!\brief This method is used to create a shader program |
282 | | * |
283 | | * \param[in] vertex_source vertex shader source code |
284 | | * \param[in] fragment_source fragment shader source code |
285 | | * |
286 | | * \return GLuint #shader_program_id if operation succeeds, 0 otherwise. |
287 | | */ |
288 | | GLuint create_shader_program(const char* vertex_source, const char* fragment_source); |
289 | | |
290 | | /*!\brief This method is used to create a 2D texture for a raw image |
291 | | * NOTE: For multichannel planar image, this method assumes the channel data to be contiguous |
292 | | * NOTE: For any channel, this method assumes width and stride to be identical |
293 | | * |
294 | | * \param[in] fmt image format |
295 | | * \param[in] w image width |
296 | | * \param[in] h image height |
297 | | * \param[in] data image data |
298 | | * |
299 | | * \return GLuint #texture_id if operation succeeds, 0 otherwise. |
300 | | */ |
301 | | GLuint create_texture(uhdr_img_fmt_t fmt, int w, int h, void* data); |
302 | | |
303 | | /*!\breif This method is used to read data from texture into a raw image |
304 | | * NOTE: For any channel, this method assumes width and stride to be identical |
305 | | * |
306 | | * \param[in] texture texture_id |
307 | | * \param[in] fmt image format |
308 | | * \param[in] w image width |
309 | | * \param[in] h image height |
310 | | * \param[in] data image data |
311 | | * |
312 | | * \return none |
313 | | */ |
314 | | void read_texture(GLuint* texture, uhdr_img_fmt_t fmt, int w, int h, void* data); |
315 | | |
316 | | /*!\brief This method is used to set up quad buffers and arrays |
317 | | * |
318 | | * \return none |
319 | | */ |
320 | | void setup_quad(); |
321 | | |
322 | | /*!\brief This method is used to set up frame buffer for a 2D texture |
323 | | * |
324 | | * \param[in] texture texture id |
325 | | * |
326 | | * \return GLuint #framebuffer_id if operation succeeds, 0 otherwise. |
327 | | */ |
328 | | GLuint setup_framebuffer(GLuint& texture); |
329 | | |
330 | | /*!\brief Checks for gl errors. On error, internal error state is updated with details |
331 | | * |
332 | | * \param[in] msg useful description for logging |
333 | | * |
334 | | * \return none |
335 | | */ |
336 | | void check_gl_errors(const char* msg); |
337 | | |
338 | | /*!\brief Reset the current context to default state for reuse |
339 | | * |
340 | | * \return none |
341 | | */ |
342 | | void reset_opengl_ctxt(); |
343 | | |
344 | | /*!\brief Deletes the current context |
345 | | * |
346 | | * \return none |
347 | | */ |
348 | | void delete_opengl_ctxt(); |
349 | | |
350 | | } uhdr_opengl_ctxt_t; /**< alias for struct uhdr_opengl_ctxt */ |
351 | | |
352 | | bool isBufferDataContiguous(uhdr_raw_image_t* img); |
353 | | |
354 | | #endif |
355 | | |
356 | | uhdr_error_info_t uhdr_validate_gainmap_metadata_descriptor(uhdr_gainmap_metadata_t* metadata); |
357 | | |
358 | | } // namespace ultrahdr |
359 | | |
360 | | // =============================================================================================== |
361 | | // Extensions of ultrahdr api definitions, so outside ultrahdr namespace |
362 | | // =============================================================================================== |
363 | | |
364 | | struct uhdr_codec_private { |
365 | | std::deque<ultrahdr::uhdr_effect_desc_t*> m_effects; |
366 | | #ifdef UHDR_ENABLE_GLES |
367 | | ultrahdr::uhdr_opengl_ctxt_t m_uhdr_gl_ctxt; |
368 | | bool m_enable_gles; |
369 | | #endif |
370 | | bool m_sailed; |
371 | | |
372 | | virtual ~uhdr_codec_private(); |
373 | | }; |
374 | | |
375 | | struct uhdr_encoder_private : uhdr_codec_private { |
376 | | // config data |
377 | | std::map<uhdr_img_label, std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t>> m_raw_images; |
378 | | std::map<uhdr_img_label, std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t>> |
379 | | m_compressed_images; |
380 | | std::map<uhdr_img_label, int> m_quality; |
381 | | std::vector<uint8_t> m_exif; |
382 | | uhdr_gainmap_metadata_t m_metadata; |
383 | | uhdr_codec_t m_output_format; |
384 | | int m_gainmap_scale_factor; |
385 | | bool m_use_multi_channel_gainmap; |
386 | | float m_gamma; |
387 | | uhdr_enc_preset_t m_enc_preset; |
388 | | float m_min_content_boost; |
389 | | float m_max_content_boost; |
390 | | float m_target_disp_max_brightness; |
391 | | |
392 | | // internal data |
393 | | std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_compressed_output_buffer; |
394 | | uhdr_error_info_t m_encode_call_status; |
395 | | }; |
396 | | |
397 | | struct uhdr_decoder_private : uhdr_codec_private { |
398 | | // config data |
399 | | std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_uhdr_compressed_img; |
400 | | uhdr_img_fmt_t m_output_fmt; |
401 | | uhdr_color_transfer_t m_output_ct; |
402 | | float m_output_max_disp_boost; |
403 | | |
404 | | // internal data |
405 | | bool m_probed; |
406 | | std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> m_decoded_img_buffer; |
407 | | std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> m_gainmap_img_buffer; |
408 | | int m_img_wd, m_img_ht; |
409 | | int m_gainmap_wd, m_gainmap_ht, m_gainmap_num_comp; |
410 | | std::vector<uint8_t> m_exif; |
411 | | uhdr_mem_block_t m_exif_block; |
412 | | std::vector<uint8_t> m_icc; |
413 | | uhdr_mem_block_t m_icc_block; |
414 | | std::vector<uint8_t> m_base_img; |
415 | | uhdr_mem_block_t m_base_img_block; |
416 | | std::vector<uint8_t> m_gainmap_img; |
417 | | uhdr_mem_block_t m_gainmap_img_block; |
418 | | uhdr_gainmap_metadata_t m_metadata; |
419 | | uhdr_error_info_t m_probe_call_status; |
420 | | uhdr_error_info_t m_decode_call_status; |
421 | | }; |
422 | | |
423 | | #endif // ULTRAHDR_ULTRAHDRCOMMON_H |