• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       : uhdr_gainmap_metadata_ext(ver) {
211     std::copy(metadata.max_content_boost, metadata.max_content_boost + 3, max_content_boost);
212     std::copy(metadata.min_content_boost, metadata.min_content_boost + 3, min_content_boost);
213     std::copy(metadata.gamma, metadata.gamma + 3, gamma);
214     std::copy(metadata.offset_sdr, metadata.offset_sdr + 3, offset_sdr);
215     std::copy(metadata.offset_hdr, metadata.offset_hdr + 3, offset_hdr);
216     hdr_capacity_min = metadata.hdr_capacity_min;
217     hdr_capacity_max = metadata.hdr_capacity_max;
218     use_base_cg = metadata.use_base_cg;
219   }
220 
are_all_channels_identicaluhdr_gainmap_metadata_ext221   bool are_all_channels_identical() const {
222     return max_content_boost[0] == max_content_boost[1] &&
223            max_content_boost[0] == max_content_boost[2] &&
224            min_content_boost[0] == min_content_boost[1] &&
225            min_content_boost[0] == min_content_boost[2] && gamma[0] == gamma[1] &&
226            gamma[0] == gamma[2] && offset_sdr[0] == offset_sdr[1] &&
227            offset_sdr[0] == offset_sdr[2] && offset_hdr[0] == offset_hdr[1] &&
228            offset_hdr[0] == offset_hdr[2];
229   }
230 
231   std::string version;         /**< Ultra HDR format version */
232 } uhdr_gainmap_metadata_ext_t; /**< alias for struct uhdr_gainmap_metadata */
233 
234 #ifdef UHDR_ENABLE_GLES
235 
236 typedef enum uhdr_effect_shader {
237   UHDR_MIR_HORZ,
238   UHDR_MIR_VERT,
239   UHDR_ROT_90,
240   UHDR_ROT_180,
241   UHDR_ROT_270,
242   UHDR_CROP,
243   UHDR_RESIZE,
244 } uhdr_effect_shader_t;
245 
246 /**\brief OpenGL context */
247 typedef struct uhdr_opengl_ctxt {
248   // EGL Context
249   EGLDisplay mEGLDisplay; /**< EGL display connection */
250   EGLContext mEGLContext; /**< EGL rendering context */
251   EGLSurface mEGLSurface; /**< EGL surface for rendering */
252   EGLConfig mEGLConfig;   /**< EGL frame buffer configuration */
253 
254   // GLES Context
255   GLuint mQuadVAO, mQuadVBO, mQuadEBO;           /**< GL objects */
256   GLuint mShaderProgram[UHDR_RESIZE + 1];        /**< Shader programs */
257   GLuint mDecodedImgTexture, mGainmapImgTexture; /**< GL Textures */
258   uhdr_error_info_t mErrorStatus;                /**< Context status */
259 
260   uhdr_opengl_ctxt();
261   ~uhdr_opengl_ctxt();
262 
263   /*!\brief Initializes the OpenGL context. Mainly it prepares EGL. We want a GLES3.0 context and a
264    * surface that supports pbuffer. Once this is done and surface is made current, the gl state is
265    * initialized
266    *
267    * \return none
268    */
269   void init_opengl_ctxt();
270 
271   /*!\brief This method is used to compile a shader
272    *
273    * \param[in]   type    shader type
274    * \param[in]   source  shader source code
275    *
276    * \return GLuint #shader_id if operation succeeds, 0 otherwise.
277    */
278   GLuint compile_shader(GLenum type, const char* source);
279 
280   /*!\brief This method is used to create a shader program
281    *
282    * \param[in]   vertex_source      vertex shader source code
283    * \param[in]   fragment_source    fragment shader source code
284    *
285    * \return GLuint #shader_program_id if operation succeeds, 0 otherwise.
286    */
287   GLuint create_shader_program(const char* vertex_source, const char* fragment_source);
288 
289   /*!\brief This method is used to create a 2D texture for a raw image
290    * NOTE: For multichannel planar image, this method assumes the channel data to be contiguous
291    * NOTE: For any channel, this method assumes width and stride to be identical
292    *
293    * \param[in]   fmt       image format
294    * \param[in]   w         image width
295    * \param[in]   h         image height
296    * \param[in]   data      image data
297    *
298    * \return GLuint #texture_id if operation succeeds, 0 otherwise.
299    */
300   GLuint create_texture(uhdr_img_fmt_t fmt, int w, int h, void* data);
301 
302   /*!\breif This method is used to read data from texture into a raw image
303    * NOTE: For any channel, this method assumes width and stride to be identical
304    *
305    * \param[in]   texture    texture_id
306    * \param[in]   fmt        image format
307    * \param[in]   w          image width
308    * \param[in]   h          image height
309    * \param[in]   data       image data
310    *
311    * \return none
312    */
313   void read_texture(GLuint* texture, uhdr_img_fmt_t fmt, int w, int h, void* data);
314 
315   /*!\brief This method is used to set up quad buffers and arrays
316    *
317    * \return none
318    */
319   void setup_quad();
320 
321   /*!\brief This method is used to set up frame buffer for a 2D texture
322    *
323    * \param[in]   texture         texture id
324    *
325    * \return GLuint #framebuffer_id if operation succeeds, 0 otherwise.
326    */
327   GLuint setup_framebuffer(GLuint& texture);
328 
329   /*!\brief Checks for gl errors. On error, internal error state is updated with details
330    *
331    * \param[in]   msg     useful description for logging
332    *
333    * \return none
334    */
335   void check_gl_errors(const char* msg);
336 
337   /*!\brief Reset the current context to default state for reuse
338    *
339    * \return none
340    */
341   void reset_opengl_ctxt();
342 
343   /*!\brief Deletes the current context
344    *
345    * \return none
346    */
347   void delete_opengl_ctxt();
348 
349 } uhdr_opengl_ctxt_t; /**< alias for struct uhdr_opengl_ctxt */
350 
351 bool isBufferDataContiguous(uhdr_raw_image_t* img);
352 
353 #endif
354 
355 uhdr_error_info_t uhdr_validate_gainmap_metadata_descriptor(uhdr_gainmap_metadata_t* metadata);
356 
357 }  // namespace ultrahdr
358 
359 // ===============================================================================================
360 // Extensions of ultrahdr api definitions, so outside ultrahdr namespace
361 // ===============================================================================================
362 
363 struct uhdr_codec_private {
364   std::deque<ultrahdr::uhdr_effect_desc_t*> m_effects;
365 #ifdef UHDR_ENABLE_GLES
366   ultrahdr::uhdr_opengl_ctxt_t m_uhdr_gl_ctxt;
367   bool m_enable_gles;
368 #endif
369   bool m_sailed;
370 
371   virtual ~uhdr_codec_private();
372 };
373 
374 struct uhdr_encoder_private : uhdr_codec_private {
375   // config data
376   std::map<uhdr_img_label, std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t>> m_raw_images;
377   std::map<uhdr_img_label, std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t>>
378       m_compressed_images;
379   std::map<uhdr_img_label, int> m_quality;
380   std::vector<uint8_t> m_exif;
381   uhdr_gainmap_metadata_t m_metadata;
382   uhdr_codec_t m_output_format;
383   int m_gainmap_scale_factor;
384   bool m_use_multi_channel_gainmap;
385   float m_gamma;
386   uhdr_enc_preset_t m_enc_preset;
387   float m_min_content_boost;
388   float m_max_content_boost;
389   float m_target_disp_max_brightness;
390 
391   // internal data
392   std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_compressed_output_buffer;
393   uhdr_error_info_t m_encode_call_status;
394 };
395 
396 struct uhdr_decoder_private : uhdr_codec_private {
397   // config data
398   std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_uhdr_compressed_img;
399   uhdr_img_fmt_t m_output_fmt;
400   uhdr_color_transfer_t m_output_ct;
401   float m_output_max_disp_boost;
402 
403   // internal data
404   bool m_probed;
405   std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> m_decoded_img_buffer;
406   std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> m_gainmap_img_buffer;
407   int m_img_wd, m_img_ht;
408   int m_gainmap_wd, m_gainmap_ht, m_gainmap_num_comp;
409   std::vector<uint8_t> m_exif;
410   uhdr_mem_block_t m_exif_block;
411   std::vector<uint8_t> m_icc;
412   uhdr_mem_block_t m_icc_block;
413   std::vector<uint8_t> m_base_img;
414   uhdr_mem_block_t m_base_img_block;
415   std::vector<uint8_t> m_gainmap_img;
416   uhdr_mem_block_t m_gainmap_img_block;
417   uhdr_gainmap_metadata_t m_metadata;
418   uhdr_error_info_t m_probe_call_status;
419   uhdr_error_info_t m_decode_call_status;
420 };
421 
422 #endif  // ULTRAHDR_ULTRAHDRCOMMON_H
423