Backed out 3 changesets (bug 1790375) for causing wd failures on fetch_error.py....
[gecko.git] / third_party / jpeg-xl / lib / jpegli / output_suspension_test.cc
blob73db791727b8251294b24f1207a545f5bc6ccbc3
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
6 #include "lib/jpegli/encode.h"
7 #include "lib/jpegli/test_utils.h"
8 #include "lib/jpegli/testing.h"
10 namespace jpegli {
11 namespace {
13 static constexpr size_t kInitialBufferSize = 1024;
14 static constexpr size_t kFinalBufferSize = 18;
16 struct DestinationManager {
17 jpeg_destination_mgr pub;
18 std::vector<uint8_t> buffer;
20 DestinationManager() {
21 pub.init_destination = init_destination;
22 pub.empty_output_buffer = empty_output_buffer;
23 pub.term_destination = term_destination;
26 void Rewind() {
27 pub.next_output_byte = buffer.data();
28 pub.free_in_buffer = buffer.size();
31 void EmptyTo(std::vector<uint8_t>* output, size_t new_size = 0) {
32 output->insert(output->end(), buffer.data(), pub.next_output_byte);
33 if (new_size > 0) {
34 buffer.resize(new_size);
36 Rewind();
39 static void init_destination(j_compress_ptr cinfo) {
40 auto us = reinterpret_cast<DestinationManager*>(cinfo->dest);
41 us->buffer.resize(kInitialBufferSize);
42 us->Rewind();
45 static boolean empty_output_buffer(j_compress_ptr cinfo) { return FALSE; }
47 static void term_destination(j_compress_ptr cinfo) {}
50 struct TestConfig {
51 TestImage input;
52 CompressParams jparams;
53 size_t buffer_size;
54 size_t lines_batch_size;
57 class OutputSuspensionTestParam : public ::testing::TestWithParam<TestConfig> {
60 TEST_P(OutputSuspensionTestParam, PixelData) {
61 jpeg_compress_struct cinfo = {};
62 TestConfig config = GetParam();
63 TestImage& input = config.input;
64 GeneratePixels(&input);
65 DestinationManager dest;
66 std::vector<uint8_t> compressed;
67 const auto try_catch_block = [&]() -> bool {
68 ERROR_HANDLER_SETUP(jpegli);
69 jpegli_create_compress(&cinfo);
70 cinfo.dest = reinterpret_cast<jpeg_destination_mgr*>(&dest);
72 cinfo.image_width = input.xsize;
73 cinfo.image_height = input.ysize;
74 cinfo.input_components = input.components;
75 cinfo.in_color_space = JCS_RGB;
76 jpegli_set_defaults(&cinfo);
77 cinfo.comp_info[0].v_samp_factor = config.jparams.v_sampling[0];
78 jpegli_set_progressive_level(&cinfo, 0);
79 cinfo.optimize_coding = FALSE;
80 jpegli_start_compress(&cinfo, TRUE);
82 size_t stride = cinfo.image_width * cinfo.input_components;
83 std::vector<uint8_t> row_bytes(config.lines_batch_size * stride);
84 while (cinfo.next_scanline < cinfo.image_height) {
85 size_t lines_left = cinfo.image_height - cinfo.next_scanline;
86 size_t num_lines = std::min(config.lines_batch_size, lines_left);
87 memcpy(&row_bytes[0], &input.pixels[cinfo.next_scanline * stride],
88 num_lines * stride);
89 std::vector<JSAMPROW> rows(num_lines);
90 for (size_t i = 0; i < num_lines; ++i) {
91 rows[i] = &row_bytes[i * stride];
93 size_t lines_done = 0;
94 while (lines_done < num_lines) {
95 lines_done += jpegli_write_scanlines(&cinfo, &rows[lines_done],
96 num_lines - lines_done);
97 if (lines_done < num_lines) {
98 dest.EmptyTo(&compressed, config.buffer_size);
102 dest.EmptyTo(&compressed, kFinalBufferSize);
103 jpegli_finish_compress(&cinfo);
104 dest.EmptyTo(&compressed);
105 return true;
107 ASSERT_TRUE(try_catch_block());
108 jpegli_destroy_compress(&cinfo);
109 TestImage output;
110 DecodeWithLibjpeg(CompressParams(), DecompressParams(), compressed, &output);
111 VerifyOutputImage(input, output, 2.5);
114 TEST_P(OutputSuspensionTestParam, RawData) {
115 jpeg_compress_struct cinfo = {};
116 TestConfig config = GetParam();
117 if (config.lines_batch_size != 1) return;
118 TestImage& input = config.input;
119 input.color_space = JCS_YCbCr;
120 GeneratePixels(&input);
121 GenerateRawData(config.jparams, &input);
122 DestinationManager dest;
123 std::vector<uint8_t> compressed;
124 const auto try_catch_block = [&]() -> bool {
125 ERROR_HANDLER_SETUP(jpegli);
126 jpegli_create_compress(&cinfo);
127 cinfo.dest = reinterpret_cast<jpeg_destination_mgr*>(&dest);
128 cinfo.image_width = input.xsize;
129 cinfo.image_height = input.ysize;
130 cinfo.input_components = input.components;
131 cinfo.in_color_space = JCS_YCbCr;
132 jpegli_set_defaults(&cinfo);
133 cinfo.comp_info[0].v_samp_factor = config.jparams.v_sampling[0];
134 jpegli_set_progressive_level(&cinfo, 0);
135 cinfo.optimize_coding = FALSE;
136 cinfo.raw_data_in = TRUE;
137 jpegli_start_compress(&cinfo, TRUE);
139 std::vector<std::vector<uint8_t>> raw_data = input.raw_data;
140 size_t max_lines = config.jparams.max_v_sample() * DCTSIZE;
141 std::vector<std::vector<JSAMPROW>> rowdata(cinfo.num_components);
142 std::vector<JSAMPARRAY> data(cinfo.num_components);
143 for (int c = 0; c < cinfo.num_components; ++c) {
144 rowdata[c].resize(config.jparams.v_samp(c) * DCTSIZE);
145 data[c] = &rowdata[c][0];
147 while (cinfo.next_scanline < cinfo.image_height) {
148 for (int c = 0; c < cinfo.num_components; ++c) {
149 size_t cwidth = cinfo.comp_info[c].width_in_blocks * DCTSIZE;
150 size_t cheight = cinfo.comp_info[c].height_in_blocks * DCTSIZE;
151 size_t num_lines = config.jparams.v_samp(c) * DCTSIZE;
152 size_t y0 = (cinfo.next_scanline / max_lines) * num_lines;
153 for (size_t i = 0; i < num_lines; ++i) {
154 rowdata[c][i] =
155 (y0 + i < cheight ? &raw_data[c][(y0 + i) * cwidth] : nullptr);
158 while (jpegli_write_raw_data(&cinfo, &data[0], max_lines) == 0) {
159 dest.EmptyTo(&compressed, config.buffer_size);
162 dest.EmptyTo(&compressed, kFinalBufferSize);
163 jpegli_finish_compress(&cinfo);
164 dest.EmptyTo(&compressed);
165 return true;
167 try_catch_block();
168 jpegli_destroy_compress(&cinfo);
169 DecompressParams dparams;
170 dparams.output_mode = RAW_DATA;
171 TestImage output;
172 DecodeWithLibjpeg(CompressParams(), dparams, compressed, &output);
173 VerifyOutputImage(input, output, 3.5);
176 std::vector<TestConfig> GenerateTests() {
177 std::vector<TestConfig> all_tests;
178 const size_t xsize0 = 1920;
179 const size_t ysize0 = 1080;
180 for (int dysize : {0, 1, 8, 9}) {
181 for (int v_sampling : {1, 2}) {
182 for (int nlines : {1, 8, 117}) {
183 for (int bufsize : {1, 16, 16 << 10}) {
184 TestConfig config;
185 config.lines_batch_size = nlines;
186 config.buffer_size = bufsize;
187 config.input.xsize = xsize0;
188 config.input.ysize = ysize0 + dysize;
189 config.jparams.h_sampling = {1, 1, 1};
190 config.jparams.v_sampling = {v_sampling, 1, 1};
191 all_tests.push_back(config);
196 return all_tests;
199 std::ostream& operator<<(std::ostream& os, const TestConfig& c) {
200 os << c.input;
201 os << c.jparams;
202 os << "Lines" << c.lines_batch_size;
203 os << "BufSize" << c.buffer_size;
204 return os;
207 std::string TestDescription(
208 const testing::TestParamInfo<OutputSuspensionTestParam::ParamType>& info) {
209 std::stringstream name;
210 name << info.param;
211 return name.str();
214 JPEGLI_INSTANTIATE_TEST_SUITE_P(OutputSuspensionTest, OutputSuspensionTestParam,
215 testing::ValuesIn(GenerateTests()),
216 TestDescription);
218 } // namespace
219 } // namespace jpegli