1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#ifdef SK_HAS_HEIF_LIBRARY 11cb93a386Sopenharmony_ci#include "include/codec/SkCodec.h" 12cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 13cb93a386Sopenharmony_ci#include "include/private/SkColorData.h" 14cb93a386Sopenharmony_ci#include "src/codec/SkCodecPriv.h" 15cb93a386Sopenharmony_ci#include "src/codec/SkHeifCodec.h" 16cb93a386Sopenharmony_ci#include "src/core/SkEndian.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) 19cb93a386Sopenharmony_ci#include <dlfcn.h> 20cb93a386Sopenharmony_ci#endif 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci#define FOURCC(c1, c2, c3, c4) \ 23cb93a386Sopenharmony_ci ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4)) 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ciconst static char *HEIF_IMPL_SO_NAME = "libheifimpl.z.so"; 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_cibool SkHeifCodec::IsSupported(const void* buffer, size_t bytesRead, 28cb93a386Sopenharmony_ci SkEncodedImageFormat* format) { 29cb93a386Sopenharmony_ci // Parse the ftyp box up to bytesRead to determine if this is HEIF or AVIF. 30cb93a386Sopenharmony_ci // Any valid ftyp box should have at least 8 bytes. 31cb93a386Sopenharmony_ci if (bytesRead < 8) { 32cb93a386Sopenharmony_ci return false; 33cb93a386Sopenharmony_ci } 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci uint32_t* ptr = (uint32_t*)buffer; 36cb93a386Sopenharmony_ci uint64_t chunkSize = SkEndian_SwapBE32(ptr[0]); 37cb93a386Sopenharmony_ci uint32_t chunkType = SkEndian_SwapBE32(ptr[1]); 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci if (chunkType != FOURCC('f', 't', 'y', 'p')) { 40cb93a386Sopenharmony_ci return false; 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci int64_t offset = 8; 44cb93a386Sopenharmony_ci if (chunkSize == 1) { 45cb93a386Sopenharmony_ci // This indicates that the next 8 bytes represent the chunk size, 46cb93a386Sopenharmony_ci // and chunk data comes after that. 47cb93a386Sopenharmony_ci if (bytesRead < 16) { 48cb93a386Sopenharmony_ci return false; 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci auto* chunkSizePtr = SkTAddOffset<const uint64_t>(buffer, offset); 51cb93a386Sopenharmony_ci chunkSize = SkEndian_SwapBE64(*chunkSizePtr); 52cb93a386Sopenharmony_ci if (chunkSize < 16) { 53cb93a386Sopenharmony_ci // The smallest valid chunk is 16 bytes long in this case. 54cb93a386Sopenharmony_ci return false; 55cb93a386Sopenharmony_ci } 56cb93a386Sopenharmony_ci offset += 8; 57cb93a386Sopenharmony_ci } else if (chunkSize < 8) { 58cb93a386Sopenharmony_ci // The smallest valid chunk is 8 bytes long. 59cb93a386Sopenharmony_ci return false; 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci if (chunkSize > bytesRead) { 63cb93a386Sopenharmony_ci chunkSize = bytesRead; 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci int64_t chunkDataSize = chunkSize - offset; 66cb93a386Sopenharmony_ci // It should at least have major brand (4-byte) and minor version (4-bytes). 67cb93a386Sopenharmony_ci // The rest of the chunk (if any) is a list of (4-byte) compatible brands. 68cb93a386Sopenharmony_ci if (chunkDataSize < 8) { 69cb93a386Sopenharmony_ci return false; 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4; 73cb93a386Sopenharmony_ci bool isHeif = false; 74cb93a386Sopenharmony_ci for (size_t i = 0; i < numCompatibleBrands + 2; ++i) { 75cb93a386Sopenharmony_ci if (i == 1) { 76cb93a386Sopenharmony_ci // Skip this index, it refers to the minorVersion, 77cb93a386Sopenharmony_ci // not a brand. 78cb93a386Sopenharmony_ci continue; 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci auto* brandPtr = SkTAddOffset<const uint32_t>(buffer, offset + 4 * i); 81cb93a386Sopenharmony_ci uint32_t brand = SkEndian_SwapBE32(*brandPtr); 82cb93a386Sopenharmony_ci if (brand == FOURCC('m', 'i', 'f', '1') || brand == FOURCC('h', 'e', 'i', 'c') 83cb93a386Sopenharmony_ci || brand == FOURCC('m', 's', 'f', '1') || brand == FOURCC('h', 'e', 'v', 'c') 84cb93a386Sopenharmony_ci || brand == FOURCC('a', 'v', 'i', 'f') || brand == FOURCC('a', 'v', 'i', 's')) { 85cb93a386Sopenharmony_ci // AVIF files could have "mif1" as the major brand. So we cannot 86cb93a386Sopenharmony_ci // distinguish whether the image is AVIF or HEIC just based on the 87cb93a386Sopenharmony_ci // "mif1" brand. So wait until we see a specific avif brand to 88cb93a386Sopenharmony_ci // determine whether it is AVIF or HEIC. 89cb93a386Sopenharmony_ci isHeif = true; 90cb93a386Sopenharmony_ci if (brand == FOURCC('a', 'v', 'i', 'f') 91cb93a386Sopenharmony_ci || brand == FOURCC('a', 'v', 'i', 's')) { 92cb93a386Sopenharmony_ci if (format != nullptr) { 93cb93a386Sopenharmony_ci *format = SkEncodedImageFormat::kAVIF; 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci return true; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci if (isHeif) { 100cb93a386Sopenharmony_ci if (format != nullptr) { 101cb93a386Sopenharmony_ci *format = SkEncodedImageFormat::kHEIF; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci return true; 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci return false; 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_cistatic SkEncodedOrigin get_orientation(const HeifFrameInfo& frameInfo) { 109cb93a386Sopenharmony_ci switch (frameInfo.mRotationAngle) { 110cb93a386Sopenharmony_ci case 0: return kTopLeft_SkEncodedOrigin; 111cb93a386Sopenharmony_ci case 90: return kRightTop_SkEncodedOrigin; 112cb93a386Sopenharmony_ci case 180: return kBottomRight_SkEncodedOrigin; 113cb93a386Sopenharmony_ci case 270: return kLeftBottom_SkEncodedOrigin; 114cb93a386Sopenharmony_ci } 115cb93a386Sopenharmony_ci return kDefault_SkEncodedOrigin; 116cb93a386Sopenharmony_ci} 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_cistruct SkHeifStreamWrapper : public HeifStream { 119cb93a386Sopenharmony_ci SkHeifStreamWrapper(SkStream* stream) : fStream(stream) {} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci ~SkHeifStreamWrapper() override {} 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci size_t read(void* buffer, size_t size) override { 124cb93a386Sopenharmony_ci return fStream->read(buffer, size); 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci bool rewind() override { 128cb93a386Sopenharmony_ci return fStream->rewind(); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci bool seek(size_t position) override { 132cb93a386Sopenharmony_ci return fStream->seek(position); 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci bool hasLength() const override { 136cb93a386Sopenharmony_ci return fStream->hasLength(); 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci size_t getLength() const override { 140cb93a386Sopenharmony_ci return fStream->getLength(); 141cb93a386Sopenharmony_ci } 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci bool hasPosition() const override { 144cb93a386Sopenharmony_ci return fStream->hasPosition(); 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci size_t getPosition() const override { 148cb93a386Sopenharmony_ci return fStream->getPosition(); 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ciprivate: 152cb93a386Sopenharmony_ci std::unique_ptr<SkStream> fStream; 153cb93a386Sopenharmony_ci}; 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_cistatic void releaseProc(const void* ptr, void* context) { 156cb93a386Sopenharmony_ci delete reinterpret_cast<std::vector<uint8_t>*>(context); 157cb93a386Sopenharmony_ci} 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_cistd::unique_ptr<SkCodec> SkHeifCodec::MakeFromStream(std::unique_ptr<SkStream> stream, 160cb93a386Sopenharmony_ci SkCodec::SelectionPolicy selectionPolicy, SkEncodedImageFormat format, Result* result) { 161cb93a386Sopenharmony_ci std::unique_ptr<HeifDecoder> heifDecoder(createHeifDecoder()); 162cb93a386Sopenharmony_ci if (heifDecoder == nullptr) { 163cb93a386Sopenharmony_ci *result = kInternalError; 164cb93a386Sopenharmony_ci return nullptr; 165cb93a386Sopenharmony_ci } 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ci HeifFrameInfo heifInfo; 168cb93a386Sopenharmony_ci if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()), &heifInfo)) { 169cb93a386Sopenharmony_ci *result = kInvalidInput; 170cb93a386Sopenharmony_ci return nullptr; 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci 173cb93a386Sopenharmony_ci size_t frameCount = 1; 174cb93a386Sopenharmony_ci if (selectionPolicy == SkCodec::SelectionPolicy::kPreferAnimation) { 175cb93a386Sopenharmony_ci HeifFrameInfo sequenceInfo; 176cb93a386Sopenharmony_ci if (heifDecoder->getSequenceInfo(&sequenceInfo, &frameCount) && 177cb93a386Sopenharmony_ci frameCount > 1) { 178cb93a386Sopenharmony_ci heifInfo = std::move(sequenceInfo); 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci std::unique_ptr<SkEncodedInfo::ICCProfile> profile = nullptr; 183cb93a386Sopenharmony_ci if (heifInfo.mIccData.size() > 0) { 184cb93a386Sopenharmony_ci auto iccData = new std::vector<uint8_t>(std::move(heifInfo.mIccData)); 185cb93a386Sopenharmony_ci auto icc = SkData::MakeWithProc(iccData->data(), iccData->size(), releaseProc, iccData); 186cb93a386Sopenharmony_ci profile = SkEncodedInfo::ICCProfile::Make(std::move(icc)); 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci if (profile && profile->profile()->data_color_space != skcms_Signature_RGB) { 189cb93a386Sopenharmony_ci // This will result in sRGB. 190cb93a386Sopenharmony_ci profile = nullptr; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci SkEncodedInfo info = SkEncodedInfo::Make(heifInfo.mWidth, heifInfo.mHeight, 194cb93a386Sopenharmony_ci SkEncodedInfo::kYUV_Color, SkEncodedInfo::kOpaque_Alpha, 8, std::move(profile)); 195cb93a386Sopenharmony_ci SkEncodedOrigin orientation = get_orientation(heifInfo); 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci *result = kSuccess; 198cb93a386Sopenharmony_ci return std::unique_ptr<SkCodec>(new SkHeifCodec( 199cb93a386Sopenharmony_ci std::move(info), heifDecoder.release(), orientation, frameCount > 1, format)); 200cb93a386Sopenharmony_ci} 201cb93a386Sopenharmony_ci 202cb93a386Sopenharmony_ciSkHeifCodec::SkHeifCodec( 203cb93a386Sopenharmony_ci SkEncodedInfo&& info, 204cb93a386Sopenharmony_ci HeifDecoder* heifDecoder, 205cb93a386Sopenharmony_ci SkEncodedOrigin origin, 206cb93a386Sopenharmony_ci bool useAnimation, 207cb93a386Sopenharmony_ci SkEncodedImageFormat format) 208cb93a386Sopenharmony_ci : INHERITED(std::move(info), skcms_PixelFormat_RGBA_8888, nullptr, origin) 209cb93a386Sopenharmony_ci , fHeifDecoder(heifDecoder) 210cb93a386Sopenharmony_ci , fSwizzleSrcRow(nullptr) 211cb93a386Sopenharmony_ci , fColorXformSrcRow(nullptr) 212cb93a386Sopenharmony_ci , fUseAnimation(useAnimation) 213cb93a386Sopenharmony_ci , fFormat(format) 214cb93a386Sopenharmony_ci{} 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_cibool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque, 217cb93a386Sopenharmony_ci bool needsColorXform) { 218cb93a386Sopenharmony_ci SkASSERT(srcIsOpaque); 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci if (kUnknown_SkAlphaType == dstInfo.alphaType()) { 221cb93a386Sopenharmony_ci return false; 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci if (kOpaque_SkAlphaType != dstInfo.alphaType()) { 225cb93a386Sopenharmony_ci SkCodecPrintf("Warning: an opaque image should be decoded as opaque " 226cb93a386Sopenharmony_ci "- it is being decoded as non-opaque, which will draw slower\n"); 227cb93a386Sopenharmony_ci } 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ci switch (dstInfo.colorType()) { 230cb93a386Sopenharmony_ci case kRGBA_8888_SkColorType: 231cb93a386Sopenharmony_ci return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ci case kBGRA_8888_SkColorType: 234cb93a386Sopenharmony_ci return fHeifDecoder->setOutputColor(kHeifColorFormat_BGRA_8888); 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci case kRGB_565_SkColorType: 237cb93a386Sopenharmony_ci if (needsColorXform) { 238cb93a386Sopenharmony_ci return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); 239cb93a386Sopenharmony_ci } else { 240cb93a386Sopenharmony_ci return fHeifDecoder->setOutputColor(kHeifColorFormat_RGB565); 241cb93a386Sopenharmony_ci } 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci case kRGBA_F16_SkColorType: 244cb93a386Sopenharmony_ci SkASSERT(needsColorXform); 245cb93a386Sopenharmony_ci return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci default: 248cb93a386Sopenharmony_ci return false; 249cb93a386Sopenharmony_ci } 250cb93a386Sopenharmony_ci} 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ciint SkHeifCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count, 253cb93a386Sopenharmony_ci const Options& opts) { 254cb93a386Sopenharmony_ci // When fSwizzleSrcRow is non-null, it means that we need to swizzle. In this case, 255cb93a386Sopenharmony_ci // we will always decode into fSwizzlerSrcRow before swizzling into the next buffer. 256cb93a386Sopenharmony_ci // We can never swizzle "in place" because the swizzler may perform sampling and/or 257cb93a386Sopenharmony_ci // subsetting. 258cb93a386Sopenharmony_ci // When fColorXformSrcRow is non-null, it means that we need to color xform and that 259cb93a386Sopenharmony_ci // we cannot color xform "in place" (many times we can, but not when the dst is F16). 260cb93a386Sopenharmony_ci // In this case, we will color xform from fColorXformSrcRow into the dst. 261cb93a386Sopenharmony_ci uint8_t* decodeDst = (uint8_t*) dst; 262cb93a386Sopenharmony_ci uint32_t* swizzleDst = (uint32_t*) dst; 263cb93a386Sopenharmony_ci size_t decodeDstRowBytes = rowBytes; 264cb93a386Sopenharmony_ci size_t swizzleDstRowBytes = rowBytes; 265cb93a386Sopenharmony_ci int dstWidth = opts.fSubset ? opts.fSubset->width() : dstInfo.width(); 266cb93a386Sopenharmony_ci if (fSwizzleSrcRow && fColorXformSrcRow) { 267cb93a386Sopenharmony_ci decodeDst = fSwizzleSrcRow; 268cb93a386Sopenharmony_ci swizzleDst = fColorXformSrcRow; 269cb93a386Sopenharmony_ci decodeDstRowBytes = 0; 270cb93a386Sopenharmony_ci swizzleDstRowBytes = 0; 271cb93a386Sopenharmony_ci dstWidth = fSwizzler->swizzleWidth(); 272cb93a386Sopenharmony_ci } else if (fColorXformSrcRow) { 273cb93a386Sopenharmony_ci decodeDst = (uint8_t*) fColorXformSrcRow; 274cb93a386Sopenharmony_ci swizzleDst = fColorXformSrcRow; 275cb93a386Sopenharmony_ci decodeDstRowBytes = 0; 276cb93a386Sopenharmony_ci swizzleDstRowBytes = 0; 277cb93a386Sopenharmony_ci } else if (fSwizzleSrcRow) { 278cb93a386Sopenharmony_ci decodeDst = fSwizzleSrcRow; 279cb93a386Sopenharmony_ci decodeDstRowBytes = 0; 280cb93a386Sopenharmony_ci dstWidth = fSwizzler->swizzleWidth(); 281cb93a386Sopenharmony_ci } 282cb93a386Sopenharmony_ci 283cb93a386Sopenharmony_ci for (int y = 0; y < count; y++) { 284cb93a386Sopenharmony_ci if (!fHeifDecoder->getScanline(decodeDst)) { 285cb93a386Sopenharmony_ci return y; 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci 288cb93a386Sopenharmony_ci if (fSwizzler) { 289cb93a386Sopenharmony_ci fSwizzler->swizzle(swizzleDst, decodeDst); 290cb93a386Sopenharmony_ci } 291cb93a386Sopenharmony_ci 292cb93a386Sopenharmony_ci if (this->colorXform()) { 293cb93a386Sopenharmony_ci this->applyColorXform(dst, swizzleDst, dstWidth); 294cb93a386Sopenharmony_ci dst = SkTAddOffset<void>(dst, rowBytes); 295cb93a386Sopenharmony_ci } 296cb93a386Sopenharmony_ci 297cb93a386Sopenharmony_ci decodeDst = SkTAddOffset<uint8_t>(decodeDst, decodeDstRowBytes); 298cb93a386Sopenharmony_ci swizzleDst = SkTAddOffset<uint32_t>(swizzleDst, swizzleDstRowBytes); 299cb93a386Sopenharmony_ci } 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_ci return count; 302cb93a386Sopenharmony_ci} 303cb93a386Sopenharmony_ci 304cb93a386Sopenharmony_ciint SkHeifCodec::onGetFrameCount() { 305cb93a386Sopenharmony_ci if (!fUseAnimation) { 306cb93a386Sopenharmony_ci return 1; 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci 309cb93a386Sopenharmony_ci if (fFrameHolder.size() == 0) { 310cb93a386Sopenharmony_ci size_t frameCount; 311cb93a386Sopenharmony_ci HeifFrameInfo frameInfo; 312cb93a386Sopenharmony_ci if (!fHeifDecoder->getSequenceInfo(&frameInfo, &frameCount) 313cb93a386Sopenharmony_ci || frameCount <= 1) { 314cb93a386Sopenharmony_ci fUseAnimation = false; 315cb93a386Sopenharmony_ci return 1; 316cb93a386Sopenharmony_ci } 317cb93a386Sopenharmony_ci fFrameHolder.reserve(frameCount); 318cb93a386Sopenharmony_ci for (size_t i = 0; i < frameCount; i++) { 319cb93a386Sopenharmony_ci Frame* frame = fFrameHolder.appendNewFrame(); 320cb93a386Sopenharmony_ci frame->setXYWH(0, 0, frameInfo.mWidth, frameInfo.mHeight); 321cb93a386Sopenharmony_ci frame->setDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep); 322cb93a386Sopenharmony_ci // Currently we don't know the duration until the frame is actually 323cb93a386Sopenharmony_ci // decoded (onGetFrameInfo is also called before frame is decoded). 324cb93a386Sopenharmony_ci // For now, fill it base on the value reported for the sequence. 325cb93a386Sopenharmony_ci frame->setDuration(frameInfo.mDurationUs / 1000); 326cb93a386Sopenharmony_ci frame->setRequiredFrame(SkCodec::kNoFrame); 327cb93a386Sopenharmony_ci frame->setHasAlpha(false); 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci } 330cb93a386Sopenharmony_ci 331cb93a386Sopenharmony_ci return fFrameHolder.size(); 332cb93a386Sopenharmony_ci} 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_ciconst SkFrame* SkHeifCodec::FrameHolder::onGetFrame(int i) const { 335cb93a386Sopenharmony_ci return static_cast<const SkFrame*>(this->frame(i)); 336cb93a386Sopenharmony_ci} 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ciSkHeifCodec::Frame* SkHeifCodec::FrameHolder::appendNewFrame() { 339cb93a386Sopenharmony_ci const int i = this->size(); 340cb93a386Sopenharmony_ci fFrames.emplace_back(i); // TODO: need to handle frame duration here 341cb93a386Sopenharmony_ci return &fFrames[i]; 342cb93a386Sopenharmony_ci} 343cb93a386Sopenharmony_ci 344cb93a386Sopenharmony_ciconst SkHeifCodec::Frame* SkHeifCodec::FrameHolder::frame(int i) const { 345cb93a386Sopenharmony_ci SkASSERT(i >= 0 && i < this->size()); 346cb93a386Sopenharmony_ci return &fFrames[i]; 347cb93a386Sopenharmony_ci} 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_ciSkHeifCodec::Frame* SkHeifCodec::FrameHolder::editFrameAt(int i) { 350cb93a386Sopenharmony_ci SkASSERT(i >= 0 && i < this->size()); 351cb93a386Sopenharmony_ci return &fFrames[i]; 352cb93a386Sopenharmony_ci} 353cb93a386Sopenharmony_ci 354cb93a386Sopenharmony_cibool SkHeifCodec::onGetFrameInfo(int i, FrameInfo* frameInfo) const { 355cb93a386Sopenharmony_ci if (i >= fFrameHolder.size()) { 356cb93a386Sopenharmony_ci return false; 357cb93a386Sopenharmony_ci } 358cb93a386Sopenharmony_ci 359cb93a386Sopenharmony_ci const Frame* frame = fFrameHolder.frame(i); 360cb93a386Sopenharmony_ci if (!frame) { 361cb93a386Sopenharmony_ci return false; 362cb93a386Sopenharmony_ci } 363cb93a386Sopenharmony_ci 364cb93a386Sopenharmony_ci if (frameInfo) { 365cb93a386Sopenharmony_ci frame->fillIn(frameInfo, true); 366cb93a386Sopenharmony_ci } 367cb93a386Sopenharmony_ci 368cb93a386Sopenharmony_ci return true; 369cb93a386Sopenharmony_ci} 370cb93a386Sopenharmony_ci 371cb93a386Sopenharmony_ciint SkHeifCodec::onGetRepetitionCount() { 372cb93a386Sopenharmony_ci return kRepetitionCountInfinite; 373cb93a386Sopenharmony_ci} 374cb93a386Sopenharmony_ci 375cb93a386Sopenharmony_ci/* 376cb93a386Sopenharmony_ci * Performs the heif decode 377cb93a386Sopenharmony_ci */ 378cb93a386Sopenharmony_ciSkCodec::Result SkHeifCodec::onGetPixels(const SkImageInfo& dstInfo, 379cb93a386Sopenharmony_ci void* dst, size_t dstRowBytes, 380cb93a386Sopenharmony_ci const Options& options, 381cb93a386Sopenharmony_ci int* rowsDecoded) { 382cb93a386Sopenharmony_ci if (options.fSubset) { 383cb93a386Sopenharmony_ci // Not supporting subsets on this path for now. 384cb93a386Sopenharmony_ci // TODO: if the heif has tiles, we can support subset here, but 385cb93a386Sopenharmony_ci // need to retrieve tile config from metadata retriever first. 386cb93a386Sopenharmony_ci return kUnimplemented; 387cb93a386Sopenharmony_ci } 388cb93a386Sopenharmony_ci 389cb93a386Sopenharmony_ci bool success; 390cb93a386Sopenharmony_ci if (fUseAnimation) { 391cb93a386Sopenharmony_ci success = fHeifDecoder->decodeSequence(options.fFrameIndex, &fFrameInfo); 392cb93a386Sopenharmony_ci fFrameHolder.editFrameAt(options.fFrameIndex)->setDuration( 393cb93a386Sopenharmony_ci fFrameInfo.mDurationUs / 1000); 394cb93a386Sopenharmony_ci } else { 395cb93a386Sopenharmony_ci fHeifDecoder->setDstBuffer((uint8_t *)dst, dstRowBytes, nullptr); 396cb93a386Sopenharmony_ci success = fHeifDecoder->decode(&fFrameInfo); 397cb93a386Sopenharmony_ci } 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_ci if (!success) { 400cb93a386Sopenharmony_ci return kInvalidInput; 401cb93a386Sopenharmony_ci } 402cb93a386Sopenharmony_ci 403cb93a386Sopenharmony_ci fSwizzler.reset(nullptr); 404cb93a386Sopenharmony_ci this->allocateStorage(dstInfo); 405cb93a386Sopenharmony_ci 406cb93a386Sopenharmony_ci int rows = this->readRows(dstInfo, dst, dstRowBytes, dstInfo.height(), options); 407cb93a386Sopenharmony_ci if (rows < dstInfo.height()) { 408cb93a386Sopenharmony_ci *rowsDecoded = rows; 409cb93a386Sopenharmony_ci return kIncompleteInput; 410cb93a386Sopenharmony_ci } 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_ci return kSuccess; 413cb93a386Sopenharmony_ci} 414cb93a386Sopenharmony_ci 415cb93a386Sopenharmony_civoid SkHeifCodec::allocateStorage(const SkImageInfo& dstInfo) { 416cb93a386Sopenharmony_ci int dstWidth = dstInfo.width(); 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci size_t swizzleBytes = 0; 419cb93a386Sopenharmony_ci if (fSwizzler) { 420cb93a386Sopenharmony_ci swizzleBytes = fFrameInfo.mBytesPerPixel * fFrameInfo.mWidth; 421cb93a386Sopenharmony_ci dstWidth = fSwizzler->swizzleWidth(); 422cb93a386Sopenharmony_ci SkASSERT(!this->colorXform() || SkIsAlign4(swizzleBytes)); 423cb93a386Sopenharmony_ci } 424cb93a386Sopenharmony_ci 425cb93a386Sopenharmony_ci size_t xformBytes = 0; 426cb93a386Sopenharmony_ci if (this->colorXform() && (kRGBA_F16_SkColorType == dstInfo.colorType() || 427cb93a386Sopenharmony_ci kRGB_565_SkColorType == dstInfo.colorType())) { 428cb93a386Sopenharmony_ci xformBytes = dstWidth * sizeof(uint32_t); 429cb93a386Sopenharmony_ci } 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ci size_t totalBytes = swizzleBytes + xformBytes; 432cb93a386Sopenharmony_ci fStorage.reset(totalBytes); 433cb93a386Sopenharmony_ci if (totalBytes > 0) { 434cb93a386Sopenharmony_ci fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr; 435cb93a386Sopenharmony_ci fColorXformSrcRow = (xformBytes > 0) ? 436cb93a386Sopenharmony_ci SkTAddOffset<uint32_t>(fStorage.get(), swizzleBytes) : nullptr; 437cb93a386Sopenharmony_ci } 438cb93a386Sopenharmony_ci} 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_civoid SkHeifCodec::initializeSwizzler( 441cb93a386Sopenharmony_ci const SkImageInfo& dstInfo, const Options& options) { 442cb93a386Sopenharmony_ci SkImageInfo swizzlerDstInfo = dstInfo; 443cb93a386Sopenharmony_ci if (this->colorXform()) { 444cb93a386Sopenharmony_ci // The color xform will be expecting RGBA 8888 input. 445cb93a386Sopenharmony_ci swizzlerDstInfo = swizzlerDstInfo.makeColorType(kRGBA_8888_SkColorType); 446cb93a386Sopenharmony_ci } 447cb93a386Sopenharmony_ci 448cb93a386Sopenharmony_ci int srcBPP = 4; 449cb93a386Sopenharmony_ci if (dstInfo.colorType() == kRGB_565_SkColorType && !this->colorXform()) { 450cb93a386Sopenharmony_ci srcBPP = 2; 451cb93a386Sopenharmony_ci } 452cb93a386Sopenharmony_ci 453cb93a386Sopenharmony_ci fSwizzler = SkSwizzler::MakeSimple(srcBPP, swizzlerDstInfo, options); 454cb93a386Sopenharmony_ci SkASSERT(fSwizzler); 455cb93a386Sopenharmony_ci} 456cb93a386Sopenharmony_ci 457cb93a386Sopenharmony_ciSkSampler* SkHeifCodec::getSampler(bool createIfNecessary) { 458cb93a386Sopenharmony_ci if (!createIfNecessary || fSwizzler) { 459cb93a386Sopenharmony_ci SkASSERT(!fSwizzler || (fSwizzleSrcRow && fStorage.get() == fSwizzleSrcRow)); 460cb93a386Sopenharmony_ci return fSwizzler.get(); 461cb93a386Sopenharmony_ci } 462cb93a386Sopenharmony_ci 463cb93a386Sopenharmony_ci this->initializeSwizzler(this->dstInfo(), this->options()); 464cb93a386Sopenharmony_ci this->allocateStorage(this->dstInfo()); 465cb93a386Sopenharmony_ci return fSwizzler.get(); 466cb93a386Sopenharmony_ci} 467cb93a386Sopenharmony_ci 468cb93a386Sopenharmony_cibool SkHeifCodec::onRewind() { 469cb93a386Sopenharmony_ci fSwizzler.reset(nullptr); 470cb93a386Sopenharmony_ci fSwizzleSrcRow = nullptr; 471cb93a386Sopenharmony_ci fColorXformSrcRow = nullptr; 472cb93a386Sopenharmony_ci fStorage.reset(); 473cb93a386Sopenharmony_ci 474cb93a386Sopenharmony_ci return true; 475cb93a386Sopenharmony_ci} 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ciSkCodec::Result SkHeifCodec::onStartScanlineDecode( 478cb93a386Sopenharmony_ci const SkImageInfo& dstInfo, const Options& options) { 479cb93a386Sopenharmony_ci // TODO: For now, just decode the whole thing even when there is a subset. 480cb93a386Sopenharmony_ci // If the heif image has tiles, we could potentially do this much faster, 481cb93a386Sopenharmony_ci // but the tile configuration needs to be retrieved from the metadata. 482cb93a386Sopenharmony_ci if (!fHeifDecoder->decode(&fFrameInfo)) { 483cb93a386Sopenharmony_ci return kInvalidInput; 484cb93a386Sopenharmony_ci } 485cb93a386Sopenharmony_ci 486cb93a386Sopenharmony_ci if (options.fSubset) { 487cb93a386Sopenharmony_ci this->initializeSwizzler(dstInfo, options); 488cb93a386Sopenharmony_ci } else { 489cb93a386Sopenharmony_ci fSwizzler.reset(nullptr); 490cb93a386Sopenharmony_ci } 491cb93a386Sopenharmony_ci 492cb93a386Sopenharmony_ci this->allocateStorage(dstInfo); 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_ci return kSuccess; 495cb93a386Sopenharmony_ci} 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_ciint SkHeifCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) { 498cb93a386Sopenharmony_ci return this->readRows(this->dstInfo(), dst, dstRowBytes, count, this->options()); 499cb93a386Sopenharmony_ci} 500cb93a386Sopenharmony_ci 501cb93a386Sopenharmony_cibool SkHeifCodec::onSkipScanlines(int count) { 502cb93a386Sopenharmony_ci return count == (int) fHeifDecoder->skipScanlines(count); 503cb93a386Sopenharmony_ci} 504cb93a386Sopenharmony_ci 505cb93a386Sopenharmony_civoid *SkHeifCodec::heifImplHandle = nullptr; 506cb93a386Sopenharmony_ciHeifDecoder* SkHeifCodec::createHeifDecoder() { 507cb93a386Sopenharmony_ci#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) 508cb93a386Sopenharmony_ci if (!heifImplHandle) { 509cb93a386Sopenharmony_ci heifImplHandle = dlopen(HEIF_IMPL_SO_NAME, RTLD_LAZY); 510cb93a386Sopenharmony_ci } 511cb93a386Sopenharmony_ci if (!heifImplHandle) { 512cb93a386Sopenharmony_ci return new StubHeifDecoder(); 513cb93a386Sopenharmony_ci } 514cb93a386Sopenharmony_ci typedef HeifDecoder* (*CreateHeifDecoderImplT)(); 515cb93a386Sopenharmony_ci HeifDecoder* decoder = nullptr; 516cb93a386Sopenharmony_ci CreateHeifDecoderImplT func = (CreateHeifDecoderImplT)dlsym(heifImplHandle, "CreateHeifDecoderImpl"); 517cb93a386Sopenharmony_ci if (func) { 518cb93a386Sopenharmony_ci decoder = func(); 519cb93a386Sopenharmony_ci } 520cb93a386Sopenharmony_ci return decoder != nullptr ? decoder : new StubHeifDecoder(); 521cb93a386Sopenharmony_ci#else 522cb93a386Sopenharmony_ci return new StubHeifDecoder(); 523cb93a386Sopenharmony_ci#endif 524cb93a386Sopenharmony_ci} 525cb93a386Sopenharmony_ci 526cb93a386Sopenharmony_ci#endif // SK_HAS_HEIF_LIBRARY 527