X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=ycbcr_input_test.cpp;h=109178f09e2fa8e20d805830285989437aefd7c6;hp=6895b3834a62602aa293c012957638684b471074;hb=1349c2cabb17a3637aa5bc2520c058333d8d48d7;hpb=1320ed72d619610b9f056c106496dfe7dbd95e06 diff --git a/ycbcr_input_test.cpp b/ycbcr_input_test.cpp index 6895b38..109178f 100644 --- a/ycbcr_input_test.cpp +++ b/ycbcr_input_test.cpp @@ -1,5 +1,4 @@ // Unit tests for YCbCrInput. -// FIXME: This class really ought to support mipmaps. #include #include @@ -8,11 +7,12 @@ #include "gtest/gtest.h" #include "test_util.h" #include "util.h" +#include "resource_pool.h" #include "ycbcr_input.h" namespace movit { -TEST(YCbCrInput, Simple444) { +TEST(YCbCrInputTest, Simple444) { const int width = 1; const int height = 5; @@ -45,6 +45,7 @@ TEST(YCbCrInput, Simple444) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_601; ycbcr_format.full_range = false; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 1; ycbcr_format.chroma_subsampling_y = 1; ycbcr_format.cb_x_position = 0.5f; @@ -65,7 +66,7 @@ TEST(YCbCrInput, Simple444) { expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002); } -TEST(YCbCrInput, FullRangeRec601) { +TEST(YCbCrInputTest, FullRangeRec601) { const int width = 1; const int height = 5; @@ -99,6 +100,7 @@ TEST(YCbCrInput, FullRangeRec601) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_601; ycbcr_format.full_range = true; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 1; ycbcr_format.chroma_subsampling_y = 1; ycbcr_format.cb_x_position = 0.5f; @@ -119,7 +121,7 @@ TEST(YCbCrInput, FullRangeRec601) { expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002); } -TEST(YCbCrInput, Rec709) { +TEST(YCbCrInputTest, Rec709) { const int width = 1; const int height = 5; @@ -152,6 +154,7 @@ TEST(YCbCrInput, Rec709) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_709; ycbcr_format.full_range = false; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 1; ycbcr_format.chroma_subsampling_y = 1; ycbcr_format.cb_x_position = 0.5f; @@ -172,7 +175,7 @@ TEST(YCbCrInput, Rec709) { expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002); } -TEST(YCbCrInput, Rec2020) { +TEST(YCbCrInputTest, Rec2020) { const int width = 1; const int height = 5; @@ -207,6 +210,7 @@ TEST(YCbCrInput, Rec2020) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_2020; ycbcr_format.full_range = false; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 1; ycbcr_format.chroma_subsampling_y = 1; ycbcr_format.cb_x_position = 0.5f; @@ -227,7 +231,7 @@ TEST(YCbCrInput, Rec2020) { expect_equal(expected_data, out_data, 4 * width, height, 0.025, 0.002); } -TEST(YCbCrInput, Subsampling420) { +TEST(YCbCrInputTest, Subsampling420) { const int width = 4; const int height = 4; @@ -268,6 +272,7 @@ TEST(YCbCrInput, Subsampling420) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_601; ycbcr_format.full_range = false; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 2; ycbcr_format.chroma_subsampling_y = 2; ycbcr_format.cb_x_position = 0.5f; @@ -288,7 +293,7 @@ TEST(YCbCrInput, Subsampling420) { expect_equal(expected_data, out_data, width, height, 0.01, 0.001); } -TEST(YCbCrInput, Subsampling420WithNonCenteredSamples) { +TEST(YCbCrInputTest, Subsampling420WithNonCenteredSamples) { const int width = 4; const int height = 4; @@ -329,6 +334,7 @@ TEST(YCbCrInput, Subsampling420WithNonCenteredSamples) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_601; ycbcr_format.full_range = false; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 2; ycbcr_format.chroma_subsampling_y = 2; ycbcr_format.cb_x_position = 0.0f; @@ -350,7 +356,7 @@ TEST(YCbCrInput, Subsampling420WithNonCenteredSamples) { } // Yes, some 4:2:2 formats actually have this craziness. -TEST(YCbCrInput, DifferentCbAndCrPositioning) { +TEST(YCbCrInputTest, DifferentCbAndCrPositioning) { const int width = 4; const int height = 4; @@ -398,6 +404,7 @@ TEST(YCbCrInput, DifferentCbAndCrPositioning) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_601; ycbcr_format.full_range = false; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 2; ycbcr_format.chroma_subsampling_y = 1; ycbcr_format.cb_x_position = 0.0f; @@ -420,7 +427,7 @@ TEST(YCbCrInput, DifferentCbAndCrPositioning) { expect_equal(expected_data_blue, out_data, width, height, 0.01, 0.001); } -TEST(YCbCrInput, PBO) { +TEST(YCbCrInputTest, PBO) { const int width = 1; const int height = 5; @@ -455,6 +462,7 @@ TEST(YCbCrInput, PBO) { YCbCrFormat ycbcr_format; ycbcr_format.luma_coefficients = YCBCR_REC_601; ycbcr_format.full_range = false; + ycbcr_format.num_levels = 256; ycbcr_format.chroma_subsampling_x = 1; ycbcr_format.chroma_subsampling_y = 1; ycbcr_format.cb_x_position = 0.5f; @@ -477,4 +485,131 @@ TEST(YCbCrInput, PBO) { glDeleteBuffers(1, &pbo); } +TEST(YCbCrInputTest, CombinedCbAndCr) { + 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 y[width * height] = { + 16, 235, 81, 145, 41, + }; + unsigned char cb_cr[width * height * 2] = { + 128, 128, + 128, 128, + 90, 240, + 54, 34, + 240, 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]; + + 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.num_levels = 256; + 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, YCBCR_INPUT_SPLIT_Y_AND_CBCR); + input->set_pixel_data(0, y); + input->set_pixel_data(1, cb_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(YCbCrInputTest, ExternalTexture) { + 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 y[width * height] = { + 16, 235, 81, 145, 41, + }; + unsigned char cb[width * height] = { + 128, 128, 90, 54, 240, + }; + unsigned char cr[width * height] = { + 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]; + + 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.num_levels = 256; + 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; + + // Make a texture for the Cb data; keep the others as regular uploads. + ResourcePool pool; + GLuint cb_tex = pool.create_2d_texture(GL_R8, width, height); + check_error(); + glBindTexture(GL_TEXTURE_2D, cb_tex); + check_error(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + check_error(); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + check_error(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, cb); + check_error(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + check_error(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + check_error(); + + YCbCrInput *input = new YCbCrInput(format, ycbcr_format, width, height); + input->set_pixel_data(0, y); + input->set_texture_num(1, cb_tex); + input->set_pixel_data(2, cr); + tester.get_chain()->add_input(input); + + tester.run(out_data, GL_RGBA, COLORSPACE_sRGB, GAMMA_sRGB); + + pool.release_2d_texture(cb_tex); + + // 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); +} + } // namespace movit