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