aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@google.com>2017-08-17 13:33:56 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-08-17 13:34:07 +0000
commitdb68a426b6ba3a0fa1cace25ac306037eb7413a6 (patch)
tree6a928b31410abb8d866ed8c5289d7243e5020155 /src/codec
parentbe1b071753538584c34257ce6eb17dcb78ef7d35 (diff)
Revert "skia: add heif decoding support"
This reverts commit c2a954290dc3888f877a047098b84c24363895fb. Reason for revert: both Android and Google3 rolls cannot compile. Android cannot cast std::unique_ptr<T> to T*, Google3 cannot find HeifDecoderAPI.h. Original change's description: > skia: add heif decoding support > > Bug: b/64077740 > Change-Id: I11e0243bcc4c21c0aa5aa29a719dd0fcba7ae6f7 > Reviewed-on: https://skia-review.googlesource.com/35123 > Reviewed-by: Chong Zhang <chz@google.com> > Reviewed-by: Leon Scroggins <scroggo@google.com> > Commit-Queue: Chong Zhang <chz@google.com> > Commit-Queue: Leon Scroggins <scroggo@google.com> TBR=scroggo@google.com,chz@google.com Change-Id: Id98f025e63daec50408186000453d1695170f7a8 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: b/64077740 Reviewed-on: https://skia-review.googlesource.com/35741 Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Mike Klein <mtklein@google.com>
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/SkAndroidCodec.cpp3
-rw-r--r--src/codec/SkCodec.cpp14
-rw-r--r--src/codec/SkHeifCodec.cpp397
-rw-r--r--src/codec/SkHeifCodec.h108
-rw-r--r--src/codec/SkWebpCodec.h2
5 files changed, 10 insertions, 514 deletions
diff --git a/src/codec/SkAndroidCodec.cpp b/src/codec/SkAndroidCodec.cpp
index 3bf69053ea..3a57352113 100644
--- a/src/codec/SkAndroidCodec.cpp
+++ b/src/codec/SkAndroidCodec.cpp
@@ -83,9 +83,6 @@ std::unique_ptr<SkAndroidCodec> SkAndroidCodec::MakeFromStream(std::unique_ptr<S
case SkEncodedImageFormat::kGIF:
case SkEncodedImageFormat::kBMP:
case SkEncodedImageFormat::kWBMP:
-#ifdef SK_HAS_HEIF_LIBRARY
- case SkEncodedImageFormat::kHEIF:
-#endif
return skstd::make_unique<SkSampledCodec>(codec.release());
#ifdef SK_HAS_WEBP_LIBRARY
case SkEncodedImageFormat::kWEBP:
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index 7dc10854d2..2b6108250c 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -23,7 +23,6 @@
#include "SkStream.h"
#include "SkWbmpCodec.h"
#include "SkWebpCodec.h"
-#include "SkHeifCodec.h"
struct DecoderProc {
bool (*IsFormat)(const void*, size_t);
@@ -42,12 +41,13 @@ static const DecoderProc gDecoderProcs[] = {
{ SkIcoCodec::IsIco, SkIcoCodec::MakeFromStream },
#endif
{ SkBmpCodec::IsBmp, SkBmpCodec::MakeFromStream },
- { SkWbmpCodec::IsWbmp, SkWbmpCodec::MakeFromStream },
-#ifdef SK_HAS_HEIF_LIBRARY
- { SkHeifCodec::IsHeif, SkHeifCodec::MakeFromStream },
-#endif
+ { SkWbmpCodec::IsWbmp, SkWbmpCodec::MakeFromStream }
};
+size_t SkCodec::MinBufferedBytesNeeded() {
+ return WEBP_VP8_HEADER_SIZE;
+}
+
std::unique_ptr<SkCodec> SkCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
Result* outResult, SkPngChunkReader* chunkReader) {
Result resultStorage;
@@ -60,7 +60,9 @@ std::unique_ptr<SkCodec> SkCodec::MakeFromStream(std::unique_ptr<SkStream> strea
return nullptr;
}
- constexpr size_t bytesToRead = MinBufferedBytesNeeded();
+ // 14 is enough to read all of the supported types.
+ const size_t bytesToRead = 14;
+ SkASSERT(bytesToRead <= MinBufferedBytesNeeded());
char buffer[bytesToRead];
size_t bytesRead = stream->peek(buffer, bytesToRead);
diff --git a/src/codec/SkHeifCodec.cpp b/src/codec/SkHeifCodec.cpp
deleted file mode 100644
index aea3ef0745..0000000000
--- a/src/codec/SkHeifCodec.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkCodec.h"
-#include "SkCodecPriv.h"
-#include "SkColorPriv.h"
-#include "SkColorSpace_Base.h"
-#include "SkStream.h"
-#include "SkTypes.h"
-#include "SkHeifCodec.h"
-#include "SkEndian.h"
-#include "HeifDecoderAPI.h"
-
-#define FOURCC(c1, c2, c3, c4) \
- ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4))
-
-bool SkHeifCodec::IsHeif(const void* buffer, size_t bytesRead) {
- // Parse the ftyp box up to bytesRead to determine if this is HEIF.
- // Any valid ftyp box should have at least 8 bytes.
- if (bytesRead < 8) {
- return false;
- }
-
- uint32_t* ptr = (uint32_t*)buffer;
- uint64_t chunkSize = SkEndian_SwapBE32(ptr[0]);
- uint32_t chunkType = SkEndian_SwapBE32(ptr[1]);
-
- if (chunkType != FOURCC('f', 't', 'y', 'p')) {
- return false;
- }
-
- off64_t offset = 8;
- if (chunkSize == 1) {
- // This indicates that the next 8 bytes represent the chunk size,
- // and chunk data comes after that.
- if (bytesRead < 16) {
- return false;
- }
- auto* chunkSizePtr = SkTAddOffset<const uint64_t>(buffer, offset);
- chunkSize = SkEndian_SwapBE64(*chunkSizePtr);
- if (chunkSize < 16) {
- // The smallest valid chunk is 16 bytes long in this case.
- return false;
- }
- offset += 8;
- } else if (chunkSize < 8) {
- // The smallest valid chunk is 8 bytes long.
- return false;
- }
-
- if (chunkSize > bytesRead) {
- chunkSize = bytesRead;
- }
- off64_t chunkDataSize = chunkSize - offset;
- // It should at least have major brand (4-byte) and minor version (4-bytes).
- // The rest of the chunk (if any) is a list of (4-byte) compatible brands.
- if (chunkDataSize < 8) {
- return false;
- }
-
- uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
- for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
- if (i == 1) {
- // Skip this index, it refers to the minorVersion,
- // not a brand.
- continue;
- }
- auto* brandPtr = SkTAddOffset<const uint32_t>(buffer, offset + 4 * i);
- uint32_t brand = SkEndian_SwapBE32(*brandPtr);
- if (brand == FOURCC('m', 'i', 'f', '1') || brand == FOURCC('h', 'e', 'i', 'c')) {
- return true;
- }
- }
- return false;
-}
-
-std::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(
- std::unique_ptr<SkStream> stream, Result* result) {
- SkCodec* codec = nullptr;
-
- *result = ReadHeader(stream, &codec);
- if (kSuccess == *result) {
- // Codec has taken ownership of the stream, we do not need to delete it
- SkASSERT(codec);
- stream.release();
- return codec;
- }
- return nullptr;
-}
-
-static SkCodec::Origin get_orientation(const HeifFrameInfo& frameInfo) {
- switch (frameInfo.mRotationAngle) {
- case 0: return SkCodec::kTopLeft_Origin;
- case 90: return SkCodec::kRightTop_Origin;
- case 180: return SkCodec::kBottomRight_Origin;
- case 270: return SkCodec::kLeftBottom_Origin;
- }
- return SkCodec::kDefault_Origin;
-}
-
-struct SkHeifStreamWrapper : public HeifStream {
- SkHeifStreamWrapper(SkStream* stream) : fStream(stream) {}
-
- ~SkHeifStreamWrapper() override {}
-
- size_t read(void* buffer, size_t size) override {
- return fStream->read(buffer, size);
- }
-
- bool rewind() override {
- return fStream->rewind();
- }
-
- bool seek(size_t position) override {
- return fStream->seek(position);
- }
-
- bool hasLength() const override {
- return fStream->hasLength();
- }
-
- size_t getLength() const override {
- return fStream->getLength();
- }
-
-private:
- std::unique_ptr<SkStream> fStream;
-};
-
-SkCodec::Result SkHeifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut) {
- std::unique_ptr<SkHeifStreamWrapper> streamWrapper(
- new SkHeifStreamWrapper(stream));
-
- SkASSERT(codecOut != nullptr);
-
- // Create a HeifDecoder to own all of the decode information
- std::unique_ptr<HeifDecoder> heifDecoder(createHeifDecoder());
- if (heifDecoder.get() == nullptr) {
- return kInternalError;
- }
-
- // Initialize the decoder info and the source manager
- HeifFrameInfo frameInfo;
- if (!heifDecoder->init(streamWrapper.release(), &frameInfo)) {
- return kInvalidInput;
- }
-
- // Create image info object and the codec
- SkEncodedInfo info = SkEncodedInfo::Make(
- SkEncodedInfo::kYUV_Color, SkEncodedInfo::kOpaque_Alpha, 8);
-
- Origin orientation = get_orientation(frameInfo);
-
- sk_sp<SkColorSpace> colorSpace = nullptr;
- if ((frameInfo.mIccSize > 0) && (frameInfo.mIccData != nullptr)) {
- SkColorSpace_Base::ICCTypeFlag iccType = SkColorSpace_Base::kRGB_ICCTypeFlag;
- colorSpace = SkColorSpace_Base::MakeICC(
- frameInfo.mIccData.get(), frameInfo.mIccSize, iccType);
- }
- if (!colorSpace) {
- colorSpace = SkColorSpace::MakeSRGB();
- }
-
- *codecOut = new SkHeifCodec(frameInfo.mWidth, frameInfo.mHeight,
- info, heifDecoder.release(), std::move(colorSpace), orientation);
- return kSuccess;
-}
-
-SkHeifCodec::SkHeifCodec(int width, int height, const SkEncodedInfo& info,
- HeifDecoder* heifDecoder, sk_sp<SkColorSpace> colorSpace, Origin origin)
- : INHERITED(width, height, info, SkColorSpaceXform::kRGBA_8888_ColorFormat,
- nullptr, std::move(colorSpace), origin)
- , fHeifDecoder(heifDecoder)
- , fFrameInfo(new HeifFrameInfo())
- , fSwizzleSrcRow(nullptr)
- , fColorXformSrcRow(nullptr)
- , fSwizzlerSubset(SkIRect::MakeEmpty())
-{}
-
-/*
- * Checks if the conversion between the input image and the requested output
- * image has been implemented
- * Sets the output color format
- */
-bool SkHeifCodec::setOutputColorFormat(const SkImageInfo& dstInfo) {
- if (kUnknown_SkAlphaType == dstInfo.alphaType()) {
- return false;
- }
-
- if (kOpaque_SkAlphaType != dstInfo.alphaType()) {
- SkCodecPrintf("Warning: an opaque image should be decoded as opaque "
- "- it is being decoded as non-opaque, which will draw slower\n");
- }
-
- switch (dstInfo.colorType()) {
- case kRGBA_8888_SkColorType:
- return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
-
- case kBGRA_8888_SkColorType:
- return fHeifDecoder->setOutputColor(kHeifColorFormat_BGRA_8888);
-
- case kRGB_565_SkColorType:
- if (this->colorXform()) {
- return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
- } else {
- return fHeifDecoder->setOutputColor(kHeifColorFormat_RGB565);
- }
-
- case kRGBA_F16_SkColorType:
- SkASSERT(this->colorXform());
-
- if (!dstInfo.colorSpace()->gammaIsLinear()) {
- return false;
- }
- return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888);
-
- default:
- return false;
- }
-}
-
-int SkHeifCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count,
- const Options& opts) {
- // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case,
- // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer.
- // We can never swizzle "in place" because the swizzler may perform sampling and/or
- // subsetting.
- // When fColorXformSrcRow is non-null, it means that we need to color xform and that
- // we cannot color xform "in place" (many times we can, but not when the dst is F16).
- // In this case, we will color xform from fColorXformSrcRow into the dst.
- uint8_t* decodeDst = (uint8_t*) dst;
- uint32_t* swizzleDst = (uint32_t*) dst;
- size_t decodeDstRowBytes = rowBytes;
- size_t swizzleDstRowBytes = rowBytes;
- int dstWidth = opts.fSubset ? opts.fSubset->width() : dstInfo.width();
- if (fSwizzleSrcRow && fColorXformSrcRow) {
- decodeDst = fSwizzleSrcRow;
- swizzleDst = fColorXformSrcRow;
- decodeDstRowBytes = 0;
- swizzleDstRowBytes = 0;
- dstWidth = fSwizzler->swizzleWidth();
- } else if (fColorXformSrcRow) {
- decodeDst = (uint8_t*) fColorXformSrcRow;
- swizzleDst = fColorXformSrcRow;
- decodeDstRowBytes = 0;
- swizzleDstRowBytes = 0;
- } else if (fSwizzleSrcRow) {
- decodeDst = fSwizzleSrcRow;
- decodeDstRowBytes = 0;
- dstWidth = fSwizzler->swizzleWidth();
- }
-
- for (int y = 0; y < count; y++) {
- if (!fHeifDecoder->getScanline(decodeDst)) {
- return y;
- }
-
- if (fSwizzler) {
- fSwizzler->swizzle(swizzleDst, decodeDst);
- }
-
- if (this->colorXform()) {
- this->applyColorXform(dst, swizzleDst, dstWidth, kOpaque_SkAlphaType);
- dst = SkTAddOffset<void>(dst, rowBytes);
- }
-
- decodeDst = SkTAddOffset<uint8_t>(decodeDst, decodeDstRowBytes);
- swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes);
- }
-
- return count;
-}
-
-/*
- * Performs the heif decode
- */
-SkCodec::Result SkHeifCodec::onGetPixels(const SkImageInfo& dstInfo,
- void* dst, size_t dstRowBytes,
- const Options& options,
- int* rowsDecoded) {
- if (options.fSubset) {
- // Not supporting subsets on this path for now.
- // TODO: if the heif has tiles, we can support subset here, but
- // need to retrieve tile config from metadata retriever first.
- return kUnimplemented;
- }
-
- if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
- return kInvalidConversion;
- }
-
- // Check if we can decode to the requested destination and set the output color space
- if (!this->setOutputColorFormat(dstInfo)) {
- return kInvalidConversion;
- }
-
- if (!fHeifDecoder->decode(fFrameInfo.get())) {
- return kInvalidInput;
- }
-
- this->allocateStorage(dstInfo);
-
- int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height(), options);
- if (rows < dstInfo.height()) {
- *rowsDecoded = rows;
- return kIncompleteInput;
- }
-
- return kSuccess;
-}
-
-void SkHeifCodec::allocateStorage(const SkImageInfo& dstInfo) {
- int dstWidth = dstInfo.width();
-
- size_t swizzleBytes = 0;
- if (fSwizzler) {
- swizzleBytes = fFrameInfo->mBytesPerPixel * fFrameInfo->mWidth;
- dstWidth = fSwizzler->swizzleWidth();
- SkASSERT(!this->colorXform() || SkIsAlign4(swizzleBytes));
- }
-
- size_t xformBytes = 0;
- if (this->colorXform() && (kRGBA_F16_SkColorType == dstInfo.colorType() ||
- kRGB_565_SkColorType == dstInfo.colorType())) {
- xformBytes = dstWidth * sizeof(uint32_t);
- }
-
- size_t totalBytes = swizzleBytes + xformBytes;
- fStorage.reset(totalBytes);
- if (totalBytes > 0) {
- fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr;
- fColorXformSrcRow = (xformBytes > 0) ?
- SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr;
- }
-}
-
-void SkHeifCodec::initializeSwizzler(
- const SkImageInfo& dstInfo, const Options& options) {
- SkEncodedInfo swizzlerInfo = this->getEncodedInfo();
-
- SkImageInfo swizzlerDstInfo = dstInfo;
- if (this->colorXform()) {
- // The color xform will be expecting RGBA 8888 input.
- swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType);
- }
-
- fSwizzler.reset(SkSwizzler::CreateSwizzler(swizzlerInfo, nullptr,
- swizzlerDstInfo, options, nullptr, true));
- SkASSERT(fSwizzler);
-}
-
-SkSampler* SkHeifCodec::getSampler(bool createIfNecessary) {
- if (!createIfNecessary || fSwizzler) {
- SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow));
- return fSwizzler.get();
- }
-
- this->initializeSwizzler(this->dstInfo(), this->options());
- this->allocateStorage(this->dstInfo());
- return fSwizzler.get();
-}
-
-SkCodec::Result SkHeifCodec::onStartScanlineDecode(
- const SkImageInfo& dstInfo, const Options& options) {
- if (!this->initializeColorXform(dstInfo, options.fPremulBehavior)) {
- return kInvalidConversion;
- }
-
- // Check if we can decode to the requested destination and set the output color space
- if (!this->setOutputColorFormat(dstInfo)) {
- return kInvalidConversion;
- }
-
- // TODO: For now, just decode the whole thing even when there is a subset.
- // If the heif image has tiles, we could potentially do this much faster,
- // but the tile configuration needs to be retrieved from the metadata.
- if (!fHeifDecoder->decode(fFrameInfo.get())) {
- return kInvalidInput;
- }
-
- this->allocateStorage(dstInfo);
-
- return kSuccess;
-}
-
-int SkHeifCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
- return this->readRows(this->dstInfo(), dst, dstRowBytes, count, this->options());
-}
-
-bool SkHeifCodec::onSkipScanlines(int count) {
- return count == (int) fHeifDecoder->skipScanlines(count);
-}
-
diff --git a/src/codec/SkHeifCodec.h b/src/codec/SkHeifCodec.h
deleted file mode 100644
index dab1535b6b..0000000000
--- a/src/codec/SkHeifCodec.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkHeifCodec_DEFINED
-#define SkHeifCodec_DEFINED
-
-#include "SkCodec.h"
-#include "SkColorSpace.h"
-#include "SkColorSpaceXform.h"
-#include "SkImageInfo.h"
-#include "SkSwizzler.h"
-#include "SkStream.h"
-
-struct HeifFrameInfo;
-struct HeifDecoder;
-
-/*
- *
- * This class implements the decoding for heif images.
- *
- */
-class SkHeifCodec : public SkCodec {
-public:
- static bool IsHeif(const void*, size_t);
-
- /*
- * Assumes IsHeif was called and returned true.
- * Creates a heif decoder and takes ownership of the stream.
- */
- static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
-
-protected:
-
- Result onGetPixels(
- const SkImageInfo& dstInfo,
- void* dst, size_t dstRowBytes,
- const Options& options,
- int* rowsDecoded) override;
-
- SkEncodedImageFormat onGetEncodedFormat() const override {
- return SkEncodedImageFormat::kHEIF;
- }
-
-private:
-
- /*
- * Read enough of the stream to initialize the SkHeifCodec.
- * Returns a bool representing success or failure.
- *
- * @param codecOut
- * If this returns true, and codecOut was not nullptr,
- * codecOut will be set to a new SkHeifCodec.
- *
- * @param stream
- * Deleted on failure.
- * codecOut will take ownership of it in the case where we created a codec.
- */
- static Result ReadHeader(SkStream* stream, SkCodec** codecOut);
-
- /*
- * Creates an instance of the decoder
- * Called only by NewFromStream
- */
- SkHeifCodec(int width, int height, const SkEncodedInfo&,
- HeifDecoder*, sk_sp<SkColorSpace>, Origin);
-
- /*
- * Checks if the conversion between the input image and the requested output
- * image has been implemented.
- *
- * Sets the output color format.
- */
- bool setOutputColorFormat(const SkImageInfo& dst);
-
- void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options);
- void allocateStorage(const SkImageInfo& dstInfo);
- int readRows(const SkImageInfo& dstInfo, void* dst,
- size_t rowBytes, int count, const Options&);
-
- /*
- * Scanline decoding.
- */
- SkSampler* getSampler(bool createIfNecessary) override;
- Result onStartScanlineDecode(const SkImageInfo& dstInfo,
- const Options& options) override;
- int onGetScanlines(void* dst, int count, size_t rowBytes) override;
- bool onSkipScanlines(int count) override;
-
- std::unique_ptr<HeifDecoder> fHeifDecoder;
- std::unique_ptr<HeifFrameInfo> fFrameInfo;
- SkAutoTMalloc<uint8_t> fStorage;
- uint8_t* fSwizzleSrcRow;
- uint32_t* fColorXformSrcRow;
-
- // In the case that heif decoder cannot take the exact the subset that
- // we need, we will use the swizzler to further subset the output.
- SkIRect fSwizzlerSubset;
-
- std::unique_ptr<SkSwizzler> fSwizzler;
-
- typedef SkCodec INHERITED;
-};
-
-#endif // SkHeifCodec_DEFINED
diff --git a/src/codec/SkWebpCodec.h b/src/codec/SkWebpCodec.h
index 134dafa3d5..60bff61220 100644
--- a/src/codec/SkWebpCodec.h
+++ b/src/codec/SkWebpCodec.h
@@ -23,6 +23,8 @@ extern "C" {
void WebPDemuxDelete(WebPDemuxer* dmux);
}
+static const size_t WEBP_VP8_HEADER_SIZE = 30;
+
class SkWebpCodec final : public SkCodec {
public:
// Assumes IsWebp was called and returned true.