From 9697a5f8706bbe95d86036d16f0395fcab0e14a4 Mon Sep 17 00:00:00 2001 From: wuxinzao Date: Fri, 15 Nov 2024 11:08:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86heif=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E7=9A=84=E5=88=86=E4=BA=AB=E5=A4=8D=E5=88=B6=E4=BF=9D?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wuxinzao --- gn/codec.gni | 4 ++ src/codec/SkHeifCodec.cpp | 73 +++++++++---------- src/codec/SkHeifCodec.h | 6 +- src/codec/SkHeifDecoderAPI.cpp | 125 +++++++++++++++++++++++++++++++++ src/codec/SkHeifDecoderAPI.h | 65 +++++++++++++++++ 5 files changed, 229 insertions(+), 44 deletions(-) create mode 100644 src/codec/SkHeifDecoderAPI.cpp create mode 100644 src/codec/SkHeifDecoderAPI.h diff --git a/gn/codec.gni b/gn/codec.gni index 0c08409f..6d54c0db 100644 --- a/gn/codec.gni +++ b/gn/codec.gni @@ -28,6 +28,10 @@ skia_codec_core = [ "$_src/codec/SkSampler.h", "$_src/codec/SkSwizzler.cpp", "$_src/codec/SkSwizzler.h", + "$_src/codec/SkHeifCodec.cpp", + "$_src/codec/SkHeifCodec.h", + "$_src/codec/SkHeifDecoderAPI.cpp", + "$_src/codec/SkHeifDecoderAPI.h", ] # List generated by Bazel rules: diff --git a/src/codec/SkHeifCodec.cpp b/src/codec/SkHeifCodec.cpp index 4082fa5e..a08f2e57 100644 --- a/src/codec/SkHeifCodec.cpp +++ b/src/codec/SkHeifCodec.cpp @@ -8,6 +8,7 @@ #include "include/core/SkTypes.h" #ifdef SK_HAS_HEIF_LIBRARY +#include "base/logging.h" #include "include/codec/SkCodec.h" #include "include/codec/SkEncodedImageFormat.h" #include "include/core/SkStream.h" @@ -16,6 +17,7 @@ #include "src/base/SkEndian.h" #include "src/codec/SkCodecPriv.h" #include "src/codec/SkHeifCodec.h" +#include "third_party/bounds_checking_function/include/securec.h" #define FOURCC(c1, c2, c3, c4) \ ((c1) << 24 | (c2) << 16 | (c3) << 8 | (c4)) @@ -111,35 +113,6 @@ static SkEncodedOrigin get_orientation(const HeifFrameInfo& frameInfo) { return kDefault_SkEncodedOrigin; } -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 fStream; -}; - static void releaseProc(const void* ptr, void* context) { delete reinterpret_cast*>(context); } @@ -153,7 +126,7 @@ std::unique_ptr SkHeifCodec::MakeFromStream(std::unique_ptr s } HeifFrameInfo heifInfo; - if (!heifDecoder->init(new SkHeifStreamWrapper(stream.release()), &heifInfo)) { + if (!heifDecoder->Init(std::move(stream), &heifInfo)) { *result = kInvalidInput; return nullptr; } @@ -187,12 +160,13 @@ std::unique_ptr SkHeifCodec::MakeFromStream(std::unique_ptr s *result = kSuccess; return std::unique_ptr(new SkHeifCodec( - std::move(info), heifDecoder.release(), orientation, frameCount > 1, format)); + std::move(info), heifDecoder.release(), heifInfo, orientation, frameCount > 1, format)); } SkHeifCodec::SkHeifCodec( SkEncodedInfo&& info, HeifDecoder* heifDecoder, + HeifFrameInfo heifInfo, SkEncodedOrigin origin, bool useAnimation, SkEncodedImageFormat format) @@ -221,32 +195,32 @@ bool SkHeifCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaq switch (dstInfo.colorType()) { case kRGBA_8888_SkColorType: this->setSrcXformFormat(skcms_PixelFormat_RGBA_8888); - return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); + return fHeifDecoder->SetOutputColor(kHeifColorFormat_RGBA_8888); case kBGRA_8888_SkColorType: this->setSrcXformFormat(skcms_PixelFormat_RGBA_8888); - return fHeifDecoder->setOutputColor(kHeifColorFormat_BGRA_8888); + return fHeifDecoder->SetOutputColor(kHeifColorFormat_BGRA_8888); case kRGB_565_SkColorType: this->setSrcXformFormat(skcms_PixelFormat_RGBA_8888); if (needsColorXform) { - return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); + return fHeifDecoder->SetOutputColor(kHeifColorFormat_RGBA_8888); } else { - return fHeifDecoder->setOutputColor(kHeifColorFormat_RGB565); + return fHeifDecoder->SetOutputColor(kHeifColorFormat_RGB565); } case kRGBA_1010102_SkColorType: this->setSrcXformFormat(skcms_PixelFormat_RGBA_1010102); - return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_1010102); + return fHeifDecoder->SetOutputColor(kHeifColorFormat_RGBA_1010102); case kRGBA_F16_SkColorType: SkASSERT(needsColorXform); if (srcIsOpaque && colorDepth == 10) { this->setSrcXformFormat(skcms_PixelFormat_RGBA_1010102); - return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_1010102); + return fHeifDecoder->SetOutputColor(kHeifColorFormat_RGBA_1010102); } else { this->setSrcXformFormat(skcms_PixelFormat_RGBA_8888); - return fHeifDecoder->setOutputColor(kHeifColorFormat_RGBA_8888); + return fHeifDecoder->SetOutputColor(kHeifColorFormat_RGBA_8888); } default: @@ -285,9 +259,19 @@ int SkHeifCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes dstWidth = fSwizzler->swizzleWidth(); } + uint64_t size = 0; + void* ptr = fHeifDecoder->GetDecodeData(size); + int32_t stride = fHeifDecoder->GetStride(); + if (ptr == nullptr) { + LOG(ERROR) << "[HeifSupport] SkHeifCodec::readRows GetDecodeData failed."; + return 0; + } + for (int y = 0; y < count; y++) { - if (!fHeifDecoder->getScanline(decodeDst)) { - return y; + if (memcpy_s((uint8_t*)decodeDst, rowBytes, + (uint8_t*)ptr + y * stride, dstWidth * fFrameInfo.mBytesPerPixel) != EOK) { + LOG(ERROR) << "[HeifSupport] SkHeifCodec::readRows memcpy failed."; + return 0; } if (fSwizzler) { @@ -303,6 +287,8 @@ int SkHeifCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes swizzleDst = SkTAddOffset(swizzleDst, swizzleDstRowBytes); } + fHeifDecoder->CloseDecodeData(ptr, size); + return count; } @@ -397,7 +383,7 @@ SkCodec::Result SkHeifCodec::onGetPixels(const SkImageInfo& dstInfo, fFrameHolder.editFrameAt(options.fFrameIndex)->setDuration( fFrameInfo.mDurationUs / 1000); } else { - success = fHeifDecoder->decode(&fFrameInfo); + success = fHeifDecoder->Decode(&fFrameInfo); } if (!success) { @@ -433,6 +419,11 @@ void SkHeifCodec::allocateStorage(const SkImageInfo& dstInfo) { } size_t totalBytes = swizzleBytes + xformBytes; + if (dstInfo.colorType() == kRGBA_8888_SkColorType) { + totalBytes = fFrameInfo.mBytesPerPixel * fFrameInfo.mWidth * fFrameInfo.mHeight; + } + LOG(DEBUG) << "[HeifSupport] SkHeifCodec::allocateStorage totalBytes = " << totalBytes; + fStorage.reset(totalBytes); if (totalBytes > 0) { fSwizzleSrcRow = (swizzleBytes > 0) ? fStorage.get() : nullptr; diff --git a/src/codec/SkHeifCodec.h b/src/codec/SkHeifCodec.h index 0843134e..7aef20e9 100644 --- a/src/codec/SkHeifCodec.h +++ b/src/codec/SkHeifCodec.h @@ -15,8 +15,8 @@ #include "src/codec/SkFrameHolder.h" #include "src/codec/SkSwizzler.h" -#if __has_include("HeifDecoderAPI.h") - #include "HeifDecoderAPI.h" +#if __has_include("SkHeifDecoderAPI.h") + #include "SkHeifDecoderAPI.h" #else #include "src/codec/SkStubHeifDecoderAPI.h" #endif @@ -65,7 +65,7 @@ private: * Creates an instance of the decoder * Called only by NewFromStream */ - SkHeifCodec(SkEncodedInfo&&, HeifDecoder*, SkEncodedOrigin, bool animation, + SkHeifCodec(SkEncodedInfo&&, HeifDecoder*, HeifFrameInfo, SkEncodedOrigin, bool animation, SkEncodedImageFormat); void initializeSwizzler(const SkImageInfo& dstInfo, const Options& options); diff --git a/src/codec/SkHeifDecoderAPI.cpp b/src/codec/SkHeifDecoderAPI.cpp new file mode 100644 index 00000000..26c09ea1 --- /dev/null +++ b/src/codec/SkHeifDecoderAPI.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef SK_HAS_HEIF_LIBRARY +#include +#include + +#include "base/logging.h" +#include "base/containers/span.h" +#include "include/core/SkStream.h" +#include "third_party/ohos_ndk/includes/ohos_adapter/ohos_adapter_helper.h" + +#include "SkHeifDecoderAPI.h" + +std::unique_ptr HeifDecoder::decoder_adapter_; + +#define HEIF_BYTES_PER_PIXEL_RGBA_8888 4 + +void HeifDecoder::SaveDataToFile(void* ptr, uint64_t size) +{ + static const std::string SANDBOX = "/data/storage/el2/base/files/"; + + std::string fileName = SANDBOX + "heif"; + std::string mapString = "_w_" + std::to_string(GetDecoderAdapter()->GetImageWidth()) + + "_h_" + std::to_string(GetDecoderAdapter()->GetImageHeight()) + + "_stride_" + std::to_string(GetDecoderAdapter()->GetStride()) + + "_size_" + std::to_string(size); + fileName += mapString + ".dat"; + + std::ofstream outFile(fileName, std::ofstream::out); + if (!outFile.is_open()) { + LOG(ERROR) << "[HeifSupport] HeifDecoder::SaveDataToFile open " << fileName << " failed."; + outFile.close(); + return; + } + + outFile.write(reinterpret_cast(ptr), size); + if (outFile.fail()) { + LOG(ERROR) << "[HeifSupport] HeifDecoder::SaveDataToFile write " << fileName << " failed."; + } + LOG(DEBUG) << "[HeifSupport] HeifDecoder::SaveDataToFile close " << fileName; + outFile.close(); +} + +bool HeifDecoder::Init(std::unique_ptr stream, HeifFrameInfo* heifInfo) +{ + auto skData = SkData::MakeFromeStream(stream.get(), stream->getLength()); + if (skData == nullptr) { + LOG(ERROR) << "[HeifSupport] HeifDecoder::Init skData is null."; + return false; + } + + base::span encodedData = base::make_span(skData->bytes(), skData->size()); + if (!GetDecoderAdapter()->ParseImageInfo(encodedData.data(), (uint32_t)encodedData.size())) { + LOG(ERROR) << "[HeifSupport] HeifDecoder::Init ParseImageInfo failed."; + return false; + } + + heifInfo->mHeight = GetDecoderAdapter()->GetImageHeight(); + heifInfo->mWidth = GetDecoderAdapter()->GetImageWidth(); + + data_ = std::move(skData); + return true; +} + +bool HeifDecoder::Decode(HeifFrameInfo* heifInfo) +{ + bool useYuv = (color_format_ == kHeifColorFormat_RGBA_8888) ? false : true; + if (!useYuv) { + heifInfo->mBytesPerPixel = HEIF_BYTES_PER_PIXEL_RGBA_8888; + } + + return GetDecoderAdapter()->Decode((const uint8_t*)data_->bytes(), (uint32_t)data_->size(), + OHOS::NWeb::AllocatorType::kDmaAlloc, useYuv); +} + +bool HeifDecoder::SetOutputColor(HeifColorFormat colorFormat) +{ + color_format_ = colorFormat; + return true; +} + +void* HeifDecoder::GetDecodeData(uint64_t& size) +{ + size = GetDecoderAdapter()->GetSize(); + void* ptr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, + GetDecoderAdapter()->GetFd(), GetDecoderAdapter()->GetOffset()); + if (ptr == MAP_FALED) { + return nullptr; + } + return ptr; +} + +int32_t HeifDecoder::GetStride() +{ + return GetDecoderAdapter()->GetStride(); +} + +void HeifDecoder::CloseDecodeData(void* ptr, uint64_t size) +{ + munmap(ptr, size); + return; +} + +OHOS::NWeb::OhosImageDecoderAdapter* HeifDecoder::GetDecoderAdapter() { + if (!decoder_adapter_) { + decoder_adapter_ = OHOS::NWeb::OhosAdapterHelper::GetInstance().CreateOhosImageDecoderAdapter(); + } + + return decoder_adapter_.get(); +} + +#endif // SK_HAS_HEIF_LIBRARY diff --git a/src/codec/SkHeifDecoderAPI.h b/src/codec/SkHeifDecoderAPI.h new file mode 100644 index 00000000..5ed42dca --- /dev/null +++ b/src/codec/SkHeifDecoderAPI.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SKHEIFDECODERAPI +#define SKHEIFDECODERAPI + +#include +#include +#include + +enum HeifColorFormat { + kHeifColorFormat_RGB565, + kHeifColorFormat_RGBA_8888, + kHeifColorFormat_BGRA_8888, + kHeifColorFormat_RGBA_1010102, +}; + +struct HeifFrameInfo { + 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 mIccData; // ICC data array +}; + +namespace OHOS::NWeb { +class OhosImageDecoderAdapter; +} + +class HeifDecoder { +public: + bool Init(std::unique_ptr stream, HeifFrameInfo* heifInfo); + bool Decode(HeifFrameInfo* heifInfo); + bool SetOutputColor(HeifColorFormat colorFormat); + void* GetDecodeData(uint64_t& size); + void CloseDecodeData(void* ptr, uint64_t size); + int32_t GetStride(); + + bool getSequenceInfo(HeifFrameInfo* frameInfo, size_t *frameCount) { return false; } + bool decode(HeifFrameInfo*) { return false; } + bool decodeSequence(int frameIndex, HeifFrameInfo* frameInfo) { return false; } + int skipScanlines(int) { return 0; } + uint32_t getColorDepth() { return 0; } + +private: + void SaveDataToFile(void* ptr, uint64_t size); + OHOS::NWeb::OhosImageDecoderAdapter* GetDecoderAdapter(); +}; + +static inline HeifDecoder* createHeifDecoder() { return new HeifDecoder(); } + +#endif // SKHEIFDECODERAPI -- Gitee From ed32a6ffecbf37516bbb070db939bed4a79a9b95 Mon Sep 17 00:00:00 2001 From: wuxinzao Date: Fri, 15 Nov 2024 11:58:20 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=A8=E7=A6=81?= =?UTF-8?q?=E5=91=8A=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wuxinzao --- src/codec/SkHeifDecoderAPI.cpp | 4 ++-- src/codec/SkHeifDecoderAPI.h | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/codec/SkHeifDecoderAPI.cpp b/src/codec/SkHeifDecoderAPI.cpp index 26c09ea1..94cc6a2d 100644 --- a/src/codec/SkHeifDecoderAPI.cpp +++ b/src/codec/SkHeifDecoderAPI.cpp @@ -56,7 +56,7 @@ void HeifDecoder::SaveDataToFile(void* ptr, uint64_t size) bool HeifDecoder::Init(std::unique_ptr stream, HeifFrameInfo* heifInfo) { - auto skData = SkData::MakeFromeStream(stream.get(), stream->getLength()); + auto skData = SkData::MakeFromStream(stream.get(), stream->getLength()); if (skData == nullptr) { LOG(ERROR) << "[HeifSupport] HeifDecoder::Init skData is null."; return false; @@ -97,7 +97,7 @@ void* HeifDecoder::GetDecodeData(uint64_t& size) size = GetDecoderAdapter()->GetSize(); void* ptr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, GetDecoderAdapter()->GetFd(), GetDecoderAdapter()->GetOffset()); - if (ptr == MAP_FALED) { + if (ptr == MAP_FAILED) { return nullptr; } return ptr; diff --git a/src/codec/SkHeifDecoderAPI.h b/src/codec/SkHeifDecoderAPI.h index 5ed42dca..0bbcd2d7 100644 --- a/src/codec/SkHeifDecoderAPI.h +++ b/src/codec/SkHeifDecoderAPI.h @@ -56,8 +56,11 @@ public: uint32_t getColorDepth() { return 0; } private: + static std::unique_ptr decoder_adapter_; + static OHOS::NWeb::OhosImageDecoderAdapter* GetDecoderAdapter(); void SaveDataToFile(void* ptr, uint64_t size); - OHOS::NWeb::OhosImageDecoderAdapter* GetDecoderAdapter(); + HeifColorFormat color_format_; + sk_sp data_; }; static inline HeifDecoder* createHeifDecoder() { return new HeifDecoder(); } -- Gitee