1 #include <algorithm>
2 #include <cstdint>
3 #include "common/alloc.h"
4 #include "common/except.h"
5 #include "common/make_unique.h"
6 #include "common/pixel.h"
7 #include "graph/basic_filter.h"
8 #include "graph/filtergraph.h"
9 #include "graph/image_filter.h"
10
11 #include "gtest/gtest.h"
12 #include "audit_buffer.h"
13 #include "mock_filter.h"
14
15 namespace {
16
17 using zimg::graph::node_id;
18 using zimg::graph::plane_mask;
19 using zimg::graph::id_map;
20 using zimg::graph::invalid_id;
21
enabled_planes(bool color)22 plane_mask enabled_planes(bool color)
23 {
24 plane_mask mask{};
25 mask[zimg::graph::PLANE_Y] = true;
26 mask[zimg::graph::PLANE_U] = color;
27 mask[zimg::graph::PLANE_V] = color;
28 return mask;
29 }
30
id_to_map(node_id id,bool color)31 id_map id_to_map(node_id id, bool color)
32 {
33 id_map map = zimg::graph::null_ids;
34 map[zimg::graph::PLANE_Y] = id;
35 map[zimg::graph::PLANE_U] = color ? id : invalid_id;
36 map[zimg::graph::PLANE_V] = color ? id : invalid_id;
37 return map;
38 }
39
40
41 template <class T>
42 class AuditImage : public AuditBuffer<T> {
43 unsigned m_width;
44 unsigned m_height;
45 public:
AuditImage(AuditBufferType buffer_type,unsigned width,unsigned height,zimg::PixelType type,unsigned subsample_w,unsigned subsample_h)46 AuditImage(AuditBufferType buffer_type, unsigned width, unsigned height, zimg::PixelType type, unsigned subsample_w, unsigned subsample_h) :
47 AuditBuffer<T>(buffer_type, width, height, type, zimg::graph::BUFFER_MAX, subsample_w, subsample_h),
48 m_width{ width },
49 m_height{ height }
50 {}
51
validate()52 void validate()
53 {
54 for (unsigned i = 0; i < m_height; ++i) {
55 ASSERT_FALSE(AuditBuffer<T>::detect_write(i, 0, m_width)) << "unexpected write at line: " << i;
56 }
57 }
58 };
59
60 } // namespace
61
62
TEST(FilterGraphTest,test_noop)63 TEST(FilterGraphTest, test_noop)
64 {
65 const unsigned w = 640;
66 const unsigned h = 480;
67 const zimg::PixelType type = zimg::PixelType::BYTE;
68
69 for (unsigned x = 0; x < 2; ++x) {
70 SCOPED_TRACE(!!x);
71
72 bool color = !!x;
73 AuditBufferType buffer_type = color ? AuditBufferType::COLOR_RGB : AuditBufferType::PLANE;
74
75 zimg::graph::FilterGraph graph;
76 node_id id = graph.add_source({ w, h, type }, 0, 0, enabled_planes(color));
77 graph.set_output(id_to_map(id, color));
78
79 AuditImage<uint8_t> src_image{ buffer_type, w, h, type, 0, 0 };
80 AuditImage<uint8_t> dst_image{ buffer_type, w, h, type, 0, 0 };
81 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
82
83 src_image.default_fill();
84 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
85
86 SCOPED_TRACE("validating src");
87 src_image.validate();
88 SCOPED_TRACE("validating dst");
89 dst_image.validate();
90 }
91 }
92
TEST(FilterGraphTest,test_noop_subsampling)93 TEST(FilterGraphTest, test_noop_subsampling)
94 {
95 const unsigned w = 640;
96 const unsigned h = 480;
97 const zimg::PixelType type = zimg::PixelType::BYTE;
98
99 for (unsigned sw = 0; sw < 3; ++sw) {
100 for (unsigned sh = 0; sh < 3; ++sh) {
101 SCOPED_TRACE(sw);
102 SCOPED_TRACE(sh);
103
104 zimg::graph::FilterGraph graph;
105 node_id id = graph.add_source({ w, h, type }, sw, sh, enabled_planes(true));
106 graph.set_output(id_to_map(id, true));
107
108 AuditImage<uint8_t> src_image{ AuditBufferType::COLOR_YUV, w, h, type, sw, sh };
109 AuditImage<uint8_t> dst_image{ AuditBufferType::COLOR_YUV, w, h, type, sw, sh };
110 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
111
112 src_image.default_fill();
113 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
114
115 SCOPED_TRACE("validating src");
116 src_image.validate();
117 SCOPED_TRACE("validating dst");
118 dst_image.validate();
119 }
120 }
121 }
122
TEST(FilterGraphTest,test_basic)123 TEST(FilterGraphTest, test_basic)
124 {
125 const unsigned w = 640;
126 const unsigned h = 480;
127 const zimg::PixelType type = zimg::PixelType::WORD;
128
129 const uint8_t test_byte1 = 0xCD;
130 const uint8_t test_byte2 = 0xDD;
131 const uint8_t test_byte3 = 0xDC;
132
133 for (unsigned x = 0; x < 2; ++x) {
134 SCOPED_TRACE(!!x);
135
136 bool color = !!x;
137 AuditBufferType buffer_type = color ? AuditBufferType::COLOR_RGB : AuditBufferType::PLANE;
138
139 zimg::graph::ImageFilter::filter_flags flags1{};
140 flags1.has_state = true;
141 flags1.entire_row = true;
142 flags1.entire_plane = true;
143 flags1.color = !!x;
144
145 zimg::graph::ImageFilter::filter_flags flags2{};
146 flags2.has_state = true;
147 flags2.entire_row = false;
148 flags2.entire_plane = false;
149 flags2.color = !!x;
150
151 auto filter1 = std::make_shared<SplatFilter<uint16_t>>(w, h, type, flags1);
152 auto filter2 = std::make_shared<SplatFilter<uint16_t>>(w, h, type, flags2);
153
154 filter1->set_input_val(test_byte1);
155 filter1->set_output_val(test_byte2);
156
157 filter2->set_input_val(test_byte2);
158 filter2->set_output_val(test_byte3);
159
160 zimg::graph::FilterGraph graph;
161 node_id id = graph.add_source({ w, h, type }, 0, 0, enabled_planes(color));
162
163 id = graph.attach_filter(filter1, id_to_map(id, color), enabled_planes(color));
164 id = graph.attach_filter(filter2, id_to_map(id, color), enabled_planes(color));
165 graph.set_output(id_to_map(id, color));
166
167 AuditImage<uint16_t> src_image{ buffer_type, w, h, type, 0, 0 };
168 AuditImage<uint16_t> dst_image{ buffer_type, w, h, type, 0, 0 };
169 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
170
171 src_image.set_fill_val(test_byte1);
172 src_image.default_fill();
173 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
174 dst_image.set_fill_val(test_byte3);
175
176 ASSERT_EQ(1U, filter1->get_total_calls());
177 ASSERT_EQ(h, filter2->get_total_calls());
178
179 SCOPED_TRACE("validating src");
180 src_image.validate();
181 SCOPED_TRACE("validating dst");
182 dst_image.validate();
183 }
184 }
185
TEST(FilterGraphTest,test_skip_plane)186 TEST(FilterGraphTest, test_skip_plane)
187 {
188 const unsigned w = 640;
189 const unsigned h = 480;
190 const zimg::PixelType type = zimg::PixelType::FLOAT;
191
192 const uint8_t test_byte1 = 0xCD;
193 const uint8_t test_byte2 = 0xDD;
194 const uint8_t test_byte3 = 0xDC;
195
196 for (unsigned x = 0; x < 2; ++x) {
197 SCOPED_TRACE(!!x);
198
199 zimg::graph::ImageFilter::filter_flags flags1{};
200 flags1.has_state = true;
201 flags1.entire_row = true;
202 flags1.color = true;
203
204 zimg::graph::ImageFilter::filter_flags flags2{};
205 flags2.has_state = false;
206 flags2.entire_row = true;
207 flags2.color = false;
208
209 auto filter1 = std::make_shared<SplatFilter<float>>(w, h, type, flags1);
210 auto filter2 = std::make_shared<SplatFilter<float>>(w, h, type, flags2);
211
212 filter1->set_input_val(test_byte1);
213 filter1->set_output_val(test_byte2);
214
215 filter2->set_input_val(test_byte2);
216 filter2->set_output_val(test_byte3);
217
218 zimg::graph::FilterGraph graph;
219 node_id id_y = graph.add_source({ w, h, type }, 0, 0, enabled_planes(true));
220 id_y = graph.attach_filter(filter1, id_to_map(id_y, true), enabled_planes(true));
221
222 node_id id_u = id_y;
223 node_id id_v = id_y;
224
225 if (x) {
226 id_y = graph.attach_filter(filter2, id_to_map(id_y, false), enabled_planes(false));
227 } else {
228 id_u = graph.attach_filter(filter2, { invalid_id, id_u, invalid_id, invalid_id }, { false, true, false, false });
229 id_v = graph.attach_filter(filter2, { invalid_id, invalid_id, id_v, invalid_id }, { false, false, true, false });
230 }
231
232 graph.set_output({ id_y, id_u, id_v, invalid_id });
233
234 AuditImage<float> src_image{ AuditBufferType::COLOR_YUV, w, h, type, 0, 0 };
235 AuditImage<float> dst_image{ AuditBufferType::COLOR_YUV, w, h, type, 0, 0 };
236 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
237
238 src_image.set_fill_val(test_byte1);
239 src_image.default_fill();
240
241 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
242
243 if (x) {
244 dst_image.set_fill_val(test_byte3, 0);
245 dst_image.set_fill_val(test_byte2, 1);
246 dst_image.set_fill_val(test_byte2, 2);
247 } else {
248 dst_image.set_fill_val(test_byte2, 0);
249 dst_image.set_fill_val(test_byte3, 1);
250 dst_image.set_fill_val(test_byte3, 2);
251 }
252
253 ASSERT_EQ(h, filter1->get_total_calls());
254 ASSERT_EQ(h * (x ? 1 : 2), filter2->get_total_calls());
255
256 SCOPED_TRACE("validating src");
257 src_image.validate();
258 SCOPED_TRACE("validating dst");
259 dst_image.validate();
260 }
261 }
262
TEST(FilterGraphTest,test_color_to_grey)263 TEST(FilterGraphTest, test_color_to_grey)
264 {
265 const unsigned w = 640;
266 const unsigned h = 480;
267 const zimg::PixelType type = zimg::PixelType::BYTE;
268
269 const uint8_t test_byte1 = 0xCD;
270 const uint8_t test_byte2 = 0xDC;
271
272 zimg::graph::ImageFilter::filter_flags flags{};
273 flags.has_state = true;
274 flags.entire_row = true;
275 flags.color = true;
276
277 auto filter = std::make_shared<SplatFilter<uint8_t>>(w, h, type, flags);
278 filter->set_input_val(test_byte1);
279 filter->set_output_val(test_byte2);
280
281 zimg::graph::FilterGraph graph;
282 node_id id = graph.add_source({ w, h, type }, 0, 0, enabled_planes(true));
283
284 id = graph.attach_filter(filter, id_to_map(id, true), enabled_planes(true));
285 graph.set_output(id_to_map(id, false));
286
287 AuditImage<uint8_t> src_image{ AuditBufferType::COLOR_YUV, w, h, type, 0, 0 };
288 AuditImage<uint8_t> dst_image{ AuditBufferType::PLANE, w, h, type, 0, 0 };
289 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
290
291 src_image.set_fill_val(test_byte1);
292 src_image.default_fill();
293
294 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
295
296 dst_image.set_fill_val(test_byte2);
297
298 ASSERT_EQ(h, filter->get_total_calls());
299
300 SCOPED_TRACE("validating src");
301 src_image.validate();
302 SCOPED_TRACE("validating dst");
303 dst_image.validate();
304 }
305
TEST(FilterGraphTest,test_grey_to_color_rgb)306 TEST(FilterGraphTest, test_grey_to_color_rgb)
307 {
308 const unsigned w = 640;
309 const unsigned h = 480;
310 const zimg::PixelType type = zimg::PixelType::BYTE;
311
312 const uint8_t test_byte1 = 0xCD;
313 const uint8_t test_byte2 = 0xDD;
314 const uint8_t test_byte3 = 0xDC;
315
316 zimg::graph::ImageFilter::filter_flags flags1{};
317 flags1.has_state = true;
318 flags1.entire_row = true;
319 flags1.color = false;
320
321 zimg::graph::ImageFilter::filter_flags flags2{};
322 flags2.has_state = true;
323 flags2.entire_row = true;
324 flags2.color = true;
325
326 auto filter1 = std::make_shared<SplatFilter<uint8_t>>(w, h, type, flags1);
327 auto filter2 = std::make_shared<SplatFilter<uint8_t>>(w, h, type, flags2);
328
329 filter1->set_input_val(test_byte1);
330 filter1->set_output_val(test_byte2);
331
332 filter2->set_input_val(test_byte2);
333 filter2->set_output_val(test_byte3);
334
335 zimg::graph::FilterGraph graph;
336 node_id id = graph.add_source({ w, h, type }, 0, 0, enabled_planes(false));
337
338 id = graph.attach_filter(filter1, id_to_map(id, false), enabled_planes(false));
339
340 auto rgbextend = ztd::make_unique<zimg::graph::RGBExtendFilter>(w, h, type);
341 id = graph.attach_filter(std::move(rgbextend), id_to_map(id, false), enabled_planes(true));
342
343 id = graph.attach_filter(filter2, id_to_map(id, true), enabled_planes(true));
344 graph.set_output(id_to_map(id, true));
345
346 AuditImage<uint8_t> src_image{ AuditBufferType::PLANE, w, h, type, 0, 0 };
347 AuditImage<uint8_t> dst_image{ AuditBufferType::COLOR_RGB, w, h, type, 0, 0 };
348 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
349
350 src_image.set_fill_val(test_byte1);
351 src_image.default_fill();
352
353 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
354
355 dst_image.set_fill_val(test_byte3);
356
357 ASSERT_EQ(h, filter1->get_total_calls());
358 ASSERT_EQ(h, filter2->get_total_calls());
359
360 SCOPED_TRACE("validating src");
361 src_image.validate();
362 SCOPED_TRACE("validating dst");
363 dst_image.validate();
364 }
365
TEST(FilterGraphTest,test_grey_to_color_yuv)366 TEST(FilterGraphTest, test_grey_to_color_yuv)
367 {
368 const unsigned w = 640;
369 const unsigned h = 480;
370 const zimg::PixelType type = zimg::PixelType::BYTE;
371
372 const uint8_t test_byte1 = 0xCD;
373 const uint8_t test_byte2 = 0xDD;
374 const uint8_t test_byte2_uv = 128;
375
376 zimg::graph::ImageFilter::filter_flags flags{};
377 flags.has_state = true;
378 flags.entire_row = true;
379 flags.color = false;
380
381 auto filter = std::make_shared<SplatFilter<uint8_t>>(w, h, type, flags);
382 filter->set_input_val(test_byte1);
383 filter->set_output_val(test_byte2);
384
385 zimg::graph::FilterGraph graph;
386 node_id id_y = graph.add_source({ w, h, type }, 0, 0, enabled_planes(false));
387 node_id id_u = id_y;
388 node_id id_v = id_y;
389
390 id_y = graph.attach_filter(filter, id_to_map(id_y, false), enabled_planes(false));
391
392 zimg::graph::ValueInitializeFilter::value_type init_val{};
393 init_val.b = test_byte2_uv;
394 auto chroma_init = std::make_shared<zimg::graph::ValueInitializeFilter>(w >> 1, h >> 1, type, init_val);
395 id_u = graph.attach_filter(chroma_init, zimg::graph::null_ids, { false, true, false, false });
396 id_v = graph.attach_filter(chroma_init, zimg::graph::null_ids, { false, false, true, false });
397
398 graph.set_output({ id_y, id_u, id_v, invalid_id });
399
400 AuditImage<uint8_t> src_image{ AuditBufferType::PLANE, w, h, type, 0, 0 };
401 AuditImage<uint8_t> dst_image{ AuditBufferType::COLOR_YUV, w, h, type, 1, 1 };
402 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
403
404 src_image.set_fill_val(test_byte1);
405 src_image.default_fill();
406
407 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
408
409 dst_image.set_fill_val(test_byte2, 0);
410 dst_image.set_fill_val(test_byte2_uv, 1);
411 dst_image.set_fill_val(test_byte2_uv, 2);
412
413 ASSERT_EQ(h, filter->get_total_calls());
414
415 SCOPED_TRACE("validating src");
416 src_image.validate();
417 SCOPED_TRACE("validating dst");
418 dst_image.validate();
419 }
420
TEST(FilterGraphTest,test_support)421 TEST(FilterGraphTest, test_support)
422 {
423 const unsigned w = 1024;
424 const unsigned h = 576;
425 const zimg::PixelType type = zimg::PixelType::HALF;
426
427 const uint8_t test_byte1 = 0xCD;
428 const uint8_t test_byte2 = 0xDD;
429 const uint8_t test_byte3 = 0xDC;
430
431 for (unsigned x = 0; x < 2; ++x) {
432 SCOPED_TRACE(!!x);
433
434 auto filter1 = std::make_shared<SplatFilter<uint16_t>>(w, h, type);
435 auto filter2 = std::make_shared<SplatFilter<uint16_t>>(w, h, type);
436
437 filter1->set_input_val(test_byte1);
438 filter1->set_output_val(test_byte2);
439
440 filter2->set_input_val(test_byte2);
441 filter2->set_output_val(test_byte3);
442
443 if (x) {
444 filter1->set_horizontal_support(5);
445 filter1->set_simultaneous_lines(5);
446
447 filter2->set_horizontal_support(3);
448 filter2->set_simultaneous_lines(3);
449 } else {
450 filter1->set_horizontal_support(3);
451 filter1->set_simultaneous_lines(3);
452
453 filter2->set_horizontal_support(5);
454 filter2->set_simultaneous_lines(5);
455 }
456
457 zimg::graph::FilterGraph graph;
458 node_id id = graph.add_source({ w, h, type }, 0, 0, enabled_planes(false));
459
460 id = graph.attach_filter(filter1, id_to_map(id, false), enabled_planes(false));
461 id = graph.attach_filter(filter2, id_to_map(id, false), enabled_planes(false));
462 graph.set_output(id_to_map(id, false));
463
464 graph.set_tile_width(512);
465
466 AuditImage<uint16_t> src_image{ AuditBufferType::PLANE, w, h, type, 0, 0 };
467 AuditImage<uint16_t> dst_image{ AuditBufferType::PLANE, w, h, type, 0, 0 };
468 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
469
470 src_image.set_fill_val(test_byte1);
471 src_image.default_fill();
472
473 if (x) {
474 EXPECT_EQ(8U, graph.get_input_buffering());
475 EXPECT_EQ(4U, graph.get_output_buffering());
476 } else {
477 EXPECT_EQ(4U, graph.get_input_buffering());
478 EXPECT_EQ(8U, graph.get_output_buffering());
479 }
480
481 graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), nullptr, nullptr);
482 dst_image.set_fill_val(test_byte3);
483
484 SCOPED_TRACE("validating src");
485 src_image.validate();
486 SCOPED_TRACE("validating dst");
487 dst_image.validate();
488
489 if (x) {
490 EXPECT_EQ(2 * 116U, filter1->get_total_calls());
491 EXPECT_EQ(2 * 192U, filter2->get_total_calls());
492 } else {
493 EXPECT_EQ(2 * 192U, filter1->get_total_calls());
494 EXPECT_EQ(2 * 116U, filter2->get_total_calls());
495 }
496 }
497 }
498
TEST(FilterGraphTest,test_callback)499 TEST(FilterGraphTest, test_callback)
500 {
501 static const unsigned w = 1024;
502 static const unsigned h = 576;
503 const zimg::PixelType type = zimg::PixelType::BYTE;
504
505 const uint8_t test_byte1 = 0xCD;
506 const uint8_t test_byte2 = 0xFF;
507 const uint8_t test_byte3 = 0xDC;
508
509 struct callback_data {
510 zimg::graph::ColorImageBuffer<void> buffer;
511 unsigned subsample_w;
512 unsigned subsample_h;
513 unsigned call_count;
514 uint8_t byte_val;
515 };
516
517 auto cb = [](void *ptr, unsigned i, unsigned left, unsigned right) -> int
518 {
519 callback_data *xptr = static_cast<callback_data *>(ptr);
520
521 if (right > w)
522 return 1;
523
524 EXPECT_LT(i, h);
525 EXPECT_EQ(0U, i % (1 << xptr->subsample_h));
526 EXPECT_LT(left, right);
527 EXPECT_LE(right, w);
528
529 if (HasFailure())
530 return 1;
531
532 for (unsigned ii = i; ii < i + (1 << xptr->subsample_h); ++ii) {
533 const auto &buf = zimg::graph::static_buffer_cast<uint8_t>(xptr->buffer[0]);
534
535 std::fill(buf[ii] + left, buf[ii] + right, xptr->byte_val);
536 }
537 for (unsigned p = 1; p < 3; ++p) {
538 const auto &chroma_buf = zimg::graph::static_buffer_cast<uint8_t>(xptr->buffer[p]);
539 unsigned i_chroma = i >> xptr->subsample_h;
540 unsigned left_chroma = (left % 2 ? left - 1 : left) >> xptr->subsample_w;
541 unsigned right_chroma = (right % 2 ? right + 1 : right) >> xptr->subsample_w;
542
543 std::fill(chroma_buf[i_chroma] + left_chroma, chroma_buf[i_chroma] + right_chroma, xptr->byte_val);
544 }
545
546 ++xptr->call_count;
547 return 0;
548 };
549
550 for (unsigned sw = 0; sw < 3; ++sw) {
551 for (unsigned sh = 0; sh < 3; ++sh) {
552 for (unsigned x = 0; x < 2; ++x) {
553 SCOPED_TRACE(sw);
554 SCOPED_TRACE(sh);
555 SCOPED_TRACE(!!x);
556
557 zimg::graph::ImageFilter::filter_flags flags{};
558 flags.entire_row = !!x;
559 flags.color = false;
560
561 auto filter1 = std::make_shared<SplatFilter<uint8_t>>(w, h, type, flags);
562 auto filter2 = std::make_shared<SplatFilter<uint8_t>>(w >> sw, h >> sh, type, flags);
563
564 filter1->set_input_val(test_byte1);
565 filter1->set_output_val(test_byte2);
566
567 filter2->set_input_val(test_byte1);
568 filter2->set_output_val(test_byte2);
569
570 zimg::graph::FilterGraph graph;
571 node_id id_y = graph.add_source({ w, h, type }, sw, sh, enabled_planes(true));
572 node_id id_u = id_y;
573 node_id id_v = id_y;
574
575 id_y = graph.attach_filter(filter1, id_to_map(id_y, false), enabled_planes(false));
576 id_u = graph.attach_filter(filter2, { invalid_id, id_u, invalid_id, invalid_id }, { false, true, false, false });
577 id_v = graph.attach_filter(filter2, { invalid_id, invalid_id, id_v, invalid_id }, { false, false, true, false });
578 graph.set_output({ id_y, id_u, id_v, invalid_id });
579
580 graph.set_tile_width(512);
581
582 AuditImage<uint8_t> src_image{ AuditBufferType::COLOR_RGB, w, h, type, sw, sh };
583 AuditImage<uint8_t> tmp_image{ AuditBufferType::COLOR_RGB, w, h, type, sw, sh };
584 AuditImage<uint8_t> dst_image{ AuditBufferType::COLOR_RGB, w, h, type, sw, sh };
585 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
586
587 callback_data cb1_data = { src_image.as_write_buffer(), sw, sh, 0, test_byte1 };
588 callback_data cb2_data = { dst_image.as_write_buffer(), sw, sh, 0, test_byte3 };
589
590 src_image.set_fill_val(test_byte1);
591 tmp_image.set_fill_val(test_byte2);
592 dst_image.set_fill_val(test_byte3);
593
594 graph.process(src_image.as_read_buffer(), tmp_image.as_write_buffer(), tmp.data(), { cb, &cb1_data }, { cb, &cb2_data });
595
596 SCOPED_TRACE("validating src");
597 src_image.validate();
598 SCOPED_TRACE("validating tmp");
599 tmp_image.validate();
600 SCOPED_TRACE("validating dst");
601 dst_image.validate();
602
603 EXPECT_EQ((h >> sh) * (x ? 1 : 2), cb1_data.call_count);
604 EXPECT_EQ((h >> sh) * (x ? 1 : 2), cb2_data.call_count);
605 }
606 }
607 }
608 }
609
TEST(FilterGraphTest,test_callback_failed)610 TEST(FilterGraphTest, test_callback_failed)
611 {
612 const unsigned w = 640;
613 const unsigned h = 480;
614 zimg::PixelType type = zimg::PixelType::BYTE;
615
616 auto cb = [](void *, unsigned i, unsigned left, unsigned right) -> int
617 {
618 return 1;
619 };
620
621 zimg::graph::FilterGraph graph;
622 node_id id = graph.add_source({ w, h, type }, 0, 0, enabled_planes(false));
623 graph.set_output(id_to_map(id, false));
624
625 AuditImage<uint8_t> src_image{ AuditBufferType::PLANE, w, h, type, 0, 0 };
626 AuditImage<uint8_t> dst_image{ AuditBufferType::PLANE, w, h, type, 0, 0 };
627 zimg::AlignedVector<char> tmp(graph.get_tmp_size());
628
629 src_image.set_fill_val(255);
630 dst_image.set_fill_val(0);
631
632 src_image.default_fill();
633 dst_image.default_fill();
634
635 ASSERT_THROW(graph.process(src_image.as_read_buffer(), dst_image.as_write_buffer(), tmp.data(), { cb, nullptr }, nullptr), zimg::error::UserCallbackFailed);
636
637 SCOPED_TRACE("validating dst");
638 dst_image.validate();
639 }
640