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