Skip to content

Commit 04788ce

Browse files
ram-mohanDichenZhang1
authored andcommitted
Allow for larger excursions of min, max content boost
Current implementation clips min/max content boost to a smaller range. Allow for larger excursions for better hdr intent representation. This is not enabled by default and is enabled in best quality encoding preset. Test: ./ultrahdr_app <options> -D 1 Test: ./ultrahdr_unit_test
1 parent 4ef6913 commit 04788ce

10 files changed

Lines changed: 449 additions & 192 deletions

File tree

examples/ultrahdr_app.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -244,17 +244,20 @@ static bool writeFile(const char* filename, uhdr_raw_image_t* img) {
244244

245245
class UltraHdrAppInput {
246246
public:
247-
UltraHdrAppInput(
248-
const char* hdrIntentRawFile, const char* sdrIntentRawFile,
249-
const char* sdrIntentCompressedFile, const char* gainmapCompressedFile,
250-
const char* gainmapMetadataCfgFile, const char* exifFile, const char* outputFile,
251-
size_t width, size_t height, uhdr_img_fmt_t hdrCf = UHDR_IMG_FMT_32bppRGBA1010102,
252-
uhdr_img_fmt_t sdrCf = UHDR_IMG_FMT_32bppRGBA8888,
253-
uhdr_color_gamut_t hdrCg = UHDR_CG_DISPLAY_P3, uhdr_color_gamut_t sdrCg = UHDR_CG_BT_709,
254-
uhdr_color_transfer_t hdrTf = UHDR_CT_HLG, int quality = 95,
255-
uhdr_color_transfer_t oTf = UHDR_CT_HLG, uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102,
256-
bool isHdrCrFull = false, int gainmapScaleFactor = 4, int gainmapQuality = 85,
257-
bool enableMultiChannelGainMap = false, float gamma = 1.0f, bool enableGLES = false)
247+
UltraHdrAppInput(const char* hdrIntentRawFile, const char* sdrIntentRawFile,
248+
const char* sdrIntentCompressedFile, const char* gainmapCompressedFile,
249+
const char* gainmapMetadataCfgFile, const char* exifFile, const char* outputFile,
250+
size_t width, size_t height,
251+
uhdr_img_fmt_t hdrCf = UHDR_IMG_FMT_32bppRGBA1010102,
252+
uhdr_img_fmt_t sdrCf = UHDR_IMG_FMT_32bppRGBA8888,
253+
uhdr_color_gamut_t hdrCg = UHDR_CG_DISPLAY_P3,
254+
uhdr_color_gamut_t sdrCg = UHDR_CG_BT_709,
255+
uhdr_color_transfer_t hdrTf = UHDR_CT_HLG, int quality = 95,
256+
uhdr_color_transfer_t oTf = UHDR_CT_HLG,
257+
uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102, bool isHdrCrFull = false,
258+
int gainmapScaleFactor = 4, int gainmapQuality = 85,
259+
bool enableMultiChannelGainMap = false, float gamma = 1.0f,
260+
bool enableGLES = false, uhdr_enc_preset_t encPreset = UHDR_USAGE_REALTIME)
258261
: mHdrIntentRawFile(hdrIntentRawFile),
259262
mSdrIntentRawFile(sdrIntentRawFile),
260263
mSdrIntentCompressedFile(sdrIntentCompressedFile),
@@ -279,6 +282,7 @@ class UltraHdrAppInput {
279282
mUseMultiChannelGainMap(enableMultiChannelGainMap),
280283
mGamma(gamma),
281284
mEnableGLES(enableGLES),
285+
mEncPreset(encPreset),
282286
mMode(0){};
283287

284288
UltraHdrAppInput(const char* gainmapMetadataCfgFile, const char* uhdrFile, const char* outputFile,
@@ -308,6 +312,7 @@ class UltraHdrAppInput {
308312
mUseMultiChannelGainMap(false),
309313
mGamma(1.0f),
310314
mEnableGLES(enableGLES),
315+
mEncPreset(UHDR_USAGE_REALTIME),
311316
mMode(1){};
312317

313318
~UltraHdrAppInput() {
@@ -387,6 +392,7 @@ class UltraHdrAppInput {
387392
const bool mUseMultiChannelGainMap;
388393
const float mGamma;
389394
const bool mEnableGLES;
395+
const uhdr_enc_preset_t mEncPreset;
390396
const int mMode;
391397

392398
uhdr_raw_image_t mRawP010Image{};
@@ -683,6 +689,7 @@ bool UltraHdrAppInput::encode() {
683689
RET_IF_ERR(uhdr_enc_set_using_multi_channel_gainmap(handle, mUseMultiChannelGainMap))
684690
RET_IF_ERR(uhdr_enc_set_gainmap_scale_factor(handle, mMapDimensionScaleFactor))
685691
RET_IF_ERR(uhdr_enc_set_gainmap_gamma(handle, mGamma))
692+
RET_IF_ERR(uhdr_enc_set_preset(handle, mEncPreset))
686693
if (mEnableGLES) {
687694
RET_IF_ERR(uhdr_enable_gpu_acceleration(handle, mEnableGLES))
688695
}
@@ -1348,6 +1355,9 @@ static void usage(const char* name) {
13481355
"real number (1.0 : default)].\n");
13491356
fprintf(stderr,
13501357
" -M select multi channel gain map, optional. [0:disable (default), 1:enable]. \n");
1358+
fprintf(
1359+
stderr,
1360+
" -D select encoding preset, optional. [0:real time (default), 1:best quality]. \n");
13511361
fprintf(stderr, " -x binary input resource containing exif data to insert, optional. \n");
13521362
fprintf(stderr, "\n## decoder options : \n");
13531363
fprintf(stderr, " -j ultra hdr compressed input resource, required. \n");
@@ -1425,7 +1435,7 @@ static void usage(const char* name) {
14251435
fprintf(stderr, "\n## encode at high quality :\n");
14261436
fprintf(stderr,
14271437
" ultrahdr_app -m 0 -p hdr_intent.raw -y sdr_intent.raw -w 640 -h 480 -c <select> -C "
1428-
"<select> -t <select> -s 1 -M 1 -Q 98 -q 98\n");
1438+
"<select> -t <select> -s 1 -M 1 -Q 98 -q 98 -D 1\n");
14291439

14301440
fprintf(stderr, "\n## decode api :\n");
14311441
fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg \n");
@@ -1435,7 +1445,7 @@ static void usage(const char* name) {
14351445
}
14361446

14371447
int main(int argc, char* argv[]) {
1438-
char opt_string[] = "p:y:i:g:f:w:h:C:c:t:q:o:O:m:j:e:a:b:z:R:s:M:Q:G:x:u:";
1448+
char opt_string[] = "p:y:i:g:f:w:h:C:c:t:q:o:O:m:j:e:a:b:z:R:s:M:Q:G:x:u:D:";
14391449
char *hdr_intent_raw_file = nullptr, *sdr_intent_raw_file = nullptr, *uhdr_file = nullptr,
14401450
*sdr_intent_compressed_file = nullptr, *gainmap_compressed_file = nullptr,
14411451
*gainmap_metadata_cfg_file = nullptr, *output_file = nullptr, *exif_file = nullptr;
@@ -1456,6 +1466,7 @@ int main(int argc, char* argv[]) {
14561466
int compute_psnr = 0;
14571467
float gamma = 1.0f;
14581468
bool enable_gles = false;
1469+
uhdr_enc_preset_t enc_preset = UHDR_USAGE_REALTIME;
14591470
int ch;
14601471
while ((ch = getopt_s(argc, argv, opt_string)) != -1) {
14611472
switch (ch) {
@@ -1541,6 +1552,9 @@ int main(int argc, char* argv[]) {
15411552
case 'u':
15421553
enable_gles = atoi(optarg_s) == 1 ? true : false;
15431554
break;
1555+
case 'D':
1556+
enc_preset = static_cast<uhdr_enc_preset_t>(atoi(optarg_s));
1557+
break;
15441558
default:
15451559
usage(argv[0]);
15461560
return -1;
@@ -1568,7 +1582,7 @@ int main(int argc, char* argv[]) {
15681582
gainmap_compressed_file, gainmap_metadata_cfg_file, exif_file,
15691583
output_file ? output_file : "out.jpeg", width, height, hdr_cf, sdr_cf, hdr_cg, sdr_cg,
15701584
hdr_tf, quality, out_tf, out_cf, use_full_range_color_hdr, gainmap_scale_factor,
1571-
gainmap_compression_quality, use_multi_channel_gainmap, gamma, enable_gles);
1585+
gainmap_compression_quality, use_multi_channel_gainmap, gamma, enable_gles, enc_preset);
15721586
if (!appInput.encode()) return -1;
15731587
if (compute_psnr == 1) {
15741588
if (!appInput.decode()) return -1;

fuzzer/ultrahdr_enc_fuzzer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ void UltraHdrEncFuzzer::process() {
113113
// gainmap scale factor
114114
auto gm_scale_factor = mFdp.ConsumeIntegralInRange<int>(1, 128);
115115

116+
// encoding speed preset
117+
auto enc_preset = static_cast<uhdr_enc_preset_t>(mFdp.ConsumeIntegralInRange<int>(0, 1));
118+
116119
std::unique_ptr<uint32_t[]> bufferHdr = nullptr;
117120
std::unique_ptr<uint16_t[]> bufferYHdr = nullptr;
118121
std::unique_ptr<uint16_t[]> bufferUVHdr = nullptr;
@@ -265,6 +268,7 @@ void UltraHdrEncFuzzer::process() {
265268
ON_ERR(uhdr_enc_set_quality(enc_handle, gainmap_quality, UHDR_GAIN_MAP_IMG))
266269
ON_ERR(uhdr_enc_set_gainmap_scale_factor(enc_handle, gm_scale_factor))
267270
ON_ERR(uhdr_enc_set_using_multi_channel_gainmap(enc_handle, multi_channel_gainmap))
271+
ON_ERR(uhdr_enc_set_preset(enc_handle, enc_preset))
268272

269273
uhdr_error_info_t status = {UHDR_CODEC_OK, 0, ""};
270274
if (muxSwitch == 0 || muxSwitch == 1) { // api 0 or api 1

lib/include/ultrahdr/gainmapmath.h

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ struct GainLUT {
194194

195195
GainLUT(uhdr_gainmap_metadata_ext_t* metadata, float displayBoost) {
196196
this->mGammaInv = 1.0f / metadata->gamma;
197-
float boostFactor = displayBoost > 0 ? displayBoost / metadata->max_content_boost : 1.0f;
197+
float boostFactor = displayBoost > 0 ? displayBoost / metadata->hdr_capacity_max : 1.0f;
198198
for (int32_t idx = 0; idx < kGainFactorNumEntries; idx++) {
199199
float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
200200
float logBoost = log2(metadata->min_content_boost) * (1.0f - value) +
@@ -540,23 +540,17 @@ void transformYuv444(uhdr_raw_image_t* image, const std::array<float, 9>& coeffs
540540

541541
/*
542542
* Calculate the 8-bit unsigned integer gain value for the given SDR and HDR
543-
* luminances in linear space, and the hdr ratio to encode against.
544-
*
545-
* Note: since this library always uses gamma of 1.0, offsetSdr of 0.0, and
546-
* offsetHdr of 0.0, this function doesn't handle different metadata values for
547-
* these fields.
543+
* luminances in linear space and gainmap metadata fields.
548544
*/
549545
uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metadata);
550546
uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metadata,
551547
float log2MinContentBoost, float log2MaxContentBoost);
548+
float computeGain(float sdr, float hdr);
549+
uint8_t affineMapGain(float gainlog2, float mingainlog2, float maxgainlog2, float gamma);
552550

553551
/*
554552
* Calculates the linear luminance in nits after applying the given gain
555553
* value, with the given hdr ratio, to the given sdr input in the range [0, 1].
556-
*
557-
* Note: similar to encodeGain(), this function only supports gamma 1.0,
558-
* offsetSdr 0.0, offsetHdr 0.0, hdrCapacityMin 1.0, and hdrCapacityMax equal to
559-
* gainMapMax, as this library encodes.
560554
*/
561555
Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata);
562556
Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata, float displayBoost);
@@ -565,10 +559,6 @@ Color applyGainLUT(Color e, float gain, GainLUT& gainLUT);
565559
/*
566560
* Apply gain in R, G and B channels, with the given hdr ratio, to the given sdr input
567561
* in the range [0, 1].
568-
*
569-
* Note: similar to encodeGain(), this function only supports gamma 1.0,
570-
* offsetSdr 0.0, offsetHdr 0.0, hdrCapacityMin 1.0, and hdrCapacityMax equal to
571-
* gainMapMax, as this library encodes.
572562
*/
573563
Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata);
574564
Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata, float displayBoost);

lib/include/ultrahdr/jpegr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class JpegR {
7777
size_t mapDimensionScaleFactor = kMapDimensionScaleFactorDefault,
7878
int mapCompressQuality = kMapCompressQualityDefault,
7979
bool useMultiChannelGainMap = kUseMultiChannelGainMapDefault,
80-
float gamma = kGainMapGammaDefault);
80+
float gamma = kGainMapGammaDefault, uhdr_enc_preset_t preset = UHDR_USAGE_REALTIME);
8181

8282
/*!\brief Encode API-0.
8383
*
@@ -571,6 +571,7 @@ class JpegR {
571571
int mMapCompressQuality; // gain map quality factor
572572
bool mUseMultiChannelGainMap; // enable multichannel gain map
573573
float mGamma; // gain map gamma parameter
574+
uhdr_enc_preset_t mEncPreset; // encoding speed preset
574575
};
575576

576577
struct GlobalTonemapOutputs {

lib/include/ultrahdr/ultrahdrcommon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ struct uhdr_encoder_private : uhdr_codec_private {
327327
int m_gainmap_scale_factor;
328328
bool m_use_multi_channel_gainmap;
329329
float m_gamma;
330+
uhdr_enc_preset_t m_enc_preset;
330331

331332
// internal data
332333
std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_compressed_output_buffer;

lib/src/gainmapmath.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ SamplePixelFn getSamplePixelFn(uhdr_img_fmt_t format) {
490490
float getMaxDisplayMasteringLuminance(uhdr_color_transfer_t transfer) {
491491
switch (transfer) {
492492
case UHDR_CT_LINEAR:
493-
// TODO: configure maxCLL correctly for linear tf
493+
// TODO: configure MDML correctly for linear tf
494494
return kHlgMaxNits;
495495
case UHDR_CT_HLG:
496496
return kHlgMaxNits;
@@ -647,6 +647,22 @@ uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metada
647647
return static_cast<uint8_t>(gain_normalized_gamma * 255.0f);
648648
}
649649

650+
float computeGain(float sdr, float hdr) {
651+
if (sdr == 0.0f) return 0.0f; // for sdr black return no gain
652+
if (hdr == 0.0f) { // for hdr black, return a gain large enough to attenuate the sdr pel
653+
float offset = (1.0f / 64);
654+
return log2(offset / (offset + sdr));
655+
}
656+
return log2(hdr / sdr);
657+
}
658+
659+
uint8_t affineMapGain(float gainlog2, float mingainlog2, float maxgainlog2, float gamma) {
660+
float mappedVal = (gainlog2 - mingainlog2) / (maxgainlog2 - mingainlog2);
661+
if (gamma != 1.0f) mappedVal = pow(mappedVal, gamma);
662+
mappedVal *= 255;
663+
return CLIP3(mappedVal + 0.5f, 0, 255);
664+
}
665+
650666
Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata) {
651667
gain = pow(gain, 1.0f / metadata->gamma);
652668
float logBoost =
@@ -659,7 +675,7 @@ Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata, floa
659675
gain = pow(gain, 1.0f / metadata->gamma);
660676
float logBoost =
661677
log2(metadata->min_content_boost) * (1.0f - gain) + log2(metadata->max_content_boost) * gain;
662-
float gainFactor = exp2(logBoost * displayBoost / metadata->max_content_boost);
678+
float gainFactor = exp2(logBoost * displayBoost / metadata->hdr_capacity_max);
663679
return e * gainFactor;
664680
}
665681

@@ -694,9 +710,9 @@ Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata, floa
694710
log2(metadata->max_content_boost) * gain.g;
695711
float logBoostB = log2(metadata->min_content_boost) * (1.0f - gain.b) +
696712
log2(metadata->max_content_boost) * gain.b;
697-
float gainFactorR = exp2(logBoostR * displayBoost / metadata->max_content_boost);
698-
float gainFactorG = exp2(logBoostG * displayBoost / metadata->max_content_boost);
699-
float gainFactorB = exp2(logBoostB * displayBoost / metadata->max_content_boost);
713+
float gainFactorR = exp2(logBoostR * displayBoost / metadata->hdr_capacity_max);
714+
float gainFactorG = exp2(logBoostG * displayBoost / metadata->hdr_capacity_max);
715+
float gainFactorB = exp2(logBoostB * displayBoost / metadata->hdr_capacity_max);
700716
return {{{e.r * gainFactorR, e.g * gainFactorG, e.b * gainFactorB}}};
701717
}
702718

0 commit comments

Comments
 (0)