1*89a0ef05SAndroid Build Coastguard Worker /*
2*89a0ef05SAndroid Build Coastguard Worker * Copyright 2023 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 #ifdef _WIN32
18*89a0ef05SAndroid Build Coastguard Worker #include <Windows.h>
19*89a0ef05SAndroid Build Coastguard Worker #else
20*89a0ef05SAndroid Build Coastguard Worker #include <sys/time.h>
21*89a0ef05SAndroid Build Coastguard Worker #endif
22*89a0ef05SAndroid Build Coastguard Worker
23*89a0ef05SAndroid Build Coastguard Worker #include <string.h>
24*89a0ef05SAndroid Build Coastguard Worker
25*89a0ef05SAndroid Build Coastguard Worker #include <algorithm>
26*89a0ef05SAndroid Build Coastguard Worker #include <cfloat>
27*89a0ef05SAndroid Build Coastguard Worker #include <cmath>
28*89a0ef05SAndroid Build Coastguard Worker #include <cstdint>
29*89a0ef05SAndroid Build Coastguard Worker #include <fstream>
30*89a0ef05SAndroid Build Coastguard Worker #include <iostream>
31*89a0ef05SAndroid Build Coastguard Worker #include <sstream>
32*89a0ef05SAndroid Build Coastguard Worker
33*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr_api.h"
34*89a0ef05SAndroid Build Coastguard Worker
35*89a0ef05SAndroid Build Coastguard Worker const float BT601YUVtoRGBMatrix[9] = {
36*89a0ef05SAndroid Build Coastguard Worker 1.f, 0.f, 1.402f, 1.f, (-0.202008f / 0.587f), (-0.419198f / 0.587f), 1.0f, 1.772f, 0.0f};
37*89a0ef05SAndroid Build Coastguard Worker const float BT709YUVtoRGBMatrix[9] = {
38*89a0ef05SAndroid Build Coastguard Worker 1.f, 0.f, 1.5748f, 1.f, (-0.13397432f / 0.7152f), (-0.33480248f / 0.7152f),
39*89a0ef05SAndroid Build Coastguard Worker 1.0f, 1.8556f, 0.0f};
40*89a0ef05SAndroid Build Coastguard Worker const float BT2020YUVtoRGBMatrix[9] = {
41*89a0ef05SAndroid Build Coastguard Worker 1.f, 0.f, 1.4746f, 1.f, (-0.11156702f / 0.6780f), (-0.38737742f / 0.6780f), 1.f, 1.8814f, 0.f};
42*89a0ef05SAndroid Build Coastguard Worker
43*89a0ef05SAndroid Build Coastguard Worker const float BT601RGBtoYUVMatrix[9] = {0.299f,
44*89a0ef05SAndroid Build Coastguard Worker 0.587f,
45*89a0ef05SAndroid Build Coastguard Worker 0.114f,
46*89a0ef05SAndroid Build Coastguard Worker (-0.299f / 1.772f),
47*89a0ef05SAndroid Build Coastguard Worker (-0.587f / 1.772f),
48*89a0ef05SAndroid Build Coastguard Worker 0.5f,
49*89a0ef05SAndroid Build Coastguard Worker 0.5f,
50*89a0ef05SAndroid Build Coastguard Worker (-0.587f / 1.402f),
51*89a0ef05SAndroid Build Coastguard Worker (-0.114f / 1.402f)};
52*89a0ef05SAndroid Build Coastguard Worker const float BT709RGBtoYUVMatrix[9] = {0.2126f,
53*89a0ef05SAndroid Build Coastguard Worker 0.7152f,
54*89a0ef05SAndroid Build Coastguard Worker 0.0722f,
55*89a0ef05SAndroid Build Coastguard Worker (-0.2126f / 1.8556f),
56*89a0ef05SAndroid Build Coastguard Worker (-0.7152f / 1.8556f),
57*89a0ef05SAndroid Build Coastguard Worker 0.5f,
58*89a0ef05SAndroid Build Coastguard Worker 0.5f,
59*89a0ef05SAndroid Build Coastguard Worker (-0.7152f / 1.5748f),
60*89a0ef05SAndroid Build Coastguard Worker (-0.0722f / 1.5748f)};
61*89a0ef05SAndroid Build Coastguard Worker const float BT2020RGBtoYUVMatrix[9] = {0.2627f,
62*89a0ef05SAndroid Build Coastguard Worker 0.6780f,
63*89a0ef05SAndroid Build Coastguard Worker 0.0593f,
64*89a0ef05SAndroid Build Coastguard Worker (-0.2627f / 1.8814f),
65*89a0ef05SAndroid Build Coastguard Worker (-0.6780f / 1.8814f),
66*89a0ef05SAndroid Build Coastguard Worker 0.5f,
67*89a0ef05SAndroid Build Coastguard Worker 0.5f,
68*89a0ef05SAndroid Build Coastguard Worker (-0.6780f / 1.4746f),
69*89a0ef05SAndroid Build Coastguard Worker (-0.0593f / 1.4746f)};
70*89a0ef05SAndroid Build Coastguard Worker
71*89a0ef05SAndroid Build Coastguard Worker // remove these once introduced in ultrahdr_api.h
72*89a0ef05SAndroid Build Coastguard Worker const int UHDR_IMG_FMT_48bppYCbCr444 = 101;
73*89a0ef05SAndroid Build Coastguard Worker
74*89a0ef05SAndroid Build Coastguard Worker int optind_s = 1;
75*89a0ef05SAndroid Build Coastguard Worker int optopt_s = 0;
76*89a0ef05SAndroid Build Coastguard Worker char* optarg_s = nullptr;
77*89a0ef05SAndroid Build Coastguard Worker
getopt_s(int argc,char * const argv[],char * ostr)78*89a0ef05SAndroid Build Coastguard Worker int getopt_s(int argc, char* const argv[], char* ostr) {
79*89a0ef05SAndroid Build Coastguard Worker if (optind_s >= argc) return -1;
80*89a0ef05SAndroid Build Coastguard Worker
81*89a0ef05SAndroid Build Coastguard Worker const char* arg = argv[optind_s];
82*89a0ef05SAndroid Build Coastguard Worker if (arg[0] != '-' || !arg[1]) {
83*89a0ef05SAndroid Build Coastguard Worker std::cerr << "invalid option " << arg << std::endl;
84*89a0ef05SAndroid Build Coastguard Worker return '?';
85*89a0ef05SAndroid Build Coastguard Worker }
86*89a0ef05SAndroid Build Coastguard Worker optopt_s = arg[1];
87*89a0ef05SAndroid Build Coastguard Worker char* oindex = strchr(ostr, optopt_s);
88*89a0ef05SAndroid Build Coastguard Worker if (!oindex) {
89*89a0ef05SAndroid Build Coastguard Worker std::cerr << "unsupported option " << arg << std::endl;
90*89a0ef05SAndroid Build Coastguard Worker return '?';
91*89a0ef05SAndroid Build Coastguard Worker }
92*89a0ef05SAndroid Build Coastguard Worker if (oindex[1] != ':') {
93*89a0ef05SAndroid Build Coastguard Worker optarg_s = nullptr;
94*89a0ef05SAndroid Build Coastguard Worker return optopt_s;
95*89a0ef05SAndroid Build Coastguard Worker }
96*89a0ef05SAndroid Build Coastguard Worker
97*89a0ef05SAndroid Build Coastguard Worker if (argc > ++optind_s) {
98*89a0ef05SAndroid Build Coastguard Worker optarg_s = (char*)argv[optind_s++];
99*89a0ef05SAndroid Build Coastguard Worker } else {
100*89a0ef05SAndroid Build Coastguard Worker std::cerr << "option " << arg << " requires an argument" << std::endl;
101*89a0ef05SAndroid Build Coastguard Worker optarg_s = nullptr;
102*89a0ef05SAndroid Build Coastguard Worker return '?';
103*89a0ef05SAndroid Build Coastguard Worker }
104*89a0ef05SAndroid Build Coastguard Worker return optopt_s;
105*89a0ef05SAndroid Build Coastguard Worker }
106*89a0ef05SAndroid Build Coastguard Worker
107*89a0ef05SAndroid Build Coastguard Worker // #define PROFILE_ENABLE 1
108*89a0ef05SAndroid Build Coastguard Worker #ifdef _WIN32
109*89a0ef05SAndroid Build Coastguard Worker class Profiler {
110*89a0ef05SAndroid Build Coastguard Worker public:
timerStart()111*89a0ef05SAndroid Build Coastguard Worker void timerStart() { QueryPerformanceCounter(&mStartingTime); }
112*89a0ef05SAndroid Build Coastguard Worker
timerStop()113*89a0ef05SAndroid Build Coastguard Worker void timerStop() { QueryPerformanceCounter(&mEndingTime); }
114*89a0ef05SAndroid Build Coastguard Worker
elapsedTime()115*89a0ef05SAndroid Build Coastguard Worker double elapsedTime() {
116*89a0ef05SAndroid Build Coastguard Worker LARGE_INTEGER frequency;
117*89a0ef05SAndroid Build Coastguard Worker LARGE_INTEGER elapsedMicroseconds;
118*89a0ef05SAndroid Build Coastguard Worker QueryPerformanceFrequency(&frequency);
119*89a0ef05SAndroid Build Coastguard Worker elapsedMicroseconds.QuadPart = mEndingTime.QuadPart - mStartingTime.QuadPart;
120*89a0ef05SAndroid Build Coastguard Worker return (double)elapsedMicroseconds.QuadPart / (double)frequency.QuadPart * 1000000;
121*89a0ef05SAndroid Build Coastguard Worker }
122*89a0ef05SAndroid Build Coastguard Worker
123*89a0ef05SAndroid Build Coastguard Worker private:
124*89a0ef05SAndroid Build Coastguard Worker LARGE_INTEGER mStartingTime;
125*89a0ef05SAndroid Build Coastguard Worker LARGE_INTEGER mEndingTime;
126*89a0ef05SAndroid Build Coastguard Worker };
127*89a0ef05SAndroid Build Coastguard Worker #else
128*89a0ef05SAndroid Build Coastguard Worker class Profiler {
129*89a0ef05SAndroid Build Coastguard Worker public:
timerStart()130*89a0ef05SAndroid Build Coastguard Worker void timerStart() { gettimeofday(&mStartingTime, nullptr); }
131*89a0ef05SAndroid Build Coastguard Worker
timerStop()132*89a0ef05SAndroid Build Coastguard Worker void timerStop() { gettimeofday(&mEndingTime, nullptr); }
133*89a0ef05SAndroid Build Coastguard Worker
elapsedTime()134*89a0ef05SAndroid Build Coastguard Worker int64_t elapsedTime() {
135*89a0ef05SAndroid Build Coastguard Worker struct timeval elapsedMicroseconds;
136*89a0ef05SAndroid Build Coastguard Worker elapsedMicroseconds.tv_sec = mEndingTime.tv_sec - mStartingTime.tv_sec;
137*89a0ef05SAndroid Build Coastguard Worker elapsedMicroseconds.tv_usec = mEndingTime.tv_usec - mStartingTime.tv_usec;
138*89a0ef05SAndroid Build Coastguard Worker return elapsedMicroseconds.tv_sec * 1000000 + elapsedMicroseconds.tv_usec;
139*89a0ef05SAndroid Build Coastguard Worker }
140*89a0ef05SAndroid Build Coastguard Worker
141*89a0ef05SAndroid Build Coastguard Worker private:
142*89a0ef05SAndroid Build Coastguard Worker struct timeval mStartingTime;
143*89a0ef05SAndroid Build Coastguard Worker struct timeval mEndingTime;
144*89a0ef05SAndroid Build Coastguard Worker };
145*89a0ef05SAndroid Build Coastguard Worker #endif
146*89a0ef05SAndroid Build Coastguard Worker
147*89a0ef05SAndroid Build Coastguard Worker #define READ_BYTES(DESC, ADDR, LEN) \
148*89a0ef05SAndroid Build Coastguard Worker DESC.read(static_cast<char*>(ADDR), (LEN)); \
149*89a0ef05SAndroid Build Coastguard Worker if (DESC.gcount() != (LEN)) { \
150*89a0ef05SAndroid Build Coastguard Worker std::cerr << "failed to read : " << (LEN) << " bytes, read : " << DESC.gcount() << " bytes" \
151*89a0ef05SAndroid Build Coastguard Worker << std::endl; \
152*89a0ef05SAndroid Build Coastguard Worker return false; \
153*89a0ef05SAndroid Build Coastguard Worker }
154*89a0ef05SAndroid Build Coastguard Worker
loadFile(const char * filename,void * & result,std::streamoff length)155*89a0ef05SAndroid Build Coastguard Worker static bool loadFile(const char* filename, void*& result, std::streamoff length) {
156*89a0ef05SAndroid Build Coastguard Worker if (length <= 0) {
157*89a0ef05SAndroid Build Coastguard Worker std::cerr << "requested to read invalid length : " << length
158*89a0ef05SAndroid Build Coastguard Worker << " bytes from file : " << filename << std::endl;
159*89a0ef05SAndroid Build Coastguard Worker return false;
160*89a0ef05SAndroid Build Coastguard Worker }
161*89a0ef05SAndroid Build Coastguard Worker std::ifstream ifd(filename, std::ios::binary | std::ios::ate);
162*89a0ef05SAndroid Build Coastguard Worker if (ifd.good()) {
163*89a0ef05SAndroid Build Coastguard Worker auto size = ifd.tellg();
164*89a0ef05SAndroid Build Coastguard Worker if (size < length) {
165*89a0ef05SAndroid Build Coastguard Worker std::cerr << "requested to read " << length << " bytes from file : " << filename
166*89a0ef05SAndroid Build Coastguard Worker << ", file contains only " << size << " bytes" << std::endl;
167*89a0ef05SAndroid Build Coastguard Worker return false;
168*89a0ef05SAndroid Build Coastguard Worker }
169*89a0ef05SAndroid Build Coastguard Worker ifd.seekg(0, std::ios::beg);
170*89a0ef05SAndroid Build Coastguard Worker result = malloc(length);
171*89a0ef05SAndroid Build Coastguard Worker if (result == nullptr) {
172*89a0ef05SAndroid Build Coastguard Worker std::cerr << "failed to allocate memory to store contents of file : " << filename
173*89a0ef05SAndroid Build Coastguard Worker << std::endl;
174*89a0ef05SAndroid Build Coastguard Worker return false;
175*89a0ef05SAndroid Build Coastguard Worker }
176*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, result, length)
177*89a0ef05SAndroid Build Coastguard Worker return true;
178*89a0ef05SAndroid Build Coastguard Worker }
179*89a0ef05SAndroid Build Coastguard Worker std::cerr << "unable to open file : " << filename << std::endl;
180*89a0ef05SAndroid Build Coastguard Worker return false;
181*89a0ef05SAndroid Build Coastguard Worker }
182*89a0ef05SAndroid Build Coastguard Worker
loadFile(const char * filename,uhdr_raw_image_t * handle)183*89a0ef05SAndroid Build Coastguard Worker static bool loadFile(const char* filename, uhdr_raw_image_t* handle) {
184*89a0ef05SAndroid Build Coastguard Worker std::ifstream ifd(filename, std::ios::binary);
185*89a0ef05SAndroid Build Coastguard Worker if (ifd.good()) {
186*89a0ef05SAndroid Build Coastguard Worker if (handle->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
187*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = 2;
188*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, handle->planes[UHDR_PLANE_Y], bpp * handle->w * handle->h)
189*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, handle->planes[UHDR_PLANE_UV], bpp * (handle->w / 2) * (handle->h / 2) * 2)
190*89a0ef05SAndroid Build Coastguard Worker return true;
191*89a0ef05SAndroid Build Coastguard Worker } else if (handle->fmt == UHDR_IMG_FMT_32bppRGBA1010102 ||
192*89a0ef05SAndroid Build Coastguard Worker handle->fmt == UHDR_IMG_FMT_32bppRGBA8888) {
193*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = 4;
194*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, handle->planes[UHDR_PLANE_PACKED], bpp * handle->w * handle->h)
195*89a0ef05SAndroid Build Coastguard Worker return true;
196*89a0ef05SAndroid Build Coastguard Worker } else if (handle->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
197*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = 8;
198*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, handle->planes[UHDR_PLANE_PACKED], bpp * handle->w * handle->h)
199*89a0ef05SAndroid Build Coastguard Worker return true;
200*89a0ef05SAndroid Build Coastguard Worker } else if (handle->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
201*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, handle->planes[UHDR_PLANE_Y], (size_t)handle->w * handle->h)
202*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, handle->planes[UHDR_PLANE_U], (size_t)(handle->w / 2) * (handle->h / 2))
203*89a0ef05SAndroid Build Coastguard Worker READ_BYTES(ifd, handle->planes[UHDR_PLANE_V], (size_t)(handle->w / 2) * (handle->h / 2))
204*89a0ef05SAndroid Build Coastguard Worker return true;
205*89a0ef05SAndroid Build Coastguard Worker }
206*89a0ef05SAndroid Build Coastguard Worker return false;
207*89a0ef05SAndroid Build Coastguard Worker }
208*89a0ef05SAndroid Build Coastguard Worker std::cerr << "unable to open file : " << filename << std::endl;
209*89a0ef05SAndroid Build Coastguard Worker return false;
210*89a0ef05SAndroid Build Coastguard Worker }
211*89a0ef05SAndroid Build Coastguard Worker
writeFile(const char * filename,void * & result,size_t length)212*89a0ef05SAndroid Build Coastguard Worker static bool writeFile(const char* filename, void*& result, size_t length) {
213*89a0ef05SAndroid Build Coastguard Worker std::ofstream ofd(filename, std::ios::binary);
214*89a0ef05SAndroid Build Coastguard Worker if (ofd.is_open()) {
215*89a0ef05SAndroid Build Coastguard Worker ofd.write(static_cast<char*>(result), length);
216*89a0ef05SAndroid Build Coastguard Worker return true;
217*89a0ef05SAndroid Build Coastguard Worker }
218*89a0ef05SAndroid Build Coastguard Worker std::cerr << "unable to write to file : " << filename << std::endl;
219*89a0ef05SAndroid Build Coastguard Worker return false;
220*89a0ef05SAndroid Build Coastguard Worker }
221*89a0ef05SAndroid Build Coastguard Worker
writeFile(const char * filename,uhdr_raw_image_t * img)222*89a0ef05SAndroid Build Coastguard Worker static bool writeFile(const char* filename, uhdr_raw_image_t* img) {
223*89a0ef05SAndroid Build Coastguard Worker std::ofstream ofd(filename, std::ios::binary);
224*89a0ef05SAndroid Build Coastguard Worker if (ofd.is_open()) {
225*89a0ef05SAndroid Build Coastguard Worker if (img->fmt == UHDR_IMG_FMT_32bppRGBA8888 || img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ||
226*89a0ef05SAndroid Build Coastguard Worker img->fmt == UHDR_IMG_FMT_32bppRGBA1010102) {
227*89a0ef05SAndroid Build Coastguard Worker char* data = static_cast<char*>(img->planes[UHDR_PLANE_PACKED]);
228*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ? 8 : 4;
229*89a0ef05SAndroid Build Coastguard Worker const size_t stride = img->stride[UHDR_PLANE_PACKED] * bpp;
230*89a0ef05SAndroid Build Coastguard Worker const size_t length = img->w * bpp;
231*89a0ef05SAndroid Build Coastguard Worker for (unsigned i = 0; i < img->h; i++, data += stride) {
232*89a0ef05SAndroid Build Coastguard Worker ofd.write(data, length);
233*89a0ef05SAndroid Build Coastguard Worker }
234*89a0ef05SAndroid Build Coastguard Worker return true;
235*89a0ef05SAndroid Build Coastguard Worker } else if ((int)img->fmt == UHDR_IMG_FMT_24bppYCbCr444 ||
236*89a0ef05SAndroid Build Coastguard Worker (int)img->fmt == UHDR_IMG_FMT_48bppYCbCr444) {
237*89a0ef05SAndroid Build Coastguard Worker char* data = static_cast<char*>(img->planes[UHDR_PLANE_Y]);
238*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = (int)img->fmt == UHDR_IMG_FMT_48bppYCbCr444 ? 2 : 1;
239*89a0ef05SAndroid Build Coastguard Worker size_t stride = img->stride[UHDR_PLANE_Y] * bpp;
240*89a0ef05SAndroid Build Coastguard Worker size_t length = img->w * bpp;
241*89a0ef05SAndroid Build Coastguard Worker for (unsigned i = 0; i < img->h; i++, data += stride) {
242*89a0ef05SAndroid Build Coastguard Worker ofd.write(data, length);
243*89a0ef05SAndroid Build Coastguard Worker }
244*89a0ef05SAndroid Build Coastguard Worker data = static_cast<char*>(img->planes[UHDR_PLANE_U]);
245*89a0ef05SAndroid Build Coastguard Worker stride = img->stride[UHDR_PLANE_U] * bpp;
246*89a0ef05SAndroid Build Coastguard Worker for (unsigned i = 0; i < img->h; i++, data += stride) {
247*89a0ef05SAndroid Build Coastguard Worker ofd.write(data, length);
248*89a0ef05SAndroid Build Coastguard Worker }
249*89a0ef05SAndroid Build Coastguard Worker data = static_cast<char*>(img->planes[UHDR_PLANE_V]);
250*89a0ef05SAndroid Build Coastguard Worker stride = img->stride[UHDR_PLANE_V] * bpp;
251*89a0ef05SAndroid Build Coastguard Worker for (unsigned i = 0; i < img->h; i++, data += stride) {
252*89a0ef05SAndroid Build Coastguard Worker ofd.write(data, length);
253*89a0ef05SAndroid Build Coastguard Worker }
254*89a0ef05SAndroid Build Coastguard Worker return true;
255*89a0ef05SAndroid Build Coastguard Worker }
256*89a0ef05SAndroid Build Coastguard Worker return false;
257*89a0ef05SAndroid Build Coastguard Worker }
258*89a0ef05SAndroid Build Coastguard Worker std::cerr << "unable to write to file : " << filename << std::endl;
259*89a0ef05SAndroid Build Coastguard Worker return false;
260*89a0ef05SAndroid Build Coastguard Worker }
261*89a0ef05SAndroid Build Coastguard Worker
262*89a0ef05SAndroid Build Coastguard Worker class UltraHdrAppInput {
263*89a0ef05SAndroid Build Coastguard Worker public:
UltraHdrAppInput(const char * hdrIntentRawFile,const char * sdrIntentRawFile,const char * sdrIntentCompressedFile,const char * gainmapCompressedFile,const char * gainmapMetadataCfgFile,const char * exifFile,const char * outputFile,int width,int height,uhdr_img_fmt_t hdrCf=UHDR_IMG_FMT_32bppRGBA1010102,uhdr_img_fmt_t sdrCf=UHDR_IMG_FMT_32bppRGBA8888,uhdr_color_gamut_t hdrCg=UHDR_CG_DISPLAY_P3,uhdr_color_gamut_t sdrCg=UHDR_CG_BT_709,uhdr_color_transfer_t hdrTf=UHDR_CT_HLG,int quality=95,uhdr_color_transfer_t oTf=UHDR_CT_HLG,uhdr_img_fmt_t oFmt=UHDR_IMG_FMT_32bppRGBA1010102,bool isHdrCrFull=false,int gainmapScaleFactor=1,int gainmapQuality=95,bool enableMultiChannelGainMap=true,float gamma=1.0f,bool enableGLES=false,uhdr_enc_preset_t encPreset=UHDR_USAGE_BEST_QUALITY,float minContentBoost=FLT_MIN,float maxContentBoost=FLT_MAX,float targetDispPeakBrightness=-1.0f)264*89a0ef05SAndroid Build Coastguard Worker UltraHdrAppInput(const char* hdrIntentRawFile, const char* sdrIntentRawFile,
265*89a0ef05SAndroid Build Coastguard Worker const char* sdrIntentCompressedFile, const char* gainmapCompressedFile,
266*89a0ef05SAndroid Build Coastguard Worker const char* gainmapMetadataCfgFile, const char* exifFile, const char* outputFile,
267*89a0ef05SAndroid Build Coastguard Worker int width, int height, uhdr_img_fmt_t hdrCf = UHDR_IMG_FMT_32bppRGBA1010102,
268*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t sdrCf = UHDR_IMG_FMT_32bppRGBA8888,
269*89a0ef05SAndroid Build Coastguard Worker uhdr_color_gamut_t hdrCg = UHDR_CG_DISPLAY_P3,
270*89a0ef05SAndroid Build Coastguard Worker uhdr_color_gamut_t sdrCg = UHDR_CG_BT_709,
271*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t hdrTf = UHDR_CT_HLG, int quality = 95,
272*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t oTf = UHDR_CT_HLG,
273*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102, bool isHdrCrFull = false,
274*89a0ef05SAndroid Build Coastguard Worker int gainmapScaleFactor = 1, int gainmapQuality = 95,
275*89a0ef05SAndroid Build Coastguard Worker bool enableMultiChannelGainMap = true, float gamma = 1.0f,
276*89a0ef05SAndroid Build Coastguard Worker bool enableGLES = false, uhdr_enc_preset_t encPreset = UHDR_USAGE_BEST_QUALITY,
277*89a0ef05SAndroid Build Coastguard Worker float minContentBoost = FLT_MIN, float maxContentBoost = FLT_MAX,
278*89a0ef05SAndroid Build Coastguard Worker float targetDispPeakBrightness = -1.0f)
279*89a0ef05SAndroid Build Coastguard Worker : mHdrIntentRawFile(hdrIntentRawFile),
280*89a0ef05SAndroid Build Coastguard Worker mSdrIntentRawFile(sdrIntentRawFile),
281*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedFile(sdrIntentCompressedFile),
282*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedFile(gainmapCompressedFile),
283*89a0ef05SAndroid Build Coastguard Worker mGainMapMetadataCfgFile(gainmapMetadataCfgFile),
284*89a0ef05SAndroid Build Coastguard Worker mExifFile(exifFile),
285*89a0ef05SAndroid Build Coastguard Worker mUhdrFile(nullptr),
286*89a0ef05SAndroid Build Coastguard Worker mOutputFile(outputFile),
287*89a0ef05SAndroid Build Coastguard Worker mWidth(width),
288*89a0ef05SAndroid Build Coastguard Worker mHeight(height),
289*89a0ef05SAndroid Build Coastguard Worker mHdrCf(hdrCf),
290*89a0ef05SAndroid Build Coastguard Worker mSdrCf(sdrCf),
291*89a0ef05SAndroid Build Coastguard Worker mHdrCg(hdrCg),
292*89a0ef05SAndroid Build Coastguard Worker mSdrCg(sdrCg),
293*89a0ef05SAndroid Build Coastguard Worker mHdrTf(hdrTf),
294*89a0ef05SAndroid Build Coastguard Worker mQuality(quality),
295*89a0ef05SAndroid Build Coastguard Worker mOTf(oTf),
296*89a0ef05SAndroid Build Coastguard Worker mOfmt(oFmt),
297*89a0ef05SAndroid Build Coastguard Worker mFullRange(isHdrCrFull),
298*89a0ef05SAndroid Build Coastguard Worker mMapDimensionScaleFactor(gainmapScaleFactor),
299*89a0ef05SAndroid Build Coastguard Worker mMapCompressQuality(gainmapQuality),
300*89a0ef05SAndroid Build Coastguard Worker mUseMultiChannelGainMap(enableMultiChannelGainMap),
301*89a0ef05SAndroid Build Coastguard Worker mGamma(gamma),
302*89a0ef05SAndroid Build Coastguard Worker mEnableGLES(enableGLES),
303*89a0ef05SAndroid Build Coastguard Worker mEncPreset(encPreset),
304*89a0ef05SAndroid Build Coastguard Worker mMinContentBoost(minContentBoost),
305*89a0ef05SAndroid Build Coastguard Worker mMaxContentBoost(maxContentBoost),
306*89a0ef05SAndroid Build Coastguard Worker mTargetDispPeakBrightness(targetDispPeakBrightness),
307*89a0ef05SAndroid Build Coastguard Worker mMode(0){};
308*89a0ef05SAndroid Build Coastguard Worker
UltraHdrAppInput(const char * gainmapMetadataCfgFile,const char * uhdrFile,const char * outputFile,uhdr_color_transfer_t oTf=UHDR_CT_HLG,uhdr_img_fmt_t oFmt=UHDR_IMG_FMT_32bppRGBA1010102,bool enableGLES=false)309*89a0ef05SAndroid Build Coastguard Worker UltraHdrAppInput(const char* gainmapMetadataCfgFile, const char* uhdrFile, const char* outputFile,
310*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t oTf = UHDR_CT_HLG,
311*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102, bool enableGLES = false)
312*89a0ef05SAndroid Build Coastguard Worker : mHdrIntentRawFile(nullptr),
313*89a0ef05SAndroid Build Coastguard Worker mSdrIntentRawFile(nullptr),
314*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedFile(nullptr),
315*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedFile(nullptr),
316*89a0ef05SAndroid Build Coastguard Worker mGainMapMetadataCfgFile(gainmapMetadataCfgFile),
317*89a0ef05SAndroid Build Coastguard Worker mExifFile(nullptr),
318*89a0ef05SAndroid Build Coastguard Worker mUhdrFile(uhdrFile),
319*89a0ef05SAndroid Build Coastguard Worker mOutputFile(outputFile),
320*89a0ef05SAndroid Build Coastguard Worker mWidth(0),
321*89a0ef05SAndroid Build Coastguard Worker mHeight(0),
322*89a0ef05SAndroid Build Coastguard Worker mHdrCf(UHDR_IMG_FMT_UNSPECIFIED),
323*89a0ef05SAndroid Build Coastguard Worker mSdrCf(UHDR_IMG_FMT_UNSPECIFIED),
324*89a0ef05SAndroid Build Coastguard Worker mHdrCg(UHDR_CG_UNSPECIFIED),
325*89a0ef05SAndroid Build Coastguard Worker mSdrCg(UHDR_CG_UNSPECIFIED),
326*89a0ef05SAndroid Build Coastguard Worker mHdrTf(UHDR_CT_UNSPECIFIED),
327*89a0ef05SAndroid Build Coastguard Worker mQuality(95),
328*89a0ef05SAndroid Build Coastguard Worker mOTf(oTf),
329*89a0ef05SAndroid Build Coastguard Worker mOfmt(oFmt),
330*89a0ef05SAndroid Build Coastguard Worker mFullRange(false),
331*89a0ef05SAndroid Build Coastguard Worker mMapDimensionScaleFactor(1),
332*89a0ef05SAndroid Build Coastguard Worker mMapCompressQuality(95),
333*89a0ef05SAndroid Build Coastguard Worker mUseMultiChannelGainMap(true),
334*89a0ef05SAndroid Build Coastguard Worker mGamma(1.0f),
335*89a0ef05SAndroid Build Coastguard Worker mEnableGLES(enableGLES),
336*89a0ef05SAndroid Build Coastguard Worker mEncPreset(UHDR_USAGE_BEST_QUALITY),
337*89a0ef05SAndroid Build Coastguard Worker mMinContentBoost(FLT_MIN),
338*89a0ef05SAndroid Build Coastguard Worker mMaxContentBoost(FLT_MAX),
339*89a0ef05SAndroid Build Coastguard Worker mTargetDispPeakBrightness(-1.0f),
340*89a0ef05SAndroid Build Coastguard Worker mMode(1){};
341*89a0ef05SAndroid Build Coastguard Worker
~UltraHdrAppInput()342*89a0ef05SAndroid Build Coastguard Worker ~UltraHdrAppInput() {
343*89a0ef05SAndroid Build Coastguard Worker int count = sizeof mRawP010Image.planes / sizeof mRawP010Image.planes[UHDR_PLANE_Y];
344*89a0ef05SAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
345*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.planes[i]) {
346*89a0ef05SAndroid Build Coastguard Worker free(mRawP010Image.planes[i]);
347*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.planes[i] = nullptr;
348*89a0ef05SAndroid Build Coastguard Worker }
349*89a0ef05SAndroid Build Coastguard Worker if (mRawRgba1010102Image.planes[i]) {
350*89a0ef05SAndroid Build Coastguard Worker free(mRawRgba1010102Image.planes[i]);
351*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.planes[i] = nullptr;
352*89a0ef05SAndroid Build Coastguard Worker }
353*89a0ef05SAndroid Build Coastguard Worker if (mRawRgbaF16Image.planes[i]) {
354*89a0ef05SAndroid Build Coastguard Worker free(mRawRgbaF16Image.planes[i]);
355*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.planes[i] = nullptr;
356*89a0ef05SAndroid Build Coastguard Worker }
357*89a0ef05SAndroid Build Coastguard Worker if (mRawYuv420Image.planes[i]) {
358*89a0ef05SAndroid Build Coastguard Worker free(mRawYuv420Image.planes[i]);
359*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.planes[i] = nullptr;
360*89a0ef05SAndroid Build Coastguard Worker }
361*89a0ef05SAndroid Build Coastguard Worker if (mRawRgba8888Image.planes[i]) {
362*89a0ef05SAndroid Build Coastguard Worker free(mRawRgba8888Image.planes[i]);
363*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.planes[i] = nullptr;
364*89a0ef05SAndroid Build Coastguard Worker }
365*89a0ef05SAndroid Build Coastguard Worker if (mDecodedUhdrRgbImage.planes[i]) {
366*89a0ef05SAndroid Build Coastguard Worker free(mDecodedUhdrRgbImage.planes[i]);
367*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.planes[i] = nullptr;
368*89a0ef05SAndroid Build Coastguard Worker }
369*89a0ef05SAndroid Build Coastguard Worker if (mDecodedUhdrYuv444Image.planes[i]) {
370*89a0ef05SAndroid Build Coastguard Worker free(mDecodedUhdrYuv444Image.planes[i]);
371*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.planes[i] = nullptr;
372*89a0ef05SAndroid Build Coastguard Worker }
373*89a0ef05SAndroid Build Coastguard Worker }
374*89a0ef05SAndroid Build Coastguard Worker if (mExifBlock.data) free(mExifBlock.data);
375*89a0ef05SAndroid Build Coastguard Worker if (mUhdrImage.data) free(mUhdrImage.data);
376*89a0ef05SAndroid Build Coastguard Worker }
377*89a0ef05SAndroid Build Coastguard Worker
378*89a0ef05SAndroid Build Coastguard Worker bool fillUhdrImageHandle();
379*89a0ef05SAndroid Build Coastguard Worker bool fillP010ImageHandle();
380*89a0ef05SAndroid Build Coastguard Worker bool fillRGBA1010102ImageHandle();
381*89a0ef05SAndroid Build Coastguard Worker bool fillRGBAF16ImageHandle();
382*89a0ef05SAndroid Build Coastguard Worker bool convertP010ToRGBImage();
383*89a0ef05SAndroid Build Coastguard Worker bool fillYuv420ImageHandle();
384*89a0ef05SAndroid Build Coastguard Worker bool fillRGBA8888ImageHandle();
385*89a0ef05SAndroid Build Coastguard Worker bool convertYuv420ToRGBImage();
386*89a0ef05SAndroid Build Coastguard Worker bool fillSdrCompressedImageHandle();
387*89a0ef05SAndroid Build Coastguard Worker bool fillGainMapCompressedImageHandle();
388*89a0ef05SAndroid Build Coastguard Worker bool fillGainMapMetadataDescriptor();
389*89a0ef05SAndroid Build Coastguard Worker bool fillExifMemoryBlock();
390*89a0ef05SAndroid Build Coastguard Worker bool writeGainMapMetadataToFile(uhdr_gainmap_metadata_t* metadata);
391*89a0ef05SAndroid Build Coastguard Worker bool convertRgba8888ToYUV444Image();
392*89a0ef05SAndroid Build Coastguard Worker bool convertRgba1010102ToYUV444Image();
393*89a0ef05SAndroid Build Coastguard Worker bool encode();
394*89a0ef05SAndroid Build Coastguard Worker bool decode();
395*89a0ef05SAndroid Build Coastguard Worker void computeRGBHdrPSNR();
396*89a0ef05SAndroid Build Coastguard Worker void computeRGBSdrPSNR();
397*89a0ef05SAndroid Build Coastguard Worker void computeYUVHdrPSNR();
398*89a0ef05SAndroid Build Coastguard Worker void computeYUVSdrPSNR();
399*89a0ef05SAndroid Build Coastguard Worker
400*89a0ef05SAndroid Build Coastguard Worker const char* mHdrIntentRawFile;
401*89a0ef05SAndroid Build Coastguard Worker const char* mSdrIntentRawFile;
402*89a0ef05SAndroid Build Coastguard Worker const char* mSdrIntentCompressedFile;
403*89a0ef05SAndroid Build Coastguard Worker const char* mGainMapCompressedFile;
404*89a0ef05SAndroid Build Coastguard Worker const char* mGainMapMetadataCfgFile;
405*89a0ef05SAndroid Build Coastguard Worker const char* mExifFile;
406*89a0ef05SAndroid Build Coastguard Worker const char* mUhdrFile;
407*89a0ef05SAndroid Build Coastguard Worker const char* mOutputFile;
408*89a0ef05SAndroid Build Coastguard Worker const int mWidth;
409*89a0ef05SAndroid Build Coastguard Worker const int mHeight;
410*89a0ef05SAndroid Build Coastguard Worker const uhdr_img_fmt_t mHdrCf;
411*89a0ef05SAndroid Build Coastguard Worker const uhdr_img_fmt_t mSdrCf;
412*89a0ef05SAndroid Build Coastguard Worker const uhdr_color_gamut_t mHdrCg;
413*89a0ef05SAndroid Build Coastguard Worker const uhdr_color_gamut_t mSdrCg;
414*89a0ef05SAndroid Build Coastguard Worker const uhdr_color_transfer_t mHdrTf;
415*89a0ef05SAndroid Build Coastguard Worker const int mQuality;
416*89a0ef05SAndroid Build Coastguard Worker const uhdr_color_transfer_t mOTf;
417*89a0ef05SAndroid Build Coastguard Worker const uhdr_img_fmt_t mOfmt;
418*89a0ef05SAndroid Build Coastguard Worker const bool mFullRange;
419*89a0ef05SAndroid Build Coastguard Worker const int mMapDimensionScaleFactor;
420*89a0ef05SAndroid Build Coastguard Worker const int mMapCompressQuality;
421*89a0ef05SAndroid Build Coastguard Worker const bool mUseMultiChannelGainMap;
422*89a0ef05SAndroid Build Coastguard Worker const float mGamma;
423*89a0ef05SAndroid Build Coastguard Worker const bool mEnableGLES;
424*89a0ef05SAndroid Build Coastguard Worker const uhdr_enc_preset_t mEncPreset;
425*89a0ef05SAndroid Build Coastguard Worker const float mMinContentBoost;
426*89a0ef05SAndroid Build Coastguard Worker const float mMaxContentBoost;
427*89a0ef05SAndroid Build Coastguard Worker const float mTargetDispPeakBrightness;
428*89a0ef05SAndroid Build Coastguard Worker const int mMode;
429*89a0ef05SAndroid Build Coastguard Worker
430*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t mRawP010Image{};
431*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t mRawRgba1010102Image{};
432*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t mRawRgbaF16Image{};
433*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t mRawYuv420Image{};
434*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t mRawRgba8888Image{};
435*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t mSdrIntentCompressedImage{};
436*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t mGainMapCompressedImage{};
437*89a0ef05SAndroid Build Coastguard Worker uhdr_gainmap_metadata mGainMapMetadata{};
438*89a0ef05SAndroid Build Coastguard Worker uhdr_mem_block_t mExifBlock{};
439*89a0ef05SAndroid Build Coastguard Worker uhdr_compressed_image_t mUhdrImage{};
440*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t mDecodedUhdrRgbImage{};
441*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t mDecodedUhdrYuv444Image{};
442*89a0ef05SAndroid Build Coastguard Worker double mPsnr[3]{};
443*89a0ef05SAndroid Build Coastguard Worker };
444*89a0ef05SAndroid Build Coastguard Worker
fillP010ImageHandle()445*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillP010ImageHandle() {
446*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = 2;
447*89a0ef05SAndroid Build Coastguard Worker size_t p010Size = bpp * mWidth * mHeight * 3 / 2;
448*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
449*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.cg = mHdrCg;
450*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.ct = mHdrTf;
451*89a0ef05SAndroid Build Coastguard Worker
452*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.range = mFullRange ? UHDR_CR_FULL_RANGE : UHDR_CR_LIMITED_RANGE;
453*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.w = mWidth;
454*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.h = mHeight;
455*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.planes[UHDR_PLANE_Y] = malloc(bpp * mWidth * mHeight);
456*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.planes[UHDR_PLANE_UV] = malloc(bpp * (mWidth / 2) * (mHeight / 2) * 2);
457*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.planes[UHDR_PLANE_V] = nullptr;
458*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.stride[UHDR_PLANE_Y] = mWidth;
459*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.stride[UHDR_PLANE_UV] = mWidth;
460*89a0ef05SAndroid Build Coastguard Worker mRawP010Image.stride[UHDR_PLANE_V] = 0;
461*89a0ef05SAndroid Build Coastguard Worker return loadFile(mHdrIntentRawFile, &mRawP010Image);
462*89a0ef05SAndroid Build Coastguard Worker }
463*89a0ef05SAndroid Build Coastguard Worker
fillYuv420ImageHandle()464*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillYuv420ImageHandle() {
465*89a0ef05SAndroid Build Coastguard Worker size_t yuv420Size = (size_t)mWidth * mHeight * 3 / 2;
466*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.fmt = UHDR_IMG_FMT_12bppYCbCr420;
467*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.cg = mSdrCg;
468*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.ct = UHDR_CT_SRGB;
469*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.range = UHDR_CR_FULL_RANGE;
470*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.w = mWidth;
471*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.h = mHeight;
472*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.planes[UHDR_PLANE_Y] = malloc((size_t)mWidth * mHeight);
473*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.planes[UHDR_PLANE_U] = malloc((size_t)(mWidth / 2) * (mHeight / 2));
474*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.planes[UHDR_PLANE_V] = malloc((size_t)(mWidth / 2) * (mHeight / 2));
475*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.stride[UHDR_PLANE_Y] = mWidth;
476*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.stride[UHDR_PLANE_U] = mWidth / 2;
477*89a0ef05SAndroid Build Coastguard Worker mRawYuv420Image.stride[UHDR_PLANE_V] = mWidth / 2;
478*89a0ef05SAndroid Build Coastguard Worker return loadFile(mSdrIntentRawFile, &mRawYuv420Image);
479*89a0ef05SAndroid Build Coastguard Worker }
480*89a0ef05SAndroid Build Coastguard Worker
fillRGBA1010102ImageHandle()481*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillRGBA1010102ImageHandle() {
482*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = 4;
483*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.fmt = UHDR_IMG_FMT_32bppRGBA1010102;
484*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.cg = mHdrCg;
485*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.ct = mHdrTf;
486*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.range = UHDR_CR_FULL_RANGE;
487*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.w = mWidth;
488*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.h = mHeight;
489*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.planes[UHDR_PLANE_PACKED] = malloc(bpp * mWidth * mHeight);
490*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.planes[UHDR_PLANE_UV] = nullptr;
491*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.planes[UHDR_PLANE_V] = nullptr;
492*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.stride[UHDR_PLANE_PACKED] = mWidth;
493*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.stride[UHDR_PLANE_UV] = 0;
494*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.stride[UHDR_PLANE_V] = 0;
495*89a0ef05SAndroid Build Coastguard Worker return loadFile(mHdrIntentRawFile, &mRawRgba1010102Image);
496*89a0ef05SAndroid Build Coastguard Worker }
497*89a0ef05SAndroid Build Coastguard Worker
fillRGBAF16ImageHandle()498*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillRGBAF16ImageHandle() {
499*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = 8;
500*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.fmt = UHDR_IMG_FMT_64bppRGBAHalfFloat;
501*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.cg = mHdrCg;
502*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.ct = mHdrTf;
503*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.range = UHDR_CR_FULL_RANGE;
504*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.w = mWidth;
505*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.h = mHeight;
506*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.planes[UHDR_PLANE_PACKED] = malloc(bpp * mWidth * mHeight);
507*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.planes[UHDR_PLANE_UV] = nullptr;
508*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.planes[UHDR_PLANE_V] = nullptr;
509*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.stride[UHDR_PLANE_PACKED] = mWidth;
510*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.stride[UHDR_PLANE_UV] = 0;
511*89a0ef05SAndroid Build Coastguard Worker mRawRgbaF16Image.stride[UHDR_PLANE_V] = 0;
512*89a0ef05SAndroid Build Coastguard Worker return loadFile(mHdrIntentRawFile, &mRawRgbaF16Image);
513*89a0ef05SAndroid Build Coastguard Worker }
514*89a0ef05SAndroid Build Coastguard Worker
fillRGBA8888ImageHandle()515*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillRGBA8888ImageHandle() {
516*89a0ef05SAndroid Build Coastguard Worker const size_t bpp = 4;
517*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.fmt = UHDR_IMG_FMT_32bppRGBA8888;
518*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.cg = mSdrCg;
519*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.ct = UHDR_CT_SRGB;
520*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.range = UHDR_CR_FULL_RANGE;
521*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.w = mWidth;
522*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.h = mHeight;
523*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.planes[UHDR_PLANE_PACKED] = malloc(bpp * mWidth * mHeight);
524*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.planes[UHDR_PLANE_U] = nullptr;
525*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.planes[UHDR_PLANE_V] = nullptr;
526*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.stride[UHDR_PLANE_Y] = mWidth;
527*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.stride[UHDR_PLANE_U] = 0;
528*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.stride[UHDR_PLANE_V] = 0;
529*89a0ef05SAndroid Build Coastguard Worker return loadFile(mSdrIntentRawFile, &mRawRgba8888Image);
530*89a0ef05SAndroid Build Coastguard Worker }
531*89a0ef05SAndroid Build Coastguard Worker
fillSdrCompressedImageHandle()532*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillSdrCompressedImageHandle() {
533*89a0ef05SAndroid Build Coastguard Worker std::ifstream ifd(mSdrIntentCompressedFile, std::ios::binary | std::ios::ate);
534*89a0ef05SAndroid Build Coastguard Worker if (ifd.good()) {
535*89a0ef05SAndroid Build Coastguard Worker auto size = ifd.tellg();
536*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedImage.capacity = size;
537*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedImage.data_sz = size;
538*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedImage.data = nullptr;
539*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedImage.cg = mSdrCg;
540*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedImage.ct = UHDR_CT_UNSPECIFIED;
541*89a0ef05SAndroid Build Coastguard Worker mSdrIntentCompressedImage.range = UHDR_CR_UNSPECIFIED;
542*89a0ef05SAndroid Build Coastguard Worker ifd.close();
543*89a0ef05SAndroid Build Coastguard Worker return loadFile(mSdrIntentCompressedFile, mSdrIntentCompressedImage.data, size);
544*89a0ef05SAndroid Build Coastguard Worker }
545*89a0ef05SAndroid Build Coastguard Worker return false;
546*89a0ef05SAndroid Build Coastguard Worker }
547*89a0ef05SAndroid Build Coastguard Worker
fillGainMapCompressedImageHandle()548*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillGainMapCompressedImageHandle() {
549*89a0ef05SAndroid Build Coastguard Worker std::ifstream ifd(mGainMapCompressedFile, std::ios::binary | std::ios::ate);
550*89a0ef05SAndroid Build Coastguard Worker if (ifd.good()) {
551*89a0ef05SAndroid Build Coastguard Worker auto size = ifd.tellg();
552*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedImage.capacity = size;
553*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedImage.data_sz = size;
554*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedImage.data = nullptr;
555*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedImage.cg = UHDR_CG_UNSPECIFIED;
556*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedImage.ct = UHDR_CT_UNSPECIFIED;
557*89a0ef05SAndroid Build Coastguard Worker mGainMapCompressedImage.range = UHDR_CR_UNSPECIFIED;
558*89a0ef05SAndroid Build Coastguard Worker ifd.close();
559*89a0ef05SAndroid Build Coastguard Worker return loadFile(mGainMapCompressedFile, mGainMapCompressedImage.data, size);
560*89a0ef05SAndroid Build Coastguard Worker }
561*89a0ef05SAndroid Build Coastguard Worker return false;
562*89a0ef05SAndroid Build Coastguard Worker }
563*89a0ef05SAndroid Build Coastguard Worker
parse_argument(uhdr_gainmap_metadata * metadata,char * argument,float * value)564*89a0ef05SAndroid Build Coastguard Worker void parse_argument(uhdr_gainmap_metadata* metadata, char* argument, float* value) {
565*89a0ef05SAndroid Build Coastguard Worker if (!strcmp(argument, "maxContentBoost"))
566*89a0ef05SAndroid Build Coastguard Worker metadata->max_content_boost = *value;
567*89a0ef05SAndroid Build Coastguard Worker else if (!strcmp(argument, "minContentBoost"))
568*89a0ef05SAndroid Build Coastguard Worker metadata->min_content_boost = *value;
569*89a0ef05SAndroid Build Coastguard Worker else if (!strcmp(argument, "gamma"))
570*89a0ef05SAndroid Build Coastguard Worker metadata->gamma = *value;
571*89a0ef05SAndroid Build Coastguard Worker else if (!strcmp(argument, "offsetSdr"))
572*89a0ef05SAndroid Build Coastguard Worker metadata->offset_sdr = *value;
573*89a0ef05SAndroid Build Coastguard Worker else if (!strcmp(argument, "offsetHdr"))
574*89a0ef05SAndroid Build Coastguard Worker metadata->offset_hdr = *value;
575*89a0ef05SAndroid Build Coastguard Worker else if (!strcmp(argument, "hdrCapacityMin"))
576*89a0ef05SAndroid Build Coastguard Worker metadata->hdr_capacity_min = *value;
577*89a0ef05SAndroid Build Coastguard Worker else if (!strcmp(argument, "hdrCapacityMax"))
578*89a0ef05SAndroid Build Coastguard Worker metadata->hdr_capacity_max = *value;
579*89a0ef05SAndroid Build Coastguard Worker else
580*89a0ef05SAndroid Build Coastguard Worker std::cout << " Ignoring argument " << argument << std::endl;
581*89a0ef05SAndroid Build Coastguard Worker }
582*89a0ef05SAndroid Build Coastguard Worker
fillGainMapMetadataDescriptor()583*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillGainMapMetadataDescriptor() {
584*89a0ef05SAndroid Build Coastguard Worker std::ifstream file(mGainMapMetadataCfgFile);
585*89a0ef05SAndroid Build Coastguard Worker if (!file.is_open()) {
586*89a0ef05SAndroid Build Coastguard Worker return false;
587*89a0ef05SAndroid Build Coastguard Worker }
588*89a0ef05SAndroid Build Coastguard Worker std::string line;
589*89a0ef05SAndroid Build Coastguard Worker char argument[128];
590*89a0ef05SAndroid Build Coastguard Worker float value;
591*89a0ef05SAndroid Build Coastguard Worker while (std::getline(file, line)) {
592*89a0ef05SAndroid Build Coastguard Worker if (sscanf(line.c_str(), "--%s %f", argument, &value) == 2) {
593*89a0ef05SAndroid Build Coastguard Worker parse_argument(&mGainMapMetadata, argument, &value);
594*89a0ef05SAndroid Build Coastguard Worker }
595*89a0ef05SAndroid Build Coastguard Worker }
596*89a0ef05SAndroid Build Coastguard Worker file.close();
597*89a0ef05SAndroid Build Coastguard Worker return true;
598*89a0ef05SAndroid Build Coastguard Worker }
599*89a0ef05SAndroid Build Coastguard Worker
fillExifMemoryBlock()600*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillExifMemoryBlock() {
601*89a0ef05SAndroid Build Coastguard Worker std::ifstream ifd(mExifFile, std::ios::binary | std::ios::ate);
602*89a0ef05SAndroid Build Coastguard Worker if (ifd.good()) {
603*89a0ef05SAndroid Build Coastguard Worker auto size = ifd.tellg();
604*89a0ef05SAndroid Build Coastguard Worker ifd.close();
605*89a0ef05SAndroid Build Coastguard Worker return loadFile(mExifFile, mExifBlock.data, size);
606*89a0ef05SAndroid Build Coastguard Worker }
607*89a0ef05SAndroid Build Coastguard Worker return false;
608*89a0ef05SAndroid Build Coastguard Worker }
609*89a0ef05SAndroid Build Coastguard Worker
writeGainMapMetadataToFile(uhdr_gainmap_metadata_t * metadata)610*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::writeGainMapMetadataToFile(uhdr_gainmap_metadata_t* metadata) {
611*89a0ef05SAndroid Build Coastguard Worker std::ofstream file(mGainMapMetadataCfgFile);
612*89a0ef05SAndroid Build Coastguard Worker if (!file.is_open()) {
613*89a0ef05SAndroid Build Coastguard Worker return false;
614*89a0ef05SAndroid Build Coastguard Worker }
615*89a0ef05SAndroid Build Coastguard Worker file << "--maxContentBoost " << metadata->max_content_boost << std::endl;
616*89a0ef05SAndroid Build Coastguard Worker file << "--minContentBoost " << metadata->min_content_boost << std::endl;
617*89a0ef05SAndroid Build Coastguard Worker file << "--gamma " << metadata->gamma << std::endl;
618*89a0ef05SAndroid Build Coastguard Worker file << "--offsetSdr " << metadata->offset_sdr << std::endl;
619*89a0ef05SAndroid Build Coastguard Worker file << "--offsetHdr " << metadata->offset_hdr << std::endl;
620*89a0ef05SAndroid Build Coastguard Worker file << "--hdrCapacityMin " << metadata->hdr_capacity_min << std::endl;
621*89a0ef05SAndroid Build Coastguard Worker file << "--hdrCapacityMax " << metadata->hdr_capacity_max << std::endl;
622*89a0ef05SAndroid Build Coastguard Worker file.close();
623*89a0ef05SAndroid Build Coastguard Worker return true;
624*89a0ef05SAndroid Build Coastguard Worker }
625*89a0ef05SAndroid Build Coastguard Worker
fillUhdrImageHandle()626*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::fillUhdrImageHandle() {
627*89a0ef05SAndroid Build Coastguard Worker std::ifstream ifd(mUhdrFile, std::ios::binary | std::ios::ate);
628*89a0ef05SAndroid Build Coastguard Worker if (ifd.good()) {
629*89a0ef05SAndroid Build Coastguard Worker auto size = ifd.tellg();
630*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.capacity = size;
631*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.data_sz = size;
632*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.data = nullptr;
633*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.cg = UHDR_CG_UNSPECIFIED;
634*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.ct = UHDR_CT_UNSPECIFIED;
635*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.range = UHDR_CR_UNSPECIFIED;
636*89a0ef05SAndroid Build Coastguard Worker ifd.close();
637*89a0ef05SAndroid Build Coastguard Worker return loadFile(mUhdrFile, mUhdrImage.data, size);
638*89a0ef05SAndroid Build Coastguard Worker }
639*89a0ef05SAndroid Build Coastguard Worker return false;
640*89a0ef05SAndroid Build Coastguard Worker }
641*89a0ef05SAndroid Build Coastguard Worker
encode()642*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::encode() {
643*89a0ef05SAndroid Build Coastguard Worker if (mHdrIntentRawFile != nullptr) {
644*89a0ef05SAndroid Build Coastguard Worker if (mHdrCf == UHDR_IMG_FMT_24bppYCbCrP010) {
645*89a0ef05SAndroid Build Coastguard Worker if (!fillP010ImageHandle()) {
646*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mHdrIntentRawFile << std::endl;
647*89a0ef05SAndroid Build Coastguard Worker return false;
648*89a0ef05SAndroid Build Coastguard Worker }
649*89a0ef05SAndroid Build Coastguard Worker } else if (mHdrCf == UHDR_IMG_FMT_32bppRGBA1010102) {
650*89a0ef05SAndroid Build Coastguard Worker if (!fillRGBA1010102ImageHandle()) {
651*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mHdrIntentRawFile << std::endl;
652*89a0ef05SAndroid Build Coastguard Worker return false;
653*89a0ef05SAndroid Build Coastguard Worker }
654*89a0ef05SAndroid Build Coastguard Worker } else if (mHdrCf == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
655*89a0ef05SAndroid Build Coastguard Worker if (!fillRGBAF16ImageHandle()) {
656*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mHdrIntentRawFile << std::endl;
657*89a0ef05SAndroid Build Coastguard Worker return false;
658*89a0ef05SAndroid Build Coastguard Worker }
659*89a0ef05SAndroid Build Coastguard Worker } else {
660*89a0ef05SAndroid Build Coastguard Worker std::cerr << " invalid hdr intent color format " << mHdrCf << std::endl;
661*89a0ef05SAndroid Build Coastguard Worker return false;
662*89a0ef05SAndroid Build Coastguard Worker }
663*89a0ef05SAndroid Build Coastguard Worker }
664*89a0ef05SAndroid Build Coastguard Worker if (mSdrIntentRawFile != nullptr) {
665*89a0ef05SAndroid Build Coastguard Worker if (mSdrCf == UHDR_IMG_FMT_12bppYCbCr420) {
666*89a0ef05SAndroid Build Coastguard Worker if (!fillYuv420ImageHandle()) {
667*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mSdrIntentRawFile << std::endl;
668*89a0ef05SAndroid Build Coastguard Worker return false;
669*89a0ef05SAndroid Build Coastguard Worker }
670*89a0ef05SAndroid Build Coastguard Worker } else if (mSdrCf == UHDR_IMG_FMT_32bppRGBA8888) {
671*89a0ef05SAndroid Build Coastguard Worker if (!fillRGBA8888ImageHandle()) {
672*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mSdrIntentRawFile << std::endl;
673*89a0ef05SAndroid Build Coastguard Worker return false;
674*89a0ef05SAndroid Build Coastguard Worker }
675*89a0ef05SAndroid Build Coastguard Worker } else {
676*89a0ef05SAndroid Build Coastguard Worker std::cerr << " invalid sdr intent color format " << mSdrCf << std::endl;
677*89a0ef05SAndroid Build Coastguard Worker return false;
678*89a0ef05SAndroid Build Coastguard Worker }
679*89a0ef05SAndroid Build Coastguard Worker }
680*89a0ef05SAndroid Build Coastguard Worker if (mSdrIntentCompressedFile != nullptr) {
681*89a0ef05SAndroid Build Coastguard Worker if (!fillSdrCompressedImageHandle()) {
682*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mSdrIntentCompressedFile << std::endl;
683*89a0ef05SAndroid Build Coastguard Worker return false;
684*89a0ef05SAndroid Build Coastguard Worker }
685*89a0ef05SAndroid Build Coastguard Worker }
686*89a0ef05SAndroid Build Coastguard Worker if (mGainMapCompressedFile != nullptr && mGainMapMetadataCfgFile != nullptr) {
687*89a0ef05SAndroid Build Coastguard Worker if (!fillGainMapCompressedImageHandle()) {
688*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mGainMapCompressedFile << std::endl;
689*89a0ef05SAndroid Build Coastguard Worker return false;
690*89a0ef05SAndroid Build Coastguard Worker }
691*89a0ef05SAndroid Build Coastguard Worker if (!fillGainMapMetadataDescriptor()) {
692*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to read config file " << mGainMapMetadataCfgFile << std::endl;
693*89a0ef05SAndroid Build Coastguard Worker return false;
694*89a0ef05SAndroid Build Coastguard Worker }
695*89a0ef05SAndroid Build Coastguard Worker }
696*89a0ef05SAndroid Build Coastguard Worker if (mExifFile != nullptr) {
697*89a0ef05SAndroid Build Coastguard Worker if (!fillExifMemoryBlock()) {
698*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mExifFile << std::endl;
699*89a0ef05SAndroid Build Coastguard Worker return false;
700*89a0ef05SAndroid Build Coastguard Worker }
701*89a0ef05SAndroid Build Coastguard Worker }
702*89a0ef05SAndroid Build Coastguard Worker
703*89a0ef05SAndroid Build Coastguard Worker #define RET_IF_ERR(x) \
704*89a0ef05SAndroid Build Coastguard Worker { \
705*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = (x); \
706*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) { \
707*89a0ef05SAndroid Build Coastguard Worker if (status.has_detail) { \
708*89a0ef05SAndroid Build Coastguard Worker std::cerr << status.detail << std::endl; \
709*89a0ef05SAndroid Build Coastguard Worker } \
710*89a0ef05SAndroid Build Coastguard Worker uhdr_release_encoder(handle); \
711*89a0ef05SAndroid Build Coastguard Worker return false; \
712*89a0ef05SAndroid Build Coastguard Worker } \
713*89a0ef05SAndroid Build Coastguard Worker }
714*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private_t* handle = uhdr_create_encoder();
715*89a0ef05SAndroid Build Coastguard Worker if (mHdrIntentRawFile != nullptr) {
716*89a0ef05SAndroid Build Coastguard Worker if (mHdrCf == UHDR_IMG_FMT_24bppYCbCrP010) {
717*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_raw_image(handle, &mRawP010Image, UHDR_HDR_IMG))
718*89a0ef05SAndroid Build Coastguard Worker } else if (mHdrCf == UHDR_IMG_FMT_32bppRGBA1010102) {
719*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_raw_image(handle, &mRawRgba1010102Image, UHDR_HDR_IMG))
720*89a0ef05SAndroid Build Coastguard Worker } else if (mHdrCf == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
721*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_raw_image(handle, &mRawRgbaF16Image, UHDR_HDR_IMG))
722*89a0ef05SAndroid Build Coastguard Worker }
723*89a0ef05SAndroid Build Coastguard Worker }
724*89a0ef05SAndroid Build Coastguard Worker if (mSdrIntentRawFile != nullptr) {
725*89a0ef05SAndroid Build Coastguard Worker if (mSdrCf == UHDR_IMG_FMT_12bppYCbCr420) {
726*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_raw_image(handle, &mRawYuv420Image, UHDR_SDR_IMG))
727*89a0ef05SAndroid Build Coastguard Worker } else if (mSdrCf == UHDR_IMG_FMT_32bppRGBA8888) {
728*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_raw_image(handle, &mRawRgba8888Image, UHDR_SDR_IMG))
729*89a0ef05SAndroid Build Coastguard Worker }
730*89a0ef05SAndroid Build Coastguard Worker }
731*89a0ef05SAndroid Build Coastguard Worker if (mSdrIntentCompressedFile != nullptr) {
732*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_compressed_image(
733*89a0ef05SAndroid Build Coastguard Worker handle, &mSdrIntentCompressedImage,
734*89a0ef05SAndroid Build Coastguard Worker (mGainMapCompressedFile != nullptr && mGainMapMetadataCfgFile != nullptr) ? UHDR_BASE_IMG
735*89a0ef05SAndroid Build Coastguard Worker : UHDR_SDR_IMG))
736*89a0ef05SAndroid Build Coastguard Worker }
737*89a0ef05SAndroid Build Coastguard Worker if (mGainMapCompressedFile != nullptr && mGainMapMetadataCfgFile != nullptr) {
738*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_gainmap_image(handle, &mGainMapCompressedImage, &mGainMapMetadata))
739*89a0ef05SAndroid Build Coastguard Worker }
740*89a0ef05SAndroid Build Coastguard Worker if (mExifFile != nullptr) {
741*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_exif_data(handle, &mExifBlock))
742*89a0ef05SAndroid Build Coastguard Worker }
743*89a0ef05SAndroid Build Coastguard Worker
744*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_quality(handle, mQuality, UHDR_BASE_IMG))
745*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_quality(handle, mMapCompressQuality, UHDR_GAIN_MAP_IMG))
746*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_using_multi_channel_gainmap(handle, mUseMultiChannelGainMap))
747*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_gainmap_scale_factor(handle, mMapDimensionScaleFactor))
748*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_gainmap_gamma(handle, mGamma))
749*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_preset(handle, mEncPreset))
750*89a0ef05SAndroid Build Coastguard Worker if (mMinContentBoost != FLT_MIN || mMaxContentBoost != FLT_MAX) {
751*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_min_max_content_boost(handle, mMinContentBoost, mMaxContentBoost))
752*89a0ef05SAndroid Build Coastguard Worker }
753*89a0ef05SAndroid Build Coastguard Worker if (mTargetDispPeakBrightness != -1.0f) {
754*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enc_set_target_display_peak_brightness(handle, mTargetDispPeakBrightness))
755*89a0ef05SAndroid Build Coastguard Worker }
756*89a0ef05SAndroid Build Coastguard Worker if (mEnableGLES) {
757*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enable_gpu_acceleration(handle, mEnableGLES))
758*89a0ef05SAndroid Build Coastguard Worker }
759*89a0ef05SAndroid Build Coastguard Worker #ifdef PROFILE_ENABLE
760*89a0ef05SAndroid Build Coastguard Worker Profiler profileEncode;
761*89a0ef05SAndroid Build Coastguard Worker profileEncode.timerStart();
762*89a0ef05SAndroid Build Coastguard Worker #endif
763*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_encode(handle))
764*89a0ef05SAndroid Build Coastguard Worker #ifdef PROFILE_ENABLE
765*89a0ef05SAndroid Build Coastguard Worker profileEncode.timerStop();
766*89a0ef05SAndroid Build Coastguard Worker auto avgEncTime = profileEncode.elapsedTime() / 1000.f;
767*89a0ef05SAndroid Build Coastguard Worker printf("Average encode time for res %d x %d is %f ms \n", mWidth, mHeight, avgEncTime);
768*89a0ef05SAndroid Build Coastguard Worker #endif
769*89a0ef05SAndroid Build Coastguard Worker
770*89a0ef05SAndroid Build Coastguard Worker #undef RET_IF_ERR
771*89a0ef05SAndroid Build Coastguard Worker
772*89a0ef05SAndroid Build Coastguard Worker auto output = uhdr_get_encoded_stream(handle);
773*89a0ef05SAndroid Build Coastguard Worker
774*89a0ef05SAndroid Build Coastguard Worker // for decoding
775*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.data = malloc(output->data_sz);
776*89a0ef05SAndroid Build Coastguard Worker memcpy(mUhdrImage.data, output->data, output->data_sz);
777*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.capacity = mUhdrImage.data_sz = output->data_sz;
778*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.cg = output->cg;
779*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.ct = output->ct;
780*89a0ef05SAndroid Build Coastguard Worker mUhdrImage.range = output->range;
781*89a0ef05SAndroid Build Coastguard Worker uhdr_release_encoder(handle);
782*89a0ef05SAndroid Build Coastguard Worker
783*89a0ef05SAndroid Build Coastguard Worker return writeFile(mOutputFile, mUhdrImage.data, mUhdrImage.data_sz);
784*89a0ef05SAndroid Build Coastguard Worker }
785*89a0ef05SAndroid Build Coastguard Worker
decode()786*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::decode() {
787*89a0ef05SAndroid Build Coastguard Worker if (mMode == 1 && !fillUhdrImageHandle()) {
788*89a0ef05SAndroid Build Coastguard Worker std::cerr << " failed to load file " << mUhdrFile << std::endl;
789*89a0ef05SAndroid Build Coastguard Worker return false;
790*89a0ef05SAndroid Build Coastguard Worker }
791*89a0ef05SAndroid Build Coastguard Worker
792*89a0ef05SAndroid Build Coastguard Worker #define RET_IF_ERR(x) \
793*89a0ef05SAndroid Build Coastguard Worker { \
794*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = (x); \
795*89a0ef05SAndroid Build Coastguard Worker if (status.error_code != UHDR_CODEC_OK) { \
796*89a0ef05SAndroid Build Coastguard Worker if (status.has_detail) { \
797*89a0ef05SAndroid Build Coastguard Worker std::cerr << status.detail << std::endl; \
798*89a0ef05SAndroid Build Coastguard Worker } \
799*89a0ef05SAndroid Build Coastguard Worker uhdr_release_decoder(handle); \
800*89a0ef05SAndroid Build Coastguard Worker return false; \
801*89a0ef05SAndroid Build Coastguard Worker } \
802*89a0ef05SAndroid Build Coastguard Worker }
803*89a0ef05SAndroid Build Coastguard Worker
804*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private_t* handle = uhdr_create_decoder();
805*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_dec_set_image(handle, &mUhdrImage))
806*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_dec_set_out_color_transfer(handle, mOTf))
807*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_dec_set_out_img_format(handle, mOfmt))
808*89a0ef05SAndroid Build Coastguard Worker if (mEnableGLES) {
809*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_enable_gpu_acceleration(handle, mEnableGLES))
810*89a0ef05SAndroid Build Coastguard Worker }
811*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_dec_probe(handle))
812*89a0ef05SAndroid Build Coastguard Worker if (mGainMapMetadataCfgFile != nullptr) {
813*89a0ef05SAndroid Build Coastguard Worker uhdr_gainmap_metadata_t* metadata = uhdr_dec_get_gainmap_metadata(handle);
814*89a0ef05SAndroid Build Coastguard Worker if (!writeGainMapMetadataToFile(metadata)) {
815*89a0ef05SAndroid Build Coastguard Worker std::cerr << "failed to write gainmap metadata to file: " << mGainMapMetadataCfgFile
816*89a0ef05SAndroid Build Coastguard Worker << std::endl;
817*89a0ef05SAndroid Build Coastguard Worker }
818*89a0ef05SAndroid Build Coastguard Worker }
819*89a0ef05SAndroid Build Coastguard Worker
820*89a0ef05SAndroid Build Coastguard Worker #ifdef PROFILE_ENABLE
821*89a0ef05SAndroid Build Coastguard Worker Profiler profileDecode;
822*89a0ef05SAndroid Build Coastguard Worker profileDecode.timerStart();
823*89a0ef05SAndroid Build Coastguard Worker #endif
824*89a0ef05SAndroid Build Coastguard Worker RET_IF_ERR(uhdr_decode(handle))
825*89a0ef05SAndroid Build Coastguard Worker #ifdef PROFILE_ENABLE
826*89a0ef05SAndroid Build Coastguard Worker profileDecode.timerStop();
827*89a0ef05SAndroid Build Coastguard Worker auto avgDecTime = profileDecode.elapsedTime() / 1000.f;
828*89a0ef05SAndroid Build Coastguard Worker printf("Average decode time for res %d x %d is %f ms \n", uhdr_dec_get_image_width(handle),
829*89a0ef05SAndroid Build Coastguard Worker uhdr_dec_get_image_height(handle), avgDecTime);
830*89a0ef05SAndroid Build Coastguard Worker #endif
831*89a0ef05SAndroid Build Coastguard Worker
832*89a0ef05SAndroid Build Coastguard Worker #undef RET_IF_ERR
833*89a0ef05SAndroid Build Coastguard Worker
834*89a0ef05SAndroid Build Coastguard Worker uhdr_raw_image_t* output = uhdr_get_decoded_image(handle);
835*89a0ef05SAndroid Build Coastguard Worker
836*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.fmt = output->fmt;
837*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.cg = output->cg;
838*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.ct = output->ct;
839*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.range = output->range;
840*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.w = output->w;
841*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.h = output->h;
842*89a0ef05SAndroid Build Coastguard Worker size_t bpp = (output->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) ? 8 : 4;
843*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.planes[UHDR_PLANE_PACKED] = malloc(bpp * output->w * output->h);
844*89a0ef05SAndroid Build Coastguard Worker char* inData = static_cast<char*>(output->planes[UHDR_PLANE_PACKED]);
845*89a0ef05SAndroid Build Coastguard Worker char* outData = static_cast<char*>(mDecodedUhdrRgbImage.planes[UHDR_PLANE_PACKED]);
846*89a0ef05SAndroid Build Coastguard Worker const size_t inStride = output->stride[UHDR_PLANE_PACKED] * bpp;
847*89a0ef05SAndroid Build Coastguard Worker const size_t outStride = output->w * bpp;
848*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrRgbImage.stride[UHDR_PLANE_PACKED] = output->w;
849*89a0ef05SAndroid Build Coastguard Worker const size_t length = output->w * bpp;
850*89a0ef05SAndroid Build Coastguard Worker for (unsigned i = 0; i < output->h; i++, inData += inStride, outData += outStride) {
851*89a0ef05SAndroid Build Coastguard Worker memcpy(outData, inData, length);
852*89a0ef05SAndroid Build Coastguard Worker }
853*89a0ef05SAndroid Build Coastguard Worker uhdr_release_decoder(handle);
854*89a0ef05SAndroid Build Coastguard Worker
855*89a0ef05SAndroid Build Coastguard Worker return mMode == 1 ? writeFile(mOutputFile, &mDecodedUhdrRgbImage) : true;
856*89a0ef05SAndroid Build Coastguard Worker }
857*89a0ef05SAndroid Build Coastguard Worker
858*89a0ef05SAndroid Build Coastguard Worker #define CLIP3(x, min, max) ((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x)
convertP010ToRGBImage()859*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::convertP010ToRGBImage() {
860*89a0ef05SAndroid Build Coastguard Worker const float* coeffs = BT2020YUVtoRGBMatrix;
861*89a0ef05SAndroid Build Coastguard Worker if (mHdrCg == UHDR_CG_BT_709) {
862*89a0ef05SAndroid Build Coastguard Worker coeffs = BT709YUVtoRGBMatrix;
863*89a0ef05SAndroid Build Coastguard Worker } else if (mHdrCg == UHDR_CG_BT_2100) {
864*89a0ef05SAndroid Build Coastguard Worker coeffs = BT2020YUVtoRGBMatrix;
865*89a0ef05SAndroid Build Coastguard Worker } else if (mHdrCg == UHDR_CG_DISPLAY_P3) {
866*89a0ef05SAndroid Build Coastguard Worker coeffs = BT601YUVtoRGBMatrix;
867*89a0ef05SAndroid Build Coastguard Worker } else {
868*89a0ef05SAndroid Build Coastguard Worker std::cerr << "color matrix not present for gamut " << mHdrCg << " using BT2020Matrix"
869*89a0ef05SAndroid Build Coastguard Worker << std::endl;
870*89a0ef05SAndroid Build Coastguard Worker }
871*89a0ef05SAndroid Build Coastguard Worker
872*89a0ef05SAndroid Build Coastguard Worker size_t bpp = 4;
873*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.fmt = UHDR_IMG_FMT_32bppRGBA1010102;
874*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.cg = mRawP010Image.cg;
875*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.ct = mRawP010Image.ct;
876*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.range = UHDR_CR_FULL_RANGE;
877*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.w = mRawP010Image.w;
878*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.h = mRawP010Image.h;
879*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.planes[UHDR_PLANE_PACKED] = malloc(bpp * mRawP010Image.w * mRawP010Image.h);
880*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.planes[UHDR_PLANE_U] = nullptr;
881*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.planes[UHDR_PLANE_V] = nullptr;
882*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.stride[UHDR_PLANE_PACKED] = mWidth;
883*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.stride[UHDR_PLANE_U] = 0;
884*89a0ef05SAndroid Build Coastguard Worker mRawRgba1010102Image.stride[UHDR_PLANE_V] = 0;
885*89a0ef05SAndroid Build Coastguard Worker
886*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbData = static_cast<uint32_t*>(mRawRgba1010102Image.planes[UHDR_PLANE_PACKED]);
887*89a0ef05SAndroid Build Coastguard Worker uint16_t* y = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_Y]);
888*89a0ef05SAndroid Build Coastguard Worker uint16_t* u = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_UV]);
889*89a0ef05SAndroid Build Coastguard Worker uint16_t* v = u + 1;
890*89a0ef05SAndroid Build Coastguard Worker
891*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < mRawP010Image.h; i++) {
892*89a0ef05SAndroid Build Coastguard Worker for (size_t j = 0; j < mRawP010Image.w; j++) {
893*89a0ef05SAndroid Build Coastguard Worker float y0 = float(y[mRawP010Image.stride[UHDR_PLANE_Y] * i + j] >> 6);
894*89a0ef05SAndroid Build Coastguard Worker float u0 = float(u[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6);
895*89a0ef05SAndroid Build Coastguard Worker float v0 = float(v[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6);
896*89a0ef05SAndroid Build Coastguard Worker
897*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.range == UHDR_CR_FULL_RANGE) {
898*89a0ef05SAndroid Build Coastguard Worker y0 = CLIP3(y0, 0.0f, 1023.0f);
899*89a0ef05SAndroid Build Coastguard Worker u0 = CLIP3(u0, 0.0f, 1023.0f);
900*89a0ef05SAndroid Build Coastguard Worker v0 = CLIP3(v0, 0.0f, 1023.0f);
901*89a0ef05SAndroid Build Coastguard Worker
902*89a0ef05SAndroid Build Coastguard Worker y0 = y0 / 1023.0f;
903*89a0ef05SAndroid Build Coastguard Worker u0 = u0 / 1023.0f - 0.5f;
904*89a0ef05SAndroid Build Coastguard Worker v0 = v0 / 1023.0f - 0.5f;
905*89a0ef05SAndroid Build Coastguard Worker } else {
906*89a0ef05SAndroid Build Coastguard Worker y0 = CLIP3(y0, 64.0f, 940.0f);
907*89a0ef05SAndroid Build Coastguard Worker u0 = CLIP3(u0, 64.0f, 960.0f);
908*89a0ef05SAndroid Build Coastguard Worker v0 = CLIP3(v0, 64.0f, 960.0f);
909*89a0ef05SAndroid Build Coastguard Worker
910*89a0ef05SAndroid Build Coastguard Worker y0 = (y0 - 64.0f) / 876.0f;
911*89a0ef05SAndroid Build Coastguard Worker u0 = (u0 - 512.0f) / 896.0f;
912*89a0ef05SAndroid Build Coastguard Worker v0 = (v0 - 512.0f) / 896.0f;
913*89a0ef05SAndroid Build Coastguard Worker }
914*89a0ef05SAndroid Build Coastguard Worker
915*89a0ef05SAndroid Build Coastguard Worker float r = coeffs[0] * y0 + coeffs[1] * u0 + coeffs[2] * v0;
916*89a0ef05SAndroid Build Coastguard Worker float g = coeffs[3] * y0 + coeffs[4] * u0 + coeffs[5] * v0;
917*89a0ef05SAndroid Build Coastguard Worker float b = coeffs[6] * y0 + coeffs[7] * u0 + coeffs[8] * v0;
918*89a0ef05SAndroid Build Coastguard Worker
919*89a0ef05SAndroid Build Coastguard Worker r = CLIP3(r * 1023.0f + 0.5f, 0.0f, 1023.0f);
920*89a0ef05SAndroid Build Coastguard Worker g = CLIP3(g * 1023.0f + 0.5f, 0.0f, 1023.0f);
921*89a0ef05SAndroid Build Coastguard Worker b = CLIP3(b * 1023.0f + 0.5f, 0.0f, 1023.0f);
922*89a0ef05SAndroid Build Coastguard Worker
923*89a0ef05SAndroid Build Coastguard Worker int32_t r0 = int32_t(r);
924*89a0ef05SAndroid Build Coastguard Worker int32_t g0 = int32_t(g);
925*89a0ef05SAndroid Build Coastguard Worker int32_t b0 = int32_t(b);
926*89a0ef05SAndroid Build Coastguard Worker *rgbData = (0x3ff & r0) | ((0x3ff & g0) << 10) | ((0x3ff & b0) << 20) |
927*89a0ef05SAndroid Build Coastguard Worker (0x3 << 30); // Set alpha to 1.0
928*89a0ef05SAndroid Build Coastguard Worker
929*89a0ef05SAndroid Build Coastguard Worker rgbData++;
930*89a0ef05SAndroid Build Coastguard Worker }
931*89a0ef05SAndroid Build Coastguard Worker }
932*89a0ef05SAndroid Build Coastguard Worker #ifdef DUMP_DEBUG_DATA
933*89a0ef05SAndroid Build Coastguard Worker writeFile("inRgba1010102.raw", &mRawRgba1010102Image);
934*89a0ef05SAndroid Build Coastguard Worker #endif
935*89a0ef05SAndroid Build Coastguard Worker return true;
936*89a0ef05SAndroid Build Coastguard Worker }
937*89a0ef05SAndroid Build Coastguard Worker
convertYuv420ToRGBImage()938*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::convertYuv420ToRGBImage() {
939*89a0ef05SAndroid Build Coastguard Worker size_t bpp = 4;
940*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.fmt = UHDR_IMG_FMT_32bppRGBA8888;
941*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.cg = mRawYuv420Image.cg;
942*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.ct = mRawYuv420Image.ct;
943*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.range = UHDR_CR_FULL_RANGE;
944*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.w = mRawYuv420Image.w;
945*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.h = mRawYuv420Image.h;
946*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.planes[UHDR_PLANE_PACKED] = malloc(bpp * mRawYuv420Image.w * mRawYuv420Image.h);
947*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.planes[UHDR_PLANE_U] = nullptr;
948*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.planes[UHDR_PLANE_V] = nullptr;
949*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.stride[UHDR_PLANE_PACKED] = mWidth;
950*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.stride[UHDR_PLANE_U] = 0;
951*89a0ef05SAndroid Build Coastguard Worker mRawRgba8888Image.stride[UHDR_PLANE_V] = 0;
952*89a0ef05SAndroid Build Coastguard Worker
953*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbData = static_cast<uint32_t*>(mRawRgba8888Image.planes[UHDR_PLANE_PACKED]);
954*89a0ef05SAndroid Build Coastguard Worker uint8_t* y = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_Y]);
955*89a0ef05SAndroid Build Coastguard Worker uint8_t* u = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_U]);
956*89a0ef05SAndroid Build Coastguard Worker uint8_t* v = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_V]);
957*89a0ef05SAndroid Build Coastguard Worker
958*89a0ef05SAndroid Build Coastguard Worker const float* coeffs = BT601YUVtoRGBMatrix;
959*89a0ef05SAndroid Build Coastguard Worker if (mSdrCg == UHDR_CG_BT_709) {
960*89a0ef05SAndroid Build Coastguard Worker coeffs = BT709YUVtoRGBMatrix;
961*89a0ef05SAndroid Build Coastguard Worker } else if (mSdrCg == UHDR_CG_BT_2100) {
962*89a0ef05SAndroid Build Coastguard Worker coeffs = BT2020YUVtoRGBMatrix;
963*89a0ef05SAndroid Build Coastguard Worker } else if (mSdrCg == UHDR_CG_DISPLAY_P3) {
964*89a0ef05SAndroid Build Coastguard Worker coeffs = BT601YUVtoRGBMatrix;
965*89a0ef05SAndroid Build Coastguard Worker } else {
966*89a0ef05SAndroid Build Coastguard Worker std::cerr << "color matrix not present for gamut " << mSdrCg << " using BT601Matrix"
967*89a0ef05SAndroid Build Coastguard Worker << std::endl;
968*89a0ef05SAndroid Build Coastguard Worker }
969*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < mRawYuv420Image.h; i++) {
970*89a0ef05SAndroid Build Coastguard Worker for (size_t j = 0; j < mRawYuv420Image.w; j++) {
971*89a0ef05SAndroid Build Coastguard Worker float y0 = float(y[mRawYuv420Image.stride[UHDR_PLANE_Y] * i + j]);
972*89a0ef05SAndroid Build Coastguard Worker float u0 = float(u[mRawYuv420Image.stride[UHDR_PLANE_U] * (i / 2) + (j / 2)] - 128);
973*89a0ef05SAndroid Build Coastguard Worker float v0 = float(v[mRawYuv420Image.stride[UHDR_PLANE_V] * (i / 2) + (j / 2)] - 128);
974*89a0ef05SAndroid Build Coastguard Worker
975*89a0ef05SAndroid Build Coastguard Worker y0 /= 255.0f;
976*89a0ef05SAndroid Build Coastguard Worker u0 /= 255.0f;
977*89a0ef05SAndroid Build Coastguard Worker v0 /= 255.0f;
978*89a0ef05SAndroid Build Coastguard Worker
979*89a0ef05SAndroid Build Coastguard Worker float r = coeffs[0] * y0 + coeffs[1] * u0 + coeffs[2] * v0;
980*89a0ef05SAndroid Build Coastguard Worker float g = coeffs[3] * y0 + coeffs[4] * u0 + coeffs[5] * v0;
981*89a0ef05SAndroid Build Coastguard Worker float b = coeffs[6] * y0 + coeffs[7] * u0 + coeffs[8] * v0;
982*89a0ef05SAndroid Build Coastguard Worker
983*89a0ef05SAndroid Build Coastguard Worker r = r * 255.0f + 0.5f;
984*89a0ef05SAndroid Build Coastguard Worker g = g * 255.0f + 0.5f;
985*89a0ef05SAndroid Build Coastguard Worker b = b * 255.0f + 0.5f;
986*89a0ef05SAndroid Build Coastguard Worker
987*89a0ef05SAndroid Build Coastguard Worker r = CLIP3(r, 0.0f, 255.0f);
988*89a0ef05SAndroid Build Coastguard Worker g = CLIP3(g, 0.0f, 255.0f);
989*89a0ef05SAndroid Build Coastguard Worker b = CLIP3(b, 0.0f, 255.0f);
990*89a0ef05SAndroid Build Coastguard Worker
991*89a0ef05SAndroid Build Coastguard Worker int32_t r0 = int32_t(r);
992*89a0ef05SAndroid Build Coastguard Worker int32_t g0 = int32_t(g);
993*89a0ef05SAndroid Build Coastguard Worker int32_t b0 = int32_t(b);
994*89a0ef05SAndroid Build Coastguard Worker *rgbData = r0 | (g0 << 8) | (b0 << 16) | (255 << 24); // Set alpha to 1.0
995*89a0ef05SAndroid Build Coastguard Worker
996*89a0ef05SAndroid Build Coastguard Worker rgbData++;
997*89a0ef05SAndroid Build Coastguard Worker }
998*89a0ef05SAndroid Build Coastguard Worker }
999*89a0ef05SAndroid Build Coastguard Worker #ifdef DUMP_DEBUG_DATA
1000*89a0ef05SAndroid Build Coastguard Worker writeFile("inRgba8888.raw", &mRawRgba8888Image);
1001*89a0ef05SAndroid Build Coastguard Worker #endif
1002*89a0ef05SAndroid Build Coastguard Worker return true;
1003*89a0ef05SAndroid Build Coastguard Worker }
1004*89a0ef05SAndroid Build Coastguard Worker
convertRgba8888ToYUV444Image()1005*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::convertRgba8888ToYUV444Image() {
1006*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.fmt = static_cast<uhdr_img_fmt_t>(UHDR_IMG_FMT_24bppYCbCr444);
1007*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.cg = mDecodedUhdrRgbImage.cg;
1008*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.ct = mDecodedUhdrRgbImage.ct;
1009*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.range = UHDR_CR_FULL_RANGE;
1010*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.w = mDecodedUhdrRgbImage.w;
1011*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.h = mDecodedUhdrRgbImage.h;
1012*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.planes[UHDR_PLANE_Y] =
1013*89a0ef05SAndroid Build Coastguard Worker malloc((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1014*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.planes[UHDR_PLANE_U] =
1015*89a0ef05SAndroid Build Coastguard Worker malloc((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1016*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.planes[UHDR_PLANE_V] =
1017*89a0ef05SAndroid Build Coastguard Worker malloc((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1018*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.stride[UHDR_PLANE_Y] = mWidth;
1019*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] = mWidth;
1020*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] = mWidth;
1021*89a0ef05SAndroid Build Coastguard Worker
1022*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbData = static_cast<uint32_t*>(mDecodedUhdrRgbImage.planes[UHDR_PLANE_PACKED]);
1023*89a0ef05SAndroid Build Coastguard Worker
1024*89a0ef05SAndroid Build Coastguard Worker uint8_t* yData = static_cast<uint8_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_Y]);
1025*89a0ef05SAndroid Build Coastguard Worker uint8_t* uData = static_cast<uint8_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_U]);
1026*89a0ef05SAndroid Build Coastguard Worker uint8_t* vData = static_cast<uint8_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_V]);
1027*89a0ef05SAndroid Build Coastguard Worker
1028*89a0ef05SAndroid Build Coastguard Worker const float* coeffs = BT601RGBtoYUVMatrix;
1029*89a0ef05SAndroid Build Coastguard Worker if (mDecodedUhdrRgbImage.cg == UHDR_CG_BT_709) {
1030*89a0ef05SAndroid Build Coastguard Worker coeffs = BT709RGBtoYUVMatrix;
1031*89a0ef05SAndroid Build Coastguard Worker } else if (mDecodedUhdrRgbImage.cg == UHDR_CG_BT_2100) {
1032*89a0ef05SAndroid Build Coastguard Worker coeffs = BT2020RGBtoYUVMatrix;
1033*89a0ef05SAndroid Build Coastguard Worker } else if (mDecodedUhdrRgbImage.cg == UHDR_CG_DISPLAY_P3) {
1034*89a0ef05SAndroid Build Coastguard Worker coeffs = BT601RGBtoYUVMatrix;
1035*89a0ef05SAndroid Build Coastguard Worker } else {
1036*89a0ef05SAndroid Build Coastguard Worker std::cerr << "color matrix not present for gamut " << mDecodedUhdrRgbImage.cg
1037*89a0ef05SAndroid Build Coastguard Worker << " using BT601Matrix" << std::endl;
1038*89a0ef05SAndroid Build Coastguard Worker }
1039*89a0ef05SAndroid Build Coastguard Worker
1040*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < mDecodedUhdrRgbImage.h; i++) {
1041*89a0ef05SAndroid Build Coastguard Worker for (size_t j = 0; j < mDecodedUhdrRgbImage.w; j++) {
1042*89a0ef05SAndroid Build Coastguard Worker float r0 = float(rgbData[mDecodedUhdrRgbImage.stride[UHDR_PLANE_PACKED] * i + j] & 0xff);
1043*89a0ef05SAndroid Build Coastguard Worker float g0 =
1044*89a0ef05SAndroid Build Coastguard Worker float((rgbData[mDecodedUhdrRgbImage.stride[UHDR_PLANE_PACKED] * i + j] >> 8) & 0xff);
1045*89a0ef05SAndroid Build Coastguard Worker float b0 =
1046*89a0ef05SAndroid Build Coastguard Worker float((rgbData[mDecodedUhdrRgbImage.stride[UHDR_PLANE_PACKED] * i + j] >> 16) & 0xff);
1047*89a0ef05SAndroid Build Coastguard Worker
1048*89a0ef05SAndroid Build Coastguard Worker r0 /= 255.0f;
1049*89a0ef05SAndroid Build Coastguard Worker g0 /= 255.0f;
1050*89a0ef05SAndroid Build Coastguard Worker b0 /= 255.0f;
1051*89a0ef05SAndroid Build Coastguard Worker
1052*89a0ef05SAndroid Build Coastguard Worker float y = coeffs[0] * r0 + coeffs[1] * g0 + coeffs[2] * b0;
1053*89a0ef05SAndroid Build Coastguard Worker float u = coeffs[3] * r0 + coeffs[4] * g0 + coeffs[5] * b0;
1054*89a0ef05SAndroid Build Coastguard Worker float v = coeffs[6] * r0 + coeffs[7] * g0 + coeffs[8] * b0;
1055*89a0ef05SAndroid Build Coastguard Worker
1056*89a0ef05SAndroid Build Coastguard Worker y = y * 255.0f + 0.5f;
1057*89a0ef05SAndroid Build Coastguard Worker u = u * 255.0f + 0.5f + 128.0f;
1058*89a0ef05SAndroid Build Coastguard Worker v = v * 255.0f + 0.5f + 128.0f;
1059*89a0ef05SAndroid Build Coastguard Worker
1060*89a0ef05SAndroid Build Coastguard Worker y = CLIP3(y, 0.0f, 255.0f);
1061*89a0ef05SAndroid Build Coastguard Worker u = CLIP3(u, 0.0f, 255.0f);
1062*89a0ef05SAndroid Build Coastguard Worker v = CLIP3(v, 0.0f, 255.0f);
1063*89a0ef05SAndroid Build Coastguard Worker
1064*89a0ef05SAndroid Build Coastguard Worker yData[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_Y] * i + j] = uint8_t(y);
1065*89a0ef05SAndroid Build Coastguard Worker uData[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * i + j] = uint8_t(u);
1066*89a0ef05SAndroid Build Coastguard Worker vData[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * i + j] = uint8_t(v);
1067*89a0ef05SAndroid Build Coastguard Worker }
1068*89a0ef05SAndroid Build Coastguard Worker }
1069*89a0ef05SAndroid Build Coastguard Worker #ifdef DUMP_DEBUG_DATA
1070*89a0ef05SAndroid Build Coastguard Worker writeFile("outyuv444.yuv", &mDecodedUhdrYuv444Image);
1071*89a0ef05SAndroid Build Coastguard Worker #endif
1072*89a0ef05SAndroid Build Coastguard Worker return true;
1073*89a0ef05SAndroid Build Coastguard Worker }
1074*89a0ef05SAndroid Build Coastguard Worker
convertRgba1010102ToYUV444Image()1075*89a0ef05SAndroid Build Coastguard Worker bool UltraHdrAppInput::convertRgba1010102ToYUV444Image() {
1076*89a0ef05SAndroid Build Coastguard Worker const float* coeffs = BT2020RGBtoYUVMatrix;
1077*89a0ef05SAndroid Build Coastguard Worker if (mDecodedUhdrRgbImage.cg == UHDR_CG_BT_709) {
1078*89a0ef05SAndroid Build Coastguard Worker coeffs = BT709RGBtoYUVMatrix;
1079*89a0ef05SAndroid Build Coastguard Worker } else if (mDecodedUhdrRgbImage.cg == UHDR_CG_BT_2100) {
1080*89a0ef05SAndroid Build Coastguard Worker coeffs = BT2020RGBtoYUVMatrix;
1081*89a0ef05SAndroid Build Coastguard Worker } else if (mDecodedUhdrRgbImage.cg == UHDR_CG_DISPLAY_P3) {
1082*89a0ef05SAndroid Build Coastguard Worker coeffs = BT601RGBtoYUVMatrix;
1083*89a0ef05SAndroid Build Coastguard Worker } else {
1084*89a0ef05SAndroid Build Coastguard Worker std::cerr << "color matrix not present for gamut " << mDecodedUhdrRgbImage.cg
1085*89a0ef05SAndroid Build Coastguard Worker << " using BT2020Matrix" << std::endl;
1086*89a0ef05SAndroid Build Coastguard Worker }
1087*89a0ef05SAndroid Build Coastguard Worker
1088*89a0ef05SAndroid Build Coastguard Worker size_t bpp = 2;
1089*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.fmt = static_cast<uhdr_img_fmt_t>(UHDR_IMG_FMT_48bppYCbCr444);
1090*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.cg = mDecodedUhdrRgbImage.cg;
1091*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.ct = mDecodedUhdrRgbImage.ct;
1092*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.range = mRawP010Image.range;
1093*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.w = mDecodedUhdrRgbImage.w;
1094*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.h = mDecodedUhdrRgbImage.h;
1095*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.planes[UHDR_PLANE_Y] =
1096*89a0ef05SAndroid Build Coastguard Worker malloc(bpp * mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1097*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.planes[UHDR_PLANE_U] =
1098*89a0ef05SAndroid Build Coastguard Worker malloc(bpp * mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1099*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.planes[UHDR_PLANE_V] =
1100*89a0ef05SAndroid Build Coastguard Worker malloc(bpp * mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1101*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.stride[UHDR_PLANE_Y] = mWidth;
1102*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] = mWidth;
1103*89a0ef05SAndroid Build Coastguard Worker mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] = mWidth;
1104*89a0ef05SAndroid Build Coastguard Worker
1105*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbData = static_cast<uint32_t*>(mDecodedUhdrRgbImage.planes[UHDR_PLANE_PACKED]);
1106*89a0ef05SAndroid Build Coastguard Worker
1107*89a0ef05SAndroid Build Coastguard Worker uint16_t* yData = static_cast<uint16_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_Y]);
1108*89a0ef05SAndroid Build Coastguard Worker uint16_t* uData = static_cast<uint16_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_U]);
1109*89a0ef05SAndroid Build Coastguard Worker uint16_t* vData = static_cast<uint16_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_V]);
1110*89a0ef05SAndroid Build Coastguard Worker
1111*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < mDecodedUhdrRgbImage.h; i++) {
1112*89a0ef05SAndroid Build Coastguard Worker for (size_t j = 0; j < mDecodedUhdrRgbImage.w; j++) {
1113*89a0ef05SAndroid Build Coastguard Worker float r0 = float(rgbData[mDecodedUhdrRgbImage.stride[UHDR_PLANE_PACKED] * i + j] & 0x3ff);
1114*89a0ef05SAndroid Build Coastguard Worker float g0 =
1115*89a0ef05SAndroid Build Coastguard Worker float((rgbData[mDecodedUhdrRgbImage.stride[UHDR_PLANE_PACKED] * i + j] >> 10) & 0x3ff);
1116*89a0ef05SAndroid Build Coastguard Worker float b0 =
1117*89a0ef05SAndroid Build Coastguard Worker float((rgbData[mDecodedUhdrRgbImage.stride[UHDR_PLANE_PACKED] * i + j] >> 20) & 0x3ff);
1118*89a0ef05SAndroid Build Coastguard Worker
1119*89a0ef05SAndroid Build Coastguard Worker r0 /= 1023.0f;
1120*89a0ef05SAndroid Build Coastguard Worker g0 /= 1023.0f;
1121*89a0ef05SAndroid Build Coastguard Worker b0 /= 1023.0f;
1122*89a0ef05SAndroid Build Coastguard Worker
1123*89a0ef05SAndroid Build Coastguard Worker float y = coeffs[0] * r0 + coeffs[1] * g0 + coeffs[2] * b0;
1124*89a0ef05SAndroid Build Coastguard Worker float u = coeffs[3] * r0 + coeffs[4] * g0 + coeffs[5] * b0;
1125*89a0ef05SAndroid Build Coastguard Worker float v = coeffs[6] * r0 + coeffs[7] * g0 + coeffs[8] * b0;
1126*89a0ef05SAndroid Build Coastguard Worker
1127*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.range == UHDR_CR_FULL_RANGE) {
1128*89a0ef05SAndroid Build Coastguard Worker y = y * 1023.0f + 0.5f;
1129*89a0ef05SAndroid Build Coastguard Worker u = (u + 0.5f) * 1023.0f + 0.5f;
1130*89a0ef05SAndroid Build Coastguard Worker v = (v + 0.5f) * 1023.0f + 0.5f;
1131*89a0ef05SAndroid Build Coastguard Worker
1132*89a0ef05SAndroid Build Coastguard Worker y = CLIP3(y, 0.0f, 1023.0f);
1133*89a0ef05SAndroid Build Coastguard Worker u = CLIP3(u, 0.0f, 1023.0f);
1134*89a0ef05SAndroid Build Coastguard Worker v = CLIP3(v, 0.0f, 1023.0f);
1135*89a0ef05SAndroid Build Coastguard Worker } else {
1136*89a0ef05SAndroid Build Coastguard Worker y = (y * 876.0f) + 64.0f + 0.5f;
1137*89a0ef05SAndroid Build Coastguard Worker u = (u * 896.0f) + 512.0f + 0.5f;
1138*89a0ef05SAndroid Build Coastguard Worker v = (v * 896.0f) + 512.0f + 0.5f;
1139*89a0ef05SAndroid Build Coastguard Worker
1140*89a0ef05SAndroid Build Coastguard Worker y = CLIP3(y, 64.0f, 940.0f);
1141*89a0ef05SAndroid Build Coastguard Worker u = CLIP3(u, 64.0f, 960.0f);
1142*89a0ef05SAndroid Build Coastguard Worker v = CLIP3(v, 64.0f, 960.0f);
1143*89a0ef05SAndroid Build Coastguard Worker }
1144*89a0ef05SAndroid Build Coastguard Worker
1145*89a0ef05SAndroid Build Coastguard Worker yData[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_Y] * i + j] = uint16_t(y);
1146*89a0ef05SAndroid Build Coastguard Worker uData[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * i + j] = uint16_t(u);
1147*89a0ef05SAndroid Build Coastguard Worker vData[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * i + j] = uint16_t(v);
1148*89a0ef05SAndroid Build Coastguard Worker }
1149*89a0ef05SAndroid Build Coastguard Worker }
1150*89a0ef05SAndroid Build Coastguard Worker #ifdef DUMP_DEBUG_DATA
1151*89a0ef05SAndroid Build Coastguard Worker writeFile("outyuv444.yuv", &mDecodedUhdrYuv444Image);
1152*89a0ef05SAndroid Build Coastguard Worker #endif
1153*89a0ef05SAndroid Build Coastguard Worker return true;
1154*89a0ef05SAndroid Build Coastguard Worker }
1155*89a0ef05SAndroid Build Coastguard Worker
computeRGBHdrPSNR()1156*89a0ef05SAndroid Build Coastguard Worker void UltraHdrAppInput::computeRGBHdrPSNR() {
1157*89a0ef05SAndroid Build Coastguard Worker if (mOfmt != UHDR_IMG_FMT_32bppRGBA1010102) {
1158*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr not supported for output format " << mOfmt << std::endl;
1159*89a0ef05SAndroid Build Coastguard Worker return;
1160*89a0ef05SAndroid Build Coastguard Worker }
1161*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbDataSrc = static_cast<uint32_t*>(mRawRgba1010102Image.planes[UHDR_PLANE_PACKED]);
1162*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbDataDst = static_cast<uint32_t*>(mDecodedUhdrRgbImage.planes[UHDR_PLANE_PACKED]);
1163*89a0ef05SAndroid Build Coastguard Worker if (rgbDataSrc == nullptr || rgbDataDst == nullptr) {
1164*89a0ef05SAndroid Build Coastguard Worker std::cerr << "invalid src or dst pointer for psnr computation " << std::endl;
1165*89a0ef05SAndroid Build Coastguard Worker return;
1166*89a0ef05SAndroid Build Coastguard Worker }
1167*89a0ef05SAndroid Build Coastguard Worker if (mRawRgba1010102Image.ct != mDecodedUhdrRgbImage.ct) {
1168*89a0ef05SAndroid Build Coastguard Worker std::cout << "input color transfer and output color transfer are not identical, rgb psnr "
1169*89a0ef05SAndroid Build Coastguard Worker "results may be unreliable"
1170*89a0ef05SAndroid Build Coastguard Worker << std::endl;
1171*89a0ef05SAndroid Build Coastguard Worker }
1172*89a0ef05SAndroid Build Coastguard Worker if (mRawRgba1010102Image.cg != mDecodedUhdrRgbImage.cg) {
1173*89a0ef05SAndroid Build Coastguard Worker std::cout << "input color gamut and output color gamut are not identical, rgb psnr results "
1174*89a0ef05SAndroid Build Coastguard Worker "may be unreliable"
1175*89a0ef05SAndroid Build Coastguard Worker << std::endl;
1176*89a0ef05SAndroid Build Coastguard Worker }
1177*89a0ef05SAndroid Build Coastguard Worker uint64_t rSqError = 0, gSqError = 0, bSqError = 0;
1178*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < (size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h; i++) {
1179*89a0ef05SAndroid Build Coastguard Worker int rSrc = *rgbDataSrc & 0x3ff;
1180*89a0ef05SAndroid Build Coastguard Worker int rDst = *rgbDataDst & 0x3ff;
1181*89a0ef05SAndroid Build Coastguard Worker rSqError += (rSrc - rDst) * (rSrc - rDst);
1182*89a0ef05SAndroid Build Coastguard Worker
1183*89a0ef05SAndroid Build Coastguard Worker int gSrc = (*rgbDataSrc >> 10) & 0x3ff;
1184*89a0ef05SAndroid Build Coastguard Worker int gDst = (*rgbDataDst >> 10) & 0x3ff;
1185*89a0ef05SAndroid Build Coastguard Worker gSqError += (gSrc - gDst) * (gSrc - gDst);
1186*89a0ef05SAndroid Build Coastguard Worker
1187*89a0ef05SAndroid Build Coastguard Worker int bSrc = (*rgbDataSrc >> 20) & 0x3ff;
1188*89a0ef05SAndroid Build Coastguard Worker int bDst = (*rgbDataDst >> 20) & 0x3ff;
1189*89a0ef05SAndroid Build Coastguard Worker bSqError += (bSrc - bDst) * (bSrc - bDst);
1190*89a0ef05SAndroid Build Coastguard Worker
1191*89a0ef05SAndroid Build Coastguard Worker rgbDataSrc++;
1192*89a0ef05SAndroid Build Coastguard Worker rgbDataDst++;
1193*89a0ef05SAndroid Build Coastguard Worker }
1194*89a0ef05SAndroid Build Coastguard Worker double meanSquareError =
1195*89a0ef05SAndroid Build Coastguard Worker (double)rSqError / ((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1196*89a0ef05SAndroid Build Coastguard Worker mPsnr[0] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
1197*89a0ef05SAndroid Build Coastguard Worker
1198*89a0ef05SAndroid Build Coastguard Worker meanSquareError = (double)gSqError / ((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1199*89a0ef05SAndroid Build Coastguard Worker mPsnr[1] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
1200*89a0ef05SAndroid Build Coastguard Worker
1201*89a0ef05SAndroid Build Coastguard Worker meanSquareError = (double)bSqError / ((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1202*89a0ef05SAndroid Build Coastguard Worker mPsnr[2] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
1203*89a0ef05SAndroid Build Coastguard Worker
1204*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr rgb: \t" << mPsnr[0] << " \t " << mPsnr[1] << " \t " << mPsnr[2] << std::endl;
1205*89a0ef05SAndroid Build Coastguard Worker }
1206*89a0ef05SAndroid Build Coastguard Worker
computeRGBSdrPSNR()1207*89a0ef05SAndroid Build Coastguard Worker void UltraHdrAppInput::computeRGBSdrPSNR() {
1208*89a0ef05SAndroid Build Coastguard Worker if (mOfmt != UHDR_IMG_FMT_32bppRGBA8888) {
1209*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr not supported for output format " << mOfmt << std::endl;
1210*89a0ef05SAndroid Build Coastguard Worker return;
1211*89a0ef05SAndroid Build Coastguard Worker }
1212*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbDataSrc = static_cast<uint32_t*>(mRawRgba8888Image.planes[UHDR_PLANE_PACKED]);
1213*89a0ef05SAndroid Build Coastguard Worker uint32_t* rgbDataDst = static_cast<uint32_t*>(mDecodedUhdrRgbImage.planes[UHDR_PLANE_PACKED]);
1214*89a0ef05SAndroid Build Coastguard Worker if (rgbDataSrc == nullptr || rgbDataDst == nullptr) {
1215*89a0ef05SAndroid Build Coastguard Worker std::cerr << "invalid src or dst pointer for psnr computation " << std::endl;
1216*89a0ef05SAndroid Build Coastguard Worker return;
1217*89a0ef05SAndroid Build Coastguard Worker }
1218*89a0ef05SAndroid Build Coastguard Worker
1219*89a0ef05SAndroid Build Coastguard Worker uint64_t rSqError = 0, gSqError = 0, bSqError = 0;
1220*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < (size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h; i++) {
1221*89a0ef05SAndroid Build Coastguard Worker int rSrc = *rgbDataSrc & 0xff;
1222*89a0ef05SAndroid Build Coastguard Worker int rDst = *rgbDataDst & 0xff;
1223*89a0ef05SAndroid Build Coastguard Worker rSqError += (rSrc - rDst) * (rSrc - rDst);
1224*89a0ef05SAndroid Build Coastguard Worker
1225*89a0ef05SAndroid Build Coastguard Worker int gSrc = (*rgbDataSrc >> 8) & 0xff;
1226*89a0ef05SAndroid Build Coastguard Worker int gDst = (*rgbDataDst >> 8) & 0xff;
1227*89a0ef05SAndroid Build Coastguard Worker gSqError += (gSrc - gDst) * (gSrc - gDst);
1228*89a0ef05SAndroid Build Coastguard Worker
1229*89a0ef05SAndroid Build Coastguard Worker int bSrc = (*rgbDataSrc >> 16) & 0xff;
1230*89a0ef05SAndroid Build Coastguard Worker int bDst = (*rgbDataDst >> 16) & 0xff;
1231*89a0ef05SAndroid Build Coastguard Worker bSqError += (bSrc - bDst) * (bSrc - bDst);
1232*89a0ef05SAndroid Build Coastguard Worker
1233*89a0ef05SAndroid Build Coastguard Worker rgbDataSrc++;
1234*89a0ef05SAndroid Build Coastguard Worker rgbDataDst++;
1235*89a0ef05SAndroid Build Coastguard Worker }
1236*89a0ef05SAndroid Build Coastguard Worker double meanSquareError =
1237*89a0ef05SAndroid Build Coastguard Worker (double)rSqError / ((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1238*89a0ef05SAndroid Build Coastguard Worker mPsnr[0] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
1239*89a0ef05SAndroid Build Coastguard Worker
1240*89a0ef05SAndroid Build Coastguard Worker meanSquareError = (double)gSqError / ((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1241*89a0ef05SAndroid Build Coastguard Worker mPsnr[1] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
1242*89a0ef05SAndroid Build Coastguard Worker
1243*89a0ef05SAndroid Build Coastguard Worker meanSquareError = (double)bSqError / ((size_t)mDecodedUhdrRgbImage.w * mDecodedUhdrRgbImage.h);
1244*89a0ef05SAndroid Build Coastguard Worker mPsnr[2] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
1245*89a0ef05SAndroid Build Coastguard Worker
1246*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr rgb: \t" << mPsnr[0] << " \t " << mPsnr[1] << " \t " << mPsnr[2] << std::endl;
1247*89a0ef05SAndroid Build Coastguard Worker }
1248*89a0ef05SAndroid Build Coastguard Worker
computeYUVHdrPSNR()1249*89a0ef05SAndroid Build Coastguard Worker void UltraHdrAppInput::computeYUVHdrPSNR() {
1250*89a0ef05SAndroid Build Coastguard Worker if (mOfmt != UHDR_IMG_FMT_32bppRGBA1010102) {
1251*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr not supported for output format " << mOfmt << std::endl;
1252*89a0ef05SAndroid Build Coastguard Worker return;
1253*89a0ef05SAndroid Build Coastguard Worker }
1254*89a0ef05SAndroid Build Coastguard Worker uint16_t* yDataSrc = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_Y]);
1255*89a0ef05SAndroid Build Coastguard Worker uint16_t* uDataSrc = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_UV]);
1256*89a0ef05SAndroid Build Coastguard Worker uint16_t* vDataSrc = uDataSrc + 1;
1257*89a0ef05SAndroid Build Coastguard Worker
1258*89a0ef05SAndroid Build Coastguard Worker uint16_t* yDataDst = static_cast<uint16_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_Y]);
1259*89a0ef05SAndroid Build Coastguard Worker uint16_t* uDataDst = static_cast<uint16_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_U]);
1260*89a0ef05SAndroid Build Coastguard Worker uint16_t* vDataDst = static_cast<uint16_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_V]);
1261*89a0ef05SAndroid Build Coastguard Worker if (yDataSrc == nullptr || uDataSrc == nullptr || yDataDst == nullptr || uDataDst == nullptr ||
1262*89a0ef05SAndroid Build Coastguard Worker vDataDst == nullptr) {
1263*89a0ef05SAndroid Build Coastguard Worker std::cerr << "invalid src or dst pointer for psnr computation " << std::endl;
1264*89a0ef05SAndroid Build Coastguard Worker return;
1265*89a0ef05SAndroid Build Coastguard Worker }
1266*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.ct != mDecodedUhdrYuv444Image.ct) {
1267*89a0ef05SAndroid Build Coastguard Worker std::cout << "input color transfer and output color transfer are not identical, yuv psnr "
1268*89a0ef05SAndroid Build Coastguard Worker "results may be unreliable"
1269*89a0ef05SAndroid Build Coastguard Worker << std::endl;
1270*89a0ef05SAndroid Build Coastguard Worker }
1271*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.cg != mDecodedUhdrYuv444Image.cg) {
1272*89a0ef05SAndroid Build Coastguard Worker std::cout << "input color gamut and output color gamut are not identical, yuv psnr results "
1273*89a0ef05SAndroid Build Coastguard Worker "may be unreliable"
1274*89a0ef05SAndroid Build Coastguard Worker << std::endl;
1275*89a0ef05SAndroid Build Coastguard Worker }
1276*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.range != mDecodedUhdrYuv444Image.range) {
1277*89a0ef05SAndroid Build Coastguard Worker std::cout << "input range and output range are not identical, yuv psnr results "
1278*89a0ef05SAndroid Build Coastguard Worker "may be unreliable"
1279*89a0ef05SAndroid Build Coastguard Worker << std::endl;
1280*89a0ef05SAndroid Build Coastguard Worker }
1281*89a0ef05SAndroid Build Coastguard Worker
1282*89a0ef05SAndroid Build Coastguard Worker uint64_t ySqError = 0, uSqError = 0, vSqError = 0;
1283*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < mDecodedUhdrYuv444Image.h; i++) {
1284*89a0ef05SAndroid Build Coastguard Worker for (size_t j = 0; j < mDecodedUhdrYuv444Image.w; j++) {
1285*89a0ef05SAndroid Build Coastguard Worker int ySrc = (yDataSrc[mRawP010Image.stride[UHDR_PLANE_Y] * i + j] >> 6) & 0x3ff;
1286*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.range == UHDR_CR_LIMITED_RANGE) ySrc = CLIP3(ySrc, 64, 940);
1287*89a0ef05SAndroid Build Coastguard Worker int yDst = yDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_Y] * i + j] & 0x3ff;
1288*89a0ef05SAndroid Build Coastguard Worker ySqError += (ySrc - yDst) * (ySrc - yDst);
1289*89a0ef05SAndroid Build Coastguard Worker
1290*89a0ef05SAndroid Build Coastguard Worker if (i % 2 == 0 && j % 2 == 0) {
1291*89a0ef05SAndroid Build Coastguard Worker int uSrc =
1292*89a0ef05SAndroid Build Coastguard Worker (uDataSrc[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6) & 0x3ff;
1293*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.range == UHDR_CR_LIMITED_RANGE) uSrc = CLIP3(uSrc, 64, 960);
1294*89a0ef05SAndroid Build Coastguard Worker int uDst = uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * i + j] & 0x3ff;
1295*89a0ef05SAndroid Build Coastguard Worker uDst += uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * i + j + 1] & 0x3ff;
1296*89a0ef05SAndroid Build Coastguard Worker uDst += uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * (i + 1) + j] & 0x3ff;
1297*89a0ef05SAndroid Build Coastguard Worker uDst += uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * (i + 1) + j + 1] & 0x3ff;
1298*89a0ef05SAndroid Build Coastguard Worker uDst = (uDst + 2) >> 2;
1299*89a0ef05SAndroid Build Coastguard Worker uSqError += (uSrc - uDst) * (uSrc - uDst);
1300*89a0ef05SAndroid Build Coastguard Worker
1301*89a0ef05SAndroid Build Coastguard Worker int vSrc =
1302*89a0ef05SAndroid Build Coastguard Worker (vDataSrc[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6) & 0x3ff;
1303*89a0ef05SAndroid Build Coastguard Worker if (mRawP010Image.range == UHDR_CR_LIMITED_RANGE) vSrc = CLIP3(vSrc, 64, 960);
1304*89a0ef05SAndroid Build Coastguard Worker int vDst = vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * i + j] & 0x3ff;
1305*89a0ef05SAndroid Build Coastguard Worker vDst += vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * i + j + 1] & 0x3ff;
1306*89a0ef05SAndroid Build Coastguard Worker vDst += vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * (i + 1) + j] & 0x3ff;
1307*89a0ef05SAndroid Build Coastguard Worker vDst += vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * (i + 1) + j + 1] & 0x3ff;
1308*89a0ef05SAndroid Build Coastguard Worker vDst = (vDst + 2) >> 2;
1309*89a0ef05SAndroid Build Coastguard Worker vSqError += (vSrc - vDst) * (vSrc - vDst);
1310*89a0ef05SAndroid Build Coastguard Worker }
1311*89a0ef05SAndroid Build Coastguard Worker }
1312*89a0ef05SAndroid Build Coastguard Worker }
1313*89a0ef05SAndroid Build Coastguard Worker
1314*89a0ef05SAndroid Build Coastguard Worker double meanSquareError =
1315*89a0ef05SAndroid Build Coastguard Worker (double)ySqError / ((size_t)mDecodedUhdrYuv444Image.w * mDecodedUhdrYuv444Image.h);
1316*89a0ef05SAndroid Build Coastguard Worker mPsnr[0] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
1317*89a0ef05SAndroid Build Coastguard Worker
1318*89a0ef05SAndroid Build Coastguard Worker meanSquareError =
1319*89a0ef05SAndroid Build Coastguard Worker (double)uSqError / ((size_t)mDecodedUhdrYuv444Image.w * mDecodedUhdrYuv444Image.h / 4);
1320*89a0ef05SAndroid Build Coastguard Worker mPsnr[1] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
1321*89a0ef05SAndroid Build Coastguard Worker
1322*89a0ef05SAndroid Build Coastguard Worker meanSquareError =
1323*89a0ef05SAndroid Build Coastguard Worker (double)vSqError / ((size_t)mDecodedUhdrYuv444Image.w * mDecodedUhdrYuv444Image.h / 4);
1324*89a0ef05SAndroid Build Coastguard Worker mPsnr[2] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
1325*89a0ef05SAndroid Build Coastguard Worker
1326*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr yuv: \t" << mPsnr[0] << " \t " << mPsnr[1] << " \t " << mPsnr[2] << std::endl;
1327*89a0ef05SAndroid Build Coastguard Worker }
1328*89a0ef05SAndroid Build Coastguard Worker
computeYUVSdrPSNR()1329*89a0ef05SAndroid Build Coastguard Worker void UltraHdrAppInput::computeYUVSdrPSNR() {
1330*89a0ef05SAndroid Build Coastguard Worker if (mOfmt != UHDR_IMG_FMT_32bppRGBA8888) {
1331*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr not supported for output format " << mOfmt << std::endl;
1332*89a0ef05SAndroid Build Coastguard Worker return;
1333*89a0ef05SAndroid Build Coastguard Worker }
1334*89a0ef05SAndroid Build Coastguard Worker
1335*89a0ef05SAndroid Build Coastguard Worker uint8_t* yDataSrc = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_Y]);
1336*89a0ef05SAndroid Build Coastguard Worker uint8_t* uDataSrc = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_U]);
1337*89a0ef05SAndroid Build Coastguard Worker uint8_t* vDataSrc = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_V]);
1338*89a0ef05SAndroid Build Coastguard Worker
1339*89a0ef05SAndroid Build Coastguard Worker uint8_t* yDataDst = static_cast<uint8_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_Y]);
1340*89a0ef05SAndroid Build Coastguard Worker uint8_t* uDataDst = static_cast<uint8_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_U]);
1341*89a0ef05SAndroid Build Coastguard Worker uint8_t* vDataDst = static_cast<uint8_t*>(mDecodedUhdrYuv444Image.planes[UHDR_PLANE_V]);
1342*89a0ef05SAndroid Build Coastguard Worker
1343*89a0ef05SAndroid Build Coastguard Worker uint64_t ySqError = 0, uSqError = 0, vSqError = 0;
1344*89a0ef05SAndroid Build Coastguard Worker for (size_t i = 0; i < mDecodedUhdrYuv444Image.h; i++) {
1345*89a0ef05SAndroid Build Coastguard Worker for (size_t j = 0; j < mDecodedUhdrYuv444Image.w; j++) {
1346*89a0ef05SAndroid Build Coastguard Worker int ySrc = yDataSrc[mRawYuv420Image.stride[UHDR_PLANE_Y] * i + j];
1347*89a0ef05SAndroid Build Coastguard Worker int yDst = yDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_Y] * i + j];
1348*89a0ef05SAndroid Build Coastguard Worker ySqError += (ySrc - yDst) * (ySrc - yDst);
1349*89a0ef05SAndroid Build Coastguard Worker
1350*89a0ef05SAndroid Build Coastguard Worker if (i % 2 == 0 && j % 2 == 0) {
1351*89a0ef05SAndroid Build Coastguard Worker int uSrc = uDataSrc[mRawYuv420Image.stride[UHDR_PLANE_U] * (i / 2) + j / 2];
1352*89a0ef05SAndroid Build Coastguard Worker int uDst = uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * i + j];
1353*89a0ef05SAndroid Build Coastguard Worker uDst += uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * i + j + 1];
1354*89a0ef05SAndroid Build Coastguard Worker uDst += uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * (i + 1) + j];
1355*89a0ef05SAndroid Build Coastguard Worker uDst += uDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_U] * (i + 1) + j + 1];
1356*89a0ef05SAndroid Build Coastguard Worker uDst = (uDst + 2) >> 2;
1357*89a0ef05SAndroid Build Coastguard Worker uSqError += (uSrc - uDst) * (uSrc - uDst);
1358*89a0ef05SAndroid Build Coastguard Worker
1359*89a0ef05SAndroid Build Coastguard Worker int vSrc = vDataSrc[mRawYuv420Image.stride[UHDR_PLANE_V] * (i / 2) + j / 2];
1360*89a0ef05SAndroid Build Coastguard Worker int vDst = vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * i + j];
1361*89a0ef05SAndroid Build Coastguard Worker vDst += vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * i + j + 1];
1362*89a0ef05SAndroid Build Coastguard Worker vDst += vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * (i + 1) + j];
1363*89a0ef05SAndroid Build Coastguard Worker vDst += vDataDst[mDecodedUhdrYuv444Image.stride[UHDR_PLANE_V] * (i + 1) + j + 1];
1364*89a0ef05SAndroid Build Coastguard Worker vDst = (vDst + 2) >> 2;
1365*89a0ef05SAndroid Build Coastguard Worker vSqError += (vSrc - vDst) * (vSrc - vDst);
1366*89a0ef05SAndroid Build Coastguard Worker }
1367*89a0ef05SAndroid Build Coastguard Worker }
1368*89a0ef05SAndroid Build Coastguard Worker }
1369*89a0ef05SAndroid Build Coastguard Worker double meanSquareError =
1370*89a0ef05SAndroid Build Coastguard Worker (double)ySqError / ((size_t)mDecodedUhdrYuv444Image.w * mDecodedUhdrYuv444Image.h);
1371*89a0ef05SAndroid Build Coastguard Worker mPsnr[0] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
1372*89a0ef05SAndroid Build Coastguard Worker
1373*89a0ef05SAndroid Build Coastguard Worker meanSquareError =
1374*89a0ef05SAndroid Build Coastguard Worker (double)uSqError / ((size_t)mDecodedUhdrYuv444Image.w * mDecodedUhdrYuv444Image.h / 4);
1375*89a0ef05SAndroid Build Coastguard Worker mPsnr[1] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
1376*89a0ef05SAndroid Build Coastguard Worker
1377*89a0ef05SAndroid Build Coastguard Worker meanSquareError =
1378*89a0ef05SAndroid Build Coastguard Worker (double)vSqError / ((size_t)mDecodedUhdrYuv444Image.w * mDecodedUhdrYuv444Image.h / 4);
1379*89a0ef05SAndroid Build Coastguard Worker mPsnr[2] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
1380*89a0ef05SAndroid Build Coastguard Worker
1381*89a0ef05SAndroid Build Coastguard Worker std::cout << "psnr yuv: \t" << mPsnr[0] << " \t " << mPsnr[1] << " \t " << mPsnr[2] << std::endl;
1382*89a0ef05SAndroid Build Coastguard Worker }
1383*89a0ef05SAndroid Build Coastguard Worker
usage(const char * name)1384*89a0ef05SAndroid Build Coastguard Worker static void usage(const char* name) {
1385*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## ultra hdr demo application. lib version: v%s \nUsage : %s \n",
1386*89a0ef05SAndroid Build Coastguard Worker UHDR_LIB_VERSION_STR, name);
1387*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " -m mode of operation. [0:encode, 1:decode] \n");
1388*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## encoder options : \n");
1389*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1390*89a0ef05SAndroid Build Coastguard Worker " -p raw hdr intent input resource (10-bit), required for encoding scenarios 0, 1, "
1391*89a0ef05SAndroid Build Coastguard Worker "2, 3. \n");
1392*89a0ef05SAndroid Build Coastguard Worker fprintf(
1393*89a0ef05SAndroid Build Coastguard Worker stderr,
1394*89a0ef05SAndroid Build Coastguard Worker " -y raw sdr intent input resource (8-bit), required for encoding scenarios 1, 2. \n");
1395*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1396*89a0ef05SAndroid Build Coastguard Worker " -a raw hdr intent color format, optional. [0:p010, 4: rgbahalffloat, "
1397*89a0ef05SAndroid Build Coastguard Worker "5:rgba1010102 (default)] \n");
1398*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1399*89a0ef05SAndroid Build Coastguard Worker " -b raw sdr intent color format, optional. [1:yuv420, 3:rgba8888 (default)] \n");
1400*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1401*89a0ef05SAndroid Build Coastguard Worker " -i compressed sdr intent input resource (jpeg), required for encoding scenarios "
1402*89a0ef05SAndroid Build Coastguard Worker "2, 3, 4. \n");
1403*89a0ef05SAndroid Build Coastguard Worker fprintf(
1404*89a0ef05SAndroid Build Coastguard Worker stderr,
1405*89a0ef05SAndroid Build Coastguard Worker " -g compressed gainmap input resource (jpeg), required for encoding scenario 4. \n");
1406*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " -w input file width, required for encoding scenarios 0, 1, 2, 3. \n");
1407*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " -h input file height, required for encoding scenarios 0, 1, 2, 3. \n");
1408*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1409*89a0ef05SAndroid Build Coastguard Worker " -C hdr intent color gamut, optional. [0:bt709, 1:p3 (default), 2:bt2100] \n");
1410*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1411*89a0ef05SAndroid Build Coastguard Worker " -c sdr intent color gamut, optional. [0:bt709 (default), 1:p3, 2:bt2100] \n");
1412*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1413*89a0ef05SAndroid Build Coastguard Worker " -t hdr intent color transfer, optional. [0:linear, 1:hlg (default), 2:pq] \n");
1414*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1415*89a0ef05SAndroid Build Coastguard Worker " It should be noted that not all combinations of input color format and input "
1416*89a0ef05SAndroid Build Coastguard Worker "color transfer are supported. \n"
1417*89a0ef05SAndroid Build Coastguard Worker " srgb color transfer shall be paired with rgba8888 or yuv420 only. \n"
1418*89a0ef05SAndroid Build Coastguard Worker " hlg, pq shall be paired with rgba1010102 or p010. \n"
1419*89a0ef05SAndroid Build Coastguard Worker " linear shall be paired with rgbahalffloat. \n");
1420*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1421*89a0ef05SAndroid Build Coastguard Worker " -q quality factor to be used while encoding sdr intent, optional. [0-100], 95 : "
1422*89a0ef05SAndroid Build Coastguard Worker "default.\n");
1423*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " -e compute psnr, optional. [0:no (default), 1:yes] \n");
1424*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1425*89a0ef05SAndroid Build Coastguard Worker " -R color range of hdr intent, optional. [0:narrow-range (default), "
1426*89a0ef05SAndroid Build Coastguard Worker "1:full-range]. \n");
1427*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1428*89a0ef05SAndroid Build Coastguard Worker " -s gainmap image downsample factor, optional. [integer values in range [1 - 128] "
1429*89a0ef05SAndroid Build Coastguard Worker "(1 : default)]. \n");
1430*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1431*89a0ef05SAndroid Build Coastguard Worker " -Q quality factor to be used while encoding gain map image, optional. [0-100], "
1432*89a0ef05SAndroid Build Coastguard Worker "95 : default. \n");
1433*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1434*89a0ef05SAndroid Build Coastguard Worker " -G gamma correction to be applied on the gainmap image, optional. [any positive "
1435*89a0ef05SAndroid Build Coastguard Worker "real number (1.0 : default)].\n");
1436*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1437*89a0ef05SAndroid Build Coastguard Worker " -M select multi channel gain map, optional. [0:disable, 1:enable (default)]. \n");
1438*89a0ef05SAndroid Build Coastguard Worker fprintf(
1439*89a0ef05SAndroid Build Coastguard Worker stderr,
1440*89a0ef05SAndroid Build Coastguard Worker " -D select encoding preset, optional. [0:real time, 1:best quality (default)]. \n");
1441*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1442*89a0ef05SAndroid Build Coastguard Worker " -k min content boost recommendation, must be in linear scale, optional. [any "
1443*89a0ef05SAndroid Build Coastguard Worker "positive real number] \n");
1444*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1445*89a0ef05SAndroid Build Coastguard Worker " -K max content boost recommendation, must be in linear scale, optional.[any "
1446*89a0ef05SAndroid Build Coastguard Worker "positive real number] \n");
1447*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1448*89a0ef05SAndroid Build Coastguard Worker " -L set target display peak brightness in nits, optional. \n"
1449*89a0ef05SAndroid Build Coastguard Worker " For HLG content, this defaults to 1000 nits. \n"
1450*89a0ef05SAndroid Build Coastguard Worker " For PQ content, this defaults to 10000 nits. \n"
1451*89a0ef05SAndroid Build Coastguard Worker " any real number in range [203, 10000]. \n");
1452*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " -x binary input resource containing exif data to insert, optional. \n");
1453*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## decoder options : \n");
1454*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " -j ultra hdr compressed input resource, required. \n");
1455*89a0ef05SAndroid Build Coastguard Worker fprintf(
1456*89a0ef05SAndroid Build Coastguard Worker stderr,
1457*89a0ef05SAndroid Build Coastguard Worker " -o output transfer function, optional. [0:linear, 1:hlg (default), 2:pq, 3:srgb] \n");
1458*89a0ef05SAndroid Build Coastguard Worker fprintf(
1459*89a0ef05SAndroid Build Coastguard Worker stderr,
1460*89a0ef05SAndroid Build Coastguard Worker " -O output color format, optional. [3:rgba8888, 4:rgbahalffloat, 5:rgba1010102 "
1461*89a0ef05SAndroid Build Coastguard Worker "(default)] \n"
1462*89a0ef05SAndroid Build Coastguard Worker " It should be noted that not all combinations of output color format and output \n"
1463*89a0ef05SAndroid Build Coastguard Worker " transfer function are supported. \n"
1464*89a0ef05SAndroid Build Coastguard Worker " srgb output color transfer shall be paired with rgba8888 only. \n"
1465*89a0ef05SAndroid Build Coastguard Worker " hlg, pq shall be paired with rgba1010102. \n"
1466*89a0ef05SAndroid Build Coastguard Worker " linear shall be paired with rgbahalffloat. \n");
1467*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1468*89a0ef05SAndroid Build Coastguard Worker " -u enable gles acceleration, optional. [0:disable (default), 1:enable]. \n");
1469*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## common options : \n");
1470*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1471*89a0ef05SAndroid Build Coastguard Worker " -z output filename, optional. \n"
1472*89a0ef05SAndroid Build Coastguard Worker " in encoding mode, default output filename 'out.jpeg'. \n"
1473*89a0ef05SAndroid Build Coastguard Worker " in decoding mode, default output filename 'outrgb.raw'. \n");
1474*89a0ef05SAndroid Build Coastguard Worker fprintf(
1475*89a0ef05SAndroid Build Coastguard Worker stderr,
1476*89a0ef05SAndroid Build Coastguard Worker " -f gainmap metadata config file. \n"
1477*89a0ef05SAndroid Build Coastguard Worker " in encoding mode, resource from which gainmap metadata is read, required for "
1478*89a0ef05SAndroid Build Coastguard Worker "encoding scenario 4. \n"
1479*89a0ef05SAndroid Build Coastguard Worker " in decoding mode, resource to which gainmap metadata is written, optional. \n");
1480*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## examples of usage :\n");
1481*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## encode scenario 0 :\n");
1482*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1483*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -w 1920 -h 1080 -q 97 -a 0\n");
1484*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1485*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -w 1920 -h 1080 -q 97 -a 5\n");
1486*89a0ef05SAndroid Build Coastguard Worker fprintf(
1487*89a0ef05SAndroid Build Coastguard Worker stderr,
1488*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -w 1920 -h 1080 -q 97 -C 1 -t 2 -a 0\n");
1489*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1490*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -w 1920 -h 1080 -q 97 -C 1 "
1491*89a0ef05SAndroid Build Coastguard Worker "-t 2 -a 5\n");
1492*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## encode scenario 1 :\n");
1493*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1494*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 "
1495*89a0ef05SAndroid Build Coastguard Worker "-h 1080 -q 97 -a 0 -b 1\n");
1496*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1497*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw "
1498*89a0ef05SAndroid Build Coastguard Worker "-y cosmat_1920x1080_rgba8888.raw -w 1920 -h 1080 -q 97 -a 5 -b 3\n");
1499*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1500*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 "
1501*89a0ef05SAndroid Build Coastguard Worker "-h 1080 -q 97 -C 2 -c 1 -t 1 -a 0 -b 1\n");
1502*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1503*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw "
1504*89a0ef05SAndroid Build Coastguard Worker "-y cosmat_1920x1080_rgba8888.raw -w 1920 -h 1080 -q 97 -C 2 -c 1 -t 1 -a 5 -b 3\n");
1505*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1506*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 "
1507*89a0ef05SAndroid Build Coastguard Worker "-h 1080 -q 97 -C 2 -c 1 -t 1 -e 1 -a 0 -b 1\n");
1508*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## encode scenario 2 :\n");
1509*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1510*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -i "
1511*89a0ef05SAndroid Build Coastguard Worker "cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 3 -O 3 -e 1 -a 0 -b 1\n");
1512*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1513*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -y cosmat_1920x1080_420.yuv "
1514*89a0ef05SAndroid Build Coastguard Worker "-i cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 3 -O 3 -e 1 -a 5 -b 1\n");
1515*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## encode scenario 3 :\n");
1516*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1517*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -i cosmat_1920x1080_420_8bit.jpg -w "
1518*89a0ef05SAndroid Build Coastguard Worker "1920 -h 1080 -t 1 -o 1 -O 5 -e 1 -a 0\n");
1519*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1520*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw "
1521*89a0ef05SAndroid Build Coastguard Worker "-i cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 1 -O 5 -e 1 -a 5\n");
1522*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## encode scenario 4 :\n");
1523*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1524*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -i cosmat_1920x1080_420_8bit.jpg -g cosmat_1920x1080_420_8bit.jpg "
1525*89a0ef05SAndroid Build Coastguard Worker "-f metadata.cfg\n");
1526*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## encode at high quality :\n");
1527*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr,
1528*89a0ef05SAndroid Build Coastguard Worker " ultrahdr_app -m 0 -p hdr_intent.raw -y sdr_intent.raw -w 640 -h 480 -c <select> -C "
1529*89a0ef05SAndroid Build Coastguard Worker "<select> -t <select> -s 1 -M 1 -Q 98 -q 98 -D 1\n");
1530*89a0ef05SAndroid Build Coastguard Worker
1531*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n## decode api :\n");
1532*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg \n");
1533*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg -o 3 -O 3\n");
1534*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg -o 1 -O 5\n");
1535*89a0ef05SAndroid Build Coastguard Worker fprintf(stderr, "\n");
1536*89a0ef05SAndroid Build Coastguard Worker }
1537*89a0ef05SAndroid Build Coastguard Worker
main(int argc,char * argv[])1538*89a0ef05SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
1539*89a0ef05SAndroid Build Coastguard Worker 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:k:K:L:";
1540*89a0ef05SAndroid Build Coastguard Worker char *hdr_intent_raw_file = nullptr, *sdr_intent_raw_file = nullptr, *uhdr_file = nullptr,
1541*89a0ef05SAndroid Build Coastguard Worker *sdr_intent_compressed_file = nullptr, *gainmap_compressed_file = nullptr,
1542*89a0ef05SAndroid Build Coastguard Worker *gainmap_metadata_cfg_file = nullptr, *output_file = nullptr, *exif_file = nullptr;
1543*89a0ef05SAndroid Build Coastguard Worker int width = 0, height = 0;
1544*89a0ef05SAndroid Build Coastguard Worker uhdr_color_gamut_t hdr_cg = UHDR_CG_DISPLAY_P3;
1545*89a0ef05SAndroid Build Coastguard Worker uhdr_color_gamut_t sdr_cg = UHDR_CG_BT_709;
1546*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t hdr_cf = UHDR_IMG_FMT_32bppRGBA1010102;
1547*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t sdr_cf = UHDR_IMG_FMT_32bppRGBA8888;
1548*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t hdr_tf = UHDR_CT_HLG;
1549*89a0ef05SAndroid Build Coastguard Worker int quality = 95;
1550*89a0ef05SAndroid Build Coastguard Worker uhdr_color_transfer_t out_tf = UHDR_CT_HLG;
1551*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t out_cf = UHDR_IMG_FMT_32bppRGBA1010102;
1552*89a0ef05SAndroid Build Coastguard Worker int mode = -1;
1553*89a0ef05SAndroid Build Coastguard Worker int gainmap_scale_factor = 1;
1554*89a0ef05SAndroid Build Coastguard Worker bool use_multi_channel_gainmap = true;
1555*89a0ef05SAndroid Build Coastguard Worker bool use_full_range_color_hdr = false;
1556*89a0ef05SAndroid Build Coastguard Worker int gainmap_compression_quality = 95;
1557*89a0ef05SAndroid Build Coastguard Worker int compute_psnr = 0;
1558*89a0ef05SAndroid Build Coastguard Worker float gamma = 1.0f;
1559*89a0ef05SAndroid Build Coastguard Worker bool enable_gles = false;
1560*89a0ef05SAndroid Build Coastguard Worker uhdr_enc_preset_t enc_preset = UHDR_USAGE_BEST_QUALITY;
1561*89a0ef05SAndroid Build Coastguard Worker float min_content_boost = FLT_MIN;
1562*89a0ef05SAndroid Build Coastguard Worker float max_content_boost = FLT_MAX;
1563*89a0ef05SAndroid Build Coastguard Worker float target_disp_peak_brightness = -1.0f;
1564*89a0ef05SAndroid Build Coastguard Worker int ch;
1565*89a0ef05SAndroid Build Coastguard Worker while ((ch = getopt_s(argc, argv, opt_string)) != -1) {
1566*89a0ef05SAndroid Build Coastguard Worker switch (ch) {
1567*89a0ef05SAndroid Build Coastguard Worker case 'a':
1568*89a0ef05SAndroid Build Coastguard Worker hdr_cf = static_cast<uhdr_img_fmt_t>(atoi(optarg_s));
1569*89a0ef05SAndroid Build Coastguard Worker break;
1570*89a0ef05SAndroid Build Coastguard Worker case 'b':
1571*89a0ef05SAndroid Build Coastguard Worker sdr_cf = static_cast<uhdr_img_fmt_t>(atoi(optarg_s));
1572*89a0ef05SAndroid Build Coastguard Worker break;
1573*89a0ef05SAndroid Build Coastguard Worker case 'p':
1574*89a0ef05SAndroid Build Coastguard Worker hdr_intent_raw_file = optarg_s;
1575*89a0ef05SAndroid Build Coastguard Worker break;
1576*89a0ef05SAndroid Build Coastguard Worker case 'y':
1577*89a0ef05SAndroid Build Coastguard Worker sdr_intent_raw_file = optarg_s;
1578*89a0ef05SAndroid Build Coastguard Worker break;
1579*89a0ef05SAndroid Build Coastguard Worker case 'i':
1580*89a0ef05SAndroid Build Coastguard Worker sdr_intent_compressed_file = optarg_s;
1581*89a0ef05SAndroid Build Coastguard Worker break;
1582*89a0ef05SAndroid Build Coastguard Worker case 'g':
1583*89a0ef05SAndroid Build Coastguard Worker gainmap_compressed_file = optarg_s;
1584*89a0ef05SAndroid Build Coastguard Worker break;
1585*89a0ef05SAndroid Build Coastguard Worker case 'f':
1586*89a0ef05SAndroid Build Coastguard Worker gainmap_metadata_cfg_file = optarg_s;
1587*89a0ef05SAndroid Build Coastguard Worker break;
1588*89a0ef05SAndroid Build Coastguard Worker case 'w':
1589*89a0ef05SAndroid Build Coastguard Worker width = atoi(optarg_s);
1590*89a0ef05SAndroid Build Coastguard Worker break;
1591*89a0ef05SAndroid Build Coastguard Worker case 'h':
1592*89a0ef05SAndroid Build Coastguard Worker height = atoi(optarg_s);
1593*89a0ef05SAndroid Build Coastguard Worker break;
1594*89a0ef05SAndroid Build Coastguard Worker case 'C':
1595*89a0ef05SAndroid Build Coastguard Worker hdr_cg = static_cast<uhdr_color_gamut_t>(atoi(optarg_s));
1596*89a0ef05SAndroid Build Coastguard Worker break;
1597*89a0ef05SAndroid Build Coastguard Worker case 'c':
1598*89a0ef05SAndroid Build Coastguard Worker sdr_cg = static_cast<uhdr_color_gamut_t>(atoi(optarg_s));
1599*89a0ef05SAndroid Build Coastguard Worker break;
1600*89a0ef05SAndroid Build Coastguard Worker case 't':
1601*89a0ef05SAndroid Build Coastguard Worker hdr_tf = static_cast<uhdr_color_transfer_t>(atoi(optarg_s));
1602*89a0ef05SAndroid Build Coastguard Worker break;
1603*89a0ef05SAndroid Build Coastguard Worker case 'q':
1604*89a0ef05SAndroid Build Coastguard Worker quality = atoi(optarg_s);
1605*89a0ef05SAndroid Build Coastguard Worker break;
1606*89a0ef05SAndroid Build Coastguard Worker case 'O':
1607*89a0ef05SAndroid Build Coastguard Worker out_cf = static_cast<uhdr_img_fmt_t>(atoi(optarg_s));
1608*89a0ef05SAndroid Build Coastguard Worker break;
1609*89a0ef05SAndroid Build Coastguard Worker case 'o':
1610*89a0ef05SAndroid Build Coastguard Worker out_tf = static_cast<uhdr_color_transfer_t>(atoi(optarg_s));
1611*89a0ef05SAndroid Build Coastguard Worker break;
1612*89a0ef05SAndroid Build Coastguard Worker case 'm':
1613*89a0ef05SAndroid Build Coastguard Worker mode = atoi(optarg_s);
1614*89a0ef05SAndroid Build Coastguard Worker break;
1615*89a0ef05SAndroid Build Coastguard Worker case 'R':
1616*89a0ef05SAndroid Build Coastguard Worker use_full_range_color_hdr = atoi(optarg_s) == 1 ? true : false;
1617*89a0ef05SAndroid Build Coastguard Worker break;
1618*89a0ef05SAndroid Build Coastguard Worker // TODO
1619*89a0ef05SAndroid Build Coastguard Worker /*case 'r':
1620*89a0ef05SAndroid Build Coastguard Worker use_full_range_color_sdr = atoi(optarg_s) == 1 ? true : false;
1621*89a0ef05SAndroid Build Coastguard Worker break;*/
1622*89a0ef05SAndroid Build Coastguard Worker case 's':
1623*89a0ef05SAndroid Build Coastguard Worker gainmap_scale_factor = atoi(optarg_s);
1624*89a0ef05SAndroid Build Coastguard Worker break;
1625*89a0ef05SAndroid Build Coastguard Worker case 'M':
1626*89a0ef05SAndroid Build Coastguard Worker use_multi_channel_gainmap = atoi(optarg_s) == 1 ? true : false;
1627*89a0ef05SAndroid Build Coastguard Worker break;
1628*89a0ef05SAndroid Build Coastguard Worker case 'Q':
1629*89a0ef05SAndroid Build Coastguard Worker gainmap_compression_quality = atoi(optarg_s);
1630*89a0ef05SAndroid Build Coastguard Worker break;
1631*89a0ef05SAndroid Build Coastguard Worker case 'G':
1632*89a0ef05SAndroid Build Coastguard Worker gamma = (float)atof(optarg_s);
1633*89a0ef05SAndroid Build Coastguard Worker break;
1634*89a0ef05SAndroid Build Coastguard Worker case 'j':
1635*89a0ef05SAndroid Build Coastguard Worker uhdr_file = optarg_s;
1636*89a0ef05SAndroid Build Coastguard Worker break;
1637*89a0ef05SAndroid Build Coastguard Worker case 'e':
1638*89a0ef05SAndroid Build Coastguard Worker compute_psnr = atoi(optarg_s);
1639*89a0ef05SAndroid Build Coastguard Worker break;
1640*89a0ef05SAndroid Build Coastguard Worker case 'z':
1641*89a0ef05SAndroid Build Coastguard Worker output_file = optarg_s;
1642*89a0ef05SAndroid Build Coastguard Worker break;
1643*89a0ef05SAndroid Build Coastguard Worker case 'x':
1644*89a0ef05SAndroid Build Coastguard Worker exif_file = optarg_s;
1645*89a0ef05SAndroid Build Coastguard Worker break;
1646*89a0ef05SAndroid Build Coastguard Worker case 'u':
1647*89a0ef05SAndroid Build Coastguard Worker enable_gles = atoi(optarg_s) == 1 ? true : false;
1648*89a0ef05SAndroid Build Coastguard Worker break;
1649*89a0ef05SAndroid Build Coastguard Worker case 'D':
1650*89a0ef05SAndroid Build Coastguard Worker enc_preset = static_cast<uhdr_enc_preset_t>(atoi(optarg_s));
1651*89a0ef05SAndroid Build Coastguard Worker break;
1652*89a0ef05SAndroid Build Coastguard Worker case 'k':
1653*89a0ef05SAndroid Build Coastguard Worker min_content_boost = (float)atof(optarg_s);
1654*89a0ef05SAndroid Build Coastguard Worker break;
1655*89a0ef05SAndroid Build Coastguard Worker case 'K':
1656*89a0ef05SAndroid Build Coastguard Worker max_content_boost = (float)atof(optarg_s);
1657*89a0ef05SAndroid Build Coastguard Worker break;
1658*89a0ef05SAndroid Build Coastguard Worker case 'L':
1659*89a0ef05SAndroid Build Coastguard Worker target_disp_peak_brightness = (float)atof(optarg_s);
1660*89a0ef05SAndroid Build Coastguard Worker break;
1661*89a0ef05SAndroid Build Coastguard Worker default:
1662*89a0ef05SAndroid Build Coastguard Worker usage(argv[0]);
1663*89a0ef05SAndroid Build Coastguard Worker return -1;
1664*89a0ef05SAndroid Build Coastguard Worker }
1665*89a0ef05SAndroid Build Coastguard Worker }
1666*89a0ef05SAndroid Build Coastguard Worker if (mode == 0) {
1667*89a0ef05SAndroid Build Coastguard Worker if (width <= 0 && gainmap_metadata_cfg_file == nullptr) {
1668*89a0ef05SAndroid Build Coastguard Worker std::cerr << "did not receive valid image width for encoding. width : " << width
1669*89a0ef05SAndroid Build Coastguard Worker << std::endl;
1670*89a0ef05SAndroid Build Coastguard Worker return -1;
1671*89a0ef05SAndroid Build Coastguard Worker }
1672*89a0ef05SAndroid Build Coastguard Worker if (height <= 0 && gainmap_metadata_cfg_file == nullptr) {
1673*89a0ef05SAndroid Build Coastguard Worker std::cerr << "did not receive valid image height for encoding. height : " << height
1674*89a0ef05SAndroid Build Coastguard Worker << std::endl;
1675*89a0ef05SAndroid Build Coastguard Worker return -1;
1676*89a0ef05SAndroid Build Coastguard Worker }
1677*89a0ef05SAndroid Build Coastguard Worker if (hdr_intent_raw_file == nullptr &&
1678*89a0ef05SAndroid Build Coastguard Worker (sdr_intent_compressed_file == nullptr || gainmap_compressed_file == nullptr ||
1679*89a0ef05SAndroid Build Coastguard Worker gainmap_metadata_cfg_file == nullptr)) {
1680*89a0ef05SAndroid Build Coastguard Worker std::cerr << "did not receive raw resources for encoding." << std::endl;
1681*89a0ef05SAndroid Build Coastguard Worker return -1;
1682*89a0ef05SAndroid Build Coastguard Worker }
1683*89a0ef05SAndroid Build Coastguard Worker UltraHdrAppInput appInput(
1684*89a0ef05SAndroid Build Coastguard Worker hdr_intent_raw_file, sdr_intent_raw_file, sdr_intent_compressed_file,
1685*89a0ef05SAndroid Build Coastguard Worker gainmap_compressed_file, gainmap_metadata_cfg_file, exif_file,
1686*89a0ef05SAndroid Build Coastguard Worker output_file ? output_file : "out.jpeg", width, height, hdr_cf, sdr_cf, hdr_cg, sdr_cg,
1687*89a0ef05SAndroid Build Coastguard Worker hdr_tf, quality, out_tf, out_cf, use_full_range_color_hdr, gainmap_scale_factor,
1688*89a0ef05SAndroid Build Coastguard Worker gainmap_compression_quality, use_multi_channel_gainmap, gamma, enable_gles, enc_preset,
1689*89a0ef05SAndroid Build Coastguard Worker min_content_boost, max_content_boost, target_disp_peak_brightness);
1690*89a0ef05SAndroid Build Coastguard Worker if (!appInput.encode()) return -1;
1691*89a0ef05SAndroid Build Coastguard Worker if (compute_psnr == 1) {
1692*89a0ef05SAndroid Build Coastguard Worker if (!appInput.decode()) return -1;
1693*89a0ef05SAndroid Build Coastguard Worker if (out_cf == UHDR_IMG_FMT_32bppRGBA8888 && sdr_intent_raw_file != nullptr) {
1694*89a0ef05SAndroid Build Coastguard Worker if (sdr_cf == UHDR_IMG_FMT_12bppYCbCr420) {
1695*89a0ef05SAndroid Build Coastguard Worker appInput.convertYuv420ToRGBImage();
1696*89a0ef05SAndroid Build Coastguard Worker }
1697*89a0ef05SAndroid Build Coastguard Worker appInput.computeRGBSdrPSNR();
1698*89a0ef05SAndroid Build Coastguard Worker if (sdr_cf == UHDR_IMG_FMT_12bppYCbCr420) {
1699*89a0ef05SAndroid Build Coastguard Worker appInput.convertRgba8888ToYUV444Image();
1700*89a0ef05SAndroid Build Coastguard Worker appInput.computeYUVSdrPSNR();
1701*89a0ef05SAndroid Build Coastguard Worker }
1702*89a0ef05SAndroid Build Coastguard Worker } else if (out_cf == UHDR_IMG_FMT_32bppRGBA1010102 && hdr_intent_raw_file != nullptr &&
1703*89a0ef05SAndroid Build Coastguard Worker hdr_cf != UHDR_IMG_FMT_64bppRGBAHalfFloat) {
1704*89a0ef05SAndroid Build Coastguard Worker if (hdr_cf == UHDR_IMG_FMT_24bppYCbCrP010) {
1705*89a0ef05SAndroid Build Coastguard Worker appInput.convertP010ToRGBImage();
1706*89a0ef05SAndroid Build Coastguard Worker }
1707*89a0ef05SAndroid Build Coastguard Worker appInput.computeRGBHdrPSNR();
1708*89a0ef05SAndroid Build Coastguard Worker if (hdr_cf == UHDR_IMG_FMT_24bppYCbCrP010) {
1709*89a0ef05SAndroid Build Coastguard Worker appInput.convertRgba1010102ToYUV444Image();
1710*89a0ef05SAndroid Build Coastguard Worker appInput.computeYUVHdrPSNR();
1711*89a0ef05SAndroid Build Coastguard Worker }
1712*89a0ef05SAndroid Build Coastguard Worker } else {
1713*89a0ef05SAndroid Build Coastguard Worker std::cerr << "failed to compute psnr " << std::endl;
1714*89a0ef05SAndroid Build Coastguard Worker }
1715*89a0ef05SAndroid Build Coastguard Worker }
1716*89a0ef05SAndroid Build Coastguard Worker } else if (mode == 1) {
1717*89a0ef05SAndroid Build Coastguard Worker if (uhdr_file == nullptr) {
1718*89a0ef05SAndroid Build Coastguard Worker std::cerr << "did not receive resources for decoding " << std::endl;
1719*89a0ef05SAndroid Build Coastguard Worker return -1;
1720*89a0ef05SAndroid Build Coastguard Worker }
1721*89a0ef05SAndroid Build Coastguard Worker UltraHdrAppInput appInput(gainmap_metadata_cfg_file, uhdr_file,
1722*89a0ef05SAndroid Build Coastguard Worker output_file ? output_file : "outrgb.raw", out_tf, out_cf,
1723*89a0ef05SAndroid Build Coastguard Worker enable_gles);
1724*89a0ef05SAndroid Build Coastguard Worker if (!appInput.decode()) return -1;
1725*89a0ef05SAndroid Build Coastguard Worker } else {
1726*89a0ef05SAndroid Build Coastguard Worker if (argc > 1) std::cerr << "did not receive valid mode of operation " << mode << std::endl;
1727*89a0ef05SAndroid Build Coastguard Worker usage(argv[0]);
1728*89a0ef05SAndroid Build Coastguard Worker return -1;
1729*89a0ef05SAndroid Build Coastguard Worker }
1730*89a0ef05SAndroid Build Coastguard Worker
1731*89a0ef05SAndroid Build Coastguard Worker return 0;
1732*89a0ef05SAndroid Build Coastguard Worker }
1733