Hook up SkHeifCodec for ImageDecoder animation
bug: 78868457 bug: 120414514 test: local test with OpenGL Rendrerer Tests animation demo and heifs files Change-Id: I09a7667a57f545927dbe9ac24c1a6b405ff0006d Reviewed-on: https://skia-review.googlesource.com/c/skia/+/232839 Commit-Queue: Leon Scroggins <scroggo@google.com> Reviewed-by: Leon Scroggins <scroggo@google.com> Reviewed-by: Derek Sollenberger <djsollen@google.com> Auto-Submit: Chong Zhang <chz@google.com>
This commit is contained in:
parent
3d77027d26
commit
6154ac4311
@ -26,3 +26,6 @@ Milestone 78
|
|||||||
|
|
||||||
* Vulkan backend now supports YCbCr sampler for I420 Vulkan images that are not
|
* Vulkan backend now supports YCbCr sampler for I420 Vulkan images that are not
|
||||||
backed by external images.
|
backed by external images.
|
||||||
|
|
||||||
|
* Add SkCodec::SelectionPolicy for distinguishing between decoding a still image
|
||||||
|
or an image sequence for a container format that has both (e.g. HEIF).
|
||||||
|
@ -111,6 +111,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
static const char* ResultToString(Result);
|
static const char* ResultToString(Result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For container formats that contain both still images and image sequences,
|
||||||
|
* instruct the decoder how the output should be selected. (Refer to comments
|
||||||
|
* for each value for more details.)
|
||||||
|
*/
|
||||||
|
enum class SelectionPolicy {
|
||||||
|
/**
|
||||||
|
* If the container format contains both still images and image sequences,
|
||||||
|
* SkCodec should choose one of the still images. This is the default.
|
||||||
|
*/
|
||||||
|
kPreferStillImage,
|
||||||
|
/**
|
||||||
|
* If the container format contains both still images and image sequences,
|
||||||
|
* SkCodec should choose one of the image sequences for animation.
|
||||||
|
*/
|
||||||
|
kPreferAnimation,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this stream represents an encoded image that we know how to decode,
|
* If this stream represents an encoded image that we know how to decode,
|
||||||
* return an SkCodec that can decode it. Otherwise return NULL.
|
* return an SkCodec that can decode it. Otherwise return NULL.
|
||||||
@ -145,8 +163,10 @@ public:
|
|||||||
* If NULL is returned, the stream is deleted immediately. Otherwise, the
|
* If NULL is returned, the stream is deleted immediately. Otherwise, the
|
||||||
* SkCodec takes ownership of it, and will delete it when done with it.
|
* SkCodec takes ownership of it, and will delete it when done with it.
|
||||||
*/
|
*/
|
||||||
static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result* = nullptr,
|
static std::unique_ptr<SkCodec> MakeFromStream(
|
||||||
SkPngChunkReader* = nullptr);
|
std::unique_ptr<SkStream>, Result* = nullptr,
|
||||||
|
SkPngChunkReader* = nullptr,
|
||||||
|
SelectionPolicy selectionPolicy = SelectionPolicy::kPreferStillImage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this data represents an encoded image that we know how to decode,
|
* If this data represents an encoded image that we know how to decode,
|
||||||
|
@ -53,9 +53,6 @@ static std::vector<DecoderProc>* decoders() {
|
|||||||
#endif
|
#endif
|
||||||
{ SkBmpCodec::IsBmp, SkBmpCodec::MakeFromStream },
|
{ SkBmpCodec::IsBmp, SkBmpCodec::MakeFromStream },
|
||||||
{ SkWbmpCodec::IsWbmp, SkWbmpCodec::MakeFromStream },
|
{ SkWbmpCodec::IsWbmp, SkWbmpCodec::MakeFromStream },
|
||||||
#ifdef SK_HAS_HEIF_LIBRARY
|
|
||||||
{ SkHeifCodec::IsHeif, SkHeifCodec::MakeFromStream },
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
return decoders;
|
return decoders;
|
||||||
}
|
}
|
||||||
@ -66,9 +63,9 @@ void SkCodec::Register(
|
|||||||
decoders()->push_back(DecoderProc{peek, make});
|
decoders()->push_back(DecoderProc{peek, make});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SkCodec> SkCodec::MakeFromStream(
|
||||||
std::unique_ptr<SkCodec> SkCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
|
std::unique_ptr<SkStream> stream, Result* outResult,
|
||||||
Result* outResult, SkPngChunkReader* chunkReader) {
|
SkPngChunkReader* chunkReader, SelectionPolicy selectionPolicy) {
|
||||||
Result resultStorage;
|
Result resultStorage;
|
||||||
if (!outResult) {
|
if (!outResult) {
|
||||||
outResult = &resultStorage;
|
outResult = &resultStorage;
|
||||||
@ -79,6 +76,12 @@ std::unique_ptr<SkCodec> SkCodec::MakeFromStream(std::unique_ptr<SkStream> strea
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selectionPolicy != SelectionPolicy::kPreferStillImage
|
||||||
|
&& selectionPolicy != SelectionPolicy::kPreferAnimation) {
|
||||||
|
*outResult = kInvalidParameters;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr size_t bytesToRead = MinBufferedBytesNeeded();
|
constexpr size_t bytesToRead = MinBufferedBytesNeeded();
|
||||||
|
|
||||||
char buffer[bytesToRead];
|
char buffer[bytesToRead];
|
||||||
@ -121,6 +124,12 @@ std::unique_ptr<SkCodec> SkCodec::MakeFromStream(std::unique_ptr<SkStream> strea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SK_HAS_HEIF_LIBRARY
|
||||||
|
if (SkHeifCodec::IsHeif(buffer, bytesRead)) {
|
||||||
|
return SkHeifCodec::MakeFromStream(std::move(stream), selectionPolicy, outResult);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SK_CODEC_DECODES_RAW
|
#ifdef SK_CODEC_DECODES_RAW
|
||||||
// Try to treat the input as RAW if all the other checks failed.
|
// Try to treat the input as RAW if all the other checks failed.
|
||||||
return SkRawCodec::MakeFromStream(std::move(stream), outResult);
|
return SkRawCodec::MakeFromStream(std::move(stream), outResult);
|
||||||
|
@ -118,49 +118,86 @@ private:
|
|||||||
std::unique_ptr<SkStream> fStream;
|
std::unique_ptr<SkStream> fStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
std::unique_ptr<SkStream> stream, Result* result) {
|
static void releaseProc(const void* ptr, void* context) {
|
||||||
|
delete reinterpret_cast<std::vector<uint8_t>*>(context);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
|
||||||
|
SkCodec::SelectionPolicy selectionPolicy, Result* result) {
|
||||||
std::unique_ptr<HeifDecoder> heifDecoder(createHeifDecoder());
|
std::unique_ptr<HeifDecoder> heifDecoder(createHeifDecoder());
|
||||||
if (heifDecoder.get() == nullptr) {
|
if (heifDecoder.get() == nullptr) {
|
||||||
*result = kInternalError;
|
*result = kInternalError;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeifFrameInfo frameInfo;
|
HeifFrameInfo heifInfo;
|
||||||
if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()),
|
if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()), &heifInfo)) {
|
||||||
&frameInfo)) {
|
|
||||||
*result = kInvalidInput;
|
*result = kInvalidInput;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
size_t frameCount = 1;
|
||||||
|
if (selectionPolicy == SkCodec::SelectionPolicy::kPreferAnimation) {
|
||||||
|
HeifFrameInfo sequenceInfo;
|
||||||
|
if (heifDecoder->getSequenceInfo(&sequenceInfo, &frameCount) &&
|
||||||
|
frameCount > 1) {
|
||||||
|
heifInfo = std::move(sequenceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<SkEncodedInfo::ICCProfile> profile = nullptr;
|
std::unique_ptr<SkEncodedInfo::ICCProfile> profile = nullptr;
|
||||||
if ((frameInfo.mIccSize > 0) && (frameInfo.mIccData != nullptr)) {
|
#ifdef SK_LEGACY_HEIF_API
|
||||||
|
if ((heifInfo.mIccSize > 0) && (heifInfo.mIccData != nullptr)) {
|
||||||
// FIXME: Would it be possible to use MakeWithoutCopy?
|
// FIXME: Would it be possible to use MakeWithoutCopy?
|
||||||
auto icc = SkData::MakeWithCopy(frameInfo.mIccData.get(), frameInfo.mIccSize);
|
auto icc = SkData::MakeWithCopy(heifInfo.mIccData.get(), heifInfo.mIccSize);
|
||||||
profile = SkEncodedInfo::ICCProfile::Make(std::move(icc));
|
profile = SkEncodedInfo::ICCProfile::Make(std::move(icc));
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (heifInfo.mIccData.size() > 0) {
|
||||||
|
auto iccData = new std::vector<uint8_t>(std::move(heifInfo.mIccData));
|
||||||
|
auto icc = SkData::MakeWithProc(iccData->data(), iccData->size(), releaseProc, iccData);
|
||||||
|
profile = SkEncodedInfo::ICCProfile::Make(std::move(icc));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (profile && profile->profile()->data_color_space != skcms_Signature_RGB) {
|
if (profile && profile->profile()->data_color_space != skcms_Signature_RGB) {
|
||||||
// This will result in sRGB.
|
// This will result in sRGB.
|
||||||
profile = nullptr;
|
profile = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkEncodedInfo info = SkEncodedInfo::Make(frameInfo.mWidth, frameInfo.mHeight,
|
SkEncodedInfo info = SkEncodedInfo::Make(heifInfo.mWidth, heifInfo.mHeight,
|
||||||
SkEncodedInfo::kYUV_Color, SkEncodedInfo::kOpaque_Alpha, 8, std::move(profile));
|
SkEncodedInfo::kYUV_Color, SkEncodedInfo::kOpaque_Alpha, 8, std::move(profile));
|
||||||
SkEncodedOrigin orientation = get_orientation(frameInfo);
|
SkEncodedOrigin orientation = get_orientation(heifInfo);
|
||||||
|
|
||||||
*result = kSuccess;
|
*result = kSuccess;
|
||||||
return std::unique_ptr<SkCodec>(new SkHeifCodec(std::move(info), heifDecoder.release(),
|
return std::unique_ptr<SkCodec>(new SkHeifCodec(
|
||||||
orientation));
|
std::move(info), heifDecoder.release(), orientation
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
, frameCount > 1
|
||||||
|
#endif
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
SkHeifCodec::SkHeifCodec(SkEncodedInfo&& info, HeifDecoder* heifDecoder, SkEncodedOrigin origin)
|
SkHeifCodec::SkHeifCodec(
|
||||||
|
SkEncodedInfo&& info,
|
||||||
|
HeifDecoder* heifDecoder,
|
||||||
|
SkEncodedOrigin origin
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
, bool useAnimation
|
||||||
|
#endif
|
||||||
|
)
|
||||||
: INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, nullptr, origin)
|
: INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, nullptr, origin)
|
||||||
, fHeifDecoder(heifDecoder)
|
, fHeifDecoder(heifDecoder)
|
||||||
, fSwizzleSrcRow(nullptr)
|
, fSwizzleSrcRow(nullptr)
|
||||||
, fColorXformSrcRow(nullptr)
|
, fColorXformSrcRow(nullptr)
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
, fUseAnimation(useAnimation)
|
||||||
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
bool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
|
bool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
|
||||||
bool needsColorXform) {
|
bool needsColorXform) {
|
||||||
SkASSERT(srcIsOpaque);
|
SkASSERT(srcIsOpaque);
|
||||||
@ -249,6 +286,79 @@ int SkHeifCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
int SkHeifCodec::onGetFrameCount() {
|
||||||
|
if (!fUseAnimation) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fFrameHolder.size() == 0) {
|
||||||
|
size_t frameCount;
|
||||||
|
HeifFrameInfo frameInfo;
|
||||||
|
if (!fHeifDecoder->getSequenceInfo(&frameInfo, &frameCount)
|
||||||
|
|| frameCount <= 1) {
|
||||||
|
fUseAnimation = false;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fFrameHolder.reserve(frameCount);
|
||||||
|
for (size_t i = 0; i < frameCount; i++) {
|
||||||
|
Frame* frame = fFrameHolder.appendNewFrame();
|
||||||
|
frame->setXYWH(0, 0, frameInfo.mWidth, frameInfo.mHeight);
|
||||||
|
frame->setDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep);
|
||||||
|
// TODO: fill in per-frame durations
|
||||||
|
// Currently we don't know the duration until the frame is actually
|
||||||
|
// decoded (onGetFrameInfo is also called before frame is decoded).
|
||||||
|
// For now, fill it base on the value reported for the sequence.
|
||||||
|
frame->setDuration(frameInfo.mDurationUs / 1000);
|
||||||
|
frame->setRequiredFrame(SkCodec::kNoFrame);
|
||||||
|
frame->setHasAlpha(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fFrameHolder.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SkFrame* SkHeifCodec::FrameHolder::onGetFrame(int i) const {
|
||||||
|
return static_cast<const SkFrame*>(this->frame(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
SkHeifCodec::Frame* SkHeifCodec::FrameHolder::appendNewFrame() {
|
||||||
|
const int i = this->size();
|
||||||
|
fFrames.emplace_back(i); // TODO: need to handle frame duration here
|
||||||
|
return &fFrames[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
const SkHeifCodec::Frame* SkHeifCodec::FrameHolder::frame(int i) const {
|
||||||
|
SkASSERT(i >= 0 && i < this->size());
|
||||||
|
return &fFrames[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SkHeifCodec::onGetFrameInfo(int i, FrameInfo* frameInfo) const {
|
||||||
|
if (i >= fFrameHolder.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Frame* frame = fFrameHolder.frame(i);
|
||||||
|
if (!frame) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameInfo) {
|
||||||
|
frameInfo->fRequiredFrame = SkCodec::kNoFrame;
|
||||||
|
frameInfo->fDuration = frame->getDuration();
|
||||||
|
frameInfo->fFullyReceived = true;
|
||||||
|
frameInfo->fAlphaType = kOpaque_SkAlphaType;
|
||||||
|
frameInfo->fDisposalMethod = SkCodecAnimation::DisposalMethod::kKeep;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkHeifCodec::onGetRepetitionCount() {
|
||||||
|
return kRepetitionCountInfinite;
|
||||||
|
}
|
||||||
|
#endif // SK_LEGACY_HEIF_API
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Performs the heif decode
|
* Performs the heif decode
|
||||||
*/
|
*/
|
||||||
@ -263,9 +373,22 @@ SkCodec::Result SkHeifCodec::onGetPixels(const SkImageInfo& dstInfo,
|
|||||||
return kUnimplemented;
|
return kUnimplemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SK_LEGACY_HEIF_API
|
||||||
if (!fHeifDecoder->decode(&fFrameInfo)) {
|
if (!fHeifDecoder->decode(&fFrameInfo)) {
|
||||||
return kInvalidInput;
|
return kInvalidInput;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
bool success;
|
||||||
|
if (fUseAnimation) {
|
||||||
|
success = fHeifDecoder->decodeSequence(options.fFrameIndex, &fFrameInfo);
|
||||||
|
} else {
|
||||||
|
success = fHeifDecoder->decode(&fFrameInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
return kInvalidInput;
|
||||||
|
}
|
||||||
|
#endif // SK_LEGACY_HEIF_API
|
||||||
|
|
||||||
fSwizzler.reset(nullptr);
|
fSwizzler.reset(nullptr);
|
||||||
this->allocateStorage(dstInfo);
|
this->allocateStorage(dstInfo);
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "include/codec/SkEncodedOrigin.h"
|
#include "include/codec/SkEncodedOrigin.h"
|
||||||
#include "include/core/SkImageInfo.h"
|
#include "include/core/SkImageInfo.h"
|
||||||
#include "include/core/SkStream.h"
|
#include "include/core/SkStream.h"
|
||||||
|
#include "src/codec/SkFrameHolder.h"
|
||||||
#include "src/codec/SkSwizzler.h"
|
#include "src/codec/SkSwizzler.h"
|
||||||
|
|
||||||
#if __has_include("HeifDecoderAPI.h")
|
#if __has_include("HeifDecoderAPI.h")
|
||||||
@ -27,7 +28,8 @@ public:
|
|||||||
/*
|
/*
|
||||||
* Assumes IsHeif was called and returned true.
|
* Assumes IsHeif was called and returned true.
|
||||||
*/
|
*/
|
||||||
static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
|
static std::unique_ptr<SkCodec> MakeFromStream(
|
||||||
|
std::unique_ptr<SkStream>, SkCodec::SelectionPolicy selectionPolicy, Result*);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -41,6 +43,15 @@ protected:
|
|||||||
return SkEncodedImageFormat::kHEIF;
|
return SkEncodedImageFormat::kHEIF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
int onGetFrameCount() override;
|
||||||
|
bool onGetFrameInfo(int, FrameInfo*) const override;
|
||||||
|
int onGetRepetitionCount() override;
|
||||||
|
const SkFrameHolder* getFrameHolder() const override {
|
||||||
|
return &fFrameHolder;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool conversionSupported(const SkImageInfo&, bool, bool) override;
|
bool conversionSupported(const SkImageInfo&, bool, bool) override;
|
||||||
|
|
||||||
bool onRewind() override;
|
bool onRewind() override;
|
||||||
@ -50,7 +61,11 @@ private:
|
|||||||
* Creates an instance of the decoder
|
* Creates an instance of the decoder
|
||||||
* Called only by NewFromStream
|
* Called only by NewFromStream
|
||||||
*/
|
*/
|
||||||
SkHeifCodec(SkEncodedInfo&&, HeifDecoder*, SkEncodedOrigin);
|
SkHeifCodec(SkEncodedInfo&&, HeifDecoder*, SkEncodedOrigin
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
, bool animation
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options);
|
void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options);
|
||||||
void allocateStorage(const SkImageInfo& dstInfo);
|
void allocateStorage(const SkImageInfo& dstInfo);
|
||||||
@ -73,7 +88,47 @@ private:
|
|||||||
uint32_t* fColorXformSrcRow;
|
uint32_t* fColorXformSrcRow;
|
||||||
|
|
||||||
std::unique_ptr<SkSwizzler> fSwizzler;
|
std::unique_ptr<SkSwizzler> fSwizzler;
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
bool fUseAnimation;
|
||||||
|
|
||||||
|
class Frame : public SkFrame {
|
||||||
|
public:
|
||||||
|
Frame(int i) : INHERITED(i) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SkEncodedInfo::Alpha onReportedAlpha() const override {
|
||||||
|
return SkEncodedInfo::Alpha::kOpaque_Alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef SkFrame INHERITED;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FrameHolder : public SkFrameHolder {
|
||||||
|
public:
|
||||||
|
~FrameHolder() override {}
|
||||||
|
void setScreenSize(int w, int h) {
|
||||||
|
fScreenWidth = w;
|
||||||
|
fScreenHeight = h;
|
||||||
|
}
|
||||||
|
Frame* appendNewFrame();
|
||||||
|
const Frame* frame(int i) const;
|
||||||
|
int size() const {
|
||||||
|
return static_cast<int>(fFrames.size());
|
||||||
|
}
|
||||||
|
void reserve(int size) {
|
||||||
|
fFrames.reserve(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const SkFrame* onGetFrame(int i) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Frame> fFrames;
|
||||||
|
};
|
||||||
|
|
||||||
|
FrameHolder fFrameHolder;
|
||||||
|
#endif // SK_LEGACY_HEIF_API
|
||||||
typedef SkCodec INHERITED;
|
typedef SkCodec INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ struct HeifStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct HeifFrameInfo {
|
struct HeifFrameInfo {
|
||||||
|
#ifdef SK_LEGACY_HEIF_API
|
||||||
int mRotationAngle;
|
int mRotationAngle;
|
||||||
int mWidth;
|
int mWidth;
|
||||||
int mHeight;
|
int mHeight;
|
||||||
@ -39,6 +40,14 @@ struct HeifFrameInfo {
|
|||||||
|
|
||||||
size_t mIccSize;
|
size_t mIccSize;
|
||||||
std::unique_ptr<char[]> mIccData;
|
std::unique_ptr<char[]> mIccData;
|
||||||
|
#else
|
||||||
|
uint32_t mWidth;
|
||||||
|
uint32_t mHeight;
|
||||||
|
int32_t mRotationAngle; // Rotation angle, clockwise, should be multiple of 90
|
||||||
|
uint32_t mBytesPerPixel; // Number of bytes for one pixel
|
||||||
|
int64_t mDurationUs; // Duration of the frame in us
|
||||||
|
std::vector<uint8_t> mIccData; // ICC data array
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HeifDecoder {
|
struct HeifDecoder {
|
||||||
@ -47,10 +56,22 @@ struct HeifDecoder {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
bool getSequenceInfo(HeifFrameInfo* frameInfo, size_t *frameCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool decode(HeifFrameInfo*) {
|
bool decode(HeifFrameInfo*) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SK_LEGACY_HEIF_API
|
||||||
|
bool decodeSequence(int frameIndex, HeifFrameInfo* frameInfo) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool setOutputColor(HeifColorFormat) {
|
bool setOutputColor(HeifColorFormat) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user