LCOV - code coverage report
Current view: top level - image - Decoder.h (source / functions) Hit Total Coverage
Test: output.info Lines: 64 74 86.5 %
Date: 2017-07-14 16:53:18 Functions: 32 39 82.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13