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>
diff --git a/src/codec/SkHeifCodec.cpp b/src/codec/SkHeifCodec.cpp
index 93efc87..f3ad2a8 100644
--- a/src/codec/SkHeifCodec.cpp
+++ b/src/codec/SkHeifCodec.cpp
@@ -118,49 +118,86 @@
std::unique_ptr<SkStream> fStream;
};
-std::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(
- std::unique_ptr<SkStream> stream, Result* result) {
+#ifndef SK_LEGACY_HEIF_API
+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());
if (heifDecoder.get() == nullptr) {
*result = kInternalError;
return nullptr;
}
- HeifFrameInfo frameInfo;
- if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()),
- &frameInfo)) {
+ HeifFrameInfo heifInfo;
+ if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()), &heifInfo)) {
*result = kInvalidInput;
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;
- 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?
- 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));
}
+#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) {
// This will result in sRGB.
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));
- SkEncodedOrigin orientation = get_orientation(frameInfo);
+ SkEncodedOrigin orientation = get_orientation(heifInfo);
*result = kSuccess;
- return std::unique_ptr<SkCodec>(new SkHeifCodec(std::move(info), heifDecoder.release(),
- orientation));
+ return std::unique_ptr<SkCodec>(new SkHeifCodec(
+ 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)
, fHeifDecoder(heifDecoder)
, fSwizzleSrcRow(nullptr)
, fColorXformSrcRow(nullptr)
+#ifndef SK_LEGACY_HEIF_API
+ , fUseAnimation(useAnimation)
+#endif
{}
-
bool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
bool needsColorXform) {
SkASSERT(srcIsOpaque);
@@ -249,6 +286,79 @@
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
*/
@@ -263,9 +373,22 @@
return kUnimplemented;
}
+#ifdef SK_LEGACY_HEIF_API
if (!fHeifDecoder->decode(&fFrameInfo)) {
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);
this->allocateStorage(dstInfo);