X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=ycbcr_input_test.cpp;h=6895b3834a62602aa293c012957638684b471074;hp=15d76391281a7c5ccdc438b4b7fe5c4679fc4a4b;hb=95edbfccb0843da3cc105dadc5bc6d8e102f6071;hpb=37f56fcbe571b2322243f6de59494bf9e0cbb37a diff --git a/ycbcr_input_test.cpp b/ycbcr_input_test.cpp index 15d7639..6895b38 100644 --- a/ycbcr_input_test.cpp +++ b/ycbcr_input_test.cpp @@ -1,13 +1,17 @@ // Unit tests for YCbCrInput. // FIXME: This class really ought to support mipmaps. +#include #include #include "effect_chain.h" #include "gtest/gtest.h" #include "test_util.h" +#include "util.h" #include "ycbcr_input.h" +namespace movit { + TEST(YCbCrInput, Simple444) { const int width = 1; const int height = 5; @@ -168,6 +172,61 @@ TEST(YCbCrInput, Rec709) { expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002); } +TEST(YCbCrInput, Rec2020) { + const int width = 1; + const int height = 5; + + // Pure-color test inputs, calculated with the formulas in Rec. 2020 + // page 4, tables 4 and 5 (for conventional non-constant luminance). + // Note that we still use 8-bit inputs, even though Rec. 2020 is only + // defined for 10- and 12-bit. + unsigned char y[width * height] = { + 16, 235, 74, 164, 29, + }; + unsigned char cb[width * height] = { + 128, 128, 97, 47, 240, + }; + unsigned char cr[width * height] = { + 128, 128, 240, 25, 119, + }; + float expected_data[4 * width * height] = { + 0.0, 0.0, 0.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.0, 0.0, 0.0, 1.0, + 0.0, 1.0, 0.0, 1.0, + 0.0, 0.0, 1.0, 1.0, + }; + float out_data[4 * width * height]; + + EffectChainTester tester(NULL, width, height); + + ImageFormat format; + format.color_space = COLORSPACE_sRGB; + format.gamma_curve = GAMMA_sRGB; + + YCbCrFormat ycbcr_format; + ycbcr_format.luma_coefficients = YCBCR_REC_2020; + ycbcr_format.full_range = false; + ycbcr_format.chroma_subsampling_x = 1; + ycbcr_format.chroma_subsampling_y = 1; + ycbcr_format.cb_x_position = 0.5f; + ycbcr_format.cb_y_position = 0.5f; + ycbcr_format.cr_x_position = 0.5f; + ycbcr_format.cr_y_position = 0.5f; + + YCbCrInput *input = new YCbCrInput(format, ycbcr_format, width, height); + input->set_pixel_data(0, y); + input->set_pixel_data(1, cb); + input->set_pixel_data(2, cr); + tester.get_chain()->add_input(input); + + tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB); + + // Y'CbCr isn't 100% accurate (the input values are rounded), + // so we need some leeway. + expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002); +} + TEST(YCbCrInput, Subsampling420) { const int width = 4; const int height = 4; @@ -360,3 +419,62 @@ TEST(YCbCrInput, DifferentCbAndCrPositioning) { tester.run(out_data, GL_BLUE, COLORSPACE_sRGB, GAMMA_sRGB); expect_equal(expected_data_blue, out_data, width, height, 0.01, 0.001); } + +TEST(YCbCrInput, PBO) { + const int width = 1; + const int height = 5; + + // Pure-color test inputs, calculated with the formulas in Rec. 601 + // section 2.5.4. + unsigned char data[width * height * 3] = { + 16, 235, 81, 145, 41, + 128, 128, 90, 54, 240, + 128, 128, 240, 34, 110, + }; + float expected_data[4 * width * height] = { + 0.0, 0.0, 0.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.0, 0.0, 0.0, 1.0, + 0.0, 1.0, 0.0, 1.0, + 0.0, 0.0, 1.0, 1.0, + }; + float out_data[4 * width * height]; + + GLuint pbo; + glGenBuffers(1, &pbo); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); + glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 3, data, GL_STREAM_DRAW); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); + + EffectChainTester tester(NULL, width, height); + + ImageFormat format; + format.color_space = COLORSPACE_sRGB; + format.gamma_curve = GAMMA_sRGB; + + YCbCrFormat ycbcr_format; + ycbcr_format.luma_coefficients = YCBCR_REC_601; + ycbcr_format.full_range = false; + ycbcr_format.chroma_subsampling_x = 1; + ycbcr_format.chroma_subsampling_y = 1; + ycbcr_format.cb_x_position = 0.5f; + ycbcr_format.cb_y_position = 0.5f; + ycbcr_format.cr_x_position = 0.5f; + ycbcr_format.cr_y_position = 0.5f; + + YCbCrInput *input = new YCbCrInput(format, ycbcr_format, width, height); + input->set_pixel_data(0, (unsigned char *)BUFFER_OFFSET(0), pbo); + input->set_pixel_data(1, (unsigned char *)BUFFER_OFFSET(width * height), pbo); + input->set_pixel_data(2, (unsigned char *)BUFFER_OFFSET(width * height * 2), pbo); + tester.get_chain()->add_input(input); + + tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB); + + // Y'CbCr isn't 100% accurate (the input values are rounded), + // so we need some leeway. + expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002); + + glDeleteBuffers(1, &pbo); +} + +} // namespace movit