Coverage Report

Created: 2026-06-15 07:18

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