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