Coverage Report

Created: 2025-08-26 07:51

/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