1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "DecoderFactory.h"
8 #include "nsMimeTypes.h"
9 #include "mozilla/RefPtr.h"
11 #include "AnimationSurfaceProvider.h"
13 #include "DecodedSurfaceProvider.h"
14 #include "IDecodingTask.h"
16 #include "nsPNGDecoder.h"
17 #include "nsGIFDecoder2.h"
18 #include "nsJPEGDecoder.h"
19 #include "nsBMPDecoder.h"
20 #include "nsICODecoder.h"
21 #include "nsIconDecoder.h"
22 #include "nsWebPDecoder.h"
24 # include "nsAVIFDecoder.h"
34 DecoderType
DecoderFactory::GetDecoderType(const char* aMimeType
) {
35 // By default we don't know.
36 DecoderType type
= DecoderType::UNKNOWN
;
39 if (!strcmp(aMimeType
, IMAGE_PNG
)) {
40 type
= DecoderType::PNG
;
41 } else if (!strcmp(aMimeType
, IMAGE_X_PNG
)) {
42 type
= DecoderType::PNG
;
43 } else if (!strcmp(aMimeType
, IMAGE_APNG
)) {
44 type
= DecoderType::PNG
;
47 } else if (!strcmp(aMimeType
, IMAGE_GIF
)) {
48 type
= DecoderType::GIF
;
51 } else if (!strcmp(aMimeType
, IMAGE_JPEG
)) {
52 type
= DecoderType::JPEG
;
53 } else if (!strcmp(aMimeType
, IMAGE_PJPEG
)) {
54 type
= DecoderType::JPEG
;
55 } else if (!strcmp(aMimeType
, IMAGE_JPG
)) {
56 type
= DecoderType::JPEG
;
59 } else if (!strcmp(aMimeType
, IMAGE_BMP
)) {
60 type
= DecoderType::BMP
;
61 } else if (!strcmp(aMimeType
, IMAGE_BMP_MS
)) {
62 type
= DecoderType::BMP
;
65 } else if (!strcmp(aMimeType
, IMAGE_BMP_MS_CLIPBOARD
)) {
66 type
= DecoderType::BMP_CLIPBOARD
;
69 } else if (!strcmp(aMimeType
, IMAGE_ICO
)) {
70 type
= DecoderType::ICO
;
71 } else if (!strcmp(aMimeType
, IMAGE_ICO_MS
)) {
72 type
= DecoderType::ICO
;
75 } else if (!strcmp(aMimeType
, IMAGE_ICON_MS
)) {
76 type
= DecoderType::ICON
;
79 } else if (!strcmp(aMimeType
, IMAGE_WEBP
) &&
80 StaticPrefs::image_webp_enabled()) {
81 type
= DecoderType::WEBP
;
86 else if (!strcmp(aMimeType
, IMAGE_AVIF
) &&
87 StaticPrefs::image_avif_enabled()) {
88 type
= DecoderType::AVIF
;
96 already_AddRefed
<Decoder
> DecoderFactory::GetDecoder(DecoderType aType
,
99 RefPtr
<Decoder
> decoder
;
102 case DecoderType::PNG
:
103 decoder
= new nsPNGDecoder(aImage
);
105 case DecoderType::GIF
:
106 decoder
= new nsGIFDecoder2(aImage
);
108 case DecoderType::JPEG
:
109 // If we have all the data we don't want to waste cpu time doing
110 // a progressive decode.
111 decoder
= new nsJPEGDecoder(
112 aImage
, aIsRedecode
? Decoder::SEQUENTIAL
: Decoder::PROGRESSIVE
);
114 case DecoderType::BMP
:
115 decoder
= new nsBMPDecoder(aImage
);
117 case DecoderType::BMP_CLIPBOARD
:
118 decoder
= new nsBMPDecoder(aImage
, /* aForClipboard */ true);
120 case DecoderType::ICO
:
121 decoder
= new nsICODecoder(aImage
);
123 case DecoderType::ICON
:
124 decoder
= new nsIconDecoder(aImage
);
126 case DecoderType::WEBP
:
127 decoder
= new nsWebPDecoder(aImage
);
130 case DecoderType::AVIF
:
131 decoder
= new nsAVIFDecoder(aImage
);
135 MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
138 return decoder
.forget();
142 nsresult
DecoderFactory::CreateDecoder(
143 DecoderType aType
, NotNull
<RasterImage
*> aImage
,
144 NotNull
<SourceBuffer
*> aSourceBuffer
, const IntSize
& aIntrinsicSize
,
145 const IntSize
& aOutputSize
, DecoderFlags aDecoderFlags
,
146 SurfaceFlags aSurfaceFlags
, IDecodingTask
** aOutTask
) {
147 if (aType
== DecoderType::UNKNOWN
) {
148 return NS_ERROR_INVALID_ARG
;
151 // Create an anonymous decoder. Interaction with the SurfaceCache and the
152 // owning RasterImage will be mediated by DecodedSurfaceProvider.
153 RefPtr
<Decoder
> decoder
= GetDecoder(
154 aType
, nullptr, bool(aDecoderFlags
& DecoderFlags::IS_REDECODE
));
155 MOZ_ASSERT(decoder
, "Should have a decoder now");
157 // Initialize the decoder.
158 decoder
->SetMetadataDecode(false);
159 decoder
->SetIterator(aSourceBuffer
->Iterator());
160 decoder
->SetOutputSize(aOutputSize
);
161 decoder
->SetDecoderFlags(aDecoderFlags
| DecoderFlags::FIRST_FRAME_ONLY
);
162 decoder
->SetSurfaceFlags(aSurfaceFlags
);
164 nsresult rv
= decoder
->Init();
166 return NS_ERROR_FAILURE
;
169 // Create a DecodedSurfaceProvider which will manage the decoding process and
170 // make this decoder's output available in the surface cache.
171 SurfaceKey surfaceKey
=
172 RasterSurfaceKey(aOutputSize
, aSurfaceFlags
, PlaybackType::eStatic
);
173 auto provider
= MakeNotNull
<RefPtr
<DecodedSurfaceProvider
>>(
174 aImage
, surfaceKey
, WrapNotNull(decoder
));
175 if (aDecoderFlags
& DecoderFlags::CANNOT_SUBSTITUTE
) {
176 provider
->Availability().SetCannotSubstitute();
179 // Attempt to insert the surface provider into the surface cache right away so
180 // we won't trigger any more decoders with the same parameters.
181 switch (SurfaceCache::Insert(provider
)) {
182 case InsertOutcome::SUCCESS
:
184 case InsertOutcome::FAILURE_ALREADY_PRESENT
:
185 return NS_ERROR_ALREADY_INITIALIZED
;
187 return NS_ERROR_FAILURE
;
190 // Return the surface provider in its IDecodingTask guise.
191 RefPtr
<IDecodingTask
> task
= provider
.get();
192 task
.forget(aOutTask
);
197 nsresult
DecoderFactory::CreateAnimationDecoder(
198 DecoderType aType
, NotNull
<RasterImage
*> aImage
,
199 NotNull
<SourceBuffer
*> aSourceBuffer
, const IntSize
& aIntrinsicSize
,
200 DecoderFlags aDecoderFlags
, SurfaceFlags aSurfaceFlags
,
201 size_t aCurrentFrame
, IDecodingTask
** aOutTask
) {
202 if (aType
== DecoderType::UNKNOWN
) {
203 return NS_ERROR_INVALID_ARG
;
206 MOZ_ASSERT(aType
== DecoderType::GIF
|| aType
== DecoderType::PNG
||
207 aType
== DecoderType::WEBP
,
208 "Calling CreateAnimationDecoder for non-animating DecoderType");
210 // Create an anonymous decoder. Interaction with the SurfaceCache and the
211 // owning RasterImage will be mediated by AnimationSurfaceProvider.
212 RefPtr
<Decoder
> decoder
=
213 GetDecoder(aType
, nullptr, /* aIsRedecode = */ true);
214 MOZ_ASSERT(decoder
, "Should have a decoder now");
216 // Initialize the decoder.
217 decoder
->SetMetadataDecode(false);
218 decoder
->SetIterator(aSourceBuffer
->Iterator());
219 decoder
->SetDecoderFlags(aDecoderFlags
| DecoderFlags::IS_REDECODE
);
220 decoder
->SetSurfaceFlags(aSurfaceFlags
);
222 nsresult rv
= decoder
->Init();
224 return NS_ERROR_FAILURE
;
227 // Create an AnimationSurfaceProvider which will manage the decoding process
228 // and make this decoder's output available in the surface cache.
229 SurfaceKey surfaceKey
=
230 RasterSurfaceKey(aIntrinsicSize
, aSurfaceFlags
, PlaybackType::eAnimated
);
231 auto provider
= MakeNotNull
<RefPtr
<AnimationSurfaceProvider
>>(
232 aImage
, surfaceKey
, WrapNotNull(decoder
), aCurrentFrame
);
234 // Attempt to insert the surface provider into the surface cache right away so
235 // we won't trigger any more decoders with the same parameters.
236 switch (SurfaceCache::Insert(provider
)) {
237 case InsertOutcome::SUCCESS
:
239 case InsertOutcome::FAILURE_ALREADY_PRESENT
:
240 return NS_ERROR_ALREADY_INITIALIZED
;
242 return NS_ERROR_FAILURE
;
245 // Return the surface provider in its IDecodingTask guise.
246 RefPtr
<IDecodingTask
> task
= provider
.get();
247 task
.forget(aOutTask
);
252 already_AddRefed
<Decoder
> DecoderFactory::CloneAnimationDecoder(
254 MOZ_ASSERT(aDecoder
);
256 // In an ideal world, we would assert aDecoder->HasAnimation() but we cannot.
257 // The decoder may not have detected it is animated yet (e.g. it did not even
258 // get scheduled yet, or it has only decoded the first frame and has yet to
259 // rediscover it is animated).
260 DecoderType type
= aDecoder
->GetType();
261 MOZ_ASSERT(type
== DecoderType::GIF
|| type
== DecoderType::PNG
||
262 type
== DecoderType::WEBP
,
263 "Calling CloneAnimationDecoder for non-animating DecoderType");
265 RefPtr
<Decoder
> decoder
= GetDecoder(type
, nullptr, /* aIsRedecode = */ true);
266 MOZ_ASSERT(decoder
, "Should have a decoder now");
268 // Initialize the decoder.
269 decoder
->SetMetadataDecode(false);
270 decoder
->SetIterator(aDecoder
->GetSourceBuffer()->Iterator());
271 decoder
->SetDecoderFlags(aDecoder
->GetDecoderFlags());
272 decoder
->SetSurfaceFlags(aDecoder
->GetSurfaceFlags());
273 decoder
->SetFrameRecycler(aDecoder
->GetFrameRecycler());
275 if (NS_FAILED(decoder
->Init())) {
279 return decoder
.forget();
283 already_AddRefed
<IDecodingTask
> DecoderFactory::CreateMetadataDecoder(
284 DecoderType aType
, NotNull
<RasterImage
*> aImage
,
285 NotNull
<SourceBuffer
*> aSourceBuffer
) {
286 if (aType
== DecoderType::UNKNOWN
) {
290 RefPtr
<Decoder
> decoder
=
291 GetDecoder(aType
, aImage
, /* aIsRedecode = */ false);
292 MOZ_ASSERT(decoder
, "Should have a decoder now");
294 // Initialize the decoder.
295 decoder
->SetMetadataDecode(true);
296 decoder
->SetIterator(aSourceBuffer
->Iterator());
298 if (NS_FAILED(decoder
->Init())) {
302 RefPtr
<IDecodingTask
> task
= new MetadataDecodingTask(WrapNotNull(decoder
));
303 return task
.forget();
307 already_AddRefed
<Decoder
> DecoderFactory::CreateDecoderForICOResource(
308 DecoderType aType
, SourceBufferIterator
&& aIterator
,
309 NotNull
<nsICODecoder
*> aICODecoder
, bool aIsMetadataDecode
,
310 const Maybe
<IntSize
>& aExpectedSize
, const Maybe
<uint32_t>& aDataOffset
312 // Create the decoder.
313 RefPtr
<Decoder
> decoder
;
315 case DecoderType::BMP
:
316 MOZ_ASSERT(aDataOffset
);
318 new nsBMPDecoder(aICODecoder
->GetImageMaybeNull(), *aDataOffset
);
321 case DecoderType::PNG
:
322 MOZ_ASSERT(!aDataOffset
);
323 decoder
= new nsPNGDecoder(aICODecoder
->GetImageMaybeNull());
327 MOZ_ASSERT_UNREACHABLE("Invalid ICO resource decoder type");
333 // Initialize the decoder, copying settings from @aICODecoder.
334 decoder
->SetMetadataDecode(aIsMetadataDecode
);
335 decoder
->SetIterator(std::forward
<SourceBufferIterator
>(aIterator
));
336 if (!aIsMetadataDecode
) {
337 decoder
->SetOutputSize(aICODecoder
->OutputSize());
340 decoder
->SetExpectedSize(*aExpectedSize
);
342 decoder
->SetDecoderFlags(aICODecoder
->GetDecoderFlags());
343 decoder
->SetSurfaceFlags(aICODecoder
->GetSurfaceFlags());
344 decoder
->SetFinalizeFrames(false);
346 if (NS_FAILED(decoder
->Init())) {
350 return decoder
.forget();
354 already_AddRefed
<Decoder
> DecoderFactory::CreateAnonymousDecoder(
355 DecoderType aType
, NotNull
<SourceBuffer
*> aSourceBuffer
,
356 const Maybe
<IntSize
>& aOutputSize
, DecoderFlags aDecoderFlags
,
357 SurfaceFlags aSurfaceFlags
) {
358 if (aType
== DecoderType::UNKNOWN
) {
362 RefPtr
<Decoder
> decoder
=
363 GetDecoder(aType
, /* aImage = */ nullptr, /* aIsRedecode = */ false);
364 MOZ_ASSERT(decoder
, "Should have a decoder now");
366 // Initialize the decoder.
367 decoder
->SetMetadataDecode(false);
368 decoder
->SetIterator(aSourceBuffer
->Iterator());
370 // Anonymous decoders are always transient; we don't want to optimize surfaces
371 // or do any other expensive work that might be wasted.
372 DecoderFlags decoderFlags
= DecoderFlags::IMAGE_IS_TRANSIENT
;
374 decoder
->SetDecoderFlags(aDecoderFlags
| decoderFlags
);
375 decoder
->SetSurfaceFlags(aSurfaceFlags
);
377 // Set an output size for downscale-during-decode if requested.
379 decoder
->SetOutputSize(*aOutputSize
);
382 if (NS_FAILED(decoder
->Init())) {
386 return decoder
.forget();
390 already_AddRefed
<Decoder
> DecoderFactory::CreateAnonymousMetadataDecoder(
391 DecoderType aType
, NotNull
<SourceBuffer
*> aSourceBuffer
) {
392 if (aType
== DecoderType::UNKNOWN
) {
396 RefPtr
<Decoder
> decoder
=
397 GetDecoder(aType
, /* aImage = */ nullptr, /* aIsRedecode = */ false);
398 MOZ_ASSERT(decoder
, "Should have a decoder now");
400 // Initialize the decoder.
401 decoder
->SetMetadataDecode(true);
402 decoder
->SetIterator(aSourceBuffer
->Iterator());
403 decoder
->SetDecoderFlags(DecoderFlags::FIRST_FRAME_ONLY
);
405 if (NS_FAILED(decoder
->Init())) {
409 return decoder
.forget();
413 } // namespace mozilla