blob: 55973034bbf073776f10a1c1517c9f4c1417bad5 [file] [log] [blame]
Dichen Zhang85b37562022-10-11 11:08:28 -07001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Nick Deakinf6bca5a2022-11-04 10:43:43 -040017#ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAP_H
18#define ANDROID_JPEGRECOVERYMAP_RECOVERYMAP_H
19
Dichen Zhang80b72482022-11-02 01:55:35 +000020#include "jpegrerrorcode.h"
Dichen Zhang6947d532022-10-22 02:16:21 +000021
Dichen Zhang85b37562022-10-11 11:08:28 -070022namespace android::recoverymap {
23
Dichen Zhangffa34012022-11-03 23:21:13 +000024typedef enum {
Nick Deakin6bd90432022-11-20 16:26:37 -050025 JPEGR_COLORGAMUT_UNSPECIFIED,
26 JPEGR_COLORGAMUT_BT709,
27 JPEGR_COLORGAMUT_P3,
28 JPEGR_COLORGAMUT_BT2100,
29} jpegr_color_gamut;
30
31// Transfer functions as defined for XMP metadata
32typedef enum {
33 JPEGR_TF_HLG = 0,
34 JPEGR_TF_PQ = 1,
35} jpegr_transfer_function;
Dichen Zhangffa34012022-11-03 23:21:13 +000036
Fyodor Kyslov1dcc4422022-11-16 01:40:53 +000037struct jpegr_info_struct {
38 size_t width;
39 size_t height;
40 std::vector<uint8_t>* iccData;
41 std::vector<uint8_t>* exifData;
42};
43
Dichen Zhang596a7562022-10-12 14:57:05 -070044/*
45 * Holds information for uncompressed image or recovery map.
46 */
Dichen Zhang6947d532022-10-22 02:16:21 +000047struct jpegr_uncompressed_struct {
Dichen Zhang596a7562022-10-12 14:57:05 -070048 // Pointer to the data location.
49 void* data;
50 // Width of the recovery map or image in pixels.
51 int width;
52 // Height of the recovery map or image in pixels.
53 int height;
Nick Deakin6bd90432022-11-20 16:26:37 -050054 // Color gamut.
55 jpegr_color_gamut colorGamut;
Dichen Zhang596a7562022-10-12 14:57:05 -070056};
57
58/*
59 * Holds information for compressed image or recovery map.
60 */
Dichen Zhang6947d532022-10-22 02:16:21 +000061struct jpegr_compressed_struct {
Dichen Zhang596a7562022-10-12 14:57:05 -070062 // Pointer to the data location.
63 void* data;
Dichen Zhang0b9f7de2022-11-18 06:52:46 +000064 // Used data length in bytes.
Dichen Zhangffa34012022-11-03 23:21:13 +000065 int length;
Dichen Zhang0b9f7de2022-11-18 06:52:46 +000066 // Maximum available data length in bytes.
67 int maxLength;
Nick Deakin6bd90432022-11-20 16:26:37 -050068 // Color gamut.
69 jpegr_color_gamut colorGamut;
Dichen Zhangffa34012022-11-03 23:21:13 +000070};
71
72/*
73 * Holds information for EXIF metadata.
74 */
75struct jpegr_exif_struct {
76 // Pointer to the data location.
77 void* data;
Dichen Zhang596a7562022-10-12 14:57:05 -070078 // Data length;
79 int length;
80};
81
Nick Deakin6bd90432022-11-20 16:26:37 -050082struct chromaticity_coord {
83 float x;
84 float y;
85};
86
87
88struct st2086_metadata {
89 // xy chromaticity coordinate of the red primary of the mastering display
90 chromaticity_coord redPrimary;
91 // xy chromaticity coordinate of the green primary of the mastering display
92 chromaticity_coord greenPrimary;
93 // xy chromaticity coordinate of the blue primary of the mastering display
94 chromaticity_coord bluePrimary;
95 // xy chromaticity coordinate of the white point of the mastering display
96 chromaticity_coord whitePoint;
97 // Maximum luminance in nits of the mastering display
98 uint32_t maxLuminance;
99 // Minimum luminance in nits of the mastering display
100 float minLuminance;
101};
102
103struct hdr10_metadata {
104 // Mastering display color volume
105 st2086_metadata st2086Metadata;
106 // Max frame average light level in nits
107 float maxFALL;
108 // Max content light level in nits
109 float maxCLL;
110};
111
112struct jpegr_metadata {
113 // JPEG/R version
114 uint32_t version;
115 // Range scaling factor for the map
116 float rangeScalingFactor;
117 // The transfer function for decoding the HDR representation of the image
118 jpegr_transfer_function transferFunction;
119 // HDR10 metadata, only applicable for transferFunction of JPEGR_TF_PQ
120 hdr10_metadata hdr10Metadata;
121};
122
Dichen Zhang6947d532022-10-22 02:16:21 +0000123typedef struct jpegr_uncompressed_struct* jr_uncompressed_ptr;
124typedef struct jpegr_compressed_struct* jr_compressed_ptr;
Dichen Zhangffa34012022-11-03 23:21:13 +0000125typedef struct jpegr_exif_struct* jr_exif_ptr;
Nick Deakin6bd90432022-11-20 16:26:37 -0500126typedef struct jpegr_metadata* jr_metadata_ptr;
Fyodor Kyslov1dcc4422022-11-16 01:40:53 +0000127typedef struct jpegr_info_struct* jr_info_ptr;
Dichen Zhang596a7562022-10-12 14:57:05 -0700128
Dichen Zhang85b37562022-10-11 11:08:28 -0700129class RecoveryMap {
130public:
131 /*
Dichen Zhang6947d532022-10-22 02:16:21 +0000132 * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
133 *
134 * Generate recovery map from the HDR and SDR inputs, compress SDR YUV to 8-bit JPEG and append
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400135 * the recovery map to the end of the compressed JPEG. HDR and SDR inputs must be the same
Nick Deakin6bd90432022-11-20 16:26:37 -0500136 * resolution.
Dichen Zhang6947d532022-10-22 02:16:21 +0000137 * @param uncompressed_p010_image uncompressed HDR image in P010 color format
138 * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
Nick Deakin6bd90432022-11-20 16:26:37 -0500139 * @param hdr_tf transfer function of the HDR image
Dichen Zhang6947d532022-10-22 02:16:21 +0000140 * @param dest destination of the compressed JPEGR image
Dichen Zhangffa34012022-11-03 23:21:13 +0000141 * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
142 * the highest quality
143 * @param exif pointer to the exif metadata.
Dichen Zhang6947d532022-10-22 02:16:21 +0000144 * @return NO_ERROR if encoding succeeds, error code if error occurs.
145 */
146 status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
147 jr_uncompressed_ptr uncompressed_yuv_420_image,
Nick Deakin6bd90432022-11-20 16:26:37 -0500148 jpegr_transfer_function hdr_tf,
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400149 jr_compressed_ptr dest,
Dichen Zhangffa34012022-11-03 23:21:13 +0000150 int quality,
Dichen Zhang95cbb9f2022-11-07 18:32:05 +0000151 jr_exif_ptr exif);
Dichen Zhang6947d532022-10-22 02:16:21 +0000152
153 /*
Dichen Zhangffa34012022-11-03 23:21:13 +0000154 * Compress JPEGR image from 10-bit HDR YUV, 8-bit SDR YUV and compressed 8-bit JPEG.
155 *
156 * This method requires HAL Hardware JPEG encoder.
Dichen Zhang6947d532022-10-22 02:16:21 +0000157 *
158 * Generate recovery map from the HDR and SDR inputs, append the recovery map to the end of the
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400159 * compressed JPEG. HDR and SDR inputs must be the same resolution and color space.
Dichen Zhang6947d532022-10-22 02:16:21 +0000160 * @param uncompressed_p010_image uncompressed HDR image in P010 color format
161 * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
162 * @param compressed_jpeg_image compressed 8-bit JPEG image
Nick Deakin6bd90432022-11-20 16:26:37 -0500163 * @param hdr_tf transfer function of the HDR image
Dichen Zhang6947d532022-10-22 02:16:21 +0000164 * @param dest destination of the compressed JPEGR image
165 * @return NO_ERROR if encoding succeeds, error code if error occurs.
166 */
167 status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
168 jr_uncompressed_ptr uncompressed_yuv_420_image,
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400169 jr_compressed_ptr compressed_jpeg_image,
Nick Deakin6bd90432022-11-20 16:26:37 -0500170 jpegr_transfer_function hdr_tf,
Dichen Zhang95cbb9f2022-11-07 18:32:05 +0000171 jr_compressed_ptr dest);
Dichen Zhang6947d532022-10-22 02:16:21 +0000172
173 /*
174 * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
175 *
Dichen Zhangffa34012022-11-03 23:21:13 +0000176 * This method requires HAL Hardware JPEG encoder.
177 *
Dichen Zhang6947d532022-10-22 02:16:21 +0000178 * Decode the compressed 8-bit JPEG image to YUV SDR, generate recovery map from the HDR input
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400179 * and the decoded SDR result, append the recovery map to the end of the compressed JPEG. HDR
Nick Deakin6bd90432022-11-20 16:26:37 -0500180 * and SDR inputs must be the same resolution.
Dichen Zhang6947d532022-10-22 02:16:21 +0000181 * @param uncompressed_p010_image uncompressed HDR image in P010 color format
182 * @param compressed_jpeg_image compressed 8-bit JPEG image
Nick Deakin6bd90432022-11-20 16:26:37 -0500183 * @param hdr_tf transfer function of the HDR image
Dichen Zhang6947d532022-10-22 02:16:21 +0000184 * @param dest destination of the compressed JPEGR image
185 * @return NO_ERROR if encoding succeeds, error code if error occurs.
186 */
187 status_t encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400188 jr_compressed_ptr compressed_jpeg_image,
Nick Deakin6bd90432022-11-20 16:26:37 -0500189 jpegr_transfer_function hdr_tf,
Dichen Zhang95cbb9f2022-11-07 18:32:05 +0000190 jr_compressed_ptr dest);
Dichen Zhang6947d532022-10-22 02:16:21 +0000191
192 /*
193 * Decompress JPEGR image.
194 *
Nick Deakin6bd90432022-11-20 16:26:37 -0500195 * The output JPEGR image is in RGBA_1010102 data format if decoding to HDR.
Dichen Zhang6947d532022-10-22 02:16:21 +0000196 * @param compressed_jpegr_image compressed JPEGR image
197 * @param dest destination of the uncompressed JPEGR image
Nick Deakin6bd90432022-11-20 16:26:37 -0500198 * @param exif destination of the decoded EXIF metadata.
199 * @param request_sdr flag that request SDR output. If set to true, decoder will only decode
200 * the primary image which is SDR. Setting of request_sdr and input source
201 * (HDR or SDR) can be found in the table below:
Dichen Zhangffa34012022-11-03 23:21:13 +0000202 * | input source | request_sdr | output of decoding |
203 * | HDR | true | SDR |
204 * | HDR | false | HDR |
205 * | SDR | true | SDR |
206 * | SDR | false | SDR |
Dichen Zhang6947d532022-10-22 02:16:21 +0000207 * @return NO_ERROR if decoding succeeds, error code if error occurs.
208 */
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400209 status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image,
Dichen Zhangffa34012022-11-03 23:21:13 +0000210 jr_uncompressed_ptr dest,
Fyodor Kyslov1dcc4422022-11-16 01:40:53 +0000211 jr_exif_ptr exif = nullptr,
212 bool request_sdr = false);
213
214 /*
215 * Gets Info from JPEGR file without decoding it.
216 *
217 * The output is filled jpegr_info structure
218 * @param compressed_jpegr_image compressed JPEGR image
219 * @param jpegr_info pointer to output JPEGR info
220 * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise
221 */
222 status_t getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image,
223 jr_info_ptr jpegr_info);
Dichen Zhang6947d532022-10-22 02:16:21 +0000224private:
225 /*
Dichen Zhang85b37562022-10-11 11:08:28 -0700226 * This method is called in the decoding pipeline. It will decode the recovery map.
227 *
Dichen Zhang596a7562022-10-12 14:57:05 -0700228 * @param compressed_recovery_map compressed recovery map
229 * @param dest decoded recover map
Dichen Zhang6947d532022-10-22 02:16:21 +0000230 * @return NO_ERROR if decoding succeeds, error code if error occurs.
Dichen Zhang85b37562022-10-11 11:08:28 -0700231 */
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400232 status_t decompressRecoveryMap(jr_compressed_ptr compressed_recovery_map,
Dichen Zhang6947d532022-10-22 02:16:21 +0000233 jr_uncompressed_ptr dest);
Dichen Zhang85b37562022-10-11 11:08:28 -0700234
235 /*
236 * This method is called in the encoding pipeline. It will encode the recovery map.
237 *
Dichen Zhang596a7562022-10-12 14:57:05 -0700238 * @param uncompressed_recovery_map uncompressed recovery map
239 * @param dest encoded recover map
Dichen Zhang6947d532022-10-22 02:16:21 +0000240 * @return NO_ERROR if encoding succeeds, error code if error occurs.
Dichen Zhang85b37562022-10-11 11:08:28 -0700241 */
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400242 status_t compressRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_map,
Dichen Zhang6947d532022-10-22 02:16:21 +0000243 jr_compressed_ptr dest);
Dichen Zhang85b37562022-10-11 11:08:28 -0700244
245 /*
246 * This method is called in the encoding pipeline. It will take the uncompressed 8-bit and
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400247 * 10-bit yuv images as input, and calculate the uncompressed recovery map. The input images
248 * must be the same resolution.
Dichen Zhang85b37562022-10-11 11:08:28 -0700249 *
Dichen Zhang596a7562022-10-12 14:57:05 -0700250 * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
251 * @param uncompressed_p010_image uncompressed HDR image in P010 color format
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400252 * @param dest recovery map; caller responsible for memory of data
Nick Deakin6bd90432022-11-20 16:26:37 -0500253 * @param metadata metadata provides the transfer function for the HDR
254 * image; range_scaling_factor and hdr10 FALL and CLL will
255 * be updated.
Dichen Zhang6947d532022-10-22 02:16:21 +0000256 * @return NO_ERROR if calculation succeeds, error code if error occurs.
Dichen Zhang85b37562022-10-11 11:08:28 -0700257 */
Dichen Zhang6947d532022-10-22 02:16:21 +0000258 status_t generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
259 jr_uncompressed_ptr uncompressed_p010_image,
Nick Deakin6bd90432022-11-20 16:26:37 -0500260 jr_metadata_ptr metadata,
261 jr_uncompressed_ptr dest);
Dichen Zhang85b37562022-10-11 11:08:28 -0700262
263 /*
264 * This method is called in the decoding pipeline. It will take the uncompressed (decoded)
Nick Deakin6bd90432022-11-20 16:26:37 -0500265 * 8-bit yuv image, the uncompressed (decoded) recovery map, and extracted JPEG/R metadata as
266 * input, and calculate the 10-bit recovered image. The recovered output image is the same
267 * color gamut as the SDR image, with the transfer function specified in the JPEG/R metadata,
268 * and is in RGBA1010102 data format.
Dichen Zhang85b37562022-10-11 11:08:28 -0700269 *
Dichen Zhang596a7562022-10-12 14:57:05 -0700270 * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
271 * @param uncompressed_recovery_map uncompressed recovery map
Nick Deakin6bd90432022-11-20 16:26:37 -0500272 * @param metadata JPEG/R metadata extracted from XMP.
Dichen Zhang596a7562022-10-12 14:57:05 -0700273 * @param dest reconstructed HDR image
Dichen Zhang6947d532022-10-22 02:16:21 +0000274 * @return NO_ERROR if calculation succeeds, error code if error occurs.
Dichen Zhang85b37562022-10-11 11:08:28 -0700275 */
Dichen Zhang6947d532022-10-22 02:16:21 +0000276 status_t applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
277 jr_uncompressed_ptr uncompressed_recovery_map,
Nick Deakin6bd90432022-11-20 16:26:37 -0500278 jr_metadata_ptr metadata,
Dichen Zhang6947d532022-10-22 02:16:21 +0000279 jr_uncompressed_ptr dest);
Dichen Zhang85b37562022-10-11 11:08:28 -0700280
281 /*
Fyodor Kyslov1dcc4422022-11-16 01:40:53 +0000282 * This methoud is called to separate primary image and recovery map image from JPEGR
283 *
284 * @param compressed_jpegr_image compressed JPEGR image
285 * @param primary_image destination of primary image
286 * @param recovery_map destination of compressed recovery map
287 * @return NO_ERROR if calculation succeeds, error code if error occurs.
288 */
289 status_t extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
290 jr_compressed_ptr primary_image,
291 jr_compressed_ptr recovery_map);
292 /*
Dichen Zhang85b37562022-10-11 11:08:28 -0700293 * This method is called in the decoding pipeline. It will read XMP metadata to find the start
294 * position of the compressed recovery map, and will extract the compressed recovery map.
295 *
Dichen Zhang6947d532022-10-22 02:16:21 +0000296 * @param compressed_jpegr_image compressed JPEGR image
297 * @param dest destination of compressed recovery map
298 * @return NO_ERROR if calculation succeeds, error code if error occurs.
Dichen Zhang85b37562022-10-11 11:08:28 -0700299 */
Nick Deakin6bd90432022-11-20 16:26:37 -0500300 status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image,
Fyodor Kyslov1dcc4422022-11-16 01:40:53 +0000301 jr_compressed_ptr dest);
Dichen Zhang85b37562022-10-11 11:08:28 -0700302
303 /*
304 * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image
305 * and the compressed recovery map as input, and update the XMP metadata with the end of JPEG
306 * marker, and append the compressed gian map after the JPEG.
307 *
Dichen Zhang596a7562022-10-12 14:57:05 -0700308 * @param compressed_jpeg_image compressed 8-bit JPEG image
309 * @param compress_recovery_map compressed recover map
Nick Deakin6bd90432022-11-20 16:26:37 -0500310 * @param metadata JPEG/R metadata to encode in XMP of the jpeg
Dichen Zhang6947d532022-10-22 02:16:21 +0000311 * @param dest compressed JPEGR image
312 * @return NO_ERROR if calculation succeeds, error code if error occurs.
Dichen Zhang85b37562022-10-11 11:08:28 -0700313 */
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400314 status_t appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image,
Dichen Zhang6947d532022-10-22 02:16:21 +0000315 jr_compressed_ptr compressed_recovery_map,
Nick Deakin6bd90432022-11-20 16:26:37 -0500316 jr_metadata_ptr metadata,
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400317 jr_compressed_ptr dest);
Dichen Zhang72fd2b12022-11-01 06:11:50 +0000318
319 /*
320 * This method generates XMP metadata.
321 *
322 * below is an example of the XMP metadata that this function generates where
323 * secondary_image_length = 1000
Nick Deakin6bd90432022-11-20 16:26:37 -0500324 * range_scaling_factor = 1.25
Dichen Zhang72fd2b12022-11-01 06:11:50 +0000325 *
326 * <x:xmpmeta
327 * xmlns:x="adobe:ns:meta/"
328 * x:xmptk="Adobe XMP Core 5.1.2">
329 * <rdf:RDF
330 * xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
331 * <rdf:Description
332 * xmlns:GContainer="http://ns.google.com/photos/1.0/container/">
333 * <GContainer:Version>1</GContainer:Version>
Nick Deakin6bd90432022-11-20 16:26:37 -0500334 * <GContainer:RangeScalingFactor>1.25</GContainer:RangeScalingFactor>
Dichen Zhang72fd2b12022-11-01 06:11:50 +0000335 * <GContainer:Directory>
336 * <rdf:Seq>
337 * <rdf:li>
338 * <GContainer:Item
339 * Item:Semantic="Primary"
340 * Item:Mime="image/jpeg"/>
341 * </rdf:li>
342 * <rdf:li>
343 * <GContainer:Item
344 * Item:Semantic="RecoveryMap"
345 * Item:Mime="image/jpeg"
346 * Item:Length="1000"/>
347 * </rdf:li>
348 * </rdf:Seq>
349 * </GContainer:Directory>
350 * </rdf:Description>
351 * </rdf:RDF>
352 * </x:xmpmeta>
353 *
354 * @param secondary_image_length length of secondary image
Nick Deakin6bd90432022-11-20 16:26:37 -0500355 * @param metadata JPEG/R metadata to encode as XMP
Dichen Zhang72fd2b12022-11-01 06:11:50 +0000356 * @return XMP metadata in type of string
357 */
Nick Deakin6bd90432022-11-20 16:26:37 -0500358 std::string generateXmp(int secondary_image_length, jpegr_metadata& metadata);
Dichen Zhang85b37562022-10-11 11:08:28 -0700359};
360
Dichen Zhang596a7562022-10-12 14:57:05 -0700361} // namespace android::recoverymap
Nick Deakinf6bca5a2022-11-04 10:43:43 -0400362
363#endif // ANDROID_JPEGRECOVERYMAP_RECOVERYMAP_H