TestDecoders.cpp (43020B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "gtest/gtest.h" 6 7 #include "Common.h" 8 #include "mozilla/Monitor.h" 9 #include "AnimationSurfaceProvider.h" 10 #include "DecodePool.h" 11 #include "Decoder.h" 12 #include "DecoderFactory.h" 13 #include "decoders/nsBMPDecoder.h" 14 #include "IDecodingTask.h" 15 #include "ImageOps.h" 16 #include "imgIContainer.h" 17 #include "ImageFactory.h" 18 #include "mozilla/ScopeExit.h" 19 #include "mozilla/gfx/2D.h" 20 #include "nsComponentManagerUtils.h" 21 #include "nsCOMPtr.h" 22 #include "nsIInputStream.h" 23 #include "mozilla/RefPtr.h" 24 #include "nsStreamUtils.h" 25 #include "nsString.h" 26 #include "nsThreadUtils.h" 27 #include "ProgressTracker.h" 28 #include "SourceBuffer.h" 29 30 using namespace mozilla; 31 using namespace mozilla::gfx; 32 using namespace mozilla::image; 33 34 static already_AddRefed<SourceSurface> CheckDecoderState( 35 const ImageTestCase& aTestCase, image::Decoder* aDecoder) { 36 // image::Decoder should match what we asked for in the MIME type. 37 EXPECT_NE(aDecoder->GetType(), DecoderType::UNKNOWN); 38 EXPECT_EQ(aDecoder->GetType(), 39 DecoderFactory::GetDecoderType(aTestCase.mMimeType)); 40 41 EXPECT_TRUE(aDecoder->GetDecodeDone()); 42 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), aDecoder->HasError()); 43 44 // Verify that the decoder made the expected progress. 45 Progress progress = aDecoder->TakeProgress(); 46 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), 47 bool(progress & FLAG_HAS_ERROR)); 48 49 if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) { 50 return nullptr; // That's all we can check for bad images. 51 } 52 53 EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE)); 54 EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE)); 55 EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE)); 56 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT), 57 bool(progress & FLAG_HAS_TRANSPARENCY)); 58 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED), 59 bool(progress & FLAG_IS_ANIMATED)); 60 61 // The decoder should get the correct size. 62 OrientedIntSize size = aDecoder->Size(); 63 EXPECT_EQ(aTestCase.mSize.width, size.width); 64 EXPECT_EQ(aTestCase.mSize.height, size.height); 65 66 // Get the current frame, which is always the first frame of the image 67 // because CreateAnonymousDecoder() forces a first-frame-only decode. 68 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 69 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 70 71 // Verify that the resulting surfaces matches our expectations. 72 EXPECT_TRUE(surface->IsDataSourceSurface()); 73 EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::OS_RGBX || 74 surface->GetFormat() == SurfaceFormat::OS_RGBA); 75 EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize()); 76 77 return surface.forget(); 78 } 79 80 static void CheckDecoderResults(const ImageTestCase& aTestCase, 81 image::Decoder* aDecoder) { 82 RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder); 83 if (!surface) { 84 return; 85 } 86 87 if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) { 88 return; 89 } 90 91 // Check the output. 92 EXPECT_TRUE(IsSolidColor(surface, aTestCase.Color(), aTestCase.Fuzz())); 93 } 94 95 template <typename Func> 96 void WithBadBufferDecode(const ImageTestCase& aTestCase, 97 const Maybe<IntSize>& aOutputSize, 98 Func aResultChecker) { 99 // Prepare a SourceBuffer with an error that will immediately move iterators 100 // to COMPLETE. 101 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>(); 102 sourceBuffer->ExpectLength(SIZE_MAX); 103 104 // Create a decoder. 105 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); 106 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder( 107 decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY, 108 aTestCase.mSurfaceFlags); 109 ASSERT_TRUE(decoder != nullptr); 110 RefPtr<IDecodingTask> task = 111 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false); 112 113 // Run the full decoder synchronously on the main thread. 114 task->Run(); 115 116 // Call the lambda to verify the expected results. 117 aResultChecker(decoder); 118 } 119 120 static void CheckDecoderBadBuffer(const ImageTestCase& aTestCase) { 121 WithBadBufferDecode(aTestCase, Nothing(), [&](image::Decoder* aDecoder) { 122 CheckDecoderResults(aTestCase, aDecoder); 123 }); 124 } 125 126 /** 127 * AnonymousDecodingTask but with a monitor so we can wait for it to finish 128 * safely. 129 */ 130 class MonitorAnonymousDecodingTask final : public AnonymousDecodingTask { 131 public: 132 explicit MonitorAnonymousDecodingTask(NotNull<Decoder*> aDecoder, 133 bool aResumable); 134 135 void Run() override; 136 137 void WaitUntilFinished(); 138 139 private: 140 virtual ~MonitorAnonymousDecodingTask() = default; 141 142 Monitor mMonitor MOZ_UNANNOTATED; 143 }; 144 145 MonitorAnonymousDecodingTask::MonitorAnonymousDecodingTask( 146 NotNull<Decoder*> aDecoder, bool aResumable) 147 : AnonymousDecodingTask(aDecoder, aResumable), 148 mMonitor("MonitorAnonymousDecodingTask") {} 149 150 void MonitorAnonymousDecodingTask::Run() { 151 MonitorAutoLock lock(mMonitor); 152 153 while (true) { 154 LexerResult result = mDecoder->Decode(WrapNotNull(this)); 155 156 if (result.is<TerminalState>()) { 157 mMonitor.NotifyAll(); 158 return; // We're done. 159 } 160 161 if (result == LexerResult(Yield::NEED_MORE_DATA)) { 162 // We can't make any more progress right now. Let the caller decide how to 163 // handle it. 164 mMonitor.NotifyAll(); 165 return; 166 } 167 168 // Right now we don't do anything special for other kinds of yields, so just 169 // keep working. 170 MOZ_ASSERT(result.is<Yield>()); 171 } 172 } 173 174 void MonitorAnonymousDecodingTask::WaitUntilFinished() { 175 MonitorAutoLock lock(mMonitor); 176 177 while (true) { 178 if (mDecoder->GetDecodeDone()) { 179 return; 180 } 181 182 // Not done yet, so we'll have to wait. 183 mMonitor.Wait(); 184 } 185 } 186 187 template <typename Func> 188 void WithSingleChunkDecode(const ImageTestCase& aTestCase, 189 const Maybe<IntSize>& aOutputSize, 190 bool aUseDecodePool, Func aResultChecker) { 191 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); 192 ASSERT_TRUE(inputStream != nullptr); 193 194 // Figure out how much data we have. 195 uint64_t length; 196 nsresult rv = inputStream->Available(&length); 197 ASSERT_NS_SUCCEEDED(rv); 198 199 // Write the data into a SourceBuffer. 200 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>(); 201 sourceBuffer->ExpectLength(length); 202 rv = sourceBuffer->AppendFromInputStream(inputStream, length); 203 ASSERT_NS_SUCCEEDED(rv); 204 sourceBuffer->Complete(NS_OK); 205 206 // Create a decoder. 207 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); 208 DecoderFlags decoderFlags = 209 DecoderFactory::GetDefaultDecoderFlagsForType(decoderType) | 210 DecoderFlags::FIRST_FRAME_ONLY; 211 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder( 212 decoderType, sourceBuffer, aOutputSize, decoderFlags, 213 aTestCase.mSurfaceFlags); 214 ASSERT_TRUE(decoder != nullptr); 215 RefPtr<MonitorAnonymousDecodingTask> task = new MonitorAnonymousDecodingTask( 216 WrapNotNull(decoder), /* aResumable */ false); 217 218 if (aUseDecodePool) { 219 DecodePool::Singleton()->AsyncRun(task.get()); 220 221 task->WaitUntilFinished(); 222 } else { // Run the full decoder synchronously on the main thread. 223 task->Run(); 224 } 225 226 // Call the lambda to verify the expected results. 227 aResultChecker(decoder); 228 } 229 230 static void CheckDecoderSingleChunk(const ImageTestCase& aTestCase, 231 bool aUseDecodePool = false) { 232 WithSingleChunkDecode(aTestCase, Nothing(), aUseDecodePool, 233 [&](image::Decoder* aDecoder) { 234 CheckDecoderResults(aTestCase, aDecoder); 235 }); 236 } 237 238 template <typename Func> 239 void WithDelayedChunkDecode(const ImageTestCase& aTestCase, 240 const Maybe<IntSize>& aOutputSize, 241 Func aResultChecker) { 242 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); 243 ASSERT_TRUE(inputStream != nullptr); 244 245 // Figure out how much data we have. 246 uint64_t length; 247 nsresult rv = inputStream->Available(&length); 248 ASSERT_NS_SUCCEEDED(rv); 249 250 // Prepare an empty SourceBuffer. 251 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>(); 252 253 // Create a decoder. 254 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); 255 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder( 256 decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY, 257 aTestCase.mSurfaceFlags); 258 ASSERT_TRUE(decoder != nullptr); 259 RefPtr<IDecodingTask> task = 260 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ true); 261 262 // Run the full decoder synchronously. It should now be waiting on 263 // the iterator to yield some data since we haven't written anything yet. 264 task->Run(); 265 266 // Writing all of the data should wake up the decoder to complete. 267 sourceBuffer->ExpectLength(length); 268 rv = sourceBuffer->AppendFromInputStream(inputStream, length); 269 ASSERT_NS_SUCCEEDED(rv); 270 sourceBuffer->Complete(NS_OK); 271 272 // It would have gotten posted to the main thread to avoid mutex contention. 273 SpinPendingEvents(); 274 275 // Call the lambda to verify the expected results. 276 aResultChecker(decoder); 277 } 278 279 static void CheckDecoderDelayedChunk(const ImageTestCase& aTestCase) { 280 WithDelayedChunkDecode(aTestCase, Nothing(), [&](image::Decoder* aDecoder) { 281 CheckDecoderResults(aTestCase, aDecoder); 282 }); 283 } 284 285 static void CheckDecoderMultiChunk(const ImageTestCase& aTestCase, 286 uint64_t aChunkSize = 1) { 287 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); 288 ASSERT_TRUE(inputStream != nullptr); 289 290 // Figure out how much data we have. 291 uint64_t length; 292 nsresult rv = inputStream->Available(&length); 293 ASSERT_NS_SUCCEEDED(rv); 294 295 // Create a SourceBuffer and a decoder. 296 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>(); 297 sourceBuffer->ExpectLength(length); 298 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); 299 DecoderFlags decoderFlags = 300 DecoderFactory::GetDefaultDecoderFlagsForType(decoderType) | 301 DecoderFlags::FIRST_FRAME_ONLY; 302 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder( 303 decoderType, sourceBuffer, Nothing(), decoderFlags, 304 aTestCase.mSurfaceFlags); 305 ASSERT_TRUE(decoder != nullptr); 306 RefPtr<IDecodingTask> task = 307 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ true); 308 309 // Run the full decoder synchronously. It should now be waiting on 310 // the iterator to yield some data since we haven't written anything yet. 311 task->Run(); 312 313 while (length > 0) { 314 uint64_t read = length > aChunkSize ? aChunkSize : length; 315 length -= read; 316 317 uint64_t available = 0; 318 rv = inputStream->Available(&available); 319 ASSERT_TRUE(available >= read); 320 ASSERT_NS_SUCCEEDED(rv); 321 322 // Writing any data should wake up the decoder to complete. 323 rv = sourceBuffer->AppendFromInputStream(inputStream, read); 324 ASSERT_NS_SUCCEEDED(rv); 325 326 // It would have gotten posted to the main thread to avoid mutex contention. 327 SpinPendingEvents(); 328 } 329 330 sourceBuffer->Complete(NS_OK); 331 SpinPendingEvents(); 332 333 CheckDecoderResults(aTestCase, decoder); 334 } 335 336 static void CheckDownscaleDuringDecode(const ImageTestCase& aTestCase) { 337 // This function expects that |aTestCase| consists of 25 lines of green, 338 // followed by 25 lines of red, followed by 25 lines of green, followed by 25 339 // more lines of red. We'll downscale it from 100x100 to 20x20. 340 IntSize outputSize(20, 20); 341 342 WithSingleChunkDecode( 343 aTestCase, Some(outputSize), /* aUseDecodePool */ false, 344 [&](image::Decoder* aDecoder) { 345 RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder); 346 347 // There are no downscale-during-decode tests that have 348 // TEST_CASE_HAS_ERROR set, so we expect to always get a surface here. 349 EXPECT_TRUE(surface != nullptr); 350 351 if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) { 352 return; 353 } 354 355 // Check that the downscaled image is correct. Note that we skip rows 356 // near the transitions between colors, since the downscaler does not 357 // produce a sharp boundary at these points. Even some of the rows we 358 // test need a small amount of fuzz; this is just the nature of Lanczos 359 // downscaling. 360 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, 361 aTestCase.ChooseColor(BGRAColor::Green()), 362 /* aFuzz = */ 47)); 363 EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, 364 aTestCase.ChooseColor(BGRAColor::Red()), 365 /* aFuzz = */ 27)); 366 EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), 367 /* aFuzz = */ 47)); 368 EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, 369 aTestCase.ChooseColor(BGRAColor::Red()), 370 /* aFuzz = */ 27)); 371 }); 372 } 373 374 static void CheckAnimationDecoderResults(const ImageTestCase& aTestCase, 375 AnimationSurfaceProvider* aProvider, 376 image::Decoder* aDecoder) { 377 EXPECT_TRUE(aDecoder->GetDecodeDone()); 378 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), aDecoder->HasError()); 379 380 if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) { 381 return; // That's all we can check for bad images. 382 } 383 384 // The decoder should get the correct size. 385 OrientedIntSize size = aDecoder->Size(); 386 EXPECT_EQ(aTestCase.mSize.width, size.width); 387 EXPECT_EQ(aTestCase.mSize.height, size.height); 388 389 if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) { 390 return; 391 } 392 393 // Check the output. 394 AutoTArray<BGRAColor, 2> framePixels; 395 framePixels.AppendElement(aTestCase.ChooseColor(BGRAColor::Green())); 396 framePixels.AppendElement( 397 aTestCase.ChooseColor(BGRAColor(0x7F, 0x7F, 0x7F, 0xFF))); 398 399 DrawableSurface drawableSurface(WrapNotNull(aProvider)); 400 for (size_t i = 0; i < framePixels.Length(); ++i) { 401 nsresult rv = drawableSurface.Seek(i); 402 EXPECT_NS_SUCCEEDED(rv); 403 404 // Check the first frame, all green. 405 RawAccessFrameRef rawFrame = drawableSurface->RawAccessRef(); 406 RefPtr<SourceSurface> surface = rawFrame->GetSourceSurface(); 407 408 // Verify that the resulting surfaces matches our expectations. 409 EXPECT_TRUE(surface->IsDataSourceSurface()); 410 EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::OS_RGBX || 411 surface->GetFormat() == SurfaceFormat::OS_RGBA); 412 EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize()); 413 EXPECT_TRUE(IsSolidColor(surface, framePixels[i], aTestCase.Fuzz())); 414 } 415 416 // Should be no more frames. 417 nsresult rv = drawableSurface.Seek(framePixels.Length()); 418 EXPECT_NS_FAILED(rv); 419 } 420 421 template <typename Func> 422 static void WithSingleChunkAnimationDecode(const ImageTestCase& aTestCase, 423 Func aResultChecker) { 424 // Create an image. 425 RefPtr<Image> image = ImageFactory::CreateAnonymousImage( 426 nsDependentCString(aTestCase.mMimeType)); 427 ASSERT_TRUE(!image->HasError()); 428 429 NotNull<RefPtr<RasterImage>> rasterImage = 430 WrapNotNull(static_cast<RasterImage*>(image.get())); 431 432 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); 433 ASSERT_TRUE(inputStream != nullptr); 434 435 // Figure out how much data we have. 436 uint64_t length; 437 nsresult rv = inputStream->Available(&length); 438 ASSERT_NS_SUCCEEDED(rv); 439 440 // Write the data into a SourceBuffer. 441 NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer()); 442 sourceBuffer->ExpectLength(length); 443 rv = sourceBuffer->AppendFromInputStream(inputStream, length); 444 ASSERT_NS_SUCCEEDED(rv); 445 sourceBuffer->Complete(NS_OK); 446 447 // Create a metadata decoder first, because otherwise RasterImage will get 448 // unhappy about finding out the image is animated during a full decode. 449 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType); 450 DecoderFlags decoderFlags = 451 DecoderFactory::GetDefaultDecoderFlagsForType(decoderType); 452 RefPtr<IDecodingTask> task = DecoderFactory::CreateMetadataDecoder( 453 decoderType, rasterImage, decoderFlags, sourceBuffer); 454 ASSERT_TRUE(task != nullptr); 455 456 // Run the metadata decoder synchronously. 457 task->Run(); 458 459 // Create a decoder. 460 SurfaceFlags surfaceFlags = aTestCase.mSurfaceFlags; 461 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder( 462 decoderType, sourceBuffer, Nothing(), decoderFlags, surfaceFlags); 463 ASSERT_TRUE(decoder != nullptr); 464 465 // Create an AnimationSurfaceProvider which will manage the decoding process 466 // and make this decoder's output available in the surface cache. 467 SurfaceKey surfaceKey = RasterSurfaceKey(aTestCase.mOutputSize, surfaceFlags, 468 PlaybackType::eAnimated); 469 RefPtr<AnimationSurfaceProvider> provider = new AnimationSurfaceProvider( 470 rasterImage, surfaceKey, WrapNotNull(decoder), 471 /* aCurrentFrame */ 0); 472 473 // Run the full decoder synchronously. 474 provider->Run(); 475 476 // Call the lambda to verify the expected results. 477 aResultChecker(provider, decoder); 478 } 479 480 static void CheckAnimationDecoderSingleChunk(const ImageTestCase& aTestCase) { 481 WithSingleChunkAnimationDecode( 482 aTestCase, 483 [&](AnimationSurfaceProvider* aProvider, image::Decoder* aDecoder) { 484 CheckAnimationDecoderResults(aTestCase, aProvider, aDecoder); 485 }); 486 } 487 488 static void CheckDecoderFrameFirst(const ImageTestCase& aTestCase) { 489 // Verify that we can decode this test case and retrieve the first frame using 490 // imgIContainer::FRAME_FIRST. This ensures that we correctly trigger a 491 // single-frame decode rather than an animated decode when 492 // imgIContainer::FRAME_FIRST is requested. 493 494 // Create an image. 495 RefPtr<Image> image = ImageFactory::CreateAnonymousImage( 496 nsDependentCString(aTestCase.mMimeType)); 497 ASSERT_TRUE(!image->HasError()); 498 499 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); 500 ASSERT_TRUE(inputStream); 501 502 // Figure out how much data we have. 503 uint64_t length; 504 nsresult rv = inputStream->Available(&length); 505 ASSERT_NS_SUCCEEDED(rv); 506 507 // Write the data into the image. 508 rv = image->OnImageDataAvailable(nullptr, inputStream, 0, 509 static_cast<uint32_t>(length)); 510 ASSERT_NS_SUCCEEDED(rv); 511 512 // Let the image know we've sent all the data. 513 rv = image->OnImageDataComplete(nullptr, NS_OK, true); 514 ASSERT_NS_SUCCEEDED(rv); 515 516 RefPtr<ProgressTracker> tracker = image->GetProgressTracker(); 517 tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); 518 519 // Lock the image so its surfaces don't disappear during the test. 520 image->LockImage(); 521 522 auto unlock = mozilla::MakeScopeExit([&] { image->UnlockImage(); }); 523 524 // Use GetFrame() to force a sync decode of the image, specifying FRAME_FIRST 525 // to ensure that we don't get an animated decode. 526 RefPtr<SourceSurface> surface = image->GetFrame( 527 imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE); 528 529 // Ensure that the image's metadata meets our expectations. 530 IntSize imageSize(0, 0); 531 rv = image->GetWidth(&imageSize.width); 532 EXPECT_NS_SUCCEEDED(rv); 533 rv = image->GetHeight(&imageSize.height); 534 EXPECT_NS_SUCCEEDED(rv); 535 536 EXPECT_EQ(aTestCase.mSize.width, imageSize.width); 537 EXPECT_EQ(aTestCase.mSize.height, imageSize.height); 538 539 Progress imageProgress = tracker->GetProgress(); 540 541 EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false); 542 EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true); 543 544 // Ensure that we decoded the static version of the image. 545 { 546 LookupResult result = SurfaceCache::Lookup( 547 ImageKey(image.get()), 548 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 549 PlaybackType::eStatic), 550 /* aMarkUsed = */ false); 551 ASSERT_EQ(MatchType::EXACT, result.Type()); 552 EXPECT_TRUE(bool(result.Surface())); 553 } 554 555 // Ensure that we didn't decode the animated version of the image. 556 { 557 LookupResult result = SurfaceCache::Lookup( 558 ImageKey(image.get()), 559 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 560 PlaybackType::eAnimated), 561 /* aMarkUsed = */ false); 562 ASSERT_EQ(MatchType::NOT_FOUND, result.Type()); 563 } 564 565 // Use GetFrame() to force a sync decode of the image, this time specifying 566 // FRAME_CURRENT to ensure that we get an animated decode. 567 RefPtr<SourceSurface> animatedSurface = image->GetFrame( 568 imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); 569 570 // Ensure that we decoded both frames of the animated version of the image. 571 { 572 LookupResult result = SurfaceCache::Lookup( 573 ImageKey(image.get()), 574 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 575 PlaybackType::eAnimated), 576 /* aMarkUsed = */ true); 577 ASSERT_EQ(MatchType::EXACT, result.Type()); 578 579 EXPECT_NS_SUCCEEDED(result.Surface().Seek(0)); 580 EXPECT_TRUE(bool(result.Surface())); 581 582 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1); 583 EXPECT_TRUE(bool(partialFrame)); 584 } 585 586 // Ensure that the static version is still around. 587 { 588 LookupResult result = SurfaceCache::Lookup( 589 ImageKey(image.get()), 590 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 591 PlaybackType::eStatic), 592 /* aMarkUsed = */ true); 593 ASSERT_EQ(MatchType::EXACT, result.Type()); 594 EXPECT_TRUE(bool(result.Surface())); 595 } 596 } 597 598 static void CheckDecoderFrameCurrent(const ImageTestCase& aTestCase) { 599 // Verify that we can decode this test case and retrieve the entire sequence 600 // of frames using imgIContainer::FRAME_CURRENT. This ensures that we 601 // correctly trigger an animated decode rather than a single-frame decode when 602 // imgIContainer::FRAME_CURRENT is requested. 603 604 // Create an image. 605 RefPtr<Image> image = ImageFactory::CreateAnonymousImage( 606 nsDependentCString(aTestCase.mMimeType)); 607 ASSERT_TRUE(!image->HasError()); 608 609 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath); 610 ASSERT_TRUE(inputStream); 611 612 // Figure out how much data we have. 613 uint64_t length; 614 nsresult rv = inputStream->Available(&length); 615 ASSERT_NS_SUCCEEDED(rv); 616 617 // Write the data into the image. 618 rv = image->OnImageDataAvailable(nullptr, inputStream, 0, 619 static_cast<uint32_t>(length)); 620 ASSERT_NS_SUCCEEDED(rv); 621 622 // Let the image know we've sent all the data. 623 rv = image->OnImageDataComplete(nullptr, NS_OK, true); 624 ASSERT_NS_SUCCEEDED(rv); 625 626 RefPtr<ProgressTracker> tracker = image->GetProgressTracker(); 627 tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); 628 629 // Lock the image so its surfaces don't disappear during the test. 630 image->LockImage(); 631 632 // Use GetFrame() to force a sync decode of the image, specifying 633 // FRAME_CURRENT to ensure we get an animated decode. 634 RefPtr<SourceSurface> surface = image->GetFrame( 635 imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); 636 637 // Ensure that the image's metadata meets our expectations. 638 IntSize imageSize(0, 0); 639 rv = image->GetWidth(&imageSize.width); 640 EXPECT_NS_SUCCEEDED(rv); 641 rv = image->GetHeight(&imageSize.height); 642 EXPECT_NS_SUCCEEDED(rv); 643 644 EXPECT_EQ(aTestCase.mSize.width, imageSize.width); 645 EXPECT_EQ(aTestCase.mSize.height, imageSize.height); 646 647 Progress imageProgress = tracker->GetProgress(); 648 649 EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false); 650 EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true); 651 652 // Ensure that we decoded both frames of the animated version of the image. 653 { 654 LookupResult result = SurfaceCache::Lookup( 655 ImageKey(image.get()), 656 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 657 PlaybackType::eAnimated), 658 /* aMarkUsed = */ true); 659 ASSERT_EQ(MatchType::EXACT, result.Type()); 660 661 EXPECT_NS_SUCCEEDED(result.Surface().Seek(0)); 662 EXPECT_TRUE(bool(result.Surface())); 663 664 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1); 665 EXPECT_TRUE(bool(partialFrame)); 666 } 667 668 // Ensure that we didn't decode the static version of the image. 669 { 670 LookupResult result = SurfaceCache::Lookup( 671 ImageKey(image.get()), 672 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 673 PlaybackType::eStatic), 674 /* aMarkUsed = */ false); 675 ASSERT_EQ(MatchType::NOT_FOUND, result.Type()); 676 } 677 678 // Use GetFrame() to force a sync decode of the image, this time specifying 679 // FRAME_FIRST to ensure that we get a single-frame decode. 680 RefPtr<SourceSurface> animatedSurface = image->GetFrame( 681 imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE); 682 683 // Ensure that we decoded the static version of the image. 684 { 685 LookupResult result = SurfaceCache::Lookup( 686 ImageKey(image.get()), 687 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 688 PlaybackType::eStatic), 689 /* aMarkUsed = */ true); 690 ASSERT_EQ(MatchType::EXACT, result.Type()); 691 EXPECT_TRUE(bool(result.Surface())); 692 } 693 694 // Ensure that both frames of the animated version are still around. 695 { 696 LookupResult result = SurfaceCache::Lookup( 697 ImageKey(image.get()), 698 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags, 699 PlaybackType::eAnimated), 700 /* aMarkUsed = */ true); 701 ASSERT_EQ(MatchType::EXACT, result.Type()); 702 703 EXPECT_NS_SUCCEEDED(result.Surface().Seek(0)); 704 EXPECT_TRUE(bool(result.Surface())); 705 706 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1); 707 EXPECT_TRUE(bool(partialFrame)); 708 } 709 } 710 711 class ImageDecoders : public ::testing::Test { 712 protected: 713 AutoInitializeImageLib mInit; 714 }; 715 716 #define IMAGE_GTEST_DECODER_BASE_F(test_prefix) \ 717 TEST_F(ImageDecoders, test_prefix##SingleChunk) { \ 718 CheckDecoderSingleChunk(Green##test_prefix##TestCase()); \ 719 } \ 720 \ 721 TEST_F(ImageDecoders, test_prefix##DelayedChunk) { \ 722 CheckDecoderDelayedChunk(Green##test_prefix##TestCase()); \ 723 } \ 724 \ 725 TEST_F(ImageDecoders, test_prefix##MultiChunk) { \ 726 CheckDecoderMultiChunk(Green##test_prefix##TestCase()); \ 727 } \ 728 \ 729 TEST_F(ImageDecoders, test_prefix##DownscaleDuringDecode) { \ 730 CheckDownscaleDuringDecode(Downscaled##test_prefix##TestCase()); \ 731 } \ 732 \ 733 TEST_F(ImageDecoders, test_prefix##ForceSRGB) { \ 734 CheckDecoderSingleChunk(Green##test_prefix##TestCase().WithSurfaceFlags( \ 735 SurfaceFlags::TO_SRGB_COLORSPACE)); \ 736 } \ 737 \ 738 TEST_F(ImageDecoders, test_prefix##BadBuffer) { \ 739 CheckDecoderBadBuffer(Green##test_prefix##TestCase().WithFlags( \ 740 TEST_CASE_HAS_ERROR | TEST_CASE_IGNORE_OUTPUT)); \ 741 } 742 743 IMAGE_GTEST_DECODER_BASE_F(PNG) 744 IMAGE_GTEST_DECODER_BASE_F(GIF) 745 IMAGE_GTEST_DECODER_BASE_F(JPG) 746 IMAGE_GTEST_DECODER_BASE_F(BMP) 747 IMAGE_GTEST_DECODER_BASE_F(ICO) 748 IMAGE_GTEST_DECODER_BASE_F(Icon) 749 IMAGE_GTEST_DECODER_BASE_F(WebP) 750 #ifdef MOZ_JXL 751 IMAGE_GTEST_DECODER_BASE_F(JXL) 752 #endif 753 754 TEST_F(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode) { 755 CheckDownscaleDuringDecode(DownscaledTransparentICOWithANDMaskTestCase()); 756 } 757 758 TEST_F(ImageDecoders, WebPLargeMultiChunk) { 759 CheckDecoderMultiChunk(LargeWebPTestCase(), /* aChunkSize */ 64); 760 } 761 762 TEST_F(ImageDecoders, WebPIccSrgbMultiChunk) { 763 CheckDecoderMultiChunk(GreenWebPIccSrgbTestCase()); 764 } 765 766 TEST_F(ImageDecoders, WebPTransparentSingleChunk) { 767 CheckDecoderSingleChunk(TransparentWebPTestCase()); 768 } 769 770 TEST_F(ImageDecoders, WebPTransparentNoAlphaHeaderSingleChunk) { 771 CheckDecoderSingleChunk(TransparentNoAlphaHeaderWebPTestCase()); 772 } 773 774 TEST_F(ImageDecoders, AVIFSingleChunk) { 775 CheckDecoderSingleChunk(GreenAVIFTestCase()); 776 } 777 778 TEST_F(ImageDecoders, AVIFSingleChunkNonzeroReserved) { 779 CheckDecoderSingleChunk(NonzeroReservedAVIFTestCase()); 780 } 781 782 TEST_F(ImageDecoders, AVIFSingleChunkMultipleColr) { 783 CheckDecoderSingleChunk(MultipleColrAVIFTestCase()); 784 } 785 786 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit420) { 787 CheckDecoderSingleChunk(Transparent10bit420AVIFTestCase()); 788 } 789 790 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit422) { 791 CheckDecoderSingleChunk(Transparent10bit422AVIFTestCase()); 792 } 793 794 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit444) { 795 CheckDecoderSingleChunk(Transparent10bit444AVIFTestCase()); 796 } 797 798 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit420) { 799 CheckDecoderSingleChunk(Transparent12bit420AVIFTestCase()); 800 } 801 802 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit422) { 803 CheckDecoderSingleChunk(Transparent12bit422AVIFTestCase()); 804 } 805 806 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit444) { 807 CheckDecoderSingleChunk(Transparent12bit444AVIFTestCase()); 808 } 809 810 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit420) { 811 CheckDecoderSingleChunk(Transparent8bit420AVIFTestCase()); 812 } 813 814 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit422) { 815 CheckDecoderSingleChunk(Transparent8bit422AVIFTestCase()); 816 } 817 818 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit444) { 819 CheckDecoderSingleChunk(Transparent8bit444AVIFTestCase()); 820 } 821 822 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT601) { 823 CheckDecoderSingleChunk(Gray8bitLimitedRangeBT601AVIFTestCase()); 824 } 825 826 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT709) { 827 CheckDecoderSingleChunk(Gray8bitLimitedRangeBT709AVIFTestCase()); 828 } 829 830 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT2020) { 831 CheckDecoderSingleChunk(Gray8bitLimitedRangeBT2020AVIFTestCase()); 832 } 833 834 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT601) { 835 CheckDecoderSingleChunk(Gray8bitFullRangeBT601AVIFTestCase()); 836 } 837 838 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT709) { 839 CheckDecoderSingleChunk(Gray8bitFullRangeBT709AVIFTestCase()); 840 } 841 842 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT2020) { 843 CheckDecoderSingleChunk(Gray8bitFullRangeBT2020AVIFTestCase()); 844 } 845 846 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT601) { 847 CheckDecoderSingleChunk(Gray10bitLimitedRangeBT601AVIFTestCase()); 848 } 849 850 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT709) { 851 CheckDecoderSingleChunk(Gray10bitLimitedRangeBT709AVIFTestCase()); 852 } 853 854 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT2020) { 855 CheckDecoderSingleChunk(Gray10bitLimitedRangeBT2020AVIFTestCase()); 856 } 857 858 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT601) { 859 CheckDecoderSingleChunk(Gray10bitFullRangeBT601AVIFTestCase()); 860 } 861 862 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT709) { 863 CheckDecoderSingleChunk(Gray10bitFullRangeBT709AVIFTestCase()); 864 } 865 866 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT2020) { 867 CheckDecoderSingleChunk(Gray10bitFullRangeBT2020AVIFTestCase()); 868 } 869 870 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT601) { 871 CheckDecoderSingleChunk(Gray12bitLimitedRangeBT601AVIFTestCase()); 872 } 873 874 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT709) { 875 CheckDecoderSingleChunk(Gray12bitLimitedRangeBT709AVIFTestCase()); 876 } 877 878 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT2020) { 879 CheckDecoderSingleChunk(Gray12bitLimitedRangeBT2020AVIFTestCase()); 880 } 881 882 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT601) { 883 CheckDecoderSingleChunk(Gray12bitFullRangeBT601AVIFTestCase()); 884 } 885 886 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT709) { 887 CheckDecoderSingleChunk(Gray12bitFullRangeBT709AVIFTestCase()); 888 } 889 890 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT2020) { 891 CheckDecoderSingleChunk(Gray12bitFullRangeBT2020AVIFTestCase()); 892 } 893 894 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeGrayscale) { 895 CheckDecoderSingleChunk(Gray8bitLimitedRangeGrayscaleAVIFTestCase()); 896 } 897 898 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeGrayscale) { 899 CheckDecoderSingleChunk(Gray8bitFullRangeGrayscaleAVIFTestCase()); 900 } 901 902 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeGrayscale) { 903 CheckDecoderSingleChunk(Gray10bitLimitedRangeGrayscaleAVIFTestCase()); 904 } 905 906 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeGrayscale) { 907 CheckDecoderSingleChunk(Gray10bitFullRangeGrayscaleAVIFTestCase()); 908 } 909 910 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeGrayscale) { 911 CheckDecoderSingleChunk(Gray12bitLimitedRangeGrayscaleAVIFTestCase()); 912 } 913 914 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeGrayscale) { 915 CheckDecoderSingleChunk(Gray12bitFullRangeGrayscaleAVIFTestCase()); 916 } 917 918 TEST_F(ImageDecoders, AVIFMultiLayerSingleChunk) { 919 CheckDecoderSingleChunk(MultiLayerAVIFTestCase()); 920 } 921 922 // This test must use the decode pool in order to check for regressions 923 // of crashing the dav1d decoder when the ImgDecoder threads have a standard- 924 // sized stack. 925 TEST_F(ImageDecoders, AVIFStackCheck) { 926 CheckDecoderSingleChunk(StackCheckAVIFTestCase(), /* aUseDecodePool */ true); 927 } 928 929 TEST_F(ImageDecoders, AVIFDelayedChunk) { 930 CheckDecoderDelayedChunk(GreenAVIFTestCase()); 931 } 932 933 TEST_F(ImageDecoders, AVIFMultiChunk) { 934 CheckDecoderMultiChunk(GreenAVIFTestCase()); 935 } 936 937 TEST_F(ImageDecoders, AVIFLargeMultiChunk) { 938 CheckDecoderMultiChunk(LargeAVIFTestCase(), /* aChunkSize */ 64); 939 } 940 941 TEST_F(ImageDecoders, AVIFDownscaleDuringDecode) { 942 CheckDownscaleDuringDecode(DownscaledAVIFTestCase()); 943 } 944 945 #ifdef MOZ_JXL 946 TEST_F(ImageDecoders, JXLLargeMultiChunk) { 947 CheckDecoderMultiChunk(LargeJXLTestCase(), /* aChunkSize */ 64); 948 } 949 #endif 950 951 TEST_F(ImageDecoders, AnimatedGIFSingleChunk) { 952 CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase()); 953 } 954 955 TEST_F(ImageDecoders, AnimatedGIFMultiChunk) { 956 CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase()); 957 } 958 959 TEST_F(ImageDecoders, AnimatedGIFWithBlendedFrames) { 960 CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase()); 961 } 962 963 TEST_F(ImageDecoders, AnimatedPNGSingleChunk) { 964 CheckDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase()); 965 } 966 967 TEST_F(ImageDecoders, AnimatedPNGMultiChunk) { 968 CheckDecoderMultiChunk(GreenFirstFrameAnimatedPNGTestCase()); 969 } 970 971 TEST_F(ImageDecoders, AnimatedPNGWithBlendedFrames) { 972 CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase()); 973 } 974 975 TEST_F(ImageDecoders, AnimatedWebPSingleChunk) { 976 CheckDecoderSingleChunk(GreenFirstFrameAnimatedWebPTestCase()); 977 } 978 979 TEST_F(ImageDecoders, AnimatedWebPMultiChunk) { 980 CheckDecoderMultiChunk(GreenFirstFrameAnimatedWebPTestCase()); 981 } 982 983 TEST_F(ImageDecoders, AnimatedWebPWithBlendedFrames) { 984 CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedWebPTestCase()); 985 } 986 987 TEST_F(ImageDecoders, AnimatedAVIFSingleChunk) { 988 CheckDecoderSingleChunk(GreenFirstFrameAnimatedAVIFTestCase()); 989 } 990 991 TEST_F(ImageDecoders, AnimatedAVIFMultiChunk) { 992 CheckDecoderMultiChunk(GreenFirstFrameAnimatedAVIFTestCase()); 993 } 994 995 TEST_F(ImageDecoders, AnimatedAVIFWithBlendedFrames) { 996 CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedAVIFTestCase()); 997 } 998 999 TEST_F(ImageDecoders, CorruptSingleChunk) { 1000 CheckDecoderSingleChunk(CorruptTestCase()); 1001 } 1002 1003 TEST_F(ImageDecoders, CorruptMultiChunk) { 1004 CheckDecoderMultiChunk(CorruptTestCase()); 1005 } 1006 1007 TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderSingleChunk) { 1008 CheckDecoderSingleChunk(CorruptBMPWithTruncatedHeader()); 1009 } 1010 1011 TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderMultiChunk) { 1012 CheckDecoderMultiChunk(CorruptBMPWithTruncatedHeader()); 1013 } 1014 1015 TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthSingleChunk) { 1016 CheckDecoderSingleChunk(CorruptICOWithBadBMPWidthTestCase()); 1017 } 1018 1019 TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthMultiChunk) { 1020 CheckDecoderMultiChunk(CorruptICOWithBadBMPWidthTestCase()); 1021 } 1022 1023 TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightSingleChunk) { 1024 CheckDecoderSingleChunk(CorruptICOWithBadBMPHeightTestCase()); 1025 } 1026 1027 TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightMultiChunk) { 1028 CheckDecoderMultiChunk(CorruptICOWithBadBMPHeightTestCase()); 1029 } 1030 1031 TEST_F(ImageDecoders, CorruptICOWithBadBppSingleChunk) { 1032 CheckDecoderSingleChunk(CorruptICOWithBadBppTestCase()); 1033 } 1034 1035 // Running this test under emulation for Android 7 on x86_64 seems to result 1036 // in the large allocation succeeding, but leaving so little memory left the 1037 // system falls over and it kills the test run, so we skip it instead. 1038 // See bug 1655846 for more details. 1039 #ifndef ANDROID 1040 TEST_F(ImageDecoders, CorruptAVIFSingleChunk) { 1041 CheckDecoderSingleChunk(CorruptAVIFTestCase()); 1042 } 1043 #endif 1044 1045 TEST_F(ImageDecoders, AnimatedGIFWithFRAME_FIRST) { 1046 CheckDecoderFrameFirst(GreenFirstFrameAnimatedGIFTestCase()); 1047 } 1048 1049 TEST_F(ImageDecoders, AnimatedGIFWithFRAME_CURRENT) { 1050 CheckDecoderFrameCurrent(GreenFirstFrameAnimatedGIFTestCase()); 1051 } 1052 1053 TEST_F(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks) { 1054 ImageTestCase testCase = ExtraImageSubBlocksAnimatedGIFTestCase(); 1055 1056 // Verify that we can decode this test case and get two frames, even though 1057 // there are extra image sub blocks between the first and second frame. The 1058 // extra data shouldn't confuse the decoder or cause the decode to fail. 1059 1060 // Create an image. 1061 RefPtr<Image> image = TestCaseToDecodedImage(testCase); 1062 1063 // Ensure that the image's metadata meets our expectations. 1064 IntSize imageSize(0, 0); 1065 nsresult rv = image->GetWidth(&imageSize.width); 1066 EXPECT_NS_SUCCEEDED(rv); 1067 rv = image->GetHeight(&imageSize.height); 1068 EXPECT_NS_SUCCEEDED(rv); 1069 1070 EXPECT_EQ(testCase.mSize.width, imageSize.width); 1071 EXPECT_EQ(testCase.mSize.height, imageSize.height); 1072 1073 RefPtr<ProgressTracker> tracker = image->GetProgressTracker(); 1074 Progress imageProgress = tracker->GetProgress(); 1075 1076 EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false); 1077 EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true); 1078 1079 // Ensure that we decoded both frames of the image. 1080 LookupResult result = 1081 SurfaceCache::Lookup(ImageKey(image.get()), 1082 RasterSurfaceKey(imageSize, testCase.mSurfaceFlags, 1083 PlaybackType::eAnimated), 1084 /* aMarkUsed = */ true); 1085 ASSERT_EQ(MatchType::EXACT, result.Type()); 1086 1087 EXPECT_NS_SUCCEEDED(result.Surface().Seek(0)); 1088 EXPECT_TRUE(bool(result.Surface())); 1089 1090 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1); 1091 EXPECT_TRUE(bool(partialFrame)); 1092 } 1093 1094 TEST_F(ImageDecoders, AnimatedWebPWithFRAME_FIRST) { 1095 CheckDecoderFrameFirst(GreenFirstFrameAnimatedWebPTestCase()); 1096 } 1097 1098 TEST_F(ImageDecoders, AnimatedWebPWithFRAME_CURRENT) { 1099 CheckDecoderFrameCurrent(GreenFirstFrameAnimatedWebPTestCase()); 1100 } 1101 1102 TEST_F(ImageDecoders, TruncatedSmallGIFSingleChunk) { 1103 CheckDecoderSingleChunk(TruncatedSmallGIFTestCase()); 1104 } 1105 1106 TEST_F(ImageDecoders, LargeICOWithBMPSingleChunk) { 1107 CheckDecoderSingleChunk(LargeICOWithBMPTestCase()); 1108 } 1109 1110 TEST_F(ImageDecoders, LargeICOWithBMPMultiChunk) { 1111 CheckDecoderMultiChunk(LargeICOWithBMPTestCase(), /* aChunkSize */ 64); 1112 } 1113 1114 TEST_F(ImageDecoders, LargeICOWithPNGSingleChunk) { 1115 CheckDecoderSingleChunk(LargeICOWithPNGTestCase()); 1116 } 1117 1118 TEST_F(ImageDecoders, LargeICOWithPNGMultiChunk) { 1119 CheckDecoderMultiChunk(LargeICOWithPNGTestCase()); 1120 } 1121 1122 TEST_F(ImageDecoders, MultipleSizesICOSingleChunk) { 1123 ImageTestCase testCase = GreenMultipleSizesICOTestCase(); 1124 1125 // Create an image. 1126 RefPtr<Image> image = ImageFactory::CreateAnonymousImage( 1127 nsDependentCString(testCase.mMimeType)); 1128 ASSERT_TRUE(!image->HasError()); 1129 1130 nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath); 1131 ASSERT_TRUE(inputStream); 1132 1133 // Figure out how much data we have. 1134 uint64_t length; 1135 nsresult rv = inputStream->Available(&length); 1136 ASSERT_NS_SUCCEEDED(rv); 1137 1138 // Write the data into the image. 1139 rv = image->OnImageDataAvailable(nullptr, inputStream, 0, 1140 static_cast<uint32_t>(length)); 1141 ASSERT_NS_SUCCEEDED(rv); 1142 1143 // Let the image know we've sent all the data. 1144 rv = image->OnImageDataComplete(nullptr, NS_OK, true); 1145 ASSERT_NS_SUCCEEDED(rv); 1146 1147 RefPtr<ProgressTracker> tracker = image->GetProgressTracker(); 1148 tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE); 1149 1150 // Use GetFrame() to force a sync decode of the image. 1151 RefPtr<SourceSurface> surface = image->GetFrame( 1152 imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE); 1153 1154 // Ensure that the image's metadata meets our expectations. 1155 IntSize imageSize(0, 0); 1156 rv = image->GetWidth(&imageSize.width); 1157 EXPECT_NS_SUCCEEDED(rv); 1158 rv = image->GetHeight(&imageSize.height); 1159 EXPECT_NS_SUCCEEDED(rv); 1160 1161 EXPECT_EQ(testCase.mSize.width, imageSize.width); 1162 EXPECT_EQ(testCase.mSize.height, imageSize.height); 1163 1164 nsTArray<IntSize> nativeSizes; 1165 rv = image->GetNativeSizes(nativeSizes); 1166 EXPECT_NS_SUCCEEDED(rv); 1167 ASSERT_EQ(6u, nativeSizes.Length()); 1168 1169 IntSize expectedSizes[] = {IntSize(16, 16), IntSize(32, 32), 1170 IntSize(64, 64), IntSize(128, 128), 1171 IntSize(256, 256), IntSize(256, 128)}; 1172 1173 for (int i = 0; i < 6; ++i) { 1174 EXPECT_EQ(expectedSizes[i], nativeSizes[i]); 1175 } 1176 1177 RefPtr<Image> image90 = 1178 ImageOps::Orient(image, Orientation(Angle::D90, Flip::Unflipped)); 1179 rv = image90->GetNativeSizes(nativeSizes); 1180 EXPECT_NS_SUCCEEDED(rv); 1181 ASSERT_EQ(6u, nativeSizes.Length()); 1182 1183 for (int i = 0; i < 5; ++i) { 1184 EXPECT_EQ(expectedSizes[i], nativeSizes[i]); 1185 } 1186 EXPECT_EQ(IntSize(128, 256), nativeSizes[5]); 1187 1188 RefPtr<Image> image180 = 1189 ImageOps::Orient(image, Orientation(Angle::D180, Flip::Unflipped)); 1190 rv = image180->GetNativeSizes(nativeSizes); 1191 EXPECT_NS_SUCCEEDED(rv); 1192 ASSERT_EQ(6u, nativeSizes.Length()); 1193 1194 for (int i = 0; i < 6; ++i) { 1195 EXPECT_EQ(expectedSizes[i], nativeSizes[i]); 1196 } 1197 } 1198 1199 TEST_F(ImageDecoders, ExifResolutionEven) { 1200 RefPtr<Image> image = TestCaseToDecodedImage(ExifResolutionTestCase()); 1201 EXPECT_EQ(image->GetResolution(), Resolution(2.0, 2.0)); 1202 }