diff --git a/bundle.json b/bundle.json index 710285f6dd1b12135bd52db074de999ab56dcd8b..79d5444765bc9726d68a122c3fe35064734c887e 100644 --- a/bundle.json +++ b/bundle.json @@ -53,7 +53,8 @@ "skia", "zlib", "astc-encoder", - "opencl-headers" + "opencl-headers", + "ffmpeg" ] }, "build": { diff --git a/frameworks/innerkitsimpl/converter/include/post_proc.h b/frameworks/innerkitsimpl/converter/include/post_proc.h index 5f1f333185bc5f8a5d071537449bb7216df3f16d..ee013a359d590ace85bcffd7edb6cb2b7295cbd1 100644 --- a/frameworks/innerkitsimpl/converter/include/post_proc.h +++ b/frameworks/innerkitsimpl/converter/include/post_proc.h @@ -40,7 +40,8 @@ public: bool CenterScale(const Size &size, PixelMap &pixelMap); static CropValue GetCropValue(const Rect &rect, const Size &size); static CropValue ValidCropValue(Rect &rect, const Size &size); - + bool ScalePixelMapEx(const Size &desiredSize, PixelMap &pixelMap, + const AntiAliasingOption &option = AntiAliasingOption::NONE); private: static uint8_t *AllocSharedMemory(const Size &size, const uint64_t bufferSize, int &fd, uint32_t uniqueId); static uint8_t *AllocDmaMemory(const Size &size, const uint64_t bufferSize, diff --git a/frameworks/innerkitsimpl/converter/src/post_proc.cpp b/frameworks/innerkitsimpl/converter/src/post_proc.cpp index 2af99bda527c8f7465f9c710d7a7825eec864608..48b0ecd5dd4f76ce8e4ee5c0ba81cdf1f1bf00fd 100644 --- a/frameworks/innerkitsimpl/converter/src/post_proc.cpp +++ b/frameworks/innerkitsimpl/converter/src/post_proc.cpp @@ -37,6 +37,13 @@ #include "surface_buffer.h" #endif +#ifdef __cplusplus +extern "C" { +#endif +#include "libswscale/swscale.h" +#ifdef __cplusplus +}; +#endif namespace OHOS { namespace Media { using namespace std; @@ -47,6 +54,16 @@ constexpr float EPSILON = 1e-6; constexpr uint8_t HALF = 2; constexpr float HALF_F = 2; +static const map PIXEL_FORMAT_MAP = { + { PixelFormat::ALPHA_8, AVPixelFormat::AV_PIX_FMT_GRAY8 }, + { PixelFormat::RGB_565, AVPixelFormat::AV_PIX_FMT_RGB565BE }, + { PixelFormat::RGB_888, AVPixelFormat::AV_PIX_FMT_RGB24 }, + { PixelFormat::RGBA_8888, AVPixelFormat::AV_PIX_FMT_RGBA }, + { PixelFormat::ARGB_8888, AVPixelFormat::AV_PIX_FMT_ARGB }, + { PixelFormat::BGRA_8888, AVPixelFormat::AV_PIX_FMT_BGRA }, + { PixelFormat::RGBA_F16, AVPixelFormat::AV_PIX_FMT_RGBA64BE }, +}; + uint32_t PostProc::DecodePostProc(const DecodeOptions &opts, PixelMap &pixelMap, FinalOutputStep finalOutputStep) { ImageInfo srcImageInfo; @@ -681,5 +698,94 @@ void PostProc::SetScanlineCropAndConvert(const Rect &cropRect, ImageInfo &dstIma } scanlineFilter.SetSrcRegion(srcRect); } + +bool GetScaleFormat(const PixelFormat &format, AVPixelFormat &pixelFormat) +{ + if (format != PixelFormat::UNKNOWN) { + auto formatPair = PIXEL_FORMAT_MAP.find(format); + if (formatPair != PIXEL_FORMAT_MAP.end() && formatPair->second != 0) { + pixelFormat = formatPair->second; + return true; + } + } + return false; +} + +int GetInterpolation(const AntiAliasingOption &option) +{ + switch (option) { + case AntiAliasingOption::NONE: + return SWS_POINT; + case AntiAliasingOption::LOW: + return SWS_BILINEAR; + case AntiAliasingOption::MEDIUM: + return SWS_BICUBIC; + case AntiAliasingOption::HIGH: + return SWS_AREA; + case AntiAliasingOption::FAST_BILINEAER: + return SWS_FAST_BILINEAR; + case AntiAliasingOption::BICUBLIN: + return SWS_BICUBLIN; + case AntiAliasingOption::GAUSS: + return SWS_GAUSS; + case AntiAliasingOption::SINC: + return SWS_SINC; + case AntiAliasingOption::LANCZOS: + return SWS_LANCZOS; + case AntiAliasingOption::SPLINE: + return SWS_SPLINE; + default: + return SWS_POINT; + } +} + +bool PostProc::ScalePixelMapEx(const Size &desiredSize, PixelMap &pixelMap, const AntiAliasingOption &option) +{ + ImageTrace imageTrace("PixelMap ScalePixelMapEx"); + ImageInfo imgInfo; + pixelMap.GetImageInfo(imgInfo); + int32_t srcWidth = pixelMap.GetWidth(); + int32_t srcHeight = pixelMap.GetHeight(); + if (srcWidth <= 0 || srcHeight <= 0 || !pixelMap.GetWritablePixels()) { + HiLog::Error(LABEL, "pixelMap param is invalid, src width:%{public}d, height:%{public}d", srcWidth, srcHeight); + return false; + } + AVPixelFormat pixelFormat; + if (!GetScaleFormat(imgInfo.pixelFormat, pixelFormat)) { + HiLog::Error(LABEL, "pixelMap format is invalid, format: %{public}d", imgInfo.pixelFormat); + return false; + } + uint32_t dstBufferSize = desiredSize.height * desiredSize.width * ImageUtils::GetPixelBytes(imgInfo.pixelFormat); + MemoryData memoryData = {nullptr, dstBufferSize, "ScalePixelMapEx ImageData", desiredSize}; + auto mem = MemoryManager::CreateMemory(pixelMap.GetAllocatorType(), memoryData); + if (mem == nullptr) { + HiLog::Error(LABEL, "ScalePixelMapEx CreateMemory failed"); + return false; + } + + uint8_t *dstPixels = reinterpret_cast(mem->data.data); + const uint8_t *srcPixels = pixelMap.GetPixels(); + int32_t srcRowStride = pixelMap.GetRowStride(); + int32_t dstRowStride; + if (mem->GetType() == AllocatorType::DMA_ALLOC) { + dstRowStride = reinterpret_cast(mem->extend.data)->GetStride(); + } else { + dstRowStride = desiredSize.width * ImageUtils::GetPixelBytes(imgInfo.pixelFormat); + } + SwsContext *swsContext = sws_getContext(srcWidth, srcHeight, pixelFormat, desiredSize.width, desiredSize.height, + pixelFormat, GetInterpolation(option), nullptr, nullptr, nullptr); + auto res = sws_scale(swsContext, &srcPixels, &srcRowStride, 0, srcHeight, &dstPixels, &dstRowStride); + if (!res) { + sws_freeContext(swsContext); + mem->Release(); + HiLog::Error(LABEL, "sws_scale failed"); + return false; + } + pixelMap.SetPixelsAddr(mem->data.data, mem->extend.data, dstBufferSize, mem->GetType(), nullptr); + imgInfo.size = desiredSize; + pixelMap.SetImageInfo(imgInfo, true); + sws_freeContext(swsContext); + return true; +} } // namespace Media } // namespace OHOS diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn index a62f7139eff7ead14a9e93523db540b1162975f8..c8c15351aa067bae63c4374f0c18572a3753d1d3 100644 --- a/interfaces/innerkits/BUILD.gn +++ b/interfaces/innerkits/BUILD.gn @@ -94,9 +94,14 @@ ohos_copy("image_declaration") { module_install_name = "" } +config("image_postproc_config") { + include_dirs = [ "//third_party/ffmpeg" ] +} + if (use_clang_android) { ohos_source_set("image_native") { public_configs = [ ":image_external_config" ] + configs = [ ":image_postproc_config" ] defines = image_decode_android_defines cflags = image_native_android_cflags sources = image_native_android_sources @@ -108,6 +113,7 @@ if (use_clang_android) { } else if (use_clang_ios) { ohos_source_set("image_native") { public_configs = [ ":image_external_config" ] + configs = [ ":image_postproc_config" ] defines = image_decode_ios_defines cflags = image_native_ios_cflags include_dirs = image_native_ios_include_dirs @@ -127,6 +133,7 @@ if (use_clang_android) { } } public_configs = [ ":image_external_config" ] + configs = [ ":image_postproc_config" ] cflags = [ "-DIMAGE_DEBUG_FLAG", @@ -211,6 +218,7 @@ if (use_clang_android) { } else { deps += [ "//third_party/libpng:libpng" ] } + deps += [ "//third_party/ffmpeg:libohosffmpeg" ] external_deps = [ "c_utils:utils", "graphic_2d:color_manager", diff --git a/interfaces/innerkits/include/image_type.h b/interfaces/innerkits/include/image_type.h index 8a5ef651b9b9067b0ddabb3fee5465fd0006cc72..4706601712d93b64a06c10c1126e82d2fc3d00eb 100644 --- a/interfaces/innerkits/include/image_type.h +++ b/interfaces/innerkits/include/image_type.h @@ -204,11 +204,18 @@ enum class ScaleMode : int32_t { enum class IncrementalMode { FULL_DATA = 0, INCREMENTAL_DATA = 1 }; +// used in ScalePixelMapEx enum class AntiAliasingOption : int32_t { - NONE = 0, - LOW = 1, - MEDIUM = 2, - HIGH = 3, + NONE = 0, // SWS_POINT_NEAREST + LOW = 1, // SWS_BILINEAR + MEDIUM = 2, // SWS_BICUBIC + HIGH = 3, // SWS_AREA + FAST_BILINEAER = 4, // SWS_FAST_BILINEAER + BICUBLIN = 5, // SWS_AREA + GAUSS = 6, // SWS_GAUSS + SINC = 7, // SWS_SINC + LANCZOS = 8, // SWS_LANCZOS + SPLINE = 9, // SWS_SPLINE }; } // namespace Media } // namespace OHOS diff --git a/plugins/cross/image_native_android.gni b/plugins/cross/image_native_android.gni index af0d865df73274f5effea8d30ccbcead6055a6d2..f884aace321a38c52377c873dea8e54d31fad521 100644 --- a/plugins/cross/image_native_android.gni +++ b/plugins/cross/image_native_android.gni @@ -246,3 +246,4 @@ image_native_android_deps = [ image_native_android_deps += skia_skcms image_native_android_deps += skia_platform +image_native_android_deps += [ "//third_party/ffmpeg:libohosffmpeg" ] diff --git a/plugins/cross/image_native_ios.gni b/plugins/cross/image_native_ios.gni index 65106d756c25c9ca27eea151af215d1e658a1514..835a4a91e4c27d0550de3cd50267936c636d2c93 100644 --- a/plugins/cross/image_native_ios.gni +++ b/plugins/cross/image_native_ios.gni @@ -237,6 +237,7 @@ image_native_ios_deps = [ image_native_ios_deps += skia_skcms image_native_ios_deps += skia_platform +image_native_ios_deps += [ "//third_party/ffmpeg:libohosffmpeg" ] image_native_ios_external_deps = [ # common