tor-browser

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

Decoder.h (22533B)


      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 #ifndef mozilla_image_Decoder_h
      7 #define mozilla_image_Decoder_h
      8 
      9 #include "FrameAnimator.h"
     10 #include "RasterImage.h"
     11 #include "mozilla/glean/ImageDecodersMetrics.h"
     12 #include "mozilla/Maybe.h"
     13 #include "mozilla/NotNull.h"
     14 #include "mozilla/RefPtr.h"
     15 #include "AnimationParams.h"
     16 #include "DecoderFlags.h"
     17 #include "ImageMetadata.h"
     18 #include "Orientation.h"
     19 #include "Resolution.h"
     20 #include "SourceBuffer.h"
     21 #include "StreamingLexer.h"
     22 #include "SurfaceFlags.h"
     23 #include "qcms.h"
     24 
     25 enum class CMSMode : int32_t;
     26 
     27 namespace mozilla {
     28 
     29 namespace image {
     30 
     31 class imgFrame;
     32 
     33 struct DecoderFinalStatus final {
     34  DecoderFinalStatus(bool aWasMetadataDecode, bool aFinished, bool aHadError,
     35                     bool aShouldReportError)
     36      : mWasMetadataDecode(aWasMetadataDecode),
     37        mFinished(aFinished),
     38        mHadError(aHadError),
     39        mShouldReportError(aShouldReportError) {}
     40 
     41  /// True if this was a metadata decode.
     42  const bool mWasMetadataDecode : 1;
     43 
     44  /// True if this decoder finished, whether successfully or due to failure.
     45  const bool mFinished : 1;
     46 
     47  /// True if this decoder encountered an error.
     48  const bool mHadError : 1;
     49 
     50  /// True if this decoder encountered the kind of error that should be reported
     51  /// to the console.
     52  const bool mShouldReportError : 1;
     53 };
     54 
     55 struct DecoderTelemetry final {
     56  DecoderTelemetry(
     57      const Maybe<glean::impl::MemoryDistributionMetric>& aSpeedMetric,
     58      size_t aBytesDecoded, uint32_t aChunkCount, TimeDuration aDecodeTime)
     59      : mSpeedMetric(aSpeedMetric),
     60        mBytesDecoded(aBytesDecoded),
     61        mChunkCount(aChunkCount),
     62        mDecodeTime(aDecodeTime) {}
     63 
     64  /// @return our decoder's speed, in KBps.
     65  int32_t Speed() const {
     66    return mBytesDecoded / (1024 * mDecodeTime.ToSeconds());
     67  }
     68 
     69  /// @return our decoder's decode time, in microseconds.
     70  int32_t DecodeTimeMicros() { return mDecodeTime.ToMicroseconds(); }
     71 
     72  /// The per-image-format telemetry ID for recording our decoder's speed, or
     73  /// Nothing() if we don't record speed telemetry for this kind of decoder.
     74  const Maybe<glean::impl::MemoryDistributionMetric> mSpeedMetric;
     75 
     76  /// The number of bytes of input our decoder processed.
     77  const size_t mBytesDecoded;
     78 
     79  /// The number of chunks our decoder's input was divided into.
     80  const uint32_t mChunkCount;
     81 
     82  /// The amount of time our decoder spent inside DoDecode().
     83  const TimeDuration mDecodeTime;
     84 };
     85 
     86 /**
     87 * Interface which owners of an animated Decoder object must implement in order
     88 * to use recycling. It allows the decoder to get a handle to the recycled
     89 * frames.
     90 */
     91 class IDecoderFrameRecycler {
     92 public:
     93  /**
     94   * Request the next available recycled imgFrame from the recycler.
     95   *
     96   * @param aRecycleRect  If a frame is returned, this must be set to the
     97   *                      accumulated dirty rect between the frame being
     98   *                      recycled, and the frame being generated.
     99   *
    100   * @returns The recycled frame, if any is available.
    101   */
    102  virtual RawAccessFrameRef RecycleFrame(gfx::IntRect& aRecycleRect) = 0;
    103 };
    104 
    105 class Decoder {
    106 public:
    107  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Decoder)
    108 
    109  explicit Decoder(RasterImage* aImage);
    110 
    111  /**
    112   * Initialize an image decoder. Decoders may not be re-initialized.
    113   *
    114   * @return NS_OK if the decoder could be initialized successfully.
    115   */
    116  nsresult Init();
    117 
    118  /**
    119   * Decodes, reading all data currently available in the SourceBuffer.
    120   *
    121   * If more data is needed and @aOnResume is non-null, Decode() will schedule
    122   * @aOnResume to be called when more data is available.
    123   *
    124   * @return a LexerResult which may indicate:
    125   *   - the image has been successfully decoded (TerminalState::SUCCESS), or
    126   *   - the image has failed to decode (TerminalState::FAILURE), or
    127   *   - the decoder is yielding until it gets more data
    128   *     (Yield::NEED_MORE_DATA), or
    129   *   - the decoder is yielding to allow the caller to access intermediate
    130   *     output (Yield::OUTPUT_AVAILABLE).
    131   */
    132  LexerResult Decode(IResumable* aOnResume = nullptr);
    133 
    134  /**
    135   * Terminate this decoder in a failure state, just as if the decoder
    136   * implementation had returned TerminalState::FAILURE from DoDecode().
    137   *
    138   * XXX(seth): This method should be removed ASAP; it exists only because
    139   * RasterImage::FinalizeDecoder() requires an actual Decoder object as an
    140   * argument, so we can't simply tell RasterImage a decode failed except via an
    141   * intervening decoder. We'll fix this in bug 1291071.
    142   */
    143  LexerResult TerminateFailure();
    144 
    145  /**
    146   * Given a maximum number of bytes we're willing to decode, @aByteLimit,
    147   * returns true if we should attempt to run this decoder synchronously.
    148   */
    149  bool ShouldSyncDecode(size_t aByteLimit);
    150 
    151  /**
    152   * Gets the invalidation region accumulated by the decoder so far, and clears
    153   * the decoder's invalidation region. This means that each call to
    154   * TakeInvalidRect() returns only the invalidation region accumulated since
    155   * the last call to TakeInvalidRect().
    156   */
    157  OrientedIntRect TakeInvalidRect() {
    158    OrientedIntRect invalidRect = mInvalidRect;
    159    mInvalidRect.SetEmpty();
    160    return invalidRect;
    161  }
    162 
    163  /**
    164   * Gets the progress changes accumulated by the decoder so far, and clears
    165   * them. This means that each call to TakeProgress() returns only the changes
    166   * accumulated since the last call to TakeProgress().
    167   */
    168  Progress TakeProgress() {
    169    Progress progress = mProgress;
    170    mProgress = NoProgress;
    171    return progress;
    172  }
    173 
    174  /**
    175   * Returns true if there's any progress to report.
    176   */
    177  bool HasProgress() const {
    178    return mProgress != NoProgress || !mInvalidRect.IsEmpty() ||
    179           mFinishedNewFrame;
    180  }
    181 
    182  /*
    183   * State.
    184   */
    185 
    186  /**
    187   * If we're doing a metadata decode, we only decode the image's headers, which
    188   * is enough to determine the image's intrinsic size. A metadata decode is
    189   * enabled by calling SetMetadataDecode() *before* calling Init().
    190   */
    191  void SetMetadataDecode(bool aMetadataDecode) {
    192    MOZ_ASSERT(!mInitialized, "Shouldn't be initialized yet");
    193    mMetadataDecode = aMetadataDecode;
    194  }
    195  bool IsMetadataDecode() const { return mMetadataDecode; }
    196 
    197  /**
    198   * Should we return how many frames we expect are in the animation.
    199   */
    200  bool WantsFrameCount() const {
    201    return bool(mDecoderFlags & DecoderFlags::COUNT_FRAMES);
    202  }
    203 
    204  /**
    205   * Sets the output size of this decoder. If this is smaller than the intrinsic
    206   * size of the image, we'll downscale it while decoding. For memory usage
    207   * reasons, upscaling is forbidden and will trigger assertions in debug
    208   * builds.
    209   *
    210   * Not calling SetOutputSize() means that we should just decode at the
    211   * intrinsic size, whatever it is.
    212   *
    213   * If SetOutputSize() was called, ExplicitOutputSize() can be used to
    214   * determine the value that was passed to it.
    215   *
    216   * This must be called before Init() is called.
    217   */
    218  void SetOutputSize(const OrientedIntSize& aSize);
    219 
    220  /**
    221   * @return the output size of this decoder. If this is smaller than the
    222   * intrinsic size, then the image will be downscaled during the decoding
    223   * process.
    224   *
    225   * Illegal to call if HasSize() returns false.
    226   */
    227  OrientedIntSize OutputSize() const {
    228    MOZ_ASSERT(HasSize());
    229    return *mOutputSize;
    230  }
    231 
    232  /**
    233   * @return either the size passed to SetOutputSize() or Nothing(), indicating
    234   * that SetOutputSize() was not explicitly called.
    235   */
    236  Maybe<OrientedIntSize> ExplicitOutputSize() const;
    237 
    238  /**
    239   * Sets the expected image size of this decoder. Decoding will fail if this
    240   * does not match.
    241   */
    242  void SetExpectedSize(const OrientedIntSize& aSize) {
    243    mExpectedSize.emplace(aSize);
    244  }
    245 
    246  /**
    247   * Is the image size what was expected, if specified?
    248   */
    249  bool IsExpectedSize() const {
    250    return mExpectedSize.isNothing() || *mExpectedSize == Size();
    251  }
    252 
    253  /**
    254   * Set an iterator to the SourceBuffer which will feed data to this decoder.
    255   * This must always be called before calling Init(). (And only before Init().)
    256   *
    257   * XXX(seth): We should eliminate this method and pass a SourceBufferIterator
    258   * to the various decoder constructors instead.
    259   */
    260  void SetIterator(SourceBufferIterator&& aIterator) {
    261    MOZ_ASSERT(!mInitialized, "Shouldn't be initialized yet");
    262    mIterator.emplace(std::move(aIterator));
    263  }
    264 
    265  SourceBuffer* GetSourceBuffer() const { return mIterator->Owner(); }
    266 
    267  /**
    268   * Should this decoder send partial invalidations?
    269   */
    270  bool ShouldSendPartialInvalidations() const {
    271    return !(mDecoderFlags & DecoderFlags::IS_REDECODE);
    272  }
    273 
    274  /**
    275   * Should we stop decoding after the first frame?
    276   */
    277  bool IsFirstFrameDecode() const {
    278    return bool(mDecoderFlags & DecoderFlags::FIRST_FRAME_ONLY);
    279  }
    280 
    281  /**
    282   * @return the number of complete animation frames which have been decoded so
    283   * far, if it has changed since the last call to TakeCompleteFrameCount();
    284   * otherwise, returns Nothing().
    285   */
    286  Maybe<uint32_t> TakeCompleteFrameCount();
    287 
    288  // The number of frames we have, including anything in-progress. Thus, this
    289  // is only 0 if we haven't begun any frames.
    290  uint32_t GetFrameCount() { return mFrameCount; }
    291 
    292  // Did we discover that the image we're decoding is animated?
    293  bool HasAnimation() const { return mImageMetadata.HasAnimation(); }
    294 
    295  // Error tracking
    296  bool HasError() const { return mError; }
    297  bool ShouldReportError() const { return mShouldReportError; }
    298 
    299  // Finalize frames
    300  void SetFinalizeFrames(bool aFinalize) { mFinalizeFrames = aFinalize; }
    301  bool GetFinalizeFrames() const { return mFinalizeFrames; }
    302 
    303  /// Did we finish decoding enough that calling Decode() again would be
    304  /// useless?
    305  bool GetDecodeDone() const {
    306    return mReachedTerminalState || mDecodeDone ||
    307           (mMetadataDecode && HasSize() && !WantsFrameCount()) || HasError();
    308  }
    309 
    310  /// Are we in the middle of a frame right now? Used for assertions only.
    311  bool InFrame() const { return mInFrame; }
    312 
    313  /// Is the image valid if embedded inside an ICO.
    314  virtual bool IsValidICOResource() const { return false; }
    315 
    316  /// Type of decoder.
    317  virtual DecoderType GetType() const { return DecoderType::UNKNOWN; }
    318 
    319  enum DecodeStyle {
    320    PROGRESSIVE,  // produce intermediate frames representing the partial
    321                  // state of the image
    322    SEQUENTIAL    // decode to final image immediately
    323  };
    324 
    325  /**
    326   * Get or set the DecoderFlags that influence the behavior of this decoder.
    327   */
    328  void SetDecoderFlags(DecoderFlags aDecoderFlags) {
    329    MOZ_ASSERT(!mInitialized);
    330    mDecoderFlags = aDecoderFlags;
    331  }
    332  DecoderFlags GetDecoderFlags() const { return mDecoderFlags; }
    333 
    334  /**
    335   * Get or set the SurfaceFlags that select the kind of output this decoder
    336   * will produce.
    337   */
    338  void SetSurfaceFlags(SurfaceFlags aSurfaceFlags);
    339  SurfaceFlags GetSurfaceFlags() const { return mSurfaceFlags; }
    340 
    341  /// @return true if we know the intrinsic size of the image we're decoding.
    342  bool HasSize() const { return mImageMetadata.HasSize(); }
    343 
    344  /**
    345   * @return the intrinsic size of the image we're decoding.
    346   *
    347   * Illegal to call if HasSize() returns false.
    348   */
    349  OrientedIntSize Size() const {
    350    MOZ_ASSERT(HasSize());
    351    return mImageMetadata.GetSize();
    352  }
    353 
    354  /**
    355   * @return an IntRect which covers the entire area of this image at its
    356   * intrinsic size, appropriate for use as a frame rect when the image itself
    357   * does not specify one.
    358   *
    359   * Illegal to call if HasSize() returns false.
    360   */
    361  OrientedIntRect FullFrame() const {
    362    return OrientedIntRect(OrientedIntPoint(), Size());
    363  }
    364 
    365  /**
    366   * @return an IntRect which covers the entire area of this image at its size
    367   * after scaling - that is, at its output size.
    368   *
    369   * XXX(seth): This is only used for decoders which are using the old
    370   * Downscaler code instead of SurfacePipe, since the old AllocateFrame() and
    371   * Downscaler APIs required that the frame rect be specified in output space.
    372   * We should remove this once all decoders use SurfacePipe.
    373   *
    374   * Illegal to call if HasSize() returns false.
    375   */
    376  OrientedIntRect FullOutputFrame() const {
    377    return OrientedIntRect(OrientedIntPoint(), OutputSize());
    378  }
    379 
    380  /**
    381   * @return the orientation of the image.
    382   *
    383   * Illegal to call if HasSize() returns false.
    384   */
    385  Orientation GetOrientation() const {
    386    MOZ_ASSERT(HasSize());
    387    return mImageMetadata.GetOrientation();
    388  }
    389 
    390  /// @return final status information about this decoder. Should be called
    391  /// after we decide we're not going to run the decoder anymore.
    392  DecoderFinalStatus FinalStatus() const;
    393 
    394  /// @return the metadata we collected about this image while decoding.
    395  const ImageMetadata& GetImageMetadata() { return mImageMetadata; }
    396 
    397  /// @return performance telemetry we collected while decoding.
    398  DecoderTelemetry Telemetry() const;
    399 
    400  /**
    401   * @return a weak pointer to the image associated with this decoder. Illegal
    402   * to call if this decoder is not associated with an image.
    403   */
    404  NotNull<RasterImage*> GetImage() const { return WrapNotNull(mImage.get()); }
    405 
    406  /**
    407   * @return a possibly-null weak pointer to the image associated with this
    408   * decoder. May be called even if this decoder is not associated with an
    409   * image.
    410   */
    411  RasterImage* GetImageMaybeNull() const { return mImage.get(); }
    412 
    413  RawAccessFrameRef GetCurrentFrameRef() {
    414    return mCurrentFrame ? mCurrentFrame->RawAccessRef() : RawAccessFrameRef();
    415  }
    416 
    417  /**
    418   * For use during decoding only. Allows the BlendAnimationFilter to get the
    419   * current frame we are producing for its animation parameters.
    420   */
    421  imgFrame* GetCurrentFrame() { return mCurrentFrame.get(); }
    422 
    423  /**
    424   * For use during decoding only. Allows the BlendAnimationFilter to get the
    425   * frame it should be pulling the previous frame data from.
    426   */
    427  const RawAccessFrameRef& GetRestoreFrameRef() const { return mRestoreFrame; }
    428 
    429  const gfx::IntRect& GetRestoreDirtyRect() const { return mRestoreDirtyRect; }
    430 
    431  const gfx::IntRect& GetRecycleRect() const { return mRecycleRect; }
    432 
    433  const gfx::IntRect& GetFirstFrameRefreshArea() const {
    434    return mFirstFrameRefreshArea;
    435  }
    436 
    437  bool HasFrameToTake() const { return mHasFrameToTake; }
    438  void ClearHasFrameToTake() {
    439    MOZ_ASSERT(mHasFrameToTake);
    440    mHasFrameToTake = false;
    441  }
    442 
    443  IDecoderFrameRecycler* GetFrameRecycler() const { return mFrameRecycler; }
    444  void SetFrameRecycler(IDecoderFrameRecycler* aFrameRecycler) {
    445    mFrameRecycler = aFrameRecycler;
    446  }
    447 
    448 protected:
    449  friend class AutoRecordDecoderTelemetry;
    450  friend class DecoderTestHelper;
    451  friend class nsBMPDecoder;
    452  friend class nsICODecoder;
    453  friend class ReorientSurfaceSink;
    454  friend class SurfaceSink;
    455 
    456  virtual ~Decoder();
    457 
    458  /*
    459   * Internal hooks. Decoder implementations may override these and
    460   * only these methods.
    461   *
    462   * BeforeFinishInternal() can be used to detect if decoding is in an
    463   * incomplete state, e.g. due to file truncation, in which case it should
    464   * return a failing nsresult.
    465   */
    466  virtual nsresult InitInternal();
    467  virtual LexerResult DoDecode(SourceBufferIterator& aIterator,
    468                               IResumable* aOnResume) = 0;
    469  virtual nsresult BeforeFinishInternal();
    470  virtual nsresult FinishInternal();
    471  virtual nsresult FinishWithErrorInternal();
    472 
    473  qcms_profile* GetCMSOutputProfile() const;
    474  qcms_transform* GetCMSsRGBTransform(gfx::SurfaceFormat aFormat) const;
    475 
    476  /**
    477   * @return the per-image-format telemetry ID for recording this decoder's
    478   * speed, or Nothing() if we don't record speed telemetry for this kind of
    479   * decoder.
    480   */
    481  virtual Maybe<glean::impl::MemoryDistributionMetric> SpeedMetric() const {
    482    return Nothing();
    483  }
    484 
    485  /*
    486   * Progress notifications.
    487   */
    488 
    489  // Called by decoders when they determine the size of the image. Informs
    490  // the image of its size and sends notifications.
    491  void PostSize(int32_t aWidth, int32_t aHeight, Orientation = Orientation(),
    492                Resolution = Resolution());
    493 
    494  // Called by decoders if they determine that the image has transparency.
    495  //
    496  // This should be fired as early as possible to allow observers to do things
    497  // that affect content, so it's necessarily pessimistic - if there's a
    498  // possibility that the image has transparency, for example because its header
    499  // specifies that it has an alpha channel, we fire PostHasTransparency
    500  // immediately. PostFrameStop's aFrameOpacity argument, on the other hand, is
    501  // only used internally to ImageLib. Because PostFrameStop isn't delivered
    502  // until the entire frame has been decoded, decoders may take into account the
    503  // actual contents of the frame and give a more accurate result.
    504  void PostHasTransparency();
    505 
    506  // Called by decoders if they determine that the image is animated.
    507  //
    508  // @param aTimeout The time for which the first frame should be shown before
    509  //                 we advance to the next frame.
    510  void PostIsAnimated(FrameTimeout aFirstFrameTimeout);
    511 
    512  // Called by decoders if they determine the expected frame count.
    513  // @param aFrameCount The expected frame count.
    514  void PostFrameCount(uint32_t aFrameCount);
    515 
    516  // Called by decoders when they end a frame. Informs the image, sends
    517  // notifications, and does internal book-keeping.
    518  // Specify whether this frame is opaque as an optimization.
    519  // For animated images, specify the disposal, blend method and timeout for
    520  // this frame.
    521  void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY);
    522 
    523  /**
    524   * Called by the decoders when they have a region to invalidate. We may not
    525   * actually pass these invalidations on right away.
    526   *
    527   * @param aRect The invalidation rect in the coordinate system of the unscaled
    528   *              image (that is, the image at its intrinsic size).
    529   * @param aRectAtOutputSize If not Nothing(), the invalidation rect in the
    530   *                          coordinate system of the scaled image (that is,
    531   *                          the image at our output size). This must
    532   *                          be supplied if we're downscaling during decode.
    533   */
    534  void PostInvalidation(
    535      const OrientedIntRect& aRect,
    536      const Maybe<OrientedIntRect>& aRectAtOutputSize = Nothing());
    537 
    538  // For animated images, specify the loop count. -1 means loop forever, 0
    539  // means a single iteration, stopping on the last frame.
    540  void PostLoopCount(int32_t aLoopCount);
    541 
    542  // Called by the decoders when they have successfully decoded the image. This
    543  // may occur as the result of the decoder getting to the appropriate point in
    544  // the stream, or by us calling FinishInternal().
    545  //
    546  // May not be called mid-frame.
    547  void PostDecodeDone();
    548 
    549  /**
    550   * Allocates a new frame, making it our current frame if successful.
    551   */
    552  nsresult AllocateFrame(const gfx::IntSize& aOutputSize,
    553                         gfx::SurfaceFormat aFormat,
    554                         const Maybe<AnimationParams>& aAnimParams = Nothing());
    555 
    556 private:
    557  /// Report that an error was encountered while decoding.
    558  void PostError();
    559 
    560  /**
    561   * CompleteDecode() finishes up the decoding process after Decode() determines
    562   * that we're finished. It records final progress and does all the cleanup
    563   * that's possible off-main-thread.
    564   */
    565  void CompleteDecode();
    566 
    567  /// @return the number of complete frames we have. Does not include the
    568  /// current frame if it's unfinished.
    569  uint32_t GetCompleteFrameCount() {
    570    if (mFrameCount == 0) {
    571      return 0;
    572    }
    573 
    574    return mInFrame ? mFrameCount - 1 : mFrameCount;
    575  }
    576 
    577  RawAccessFrameRef AllocateFrameInternal(
    578      const gfx::IntSize& aOutputSize, gfx::SurfaceFormat aFormat,
    579      const Maybe<AnimationParams>& aAnimParams,
    580      RawAccessFrameRef&& aPreviousFrame);
    581 
    582 protected:
    583  static uint8_t ChooseTransferCharacteristics(uint8_t aTC);
    584 
    585  /// Color management profile from the ICCP chunk in the image.
    586  qcms_profile* mInProfile;
    587 
    588  /// Color management transform to apply to image data.
    589  qcms_transform* mTransform;
    590 
    591  uint8_t* mImageData;  // Pointer to image data in BGRA/X
    592  uint32_t mImageDataLength;
    593 
    594  CMSMode mCMSMode;
    595 
    596 private:
    597  RefPtr<RasterImage> mImage;
    598  Maybe<SourceBufferIterator> mIterator;
    599  IDecoderFrameRecycler* mFrameRecycler;
    600 
    601  // The current frame the decoder is producing.
    602  RawAccessFrameRef mCurrentFrame;
    603 
    604  // The complete frame to combine with the current partial frame to produce
    605  // a complete current frame.
    606  RawAccessFrameRef mRestoreFrame;
    607 
    608  ImageMetadata mImageMetadata;
    609 
    610  OrientedIntRect
    611      mInvalidRect;  // Tracks new rows as the current frame is decoded.
    612  gfx::IntRect mRestoreDirtyRect;  // Tracks an invalidation region between the
    613                                   // restore frame and the previous frame.
    614  gfx::IntRect mRecycleRect;       // Tracks an invalidation region between the
    615                                   // recycled frame and the current frame.
    616  Maybe<OrientedIntSize> mOutputSize;    // The size of our output surface.
    617  Maybe<OrientedIntSize> mExpectedSize;  // The expected size of the image.
    618  Progress mProgress;
    619 
    620  uint32_t mFrameCount;      // Number of frames, including anything in-progress
    621  FrameTimeout mLoopLength;  // Length of a single loop of this image.
    622  gfx::IntRect
    623      mFirstFrameRefreshArea;  // The area of the image that needs to
    624                               // be invalidated when the animation loops.
    625 
    626  // Telemetry data for this decoder.
    627  TimeDuration mDecodeTime;
    628 
    629  DecoderFlags mDecoderFlags;
    630  SurfaceFlags mSurfaceFlags;
    631 
    632  bool mInitialized : 1;
    633  bool mMetadataDecode : 1;
    634  bool mHaveExplicitOutputSize : 1;
    635  bool mInFrame : 1;
    636  bool mFinishedNewFrame : 1;  // True if PostFrameStop() has been called since
    637                               // the last call to TakeCompleteFrameCount().
    638  // Has a new frame that AnimationSurfaceProvider can take. Unfortunately this
    639  // has to be separate from mFinishedNewFrame because the png decoder yields a
    640  // new frame before calling PostFrameStop().
    641  bool mHasFrameToTake : 1;
    642  bool mReachedTerminalState : 1;
    643  bool mDecodeDone : 1;
    644  bool mError : 1;
    645  bool mShouldReportError : 1;
    646  bool mFinalizeFrames : 1;
    647 };
    648 
    649 }  // namespace image
    650 }  // namespace mozilla
    651 
    652 #endif  // mozilla_image_Decoder_h