/* static */ already_AddRefed<IDecodingTask> DecoderFactory::CreateMetadataDecoder(DecoderType aType, NotNull<RasterImage*> aImage, NotNull<SourceBuffer*> aSourceBuffer, int aSampleSize) { if (aType == DecoderType::UNKNOWN) { return nullptr; } RefPtr<Decoder> decoder = GetDecoder(aType, aImage, /* aIsRedecode = */ false); MOZ_ASSERT(decoder, "Should have a decoder now"); // Initialize the decoder. decoder->SetMetadataDecode(true); decoder->SetIterator(aSourceBuffer->Iterator()); decoder->SetSampleSize(aSampleSize); decoder->Init(); if (NS_FAILED(decoder->GetDecoderError())) { return nullptr; } RefPtr<IDecodingTask> task = new MetadataDecodingTask(WrapNotNull(decoder)); return task.forget(); }
/* static */ already_AddRefed<IDecodingTask> DecoderFactory::CreateAnimationDecoder(DecoderType aType, NotNull<RasterImage*> aImage, NotNull<SourceBuffer*> aSourceBuffer, DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags) { if (aType == DecoderType::UNKNOWN) { return nullptr; } MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG, "Calling CreateAnimationDecoder for non-animating DecoderType"); RefPtr<Decoder> decoder = GetDecoder(aType, aImage, /* aIsRedecode = */ true); MOZ_ASSERT(decoder, "Should have a decoder now"); // Initialize the decoder. decoder->SetMetadataDecode(false); decoder->SetIterator(aSourceBuffer->Iterator()); decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE); decoder->SetSurfaceFlags(aSurfaceFlags); decoder->Init(); if (NS_FAILED(decoder->GetDecoderError())) { return nullptr; } RefPtr<IDecodingTask> task = new DecodingTask(WrapNotNull(decoder)); return task.forget(); }
/* static */ already_AddRefed<IDecodingTask> DecoderFactory::CreateDecoder(DecoderType aType, NotNull<RasterImage*> aImage, NotNull<SourceBuffer*> aSourceBuffer, const IntSize& aIntrinsicSize, const IntSize& aOutputSize, DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags) { if (aType == DecoderType::UNKNOWN) { return nullptr; } // Create an anonymous decoder. Interaction with the SurfaceCache and the // owning RasterImage will be mediated by DecodedSurfaceProvider. RefPtr<Decoder> decoder = GetDecoder(aType, nullptr, bool(aDecoderFlags & DecoderFlags::IS_REDECODE)); MOZ_ASSERT(decoder, "Should have a decoder now"); // Initialize the decoder. decoder->SetMetadataDecode(false); decoder->SetIterator(aSourceBuffer->Iterator()); decoder->SetOutputSize(aOutputSize); decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY); decoder->SetSurfaceFlags(aSurfaceFlags); if (NS_FAILED(decoder->Init())) { return nullptr; } // Create a DecodedSurfaceProvider which will manage the decoding process and // make this decoder's output available in the surface cache. SurfaceKey surfaceKey = RasterSurfaceKey(aOutputSize, aSurfaceFlags, PlaybackType::eStatic); auto provider = MakeNotNull<RefPtr<DecodedSurfaceProvider>>( aImage, surfaceKey, WrapNotNull(decoder)); if (aDecoderFlags & DecoderFlags::CANNOT_SUBSTITUTE) { provider->Availability().SetCannotSubstitute(); } // Attempt to insert the surface provider into the surface cache right away so // we won't trigger any more decoders with the same parameters. if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) { return nullptr; } // Return the surface provider in its IDecodingTask guise. RefPtr<IDecodingTask> task = provider.get(); return task.forget(); }
/* static */ already_AddRefed<IDecodingTask> DecoderFactory::CreateAnimationDecoder(DecoderType aType, NotNull<RasterImage*> aImage, NotNull<SourceBuffer*> aSourceBuffer, const IntSize& aIntrinsicSize, DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags) { if (aType == DecoderType::UNKNOWN) { return nullptr; } MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG, "Calling CreateAnimationDecoder for non-animating DecoderType"); // Create an anonymous decoder. Interaction with the SurfaceCache and the // owning RasterImage will be mediated by AnimationSurfaceProvider. RefPtr<Decoder> decoder = GetDecoder(aType, nullptr, /* aIsRedecode = */ true); MOZ_ASSERT(decoder, "Should have a decoder now"); // Initialize the decoder. decoder->SetMetadataDecode(false); decoder->SetIterator(aSourceBuffer->Iterator()); decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE); decoder->SetSurfaceFlags(aSurfaceFlags); if (NS_FAILED(decoder->Init())) { return nullptr; } // Create an AnimationSurfaceProvider which will manage the decoding process // and make this decoder's output available in the surface cache. SurfaceKey surfaceKey = RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, PlaybackType::eAnimated); auto provider = MakeNotNull<RefPtr<AnimationSurfaceProvider>>( aImage, surfaceKey, WrapNotNull(decoder)); // Attempt to insert the surface provider into the surface cache right away so // we won't trigger any more decoders with the same parameters. if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) { return nullptr; } // Return the surface provider in its IDecodingTask guise. RefPtr<IDecodingTask> task = provider.get(); return task.forget(); }
/* static */ already_AddRefed<Decoder> DecoderFactory::CreateAnonymousDecoder(DecoderType aType, NotNull<SourceBuffer*> aSourceBuffer, const Maybe<IntSize>& aTargetSize, SurfaceFlags aSurfaceFlags) { if (aType == DecoderType::UNKNOWN) { return nullptr; } RefPtr<Decoder> decoder = GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false); MOZ_ASSERT(decoder, "Should have a decoder now"); // Initialize the decoder. decoder->SetMetadataDecode(false); decoder->SetIterator(aSourceBuffer->Iterator()); // Anonymous decoders are always transient; we don't want to optimize surfaces // or do any other expensive work that might be wasted. DecoderFlags decoderFlags = DecoderFlags::IMAGE_IS_TRANSIENT; // Without an image, the decoder can't store anything in the SurfaceCache, so // callers will only be able to retrieve the most recent frame via // Decoder::GetCurrentFrame(). That means that anonymous decoders should // always be first-frame-only decoders, because nobody ever wants the *last* // frame. decoderFlags |= DecoderFlags::FIRST_FRAME_ONLY; decoder->SetDecoderFlags(decoderFlags); decoder->SetSurfaceFlags(aSurfaceFlags); // Set a target size for downscale-during-decode if applicable. if (aTargetSize) { DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize); MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?"); } decoder->Init(); if (NS_FAILED(decoder->GetDecoderError())) { return nullptr; } return decoder.forget(); }
/* static */ already_AddRefed<IDecodingTask> DecoderFactory::CreateDecoder(DecoderType aType, NotNull<RasterImage*> aImage, NotNull<SourceBuffer*> aSourceBuffer, const Maybe<IntSize>& aTargetSize, DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags, int aSampleSize) { if (aType == DecoderType::UNKNOWN) { return nullptr; } RefPtr<Decoder> decoder = GetDecoder(aType, aImage, bool(aDecoderFlags & DecoderFlags::IS_REDECODE)); MOZ_ASSERT(decoder, "Should have a decoder now"); // Initialize the decoder. decoder->SetMetadataDecode(false); decoder->SetIterator(aSourceBuffer->Iterator()); decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY); decoder->SetSurfaceFlags(aSurfaceFlags); decoder->SetSampleSize(aSampleSize); // Set a target size for downscale-during-decode if applicable. if (aTargetSize) { DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize); MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?"); } decoder->Init(); if (NS_FAILED(decoder->GetDecoderError())) { return nullptr; } RefPtr<IDecodingTask> task = new DecodingTask(WrapNotNull(decoder)); return task.forget(); }
/* static */ already_AddRefed<Decoder> DecoderFactory::CreateAnonymousMetadataDecoder(DecoderType aType, NotNull<SourceBuffer*> aSourceBuffer) { if (aType == DecoderType::UNKNOWN) { return nullptr; } RefPtr<Decoder> decoder = GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false); MOZ_ASSERT(decoder, "Should have a decoder now"); // Initialize the decoder. decoder->SetMetadataDecode(true); decoder->SetIterator(aSourceBuffer->Iterator()); decoder->SetDecoderFlags(DecoderFlags::FIRST_FRAME_ONLY); if (NS_FAILED(decoder->Init())) { return nullptr; } return decoder.forget(); }