1 /*
2 * Copyright 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <fstream>
18 #include <iostream>
19
20 #include <benchmark/benchmark.h>
21
22 #include "ultrahdr/jpegrutils.h"
23
24 using namespace ultrahdr;
25
26 #ifdef __ANDROID__
27 std::string kTestImagesPath = "/sdcard/test/UltrahdrBenchmarkTestRes-1.0/";
28 #else
29 std::string kTestImagesPath = "./data/UltrahdrBenchmarkTestRes-1.0/";
30 #endif
31
32 std::vector<std::string> kDecodeAPITestImages{
33 // 12mp test vectors
34 "mountains.jpg",
35 "mountain_lake.jpg",
36 "desert_wanda.jpg",
37 // 3mp test vectors
38 "mountains_3mp.jpg",
39 "mountain_lake_3mp.jpg",
40 "desert_wanda_3mp.jpg",
41 };
42
43 std::vector<std::string> kEncodeApi0TestImages12MpName{
44 // 12mp test vectors
45 "mountains.p010",
46 "mountain_lake.p010",
47 };
48
49 std::vector<std::string> kEncodeApi0TestImages3MpName{
50 // 3mp test vectors
51 "mountains_3mp.p010",
52 "mountain_lake_3mp.p010",
53 };
54
55 std::vector<std::pair<std::string, std::string>> kEncodeApi1TestImages12MpName{
56 // 12mp test vectors
57 {"mountains.p010", "mountains.yuv"},
58 {"mountain_lake.p010", "mountain_lake.yuv"},
59 };
60
61 std::vector<std::pair<std::string, std::string>> kEncodeApi1TestImages3MpName{
62 // 3mp test vectors
63 {"mountains_3mp.p010", "mountains_3mp.yuv"},
64 {"mountain_lake_3mp.p010", "mountain_lake_3mp.yuv"},
65 };
66
67 std::vector<std::tuple<std::string, std::string, std::string>> kEncodeApi2TestImages12MpName{
68 // 12mp test vectors
69 {"mountains.p010", "mountains.yuv", "mountains.jpg"},
70 {"mountain_lake.p010", "mountain_lake.yuv", "mountain_lake.jpg"},
71 };
72
73 std::vector<std::tuple<std::string, std::string, std::string>> kEncodeApi2TestImages3MpName{
74 // 3mp test vectors
75 {"mountains_3mp.p010", "mountains_3mp.yuv", "mountains_3mp.jpg"},
76 {"mountain_lake_3mp.p010", "mountain_lake_3mp.yuv", "mountain_lake_3mp.jpg"},
77 };
78
79 std::vector<std::pair<std::string, std::string>> kEncodeApi3TestImages12MpName{
80 // 12mp test vectors
81 {"mountains.p010", "mountains.jpg"},
82 {"mountain_lake.p010", "mountain_lake.jpg"},
83 };
84
85 std::vector<std::pair<std::string, std::string>> kEncodeApi3TestImages3MpName{
86 // 3mp test vectors
87 {"mountains_3mp.p010", "mountains_3mp.jpg"},
88 {"mountain_lake_3mp.p010", "mountain_lake_3mp.jpg"},
89 };
90
91 std::vector<std::string> kEncodeApi4TestImages12MpName{
92 // 12mp test vectors
93 "mountains.jpg",
94 "mountain_lake.jpg",
95 "desert_wanda.jpg",
96 };
97
98 std::vector<std::string> kEncodeApi4TestImages3MpName{
99 // 3mp test vectors
100 "mountains_3mp.jpg",
101 "mountain_lake_3mp.jpg",
102 "desert_wanda_3mp.jpg",
103 };
104
ofToString(const ultrahdr_output_format of)105 std::string ofToString(const ultrahdr_output_format of) {
106 switch (of) {
107 case ULTRAHDR_OUTPUT_SDR:
108 return "sdr";
109 case ULTRAHDR_OUTPUT_HDR_LINEAR:
110 return "hdr linear";
111 case ULTRAHDR_OUTPUT_HDR_PQ:
112 return "hdr pq";
113 case ULTRAHDR_OUTPUT_HDR_HLG:
114 return "hdr hlg";
115 default:
116 return "Unknown";
117 }
118 }
119
colorGamutToString(const ultrahdr_color_gamut cg)120 std::string colorGamutToString(const ultrahdr_color_gamut cg) {
121 switch (cg) {
122 case ULTRAHDR_COLORGAMUT_BT709:
123 return "bt709";
124 case ULTRAHDR_COLORGAMUT_P3:
125 return "p3";
126 case ULTRAHDR_COLORGAMUT_BT2100:
127 return "bt2100";
128 default:
129 return "Unknown";
130 }
131 }
132
tfToString(const ultrahdr_transfer_function of)133 std::string tfToString(const ultrahdr_transfer_function of) {
134 switch (of) {
135 case ULTRAHDR_TF_LINEAR:
136 return "linear";
137 case ULTRAHDR_TF_HLG:
138 return "hlg";
139 case ULTRAHDR_TF_PQ:
140 return "pq";
141 case ULTRAHDR_TF_SRGB:
142 return "srgb";
143 default:
144 return "Unknown";
145 }
146 }
147
loadFile(const char * filename,void * & result,int length)148 static bool loadFile(const char* filename, void*& result, int length) {
149 std::ifstream ifd(filename, std::ios::binary | std::ios::ate);
150 if (ifd.good()) {
151 int size = ifd.tellg();
152 if (size < length) {
153 std::cerr << "requested to read " << length << " bytes from file : " << filename
154 << ", file contains only " << size << " bytes" << std::endl;
155 return false;
156 }
157 ifd.seekg(0, std::ios::beg);
158 result = new uint8_t[length];
159 if (result == nullptr) {
160 std::cerr << "failed to allocate memory to store contents of file : " << filename
161 << std::endl;
162 return false;
163 }
164 ifd.read(static_cast<char*>(result), length);
165 return true;
166 }
167 std::cerr << "unable to open file : " << filename << std::endl;
168 return false;
169 }
170
fillRawImageHandle(jpegr_uncompressed_struct * rawImage,int width,int height,std::string file,ultrahdr_color_gamut cg,bool isP010)171 bool fillRawImageHandle(jpegr_uncompressed_struct* rawImage, int width, int height,
172 std::string file, ultrahdr_color_gamut cg, bool isP010) {
173 const int bpp = isP010 ? 2 : 1;
174 int imgSize = width * height * bpp * 1.5;
175 rawImage->width = width;
176 rawImage->height = height;
177 rawImage->colorGamut = cg;
178 return loadFile(file.c_str(), rawImage->data, imgSize);
179 }
180
fillJpgImageHandle(jpegr_compressed_struct * jpgImg,std::string file,ultrahdr_color_gamut colorGamut)181 bool fillJpgImageHandle(jpegr_compressed_struct* jpgImg, std::string file,
182 ultrahdr_color_gamut colorGamut) {
183 std::ifstream ifd(file.c_str(), std::ios::binary | std::ios::ate);
184 if (!ifd.good()) {
185 return false;
186 }
187 int size = ifd.tellg();
188 jpgImg->length = size;
189 jpgImg->maxLength = size;
190 jpgImg->data = nullptr;
191 jpgImg->colorGamut = colorGamut;
192 ifd.close();
193 return loadFile(file.c_str(), jpgImg->data, size);
194 }
195
BM_Decode(benchmark::State & s)196 static void BM_Decode(benchmark::State& s) {
197 std::string srcFileName = kTestImagesPath + "jpegr/" + kDecodeAPITestImages[s.range(0)];
198 ultrahdr_output_format of = static_cast<ultrahdr_output_format>(s.range(1));
199
200 std::ifstream ifd(srcFileName.c_str(), std::ios::binary | std::ios::ate);
201 if (!ifd.good()) {
202 s.SkipWithError("unable to open file " + srcFileName);
203 return;
204 }
205 int size = ifd.tellg();
206
207 jpegr_compressed_struct jpegImgR{};
208 jpegImgR.length = size;
209 jpegImgR.maxLength = size;
210 jpegImgR.data = nullptr;
211 jpegImgR.colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
212 ifd.close();
213 if (!loadFile(srcFileName.c_str(), jpegImgR.data, size)) {
214 s.SkipWithError("unable to load file " + srcFileName);
215 return;
216 }
217
218 std::unique_ptr<uint8_t[]> compData;
219 compData.reset(reinterpret_cast<uint8_t*>(jpegImgR.data));
220
221 JpegR jpegHdr;
222 jpegr_info_struct info{};
223 status_t status = jpegHdr.getJPEGRInfo(&jpegImgR, &info);
224 if (JPEGR_NO_ERROR != status) {
225 s.SkipWithError("getJPEGRInfo returned with error " + std::to_string(status));
226 return;
227 }
228
229 size_t outSize = info.width * info.height * ((of == ULTRAHDR_OUTPUT_HDR_LINEAR) ? 8 : 4);
230 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(outSize);
231 jpegr_uncompressed_struct destImage{};
232 destImage.data = data.get();
233 for (auto _ : s) {
234 status = jpegHdr.decodeJPEGR(&jpegImgR, &destImage, FLT_MAX, nullptr, of);
235 if (JPEGR_NO_ERROR != status) {
236 s.SkipWithError("decodeJPEGR returned with error " + std::to_string(status));
237 return;
238 }
239 }
240 if (info.width != destImage.width || info.height != destImage.height) {
241 s.SkipWithError("received unexpected width/height");
242 return;
243 }
244
245 s.SetLabel(srcFileName + ", OutputFormat: " + ofToString(of) + ", " + std::to_string(info.width) +
246 "x" + std::to_string(info.height));
247 }
248
BM_Encode_Api0(benchmark::State & s,std::vector<std::string> testVectors)249 static void BM_Encode_Api0(benchmark::State& s, std::vector<std::string> testVectors) {
250 int width = s.range(1);
251 int height = s.range(2);
252 ultrahdr_color_gamut p010Cg = static_cast<ultrahdr_color_gamut>(s.range(3));
253 ultrahdr_transfer_function tf = static_cast<ultrahdr_transfer_function>(s.range(4));
254
255 s.SetLabel(testVectors[s.range(0)] + ", " + colorGamutToString(p010Cg) + ", " + tfToString(tf) +
256 ", " + std::to_string(width) + "x" + std::to_string(height));
257
258 std::string p010File{kTestImagesPath + "p010/" + testVectors[s.range(0)]};
259
260 jpegr_uncompressed_struct rawP010Image{};
261 if (!fillRawImageHandle(&rawP010Image, width, height, p010File, p010Cg, true)) {
262 s.SkipWithError("unable to load file : " + p010File);
263 return;
264 }
265 std::unique_ptr<uint8_t[]> rawP010ImgData;
266 rawP010ImgData.reset(reinterpret_cast<uint8_t*>(rawP010Image.data));
267
268 jpegr_compressed_struct jpegImgR{};
269 jpegImgR.maxLength = (std::max)(static_cast<size_t>(8 * 1024) /* min size 8kb */,
270 rawP010Image.width * rawP010Image.height * 3 * 2);
271 jpegImgR.data = new uint8_t[jpegImgR.maxLength];
272 if (jpegImgR.data == nullptr) {
273 s.SkipWithError("unable to allocate memory to store compressed image");
274 return;
275 }
276 std::unique_ptr<uint8_t[]> jpegImgRData;
277 jpegImgRData.reset(reinterpret_cast<uint8_t*>(jpegImgR.data));
278
279 JpegR jpegHdr;
280 for (auto _ : s) {
281 status_t status = jpegHdr.encodeJPEGR(&rawP010Image, tf, &jpegImgR, 95, nullptr);
282 if (JPEGR_NO_ERROR != status) {
283 s.SkipWithError("encodeJPEGR returned with error : " + std::to_string(status));
284 return;
285 }
286 }
287 }
288
BM_Encode_Api1(benchmark::State & s,std::vector<std::pair<std::string,std::string>> testVectors)289 static void BM_Encode_Api1(benchmark::State& s,
290 std::vector<std::pair<std::string, std::string>> testVectors) {
291 int width = s.range(1);
292 int height = s.range(2);
293 ultrahdr_color_gamut p010Cg = static_cast<ultrahdr_color_gamut>(s.range(3));
294 ultrahdr_color_gamut yuv420Cg = static_cast<ultrahdr_color_gamut>(s.range(4));
295 ultrahdr_transfer_function tf = static_cast<ultrahdr_transfer_function>(s.range(5));
296
297 s.SetLabel(testVectors[s.range(0)].first + ", " + testVectors[s.range(0)].second + ", " +
298 "p010_" + colorGamutToString(p010Cg) + ", " + "yuv420_" +
299 colorGamutToString(yuv420Cg) + ", " + tfToString(tf) + ", " + std::to_string(width) +
300 "x" + std::to_string(height));
301
302 std::string p010File{kTestImagesPath + "p010/" + testVectors[s.range(0)].first};
303
304 jpegr_uncompressed_struct rawP010Image{};
305 if (!fillRawImageHandle(&rawP010Image, width, height, p010File, p010Cg, true)) {
306 s.SkipWithError("unable to load file : " + p010File);
307 return;
308 }
309 std::unique_ptr<uint8_t[]> rawP010ImgData;
310 rawP010ImgData.reset(reinterpret_cast<uint8_t*>(rawP010Image.data));
311
312 std::string yuv420File{kTestImagesPath + "yuv420/" + testVectors[s.range(0)].second};
313
314 jpegr_uncompressed_struct rawYuv420Image{};
315 if (!fillRawImageHandle(&rawYuv420Image, width, height, yuv420File, yuv420Cg, false)) {
316 s.SkipWithError("unable to load file : " + yuv420File);
317 return;
318 }
319 std::unique_ptr<uint8_t[]> rawYuv420ImgData;
320 rawYuv420ImgData.reset(reinterpret_cast<uint8_t*>(rawYuv420Image.data));
321
322 jpegr_compressed_struct jpegImgR{};
323 jpegImgR.maxLength = (std::max)(static_cast<size_t>(8 * 1024) /* min size 8kb */,
324 rawP010Image.width * rawP010Image.height * 3 * 2);
325 jpegImgR.data = new uint8_t[jpegImgR.maxLength];
326
327 std::unique_ptr<uint8_t[]> jpegImgRData;
328 jpegImgRData.reset(reinterpret_cast<uint8_t*>(jpegImgR.data));
329
330 JpegR jpegHdr;
331 for (auto _ : s) {
332 status_t status =
333 jpegHdr.encodeJPEGR(&rawP010Image, &rawYuv420Image, tf, &jpegImgR, 95, nullptr);
334 if (JPEGR_NO_ERROR != status) {
335 s.SkipWithError("encodeJPEGR returned with error : " + std::to_string(status));
336 return;
337 }
338 }
339 }
340
BM_Encode_Api2(benchmark::State & s,std::vector<std::tuple<std::string,std::string,std::string>> testVectors)341 static void BM_Encode_Api2(
342 benchmark::State& s,
343 std::vector<std::tuple<std::string, std::string, std::string>> testVectors) {
344 int width = s.range(1);
345 int height = s.range(2);
346 ultrahdr_color_gamut p010Cg = static_cast<ultrahdr_color_gamut>(s.range(3));
347 ultrahdr_transfer_function tf = static_cast<ultrahdr_transfer_function>(s.range(4));
348
349 s.SetLabel(std::get<0>(testVectors[s.range(0)]) + ", " + std::get<1>(testVectors[s.range(0)]) +
350 ", " + std::get<2>(testVectors[s.range(0)]) + ", " + colorGamutToString(p010Cg) +
351 ", " + tfToString(tf) + ", " + std::to_string(width) + "x" + std::to_string(height));
352
353 std::string p010File{kTestImagesPath + "p010/" + std::get<0>(testVectors[s.range(0)])};
354
355 jpegr_uncompressed_struct rawP010Image{};
356 if (!fillRawImageHandle(&rawP010Image, width, height, p010File, p010Cg, true)) {
357 s.SkipWithError("unable to load file : " + p010File);
358 return;
359 }
360 std::unique_ptr<uint8_t[]> rawP010ImgData;
361 rawP010ImgData.reset(reinterpret_cast<uint8_t*>(rawP010Image.data));
362
363 std::string yuv420File{kTestImagesPath + "yuv420/" + std::get<1>(testVectors[s.range(0)])};
364
365 jpegr_uncompressed_struct rawYuv420Image{};
366 if (!fillRawImageHandle(&rawYuv420Image, width, height, yuv420File, ULTRAHDR_COLORGAMUT_P3,
367 false)) {
368 s.SkipWithError("unable to load file : " + yuv420File);
369 return;
370 }
371 std::unique_ptr<uint8_t[]> rawYuv420ImgData;
372 rawYuv420ImgData.reset(reinterpret_cast<uint8_t*>(rawYuv420Image.data));
373
374 std::string yuv420JpegFile{
375 (kTestImagesPath + "yuv420jpeg/" + std::get<2>(testVectors[s.range(0)]))};
376
377 jpegr_compressed_struct yuv420JpegImage{};
378 if (!fillJpgImageHandle(&yuv420JpegImage, yuv420JpegFile, ULTRAHDR_COLORGAMUT_P3)) {
379 s.SkipWithError("unable to load file : " + yuv420JpegFile);
380 return;
381 }
382 std::unique_ptr<uint8_t[]> yuv420jpegImgData;
383 yuv420jpegImgData.reset(reinterpret_cast<uint8_t*>(yuv420JpegImage.data));
384
385 jpegr_compressed_struct jpegImgR{};
386 jpegImgR.maxLength = (std::max)(static_cast<size_t>(8 * 1024) /* min size 8kb */,
387 rawP010Image.width * rawP010Image.height * 3 * 2);
388 jpegImgR.data = new uint8_t[jpegImgR.maxLength];
389 if (jpegImgR.data == nullptr) {
390 s.SkipWithError("unable to allocate memory to store compressed image");
391 return;
392 }
393 std::unique_ptr<uint8_t[]> jpegImgRData;
394 jpegImgRData.reset(reinterpret_cast<uint8_t*>(jpegImgR.data));
395
396 JpegR jpegHdr;
397 for (auto _ : s) {
398 status_t status =
399 jpegHdr.encodeJPEGR(&rawP010Image, &rawYuv420Image, &yuv420JpegImage, tf, &jpegImgR);
400 if (JPEGR_NO_ERROR != status) {
401 s.SkipWithError("encodeJPEGR returned with error : " + std::to_string(status));
402 return;
403 }
404 }
405 }
406
BM_Encode_Api3(benchmark::State & s,std::vector<std::pair<std::string,std::string>> testVectors)407 static void BM_Encode_Api3(benchmark::State& s,
408 std::vector<std::pair<std::string, std::string>> testVectors) {
409 int width = s.range(1);
410 int height = s.range(2);
411 ultrahdr_color_gamut p010Cg = static_cast<ultrahdr_color_gamut>(s.range(3));
412 ultrahdr_transfer_function tf = static_cast<ultrahdr_transfer_function>(s.range(4));
413
414 s.SetLabel(testVectors[s.range(0)].first + ", " + testVectors[s.range(0)].second + ", " +
415 colorGamutToString(p010Cg) + ", " + tfToString(tf) + ", " + std::to_string(width) +
416 "x" + std::to_string(height));
417
418 std::string p010File{kTestImagesPath + "p010/" + testVectors[s.range(0)].first};
419
420 jpegr_uncompressed_struct rawP010Image{};
421 if (!fillRawImageHandle(&rawP010Image, width, height, p010File, p010Cg, true)) {
422 s.SkipWithError("unable to load file : " + p010File);
423 return;
424 }
425 std::unique_ptr<uint8_t[]> rawP010ImgData;
426 rawP010ImgData.reset(reinterpret_cast<uint8_t*>(rawP010Image.data));
427
428 std::string yuv420JpegFile{(kTestImagesPath + "yuv420jpeg/" + testVectors[s.range(0)].second)};
429
430 jpegr_compressed_struct yuv420JpegImage{};
431 if (!fillJpgImageHandle(&yuv420JpegImage, yuv420JpegFile, ULTRAHDR_COLORGAMUT_P3)) {
432 s.SkipWithError("unable to load file : " + yuv420JpegFile);
433 return;
434 }
435 std::unique_ptr<uint8_t[]> yuv420jpegImgData;
436 yuv420jpegImgData.reset(reinterpret_cast<uint8_t*>(yuv420JpegImage.data));
437
438 jpegr_compressed_struct jpegImgR{};
439 jpegImgR.maxLength = (std::max)(static_cast<size_t>(8 * 1024) /* min size 8kb */,
440 rawP010Image.width * rawP010Image.height * 3 * 2);
441 jpegImgR.data = new uint8_t[jpegImgR.maxLength];
442 if (jpegImgR.data == nullptr) {
443 s.SkipWithError("unable to allocate memory to store compressed image");
444 return;
445 }
446 std::unique_ptr<uint8_t[]> jpegImgRData;
447 jpegImgRData.reset(reinterpret_cast<uint8_t*>(jpegImgR.data));
448
449 JpegR jpegHdr;
450 for (auto _ : s) {
451 status_t status = jpegHdr.encodeJPEGR(&rawP010Image, &yuv420JpegImage, tf, &jpegImgR);
452 if (JPEGR_NO_ERROR != status) {
453 s.SkipWithError("encodeJPEGR returned with error : " + std::to_string(status));
454 return;
455 }
456 }
457 }
458
BM_Encode_Api4(benchmark::State & s)459 static void BM_Encode_Api4(benchmark::State& s) {
460 std::string srcFileName = kTestImagesPath + "jpegr/" + kDecodeAPITestImages[s.range(0)];
461
462 std::ifstream ifd(srcFileName.c_str(), std::ios::binary | std::ios::ate);
463 if (!ifd.good()) {
464 s.SkipWithError("unable to open file " + srcFileName);
465 return;
466 }
467 int size = ifd.tellg();
468
469 jpegr_compressed_struct inpJpegImgR{};
470 inpJpegImgR.length = size;
471 inpJpegImgR.maxLength = size;
472 inpJpegImgR.data = nullptr;
473 inpJpegImgR.colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
474 ifd.close();
475 if (!loadFile(srcFileName.c_str(), inpJpegImgR.data, size)) {
476 s.SkipWithError("unable to load file " + srcFileName);
477 return;
478 }
479 std::unique_ptr<uint8_t[]> inpJpegImgRData;
480 inpJpegImgRData.reset(reinterpret_cast<uint8_t*>(inpJpegImgR.data));
481
482 JpegR jpegHdr;
483 jpeg_info_struct primaryImgInfo;
484 jpeg_info_struct gainmapImgInfo;
485 jpegr_info_struct info{};
486 info.primaryImgInfo = &primaryImgInfo;
487 info.gainmapImgInfo = &gainmapImgInfo;
488 status_t status = jpegHdr.getJPEGRInfo(&inpJpegImgR, &info);
489 if (JPEGR_NO_ERROR != status) {
490 s.SkipWithError("getJPEGRInfo returned with error " + std::to_string(status));
491 return;
492 }
493
494 jpegr_compressed_struct jpegImgR{};
495 jpegImgR.maxLength = (std::max)(static_cast<size_t>(8 * 1024) /* min size 8kb */,
496 info.width * info.height * 3 * 2);
497 jpegImgR.data = new uint8_t[jpegImgR.maxLength];
498 if (jpegImgR.data == nullptr) {
499 s.SkipWithError("unable to allocate memory to store compressed image");
500 return;
501 }
502 std::unique_ptr<uint8_t[]> jpegImgRData;
503 jpegImgRData.reset(reinterpret_cast<uint8_t*>(jpegImgR.data));
504
505 jpegr_compressed_struct primaryImg;
506 primaryImg.data = primaryImgInfo.imgData.data();
507 primaryImg.maxLength = primaryImg.length = primaryImgInfo.imgData.size();
508 primaryImg.colorGamut = static_cast<ultrahdr_color_gamut>(s.range(1));
509 jpegr_compressed_struct gainmapImg;
510 gainmapImg.data = gainmapImgInfo.imgData.data();
511 gainmapImg.maxLength = gainmapImg.length = gainmapImgInfo.imgData.size();
512 gainmapImg.colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
513 ultrahdr_metadata_struct uhdr_metadata;
514 if (!getMetadataFromXMP(gainmapImgInfo.xmpData.data(), gainmapImgInfo.xmpData.size(),
515 &uhdr_metadata)) {
516 s.SkipWithError("getMetadataFromXMP returned with error");
517 return;
518 }
519 for (auto _ : s) {
520 status = jpegHdr.encodeJPEGR(&primaryImg, &gainmapImg, &uhdr_metadata, &jpegImgR);
521 if (JPEGR_NO_ERROR != status) {
522 s.SkipWithError("encodeJPEGR returned with error " + std::to_string(status));
523 return;
524 }
525 }
526
527 s.SetLabel(srcFileName + ", " + std::to_string(info.width) + "x" + std::to_string(info.height));
528 }
529
530 BENCHMARK(BM_Decode)
531 ->ArgsProduct({{benchmark::CreateDenseRange(0, kDecodeAPITestImages.size() - 1, 1)},
532 {ULTRAHDR_OUTPUT_HDR_HLG, ULTRAHDR_OUTPUT_HDR_PQ, ULTRAHDR_OUTPUT_SDR}})
533 ->Unit(benchmark::kMillisecond);
534
535 BENCHMARK_CAPTURE(BM_Encode_Api0, TestVectorName, kEncodeApi0TestImages12MpName)
536 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi0TestImages12MpName.size() - 1, 1)},
537 {4080},
538 {3072},
539 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
540 {
541 ULTRAHDR_TF_HLG,
542 ULTRAHDR_TF_PQ,
543 }})
544 ->Unit(benchmark::kMillisecond);
545
546 BENCHMARK_CAPTURE(BM_Encode_Api0, TestVectorName, kEncodeApi0TestImages3MpName)
547 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi0TestImages3MpName.size() - 1, 1)},
548 {2048},
549 {1536},
550 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
551 {
552 ULTRAHDR_TF_HLG,
553 ULTRAHDR_TF_PQ,
554 }})
555 ->Unit(benchmark::kMillisecond);
556
557 BENCHMARK_CAPTURE(BM_Encode_Api1, TestVectorName, kEncodeApi1TestImages12MpName)
558 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi1TestImages12MpName.size() - 1, 1)},
559 {4080},
560 {3072},
561 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
562 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
563 {
564 ULTRAHDR_TF_HLG,
565 ULTRAHDR_TF_PQ,
566 }})
567 ->Unit(benchmark::kMillisecond);
568
569 BENCHMARK_CAPTURE(BM_Encode_Api1, TestVectorName, kEncodeApi1TestImages3MpName)
570 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi1TestImages3MpName.size() - 1, 1)},
571 {2048},
572 {1536},
573 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
574 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
575 {
576 ULTRAHDR_TF_HLG,
577 ULTRAHDR_TF_PQ,
578 }})
579 ->Unit(benchmark::kMillisecond);
580
581 BENCHMARK_CAPTURE(BM_Encode_Api2, TestVectorName, kEncodeApi2TestImages12MpName)
582 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi2TestImages12MpName.size() - 1, 1)},
583 {4080},
584 {3072},
585 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
586 {
587 ULTRAHDR_TF_HLG,
588 ULTRAHDR_TF_PQ,
589 }})
590 ->Unit(benchmark::kMillisecond);
591
592 BENCHMARK_CAPTURE(BM_Encode_Api2, TestVectorName, kEncodeApi2TestImages3MpName)
593 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi2TestImages3MpName.size() - 1, 1)},
594 {2048},
595 {1536},
596 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
597 {
598 ULTRAHDR_TF_HLG,
599 ULTRAHDR_TF_PQ,
600 }})
601 ->Unit(benchmark::kMillisecond);
602
603 BENCHMARK_CAPTURE(BM_Encode_Api3, TestVectorName, kEncodeApi3TestImages12MpName)
604 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi3TestImages12MpName.size() - 1, 1)},
605 {4080},
606 {3072},
607 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
608 {
609 ULTRAHDR_TF_HLG,
610 ULTRAHDR_TF_PQ,
611 }})
612 ->Unit(benchmark::kMillisecond);
613
614 BENCHMARK_CAPTURE(BM_Encode_Api3, TestVectorName, kEncodeApi3TestImages3MpName)
615 ->ArgsProduct({{benchmark::CreateDenseRange(0, kEncodeApi3TestImages3MpName.size() - 1, 1)},
616 {2048},
617 {1536},
618 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
619 {
620 ULTRAHDR_TF_HLG,
621 ULTRAHDR_TF_PQ,
622 }})
623 ->Unit(benchmark::kMillisecond);
624
625 BENCHMARK(BM_Encode_Api4)
626 ->ArgsProduct({
627 {benchmark::CreateDenseRange(0, kEncodeApi4TestImages12MpName.size() - 1, 1)},
628 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
629 })
630 ->Unit(benchmark::kMillisecond);
631
632 BENCHMARK(BM_Encode_Api4)
633 ->ArgsProduct({
634 {benchmark::CreateDenseRange(0, kEncodeApi4TestImages3MpName.size() - 1, 1)},
635 {ULTRAHDR_COLORGAMUT_BT709, ULTRAHDR_COLORGAMUT_P3, ULTRAHDR_COLORGAMUT_BT2100},
636 })
637 ->Unit(benchmark::kMillisecond);
638
639 BENCHMARK_MAIN();
640