TestDeinterlacingFilter.cpp (27706B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "gtest/gtest.h" 8 9 #include "mozilla/gfx/2D.h" 10 #include "Common.h" 11 #include "Decoder.h" 12 #include "DecoderFactory.h" 13 #include "SourceBuffer.h" 14 #include "SurfaceFilters.h" 15 #include "SurfacePipe.h" 16 17 using namespace mozilla; 18 using namespace mozilla::gfx; 19 using namespace mozilla::image; 20 21 template <typename Func> 22 void WithDeinterlacingFilter(const IntSize& aSize, bool aProgressiveDisplay, 23 Func aFunc) { 24 RefPtr<image::Decoder> decoder = CreateTrivialDecoder(); 25 ASSERT_TRUE(bool(decoder)); 26 27 WithFilterPipeline( 28 decoder, std::forward<Func>(aFunc), 29 DeinterlacingConfig<uint32_t>{aProgressiveDisplay}, 30 SurfaceConfig{decoder, aSize, SurfaceFormat::OS_RGBA, false}); 31 } 32 33 void AssertConfiguringDeinterlacingFilterFails(const IntSize& aSize) { 34 RefPtr<image::Decoder> decoder = CreateTrivialDecoder(); 35 ASSERT_TRUE(decoder != nullptr); 36 37 AssertConfiguringPipelineFails( 38 decoder, DeinterlacingConfig<uint32_t>{/* mProgressiveDisplay = */ true}, 39 SurfaceConfig{decoder, aSize, SurfaceFormat::OS_RGBA, false}); 40 } 41 42 class ImageDeinterlacingFilter : public ::testing::Test { 43 protected: 44 AutoInitializeImageLib mInit; 45 }; 46 47 TEST_F(ImageDeinterlacingFilter, WritePixels100_100) { 48 WithDeinterlacingFilter( 49 IntSize(100, 100), /* aProgressiveDisplay = */ true, 50 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 51 CheckWritePixels(aDecoder, aFilter, 52 /* aOutputRect = */ Some(IntRect(0, 0, 100, 100)), 53 /* aInputRect = */ Some(IntRect(0, 0, 100, 100))); 54 }); 55 } 56 57 TEST_F(ImageDeinterlacingFilter, WritePixels99_99) { 58 WithDeinterlacingFilter(IntSize(99, 99), /* aProgressiveDisplay = */ true, 59 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 60 CheckWritePixels( 61 aDecoder, aFilter, 62 /* aOutputRect = */ Some(IntRect(0, 0, 99, 99)), 63 /* aInputRect = */ Some(IntRect(0, 0, 99, 99))); 64 }); 65 } 66 67 TEST_F(ImageDeinterlacingFilter, WritePixels8_8) { 68 WithDeinterlacingFilter(IntSize(8, 8), /* aProgressiveDisplay = */ true, 69 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 70 CheckWritePixels( 71 aDecoder, aFilter, 72 /* aOutputRect = */ Some(IntRect(0, 0, 8, 8)), 73 /* aInputRect = */ Some(IntRect(0, 0, 8, 8))); 74 }); 75 } 76 77 TEST_F(ImageDeinterlacingFilter, WritePixels7_7) { 78 WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, 79 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 80 CheckWritePixels( 81 aDecoder, aFilter, 82 /* aOutputRect = */ Some(IntRect(0, 0, 7, 7)), 83 /* aInputRect = */ Some(IntRect(0, 0, 7, 7))); 84 }); 85 } 86 87 TEST_F(ImageDeinterlacingFilter, WritePixels3_3) { 88 WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, 89 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 90 CheckWritePixels( 91 aDecoder, aFilter, 92 /* aOutputRect = */ Some(IntRect(0, 0, 3, 3)), 93 /* aInputRect = */ Some(IntRect(0, 0, 3, 3))); 94 }); 95 } 96 97 TEST_F(ImageDeinterlacingFilter, WritePixels1_1) { 98 WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, 99 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 100 CheckWritePixels( 101 aDecoder, aFilter, 102 /* aOutputRect = */ Some(IntRect(0, 0, 1, 1)), 103 /* aInputRect = */ Some(IntRect(0, 0, 1, 1))); 104 }); 105 } 106 107 TEST_F(ImageDeinterlacingFilter, WritePixelsNonProgressiveOutput51_52) { 108 WithDeinterlacingFilter( 109 IntSize(51, 52), /* aProgressiveDisplay = */ false, 110 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 111 // Fill the image. The output should be green for even rows and red for 112 // odd rows but we need to write the rows in the order that the 113 // deinterlacer expects them. 114 uint32_t count = 0; 115 auto result = aFilter->WritePixels<uint32_t>([&]() { 116 uint32_t row = count / 51; // Integer division. 117 ++count; 118 119 // Note that we use a switch statement here, even though it's quite 120 // verbose, because it's useful to have the mappings between input and 121 // output rows available when debugging these tests. 122 123 switch (row) { 124 // First pass. Output rows are positioned at 8n + 0. 125 case 0: // Output row 0. 126 case 1: // Output row 8. 127 case 2: // Output row 16. 128 case 3: // Output row 24. 129 case 4: // Output row 32. 130 case 5: // Output row 40. 131 case 6: // Output row 48. 132 return AsVariant(BGRAColor::Green().AsPixel()); 133 134 // Second pass. Rows are positioned at 8n + 4. 135 case 7: // Output row 4. 136 case 8: // Output row 12. 137 case 9: // Output row 20. 138 case 10: // Output row 28. 139 case 11: // Output row 36. 140 case 12: // Output row 44. 141 return AsVariant(BGRAColor::Green().AsPixel()); 142 143 // Third pass. Rows are positioned at 4n + 2. 144 case 13: // Output row 2. 145 case 14: // Output row 6. 146 case 15: // Output row 10. 147 case 16: // Output row 14. 148 case 17: // Output row 18. 149 case 18: // Output row 22. 150 case 19: // Output row 26. 151 case 20: // Output row 30. 152 case 21: // Output row 34. 153 case 22: // Output row 38. 154 case 23: // Output row 42. 155 case 24: // Output row 46. 156 case 25: // Output row 50. 157 return AsVariant(BGRAColor::Green().AsPixel()); 158 159 // Fourth pass. Rows are positioned at 2n + 1. 160 case 26: // Output row 1. 161 case 27: // Output row 3. 162 case 28: // Output row 5. 163 case 29: // Output row 7. 164 case 30: // Output row 9. 165 case 31: // Output row 11. 166 case 32: // Output row 13. 167 case 33: // Output row 15. 168 case 34: // Output row 17. 169 case 35: // Output row 19. 170 case 36: // Output row 21. 171 case 37: // Output row 23. 172 case 38: // Output row 25. 173 case 39: // Output row 27. 174 case 40: // Output row 29. 175 case 41: // Output row 31. 176 case 42: // Output row 33. 177 case 43: // Output row 35. 178 case 44: // Output row 37. 179 case 45: // Output row 39. 180 case 46: // Output row 41. 181 case 47: // Output row 43. 182 case 48: // Output row 45. 183 case 49: // Output row 47. 184 case 50: // Output row 49. 185 case 51: // Output row 51. 186 return AsVariant(BGRAColor::Red().AsPixel()); 187 188 default: 189 MOZ_CRASH("Unexpected row"); 190 } 191 }); 192 EXPECT_EQ(WriteState::FINISHED, result); 193 EXPECT_EQ(51u * 52u, count); 194 195 AssertCorrectPipelineFinalState(aFilter, IntRect(0, 0, 51, 52), 196 IntRect(0, 0, 51, 52)); 197 198 // Check that the generated image is correct. As mentioned above, we 199 // expect even rows to be green and odd rows to be red. 200 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 201 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 202 203 for (uint32_t row = 0; row < 52; ++row) { 204 EXPECT_TRUE(RowsAreSolidColor( 205 surface, row, 1, 206 row % 2 == 0 ? BGRAColor::Green() : BGRAColor::Red())); 207 } 208 }); 209 } 210 211 TEST_F(ImageDeinterlacingFilter, WritePixelsOutput20_20) { 212 WithDeinterlacingFilter( 213 IntSize(20, 20), /* aProgressiveDisplay = */ true, 214 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 215 // Fill the image. The output should be green for even rows and red for 216 // odd rows but we need to write the rows in the order that the 217 // deinterlacer expects them. 218 uint32_t count = 0; 219 auto result = aFilter->WritePixels<uint32_t>([&]() { 220 uint32_t row = count / 20; // Integer division. 221 ++count; 222 223 // Note that we use a switch statement here, even though it's quite 224 // verbose, because it's useful to have the mappings between input and 225 // output rows available when debugging these tests. 226 227 switch (row) { 228 // First pass. Output rows are positioned at 8n + 0. 229 case 0: // Output row 0. 230 case 1: // Output row 8. 231 case 2: // Output row 16. 232 return AsVariant(BGRAColor::Green().AsPixel()); 233 234 // Second pass. Rows are positioned at 8n + 4. 235 case 3: // Output row 4. 236 case 4: // Output row 12. 237 return AsVariant(BGRAColor::Green().AsPixel()); 238 239 // Third pass. Rows are positioned at 4n + 2. 240 case 5: // Output row 2. 241 case 6: // Output row 6. 242 case 7: // Output row 10. 243 case 8: // Output row 14. 244 case 9: // Output row 18. 245 return AsVariant(BGRAColor::Green().AsPixel()); 246 247 // Fourth pass. Rows are positioned at 2n + 1. 248 case 10: // Output row 1. 249 case 11: // Output row 3. 250 case 12: // Output row 5. 251 case 13: // Output row 7. 252 case 14: // Output row 9. 253 case 15: // Output row 11. 254 case 16: // Output row 13. 255 case 17: // Output row 15. 256 case 18: // Output row 17. 257 case 19: // Output row 19. 258 return AsVariant(BGRAColor::Red().AsPixel()); 259 260 default: 261 MOZ_CRASH("Unexpected row"); 262 } 263 }); 264 EXPECT_EQ(WriteState::FINISHED, result); 265 EXPECT_EQ(20u * 20u, count); 266 267 AssertCorrectPipelineFinalState(aFilter, IntRect(0, 0, 20, 20), 268 IntRect(0, 0, 20, 20)); 269 270 // Check that the generated image is correct. As mentioned above, we 271 // expect even rows to be green and odd rows to be red. 272 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 273 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 274 275 for (uint32_t row = 0; row < 20; ++row) { 276 EXPECT_TRUE(RowsAreSolidColor( 277 surface, row, 1, 278 row % 2 == 0 ? BGRAColor::Green() : BGRAColor::Red())); 279 } 280 }); 281 } 282 283 TEST_F(ImageDeinterlacingFilter, WritePixelsOutput7_7) { 284 WithDeinterlacingFilter( 285 IntSize(7, 7), /* aProgressiveDisplay = */ true, 286 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 287 // Fill the image. The output should be a repeating pattern of two green 288 // rows followed by two red rows but we need to write the rows in the 289 // order that the deinterlacer expects them. 290 uint32_t count = 0; 291 auto result = aFilter->WritePixels<uint32_t>([&]() { 292 uint32_t row = count / 7; // Integer division. 293 ++count; 294 295 switch (row) { 296 // First pass. Output rows are positioned at 8n + 0. 297 case 0: // Output row 0. 298 return AsVariant(BGRAColor::Green().AsPixel()); 299 300 // Second pass. Rows are positioned at 8n + 4. 301 case 1: // Output row 4. 302 return AsVariant(BGRAColor::Green().AsPixel()); 303 304 // Third pass. Rows are positioned at 4n + 2. 305 case 2: // Output row 2. 306 case 3: // Output row 6. 307 return AsVariant(BGRAColor::Red().AsPixel()); 308 309 // Fourth pass. Rows are positioned at 2n + 1. 310 case 4: // Output row 1. 311 return AsVariant(BGRAColor::Green().AsPixel()); 312 313 case 5: // Output row 3. 314 return AsVariant(BGRAColor::Red().AsPixel()); 315 316 case 6: // Output row 5. 317 return AsVariant(BGRAColor::Green().AsPixel()); 318 319 default: 320 MOZ_CRASH("Unexpected row"); 321 } 322 }); 323 EXPECT_EQ(WriteState::FINISHED, result); 324 EXPECT_EQ(7u * 7u, count); 325 326 AssertCorrectPipelineFinalState(aFilter, IntRect(0, 0, 7, 7), 327 IntRect(0, 0, 7, 7)); 328 329 // Check that the generated image is correct. As mentioned above, we 330 // expect two green rows, followed by two red rows, then two green rows, 331 // etc. 332 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 333 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 334 335 for (uint32_t row = 0; row < 7; ++row) { 336 BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 337 ? BGRAColor::Green() 338 : BGRAColor::Red(); 339 EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); 340 } 341 }); 342 } 343 344 TEST_F(ImageDeinterlacingFilter, WritePixelsOutput3_3) { 345 WithDeinterlacingFilter( 346 IntSize(3, 3), /* aProgressiveDisplay = */ true, 347 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 348 // Fill the image. The output should be green, red, green in that order, 349 // but we need to write the rows in the order that the deinterlacer 350 // expects them. 351 uint32_t count = 0; 352 auto result = aFilter->WritePixels<uint32_t>([&]() { 353 uint32_t row = count / 3; // Integer division. 354 ++count; 355 356 switch (row) { 357 // First pass. Output rows are positioned at 8n + 0. 358 case 0: // Output row 0. 359 return AsVariant(BGRAColor::Green().AsPixel()); 360 361 // Second pass. Rows are positioned at 8n + 4. 362 // No rows for this pass. 363 364 // Third pass. Rows are positioned at 4n + 2. 365 case 1: // Output row 2. 366 return AsVariant(BGRAColor::Green().AsPixel()); 367 368 // Fourth pass. Rows are positioned at 2n + 1. 369 case 2: // Output row 1. 370 return AsVariant(BGRAColor::Red().AsPixel()); 371 372 default: 373 MOZ_CRASH("Unexpected row"); 374 } 375 }); 376 EXPECT_EQ(WriteState::FINISHED, result); 377 EXPECT_EQ(3u * 3u, count); 378 379 AssertCorrectPipelineFinalState(aFilter, IntRect(0, 0, 3, 3), 380 IntRect(0, 0, 3, 3)); 381 382 // Check that the generated image is correct. As mentioned above, we 383 // expect green, red, green in that order. 384 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 385 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 386 387 for (uint32_t row = 0; row < 3; ++row) { 388 EXPECT_TRUE(RowsAreSolidColor( 389 surface, row, 1, 390 row == 0 || row == 2 ? BGRAColor::Green() : BGRAColor::Red())); 391 } 392 }); 393 } 394 395 TEST_F(ImageDeinterlacingFilter, WritePixelsOutput1_1) { 396 WithDeinterlacingFilter( 397 IntSize(1, 1), /* aProgressiveDisplay = */ true, 398 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 399 // Fill the image. The output should be a single red row. 400 uint32_t count = 0; 401 auto result = aFilter->WritePixels<uint32_t>([&]() { 402 ++count; 403 return AsVariant(BGRAColor::Red().AsPixel()); 404 }); 405 EXPECT_EQ(WriteState::FINISHED, result); 406 EXPECT_EQ(1u, count); 407 408 AssertCorrectPipelineFinalState(aFilter, IntRect(0, 0, 1, 1), 409 IntRect(0, 0, 1, 1)); 410 411 // Check that the generated image is correct. As mentioned above, we 412 // expect a single red row. 413 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 414 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 415 416 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 1, BGRAColor::Red())); 417 }); 418 } 419 420 void WriteRowAndCheckInterlacerOutput(image::Decoder* aDecoder, 421 SurfaceFilter* aFilter, BGRAColor aColor, 422 WriteState aNextState, 423 OrientedIntRect aInvalidRect, 424 uint32_t aFirstHaeberliRow, 425 uint32_t aLastHaeberliRow) { 426 uint32_t count = 0; 427 428 auto result = aFilter->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> { 429 if (count < 7) { 430 ++count; 431 return AsVariant(aColor.AsPixel()); 432 } 433 return AsVariant(WriteState::NEED_MORE_DATA); 434 }); 435 436 EXPECT_EQ(aNextState, result); 437 EXPECT_EQ(7u, count); 438 439 // Assert that we got the expected invalidation region. 440 Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect(); 441 EXPECT_TRUE(invalidRect.isSome()); 442 EXPECT_EQ(aInvalidRect, invalidRect->mInputSpaceRect); 443 EXPECT_EQ(aInvalidRect, invalidRect->mOutputSpaceRect); 444 445 // Check that the portion of the image generated so far is correct. The rows 446 // from aFirstHaeberliRow to aLastHaeberliRow should be filled with aColor. 447 // Note that this is not the same as the set of rows in aInvalidRect, because 448 // after writing a row the deinterlacer seeks to the next row to write, which 449 // may involve copying previously-written rows in the buffer to the output 450 // even though they don't change in this pass. 451 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 452 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 453 454 for (uint32_t row = aFirstHaeberliRow; row <= aLastHaeberliRow; ++row) { 455 EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, aColor)); 456 } 457 } 458 459 TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) { 460 WithDeinterlacingFilter( 461 IntSize(7, 7), /* aProgressiveDisplay = */ true, 462 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 463 // Fill the image. The output should be a repeating pattern of two green 464 // rows followed by two red rows but we need to write the rows in the 465 // order that the deinterlacer expects them. 466 467 // First pass. Output rows are positioned at 8n + 0. 468 469 // Output row 0. The invalid rect is the entire image because this is 470 // the end of the first pass. 471 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 472 WriteState::NEED_MORE_DATA, 473 OrientedIntRect(0, 0, 7, 7), 0, 4); 474 475 // Second pass. Rows are positioned at 8n + 4. 476 477 // Output row 4. The invalid rect is the entire image because this is 478 // the end of the second pass. 479 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 480 WriteState::NEED_MORE_DATA, 481 OrientedIntRect(0, 0, 7, 7), 1, 4); 482 483 // Third pass. Rows are positioned at 4n + 2. 484 485 // Output row 2. The invalid rect contains the Haeberli rows for this 486 // output row (rows 2 and 3) as well as the rows that we copy from 487 // previous passes when seeking to the next output row (rows 4 and 5). 488 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), 489 WriteState::NEED_MORE_DATA, 490 OrientedIntRect(0, 2, 7, 4), 2, 3); 491 492 // Output row 6. The invalid rect is the entire image because this is 493 // the end of the third pass. 494 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), 495 WriteState::NEED_MORE_DATA, 496 OrientedIntRect(0, 0, 7, 7), 6, 6); 497 498 // Fourth pass. Rows are positioned at 2n + 1. 499 500 // Output row 1. The invalid rect contains the Haeberli rows for this 501 // output row (just row 1) as well as the rows that we copy from 502 // previous passes when seeking to the next output row (row 2). 503 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 504 WriteState::NEED_MORE_DATA, 505 OrientedIntRect(0, 1, 7, 2), 1, 1); 506 507 // Output row 3. The invalid rect contains the Haeberli rows for this 508 // output row (just row 3) as well as the rows that we copy from 509 // previous passes when seeking to the next output row (row 4). 510 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), 511 WriteState::NEED_MORE_DATA, 512 OrientedIntRect(0, 3, 7, 2), 3, 3); 513 514 // Output row 5. The invalid rect contains the Haeberli rows for this 515 // output row (just row 5) as well as the rows that we copy from 516 // previous passes when seeking to the next output row (row 6). 517 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 518 WriteState::FINISHED, 519 OrientedIntRect(0, 5, 7, 2), 5, 5); 520 521 // Assert that we're in the expected final state. 522 EXPECT_TRUE(aFilter->IsSurfaceFinished()); 523 Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect(); 524 EXPECT_TRUE(invalidRect.isNothing()); 525 526 // Check that the generated image is correct. As mentioned above, we 527 // expect two green rows, followed by two red rows, then two green rows, 528 // etc. 529 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 530 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 531 532 for (uint32_t row = 0; row < 7; ++row) { 533 BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 534 ? BGRAColor::Green() 535 : BGRAColor::Red(); 536 EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); 537 } 538 }); 539 } 540 541 TEST_F(ImageDeinterlacingFilter, 542 WritePixelsNonProgressiveIntermediateOutput7_7) { 543 WithDeinterlacingFilter( 544 IntSize(7, 7), /* aProgressiveDisplay = */ false, 545 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 546 // Fill the image. The output should be a repeating pattern of two green 547 // rows followed by two red rows but we need to write the rows in the 548 // order that the deinterlacer expects them. 549 550 // First pass. Output rows are positioned at 8n + 0. 551 552 // Output row 0. The invalid rect is the entire image because this is 553 // the end of the first pass. 554 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 555 WriteState::NEED_MORE_DATA, 556 OrientedIntRect(0, 0, 7, 7), 0, 0); 557 558 // Second pass. Rows are positioned at 8n + 4. 559 560 // Output row 4. The invalid rect is the entire image because this is 561 // the end of the second pass. 562 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 563 WriteState::NEED_MORE_DATA, 564 OrientedIntRect(0, 0, 7, 7), 4, 4); 565 566 // Third pass. Rows are positioned at 4n + 2. 567 568 // Output row 2. The invalid rect contains the Haeberli rows for this 569 // output row (rows 2 and 3) as well as the rows that we copy from 570 // previous passes when seeking to the next output row (rows 4 and 5). 571 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), 572 WriteState::NEED_MORE_DATA, 573 OrientedIntRect(0, 2, 7, 4), 2, 2); 574 575 // Output row 6. The invalid rect is the entire image because this is 576 // the end of the third pass. 577 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), 578 WriteState::NEED_MORE_DATA, 579 OrientedIntRect(0, 0, 7, 7), 6, 6); 580 581 // Fourth pass. Rows are positioned at 2n + 1. 582 583 // Output row 1. The invalid rect contains the Haeberli rows for this 584 // output row (just row 1) as well as the rows that we copy from 585 // previous passes when seeking to the next output row (row 2). 586 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 587 WriteState::NEED_MORE_DATA, 588 OrientedIntRect(0, 1, 7, 2), 1, 1); 589 590 // Output row 3. The invalid rect contains the Haeberli rows for this 591 // output row (just row 3) as well as the rows that we copy from 592 // previous passes when seeking to the next output row (row 4). 593 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(), 594 WriteState::NEED_MORE_DATA, 595 OrientedIntRect(0, 3, 7, 2), 3, 3); 596 597 // Output row 5. The invalid rect contains the Haeberli rows for this 598 // output row (just row 5) as well as the rows that we copy from 599 // previous passes when seeking to the next output row (row 6). 600 WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(), 601 WriteState::FINISHED, 602 OrientedIntRect(0, 5, 7, 2), 5, 5); 603 604 // Assert that we're in the expected final state. 605 EXPECT_TRUE(aFilter->IsSurfaceFinished()); 606 Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect(); 607 EXPECT_TRUE(invalidRect.isNothing()); 608 609 // Check that the generated image is correct. As mentioned above, we 610 // expect two green rows, followed by two red rows, then two green rows, 611 // etc. 612 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 613 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 614 615 for (uint32_t row = 0; row < 7; ++row) { 616 BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5 617 ? BGRAColor::Green() 618 : BGRAColor::Red(); 619 EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color)); 620 } 621 }); 622 } 623 624 TEST_F(ImageDeinterlacingFilter, DeinterlacingFailsFor0_0) { 625 // A 0x0 input size is invalid, so configuration should fail. 626 AssertConfiguringDeinterlacingFilterFails(IntSize(0, 0)); 627 } 628 629 TEST_F(ImageDeinterlacingFilter, DeinterlacingFailsForMinus1_Minus1) { 630 // A negative input size is invalid, so configuration should fail. 631 AssertConfiguringDeinterlacingFilterFails(IntSize(-1, -1)); 632 }