image/src/Decoder.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef MOZILLA_IMAGELIB_DECODER_H_
michael@0 7 #define MOZILLA_IMAGELIB_DECODER_H_
michael@0 8
michael@0 9 #include "RasterImage.h"
michael@0 10 #include "imgDecoderObserver.h"
michael@0 11 #include "mozilla/RefPtr.h"
michael@0 12 #include "DecodeStrategy.h"
michael@0 13 #include "ImageMetadata.h"
michael@0 14 #include "Orientation.h"
michael@0 15 #include "mozilla/Telemetry.h"
michael@0 16
michael@0 17 namespace mozilla {
michael@0 18 namespace image {
michael@0 19
michael@0 20 class Decoder
michael@0 21 {
michael@0 22 public:
michael@0 23
michael@0 24 Decoder(RasterImage& aImage);
michael@0 25 virtual ~Decoder();
michael@0 26
michael@0 27 /**
michael@0 28 * Initialize an image decoder. Decoders may not be re-initialized.
michael@0 29 *
michael@0 30 * Notifications Sent: TODO
michael@0 31 */
michael@0 32 void Init();
michael@0 33
michael@0 34 /**
michael@0 35 * Initializes a decoder whose image and observer is already being used by a
michael@0 36 * parent decoder. Decoders may not be re-initialized.
michael@0 37 *
michael@0 38 * Notifications Sent: TODO
michael@0 39 */
michael@0 40 void InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength,
michael@0 41 uint32_t* colormap, uint32_t colormapSize,
michael@0 42 imgFrame* currentFrame);
michael@0 43
michael@0 44 /**
michael@0 45 * Writes data to the decoder.
michael@0 46 *
michael@0 47 * @param aBuffer buffer containing the data to be written
michael@0 48 * @param aCount the number of bytes to write
michael@0 49 *
michael@0 50 * Any errors are reported by setting the appropriate state on the decoder.
michael@0 51 *
michael@0 52 * Notifications Sent: TODO
michael@0 53 */
michael@0 54 void Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
michael@0 55
michael@0 56 /**
michael@0 57 * Informs the decoder that all the data has been written.
michael@0 58 *
michael@0 59 * Notifications Sent: TODO
michael@0 60 */
michael@0 61 void Finish(RasterImage::eShutdownIntent aShutdownIntent);
michael@0 62
michael@0 63 /**
michael@0 64 * Informs the shared decoder that all the data has been written.
michael@0 65 * Should only be used if InitSharedDecoder was useed
michael@0 66 *
michael@0 67 * Notifications Sent: TODO
michael@0 68 */
michael@0 69 void FinishSharedDecoder();
michael@0 70
michael@0 71 /**
michael@0 72 * Tells the decoder to flush any pending invalidations. This informs the image
michael@0 73 * frame of its decoded region, and sends the appropriate OnDataAvailable call
michael@0 74 * to consumers.
michael@0 75 *
michael@0 76 * This can be called any time when we're midway through decoding a frame,
michael@0 77 * and must be called after finishing a frame (before starting a new one).
michael@0 78 */
michael@0 79 void FlushInvalidations();
michael@0 80
michael@0 81 // We're not COM-y, so we don't get refcounts by default
michael@0 82 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Decoder)
michael@0 83
michael@0 84 /*
michael@0 85 * State.
michael@0 86 */
michael@0 87
michael@0 88 // If we're doing a "size decode", we more or less pass through the image
michael@0 89 // data, stopping only to scoop out the image dimensions. A size decode
michael@0 90 // must be enabled by SetSizeDecode() _before_calling Init().
michael@0 91 bool IsSizeDecode() { return mSizeDecode; }
michael@0 92 void SetSizeDecode(bool aSizeDecode)
michael@0 93 {
michael@0 94 NS_ABORT_IF_FALSE(!mInitialized, "Can't set size decode after Init()!");
michael@0 95 mSizeDecode = aSizeDecode;
michael@0 96 }
michael@0 97
michael@0 98 void SetObserver(imgDecoderObserver* aObserver)
michael@0 99 {
michael@0 100 MOZ_ASSERT(aObserver);
michael@0 101 mObserver = aObserver;
michael@0 102 }
michael@0 103
michael@0 104 // The number of frames we have, including anything in-progress. Thus, this
michael@0 105 // is only 0 if we haven't begun any frames.
michael@0 106 uint32_t GetFrameCount() { return mFrameCount; }
michael@0 107
michael@0 108 // The number of complete frames we have (ie, not including anything in-progress).
michael@0 109 uint32_t GetCompleteFrameCount() { return mInFrame ? mFrameCount - 1 : mFrameCount; }
michael@0 110
michael@0 111 // Error tracking
michael@0 112 bool HasError() { return HasDataError() || HasDecoderError(); }
michael@0 113 bool HasDataError() { return mDataError; }
michael@0 114 bool HasDecoderError() { return NS_FAILED(mFailCode); }
michael@0 115 nsresult GetDecoderError() { return mFailCode; }
michael@0 116 void PostResizeError() { PostDataError(); }
michael@0 117 bool GetDecodeDone() const {
michael@0 118 return mDecodeDone;
michael@0 119 }
michael@0 120
michael@0 121 // flags. Keep these in sync with imgIContainer.idl.
michael@0 122 // SetDecodeFlags must be called before Init(), otherwise
michael@0 123 // default flags are assumed.
michael@0 124 enum {
michael@0 125 DECODER_NO_PREMULTIPLY_ALPHA = 0x2, // imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA
michael@0 126 DECODER_NO_COLORSPACE_CONVERSION = 0x4 // imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION
michael@0 127 };
michael@0 128
michael@0 129 enum DecodeStyle {
michael@0 130 PROGRESSIVE, // produce intermediate frames representing the partial state of the image
michael@0 131 SEQUENTIAL // decode to final image immediately
michael@0 132 };
michael@0 133
michael@0 134 void SetDecodeFlags(uint32_t aFlags) { mDecodeFlags = aFlags; }
michael@0 135 uint32_t GetDecodeFlags() { return mDecodeFlags; }
michael@0 136
michael@0 137 bool HasSize() const { return mImageMetadata.HasSize(); }
michael@0 138 void SetSizeOnImage();
michael@0 139
michael@0 140 // Use HistogramCount as an invalid Histogram ID
michael@0 141 virtual Telemetry::ID SpeedHistogram() { return Telemetry::HistogramCount; }
michael@0 142
michael@0 143 ImageMetadata& GetImageMetadata() { return mImageMetadata; }
michael@0 144
michael@0 145 // Tell the decoder infrastructure to allocate a frame. By default, frame 0
michael@0 146 // is created as an ARGB frame with no offset and with size width * height.
michael@0 147 // If decoders need something different, they must ask for it.
michael@0 148 // This is called by decoders when they need a new frame. These decoders
michael@0 149 // must then save the data they have been sent but not yet processed and
michael@0 150 // return from WriteInternal. When the new frame is created, WriteInternal
michael@0 151 // will be called again with nullptr and 0 as arguments.
michael@0 152 void NeedNewFrame(uint32_t frameNum, uint32_t x_offset, uint32_t y_offset,
michael@0 153 uint32_t width, uint32_t height,
michael@0 154 gfxImageFormat format,
michael@0 155 uint8_t palette_depth = 0);
michael@0 156
michael@0 157 virtual bool NeedsNewFrame() const { return mNeedsNewFrame; }
michael@0 158
michael@0 159 // Try to allocate a frame as described in mNewFrameData and return the
michael@0 160 // status code from that attempt. Clears mNewFrameData.
michael@0 161 virtual nsresult AllocateFrame();
michael@0 162
michael@0 163 // Called when a chunk of decoding has been done and the frame needs to be
michael@0 164 // marked as dirty. Must be called only on the main thread.
michael@0 165 void MarkFrameDirty();
michael@0 166
michael@0 167 imgFrame* GetCurrentFrame() const { return mCurrentFrame; }
michael@0 168
michael@0 169 protected:
michael@0 170
michael@0 171 /*
michael@0 172 * Internal hooks. Decoder implementations may override these and
michael@0 173 * only these methods.
michael@0 174 */
michael@0 175 virtual void InitInternal();
michael@0 176 virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy);
michael@0 177 virtual void FinishInternal();
michael@0 178
michael@0 179 /*
michael@0 180 * Progress notifications.
michael@0 181 */
michael@0 182
michael@0 183 // Called by decoders when they determine the size of the image. Informs
michael@0 184 // the image of its size and sends notifications.
michael@0 185 void PostSize(int32_t aWidth,
michael@0 186 int32_t aHeight,
michael@0 187 Orientation aOrientation = Orientation());
michael@0 188
michael@0 189 // Called by decoders when they begin a frame. Informs the image, sends
michael@0 190 // notifications, and does internal book-keeping.
michael@0 191 void PostFrameStart();
michael@0 192
michael@0 193 // Called by decoders when they end a frame. Informs the image, sends
michael@0 194 // notifications, and does internal book-keeping.
michael@0 195 // Specify whether this frame is opaque as an optimization.
michael@0 196 // For animated images, specify the disposal, blend method and timeout for
michael@0 197 // this frame.
michael@0 198 void PostFrameStop(FrameBlender::FrameAlpha aFrameAlpha = FrameBlender::kFrameHasAlpha,
michael@0 199 FrameBlender::FrameDisposalMethod aDisposalMethod = FrameBlender::kDisposeKeep,
michael@0 200 int32_t aTimeout = 0,
michael@0 201 FrameBlender::FrameBlendMethod aBlendMethod = FrameBlender::kBlendOver);
michael@0 202
michael@0 203 // Called by the decoders when they have a region to invalidate. We may not
michael@0 204 // actually pass these invalidations on right away.
michael@0 205 void PostInvalidation(nsIntRect& aRect);
michael@0 206
michael@0 207 // Called by the decoders when they have successfully decoded the image. This
michael@0 208 // may occur as the result of the decoder getting to the appropriate point in
michael@0 209 // the stream, or by us calling FinishInternal().
michael@0 210 //
michael@0 211 // May not be called mid-frame.
michael@0 212 //
michael@0 213 // For animated images, specify the loop count. -1 means loop forever, 0
michael@0 214 // means a single iteration, stopping on the last frame.
michael@0 215 void PostDecodeDone(int32_t aLoopCount = 0);
michael@0 216
michael@0 217 // Data errors are the fault of the source data, decoder errors are our fault
michael@0 218 void PostDataError();
michael@0 219 void PostDecoderError(nsresult aFailCode);
michael@0 220
michael@0 221 /*
michael@0 222 * Member variables.
michael@0 223 *
michael@0 224 */
michael@0 225 RasterImage &mImage;
michael@0 226 imgFrame* mCurrentFrame;
michael@0 227 RefPtr<imgDecoderObserver> mObserver;
michael@0 228 ImageMetadata mImageMetadata;
michael@0 229
michael@0 230 uint8_t* mImageData; // Pointer to image data in either Cairo or 8bit format
michael@0 231 uint32_t mImageDataLength;
michael@0 232 uint32_t* mColormap; // Current colormap to be used in Cairo format
michael@0 233 uint32_t mColormapSize;
michael@0 234
michael@0 235 uint32_t mDecodeFlags;
michael@0 236 bool mDecodeDone;
michael@0 237 bool mDataError;
michael@0 238
michael@0 239 private:
michael@0 240 uint32_t mFrameCount; // Number of frames, including anything in-progress
michael@0 241
michael@0 242 nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame.
michael@0 243
michael@0 244 nsresult mFailCode;
michael@0 245
michael@0 246 struct NewFrameData
michael@0 247 {
michael@0 248 NewFrameData()
michael@0 249 {}
michael@0 250
michael@0 251 NewFrameData(uint32_t num, uint32_t offsetx, uint32_t offsety,
michael@0 252 uint32_t width, uint32_t height,
michael@0 253 gfxImageFormat format, uint8_t paletteDepth)
michael@0 254 : mFrameNum(num)
michael@0 255 , mOffsetX(offsetx)
michael@0 256 , mOffsetY(offsety)
michael@0 257 , mWidth(width)
michael@0 258 , mHeight(height)
michael@0 259 , mFormat(format)
michael@0 260 , mPaletteDepth(paletteDepth)
michael@0 261 {}
michael@0 262 uint32_t mFrameNum;
michael@0 263 uint32_t mOffsetX;
michael@0 264 uint32_t mOffsetY;
michael@0 265 uint32_t mWidth;
michael@0 266 uint32_t mHeight;
michael@0 267 gfxImageFormat mFormat;
michael@0 268 uint8_t mPaletteDepth;
michael@0 269 };
michael@0 270 NewFrameData mNewFrameData;
michael@0 271 bool mNeedsNewFrame;
michael@0 272 bool mInitialized;
michael@0 273 bool mSizeDecode;
michael@0 274 bool mInFrame;
michael@0 275 bool mIsAnimated;
michael@0 276 };
michael@0 277
michael@0 278 } // namespace image
michael@0 279 } // namespace mozilla
michael@0 280
michael@0 281 #endif // MOZILLA_IMAGELIB_DECODER_H_

mercurial