blob: 67a3d0664c2a99cd7cbe787ff0ab9b8c5386896a [file] [log] [blame]
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ULTRAHDR_ULTRAHDRCOMMON_H
#define ULTRAHDR_ULTRAHDRCOMMON_H
//#define LOG_NDEBUG 0
#ifdef UHDR_ENABLE_GLES
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#endif
#include <deque>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "ultrahdr_api.h"
// ===============================================================================================
// Function Macros
// ===============================================================================================
#ifdef __ANDROID__
#ifdef LOG_NDEBUG
#include "android/log.h"
#ifndef LOG_TAG
#define LOG_TAG "UHDR"
#endif
#ifndef ALOGD
#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#endif
#ifndef ALOGE
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#endif
#ifndef ALOGI
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#endif
#ifndef ALOGV
#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#endif
#ifndef ALOGW
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#endif
#else
#define ALOGD(...) ((void)0)
#define ALOGE(...) ((void)0)
#define ALOGI(...) ((void)0)
#define ALOGV(...) ((void)0)
#define ALOGW(...) ((void)0)
#endif
#else
#ifdef LOG_NDEBUG
#include <cstdio>
#define ALOGD(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while (0)
#define ALOGE(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while (0)
#define ALOGI(...) \
do { \
fprintf(stdout, __VA_ARGS__); \
fprintf(stdout, "\n"); \
} while (0)
#define ALOGV(...) \
do { \
fprintf(stdout, __VA_ARGS__); \
fprintf(stdout, "\n"); \
} while (0)
#define ALOGW(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while (0)
#else
#define ALOGD(...) ((void)0)
#define ALOGE(...) ((void)0)
#define ALOGI(...) ((void)0)
#define ALOGV(...) ((void)0)
#define ALOGW(...) ((void)0)
#endif
#endif
#define ALIGNM(x, m) ((((x) + ((m)-1)) / (m)) * (m))
#define UHDR_ERR_CHECK(x) \
{ \
uhdr_error_info_t status = (x); \
if (status.error_code != UHDR_CODEC_OK) { \
return status; \
} \
}
#if defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#define INLINE __inline
#else
#define FORCE_INLINE __inline__ __attribute__((always_inline))
#define INLINE inline
#endif
// '__has_attribute' macro was introduced by clang. later picked up by gcc.
// If not supported by the current toolchain, define it to zero.
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
// Disables undefined behavior analysis for a function.
// GCC 4.9+ uses __attribute__((no_sanitize_undefined))
// clang uses __attribute__((no_sanitize("undefined")))
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409)
#define UHDR_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
#elif __has_attribute(no_sanitize)
#define UHDR_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
#else
#define UHDR_NO_SANITIZE_UNDEFINED
#endif
static const uhdr_error_info_t g_no_error = {UHDR_CODEC_OK, 0, ""};
namespace ultrahdr {
// ===============================================================================================
// Globals
// ===============================================================================================
extern const int kMinWidth, kMinHeight;
extern const int kMaxWidth, kMaxHeight;
// ===============================================================================================
// Structure Definitions
// ===============================================================================================
/**\brief uhdr memory block */
typedef struct uhdr_memory_block {
uhdr_memory_block(size_t capacity);
std::unique_ptr<uint8_t[]> m_buffer; /**< data */
size_t m_capacity; /**< capacity */
} uhdr_memory_block_t; /**< alias for struct uhdr_memory_block */
/**\brief extended raw image descriptor */
typedef struct uhdr_raw_image_ext : uhdr_raw_image_t {
uhdr_raw_image_ext(uhdr_img_fmt_t fmt, uhdr_color_gamut_t cg, uhdr_color_transfer_t ct,
uhdr_color_range_t range, unsigned w, unsigned h, unsigned align_stride_to);
private:
std::unique_ptr<ultrahdr::uhdr_memory_block> m_block;
} uhdr_raw_image_ext_t; /**< alias for struct uhdr_raw_image_ext */
/**\brief extended compressed image descriptor */
typedef struct uhdr_compressed_image_ext : uhdr_compressed_image_t {
uhdr_compressed_image_ext(uhdr_color_gamut_t cg, uhdr_color_transfer_t ct,
uhdr_color_range_t range, size_t sz);
private:
std::unique_ptr<ultrahdr::uhdr_memory_block> m_block;
} uhdr_compressed_image_ext_t; /**< alias for struct uhdr_compressed_image_ext */
/*!\brief forward declaration for image effect descriptor */
typedef struct uhdr_effect_desc uhdr_effect_desc_t;
/**\brief Gain map metadata. */
typedef struct uhdr_gainmap_metadata_ext : uhdr_gainmap_metadata {
uhdr_gainmap_metadata_ext() {}
uhdr_gainmap_metadata_ext(std::string ver) { version = ver; }
uhdr_gainmap_metadata_ext(uhdr_gainmap_metadata& metadata, std::string ver) {
max_content_boost = metadata.max_content_boost;
min_content_boost = metadata.min_content_boost;
gamma = metadata.gamma;
offset_sdr = metadata.offset_sdr;
offset_hdr = metadata.offset_hdr;
hdr_capacity_min = metadata.hdr_capacity_min;
hdr_capacity_max = metadata.hdr_capacity_max;
version = ver;
}
std::string version; /**< Ultra HDR format version */
} uhdr_gainmap_metadata_ext_t; /**< alias for struct uhdr_gainmap_metadata */
#ifdef UHDR_ENABLE_GLES
typedef enum uhdr_effect_shader {
UHDR_MIR_HORZ,
UHDR_MIR_VERT,
UHDR_ROT_90,
UHDR_ROT_180,
UHDR_ROT_270,
UHDR_CROP,
UHDR_RESIZE,
} uhdr_effect_shader_t;
/**\brief OpenGL context */
typedef struct uhdr_opengl_ctxt {
// EGL Context
EGLDisplay mEGLDisplay; /**< EGL display connection */
EGLContext mEGLContext; /**< EGL rendering context */
EGLSurface mEGLSurface; /**< EGL surface for rendering */
EGLConfig mEGLConfig; /**< EGL frame buffer configuration */
// GLES Context
GLuint mQuadVAO, mQuadVBO, mQuadEBO; /**< GL objects */
GLuint mShaderProgram[UHDR_RESIZE + 1]; /**< Shader programs */
GLuint mDecodedImgTexture, mGainmapImgTexture; /**< GL Textures */
uhdr_error_info_t mErrorStatus; /**< Context status */
uhdr_opengl_ctxt();
~uhdr_opengl_ctxt();
/*!\brief Initializes the OpenGL context. Mainly it prepares EGL. We want a GLES3.0 context and a
* surface that supports pbuffer. Once this is done and surface is made current, the gl state is
* initialized
*
* \return none
*/
void init_opengl_ctxt();
/*!\brief This method is used to compile a shader
*
* \param[in] type shader type
* \param[in] source shader source code
*
* \return GLuint #shader_id if operation succeeds, 0 otherwise.
*/
GLuint compile_shader(GLenum type, const char* source);
/*!\brief This method is used to create a shader program
*
* \param[in] vertex_source vertex shader source code
* \param[in] fragment_source fragment shader source code
*
* \return GLuint #shader_program_id if operation succeeds, 0 otherwise.
*/
GLuint create_shader_program(const char* vertex_source, const char* fragment_source);
/*!\brief This method is used to create a 2D texture for a raw image
* NOTE: For multichannel planar image, this method assumes the channel data to be contiguous
* NOTE: For any channel, this method assumes width and stride to be identical
*
* \param[in] fmt image format
* \param[in] w image width
* \param[in] h image height
* \param[in] data image data
*
* \return GLuint #texture_id if operation succeeds, 0 otherwise.
*/
GLuint create_texture(uhdr_img_fmt_t fmt, int w, int h, void* data);
/*!\breif This method is used to read data from texture into a raw image
* NOTE: For any channel, this method assumes width and stride to be identical
*
* \param[in] texture texture_id
* \param[in] fmt image format
* \param[in] w image width
* \param[in] h image height
* \param[in] data image data
*
* \return none
*/
void read_texture(GLuint* texture, uhdr_img_fmt_t fmt, int w, int h, void* data);
/*!\brief This method is used to set up quad buffers and arrays
*
* \return none
*/
void setup_quad();
/*!\brief This method is used to set up frame buffer for a 2D texture
*
* \param[in] texture texture id
*
* \return GLuint #framebuffer_id if operation succeeds, 0 otherwise.
*/
GLuint setup_framebuffer(GLuint& texture);
/*!\brief Checks for gl errors. On error, internal error state is updated with details
*
* \param[in] msg useful description for logging
*
* \return none
*/
void check_gl_errors(const char* msg);
/*!\brief Reset the current context to default state for reuse
*
* \return none
*/
void reset_opengl_ctxt();
/*!\brief Deletes the current context
*
* \return none
*/
void delete_opengl_ctxt();
} uhdr_opengl_ctxt_t; /**< alias for struct uhdr_opengl_ctxt */
bool isBufferDataContiguous(uhdr_raw_image_t* img);
#endif
uhdr_error_info_t uhdr_validate_gainmap_metadata_descriptor(uhdr_gainmap_metadata_t* metadata);
} // namespace ultrahdr
// ===============================================================================================
// Extensions of ultrahdr api definitions, so outside ultrahdr namespace
// ===============================================================================================
struct uhdr_codec_private {
std::deque<ultrahdr::uhdr_effect_desc_t*> m_effects;
#ifdef UHDR_ENABLE_GLES
ultrahdr::uhdr_opengl_ctxt_t m_uhdr_gl_ctxt;
bool m_enable_gles;
#endif
bool m_sailed;
virtual ~uhdr_codec_private();
};
struct uhdr_encoder_private : uhdr_codec_private {
// config data
std::map<uhdr_img_label, std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t>> m_raw_images;
std::map<uhdr_img_label, std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t>>
m_compressed_images;
std::map<uhdr_img_label, int> m_quality;
std::vector<uint8_t> m_exif;
uhdr_gainmap_metadata_t m_metadata;
uhdr_codec_t m_output_format;
int m_gainmap_scale_factor;
bool m_use_multi_channel_gainmap;
float m_gamma;
uhdr_enc_preset_t m_enc_preset;
float m_min_content_boost;
float m_max_content_boost;
float m_target_disp_max_brightness;
// internal data
std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_compressed_output_buffer;
uhdr_error_info_t m_encode_call_status;
};
struct uhdr_decoder_private : uhdr_codec_private {
// config data
std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_uhdr_compressed_img;
uhdr_img_fmt_t m_output_fmt;
uhdr_color_transfer_t m_output_ct;
float m_output_max_disp_boost;
// internal data
bool m_probed;
std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> m_decoded_img_buffer;
std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> m_gainmap_img_buffer;
int m_img_wd, m_img_ht;
int m_gainmap_wd, m_gainmap_ht, m_gainmap_num_comp;
std::vector<uint8_t> m_exif;
uhdr_mem_block_t m_exif_block;
std::vector<uint8_t> m_icc;
uhdr_mem_block_t m_icc_block;
std::vector<uint8_t> m_base_img;
uhdr_mem_block_t m_base_img_block;
std::vector<uint8_t> m_gainmap_img;
uhdr_mem_block_t m_gainmap_img_block;
uhdr_gainmap_metadata_t m_metadata;
uhdr_error_info_t m_probe_call_status;
uhdr_error_info_t m_decode_call_status;
};
#endif // ULTRAHDR_ULTRAHDRCOMMON_H