Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lib/src/dsp/arm/gainmapmath_neon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,12 +324,12 @@ uhdr_error_info_t convertYuv_neon(uhdr_raw_image_t* image, uhdr_color_gamut_t sr
ALIGNED(16)
const uint16_t kRgb709ToYuv_coeffs_neon[8] = {3484, 11717, 1183, 1877, 6315, 8192, 7441, 751};

// RGB Display P3 -> Yuv Display P3
// Y = 0.2289746 * R + 0.6917385 * G + 0.0792869 * B
// U = -0.124346335 * R + -0.375653665 * G + 0.5 * B
// V = 0.5 * R + -0.448583471 * G + -0.051416529 * B
// RGB Display P3 -> YUV using BT.601 luma coefficients, matching p3RgbToYuv().
// Y = 0.299 * R + 0.587 * G + 0.114 * B
// U = -0.168735892 * R + -0.331264108 * G + 0.5 * B
// V = 0.5 * R + -0.418687589 * G + -0.081312411 * B
ALIGNED(16)
const uint16_t kRgbDispP3ToYuv_coeffs_neon[8] = {3752, 11333, 1299, 2037, 6155, 8192, 7350, 842};
const uint16_t kRgb601ToYuv_coeffs_neon[8] = {4899, 9617, 1868, 2765, 5427, 8192, 6860, 1332};

// RGB Bt2100 -> Yuv Bt2100
// Y = 0.2627 * R + 0.677998 * G + 0.059302 * B
Expand Down Expand Up @@ -456,9 +456,9 @@ std::unique_ptr<uhdr_raw_image_ext_t> convert_raw_input_to_ycbcr_neon(uhdr_raw_i
if (src->cg == UHDR_CG_BT_709) {
coeffs_ptr = kRgb709ToYuv_coeffs_neon;
} else if (src->cg == UHDR_CG_BT_2100) {
coeffs_ptr = kRgbDispP3ToYuv_coeffs_neon;
} else if (src->cg == UHDR_CG_DISPLAY_P3) {
coeffs_ptr = kRgb2100ToYuv_coeffs_neon;
} else if (src->cg == UHDR_CG_DISPLAY_P3) {
coeffs_ptr = kRgb601ToYuv_coeffs_neon;
} else {
return dst;
}
Expand Down
45 changes: 45 additions & 0 deletions tests/gainmapmath_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>

#include <vector>

#include "ultrahdr/gainmapmath.h"
#ifdef UHDR_ENABLE_SMPTE2094_50
#include "smpte2094_50/smpte2094_50.h"
Expand Down Expand Up @@ -875,6 +877,49 @@ TEST_F(GainMapMathTest, YuvConversionNeon) {
EXPECT_NEAR(result7.v, expected_values.v.at(7), 1);
}
}

TEST_F(GainMapMathTest, Rgba8888ToYuv444NeonMatchesScalarForWideGamuts) {
constexpr size_t kWidth = 16;
constexpr size_t kHeight = 1;
const std::array<std::array<uint8_t, 4>, 4> colors{{
{{255, 0, 0, 255}},
{{0, 255, 0, 255}},
{{0, 0, 255, 255}},
{{37, 149, 233, 255}},
}};

std::vector<uint8_t> rgba(kWidth * kHeight * 4);
for (size_t x = 0; x < kWidth; ++x) {
std::copy(colors[x % colors.size()].begin(), colors[x % colors.size()].end(),
rgba.begin() + x * 4);
}

for (uhdr_color_gamut_t gamut : {UHDR_CG_DISPLAY_P3, UHDR_CG_BT_2100}) {
uhdr_raw_image_t source{};
source.fmt = UHDR_IMG_FMT_32bppRGBA8888;
source.cg = gamut;
source.ct = UHDR_CT_SRGB;
source.range = UHDR_CR_FULL_RANGE;
source.w = kWidth;
source.h = kHeight;
source.planes[UHDR_PLANE_PACKED] = rgba.data();
source.stride[UHDR_PLANE_PACKED] = kWidth;

auto scalar = convert_raw_input_to_ycbcr(&source);
auto neon = convert_raw_input_to_ycbcr_neon(&source);
ASSERT_NE(scalar, nullptr);
ASSERT_NE(neon, nullptr);

for (auto plane : {UHDR_PLANE_Y, UHDR_PLANE_U, UHDR_PLANE_V}) {
const auto* scalar_data = static_cast<const uint8_t*>(scalar->planes[plane]);
const auto* neon_data = static_cast<const uint8_t*>(neon->planes[plane]);
for (size_t x = 0; x < kWidth; ++x) {
EXPECT_NEAR(scalar_data[x], neon_data[x], 1)
<< "gamut=" << gamut << ", plane=" << plane << ", x=" << x;
}
}
}
}
#endif

TEST_F(GainMapMathTest, TransformYuv420) {
Expand Down
Loading