1*89a0ef05SAndroid Build Coastguard Worker /*
2*89a0ef05SAndroid Build Coastguard Worker * Copyright 2024 The Android Open Source Project
3*89a0ef05SAndroid Build Coastguard Worker *
4*89a0ef05SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*89a0ef05SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*89a0ef05SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*89a0ef05SAndroid Build Coastguard Worker *
8*89a0ef05SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*89a0ef05SAndroid Build Coastguard Worker *
10*89a0ef05SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*89a0ef05SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*89a0ef05SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*89a0ef05SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*89a0ef05SAndroid Build Coastguard Worker * limitations under the License.
15*89a0ef05SAndroid Build Coastguard Worker */
16*89a0ef05SAndroid Build Coastguard Worker
17*89a0ef05SAndroid Build Coastguard Worker #include <cstdio>
18*89a0ef05SAndroid Build Coastguard Worker #include <cstring>
19*89a0ef05SAndroid Build Coastguard Worker
20*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr_api.h"
21*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/ultrahdrcommon.h"
22*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/gainmapmath.h"
23*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/editorhelper.h"
24*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/jpegr.h"
25*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/jpegrutils.h"
26*89a0ef05SAndroid Build Coastguard Worker
27*89a0ef05SAndroid Build Coastguard Worker #include "image_io/base/data_segment_data_source.h"
28*89a0ef05SAndroid Build Coastguard Worker #include "image_io/jpeg/jpeg_info.h"
29*89a0ef05SAndroid Build Coastguard Worker #include "image_io/jpeg/jpeg_info_builder.h"
30*89a0ef05SAndroid Build Coastguard Worker #include "image_io/jpeg/jpeg_marker.h"
31*89a0ef05SAndroid Build Coastguard Worker #include "image_io/jpeg/jpeg_scanner.h"
32*89a0ef05SAndroid Build Coastguard Worker
33*89a0ef05SAndroid Build Coastguard Worker using namespace photos_editing_formats::image_io;
34*89a0ef05SAndroid Build Coastguard Worker
35*89a0ef05SAndroid Build Coastguard Worker namespace ultrahdr {
36*89a0ef05SAndroid Build Coastguard Worker
uhdr_memory_block(size_t capacity)37*89a0ef05SAndroid Build Coastguard Worker uhdr_memory_block::uhdr_memory_block(size_t capacity) {
38*89a0ef05SAndroid Build Coastguard Worker m_buffer = std::make_unique<uint8_t[]>(capacity);
39*89a0ef05SAndroid Build Coastguard Worker m_capacity = capacity;
40*89a0ef05SAndroid Build Coastguard Worker }
41*89a0ef05SAndroid Build Coastguard Worker
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)42*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_ext::uhdr_raw_image_ext(uhdr_img_fmt_t fmt_, uhdr_color_gamut_t cg_,
43*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t ct_, uhdr_color_range_t range_,
44*89a0ef05SAndroid Build Coastguard Worker unsigned w_, unsigned h_, unsigned align_stride_to) {
45*89a0ef05SAndroid Build Coastguard Worker this->fmt = fmt_;
46*89a0ef05SAndroid Build Coastguard Worker this->cg = cg_;
47*89a0ef05SAndroid Build Coastguard Worker this->ct = ct_;
48*89a0ef05SAndroid Build Coastguard Worker this->range = range_;
49*89a0ef05SAndroid Build Coastguard Worker
50*89a0ef05SAndroid Build Coastguard Worker this->w = w_;
51*89a0ef05SAndroid Build Coastguard Worker this->h = h_;
52*89a0ef05SAndroid Build Coastguard Worker
53*89a0ef05SAndroid Build Coastguard Worker int aligned_width = ALIGNM(w_, align_stride_to);
54*89a0ef05SAndroid Build Coastguard Worker
55*89a0ef05SAndroid Build Coastguard Worker size_t bpp = 1;
56*89a0ef05SAndroid Build Coastguard Worker if (fmt_ == UHDR_IMG_FMT_24bppYCbCrP010 || fmt_ == UHDR_IMG_FMT_30bppYCbCr444) {
57*89a0ef05SAndroid Build Coastguard Worker bpp = 2;
58*89a0ef05SAndroid Build Coastguard Worker } else if (fmt_ == UHDR_IMG_FMT_24bppRGB888) {
59*89a0ef05SAndroid Build Coastguard Worker bpp = 3;
60*89a0ef05SAndroid Build Coastguard Worker } else if (fmt_ == UHDR_IMG_FMT_32bppRGBA8888 || fmt_ == UHDR_IMG_FMT_32bppRGBA1010102) {
61*89a0ef05SAndroid Build Coastguard Worker bpp = 4;
62*89a0ef05SAndroid Build Coastguard Worker } else if (fmt_ == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
63*89a0ef05SAndroid Build Coastguard Worker bpp = 8;
64*89a0ef05SAndroid Build Coastguard Worker }
65*89a0ef05SAndroid Build Coastguard Worker
66*89a0ef05SAndroid Build Coastguard Worker size_t plane_1_sz = bpp * aligned_width * h_;
67*89a0ef05SAndroid Build Coastguard Worker size_t plane_2_sz;
68*89a0ef05SAndroid Build Coastguard Worker size_t plane_3_sz;
69*89a0ef05SAndroid Build Coastguard Worker if (fmt_ == UHDR_IMG_FMT_24bppYCbCrP010) {
70*89a0ef05SAndroid Build Coastguard Worker plane_2_sz = (2 /* planes */ * bpp * (aligned_width / 2) * (h_ / 2));
71*89a0ef05SAndroid Build Coastguard Worker plane_3_sz = 0;
72*89a0ef05SAndroid Build Coastguard Worker } else if (fmt_ == UHDR_IMG_FMT_30bppYCbCr444 || fmt_ == UHDR_IMG_FMT_24bppYCbCr444) {
73*89a0ef05SAndroid Build Coastguard Worker plane_2_sz = bpp * aligned_width * h_;
74*89a0ef05SAndroid Build Coastguard Worker plane_3_sz = bpp * aligned_width * h_;
75*89a0ef05SAndroid Build Coastguard Worker } else if (fmt_ == UHDR_IMG_FMT_12bppYCbCr420) {
76*89a0ef05SAndroid Build Coastguard Worker plane_2_sz = (bpp * (aligned_width / 2) * (h_ / 2));
77*89a0ef05SAndroid Build Coastguard Worker plane_3_sz = (bpp * (aligned_width / 2) * (h_ / 2));
78*89a0ef05SAndroid Build Coastguard Worker } else {
79*89a0ef05SAndroid Build Coastguard Worker plane_2_sz = 0;
80*89a0ef05SAndroid Build Coastguard Worker plane_3_sz = 0;
81*89a0ef05SAndroid Build Coastguard Worker }
82*89a0ef05SAndroid Build Coastguard Worker size_t total_size = plane_1_sz + plane_2_sz + plane_3_sz;
83*89a0ef05SAndroid Build Coastguard Worker this->m_block = std::make_unique<uhdr_memory_block_t>(total_size);
84*89a0ef05SAndroid Build Coastguard Worker
85*89a0ef05SAndroid Build Coastguard Worker uint8_t* data = this->m_block->m_buffer.get();
86*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_Y] = data;
87*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_Y] = aligned_width;
88*89a0ef05SAndroid Build Coastguard Worker if (fmt_ == UHDR_IMG_FMT_24bppYCbCrP010) {
89*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_UV] = data + plane_1_sz;
90*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_UV] = aligned_width;
91*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_V] = nullptr;
92*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_V] = 0;
93*89a0ef05SAndroid Build Coastguard Worker } else if (fmt_ == UHDR_IMG_FMT_30bppYCbCr444 || fmt_ == UHDR_IMG_FMT_24bppYCbCr444) {
94*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_U] = data + plane_1_sz;
95*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_U] = aligned_width;
96*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_V] = data + plane_1_sz + plane_2_sz;
97*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_V] = aligned_width;
98*89a0ef05SAndroid Build Coastguard Worker } else if (fmt_ == UHDR_IMG_FMT_12bppYCbCr420) {
99*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_U] = data + plane_1_sz;
100*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_U] = aligned_width / 2;
101*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_V] = data + plane_1_sz + plane_2_sz;
102*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_V] = aligned_width / 2;
103*89a0ef05SAndroid Build Coastguard Worker } else {
104*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_U] = nullptr;
105*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_U] = 0;
106*89a0ef05SAndroid Build Coastguard Worker this->planes[UHDR_PLANE_V] = nullptr;
107*89a0ef05SAndroid Build Coastguard Worker this->stride[UHDR_PLANE_V] = 0;
108*89a0ef05SAndroid Build Coastguard Worker }
109*89a0ef05SAndroid Build Coastguard Worker }
110*89a0ef05SAndroid Build Coastguard Worker
uhdr_compressed_image_ext(uhdr_color_gamut_t cg_,uhdr_color_transfer_t ct_,uhdr_color_range_t range_,size_t size)111*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_ext::uhdr_compressed_image_ext(uhdr_color_gamut_t cg_,
112*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t ct_,
113*89a0ef05SAndroid Build Coastguard Worker uhdr_color_range_t range_, size_t size) {
114*89a0ef05SAndroid Build Coastguard Worker this->m_block = std::make_unique<uhdr_memory_block_t>(size);
115*89a0ef05SAndroid Build Coastguard Worker this->data = this->m_block->m_buffer.get();
116*89a0ef05SAndroid Build Coastguard Worker this->capacity = size;
117*89a0ef05SAndroid Build Coastguard Worker this->data_sz = 0;
118*89a0ef05SAndroid Build Coastguard Worker this->cg = cg_;
119*89a0ef05SAndroid Build Coastguard Worker this->ct = ct_;
120*89a0ef05SAndroid Build Coastguard Worker this->range = range_;
121*89a0ef05SAndroid Build Coastguard Worker }
122*89a0ef05SAndroid Build Coastguard Worker
apply_effects(uhdr_encoder_private * enc)123*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t apply_effects(uhdr_encoder_private* enc) {
124*89a0ef05SAndroid Build Coastguard Worker for (auto& it : enc->m_effects) {
125*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> hdr_img = nullptr;
126*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> sdr_img = nullptr;
127*89a0ef05SAndroid Build Coastguard Worker
128*89a0ef05SAndroid Build Coastguard Worker if (nullptr != dynamic_cast<uhdr_rotate_effect_t*>(it)) {
129*89a0ef05SAndroid Build Coastguard Worker auto& hdr_raw_entry = enc->m_raw_images.find(UHDR_HDR_IMG)->second;
130*89a0ef05SAndroid Build Coastguard Worker hdr_img = apply_rotate(dynamic_cast<uhdr_rotate_effect_t*>(it), hdr_raw_entry.get());
131*89a0ef05SAndroid Build Coastguard Worker if (enc->m_raw_images.find(UHDR_SDR_IMG) != enc->m_raw_images.end()) {
132*89a0ef05SAndroid Build Coastguard Worker auto& sdr_raw_entry = enc->m_raw_images.find(UHDR_SDR_IMG)->second;
133*89a0ef05SAndroid Build Coastguard Worker sdr_img = apply_rotate(dynamic_cast<uhdr_rotate_effect_t*>(it), sdr_raw_entry.get());
134*89a0ef05SAndroid Build Coastguard Worker }
135*89a0ef05SAndroid Build Coastguard Worker } else if (nullptr != dynamic_cast<uhdr_mirror_effect_t*>(it)) {
136*89a0ef05SAndroid Build Coastguard Worker auto& hdr_raw_entry = enc->m_raw_images.find(UHDR_HDR_IMG)->second;
137*89a0ef05SAndroid Build Coastguard Worker hdr_img = apply_mirror(dynamic_cast<uhdr_mirror_effect_t*>(it), hdr_raw_entry.get());
138*89a0ef05SAndroid Build Coastguard Worker if (enc->m_raw_images.find(UHDR_SDR_IMG) != enc->m_raw_images.end()) {
139*89a0ef05SAndroid Build Coastguard Worker auto& sdr_raw_entry = enc->m_raw_images.find(UHDR_SDR_IMG)->second;
140*89a0ef05SAndroid Build Coastguard Worker sdr_img = apply_mirror(dynamic_cast<uhdr_mirror_effect_t*>(it), sdr_raw_entry.get());
141*89a0ef05SAndroid Build Coastguard Worker }
142*89a0ef05SAndroid Build Coastguard Worker } else if (nullptr != dynamic_cast<uhdr_crop_effect_t*>(it)) {
143*89a0ef05SAndroid Build Coastguard Worker auto crop_effect = dynamic_cast<uhdr_crop_effect_t*>(it);
144*89a0ef05SAndroid Build Coastguard Worker auto& hdr_raw_entry = enc->m_raw_images.find(UHDR_HDR_IMG)->second;
145*89a0ef05SAndroid Build Coastguard Worker int left = (std::max)(0, crop_effect->m_left);
146*89a0ef05SAndroid Build Coastguard Worker int right = (std::min)((int)hdr_raw_entry->w, crop_effect->m_right);
147*89a0ef05SAndroid Build Coastguard Worker int crop_width = right - left;
148*89a0ef05SAndroid Build Coastguard Worker if (crop_width <= 0) {
149*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
150*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
151*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
152*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
153*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop width is expected to be > 0, crop width is %d",
154*89a0ef05SAndroid Build Coastguard Worker crop_width);
155*89a0ef05SAndroid Build Coastguard Worker return status;
156*89a0ef05SAndroid Build Coastguard Worker }
157*89a0ef05SAndroid Build Coastguard Worker if (crop_width % 2 != 0 && hdr_raw_entry->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
158*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
159*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
160*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
161*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
162*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop width is expected to even for format "
163*89a0ef05SAndroid Build Coastguard Worker "{UHDR_IMG_FMT_24bppYCbCrP010}, crop width is %d",
164*89a0ef05SAndroid Build Coastguard Worker crop_width);
165*89a0ef05SAndroid Build Coastguard Worker return status;
166*89a0ef05SAndroid Build Coastguard Worker }
167*89a0ef05SAndroid Build Coastguard Worker
168*89a0ef05SAndroid Build Coastguard Worker int top = (std::max)(0, crop_effect->m_top);
169*89a0ef05SAndroid Build Coastguard Worker int bottom = (std::min)((int)hdr_raw_entry->h, crop_effect->m_bottom);
170*89a0ef05SAndroid Build Coastguard Worker int crop_height = bottom - top;
171*89a0ef05SAndroid Build Coastguard Worker if (crop_height <= 0) {
172*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
173*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
174*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
175*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
176*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop height is expected to be > 0, crop height is %d",
177*89a0ef05SAndroid Build Coastguard Worker crop_height);
178*89a0ef05SAndroid Build Coastguard Worker return status;
179*89a0ef05SAndroid Build Coastguard Worker }
180*89a0ef05SAndroid Build Coastguard Worker if (crop_height % 2 != 0 && hdr_raw_entry->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
181*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
182*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
183*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
184*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
185*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop height is expected to even for format "
186*89a0ef05SAndroid Build Coastguard Worker "{UHDR_IMG_FMT_24bppYCbCrP010}. crop height is %d",
187*89a0ef05SAndroid Build Coastguard Worker crop_height);
188*89a0ef05SAndroid Build Coastguard Worker return status;
189*89a0ef05SAndroid Build Coastguard Worker }
190*89a0ef05SAndroid Build Coastguard Worker hdr_img = apply_crop(dynamic_cast<ultrahdr::uhdr_crop_effect_t*>(it), hdr_raw_entry.get(),
191*89a0ef05SAndroid Build Coastguard Worker left, top, crop_width, crop_height);
192*89a0ef05SAndroid Build Coastguard Worker if (enc->m_raw_images.find(UHDR_SDR_IMG) != enc->m_raw_images.end()) {
193*89a0ef05SAndroid Build Coastguard Worker auto& sdr_raw_entry = enc->m_raw_images.find(UHDR_SDR_IMG)->second;
194*89a0ef05SAndroid Build Coastguard Worker if (crop_width % 2 != 0 && sdr_raw_entry->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
195*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
196*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
197*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
198*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
199*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop width is expected to even for format "
200*89a0ef05SAndroid Build Coastguard Worker "{UHDR_IMG_FMT_12bppYCbCr420}, crop width is %d",
201*89a0ef05SAndroid Build Coastguard Worker crop_width);
202*89a0ef05SAndroid Build Coastguard Worker return status;
203*89a0ef05SAndroid Build Coastguard Worker }
204*89a0ef05SAndroid Build Coastguard Worker if (crop_height % 2 != 0 && sdr_raw_entry->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
205*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
206*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
207*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
208*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
209*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop height is expected to even for format "
210*89a0ef05SAndroid Build Coastguard Worker "{UHDR_IMG_FMT_12bppYCbCr420}. crop height is %d",
211*89a0ef05SAndroid Build Coastguard Worker crop_height);
212*89a0ef05SAndroid Build Coastguard Worker return status;
213*89a0ef05SAndroid Build Coastguard Worker }
214*89a0ef05SAndroid Build Coastguard Worker sdr_img = apply_crop(dynamic_cast<ultrahdr::uhdr_crop_effect_t*>(it), sdr_raw_entry.get(),
215*89a0ef05SAndroid Build Coastguard Worker left, top, crop_width, crop_height);
216*89a0ef05SAndroid Build Coastguard Worker }
217*89a0ef05SAndroid Build Coastguard Worker } else if (nullptr != dynamic_cast<uhdr_resize_effect_t*>(it)) {
218*89a0ef05SAndroid Build Coastguard Worker auto resize_effect = dynamic_cast<uhdr_resize_effect_t*>(it);
219*89a0ef05SAndroid Build Coastguard Worker int dst_w = resize_effect->m_width;
220*89a0ef05SAndroid Build Coastguard Worker int dst_h = resize_effect->m_height;
221*89a0ef05SAndroid Build Coastguard Worker auto& hdr_raw_entry = enc->m_raw_images.find(UHDR_HDR_IMG)->second;
222*89a0ef05SAndroid Build Coastguard Worker if (dst_w <= 0 || dst_h <= 0 || dst_w > ultrahdr::kMaxWidth || dst_h > ultrahdr::kMaxHeight) {
223*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
224*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
225*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
226*89a0ef05SAndroid Build Coastguard Worker "destination dimensions must be in range (0, %d] x (0, %d]. dest image width "
227*89a0ef05SAndroid Build Coastguard Worker "is %d, dest image height is %d",
228*89a0ef05SAndroid Build Coastguard Worker ultrahdr::kMaxWidth, ultrahdr::kMaxHeight, dst_w, dst_h);
229*89a0ef05SAndroid Build Coastguard Worker return status;
230*89a0ef05SAndroid Build Coastguard Worker }
231*89a0ef05SAndroid Build Coastguard Worker if ((dst_w % 2 != 0 || dst_h % 2 != 0) && hdr_raw_entry->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
232*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
233*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
234*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
235*89a0ef05SAndroid Build Coastguard Worker "destination dimensions cannot be odd for format {UHDR_IMG_FMT_24bppYCbCrP010}. "
236*89a0ef05SAndroid Build Coastguard Worker "dest image width is %d, dest image height is %d",
237*89a0ef05SAndroid Build Coastguard Worker dst_w, dst_h);
238*89a0ef05SAndroid Build Coastguard Worker return status;
239*89a0ef05SAndroid Build Coastguard Worker }
240*89a0ef05SAndroid Build Coastguard Worker hdr_img =
241*89a0ef05SAndroid Build Coastguard Worker apply_resize(dynamic_cast<uhdr_resize_effect_t*>(it), hdr_raw_entry.get(), dst_w, dst_h);
242*89a0ef05SAndroid Build Coastguard Worker if (enc->m_raw_images.find(UHDR_SDR_IMG) != enc->m_raw_images.end()) {
243*89a0ef05SAndroid Build Coastguard Worker auto& sdr_raw_entry = enc->m_raw_images.find(UHDR_SDR_IMG)->second;
244*89a0ef05SAndroid Build Coastguard Worker if ((dst_w % 2 != 0 || dst_h % 2 != 0) &&
245*89a0ef05SAndroid Build Coastguard Worker sdr_raw_entry->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
246*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
247*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
248*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
249*89a0ef05SAndroid Build Coastguard Worker "destination dimensions cannot be odd for format {UHDR_IMG_FMT_12bppYCbCr420}. "
250*89a0ef05SAndroid Build Coastguard Worker "dest image width is %d, dest image height is %d",
251*89a0ef05SAndroid Build Coastguard Worker dst_w, dst_h);
252*89a0ef05SAndroid Build Coastguard Worker return status;
253*89a0ef05SAndroid Build Coastguard Worker }
254*89a0ef05SAndroid Build Coastguard Worker sdr_img = apply_resize(dynamic_cast<uhdr_resize_effect_t*>(it), sdr_raw_entry.get(), dst_w,
255*89a0ef05SAndroid Build Coastguard Worker dst_h);
256*89a0ef05SAndroid Build Coastguard Worker }
257*89a0ef05SAndroid Build Coastguard Worker }
258*89a0ef05SAndroid Build Coastguard Worker
259*89a0ef05SAndroid Build Coastguard Worker if (hdr_img == nullptr ||
260*89a0ef05SAndroid Build Coastguard Worker (enc->m_raw_images.find(UHDR_SDR_IMG) != enc->m_raw_images.end() && sdr_img == nullptr)) {
261*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
262*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_UNKNOWN_ERROR;
263*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
264*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
265*89a0ef05SAndroid Build Coastguard Worker "encountered unknown error while applying effect %s", it->to_string().c_str());
266*89a0ef05SAndroid Build Coastguard Worker return status;
267*89a0ef05SAndroid Build Coastguard Worker }
268*89a0ef05SAndroid Build Coastguard Worker enc->m_raw_images.insert_or_assign(UHDR_HDR_IMG, std::move(hdr_img));
269*89a0ef05SAndroid Build Coastguard Worker if (sdr_img != nullptr) {
270*89a0ef05SAndroid Build Coastguard Worker enc->m_raw_images.insert_or_assign(UHDR_SDR_IMG, std::move(sdr_img));
271*89a0ef05SAndroid Build Coastguard Worker }
272*89a0ef05SAndroid Build Coastguard Worker }
273*89a0ef05SAndroid Build Coastguard Worker
274*89a0ef05SAndroid Build Coastguard Worker return g_no_error;
275*89a0ef05SAndroid Build Coastguard Worker }
276*89a0ef05SAndroid Build Coastguard Worker
is_resize_effect(const ultrahdr::uhdr_effect_desc_t * effect)277*89a0ef05SAndroid Build Coastguard Worker bool is_resize_effect(const ultrahdr::uhdr_effect_desc_t* effect) {
278*89a0ef05SAndroid Build Coastguard Worker return dynamic_cast<const ultrahdr::uhdr_resize_effect_t*>(effect) != nullptr;
279*89a0ef05SAndroid Build Coastguard Worker }
280*89a0ef05SAndroid Build Coastguard Worker
apply_effects(uhdr_decoder_private * dec)281*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t apply_effects(uhdr_decoder_private* dec) {
282*89a0ef05SAndroid Build Coastguard Worker void *gl_ctxt = nullptr, *disp_texture_ptr = nullptr, *gm_texture_ptr = nullptr;
283*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
284*89a0ef05SAndroid Build Coastguard Worker if (dec->m_enable_gles) {
285*89a0ef05SAndroid Build Coastguard Worker gl_ctxt = &dec->m_uhdr_gl_ctxt;
286*89a0ef05SAndroid Build Coastguard Worker bool texture_created =
287*89a0ef05SAndroid Build Coastguard Worker dec->m_uhdr_gl_ctxt.mDecodedImgTexture != 0 && dec->m_uhdr_gl_ctxt.mGainmapImgTexture != 0;
288*89a0ef05SAndroid Build Coastguard Worker bool resize_effect_present = std::find_if(dec->m_effects.begin(), dec->m_effects.end(),
289*89a0ef05SAndroid Build Coastguard Worker is_resize_effect) != dec->m_effects.end();
290*89a0ef05SAndroid Build Coastguard Worker if (!texture_created && resize_effect_present &&
291*89a0ef05SAndroid Build Coastguard Worker isBufferDataContiguous(dec->m_decoded_img_buffer.get()) &&
292*89a0ef05SAndroid Build Coastguard Worker isBufferDataContiguous(dec->m_gainmap_img_buffer.get())) {
293*89a0ef05SAndroid Build Coastguard Worker dec->m_uhdr_gl_ctxt.mDecodedImgTexture = dec->m_uhdr_gl_ctxt.create_texture(
294*89a0ef05SAndroid Build Coastguard Worker dec->m_decoded_img_buffer->fmt, dec->m_decoded_img_buffer->w,
295*89a0ef05SAndroid Build Coastguard Worker dec->m_decoded_img_buffer->h, dec->m_decoded_img_buffer->planes[0]);
296*89a0ef05SAndroid Build Coastguard Worker dec->m_uhdr_gl_ctxt.mGainmapImgTexture = dec->m_uhdr_gl_ctxt.create_texture(
297*89a0ef05SAndroid Build Coastguard Worker dec->m_gainmap_img_buffer->fmt, dec->m_gainmap_img_buffer->w,
298*89a0ef05SAndroid Build Coastguard Worker dec->m_gainmap_img_buffer->h, dec->m_gainmap_img_buffer->planes[0]);
299*89a0ef05SAndroid Build Coastguard Worker }
300*89a0ef05SAndroid Build Coastguard Worker disp_texture_ptr = &dec->m_uhdr_gl_ctxt.mDecodedImgTexture;
301*89a0ef05SAndroid Build Coastguard Worker gm_texture_ptr = &dec->m_uhdr_gl_ctxt.mGainmapImgTexture;
302*89a0ef05SAndroid Build Coastguard Worker }
303*89a0ef05SAndroid Build Coastguard Worker #endif
304*89a0ef05SAndroid Build Coastguard Worker for (auto& it : dec->m_effects) {
305*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> disp_img = nullptr;
306*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> gm_img = nullptr;
307*89a0ef05SAndroid Build Coastguard Worker
308*89a0ef05SAndroid Build Coastguard Worker if (nullptr != dynamic_cast<uhdr_rotate_effect_t*>(it)) {
309*89a0ef05SAndroid Build Coastguard Worker disp_img = apply_rotate(dynamic_cast<uhdr_rotate_effect_t*>(it),
310*89a0ef05SAndroid Build Coastguard Worker dec->m_decoded_img_buffer.get(), gl_ctxt, disp_texture_ptr);
311*89a0ef05SAndroid Build Coastguard Worker gm_img = apply_rotate(dynamic_cast<uhdr_rotate_effect_t*>(it),
312*89a0ef05SAndroid Build Coastguard Worker dec->m_gainmap_img_buffer.get(), gl_ctxt, gm_texture_ptr);
313*89a0ef05SAndroid Build Coastguard Worker } else if (nullptr != dynamic_cast<uhdr_mirror_effect_t*>(it)) {
314*89a0ef05SAndroid Build Coastguard Worker disp_img = apply_mirror(dynamic_cast<uhdr_mirror_effect_t*>(it),
315*89a0ef05SAndroid Build Coastguard Worker dec->m_decoded_img_buffer.get(), gl_ctxt, disp_texture_ptr);
316*89a0ef05SAndroid Build Coastguard Worker gm_img = apply_mirror(dynamic_cast<uhdr_mirror_effect_t*>(it),
317*89a0ef05SAndroid Build Coastguard Worker dec->m_gainmap_img_buffer.get(), gl_ctxt, gm_texture_ptr);
318*89a0ef05SAndroid Build Coastguard Worker } else if (nullptr != dynamic_cast<uhdr_crop_effect_t*>(it)) {
319*89a0ef05SAndroid Build Coastguard Worker auto crop_effect = dynamic_cast<uhdr_crop_effect_t*>(it);
320*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t* disp = dec->m_decoded_img_buffer.get();
321*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t* gm = dec->m_gainmap_img_buffer.get();
322*89a0ef05SAndroid Build Coastguard Worker int left = (std::max)(0, crop_effect->m_left);
323*89a0ef05SAndroid Build Coastguard Worker int right = (std::min)((int)disp->w, crop_effect->m_right);
324*89a0ef05SAndroid Build Coastguard Worker if (right <= left) {
325*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
326*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
327*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
328*89a0ef05SAndroid Build Coastguard Worker snprintf(
329*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
330*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop right is <= crop left, after crop image width is %d",
331*89a0ef05SAndroid Build Coastguard Worker right - left);
332*89a0ef05SAndroid Build Coastguard Worker return status;
333*89a0ef05SAndroid Build Coastguard Worker }
334*89a0ef05SAndroid Build Coastguard Worker
335*89a0ef05SAndroid Build Coastguard Worker int top = (std::max)(0, crop_effect->m_top);
336*89a0ef05SAndroid Build Coastguard Worker int bottom = (std::min)((int)disp->h, crop_effect->m_bottom);
337*89a0ef05SAndroid Build Coastguard Worker if (bottom <= top) {
338*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
339*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
340*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
341*89a0ef05SAndroid Build Coastguard Worker snprintf(
342*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
343*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop bottom is <= crop top, after crop image height is %d",
344*89a0ef05SAndroid Build Coastguard Worker bottom - top);
345*89a0ef05SAndroid Build Coastguard Worker return status;
346*89a0ef05SAndroid Build Coastguard Worker }
347*89a0ef05SAndroid Build Coastguard Worker
348*89a0ef05SAndroid Build Coastguard Worker float wd_ratio = ((float)disp->w) / gm->w;
349*89a0ef05SAndroid Build Coastguard Worker float ht_ratio = ((float)disp->h) / gm->h;
350*89a0ef05SAndroid Build Coastguard Worker int gm_left = (int)(left / wd_ratio);
351*89a0ef05SAndroid Build Coastguard Worker int gm_right = (int)(right / wd_ratio);
352*89a0ef05SAndroid Build Coastguard Worker if (gm_right <= gm_left) {
353*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
354*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
355*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
356*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
357*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop right is <= crop left for gainmap image, after "
358*89a0ef05SAndroid Build Coastguard Worker "crop gainmap image width is %d",
359*89a0ef05SAndroid Build Coastguard Worker gm_right - gm_left);
360*89a0ef05SAndroid Build Coastguard Worker return status;
361*89a0ef05SAndroid Build Coastguard Worker }
362*89a0ef05SAndroid Build Coastguard Worker
363*89a0ef05SAndroid Build Coastguard Worker int gm_top = (int)(top / ht_ratio);
364*89a0ef05SAndroid Build Coastguard Worker int gm_bottom = (int)(bottom / ht_ratio);
365*89a0ef05SAndroid Build Coastguard Worker if (gm_bottom <= gm_top) {
366*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
367*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
368*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
369*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
370*89a0ef05SAndroid Build Coastguard Worker "unexpected crop dimensions. crop bottom is <= crop top for gainmap image, after "
371*89a0ef05SAndroid Build Coastguard Worker "crop gainmap image height is %d",
372*89a0ef05SAndroid Build Coastguard Worker gm_bottom - gm_top);
373*89a0ef05SAndroid Build Coastguard Worker return status;
374*89a0ef05SAndroid Build Coastguard Worker }
375*89a0ef05SAndroid Build Coastguard Worker
376*89a0ef05SAndroid Build Coastguard Worker disp_img = apply_crop(dynamic_cast<ultrahdr::uhdr_crop_effect_t*>(it), disp, left, top,
377*89a0ef05SAndroid Build Coastguard Worker right - left, bottom - top, gl_ctxt, disp_texture_ptr);
378*89a0ef05SAndroid Build Coastguard Worker gm_img = apply_crop(dynamic_cast<ultrahdr::uhdr_crop_effect_t*>(it), gm, gm_left, gm_top,
379*89a0ef05SAndroid Build Coastguard Worker (gm_right - gm_left), (gm_bottom - gm_top), gl_ctxt, gm_texture_ptr);
380*89a0ef05SAndroid Build Coastguard Worker } else if (nullptr != dynamic_cast<uhdr_resize_effect_t*>(it)) {
381*89a0ef05SAndroid Build Coastguard Worker auto resize_effect = dynamic_cast<uhdr_resize_effect_t*>(it);
382*89a0ef05SAndroid Build Coastguard Worker int dst_w = resize_effect->m_width;
383*89a0ef05SAndroid Build Coastguard Worker int dst_h = resize_effect->m_height;
384*89a0ef05SAndroid Build Coastguard Worker float wd_ratio =
385*89a0ef05SAndroid Build Coastguard Worker ((float)dec->m_decoded_img_buffer.get()->w) / dec->m_gainmap_img_buffer.get()->w;
386*89a0ef05SAndroid Build Coastguard Worker float ht_ratio =
387*89a0ef05SAndroid Build Coastguard Worker ((float)dec->m_decoded_img_buffer.get()->h) / dec->m_gainmap_img_buffer.get()->h;
388*89a0ef05SAndroid Build Coastguard Worker int dst_gm_w = (int)(dst_w / wd_ratio);
389*89a0ef05SAndroid Build Coastguard Worker int dst_gm_h = (int)(dst_h / ht_ratio);
390*89a0ef05SAndroid Build Coastguard Worker if (dst_w <= 0 || dst_h <= 0 || dst_gm_w <= 0 || dst_gm_h <= 0 ||
391*89a0ef05SAndroid Build Coastguard Worker dst_w > ultrahdr::kMaxWidth || dst_h > ultrahdr::kMaxHeight ||
392*89a0ef05SAndroid Build Coastguard Worker dst_gm_w > ultrahdr::kMaxWidth || dst_gm_h > ultrahdr::kMaxHeight) {
393*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
394*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
395*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
396*89a0ef05SAndroid Build Coastguard Worker "destination dimension must be in range (0, %d] x (0, %d]. dest image width is "
397*89a0ef05SAndroid Build Coastguard Worker "%d, dest image height is %d, dest gainmap width is %d, dest gainmap height is %d",
398*89a0ef05SAndroid Build Coastguard Worker ultrahdr::kMaxWidth, ultrahdr::kMaxHeight, dst_w, dst_h, dst_gm_w, dst_gm_h);
399*89a0ef05SAndroid Build Coastguard Worker return status;
400*89a0ef05SAndroid Build Coastguard Worker }
401*89a0ef05SAndroid Build Coastguard Worker disp_img =
402*89a0ef05SAndroid Build Coastguard Worker apply_resize(dynamic_cast<uhdr_resize_effect_t*>(it), dec->m_decoded_img_buffer.get(),
403*89a0ef05SAndroid Build Coastguard Worker dst_w, dst_h, gl_ctxt, disp_texture_ptr);
404*89a0ef05SAndroid Build Coastguard Worker gm_img =
405*89a0ef05SAndroid Build Coastguard Worker apply_resize(dynamic_cast<uhdr_resize_effect_t*>(it), dec->m_gainmap_img_buffer.get(),
406*89a0ef05SAndroid Build Coastguard Worker dst_gm_w, dst_gm_h, gl_ctxt, gm_texture_ptr);
407*89a0ef05SAndroid Build Coastguard Worker }
408*89a0ef05SAndroid Build Coastguard Worker
409*89a0ef05SAndroid Build Coastguard Worker if (disp_img == nullptr || gm_img == nullptr) {
410*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
411*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_UNKNOWN_ERROR;
412*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
413*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
414*89a0ef05SAndroid Build Coastguard Worker "encountered unknown error while applying effect %s", it->to_string().c_str());
415*89a0ef05SAndroid Build Coastguard Worker return status;
416*89a0ef05SAndroid Build Coastguard Worker }
417*89a0ef05SAndroid Build Coastguard Worker dec->m_decoded_img_buffer = std::move(disp_img);
418*89a0ef05SAndroid Build Coastguard Worker dec->m_gainmap_img_buffer = std::move(gm_img);
419*89a0ef05SAndroid Build Coastguard Worker }
420*89a0ef05SAndroid Build Coastguard Worker return g_no_error;
421*89a0ef05SAndroid Build Coastguard Worker }
422*89a0ef05SAndroid Build Coastguard Worker
uhdr_validate_gainmap_metadata_descriptor(uhdr_gainmap_metadata_t * metadata)423*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_validate_gainmap_metadata_descriptor(uhdr_gainmap_metadata_t* metadata) {
424*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
425*89a0ef05SAndroid Build Coastguard Worker
426*89a0ef05SAndroid Build Coastguard Worker if (metadata == nullptr) {
427*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
428*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
429*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
430*89a0ef05SAndroid Build Coastguard Worker "received nullptr for gainmap metadata descriptor");
431*89a0ef05SAndroid Build Coastguard Worker } else if (!std::isfinite(metadata->min_content_boost) ||
432*89a0ef05SAndroid Build Coastguard Worker !std::isfinite(metadata->max_content_boost) || !std::isfinite(metadata->offset_sdr) ||
433*89a0ef05SAndroid Build Coastguard Worker !std::isfinite(metadata->offset_hdr) || !std::isfinite(metadata->hdr_capacity_min) ||
434*89a0ef05SAndroid Build Coastguard Worker !std::isfinite(metadata->hdr_capacity_max) || !std::isfinite(metadata->gamma)) {
435*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
436*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
437*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
438*89a0ef05SAndroid Build Coastguard Worker "Field(s) of gainmap metadata descriptor are either NaN or infinite. min content "
439*89a0ef05SAndroid Build Coastguard Worker "boost %f, max content boost %f, offset sdr %f, offset hdr %f, hdr capacity min %f, "
440*89a0ef05SAndroid Build Coastguard Worker "hdr capacity max %f, gamma %f",
441*89a0ef05SAndroid Build Coastguard Worker metadata->min_content_boost, metadata->max_content_boost, metadata->offset_sdr,
442*89a0ef05SAndroid Build Coastguard Worker metadata->offset_hdr, metadata->hdr_capacity_min, metadata->hdr_capacity_max,
443*89a0ef05SAndroid Build Coastguard Worker metadata->gamma);
444*89a0ef05SAndroid Build Coastguard Worker } else if (metadata->max_content_boost < metadata->min_content_boost) {
445*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
446*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
447*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
448*89a0ef05SAndroid Build Coastguard Worker "received bad value for content boost max %f, expects to be >= content boost min %f",
449*89a0ef05SAndroid Build Coastguard Worker metadata->max_content_boost, metadata->min_content_boost);
450*89a0ef05SAndroid Build Coastguard Worker } else if (metadata->min_content_boost <= 0.0f) {
451*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
452*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
453*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
454*89a0ef05SAndroid Build Coastguard Worker "received bad value for min boost %f, expects > 0.0f", metadata->min_content_boost);
455*89a0ef05SAndroid Build Coastguard Worker return status;
456*89a0ef05SAndroid Build Coastguard Worker } else if (metadata->gamma <= 0.0f) {
457*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
458*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
459*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received bad value for gamma %f, expects > 0.0f",
460*89a0ef05SAndroid Build Coastguard Worker metadata->gamma);
461*89a0ef05SAndroid Build Coastguard Worker } else if (metadata->offset_sdr < 0.0f) {
462*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
463*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
464*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
465*89a0ef05SAndroid Build Coastguard Worker "received bad value for offset sdr %f, expects to be >= 0.0f", metadata->offset_sdr);
466*89a0ef05SAndroid Build Coastguard Worker } else if (metadata->offset_hdr < 0.0f) {
467*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
468*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
469*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
470*89a0ef05SAndroid Build Coastguard Worker "received bad value for offset hdr %f, expects to be >= 0.0f", metadata->offset_hdr);
471*89a0ef05SAndroid Build Coastguard Worker } else if (metadata->hdr_capacity_max <= metadata->hdr_capacity_min) {
472*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
473*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
474*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
475*89a0ef05SAndroid Build Coastguard Worker "received bad value for hdr capacity max %f, expects to be > hdr capacity min %f",
476*89a0ef05SAndroid Build Coastguard Worker metadata->hdr_capacity_max, metadata->hdr_capacity_min);
477*89a0ef05SAndroid Build Coastguard Worker } else if (metadata->hdr_capacity_min < 1.0f) {
478*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
479*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
480*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
481*89a0ef05SAndroid Build Coastguard Worker "received bad value for hdr capacity min %f, expects to be >= 1.0f",
482*89a0ef05SAndroid Build Coastguard Worker metadata->hdr_capacity_min);
483*89a0ef05SAndroid Build Coastguard Worker }
484*89a0ef05SAndroid Build Coastguard Worker return status;
485*89a0ef05SAndroid Build Coastguard Worker }
486*89a0ef05SAndroid Build Coastguard Worker
487*89a0ef05SAndroid Build Coastguard Worker } // namespace ultrahdr
488*89a0ef05SAndroid Build Coastguard Worker
~uhdr_codec_private()489*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private::~uhdr_codec_private() {
490*89a0ef05SAndroid Build Coastguard Worker for (auto it : m_effects) delete it;
491*89a0ef05SAndroid Build Coastguard Worker m_effects.clear();
492*89a0ef05SAndroid Build Coastguard Worker }
493*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_validate_and_set_compressed_img(uhdr_codec_private_t * enc,uhdr_compressed_image_t * img,uhdr_img_label_t intent)494*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_validate_and_set_compressed_img(uhdr_codec_private_t* enc,
495*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t* img,
496*89a0ef05SAndroid Build Coastguard Worker uhdr_img_label_t intent) {
497*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
498*89a0ef05SAndroid Build Coastguard Worker
499*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
500*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
501*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
502*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
503*89a0ef05SAndroid Build Coastguard Worker } else if (img == nullptr) {
504*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
505*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
506*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for compressed image handle");
507*89a0ef05SAndroid Build Coastguard Worker } else if (img->data == nullptr) {
508*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
509*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
510*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
511*89a0ef05SAndroid Build Coastguard Worker "received nullptr for compressed img->data field");
512*89a0ef05SAndroid Build Coastguard Worker } else if (img->capacity < img->data_sz) {
513*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
514*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
515*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "img->capacity %zd is less than img->data_sz %zd",
516*89a0ef05SAndroid Build Coastguard Worker img->capacity, img->data_sz);
517*89a0ef05SAndroid Build Coastguard Worker }
518*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
519*89a0ef05SAndroid Build Coastguard Worker
520*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
521*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
522*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
523*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
524*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
525*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
526*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
527*89a0ef05SAndroid Build Coastguard Worker return status;
528*89a0ef05SAndroid Build Coastguard Worker }
529*89a0ef05SAndroid Build Coastguard Worker
530*89a0ef05SAndroid Build Coastguard Worker std::shared_ptr<DataSegment> seg =
531*89a0ef05SAndroid Build Coastguard Worker DataSegment::Create(DataRange(0, img->data_sz), static_cast<const uint8_t*>(img->data),
532*89a0ef05SAndroid Build Coastguard Worker DataSegment::BufferDispositionPolicy::kDontDelete);
533*89a0ef05SAndroid Build Coastguard Worker DataSegmentDataSource data_source(seg);
534*89a0ef05SAndroid Build Coastguard Worker JpegInfoBuilder jpeg_info_builder;
535*89a0ef05SAndroid Build Coastguard Worker JpegScanner jpeg_scanner(nullptr);
536*89a0ef05SAndroid Build Coastguard Worker jpeg_scanner.Run(&data_source, &jpeg_info_builder);
537*89a0ef05SAndroid Build Coastguard Worker data_source.Reset();
538*89a0ef05SAndroid Build Coastguard Worker if (jpeg_scanner.HasError()) {
539*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
540*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
541*89a0ef05SAndroid Build Coastguard Worker "received bad/corrupted jpeg image as part of input configuration");
542*89a0ef05SAndroid Build Coastguard Worker return status;
543*89a0ef05SAndroid Build Coastguard Worker }
544*89a0ef05SAndroid Build Coastguard Worker
545*89a0ef05SAndroid Build Coastguard Worker const auto& image_ranges = jpeg_info_builder.GetInfo().GetImageRanges();
546*89a0ef05SAndroid Build Coastguard Worker if (image_ranges.empty()) {
547*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
548*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
549*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
550*89a0ef05SAndroid Build Coastguard Worker "compressed image received as part of input config contains no valid jpeg images");
551*89a0ef05SAndroid Build Coastguard Worker return status;
552*89a0ef05SAndroid Build Coastguard Worker }
553*89a0ef05SAndroid Build Coastguard Worker
554*89a0ef05SAndroid Build Coastguard Worker if (image_ranges.size() > 1) {
555*89a0ef05SAndroid Build Coastguard Worker ALOGW(
556*89a0ef05SAndroid Build Coastguard Worker "compressed image received as part of input config contains multiple jpeg images, "
557*89a0ef05SAndroid Build Coastguard Worker "selecting first image for intent %d, rest are ignored",
558*89a0ef05SAndroid Build Coastguard Worker intent);
559*89a0ef05SAndroid Build Coastguard Worker }
560*89a0ef05SAndroid Build Coastguard Worker
561*89a0ef05SAndroid Build Coastguard Worker auto entry = std::make_unique<ultrahdr::uhdr_compressed_image_ext_t>(img->cg, img->ct, img->range,
562*89a0ef05SAndroid Build Coastguard Worker image_ranges[0].GetLength());
563*89a0ef05SAndroid Build Coastguard Worker memcpy(entry->data, static_cast<uint8_t*>(img->data) + image_ranges[0].GetBegin(),
564*89a0ef05SAndroid Build Coastguard Worker image_ranges[0].GetLength());
565*89a0ef05SAndroid Build Coastguard Worker entry->data_sz = image_ranges[0].GetLength();
566*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_images.insert_or_assign(intent, std::move(entry));
567*89a0ef05SAndroid Build Coastguard Worker
568*89a0ef05SAndroid Build Coastguard Worker return status;
569*89a0ef05SAndroid Build Coastguard Worker }
570*89a0ef05SAndroid Build Coastguard Worker
uhdr_create_encoder(void)571*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private_t* uhdr_create_encoder(void) {
572*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = new uhdr_encoder_private();
573*89a0ef05SAndroid Build Coastguard Worker
574*89a0ef05SAndroid Build Coastguard Worker if (handle != nullptr) {
575*89a0ef05SAndroid Build Coastguard Worker uhdr_reset_encoder(handle);
576*89a0ef05SAndroid Build Coastguard Worker }
577*89a0ef05SAndroid Build Coastguard Worker return handle;
578*89a0ef05SAndroid Build Coastguard Worker }
579*89a0ef05SAndroid Build Coastguard Worker
uhdr_release_encoder(uhdr_codec_private_t * enc)580*89a0ef05SAndroid Build Coastguard Worker void uhdr_release_encoder(uhdr_codec_private_t* enc) {
581*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) != nullptr) {
582*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
583*89a0ef05SAndroid Build Coastguard Worker delete handle;
584*89a0ef05SAndroid Build Coastguard Worker }
585*89a0ef05SAndroid Build Coastguard Worker }
586*89a0ef05SAndroid Build Coastguard Worker
587*89a0ef05SAndroid Build Coastguard Worker UHDR_EXTERN uhdr_error_info_t
uhdr_enc_set_using_multi_channel_gainmap(uhdr_codec_private_t * enc,int use_multi_channel_gainmap)588*89a0ef05SAndroid Build Coastguard Worker uhdr_enc_set_using_multi_channel_gainmap(uhdr_codec_private_t* enc, int use_multi_channel_gainmap) {
589*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
590*89a0ef05SAndroid Build Coastguard Worker
591*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
592*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
593*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
594*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
595*89a0ef05SAndroid Build Coastguard Worker return status;
596*89a0ef05SAndroid Build Coastguard Worker }
597*89a0ef05SAndroid Build Coastguard Worker
598*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
599*89a0ef05SAndroid Build Coastguard Worker
600*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
601*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
602*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
603*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
604*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
605*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
606*89a0ef05SAndroid Build Coastguard Worker return status;
607*89a0ef05SAndroid Build Coastguard Worker }
608*89a0ef05SAndroid Build Coastguard Worker
609*89a0ef05SAndroid Build Coastguard Worker handle->m_use_multi_channel_gainmap = use_multi_channel_gainmap;
610*89a0ef05SAndroid Build Coastguard Worker
611*89a0ef05SAndroid Build Coastguard Worker return status;
612*89a0ef05SAndroid Build Coastguard Worker }
613*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_gainmap_scale_factor(uhdr_codec_private_t * enc,int gainmap_scale_factor)614*89a0ef05SAndroid Build Coastguard Worker UHDR_EXTERN uhdr_error_info_t uhdr_enc_set_gainmap_scale_factor(uhdr_codec_private_t* enc,
615*89a0ef05SAndroid Build Coastguard Worker int gainmap_scale_factor) {
616*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
617*89a0ef05SAndroid Build Coastguard Worker
618*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
619*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
620*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
621*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
622*89a0ef05SAndroid Build Coastguard Worker return status;
623*89a0ef05SAndroid Build Coastguard Worker }
624*89a0ef05SAndroid Build Coastguard Worker
625*89a0ef05SAndroid Build Coastguard Worker if (gainmap_scale_factor <= 0 || gainmap_scale_factor > 128) {
626*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
627*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
628*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
629*89a0ef05SAndroid Build Coastguard Worker "gainmap scale factor is expected to be in range (0, 128], received %d",
630*89a0ef05SAndroid Build Coastguard Worker gainmap_scale_factor);
631*89a0ef05SAndroid Build Coastguard Worker return status;
632*89a0ef05SAndroid Build Coastguard Worker }
633*89a0ef05SAndroid Build Coastguard Worker
634*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
635*89a0ef05SAndroid Build Coastguard Worker
636*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
637*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
638*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
639*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
640*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
641*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
642*89a0ef05SAndroid Build Coastguard Worker return status;
643*89a0ef05SAndroid Build Coastguard Worker }
644*89a0ef05SAndroid Build Coastguard Worker
645*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_scale_factor = gainmap_scale_factor;
646*89a0ef05SAndroid Build Coastguard Worker
647*89a0ef05SAndroid Build Coastguard Worker return status;
648*89a0ef05SAndroid Build Coastguard Worker }
649*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_gainmap_gamma(uhdr_codec_private_t * enc,float gamma)650*89a0ef05SAndroid Build Coastguard Worker UHDR_EXTERN uhdr_error_info_t uhdr_enc_set_gainmap_gamma(uhdr_codec_private_t* enc, float gamma) {
651*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
652*89a0ef05SAndroid Build Coastguard Worker
653*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
654*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
655*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
656*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
657*89a0ef05SAndroid Build Coastguard Worker return status;
658*89a0ef05SAndroid Build Coastguard Worker }
659*89a0ef05SAndroid Build Coastguard Worker
660*89a0ef05SAndroid Build Coastguard Worker if (!std::isfinite(gamma) || gamma <= 0.0f) {
661*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
662*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
663*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "unsupported gainmap gamma %f, expects to be > 0",
664*89a0ef05SAndroid Build Coastguard Worker gamma);
665*89a0ef05SAndroid Build Coastguard Worker return status;
666*89a0ef05SAndroid Build Coastguard Worker }
667*89a0ef05SAndroid Build Coastguard Worker
668*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
669*89a0ef05SAndroid Build Coastguard Worker
670*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
671*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
672*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
673*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
674*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
675*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
676*89a0ef05SAndroid Build Coastguard Worker return status;
677*89a0ef05SAndroid Build Coastguard Worker }
678*89a0ef05SAndroid Build Coastguard Worker
679*89a0ef05SAndroid Build Coastguard Worker handle->m_gamma = gamma;
680*89a0ef05SAndroid Build Coastguard Worker
681*89a0ef05SAndroid Build Coastguard Worker return status;
682*89a0ef05SAndroid Build Coastguard Worker }
683*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_preset(uhdr_codec_private_t * enc,uhdr_enc_preset_t preset)684*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_preset(uhdr_codec_private_t* enc, uhdr_enc_preset_t preset) {
685*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
686*89a0ef05SAndroid Build Coastguard Worker
687*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
688*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
689*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
690*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
691*89a0ef05SAndroid Build Coastguard Worker return status;
692*89a0ef05SAndroid Build Coastguard Worker }
693*89a0ef05SAndroid Build Coastguard Worker
694*89a0ef05SAndroid Build Coastguard Worker if (preset != UHDR_USAGE_REALTIME && preset != UHDR_USAGE_BEST_QUALITY) {
695*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
696*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
697*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
698*89a0ef05SAndroid Build Coastguard Worker "invalid preset %d, expects one of {UHDR_USAGE_REALTIME, UHDR_USAGE_BEST_QUALITY}",
699*89a0ef05SAndroid Build Coastguard Worker preset);
700*89a0ef05SAndroid Build Coastguard Worker return status;
701*89a0ef05SAndroid Build Coastguard Worker }
702*89a0ef05SAndroid Build Coastguard Worker
703*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
704*89a0ef05SAndroid Build Coastguard Worker
705*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
706*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
707*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
708*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
709*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
710*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
711*89a0ef05SAndroid Build Coastguard Worker return status;
712*89a0ef05SAndroid Build Coastguard Worker }
713*89a0ef05SAndroid Build Coastguard Worker
714*89a0ef05SAndroid Build Coastguard Worker handle->m_enc_preset = preset;
715*89a0ef05SAndroid Build Coastguard Worker
716*89a0ef05SAndroid Build Coastguard Worker return status;
717*89a0ef05SAndroid Build Coastguard Worker }
718*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_min_max_content_boost(uhdr_codec_private_t * enc,float min_boost,float max_boost)719*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_min_max_content_boost(uhdr_codec_private_t* enc, float min_boost,
720*89a0ef05SAndroid Build Coastguard Worker float max_boost) {
721*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
722*89a0ef05SAndroid Build Coastguard Worker
723*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
724*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
725*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
726*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
727*89a0ef05SAndroid Build Coastguard Worker return status;
728*89a0ef05SAndroid Build Coastguard Worker }
729*89a0ef05SAndroid Build Coastguard Worker
730*89a0ef05SAndroid Build Coastguard Worker if (!std::isfinite(min_boost) || !std::isfinite(max_boost)) {
731*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
732*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
733*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
734*89a0ef05SAndroid Build Coastguard Worker "received an argument with value either NaN or infinite. Configured min boost %f, "
735*89a0ef05SAndroid Build Coastguard Worker "max boost %f",
736*89a0ef05SAndroid Build Coastguard Worker max_boost, min_boost);
737*89a0ef05SAndroid Build Coastguard Worker return status;
738*89a0ef05SAndroid Build Coastguard Worker }
739*89a0ef05SAndroid Build Coastguard Worker
740*89a0ef05SAndroid Build Coastguard Worker if (max_boost < min_boost) {
741*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
742*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
743*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
744*89a0ef05SAndroid Build Coastguard Worker "Invalid min boost / max boost configuration. configured max boost %f is less than "
745*89a0ef05SAndroid Build Coastguard Worker "min boost %f",
746*89a0ef05SAndroid Build Coastguard Worker max_boost, min_boost);
747*89a0ef05SAndroid Build Coastguard Worker return status;
748*89a0ef05SAndroid Build Coastguard Worker }
749*89a0ef05SAndroid Build Coastguard Worker
750*89a0ef05SAndroid Build Coastguard Worker if (min_boost <= 0.0f) {
751*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
752*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
753*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
754*89a0ef05SAndroid Build Coastguard Worker "Invalid min boost configuration %f, expects > 0.0f", min_boost);
755*89a0ef05SAndroid Build Coastguard Worker return status;
756*89a0ef05SAndroid Build Coastguard Worker }
757*89a0ef05SAndroid Build Coastguard Worker
758*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
759*89a0ef05SAndroid Build Coastguard Worker
760*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
761*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
762*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
763*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
764*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
765*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
766*89a0ef05SAndroid Build Coastguard Worker return status;
767*89a0ef05SAndroid Build Coastguard Worker }
768*89a0ef05SAndroid Build Coastguard Worker
769*89a0ef05SAndroid Build Coastguard Worker handle->m_min_content_boost = min_boost;
770*89a0ef05SAndroid Build Coastguard Worker handle->m_max_content_boost = max_boost;
771*89a0ef05SAndroid Build Coastguard Worker
772*89a0ef05SAndroid Build Coastguard Worker return status;
773*89a0ef05SAndroid Build Coastguard Worker }
774*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_target_display_peak_brightness(uhdr_codec_private_t * enc,float nits)775*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_target_display_peak_brightness(uhdr_codec_private_t* enc,
776*89a0ef05SAndroid Build Coastguard Worker float nits) {
777*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
778*89a0ef05SAndroid Build Coastguard Worker
779*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
780*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
781*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
782*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
783*89a0ef05SAndroid Build Coastguard Worker return status;
784*89a0ef05SAndroid Build Coastguard Worker }
785*89a0ef05SAndroid Build Coastguard Worker
786*89a0ef05SAndroid Build Coastguard Worker if (!std::isfinite(nits) || nits < ultrahdr::kSdrWhiteNits || nits > ultrahdr::kPqMaxNits) {
787*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
788*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
789*89a0ef05SAndroid Build Coastguard Worker snprintf(
790*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
791*89a0ef05SAndroid Build Coastguard Worker "unexpected target display peak brightness nits %f, expects to be with in range [%f, %f]",
792*89a0ef05SAndroid Build Coastguard Worker nits, ultrahdr::kSdrWhiteNits, ultrahdr::kPqMaxNits);
793*89a0ef05SAndroid Build Coastguard Worker }
794*89a0ef05SAndroid Build Coastguard Worker
795*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
796*89a0ef05SAndroid Build Coastguard Worker
797*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
798*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
799*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
800*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
801*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
802*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
803*89a0ef05SAndroid Build Coastguard Worker return status;
804*89a0ef05SAndroid Build Coastguard Worker }
805*89a0ef05SAndroid Build Coastguard Worker
806*89a0ef05SAndroid Build Coastguard Worker handle->m_target_disp_max_brightness = nits;
807*89a0ef05SAndroid Build Coastguard Worker
808*89a0ef05SAndroid Build Coastguard Worker return status;
809*89a0ef05SAndroid Build Coastguard Worker }
810*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_raw_image(uhdr_codec_private_t * enc,uhdr_raw_image_t * img,uhdr_img_label_t intent)811*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_raw_image(uhdr_codec_private_t* enc, uhdr_raw_image_t* img,
812*89a0ef05SAndroid Build Coastguard Worker uhdr_img_label_t intent) {
813*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
814*89a0ef05SAndroid Build Coastguard Worker
815*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
816*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
817*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
818*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
819*89a0ef05SAndroid Build Coastguard Worker } else if (img == nullptr) {
820*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
821*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
822*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for raw image handle");
823*89a0ef05SAndroid Build Coastguard Worker } else if (intent != UHDR_HDR_IMG && intent != UHDR_SDR_IMG) {
824*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
825*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
826*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
827*89a0ef05SAndroid Build Coastguard Worker "invalid intent %d, expects one of {UHDR_HDR_IMG, UHDR_SDR_IMG}", intent);
828*89a0ef05SAndroid Build Coastguard Worker } else if (intent == UHDR_HDR_IMG && (img->fmt != UHDR_IMG_FMT_24bppYCbCrP010 &&
829*89a0ef05SAndroid Build Coastguard Worker img->fmt != UHDR_IMG_FMT_32bppRGBA1010102 &&
830*89a0ef05SAndroid Build Coastguard Worker img->fmt != UHDR_IMG_FMT_64bppRGBAHalfFloat)) {
831*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
832*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
833*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
834*89a0ef05SAndroid Build Coastguard Worker "unsupported input pixel format for hdr intent %d, expects one of "
835*89a0ef05SAndroid Build Coastguard Worker "{UHDR_IMG_FMT_24bppYCbCrP010, UHDR_IMG_FMT_32bppRGBA1010102, "
836*89a0ef05SAndroid Build Coastguard Worker "UHDR_IMG_FMT_64bppRGBAHalfFloat}",
837*89a0ef05SAndroid Build Coastguard Worker img->fmt);
838*89a0ef05SAndroid Build Coastguard Worker } else if (intent == UHDR_SDR_IMG &&
839*89a0ef05SAndroid Build Coastguard Worker (img->fmt != UHDR_IMG_FMT_12bppYCbCr420 && img->fmt != UHDR_IMG_FMT_32bppRGBA8888)) {
840*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
841*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
842*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
843*89a0ef05SAndroid Build Coastguard Worker "unsupported input pixel format for sdr intent %d, expects one of "
844*89a0ef05SAndroid Build Coastguard Worker "{UHDR_IMG_FMT_12bppYCbCr420, UHDR_IMG_FMT_32bppRGBA8888}",
845*89a0ef05SAndroid Build Coastguard Worker img->fmt);
846*89a0ef05SAndroid Build Coastguard Worker } else if (img->cg != UHDR_CG_BT_2100 && img->cg != UHDR_CG_DISPLAY_P3 &&
847*89a0ef05SAndroid Build Coastguard Worker img->cg != UHDR_CG_BT_709) {
848*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
849*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
850*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
851*89a0ef05SAndroid Build Coastguard Worker "invalid input color gamut %d, expects one of {UHDR_CG_BT_2100, UHDR_CG_DISPLAY_P3, "
852*89a0ef05SAndroid Build Coastguard Worker "UHDR_CG_BT_709}",
853*89a0ef05SAndroid Build Coastguard Worker img->cg);
854*89a0ef05SAndroid Build Coastguard Worker } else if (intent == UHDR_SDR_IMG && img->ct != UHDR_CT_SRGB) {
855*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
856*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
857*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
858*89a0ef05SAndroid Build Coastguard Worker "invalid input color transfer for sdr intent image %d, expects UHDR_CT_SRGB", img->ct);
859*89a0ef05SAndroid Build Coastguard Worker } else if (intent == UHDR_HDR_IMG && img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat &&
860*89a0ef05SAndroid Build Coastguard Worker img->ct != UHDR_CT_LINEAR) {
861*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
862*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
863*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
864*89a0ef05SAndroid Build Coastguard Worker "invalid input color transfer for hdr intent image %d with format "
865*89a0ef05SAndroid Build Coastguard Worker "UHDR_IMG_FMT_64bppRGBAHalfFloat, expects one of {UHDR_CT_LINEAR}",
866*89a0ef05SAndroid Build Coastguard Worker img->ct);
867*89a0ef05SAndroid Build Coastguard Worker } else if (intent == UHDR_HDR_IMG && img->fmt != UHDR_IMG_FMT_64bppRGBAHalfFloat &&
868*89a0ef05SAndroid Build Coastguard Worker (img->ct != UHDR_CT_HLG && img->ct != UHDR_CT_PQ)) {
869*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
870*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
871*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
872*89a0ef05SAndroid Build Coastguard Worker "invalid input color transfer for hdr intent image %d with format %d, expects one of "
873*89a0ef05SAndroid Build Coastguard Worker "{UHDR_CT_HLG, UHDR_CT_PQ}",
874*89a0ef05SAndroid Build Coastguard Worker img->fmt, img->ct);
875*89a0ef05SAndroid Build Coastguard Worker } else if ((img->w % 2 != 0 || img->h % 2 != 0) &&
876*89a0ef05SAndroid Build Coastguard Worker (img->fmt == UHDR_IMG_FMT_12bppYCbCr420 || img->fmt == UHDR_IMG_FMT_24bppYCbCrP010)) {
877*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
878*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
879*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
880*89a0ef05SAndroid Build Coastguard Worker "image dimensions cannot be odd for formats {UHDR_IMG_FMT_12bppYCbCr420, "
881*89a0ef05SAndroid Build Coastguard Worker "UHDR_IMG_FMT_24bppYCbCrP010}, received image dimensions %dx%d",
882*89a0ef05SAndroid Build Coastguard Worker img->w, img->h);
883*89a0ef05SAndroid Build Coastguard Worker } else if ((int)img->w < ultrahdr::kMinWidth || (int)img->h < ultrahdr::kMinHeight) {
884*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
885*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
886*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
887*89a0ef05SAndroid Build Coastguard Worker "image dimensions cannot be less than %dx%d, received image dimensions %dx%d",
888*89a0ef05SAndroid Build Coastguard Worker ultrahdr::kMinWidth, ultrahdr::kMinHeight, img->w, img->h);
889*89a0ef05SAndroid Build Coastguard Worker } else if ((int)img->w > ultrahdr::kMaxWidth || (int)img->h > ultrahdr::kMaxHeight) {
890*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
891*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
892*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
893*89a0ef05SAndroid Build Coastguard Worker "image dimensions cannot be larger than %dx%d, received image dimensions %dx%d",
894*89a0ef05SAndroid Build Coastguard Worker ultrahdr::kMaxWidth, ultrahdr::kMaxHeight, img->w, img->h);
895*89a0ef05SAndroid Build Coastguard Worker } else if (img->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
896*89a0ef05SAndroid Build Coastguard Worker if (img->planes[UHDR_PLANE_Y] == nullptr || img->planes[UHDR_PLANE_UV] == nullptr) {
897*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
898*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
899*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
900*89a0ef05SAndroid Build Coastguard Worker "received nullptr for data field(s), luma ptr %p, chroma_uv ptr %p",
901*89a0ef05SAndroid Build Coastguard Worker img->planes[UHDR_PLANE_Y], img->planes[UHDR_PLANE_UV]);
902*89a0ef05SAndroid Build Coastguard Worker } else if (img->stride[UHDR_PLANE_Y] < img->w) {
903*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
904*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
905*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
906*89a0ef05SAndroid Build Coastguard Worker "luma stride must not be smaller than width, stride=%d, width=%d",
907*89a0ef05SAndroid Build Coastguard Worker img->stride[UHDR_PLANE_Y], img->w);
908*89a0ef05SAndroid Build Coastguard Worker } else if (img->stride[UHDR_PLANE_UV] < img->w) {
909*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
910*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
911*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
912*89a0ef05SAndroid Build Coastguard Worker "chroma_uv stride must not be smaller than width, stride=%d, width=%d",
913*89a0ef05SAndroid Build Coastguard Worker img->stride[UHDR_PLANE_UV], img->w);
914*89a0ef05SAndroid Build Coastguard Worker } else if (img->fmt == UHDR_IMG_FMT_24bppYCbCrP010 &&
915*89a0ef05SAndroid Build Coastguard Worker (img->range != UHDR_CR_FULL_RANGE && img->range != UHDR_CR_LIMITED_RANGE)) {
916*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
917*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
918*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
919*89a0ef05SAndroid Build Coastguard Worker "invalid range, expects one of {UHDR_CR_FULL_RANGE, UHDR_CR_LIMITED_RANGE}");
920*89a0ef05SAndroid Build Coastguard Worker } else if (img->fmt == UHDR_IMG_FMT_32bppRGBA1010102 && img->range != UHDR_CR_FULL_RANGE) {
921*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
922*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
923*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
924*89a0ef05SAndroid Build Coastguard Worker "invalid range, expects one of {UHDR_CR_FULL_RANGE}");
925*89a0ef05SAndroid Build Coastguard Worker }
926*89a0ef05SAndroid Build Coastguard Worker } else if (img->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
927*89a0ef05SAndroid Build Coastguard Worker if (img->planes[UHDR_PLANE_Y] == nullptr || img->planes[UHDR_PLANE_U] == nullptr ||
928*89a0ef05SAndroid Build Coastguard Worker img->planes[UHDR_PLANE_V] == nullptr) {
929*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
930*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
931*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
932*89a0ef05SAndroid Build Coastguard Worker "received nullptr for data field(s) luma ptr %p, chroma_u ptr %p, chroma_v ptr %p",
933*89a0ef05SAndroid Build Coastguard Worker img->planes[UHDR_PLANE_Y], img->planes[UHDR_PLANE_U], img->planes[UHDR_PLANE_V]);
934*89a0ef05SAndroid Build Coastguard Worker } else if (img->stride[UHDR_PLANE_Y] < img->w) {
935*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
936*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
937*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
938*89a0ef05SAndroid Build Coastguard Worker "luma stride must not be smaller than width, stride=%d, width=%d",
939*89a0ef05SAndroid Build Coastguard Worker img->stride[UHDR_PLANE_Y], img->w);
940*89a0ef05SAndroid Build Coastguard Worker } else if (img->stride[UHDR_PLANE_U] < img->w / 2) {
941*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
942*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
943*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
944*89a0ef05SAndroid Build Coastguard Worker "chroma_u stride must not be smaller than width / 2, stride=%d, width=%d",
945*89a0ef05SAndroid Build Coastguard Worker img->stride[UHDR_PLANE_U], img->w);
946*89a0ef05SAndroid Build Coastguard Worker } else if (img->stride[UHDR_PLANE_V] < img->w / 2) {
947*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
948*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
949*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
950*89a0ef05SAndroid Build Coastguard Worker "chroma_v stride must not be smaller than width / 2, stride=%d, width=%d",
951*89a0ef05SAndroid Build Coastguard Worker img->stride[UHDR_PLANE_V], img->w);
952*89a0ef05SAndroid Build Coastguard Worker } else if (img->range != UHDR_CR_FULL_RANGE) {
953*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
954*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
955*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
956*89a0ef05SAndroid Build Coastguard Worker "invalid range, expects one of {UHDR_CR_FULL_RANGE}");
957*89a0ef05SAndroid Build Coastguard Worker }
958*89a0ef05SAndroid Build Coastguard Worker } else if (img->fmt == UHDR_IMG_FMT_32bppRGBA1010102 || img->fmt == UHDR_IMG_FMT_32bppRGBA8888 ||
959*89a0ef05SAndroid Build Coastguard Worker img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
960*89a0ef05SAndroid Build Coastguard Worker if (img->planes[UHDR_PLANE_PACKED] == nullptr) {
961*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
962*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
963*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
964*89a0ef05SAndroid Build Coastguard Worker "received nullptr for data field(s) rgb plane packed ptr %p",
965*89a0ef05SAndroid Build Coastguard Worker img->planes[UHDR_PLANE_PACKED]);
966*89a0ef05SAndroid Build Coastguard Worker } else if (img->stride[UHDR_PLANE_PACKED] < img->w) {
967*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
968*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
969*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
970*89a0ef05SAndroid Build Coastguard Worker "rgb planar stride must not be smaller than width, stride=%d, width=%d",
971*89a0ef05SAndroid Build Coastguard Worker img->stride[UHDR_PLANE_PACKED], img->w);
972*89a0ef05SAndroid Build Coastguard Worker } else if (img->range != UHDR_CR_FULL_RANGE) {
973*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
974*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
975*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
976*89a0ef05SAndroid Build Coastguard Worker "invalid range, expects one of {UHDR_CR_FULL_RANGE}");
977*89a0ef05SAndroid Build Coastguard Worker }
978*89a0ef05SAndroid Build Coastguard Worker }
979*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
980*89a0ef05SAndroid Build Coastguard Worker
981*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
982*89a0ef05SAndroid Build Coastguard Worker if (intent == UHDR_HDR_IMG &&
983*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.find(UHDR_SDR_IMG) != handle->m_raw_images.end()) {
984*89a0ef05SAndroid Build Coastguard Worker auto& sdr_raw_entry = handle->m_raw_images.find(UHDR_SDR_IMG)->second;
985*89a0ef05SAndroid Build Coastguard Worker if (img->w != sdr_raw_entry->w || img->h != sdr_raw_entry->h) {
986*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
987*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
988*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
989*89a0ef05SAndroid Build Coastguard Worker "image resolutions mismatch: hdr intent: %dx%d, sdr intent: %dx%d", img->w, img->h,
990*89a0ef05SAndroid Build Coastguard Worker sdr_raw_entry->w, sdr_raw_entry->h);
991*89a0ef05SAndroid Build Coastguard Worker return status;
992*89a0ef05SAndroid Build Coastguard Worker }
993*89a0ef05SAndroid Build Coastguard Worker }
994*89a0ef05SAndroid Build Coastguard Worker if (intent == UHDR_SDR_IMG &&
995*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.find(UHDR_HDR_IMG) != handle->m_raw_images.end()) {
996*89a0ef05SAndroid Build Coastguard Worker auto& hdr_raw_entry = handle->m_raw_images.find(UHDR_HDR_IMG)->second;
997*89a0ef05SAndroid Build Coastguard Worker if (img->w != hdr_raw_entry->w || img->h != hdr_raw_entry->h) {
998*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
999*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1000*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1001*89a0ef05SAndroid Build Coastguard Worker "image resolutions mismatch: sdr intent: %dx%d, hdr intent: %dx%d", img->w, img->h,
1002*89a0ef05SAndroid Build Coastguard Worker hdr_raw_entry->w, hdr_raw_entry->h);
1003*89a0ef05SAndroid Build Coastguard Worker return status;
1004*89a0ef05SAndroid Build Coastguard Worker }
1005*89a0ef05SAndroid Build Coastguard Worker }
1006*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
1007*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1008*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1009*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1010*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
1011*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1012*89a0ef05SAndroid Build Coastguard Worker return status;
1013*89a0ef05SAndroid Build Coastguard Worker }
1014*89a0ef05SAndroid Build Coastguard Worker
1015*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<ultrahdr::uhdr_raw_image_ext_t> entry = ultrahdr::copy_raw_image(img);
1016*89a0ef05SAndroid Build Coastguard Worker if (entry == nullptr) {
1017*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_UNKNOWN_ERROR;
1018*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1019*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1020*89a0ef05SAndroid Build Coastguard Worker "encountered unknown error during color space conversion");
1021*89a0ef05SAndroid Build Coastguard Worker return status;
1022*89a0ef05SAndroid Build Coastguard Worker }
1023*89a0ef05SAndroid Build Coastguard Worker
1024*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.insert_or_assign(intent, std::move(entry));
1025*89a0ef05SAndroid Build Coastguard Worker
1026*89a0ef05SAndroid Build Coastguard Worker return status;
1027*89a0ef05SAndroid Build Coastguard Worker }
1028*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_compressed_image(uhdr_codec_private_t * enc,uhdr_compressed_image_t * img,uhdr_img_label_t intent)1029*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_compressed_image(uhdr_codec_private_t* enc,
1030*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t* img,
1031*89a0ef05SAndroid Build Coastguard Worker uhdr_img_label_t intent) {
1032*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1033*89a0ef05SAndroid Build Coastguard Worker
1034*89a0ef05SAndroid Build Coastguard Worker if (intent != UHDR_HDR_IMG && intent != UHDR_SDR_IMG && intent != UHDR_BASE_IMG) {
1035*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1036*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1037*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1038*89a0ef05SAndroid Build Coastguard Worker "invalid intent %d, expects one of {UHDR_HDR_IMG, UHDR_SDR_IMG, UHDR_BASE_IMG}",
1039*89a0ef05SAndroid Build Coastguard Worker intent);
1040*89a0ef05SAndroid Build Coastguard Worker }
1041*89a0ef05SAndroid Build Coastguard Worker
1042*89a0ef05SAndroid Build Coastguard Worker return uhdr_enc_validate_and_set_compressed_img(enc, img, intent);
1043*89a0ef05SAndroid Build Coastguard Worker }
1044*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_gainmap_image(uhdr_codec_private_t * enc,uhdr_compressed_image_t * img,uhdr_gainmap_metadata_t * metadata)1045*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_gainmap_image(uhdr_codec_private_t* enc,
1046*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t* img,
1047*89a0ef05SAndroid Build Coastguard Worker uhdr_gainmap_metadata_t* metadata) {
1048*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = ultrahdr::uhdr_validate_gainmap_metadata_descriptor(metadata);
1049*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1050*89a0ef05SAndroid Build Coastguard Worker
1051*89a0ef05SAndroid Build Coastguard Worker status = uhdr_enc_validate_and_set_compressed_img(enc, img, UHDR_GAIN_MAP_IMG);
1052*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1053*89a0ef05SAndroid Build Coastguard Worker
1054*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
1055*89a0ef05SAndroid Build Coastguard Worker memcpy(&handle->m_metadata, metadata, sizeof *metadata);
1056*89a0ef05SAndroid Build Coastguard Worker
1057*89a0ef05SAndroid Build Coastguard Worker return status;
1058*89a0ef05SAndroid Build Coastguard Worker }
1059*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_quality(uhdr_codec_private_t * enc,int quality,uhdr_img_label_t intent)1060*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_quality(uhdr_codec_private_t* enc, int quality,
1061*89a0ef05SAndroid Build Coastguard Worker uhdr_img_label_t intent) {
1062*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1063*89a0ef05SAndroid Build Coastguard Worker
1064*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
1065*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1066*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1067*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1068*89a0ef05SAndroid Build Coastguard Worker } else if (quality < 0 || quality > 100) {
1069*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1070*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1071*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1072*89a0ef05SAndroid Build Coastguard Worker "invalid quality factor %d, expects in range [0-100]", quality);
1073*89a0ef05SAndroid Build Coastguard Worker } else if (intent != UHDR_HDR_IMG && intent != UHDR_SDR_IMG && intent != UHDR_BASE_IMG &&
1074*89a0ef05SAndroid Build Coastguard Worker intent != UHDR_GAIN_MAP_IMG) {
1075*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1076*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1077*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1078*89a0ef05SAndroid Build Coastguard Worker "invalid intent %d, expects one of {UHDR_HDR_IMG, UHDR_SDR_IMG, UHDR_BASE_IMG, "
1079*89a0ef05SAndroid Build Coastguard Worker "UHDR_GAIN_MAP_IMG}",
1080*89a0ef05SAndroid Build Coastguard Worker intent);
1081*89a0ef05SAndroid Build Coastguard Worker }
1082*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1083*89a0ef05SAndroid Build Coastguard Worker
1084*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
1085*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
1086*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1087*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1088*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1089*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
1090*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1091*89a0ef05SAndroid Build Coastguard Worker return status;
1092*89a0ef05SAndroid Build Coastguard Worker }
1093*89a0ef05SAndroid Build Coastguard Worker
1094*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.insert_or_assign(intent, quality);
1095*89a0ef05SAndroid Build Coastguard Worker
1096*89a0ef05SAndroid Build Coastguard Worker return status;
1097*89a0ef05SAndroid Build Coastguard Worker }
1098*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_exif_data(uhdr_codec_private_t * enc,uhdr_mem_block_t * exif)1099*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_exif_data(uhdr_codec_private_t* enc, uhdr_mem_block_t* exif) {
1100*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1101*89a0ef05SAndroid Build Coastguard Worker
1102*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
1103*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1104*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1105*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1106*89a0ef05SAndroid Build Coastguard Worker } else if (exif == nullptr) {
1107*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1108*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1109*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for exif image handle");
1110*89a0ef05SAndroid Build Coastguard Worker } else if (exif->data == nullptr) {
1111*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1112*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1113*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for exif->data field");
1114*89a0ef05SAndroid Build Coastguard Worker } else if (exif->capacity < exif->data_sz) {
1115*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1116*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1117*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1118*89a0ef05SAndroid Build Coastguard Worker "exif->capacity %zd is less than exif->data_sz %zd", exif->capacity, exif->data_sz);
1119*89a0ef05SAndroid Build Coastguard Worker }
1120*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1121*89a0ef05SAndroid Build Coastguard Worker
1122*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
1123*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
1124*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1125*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1126*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1127*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
1128*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1129*89a0ef05SAndroid Build Coastguard Worker return status;
1130*89a0ef05SAndroid Build Coastguard Worker }
1131*89a0ef05SAndroid Build Coastguard Worker
1132*89a0ef05SAndroid Build Coastguard Worker uint8_t* data = static_cast<uint8_t*>(exif->data);
1133*89a0ef05SAndroid Build Coastguard Worker std::vector<uint8_t> entry(data, data + exif->data_sz);
1134*89a0ef05SAndroid Build Coastguard Worker handle->m_exif = std::move(entry);
1135*89a0ef05SAndroid Build Coastguard Worker
1136*89a0ef05SAndroid Build Coastguard Worker return status;
1137*89a0ef05SAndroid Build Coastguard Worker }
1138*89a0ef05SAndroid Build Coastguard Worker
uhdr_enc_set_output_format(uhdr_codec_private_t * enc,uhdr_codec_t media_type)1139*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enc_set_output_format(uhdr_codec_private_t* enc, uhdr_codec_t media_type) {
1140*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1141*89a0ef05SAndroid Build Coastguard Worker
1142*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
1143*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1144*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1145*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1146*89a0ef05SAndroid Build Coastguard Worker } else if (media_type != UHDR_CODEC_JPG) {
1147*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_UNSUPPORTED_FEATURE;
1148*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1149*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1150*89a0ef05SAndroid Build Coastguard Worker "invalid output format %d, expects {UHDR_CODEC_JPG}", media_type);
1151*89a0ef05SAndroid Build Coastguard Worker }
1152*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1153*89a0ef05SAndroid Build Coastguard Worker
1154*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
1155*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
1156*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1157*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1158*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1159*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode() has switched the context from configurable state to "
1160*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1161*89a0ef05SAndroid Build Coastguard Worker return status;
1162*89a0ef05SAndroid Build Coastguard Worker }
1163*89a0ef05SAndroid Build Coastguard Worker
1164*89a0ef05SAndroid Build Coastguard Worker handle->m_output_format = media_type;
1165*89a0ef05SAndroid Build Coastguard Worker
1166*89a0ef05SAndroid Build Coastguard Worker return status;
1167*89a0ef05SAndroid Build Coastguard Worker }
1168*89a0ef05SAndroid Build Coastguard Worker
uhdr_encode(uhdr_codec_private_t * enc)1169*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_encode(uhdr_codec_private_t* enc) {
1170*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
1171*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
1172*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1173*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1174*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1175*89a0ef05SAndroid Build Coastguard Worker return status;
1176*89a0ef05SAndroid Build Coastguard Worker }
1177*89a0ef05SAndroid Build Coastguard Worker
1178*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
1179*89a0ef05SAndroid Build Coastguard Worker
1180*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
1181*89a0ef05SAndroid Build Coastguard Worker return handle->m_encode_call_status;
1182*89a0ef05SAndroid Build Coastguard Worker }
1183*89a0ef05SAndroid Build Coastguard Worker
1184*89a0ef05SAndroid Build Coastguard Worker handle->m_sailed = true;
1185*89a0ef05SAndroid Build Coastguard Worker
1186*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t& status = handle->m_encode_call_status;
1187*89a0ef05SAndroid Build Coastguard Worker
1188*89a0ef05SAndroid Build Coastguard Worker if (handle->m_compressed_images.find(UHDR_BASE_IMG) != handle->m_compressed_images.end() &&
1189*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_images.find(UHDR_GAIN_MAP_IMG) != handle->m_compressed_images.end()) {
1190*89a0ef05SAndroid Build Coastguard Worker if (handle->m_effects.size() != 0) {
1191*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1192*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1193*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1194*89a0ef05SAndroid Build Coastguard Worker "image effects are not enabled for inputs with compressed intent");
1195*89a0ef05SAndroid Build Coastguard Worker return status;
1196*89a0ef05SAndroid Build Coastguard Worker }
1197*89a0ef05SAndroid Build Coastguard Worker } else if (handle->m_raw_images.find(UHDR_HDR_IMG) != handle->m_raw_images.end()) {
1198*89a0ef05SAndroid Build Coastguard Worker if (handle->m_compressed_images.find(UHDR_SDR_IMG) == handle->m_compressed_images.end() &&
1199*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.find(UHDR_SDR_IMG) == handle->m_raw_images.end()) {
1200*89a0ef05SAndroid Build Coastguard Worker // api - 0
1201*89a0ef05SAndroid Build Coastguard Worker if (handle->m_effects.size() != 0) {
1202*89a0ef05SAndroid Build Coastguard Worker status = ultrahdr::apply_effects(handle);
1203*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1204*89a0ef05SAndroid Build Coastguard Worker }
1205*89a0ef05SAndroid Build Coastguard Worker } else if (handle->m_compressed_images.find(UHDR_SDR_IMG) !=
1206*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_images.end() &&
1207*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.find(UHDR_SDR_IMG) == handle->m_raw_images.end()) {
1208*89a0ef05SAndroid Build Coastguard Worker if (handle->m_effects.size() != 0) {
1209*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1210*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1211*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1212*89a0ef05SAndroid Build Coastguard Worker "image effects are not enabled for inputs with compressed intent");
1213*89a0ef05SAndroid Build Coastguard Worker return status;
1214*89a0ef05SAndroid Build Coastguard Worker }
1215*89a0ef05SAndroid Build Coastguard Worker } else if (handle->m_raw_images.find(UHDR_SDR_IMG) != handle->m_raw_images.end()) {
1216*89a0ef05SAndroid Build Coastguard Worker if (handle->m_compressed_images.find(UHDR_SDR_IMG) == handle->m_compressed_images.end()) {
1217*89a0ef05SAndroid Build Coastguard Worker if (handle->m_effects.size() != 0) {
1218*89a0ef05SAndroid Build Coastguard Worker status = ultrahdr::apply_effects(handle);
1219*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1220*89a0ef05SAndroid Build Coastguard Worker }
1221*89a0ef05SAndroid Build Coastguard Worker } else {
1222*89a0ef05SAndroid Build Coastguard Worker if (handle->m_effects.size() != 0) {
1223*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1224*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1225*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1226*89a0ef05SAndroid Build Coastguard Worker "image effects are not enabled for inputs with compressed intent");
1227*89a0ef05SAndroid Build Coastguard Worker return status;
1228*89a0ef05SAndroid Build Coastguard Worker }
1229*89a0ef05SAndroid Build Coastguard Worker }
1230*89a0ef05SAndroid Build Coastguard Worker }
1231*89a0ef05SAndroid Build Coastguard Worker }
1232*89a0ef05SAndroid Build Coastguard Worker
1233*89a0ef05SAndroid Build Coastguard Worker if (handle->m_output_format == UHDR_CODEC_JPG) {
1234*89a0ef05SAndroid Build Coastguard Worker uhdr_mem_block_t exif{};
1235*89a0ef05SAndroid Build Coastguard Worker if (handle->m_exif.size() > 0) {
1236*89a0ef05SAndroid Build Coastguard Worker exif.data = handle->m_exif.data();
1237*89a0ef05SAndroid Build Coastguard Worker exif.capacity = exif.data_sz = handle->m_exif.size();
1238*89a0ef05SAndroid Build Coastguard Worker }
1239*89a0ef05SAndroid Build Coastguard Worker
1240*89a0ef05SAndroid Build Coastguard Worker ultrahdr::JpegR jpegr(nullptr, handle->m_gainmap_scale_factor,
1241*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.find(UHDR_GAIN_MAP_IMG)->second,
1242*89a0ef05SAndroid Build Coastguard Worker handle->m_use_multi_channel_gainmap, handle->m_gamma,
1243*89a0ef05SAndroid Build Coastguard Worker handle->m_enc_preset, handle->m_min_content_boost,
1244*89a0ef05SAndroid Build Coastguard Worker handle->m_max_content_boost, handle->m_target_disp_max_brightness);
1245*89a0ef05SAndroid Build Coastguard Worker if (handle->m_compressed_images.find(UHDR_BASE_IMG) != handle->m_compressed_images.end() &&
1246*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_images.find(UHDR_GAIN_MAP_IMG) != handle->m_compressed_images.end()) {
1247*89a0ef05SAndroid Build Coastguard Worker auto& base_entry = handle->m_compressed_images.find(UHDR_BASE_IMG)->second;
1248*89a0ef05SAndroid Build Coastguard Worker auto& gainmap_entry = handle->m_compressed_images.find(UHDR_GAIN_MAP_IMG)->second;
1249*89a0ef05SAndroid Build Coastguard Worker
1250*89a0ef05SAndroid Build Coastguard Worker size_t size =
1251*89a0ef05SAndroid Build Coastguard Worker (std::max)(((size_t)8 * 1024), 2 * (base_entry->data_sz + gainmap_entry->data_sz));
1252*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_output_buffer = std::make_unique<ultrahdr::uhdr_compressed_image_ext_t>(
1253*89a0ef05SAndroid Build Coastguard Worker UHDR_CG_UNSPECIFIED, UHDR_CT_UNSPECIFIED, UHDR_CR_UNSPECIFIED, size);
1254*89a0ef05SAndroid Build Coastguard Worker
1255*89a0ef05SAndroid Build Coastguard Worker ultrahdr::uhdr_gainmap_metadata_ext_t metadata(handle->m_metadata, ultrahdr::kJpegrVersion);
1256*89a0ef05SAndroid Build Coastguard Worker
1257*89a0ef05SAndroid Build Coastguard Worker // api - 4
1258*89a0ef05SAndroid Build Coastguard Worker status = jpegr.encodeJPEGR(base_entry.get(), gainmap_entry.get(), &metadata,
1259*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_output_buffer.get());
1260*89a0ef05SAndroid Build Coastguard Worker } else if (handle->m_raw_images.find(UHDR_HDR_IMG) != handle->m_raw_images.end()) {
1261*89a0ef05SAndroid Build Coastguard Worker auto& hdr_raw_entry = handle->m_raw_images.find(UHDR_HDR_IMG)->second;
1262*89a0ef05SAndroid Build Coastguard Worker
1263*89a0ef05SAndroid Build Coastguard Worker size_t size = (std::max)((8u * 1024), hdr_raw_entry->w * hdr_raw_entry->h * 3 * 2);
1264*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_output_buffer = std::make_unique<ultrahdr::uhdr_compressed_image_ext_t>(
1265*89a0ef05SAndroid Build Coastguard Worker UHDR_CG_UNSPECIFIED, UHDR_CT_UNSPECIFIED, UHDR_CR_UNSPECIFIED, size);
1266*89a0ef05SAndroid Build Coastguard Worker
1267*89a0ef05SAndroid Build Coastguard Worker if (handle->m_compressed_images.find(UHDR_SDR_IMG) == handle->m_compressed_images.end() &&
1268*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.find(UHDR_SDR_IMG) == handle->m_raw_images.end()) {
1269*89a0ef05SAndroid Build Coastguard Worker // api - 0
1270*89a0ef05SAndroid Build Coastguard Worker status = jpegr.encodeJPEGR(hdr_raw_entry.get(), handle->m_compressed_output_buffer.get(),
1271*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.find(UHDR_BASE_IMG)->second,
1272*89a0ef05SAndroid Build Coastguard Worker handle->m_exif.size() > 0 ? &exif : nullptr);
1273*89a0ef05SAndroid Build Coastguard Worker } else if (handle->m_compressed_images.find(UHDR_SDR_IMG) !=
1274*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_images.end() &&
1275*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.find(UHDR_SDR_IMG) == handle->m_raw_images.end()) {
1276*89a0ef05SAndroid Build Coastguard Worker auto& sdr_compressed_entry = handle->m_compressed_images.find(UHDR_SDR_IMG)->second;
1277*89a0ef05SAndroid Build Coastguard Worker // api - 3
1278*89a0ef05SAndroid Build Coastguard Worker status = jpegr.encodeJPEGR(hdr_raw_entry.get(), sdr_compressed_entry.get(),
1279*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_output_buffer.get());
1280*89a0ef05SAndroid Build Coastguard Worker } else if (handle->m_raw_images.find(UHDR_SDR_IMG) != handle->m_raw_images.end()) {
1281*89a0ef05SAndroid Build Coastguard Worker auto& sdr_raw_entry = handle->m_raw_images.find(UHDR_SDR_IMG)->second;
1282*89a0ef05SAndroid Build Coastguard Worker
1283*89a0ef05SAndroid Build Coastguard Worker if (handle->m_compressed_images.find(UHDR_SDR_IMG) == handle->m_compressed_images.end()) {
1284*89a0ef05SAndroid Build Coastguard Worker // api - 1
1285*89a0ef05SAndroid Build Coastguard Worker status = jpegr.encodeJPEGR(hdr_raw_entry.get(), sdr_raw_entry.get(),
1286*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_output_buffer.get(),
1287*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.find(UHDR_BASE_IMG)->second,
1288*89a0ef05SAndroid Build Coastguard Worker handle->m_exif.size() > 0 ? &exif : nullptr);
1289*89a0ef05SAndroid Build Coastguard Worker } else {
1290*89a0ef05SAndroid Build Coastguard Worker auto& sdr_compressed_entry = handle->m_compressed_images.find(UHDR_SDR_IMG)->second;
1291*89a0ef05SAndroid Build Coastguard Worker // api - 2
1292*89a0ef05SAndroid Build Coastguard Worker status = jpegr.encodeJPEGR(hdr_raw_entry.get(), sdr_raw_entry.get(),
1293*89a0ef05SAndroid Build Coastguard Worker sdr_compressed_entry.get(),
1294*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_output_buffer.get());
1295*89a0ef05SAndroid Build Coastguard Worker }
1296*89a0ef05SAndroid Build Coastguard Worker }
1297*89a0ef05SAndroid Build Coastguard Worker } else {
1298*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1299*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1300*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1301*89a0ef05SAndroid Build Coastguard Worker "resources required for uhdr_encode() operation are not present");
1302*89a0ef05SAndroid Build Coastguard Worker }
1303*89a0ef05SAndroid Build Coastguard Worker }
1304*89a0ef05SAndroid Build Coastguard Worker
1305*89a0ef05SAndroid Build Coastguard Worker return status;
1306*89a0ef05SAndroid Build Coastguard Worker }
1307*89a0ef05SAndroid Build Coastguard Worker
uhdr_get_encoded_stream(uhdr_codec_private_t * enc)1308*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t* uhdr_get_encoded_stream(uhdr_codec_private_t* enc) {
1309*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) == nullptr) {
1310*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1311*89a0ef05SAndroid Build Coastguard Worker }
1312*89a0ef05SAndroid Build Coastguard Worker
1313*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
1314*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_sailed || handle->m_encode_call_status.error_code != UHDR_CODEC_OK) {
1315*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1316*89a0ef05SAndroid Build Coastguard Worker }
1317*89a0ef05SAndroid Build Coastguard Worker
1318*89a0ef05SAndroid Build Coastguard Worker return handle->m_compressed_output_buffer.get();
1319*89a0ef05SAndroid Build Coastguard Worker }
1320*89a0ef05SAndroid Build Coastguard Worker
uhdr_reset_encoder(uhdr_codec_private_t * enc)1321*89a0ef05SAndroid Build Coastguard Worker void uhdr_reset_encoder(uhdr_codec_private_t* enc) {
1322*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_encoder_private*>(enc) != nullptr) {
1323*89a0ef05SAndroid Build Coastguard Worker uhdr_encoder_private* handle = dynamic_cast<uhdr_encoder_private*>(enc);
1324*89a0ef05SAndroid Build Coastguard Worker
1325*89a0ef05SAndroid Build Coastguard Worker // clear entries and restore defaults
1326*89a0ef05SAndroid Build Coastguard Worker for (auto it : handle->m_effects) delete it;
1327*89a0ef05SAndroid Build Coastguard Worker handle->m_effects.clear();
1328*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
1329*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_gl_ctxt.reset_opengl_ctxt();
1330*89a0ef05SAndroid Build Coastguard Worker handle->m_enable_gles = false;
1331*89a0ef05SAndroid Build Coastguard Worker #endif
1332*89a0ef05SAndroid Build Coastguard Worker handle->m_sailed = false;
1333*89a0ef05SAndroid Build Coastguard Worker handle->m_raw_images.clear();
1334*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_images.clear();
1335*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.clear();
1336*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.emplace(UHDR_HDR_IMG, ultrahdr::kBaseCompressQualityDefault);
1337*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.emplace(UHDR_SDR_IMG, ultrahdr::kBaseCompressQualityDefault);
1338*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.emplace(UHDR_BASE_IMG, ultrahdr::kBaseCompressQualityDefault);
1339*89a0ef05SAndroid Build Coastguard Worker handle->m_quality.emplace(UHDR_GAIN_MAP_IMG, ultrahdr::kMapCompressQualityDefault);
1340*89a0ef05SAndroid Build Coastguard Worker handle->m_exif.clear();
1341*89a0ef05SAndroid Build Coastguard Worker handle->m_output_format = UHDR_CODEC_JPG;
1342*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_scale_factor = ultrahdr::kMapDimensionScaleFactorDefault;
1343*89a0ef05SAndroid Build Coastguard Worker handle->m_use_multi_channel_gainmap = ultrahdr::kUseMultiChannelGainMapDefault;
1344*89a0ef05SAndroid Build Coastguard Worker handle->m_gamma = ultrahdr::kGainMapGammaDefault;
1345*89a0ef05SAndroid Build Coastguard Worker handle->m_enc_preset = ultrahdr::kEncSpeedPresetDefault;
1346*89a0ef05SAndroid Build Coastguard Worker handle->m_min_content_boost = FLT_MIN;
1347*89a0ef05SAndroid Build Coastguard Worker handle->m_max_content_boost = FLT_MAX;
1348*89a0ef05SAndroid Build Coastguard Worker handle->m_target_disp_max_brightness = -1.0f;
1349*89a0ef05SAndroid Build Coastguard Worker
1350*89a0ef05SAndroid Build Coastguard Worker handle->m_compressed_output_buffer.reset();
1351*89a0ef05SAndroid Build Coastguard Worker handle->m_encode_call_status = g_no_error;
1352*89a0ef05SAndroid Build Coastguard Worker }
1353*89a0ef05SAndroid Build Coastguard Worker }
1354*89a0ef05SAndroid Build Coastguard Worker
is_uhdr_image(void * data,int size)1355*89a0ef05SAndroid Build Coastguard Worker int is_uhdr_image(void* data, int size) {
1356*89a0ef05SAndroid Build Coastguard Worker #define RET_IF_ERR(x) \
1357*89a0ef05SAndroid Build Coastguard Worker { \
1358*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = (x); \
1359*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) { \
1360*89a0ef05SAndroid Build Coastguard Worker uhdr_release_decoder(obj); \
1361*89a0ef05SAndroid Build Coastguard Worker return 0; \
1362*89a0ef05SAndroid Build Coastguard Worker } \
1363*89a0ef05SAndroid Build Coastguard Worker }
1364*89a0ef05SAndroid Build Coastguard Worker
1365*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private_t* obj = uhdr_create_decoder();
1366*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t uhdr_image;
1367*89a0ef05SAndroid Build Coastguard Worker uhdr_image.data = data;
1368*89a0ef05SAndroid Build Coastguard Worker uhdr_image.data_sz = size;
1369*89a0ef05SAndroid Build Coastguard Worker uhdr_image.capacity = size;
1370*89a0ef05SAndroid Build Coastguard Worker uhdr_image.cg = UHDR_CG_UNSPECIFIED;
1371*89a0ef05SAndroid Build Coastguard Worker uhdr_image.ct = UHDR_CT_UNSPECIFIED;
1372*89a0ef05SAndroid Build Coastguard Worker uhdr_image.range = UHDR_CR_UNSPECIFIED;
1373*89a0ef05SAndroid Build Coastguard Worker
1374*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_dec_set_image(obj, &uhdr_image));
1375*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_dec_probe(obj));
1376*89a0ef05SAndroid Build Coastguard Worker #undef RET_IF_ERR
1377*89a0ef05SAndroid Build Coastguard Worker
1378*89a0ef05SAndroid Build Coastguard Worker uhdr_release_decoder(obj);
1379*89a0ef05SAndroid Build Coastguard Worker
1380*89a0ef05SAndroid Build Coastguard Worker return 1;
1381*89a0ef05SAndroid Build Coastguard Worker }
1382*89a0ef05SAndroid Build Coastguard Worker
uhdr_create_decoder(void)1383*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private_t* uhdr_create_decoder(void) {
1384*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = new uhdr_decoder_private();
1385*89a0ef05SAndroid Build Coastguard Worker
1386*89a0ef05SAndroid Build Coastguard Worker if (handle != nullptr) {
1387*89a0ef05SAndroid Build Coastguard Worker uhdr_reset_decoder(handle);
1388*89a0ef05SAndroid Build Coastguard Worker }
1389*89a0ef05SAndroid Build Coastguard Worker return handle;
1390*89a0ef05SAndroid Build Coastguard Worker }
1391*89a0ef05SAndroid Build Coastguard Worker
uhdr_release_decoder(uhdr_codec_private_t * dec)1392*89a0ef05SAndroid Build Coastguard Worker void uhdr_release_decoder(uhdr_codec_private_t* dec) {
1393*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) != nullptr) {
1394*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1395*89a0ef05SAndroid Build Coastguard Worker delete handle;
1396*89a0ef05SAndroid Build Coastguard Worker }
1397*89a0ef05SAndroid Build Coastguard Worker }
1398*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_set_image(uhdr_codec_private_t * dec,uhdr_compressed_image_t * img)1399*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_dec_set_image(uhdr_codec_private_t* dec, uhdr_compressed_image_t* img) {
1400*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1401*89a0ef05SAndroid Build Coastguard Worker
1402*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1403*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1404*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1405*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1406*89a0ef05SAndroid Build Coastguard Worker } else if (img == nullptr) {
1407*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1408*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1409*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for compressed image handle");
1410*89a0ef05SAndroid Build Coastguard Worker } else if (img->data == nullptr) {
1411*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1412*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1413*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1414*89a0ef05SAndroid Build Coastguard Worker "received nullptr for compressed img->data field");
1415*89a0ef05SAndroid Build Coastguard Worker } else if (img->capacity < img->data_sz) {
1416*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1417*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1418*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "img->capacity %zd is less than img->data_sz %zd",
1419*89a0ef05SAndroid Build Coastguard Worker img->capacity, img->data_sz);
1420*89a0ef05SAndroid Build Coastguard Worker }
1421*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1422*89a0ef05SAndroid Build Coastguard Worker
1423*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1424*89a0ef05SAndroid Build Coastguard Worker if (handle->m_probed) {
1425*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1426*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1427*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1428*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_decode() has switched the context from configurable state to "
1429*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1430*89a0ef05SAndroid Build Coastguard Worker return status;
1431*89a0ef05SAndroid Build Coastguard Worker }
1432*89a0ef05SAndroid Build Coastguard Worker
1433*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_compressed_img = std::make_unique<ultrahdr::uhdr_compressed_image_ext_t>(
1434*89a0ef05SAndroid Build Coastguard Worker img->cg, img->ct, img->range, img->data_sz);
1435*89a0ef05SAndroid Build Coastguard Worker memcpy(handle->m_uhdr_compressed_img->data, img->data, img->data_sz);
1436*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_compressed_img->data_sz = img->data_sz;
1437*89a0ef05SAndroid Build Coastguard Worker
1438*89a0ef05SAndroid Build Coastguard Worker return status;
1439*89a0ef05SAndroid Build Coastguard Worker }
1440*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_set_out_img_format(uhdr_codec_private_t * dec,uhdr_img_fmt_t fmt)1441*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_dec_set_out_img_format(uhdr_codec_private_t* dec, uhdr_img_fmt_t fmt) {
1442*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1443*89a0ef05SAndroid Build Coastguard Worker
1444*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1445*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1446*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1447*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1448*89a0ef05SAndroid Build Coastguard Worker } else if (fmt != UHDR_IMG_FMT_32bppRGBA8888 && fmt != UHDR_IMG_FMT_64bppRGBAHalfFloat &&
1449*89a0ef05SAndroid Build Coastguard Worker fmt != UHDR_IMG_FMT_32bppRGBA1010102) {
1450*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1451*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1452*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1453*89a0ef05SAndroid Build Coastguard Worker "invalid output format %d, expects one of {UHDR_IMG_FMT_32bppRGBA8888, "
1454*89a0ef05SAndroid Build Coastguard Worker "UHDR_IMG_FMT_64bppRGBAHalfFloat, UHDR_IMG_FMT_32bppRGBA1010102}",
1455*89a0ef05SAndroid Build Coastguard Worker fmt);
1456*89a0ef05SAndroid Build Coastguard Worker }
1457*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1458*89a0ef05SAndroid Build Coastguard Worker
1459*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1460*89a0ef05SAndroid Build Coastguard Worker if (handle->m_probed) {
1461*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1462*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1463*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1464*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_decode() has switched the context from configurable state to "
1465*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1466*89a0ef05SAndroid Build Coastguard Worker return status;
1467*89a0ef05SAndroid Build Coastguard Worker }
1468*89a0ef05SAndroid Build Coastguard Worker
1469*89a0ef05SAndroid Build Coastguard Worker handle->m_output_fmt = fmt;
1470*89a0ef05SAndroid Build Coastguard Worker
1471*89a0ef05SAndroid Build Coastguard Worker return status;
1472*89a0ef05SAndroid Build Coastguard Worker }
1473*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_set_out_color_transfer(uhdr_codec_private_t * dec,uhdr_color_transfer_t ct)1474*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_dec_set_out_color_transfer(uhdr_codec_private_t* dec,
1475*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t ct) {
1476*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1477*89a0ef05SAndroid Build Coastguard Worker
1478*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1479*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1480*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1481*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1482*89a0ef05SAndroid Build Coastguard Worker } else if (ct != UHDR_CT_HLG && ct != UHDR_CT_PQ && ct != UHDR_CT_LINEAR && ct != UHDR_CT_SRGB) {
1483*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1484*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1485*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1486*89a0ef05SAndroid Build Coastguard Worker "invalid output color transfer %d, expects one of {UHDR_CT_HLG, UHDR_CT_PQ, "
1487*89a0ef05SAndroid Build Coastguard Worker "UHDR_CT_LINEAR, UHDR_CT_SRGB}",
1488*89a0ef05SAndroid Build Coastguard Worker ct);
1489*89a0ef05SAndroid Build Coastguard Worker }
1490*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1491*89a0ef05SAndroid Build Coastguard Worker
1492*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1493*89a0ef05SAndroid Build Coastguard Worker if (handle->m_probed) {
1494*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1495*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1496*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1497*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_decode() has switched the context from configurable state to "
1498*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1499*89a0ef05SAndroid Build Coastguard Worker return status;
1500*89a0ef05SAndroid Build Coastguard Worker }
1501*89a0ef05SAndroid Build Coastguard Worker
1502*89a0ef05SAndroid Build Coastguard Worker handle->m_output_ct = ct;
1503*89a0ef05SAndroid Build Coastguard Worker
1504*89a0ef05SAndroid Build Coastguard Worker return status;
1505*89a0ef05SAndroid Build Coastguard Worker }
1506*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_set_out_max_display_boost(uhdr_codec_private_t * dec,float display_boost)1507*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_dec_set_out_max_display_boost(uhdr_codec_private_t* dec,
1508*89a0ef05SAndroid Build Coastguard Worker float display_boost) {
1509*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1510*89a0ef05SAndroid Build Coastguard Worker
1511*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1512*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1513*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1514*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1515*89a0ef05SAndroid Build Coastguard Worker } else if (!std::isfinite(display_boost) || display_boost < 1.0f) {
1516*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1517*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1518*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1519*89a0ef05SAndroid Build Coastguard Worker "invalid display boost %f, expects to be >= 1.0f}", display_boost);
1520*89a0ef05SAndroid Build Coastguard Worker }
1521*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1522*89a0ef05SAndroid Build Coastguard Worker
1523*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1524*89a0ef05SAndroid Build Coastguard Worker if (handle->m_probed) {
1525*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1526*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1527*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1528*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_decode() has switched the context from configurable state to "
1529*89a0ef05SAndroid Build Coastguard Worker "end state. The context is no longer configurable. To reuse, call reset()");
1530*89a0ef05SAndroid Build Coastguard Worker return status;
1531*89a0ef05SAndroid Build Coastguard Worker }
1532*89a0ef05SAndroid Build Coastguard Worker
1533*89a0ef05SAndroid Build Coastguard Worker handle->m_output_max_disp_boost = display_boost;
1534*89a0ef05SAndroid Build Coastguard Worker
1535*89a0ef05SAndroid Build Coastguard Worker return status;
1536*89a0ef05SAndroid Build Coastguard Worker }
1537*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_probe(uhdr_codec_private_t * dec)1538*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_dec_probe(uhdr_codec_private_t* dec) {
1539*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1540*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
1541*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1542*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1543*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1544*89a0ef05SAndroid Build Coastguard Worker return status;
1545*89a0ef05SAndroid Build Coastguard Worker }
1546*89a0ef05SAndroid Build Coastguard Worker
1547*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1548*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t& status = handle->m_probe_call_status;
1549*89a0ef05SAndroid Build Coastguard Worker
1550*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed) {
1551*89a0ef05SAndroid Build Coastguard Worker handle->m_probed = true;
1552*89a0ef05SAndroid Build Coastguard Worker
1553*89a0ef05SAndroid Build Coastguard Worker if (handle->m_uhdr_compressed_img.get() == nullptr) {
1554*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1555*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1556*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "did not receive any image for decoding");
1557*89a0ef05SAndroid Build Coastguard Worker return status;
1558*89a0ef05SAndroid Build Coastguard Worker }
1559*89a0ef05SAndroid Build Coastguard Worker
1560*89a0ef05SAndroid Build Coastguard Worker ultrahdr::jpeg_info_struct primary_image;
1561*89a0ef05SAndroid Build Coastguard Worker ultrahdr::jpeg_info_struct gainmap_image;
1562*89a0ef05SAndroid Build Coastguard Worker ultrahdr::jpegr_info_struct jpegr_info;
1563*89a0ef05SAndroid Build Coastguard Worker jpegr_info.primaryImgInfo = &primary_image;
1564*89a0ef05SAndroid Build Coastguard Worker jpegr_info.gainmapImgInfo = &gainmap_image;
1565*89a0ef05SAndroid Build Coastguard Worker
1566*89a0ef05SAndroid Build Coastguard Worker ultrahdr::JpegR jpegr;
1567*89a0ef05SAndroid Build Coastguard Worker status = jpegr.getJPEGRInfo(handle->m_uhdr_compressed_img.get(), &jpegr_info);
1568*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1569*89a0ef05SAndroid Build Coastguard Worker
1570*89a0ef05SAndroid Build Coastguard Worker ultrahdr::uhdr_gainmap_metadata_ext_t metadata;
1571*89a0ef05SAndroid Build Coastguard Worker status = jpegr.parseGainMapMetadata(gainmap_image.isoData.data(), gainmap_image.isoData.size(),
1572*89a0ef05SAndroid Build Coastguard Worker gainmap_image.xmpData.data(), gainmap_image.xmpData.size(),
1573*89a0ef05SAndroid Build Coastguard Worker &metadata);
1574*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1575*89a0ef05SAndroid Build Coastguard Worker handle->m_metadata.max_content_boost = metadata.max_content_boost;
1576*89a0ef05SAndroid Build Coastguard Worker handle->m_metadata.min_content_boost = metadata.min_content_boost;
1577*89a0ef05SAndroid Build Coastguard Worker handle->m_metadata.gamma = metadata.gamma;
1578*89a0ef05SAndroid Build Coastguard Worker handle->m_metadata.offset_sdr = metadata.offset_sdr;
1579*89a0ef05SAndroid Build Coastguard Worker handle->m_metadata.offset_hdr = metadata.offset_hdr;
1580*89a0ef05SAndroid Build Coastguard Worker handle->m_metadata.hdr_capacity_min = metadata.hdr_capacity_min;
1581*89a0ef05SAndroid Build Coastguard Worker handle->m_metadata.hdr_capacity_max = metadata.hdr_capacity_max;
1582*89a0ef05SAndroid Build Coastguard Worker
1583*89a0ef05SAndroid Build Coastguard Worker handle->m_img_wd = primary_image.width;
1584*89a0ef05SAndroid Build Coastguard Worker handle->m_img_ht = primary_image.height;
1585*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_wd = gainmap_image.width;
1586*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_ht = gainmap_image.height;
1587*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_num_comp = gainmap_image.numComponents;
1588*89a0ef05SAndroid Build Coastguard Worker handle->m_exif = std::move(primary_image.exifData);
1589*89a0ef05SAndroid Build Coastguard Worker handle->m_exif_block.data = handle->m_exif.data();
1590*89a0ef05SAndroid Build Coastguard Worker handle->m_exif_block.data_sz = handle->m_exif_block.capacity = handle->m_exif.size();
1591*89a0ef05SAndroid Build Coastguard Worker handle->m_icc = std::move(primary_image.iccData);
1592*89a0ef05SAndroid Build Coastguard Worker handle->m_icc_block.data = handle->m_icc.data();
1593*89a0ef05SAndroid Build Coastguard Worker handle->m_icc_block.data_sz = handle->m_icc_block.capacity = handle->m_icc.size();
1594*89a0ef05SAndroid Build Coastguard Worker handle->m_base_img = std::move(primary_image.imgData);
1595*89a0ef05SAndroid Build Coastguard Worker handle->m_base_img_block.data = handle->m_base_img.data();
1596*89a0ef05SAndroid Build Coastguard Worker handle->m_base_img_block.data_sz = handle->m_base_img_block.capacity =
1597*89a0ef05SAndroid Build Coastguard Worker handle->m_base_img.size();
1598*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img = std::move(gainmap_image.imgData);
1599*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img_block.data = handle->m_gainmap_img.data();
1600*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img_block.data_sz = handle->m_gainmap_img_block.capacity =
1601*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img.size();
1602*89a0ef05SAndroid Build Coastguard Worker }
1603*89a0ef05SAndroid Build Coastguard Worker
1604*89a0ef05SAndroid Build Coastguard Worker return status;
1605*89a0ef05SAndroid Build Coastguard Worker }
1606*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_image_width(uhdr_codec_private_t * dec)1607*89a0ef05SAndroid Build Coastguard Worker int uhdr_dec_get_image_width(uhdr_codec_private_t* dec) {
1608*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1609*89a0ef05SAndroid Build Coastguard Worker return -1;
1610*89a0ef05SAndroid Build Coastguard Worker }
1611*89a0ef05SAndroid Build Coastguard Worker
1612*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1613*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1614*89a0ef05SAndroid Build Coastguard Worker return -1;
1615*89a0ef05SAndroid Build Coastguard Worker }
1616*89a0ef05SAndroid Build Coastguard Worker
1617*89a0ef05SAndroid Build Coastguard Worker return handle->m_img_wd;
1618*89a0ef05SAndroid Build Coastguard Worker }
1619*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_image_height(uhdr_codec_private_t * dec)1620*89a0ef05SAndroid Build Coastguard Worker int uhdr_dec_get_image_height(uhdr_codec_private_t* dec) {
1621*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1622*89a0ef05SAndroid Build Coastguard Worker return -1;
1623*89a0ef05SAndroid Build Coastguard Worker }
1624*89a0ef05SAndroid Build Coastguard Worker
1625*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1626*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1627*89a0ef05SAndroid Build Coastguard Worker return -1;
1628*89a0ef05SAndroid Build Coastguard Worker }
1629*89a0ef05SAndroid Build Coastguard Worker
1630*89a0ef05SAndroid Build Coastguard Worker return handle->m_img_ht;
1631*89a0ef05SAndroid Build Coastguard Worker }
1632*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_gainmap_width(uhdr_codec_private_t * dec)1633*89a0ef05SAndroid Build Coastguard Worker int uhdr_dec_get_gainmap_width(uhdr_codec_private_t* dec) {
1634*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1635*89a0ef05SAndroid Build Coastguard Worker return -1;
1636*89a0ef05SAndroid Build Coastguard Worker }
1637*89a0ef05SAndroid Build Coastguard Worker
1638*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1639*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1640*89a0ef05SAndroid Build Coastguard Worker return -1;
1641*89a0ef05SAndroid Build Coastguard Worker }
1642*89a0ef05SAndroid Build Coastguard Worker
1643*89a0ef05SAndroid Build Coastguard Worker return handle->m_gainmap_wd;
1644*89a0ef05SAndroid Build Coastguard Worker }
1645*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_gainmap_height(uhdr_codec_private_t * dec)1646*89a0ef05SAndroid Build Coastguard Worker int uhdr_dec_get_gainmap_height(uhdr_codec_private_t* dec) {
1647*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1648*89a0ef05SAndroid Build Coastguard Worker return -1;
1649*89a0ef05SAndroid Build Coastguard Worker }
1650*89a0ef05SAndroid Build Coastguard Worker
1651*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1652*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1653*89a0ef05SAndroid Build Coastguard Worker return -1;
1654*89a0ef05SAndroid Build Coastguard Worker }
1655*89a0ef05SAndroid Build Coastguard Worker
1656*89a0ef05SAndroid Build Coastguard Worker return handle->m_gainmap_ht;
1657*89a0ef05SAndroid Build Coastguard Worker }
1658*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_exif(uhdr_codec_private_t * dec)1659*89a0ef05SAndroid Build Coastguard Worker uhdr_mem_block_t* uhdr_dec_get_exif(uhdr_codec_private_t* dec) {
1660*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1661*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1662*89a0ef05SAndroid Build Coastguard Worker }
1663*89a0ef05SAndroid Build Coastguard Worker
1664*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1665*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1666*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1667*89a0ef05SAndroid Build Coastguard Worker }
1668*89a0ef05SAndroid Build Coastguard Worker
1669*89a0ef05SAndroid Build Coastguard Worker return &handle->m_exif_block;
1670*89a0ef05SAndroid Build Coastguard Worker }
1671*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_icc(uhdr_codec_private_t * dec)1672*89a0ef05SAndroid Build Coastguard Worker uhdr_mem_block_t* uhdr_dec_get_icc(uhdr_codec_private_t* dec) {
1673*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1674*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1675*89a0ef05SAndroid Build Coastguard Worker }
1676*89a0ef05SAndroid Build Coastguard Worker
1677*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1678*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1679*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1680*89a0ef05SAndroid Build Coastguard Worker }
1681*89a0ef05SAndroid Build Coastguard Worker
1682*89a0ef05SAndroid Build Coastguard Worker return &handle->m_icc_block;
1683*89a0ef05SAndroid Build Coastguard Worker }
1684*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_base_image(uhdr_codec_private_t * dec)1685*89a0ef05SAndroid Build Coastguard Worker uhdr_mem_block_t* uhdr_dec_get_base_image(uhdr_codec_private_t* dec) {
1686*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1687*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1688*89a0ef05SAndroid Build Coastguard Worker }
1689*89a0ef05SAndroid Build Coastguard Worker
1690*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1691*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1692*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1693*89a0ef05SAndroid Build Coastguard Worker }
1694*89a0ef05SAndroid Build Coastguard Worker
1695*89a0ef05SAndroid Build Coastguard Worker return &handle->m_base_img_block;
1696*89a0ef05SAndroid Build Coastguard Worker }
1697*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_gainmap_image(uhdr_codec_private_t * dec)1698*89a0ef05SAndroid Build Coastguard Worker uhdr_mem_block_t* uhdr_dec_get_gainmap_image(uhdr_codec_private_t* dec) {
1699*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1700*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1701*89a0ef05SAndroid Build Coastguard Worker }
1702*89a0ef05SAndroid Build Coastguard Worker
1703*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1704*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1705*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1706*89a0ef05SAndroid Build Coastguard Worker }
1707*89a0ef05SAndroid Build Coastguard Worker
1708*89a0ef05SAndroid Build Coastguard Worker return &handle->m_gainmap_img_block;
1709*89a0ef05SAndroid Build Coastguard Worker }
1710*89a0ef05SAndroid Build Coastguard Worker
uhdr_dec_get_gainmap_metadata(uhdr_codec_private_t * dec)1711*89a0ef05SAndroid Build Coastguard Worker uhdr_gainmap_metadata_t* uhdr_dec_get_gainmap_metadata(uhdr_codec_private_t* dec) {
1712*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1713*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1714*89a0ef05SAndroid Build Coastguard Worker }
1715*89a0ef05SAndroid Build Coastguard Worker
1716*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1717*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_probed || handle->m_probe_call_status.error_code != UHDR_CODEC_OK) {
1718*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1719*89a0ef05SAndroid Build Coastguard Worker }
1720*89a0ef05SAndroid Build Coastguard Worker
1721*89a0ef05SAndroid Build Coastguard Worker return &handle->m_metadata;
1722*89a0ef05SAndroid Build Coastguard Worker }
1723*89a0ef05SAndroid Build Coastguard Worker
uhdr_decode(uhdr_codec_private_t * dec)1724*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_decode(uhdr_codec_private_t* dec) {
1725*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1726*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status;
1727*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1728*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1729*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1730*89a0ef05SAndroid Build Coastguard Worker return status;
1731*89a0ef05SAndroid Build Coastguard Worker }
1732*89a0ef05SAndroid Build Coastguard Worker
1733*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1734*89a0ef05SAndroid Build Coastguard Worker
1735*89a0ef05SAndroid Build Coastguard Worker if (handle->m_sailed) {
1736*89a0ef05SAndroid Build Coastguard Worker return handle->m_decode_call_status;
1737*89a0ef05SAndroid Build Coastguard Worker }
1738*89a0ef05SAndroid Build Coastguard Worker
1739*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t& status = handle->m_decode_call_status;
1740*89a0ef05SAndroid Build Coastguard Worker status = uhdr_dec_probe(dec);
1741*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1742*89a0ef05SAndroid Build Coastguard Worker
1743*89a0ef05SAndroid Build Coastguard Worker handle->m_sailed = true;
1744*89a0ef05SAndroid Build Coastguard Worker
1745*89a0ef05SAndroid Build Coastguard Worker if ((handle->m_output_fmt == UHDR_IMG_FMT_32bppRGBA1010102 &&
1746*89a0ef05SAndroid Build Coastguard Worker (handle->m_output_ct != UHDR_CT_HLG && handle->m_output_ct != UHDR_CT_PQ)) ||
1747*89a0ef05SAndroid Build Coastguard Worker (handle->m_output_fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat &&
1748*89a0ef05SAndroid Build Coastguard Worker handle->m_output_ct != UHDR_CT_LINEAR) ||
1749*89a0ef05SAndroid Build Coastguard Worker (handle->m_output_fmt == UHDR_IMG_FMT_32bppRGBA8888 && handle->m_output_ct != UHDR_CT_SRGB)) {
1750*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1751*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1752*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1753*89a0ef05SAndroid Build Coastguard Worker "unsupported output pixel format and output color transfer pair");
1754*89a0ef05SAndroid Build Coastguard Worker return status;
1755*89a0ef05SAndroid Build Coastguard Worker }
1756*89a0ef05SAndroid Build Coastguard Worker
1757*89a0ef05SAndroid Build Coastguard Worker handle->m_decoded_img_buffer = std::make_unique<ultrahdr::uhdr_raw_image_ext_t>(
1758*89a0ef05SAndroid Build Coastguard Worker handle->m_output_fmt, UHDR_CG_UNSPECIFIED, handle->m_output_ct, UHDR_CR_UNSPECIFIED,
1759*89a0ef05SAndroid Build Coastguard Worker handle->m_img_wd, handle->m_img_ht, 1);
1760*89a0ef05SAndroid Build Coastguard Worker
1761*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img_buffer = std::make_unique<ultrahdr::uhdr_raw_image_ext_t>(
1762*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_num_comp == 1 ? UHDR_IMG_FMT_8bppYCbCr400 : UHDR_IMG_FMT_32bppRGBA8888,
1763*89a0ef05SAndroid Build Coastguard Worker UHDR_CG_UNSPECIFIED, UHDR_CT_UNSPECIFIED, UHDR_CR_UNSPECIFIED, handle->m_gainmap_wd,
1764*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_ht, 1);
1765*89a0ef05SAndroid Build Coastguard Worker
1766*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
1767*89a0ef05SAndroid Build Coastguard Worker ultrahdr::uhdr_opengl_ctxt_t* uhdrGLESCtxt = nullptr;
1768*89a0ef05SAndroid Build Coastguard Worker if (handle->m_enable_gles &&
1769*89a0ef05SAndroid Build Coastguard Worker (handle->m_output_ct != UHDR_CT_SRGB || handle->m_effects.size() > 0)) {
1770*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_gl_ctxt.init_opengl_ctxt();
1771*89a0ef05SAndroid Build Coastguard Worker status = handle->m_uhdr_gl_ctxt.mErrorStatus;
1772*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) return status;
1773*89a0ef05SAndroid Build Coastguard Worker uhdrGLESCtxt = &handle->m_uhdr_gl_ctxt;
1774*89a0ef05SAndroid Build Coastguard Worker }
1775*89a0ef05SAndroid Build Coastguard Worker ultrahdr::JpegR jpegr(uhdrGLESCtxt);
1776*89a0ef05SAndroid Build Coastguard Worker #else
1777*89a0ef05SAndroid Build Coastguard Worker ultrahdr::JpegR jpegr;
1778*89a0ef05SAndroid Build Coastguard Worker #endif
1779*89a0ef05SAndroid Build Coastguard Worker
1780*89a0ef05SAndroid Build Coastguard Worker status =
1781*89a0ef05SAndroid Build Coastguard Worker jpegr.decodeJPEGR(handle->m_uhdr_compressed_img.get(), handle->m_decoded_img_buffer.get(),
1782*89a0ef05SAndroid Build Coastguard Worker handle->m_output_max_disp_boost, handle->m_output_ct, handle->m_output_fmt,
1783*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img_buffer.get(), nullptr);
1784*89a0ef05SAndroid Build Coastguard Worker
1785*89a0ef05SAndroid Build Coastguard Worker if (status.error_code == UHDR_CODEC_OK && dec->m_effects.size() != 0) {
1786*89a0ef05SAndroid Build Coastguard Worker status = ultrahdr::apply_effects(handle);
1787*89a0ef05SAndroid Build Coastguard Worker }
1788*89a0ef05SAndroid Build Coastguard Worker
1789*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
1790*89a0ef05SAndroid Build Coastguard Worker if (handle->m_enable_gles) {
1791*89a0ef05SAndroid Build Coastguard Worker if (handle->m_uhdr_gl_ctxt.mDecodedImgTexture != 0) {
1792*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_gl_ctxt.read_texture(
1793*89a0ef05SAndroid Build Coastguard Worker &handle->m_uhdr_gl_ctxt.mDecodedImgTexture, handle->m_decoded_img_buffer->fmt,
1794*89a0ef05SAndroid Build Coastguard Worker handle->m_decoded_img_buffer->w, handle->m_decoded_img_buffer->h,
1795*89a0ef05SAndroid Build Coastguard Worker handle->m_decoded_img_buffer->planes[0]);
1796*89a0ef05SAndroid Build Coastguard Worker }
1797*89a0ef05SAndroid Build Coastguard Worker if (handle->m_uhdr_gl_ctxt.mGainmapImgTexture != 0 && dec->m_effects.size() != 0) {
1798*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_gl_ctxt.read_texture(
1799*89a0ef05SAndroid Build Coastguard Worker &handle->m_uhdr_gl_ctxt.mGainmapImgTexture, handle->m_gainmap_img_buffer->fmt,
1800*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img_buffer->w, handle->m_gainmap_img_buffer->h,
1801*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img_buffer->planes[0]);
1802*89a0ef05SAndroid Build Coastguard Worker }
1803*89a0ef05SAndroid Build Coastguard Worker }
1804*89a0ef05SAndroid Build Coastguard Worker #endif
1805*89a0ef05SAndroid Build Coastguard Worker return status;
1806*89a0ef05SAndroid Build Coastguard Worker }
1807*89a0ef05SAndroid Build Coastguard Worker
uhdr_get_decoded_image(uhdr_codec_private_t * dec)1808*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t* uhdr_get_decoded_image(uhdr_codec_private_t* dec) {
1809*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1810*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1811*89a0ef05SAndroid Build Coastguard Worker }
1812*89a0ef05SAndroid Build Coastguard Worker
1813*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1814*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_sailed || handle->m_decode_call_status.error_code != UHDR_CODEC_OK) {
1815*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1816*89a0ef05SAndroid Build Coastguard Worker }
1817*89a0ef05SAndroid Build Coastguard Worker
1818*89a0ef05SAndroid Build Coastguard Worker return handle->m_decoded_img_buffer.get();
1819*89a0ef05SAndroid Build Coastguard Worker }
1820*89a0ef05SAndroid Build Coastguard Worker
uhdr_get_decoded_gainmap_image(uhdr_codec_private_t * dec)1821*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t* uhdr_get_decoded_gainmap_image(uhdr_codec_private_t* dec) {
1822*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) == nullptr) {
1823*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1824*89a0ef05SAndroid Build Coastguard Worker }
1825*89a0ef05SAndroid Build Coastguard Worker
1826*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1827*89a0ef05SAndroid Build Coastguard Worker if (!handle->m_sailed || handle->m_decode_call_status.error_code != UHDR_CODEC_OK) {
1828*89a0ef05SAndroid Build Coastguard Worker return nullptr;
1829*89a0ef05SAndroid Build Coastguard Worker }
1830*89a0ef05SAndroid Build Coastguard Worker
1831*89a0ef05SAndroid Build Coastguard Worker return handle->m_gainmap_img_buffer.get();
1832*89a0ef05SAndroid Build Coastguard Worker }
1833*89a0ef05SAndroid Build Coastguard Worker
uhdr_reset_decoder(uhdr_codec_private_t * dec)1834*89a0ef05SAndroid Build Coastguard Worker void uhdr_reset_decoder(uhdr_codec_private_t* dec) {
1835*89a0ef05SAndroid Build Coastguard Worker if (dynamic_cast<uhdr_decoder_private*>(dec) != nullptr) {
1836*89a0ef05SAndroid Build Coastguard Worker uhdr_decoder_private* handle = dynamic_cast<uhdr_decoder_private*>(dec);
1837*89a0ef05SAndroid Build Coastguard Worker
1838*89a0ef05SAndroid Build Coastguard Worker // clear entries and restore defaults
1839*89a0ef05SAndroid Build Coastguard Worker for (auto it : handle->m_effects) delete it;
1840*89a0ef05SAndroid Build Coastguard Worker handle->m_effects.clear();
1841*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
1842*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_gl_ctxt.reset_opengl_ctxt();
1843*89a0ef05SAndroid Build Coastguard Worker handle->m_enable_gles = false;
1844*89a0ef05SAndroid Build Coastguard Worker #endif
1845*89a0ef05SAndroid Build Coastguard Worker handle->m_sailed = false;
1846*89a0ef05SAndroid Build Coastguard Worker handle->m_uhdr_compressed_img.reset();
1847*89a0ef05SAndroid Build Coastguard Worker handle->m_output_fmt = UHDR_IMG_FMT_64bppRGBAHalfFloat;
1848*89a0ef05SAndroid Build Coastguard Worker handle->m_output_ct = UHDR_CT_LINEAR;
1849*89a0ef05SAndroid Build Coastguard Worker handle->m_output_max_disp_boost = FLT_MAX;
1850*89a0ef05SAndroid Build Coastguard Worker
1851*89a0ef05SAndroid Build Coastguard Worker // ready to be configured
1852*89a0ef05SAndroid Build Coastguard Worker handle->m_probed = false;
1853*89a0ef05SAndroid Build Coastguard Worker handle->m_decoded_img_buffer.reset();
1854*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img_buffer.reset();
1855*89a0ef05SAndroid Build Coastguard Worker handle->m_img_wd = 0;
1856*89a0ef05SAndroid Build Coastguard Worker handle->m_img_ht = 0;
1857*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_wd = 0;
1858*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_ht = 0;
1859*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_num_comp = 0;
1860*89a0ef05SAndroid Build Coastguard Worker handle->m_exif.clear();
1861*89a0ef05SAndroid Build Coastguard Worker memset(&handle->m_exif_block, 0, sizeof handle->m_exif_block);
1862*89a0ef05SAndroid Build Coastguard Worker handle->m_icc.clear();
1863*89a0ef05SAndroid Build Coastguard Worker memset(&handle->m_icc_block, 0, sizeof handle->m_icc_block);
1864*89a0ef05SAndroid Build Coastguard Worker handle->m_base_img.clear();
1865*89a0ef05SAndroid Build Coastguard Worker memset(&handle->m_base_img_block, 0, sizeof handle->m_base_img_block);
1866*89a0ef05SAndroid Build Coastguard Worker handle->m_gainmap_img.clear();
1867*89a0ef05SAndroid Build Coastguard Worker memset(&handle->m_gainmap_img_block, 0, sizeof handle->m_gainmap_img_block);
1868*89a0ef05SAndroid Build Coastguard Worker memset(&handle->m_metadata, 0, sizeof handle->m_metadata);
1869*89a0ef05SAndroid Build Coastguard Worker handle->m_probe_call_status = g_no_error;
1870*89a0ef05SAndroid Build Coastguard Worker handle->m_decode_call_status = g_no_error;
1871*89a0ef05SAndroid Build Coastguard Worker }
1872*89a0ef05SAndroid Build Coastguard Worker }
1873*89a0ef05SAndroid Build Coastguard Worker
uhdr_enable_gpu_acceleration(uhdr_codec_private_t * codec,int enable)1874*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_enable_gpu_acceleration(uhdr_codec_private_t* codec,
1875*89a0ef05SAndroid Build Coastguard Worker [[maybe_unused]] int enable) {
1876*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1877*89a0ef05SAndroid Build Coastguard Worker
1878*89a0ef05SAndroid Build Coastguard Worker if (codec == nullptr) {
1879*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1880*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1881*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1882*89a0ef05SAndroid Build Coastguard Worker return status;
1883*89a0ef05SAndroid Build Coastguard Worker }
1884*89a0ef05SAndroid Build Coastguard Worker
1885*89a0ef05SAndroid Build Coastguard Worker if (codec->m_sailed) {
1886*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1887*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1888*89a0ef05SAndroid Build Coastguard Worker snprintf(
1889*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
1890*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode()/uhdr_decode() has switched the context from configurable "
1891*89a0ef05SAndroid Build Coastguard Worker "state to end state. The context is no longer configurable. To reuse, call reset()");
1892*89a0ef05SAndroid Build Coastguard Worker return status;
1893*89a0ef05SAndroid Build Coastguard Worker }
1894*89a0ef05SAndroid Build Coastguard Worker
1895*89a0ef05SAndroid Build Coastguard Worker #ifdef UHDR_ENABLE_GLES
1896*89a0ef05SAndroid Build Coastguard Worker codec->m_enable_gles = enable;
1897*89a0ef05SAndroid Build Coastguard Worker #endif
1898*89a0ef05SAndroid Build Coastguard Worker
1899*89a0ef05SAndroid Build Coastguard Worker return status;
1900*89a0ef05SAndroid Build Coastguard Worker }
1901*89a0ef05SAndroid Build Coastguard Worker
uhdr_add_effect_mirror(uhdr_codec_private_t * codec,uhdr_mirror_direction_t direction)1902*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_add_effect_mirror(uhdr_codec_private_t* codec,
1903*89a0ef05SAndroid Build Coastguard Worker uhdr_mirror_direction_t direction) {
1904*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1905*89a0ef05SAndroid Build Coastguard Worker
1906*89a0ef05SAndroid Build Coastguard Worker if (codec == nullptr) {
1907*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1908*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1909*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1910*89a0ef05SAndroid Build Coastguard Worker return status;
1911*89a0ef05SAndroid Build Coastguard Worker }
1912*89a0ef05SAndroid Build Coastguard Worker
1913*89a0ef05SAndroid Build Coastguard Worker if (direction != UHDR_MIRROR_HORIZONTAL && direction != UHDR_MIRROR_VERTICAL) {
1914*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1915*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1916*89a0ef05SAndroid Build Coastguard Worker snprintf(
1917*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
1918*89a0ef05SAndroid Build Coastguard Worker "unsupported direction, expects one of {UHDR_MIRROR_HORIZONTAL, UHDR_MIRROR_VERTICAL}");
1919*89a0ef05SAndroid Build Coastguard Worker return status;
1920*89a0ef05SAndroid Build Coastguard Worker }
1921*89a0ef05SAndroid Build Coastguard Worker
1922*89a0ef05SAndroid Build Coastguard Worker if (codec->m_sailed) {
1923*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1924*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1925*89a0ef05SAndroid Build Coastguard Worker snprintf(
1926*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
1927*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode()/uhdr_decode() has switched the context from configurable "
1928*89a0ef05SAndroid Build Coastguard Worker "state to end state. The context is no longer configurable. To reuse, call reset()");
1929*89a0ef05SAndroid Build Coastguard Worker return status;
1930*89a0ef05SAndroid Build Coastguard Worker }
1931*89a0ef05SAndroid Build Coastguard Worker
1932*89a0ef05SAndroid Build Coastguard Worker codec->m_effects.push_back(new ultrahdr::uhdr_mirror_effect_t(direction));
1933*89a0ef05SAndroid Build Coastguard Worker
1934*89a0ef05SAndroid Build Coastguard Worker return status;
1935*89a0ef05SAndroid Build Coastguard Worker }
1936*89a0ef05SAndroid Build Coastguard Worker
uhdr_add_effect_rotate(uhdr_codec_private_t * codec,int degrees)1937*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_add_effect_rotate(uhdr_codec_private_t* codec, int degrees) {
1938*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1939*89a0ef05SAndroid Build Coastguard Worker
1940*89a0ef05SAndroid Build Coastguard Worker if (codec == nullptr) {
1941*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1942*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1943*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1944*89a0ef05SAndroid Build Coastguard Worker return status;
1945*89a0ef05SAndroid Build Coastguard Worker }
1946*89a0ef05SAndroid Build Coastguard Worker
1947*89a0ef05SAndroid Build Coastguard Worker if (degrees != 90 && degrees != 180 && degrees != 270) {
1948*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1949*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1950*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail,
1951*89a0ef05SAndroid Build Coastguard Worker "unsupported degrees, expects one of {90, 180, 270}");
1952*89a0ef05SAndroid Build Coastguard Worker return status;
1953*89a0ef05SAndroid Build Coastguard Worker }
1954*89a0ef05SAndroid Build Coastguard Worker
1955*89a0ef05SAndroid Build Coastguard Worker if (codec->m_sailed) {
1956*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1957*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1958*89a0ef05SAndroid Build Coastguard Worker snprintf(
1959*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
1960*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode()/uhdr_decode() has switched the context from configurable "
1961*89a0ef05SAndroid Build Coastguard Worker "state to end state. The context is no longer configurable. To reuse, call reset()");
1962*89a0ef05SAndroid Build Coastguard Worker return status;
1963*89a0ef05SAndroid Build Coastguard Worker }
1964*89a0ef05SAndroid Build Coastguard Worker
1965*89a0ef05SAndroid Build Coastguard Worker codec->m_effects.push_back(new ultrahdr::uhdr_rotate_effect_t(degrees));
1966*89a0ef05SAndroid Build Coastguard Worker
1967*89a0ef05SAndroid Build Coastguard Worker return status;
1968*89a0ef05SAndroid Build Coastguard Worker }
1969*89a0ef05SAndroid Build Coastguard Worker
uhdr_add_effect_crop(uhdr_codec_private_t * codec,int left,int right,int top,int bottom)1970*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_add_effect_crop(uhdr_codec_private_t* codec, int left, int right, int top,
1971*89a0ef05SAndroid Build Coastguard Worker int bottom) {
1972*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1973*89a0ef05SAndroid Build Coastguard Worker
1974*89a0ef05SAndroid Build Coastguard Worker if (codec == nullptr) {
1975*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
1976*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1977*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
1978*89a0ef05SAndroid Build Coastguard Worker return status;
1979*89a0ef05SAndroid Build Coastguard Worker }
1980*89a0ef05SAndroid Build Coastguard Worker
1981*89a0ef05SAndroid Build Coastguard Worker if (codec->m_sailed) {
1982*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
1983*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
1984*89a0ef05SAndroid Build Coastguard Worker snprintf(
1985*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
1986*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode()/uhdr_decode() has switched the context from configurable "
1987*89a0ef05SAndroid Build Coastguard Worker "state to end state. The context is no longer configurable. To reuse, call reset()");
1988*89a0ef05SAndroid Build Coastguard Worker return status;
1989*89a0ef05SAndroid Build Coastguard Worker }
1990*89a0ef05SAndroid Build Coastguard Worker
1991*89a0ef05SAndroid Build Coastguard Worker codec->m_effects.push_back(new ultrahdr::uhdr_crop_effect_t(left, right, top, bottom));
1992*89a0ef05SAndroid Build Coastguard Worker
1993*89a0ef05SAndroid Build Coastguard Worker return status;
1994*89a0ef05SAndroid Build Coastguard Worker }
1995*89a0ef05SAndroid Build Coastguard Worker
uhdr_add_effect_resize(uhdr_codec_private_t * codec,int width,int height)1996*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t uhdr_add_effect_resize(uhdr_codec_private_t* codec, int width, int height) {
1997*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = g_no_error;
1998*89a0ef05SAndroid Build Coastguard Worker
1999*89a0ef05SAndroid Build Coastguard Worker if (codec == nullptr) {
2000*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_PARAM;
2001*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
2002*89a0ef05SAndroid Build Coastguard Worker snprintf(status.detail, sizeof status.detail, "received nullptr for uhdr codec instance");
2003*89a0ef05SAndroid Build Coastguard Worker return status;
2004*89a0ef05SAndroid Build Coastguard Worker }
2005*89a0ef05SAndroid Build Coastguard Worker
2006*89a0ef05SAndroid Build Coastguard Worker if (codec->m_sailed) {
2007*89a0ef05SAndroid Build Coastguard Worker status.error_code = UHDR_CODEC_INVALID_OPERATION;
2008*89a0ef05SAndroid Build Coastguard Worker status.has_detail = 1;
2009*89a0ef05SAndroid Build Coastguard Worker snprintf(
2010*89a0ef05SAndroid Build Coastguard Worker status.detail, sizeof status.detail,
2011*89a0ef05SAndroid Build Coastguard Worker "An earlier call to uhdr_encode()/uhdr_decode() has switched the context from configurable "
2012*89a0ef05SAndroid Build Coastguard Worker "state to end state. The context is no longer configurable. To reuse, call reset()");
2013*89a0ef05SAndroid Build Coastguard Worker return status;
2014*89a0ef05SAndroid Build Coastguard Worker }
2015*89a0ef05SAndroid Build Coastguard Worker
2016*89a0ef05SAndroid Build Coastguard Worker codec->m_effects.push_back(new ultrahdr::uhdr_resize_effect_t(width, height));
2017*89a0ef05SAndroid Build Coastguard Worker
2018*89a0ef05SAndroid Build Coastguard Worker return status;
2019*89a0ef05SAndroid Build Coastguard Worker }
2020