Decoder.h 19 KB

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