tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DecoderFactory.cpp (15192B)


      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/. */
      5 
      6 #include "DecoderFactory.h"
      7 
      8 #include "ImageUtils.h"
      9 #include "nsMimeTypes.h"
     10 #include "mozilla/RefPtr.h"
     11 
     12 #include "AnimationSurfaceProvider.h"
     13 #include "Decoder.h"
     14 #include "DecodedSurfaceProvider.h"
     15 #include "IDecodingTask.h"
     16 #include "ImageOps.h"
     17 #include "nsPNGDecoder.h"
     18 #include "nsGIFDecoder2.h"
     19 #include "nsJPEGDecoder.h"
     20 #include "nsBMPDecoder.h"
     21 #include "nsICODecoder.h"
     22 #include "nsIconDecoder.h"
     23 #include "nsWebPDecoder.h"
     24 #ifdef MOZ_AV1
     25 #  include "nsAVIFDecoder.h"
     26 #endif
     27 #ifdef MOZ_JXL
     28 #  include "nsJXLDecoder.h"
     29 #endif
     30 
     31 namespace mozilla {
     32 
     33 using namespace gfx;
     34 
     35 namespace image {
     36 
     37 /* static */
     38 DecoderType DecoderFactory::GetDecoderType(const char* aMimeType) {
     39  // By default we don't know.
     40  DecoderType type = DecoderType::UNKNOWN;
     41 
     42  // PNG
     43  if (!strcmp(aMimeType, IMAGE_PNG)) {
     44    type = DecoderType::PNG;
     45  } else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
     46    type = DecoderType::PNG;
     47  } else if (!strcmp(aMimeType, IMAGE_APNG)) {
     48    type = DecoderType::PNG;
     49 
     50    // GIF
     51  } else if (!strcmp(aMimeType, IMAGE_GIF)) {
     52    type = DecoderType::GIF;
     53 
     54    // JPEG
     55  } else if (!strcmp(aMimeType, IMAGE_JPEG)) {
     56    type = DecoderType::JPEG;
     57  } else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
     58    type = DecoderType::JPEG;
     59  } else if (!strcmp(aMimeType, IMAGE_JPG)) {
     60    type = DecoderType::JPEG;
     61  } else if (!strcmp(aMimeType, IMAGE_JPEG_PDF)) {
     62    type = DecoderType::JPEG_PDF;
     63 
     64    // BMP
     65  } else if (!strcmp(aMimeType, IMAGE_BMP)) {
     66    type = DecoderType::BMP;
     67  } else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
     68    type = DecoderType::BMP;
     69 
     70    // BMP_CLIPBOARD
     71  } else if (!strcmp(aMimeType, IMAGE_BMP_MS_CLIPBOARD)) {
     72    type = DecoderType::BMP_CLIPBOARD;
     73 
     74    // ICO
     75  } else if (!strcmp(aMimeType, IMAGE_ICO)) {
     76    type = DecoderType::ICO;
     77  } else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
     78    type = DecoderType::ICO;
     79 
     80    // Icon
     81  } else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
     82    type = DecoderType::ICON;
     83 
     84    // WebP
     85  } else if (!strcmp(aMimeType, IMAGE_WEBP)) {
     86    type = DecoderType::WEBP;
     87 
     88    // AVIF
     89  }
     90 #ifdef MOZ_AV1
     91  else if (!strcmp(aMimeType, IMAGE_AVIF)) {
     92    type = DecoderType::AVIF;
     93  }
     94 #endif
     95 #ifdef MOZ_JXL
     96  else if (!strcmp(aMimeType, IMAGE_JXL) && StaticPrefs::image_jxl_enabled()) {
     97    type = DecoderType::JXL;
     98  }
     99 #endif
    100 
    101  return type;
    102 }
    103 
    104 /* static */
    105 DecoderFlags DecoderFactory::GetDefaultDecoderFlagsForType(DecoderType aType) {
    106  auto flags = DefaultDecoderFlags();
    107 
    108 #ifdef MOZ_AV1
    109  if (aType == DecoderType::AVIF) {
    110    if (StaticPrefs::image_avif_sequence_enabled()) {
    111      flags |= DecoderFlags::AVIF_SEQUENCES_ENABLED;
    112    }
    113    if (StaticPrefs::image_avif_sequence_animate_avif_major_branded_images()) {
    114      flags |= DecoderFlags::AVIF_ANIMATE_AVIF_MAJOR;
    115    }
    116  }
    117 #endif
    118 
    119  return flags;
    120 }
    121 
    122 /* static */
    123 already_AddRefed<Decoder> DecoderFactory::GetDecoder(DecoderType aType,
    124                                                     RasterImage* aImage,
    125                                                     bool aIsRedecode) {
    126  RefPtr<Decoder> decoder;
    127 
    128  switch (aType) {
    129    case DecoderType::PNG:
    130      decoder = new nsPNGDecoder(aImage);
    131      break;
    132    case DecoderType::GIF:
    133      decoder = new nsGIFDecoder2(aImage);
    134      break;
    135    case DecoderType::JPEG:
    136    case DecoderType::JPEG_PDF:
    137      // If we have all the data we don't want to waste cpu time doing
    138      // a progressive decode.
    139      decoder = new nsJPEGDecoder(
    140          aImage, aIsRedecode ? Decoder::SEQUENTIAL : Decoder::PROGRESSIVE,
    141          aType == DecoderType::JPEG_PDF);
    142      break;
    143    case DecoderType::BMP:
    144      decoder = new nsBMPDecoder(aImage);
    145      break;
    146    case DecoderType::BMP_CLIPBOARD:
    147      decoder = new nsBMPDecoder(aImage, /* aForClipboard */ true);
    148      break;
    149    case DecoderType::ICO:
    150      decoder = new nsICODecoder(aImage);
    151      break;
    152    case DecoderType::ICON:
    153      decoder = new nsIconDecoder(aImage);
    154      break;
    155    case DecoderType::WEBP:
    156      decoder = new nsWebPDecoder(aImage);
    157      break;
    158 #ifdef MOZ_AV1
    159    case DecoderType::AVIF:
    160      decoder = new nsAVIFDecoder(aImage);
    161      break;
    162 #endif
    163 #ifdef MOZ_JXL
    164    case DecoderType::JXL:
    165      decoder = new nsJXLDecoder(aImage);
    166      break;
    167 #endif
    168    default:
    169      MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
    170  }
    171 
    172  return decoder.forget();
    173 }
    174 
    175 /* static */
    176 nsresult DecoderFactory::CreateDecoder(
    177    DecoderType aType, NotNull<RasterImage*> aImage,
    178    NotNull<SourceBuffer*> aSourceBuffer, const IntSize& aIntrinsicSize,
    179    const IntSize& aOutputSize, DecoderFlags aDecoderFlags,
    180    SurfaceFlags aSurfaceFlags, IDecodingTask** aOutTask) {
    181  if (aType == DecoderType::UNKNOWN) {
    182    return NS_ERROR_INVALID_ARG;
    183  }
    184 
    185  // Only can use COUNT_FRAMES with metadata decoders.
    186  if (NS_WARN_IF(bool(aDecoderFlags & DecoderFlags::COUNT_FRAMES))) {
    187    return NS_ERROR_INVALID_ARG;
    188  }
    189 
    190  // Create an anonymous decoder. Interaction with the SurfaceCache and the
    191  // owning RasterImage will be mediated by DecodedSurfaceProvider.
    192  RefPtr<Decoder> decoder = GetDecoder(
    193      aType, nullptr, bool(aDecoderFlags & DecoderFlags::IS_REDECODE));
    194  MOZ_ASSERT(decoder, "Should have a decoder now");
    195 
    196  // Initialize the decoder.
    197  decoder->SetMetadataDecode(false);
    198  decoder->SetIterator(aSourceBuffer->Iterator());
    199  decoder->SetOutputSize(OrientedIntSize::FromUnknownSize(aOutputSize));
    200  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
    201  decoder->SetSurfaceFlags(aSurfaceFlags);
    202 
    203  nsresult rv = decoder->Init();
    204  if (NS_FAILED(rv)) {
    205    return NS_ERROR_FAILURE;
    206  }
    207 
    208  // Create a DecodedSurfaceProvider which will manage the decoding process and
    209  // make this decoder's output available in the surface cache.
    210  SurfaceKey surfaceKey =
    211      RasterSurfaceKey(aOutputSize, aSurfaceFlags, PlaybackType::eStatic);
    212  auto provider = MakeNotNull<RefPtr<DecodedSurfaceProvider>>(
    213      aImage, surfaceKey, WrapNotNull(decoder));
    214  if (aDecoderFlags & DecoderFlags::CANNOT_SUBSTITUTE) {
    215    provider->Availability().SetCannotSubstitute();
    216  }
    217 
    218  // Attempt to insert the surface provider into the surface cache right away so
    219  // we won't trigger any more decoders with the same parameters.
    220  switch (SurfaceCache::Insert(provider)) {
    221    case InsertOutcome::SUCCESS:
    222      break;
    223    case InsertOutcome::FAILURE_ALREADY_PRESENT:
    224      return NS_ERROR_ALREADY_INITIALIZED;
    225    default:
    226      return NS_ERROR_FAILURE;
    227  }
    228 
    229  // Return the surface provider in its IDecodingTask guise.
    230  RefPtr<IDecodingTask> task = provider.get();
    231  task.forget(aOutTask);
    232  return NS_OK;
    233 }
    234 
    235 /* static */
    236 nsresult DecoderFactory::CreateAnimationDecoder(
    237    DecoderType aType, NotNull<RasterImage*> aImage,
    238    NotNull<SourceBuffer*> aSourceBuffer, const IntSize& aIntrinsicSize,
    239    DecoderFlags aDecoderFlags, SurfaceFlags aSurfaceFlags,
    240    size_t aCurrentFrame, IDecodingTask** aOutTask) {
    241  if (aType == DecoderType::UNKNOWN) {
    242    return NS_ERROR_INVALID_ARG;
    243  }
    244 
    245  // Only can use COUNT_FRAMES with metadata decoders.
    246  if (NS_WARN_IF(bool(aDecoderFlags & DecoderFlags::COUNT_FRAMES))) {
    247    return NS_ERROR_INVALID_ARG;
    248  }
    249 
    250  MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG ||
    251                 aType == DecoderType::WEBP || aType == DecoderType::AVIF,
    252             "Calling CreateAnimationDecoder for non-animating DecoderType");
    253 
    254  // Create an anonymous decoder. Interaction with the SurfaceCache and the
    255  // owning RasterImage will be mediated by AnimationSurfaceProvider.
    256  RefPtr<Decoder> decoder =
    257      GetDecoder(aType, nullptr, /* aIsRedecode = */ true);
    258  MOZ_ASSERT(decoder, "Should have a decoder now");
    259 
    260  // Initialize the decoder.
    261  decoder->SetMetadataDecode(false);
    262  decoder->SetIterator(aSourceBuffer->Iterator());
    263  decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE);
    264  decoder->SetSurfaceFlags(aSurfaceFlags);
    265 
    266  nsresult rv = decoder->Init();
    267  if (NS_FAILED(rv)) {
    268    return NS_ERROR_FAILURE;
    269  }
    270 
    271  // Create an AnimationSurfaceProvider which will manage the decoding process
    272  // and make this decoder's output available in the surface cache.
    273  SurfaceKey surfaceKey =
    274      RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, PlaybackType::eAnimated);
    275  auto provider = MakeNotNull<RefPtr<AnimationSurfaceProvider>>(
    276      aImage, surfaceKey, WrapNotNull(decoder), aCurrentFrame);
    277 
    278  // Attempt to insert the surface provider into the surface cache right away so
    279  // we won't trigger any more decoders with the same parameters.
    280  switch (SurfaceCache::Insert(provider)) {
    281    case InsertOutcome::SUCCESS:
    282      break;
    283    case InsertOutcome::FAILURE_ALREADY_PRESENT:
    284      return NS_ERROR_ALREADY_INITIALIZED;
    285    default:
    286      return NS_ERROR_FAILURE;
    287  }
    288 
    289  // Return the surface provider in its IDecodingTask guise.
    290  RefPtr<IDecodingTask> task = provider.get();
    291  task.forget(aOutTask);
    292  return NS_OK;
    293 }
    294 
    295 /* static */
    296 already_AddRefed<Decoder> DecoderFactory::CloneAnimationDecoder(
    297    Decoder* aDecoder) {
    298  MOZ_ASSERT(aDecoder);
    299 
    300  // In an ideal world, we would assert aDecoder->HasAnimation() but we cannot.
    301  // The decoder may not have detected it is animated yet (e.g. it did not even
    302  // get scheduled yet, or it has only decoded the first frame and has yet to
    303  // rediscover it is animated).
    304  DecoderType type = aDecoder->GetType();
    305  MOZ_ASSERT(type == DecoderType::GIF || type == DecoderType::PNG ||
    306                 type == DecoderType::WEBP || type == DecoderType::AVIF,
    307             "Calling CloneAnimationDecoder for non-animating DecoderType");
    308 
    309  RefPtr<Decoder> decoder = GetDecoder(type, nullptr, /* aIsRedecode = */ true);
    310  MOZ_ASSERT(decoder, "Should have a decoder now");
    311 
    312  // Initialize the decoder.
    313  decoder->SetMetadataDecode(false);
    314  decoder->SetIterator(aDecoder->GetSourceBuffer()->Iterator());
    315  decoder->SetDecoderFlags(aDecoder->GetDecoderFlags());
    316  decoder->SetSurfaceFlags(aDecoder->GetSurfaceFlags());
    317  decoder->SetFrameRecycler(aDecoder->GetFrameRecycler());
    318 
    319  if (NS_FAILED(decoder->Init())) {
    320    return nullptr;
    321  }
    322 
    323  return decoder.forget();
    324 }
    325 
    326 /* static */
    327 already_AddRefed<Decoder> DecoderFactory::CloneAnonymousMetadataDecoder(
    328    Decoder* aDecoder, const Maybe<DecoderFlags>& aDecoderFlags) {
    329  MOZ_ASSERT(aDecoder);
    330 
    331  DecoderType type = aDecoder->GetType();
    332  RefPtr<Decoder> decoder =
    333      GetDecoder(type, nullptr, /* aIsRedecode = */ false);
    334  MOZ_ASSERT(decoder, "Should have a decoder now");
    335 
    336  // Initialize the decoder.
    337  decoder->SetMetadataDecode(true);
    338  decoder->SetIterator(aDecoder->GetSourceBuffer()->Iterator());
    339  if (aDecoderFlags) {
    340    decoder->SetDecoderFlags(*aDecoderFlags);
    341  } else {
    342    decoder->SetDecoderFlags(aDecoder->GetDecoderFlags());
    343  }
    344 
    345  if (NS_FAILED(decoder->Init())) {
    346    return nullptr;
    347  }
    348 
    349  return decoder.forget();
    350 }
    351 
    352 /* static */
    353 already_AddRefed<IDecodingTask> DecoderFactory::CreateMetadataDecoder(
    354    DecoderType aType, NotNull<RasterImage*> aImage, DecoderFlags aFlags,
    355    NotNull<SourceBuffer*> aSourceBuffer) {
    356  if (aType == DecoderType::UNKNOWN) {
    357    return nullptr;
    358  }
    359 
    360  RefPtr<Decoder> decoder =
    361      GetDecoder(aType, aImage, /* aIsRedecode = */ false);
    362  MOZ_ASSERT(decoder, "Should have a decoder now");
    363 
    364  // Initialize the decoder.
    365  decoder->SetMetadataDecode(true);
    366  decoder->SetDecoderFlags(aFlags);
    367  decoder->SetIterator(aSourceBuffer->Iterator());
    368 
    369  if (NS_FAILED(decoder->Init())) {
    370    return nullptr;
    371  }
    372 
    373  RefPtr<IDecodingTask> task = new MetadataDecodingTask(WrapNotNull(decoder));
    374  return task.forget();
    375 }
    376 
    377 /* static */
    378 already_AddRefed<Decoder> DecoderFactory::CreateDecoderForICOResource(
    379    DecoderType aType, SourceBufferIterator&& aIterator,
    380    NotNull<nsICODecoder*> aICODecoder, bool aIsMetadataDecode,
    381    const Maybe<OrientedIntSize>& aExpectedSize,
    382    const Maybe<uint32_t>& aDataOffset
    383    /* = Nothing() */) {
    384  // Create the decoder.
    385  RefPtr<Decoder> decoder;
    386  switch (aType) {
    387    case DecoderType::BMP:
    388      MOZ_ASSERT(aDataOffset);
    389      decoder =
    390          new nsBMPDecoder(aICODecoder->GetImageMaybeNull(), *aDataOffset);
    391      break;
    392 
    393    case DecoderType::PNG:
    394      MOZ_ASSERT(!aDataOffset);
    395      decoder = new nsPNGDecoder(aICODecoder->GetImageMaybeNull());
    396      break;
    397 
    398    default:
    399      MOZ_ASSERT_UNREACHABLE("Invalid ICO resource decoder type");
    400      return nullptr;
    401  }
    402 
    403  MOZ_ASSERT(decoder);
    404 
    405  // Initialize the decoder, copying settings from @aICODecoder.
    406  decoder->SetMetadataDecode(aIsMetadataDecode);
    407  decoder->SetIterator(std::forward<SourceBufferIterator>(aIterator));
    408  if (!aIsMetadataDecode) {
    409    decoder->SetOutputSize(aICODecoder->OutputSize());
    410  }
    411  if (aExpectedSize) {
    412    decoder->SetExpectedSize(*aExpectedSize);
    413  }
    414  decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags());
    415  decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags());
    416  decoder->SetFinalizeFrames(false);
    417 
    418  if (NS_FAILED(decoder->Init())) {
    419    return nullptr;
    420  }
    421 
    422  return decoder.forget();
    423 }
    424 
    425 /* static */
    426 already_AddRefed<Decoder> DecoderFactory::CreateAnonymousDecoder(
    427    DecoderType aType, NotNull<SourceBuffer*> aSourceBuffer,
    428    const Maybe<IntSize>& aOutputSize, DecoderFlags aDecoderFlags,
    429    SurfaceFlags aSurfaceFlags) {
    430  if (aType == DecoderType::UNKNOWN) {
    431    return nullptr;
    432  }
    433 
    434  // Only can use COUNT_FRAMES with metadata decoders.
    435  if (NS_WARN_IF(bool(aDecoderFlags & DecoderFlags::COUNT_FRAMES))) {
    436    return nullptr;
    437  }
    438 
    439  RefPtr<Decoder> decoder =
    440      GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
    441  MOZ_ASSERT(decoder, "Should have a decoder now");
    442 
    443  // Initialize the decoder.
    444  decoder->SetMetadataDecode(false);
    445  decoder->SetIterator(aSourceBuffer->Iterator());
    446 
    447  // Anonymous decoders are always transient; we don't want to optimize surfaces
    448  // or do any other expensive work that might be wasted.
    449  DecoderFlags decoderFlags = DecoderFlags::IMAGE_IS_TRANSIENT;
    450 
    451  decoder->SetDecoderFlags(aDecoderFlags | decoderFlags);
    452  decoder->SetSurfaceFlags(aSurfaceFlags);
    453 
    454  // Set an output size for downscale-during-decode if requested.
    455  if (aOutputSize) {
    456    decoder->SetOutputSize(OrientedIntSize::FromUnknownSize(*aOutputSize));
    457  }
    458 
    459  if (NS_FAILED(decoder->Init())) {
    460    return nullptr;
    461  }
    462 
    463  return decoder.forget();
    464 }
    465 
    466 /* static */
    467 already_AddRefed<Decoder> DecoderFactory::CreateAnonymousMetadataDecoder(
    468    DecoderType aType, NotNull<SourceBuffer*> aSourceBuffer,
    469    DecoderFlags aDecoderFlags) {
    470  if (aType == DecoderType::UNKNOWN) {
    471    return nullptr;
    472  }
    473 
    474  RefPtr<Decoder> decoder =
    475      GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
    476  MOZ_ASSERT(decoder, "Should have a decoder now");
    477 
    478  // Initialize the decoder.
    479  decoder->SetMetadataDecode(true);
    480  decoder->SetIterator(aSourceBuffer->Iterator());
    481  decoder->SetDecoderFlags(aDecoderFlags);
    482 
    483  if (NS_FAILED(decoder->Init())) {
    484    return nullptr;
    485  }
    486 
    487  return decoder.forget();
    488 }
    489 
    490 }  // namespace image
    491 }  // namespace mozilla