Loading graphics/java/android/graphics/ImageDecoder.java +30 −11 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ import android.media.MediaCodecInfo; import android.media.MediaCodecList; import android.net.Uri; import android.os.Build; import android.os.SystemProperties; import android.os.Trace; import android.system.ErrnoException; import android.system.Os; Loading Loading @@ -2069,47 +2068,67 @@ public final class ImageDecoder implements AutoCloseable { } private static boolean sIsP010SupportedForAV1 = false; private static boolean sIsP010SupportedForAV1Initialized = false; private static final Object sIsP010SupportedForAV1Lock = new Object(); private static boolean sIsP010SupportedForHEVC = false; private static boolean sIsP010SupportedFlagsInitialized = false; private static final Object sIsP010SupportedLock = new Object(); /** * Checks if the device supports decoding 10-bit AV1. */ @SuppressWarnings("AndroidFrameworkCompatChange") // This is not an app-visible API. private static boolean isP010SupportedForAV1() { synchronized (sIsP010SupportedForAV1Lock) { if (sIsP010SupportedForAV1Initialized) { synchronized (sIsP010SupportedLock) { if (sIsP010SupportedFlagsInitialized) { return sIsP010SupportedForAV1; } checkP010SupportforAV1HEVC(); return sIsP010SupportedForAV1; } } sIsP010SupportedForAV1Initialized = true; return sIsP010SupportedForAV1 = isP010SupportedforMime("video/av01"); /** * Checks if the device supports decoding 10-bit HEVC. * This method is called by JNI. */ @SuppressWarnings("unused") private static boolean isP010SupportedForHEVC() { synchronized (sIsP010SupportedLock) { if (sIsP010SupportedFlagsInitialized) { return sIsP010SupportedForHEVC; } checkP010SupportforAV1HEVC(); return sIsP010SupportedForHEVC; } } /** * Checks if the device supports decoding 10-bit for the given mime type. */ private static boolean isP010SupportedforMime(String mime) { private static void checkP010SupportforAV1HEVC() { MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS); for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) { if (mediaCodecInfo.isEncoder()) { continue; } for (String mediaType : mediaCodecInfo.getSupportedTypes()) { if (mediaType.equalsIgnoreCase(mime)) { if (mediaType.equalsIgnoreCase("video/av01") || mediaType.equalsIgnoreCase("video/hevc")) { MediaCodecInfo.CodecCapabilities codecCapabilities = mediaCodecInfo.getCapabilitiesForType(mediaType); for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) { if (codecCapabilities.colorFormats[i] == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) { return true; if (mediaType.equalsIgnoreCase("video/av01")) { sIsP010SupportedForAV1 = true; } else { sIsP010SupportedForHEVC = true; } } } } } return false; } sIsP010SupportedFlagsInitialized = true; } /** Loading libs/hwui/jni/BitmapFactory.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,14 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, decodeColorType = kN32_SkColorType; } // b/276879147, fallback to RGBA_8888 when decoding HEIF and P010 is not supported. if (decodeColorType == kRGBA_1010102_SkColorType && codec->getEncodedFormat() == SkEncodedImageFormat::kHEIF && env->CallStaticBooleanMethod(gImageDecoder_class, gImageDecoder_isP010SupportedForHEVCMethodID) == JNI_FALSE) { decodeColorType = kN32_SkColorType; } sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace( decodeColorType, prefColorSpace); Loading libs/hwui/jni/BitmapFactory.h +5 −1 Original line number Diff line number Diff line #ifndef _ANDROID_GRAPHICS_BITMAP_FACTORY_H_ #define _ANDROID_GRAPHICS_BITMAP_FACTORY_H_ #include <SkEncodedImageFormat.h> #include "GraphicsJNI.h" #include "SkEncodedImageFormat.h" extern jclass gOptions_class; extern jfieldID gOptions_justBoundsFieldID; Loading @@ -26,6 +27,9 @@ extern jfieldID gOptions_bitmapFieldID; extern jclass gBitmapConfig_class; extern jmethodID gBitmapConfig_nativeToConfigMethodID; extern jclass gImageDecoder_class; extern jmethodID gImageDecoder_isP010SupportedForHEVCMethodID; jstring getMimeTypeAsJavaString(JNIEnv*, SkEncodedImageFormat); #endif // _ANDROID_GRAPHICS_BITMAP_FACTORY_H_ libs/hwui/jni/ImageDecoder.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <SkCodecAnimation.h> #include <SkColorSpace.h> #include <SkColorType.h> #include <SkEncodedImageFormat.h> #include <SkImageInfo.h> #include <SkRect.h> #include <SkSize.h> Loading @@ -48,7 +49,8 @@ using namespace android; static jclass gImageDecoder_class; jclass gImageDecoder_class; jmethodID gImageDecoder_isP010SupportedForHEVCMethodID; static jclass gSize_class; static jclass gDecodeException_class; static jclass gCanvas_class; Loading Loading @@ -298,6 +300,14 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong colorType = kN32_SkColorType; } // b/276879147, fallback to RGBA_8888 when decoding HEIF and P010 is not supported. if (colorType == kRGBA_1010102_SkColorType && decoder->mCodec->getEncodedFormat() == SkEncodedImageFormat::kHEIF && env->CallStaticBooleanMethod(gImageDecoder_class, gImageDecoder_isP010SupportedForHEVCMethodID) == JNI_FALSE) { colorType = kN32_SkColorType; } if (!decoder->setOutColorType(colorType)) { doThrowISE(env, "Failed to set out color type!"); return nullptr; Loading Loading @@ -540,6 +550,8 @@ int register_android_graphics_ImageDecoder(JNIEnv* env) { gImageDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder")); gImageDecoder_constructorMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "<init>", "(JIIZZ)V"); gImageDecoder_postProcessMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "postProcessAndRelease", "(Landroid/graphics/Canvas;)I"); gImageDecoder_isP010SupportedForHEVCMethodID = GetStaticMethodIDOrDie(env, gImageDecoder_class, "isP010SupportedForHEVC", "()Z"); gSize_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/util/Size")); gSize_constructorMethodID = GetMethodIDOrDie(env, gSize_class, "<init>", "(II)V"); Loading Loading
graphics/java/android/graphics/ImageDecoder.java +30 −11 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ import android.media.MediaCodecInfo; import android.media.MediaCodecList; import android.net.Uri; import android.os.Build; import android.os.SystemProperties; import android.os.Trace; import android.system.ErrnoException; import android.system.Os; Loading Loading @@ -2069,47 +2068,67 @@ public final class ImageDecoder implements AutoCloseable { } private static boolean sIsP010SupportedForAV1 = false; private static boolean sIsP010SupportedForAV1Initialized = false; private static final Object sIsP010SupportedForAV1Lock = new Object(); private static boolean sIsP010SupportedForHEVC = false; private static boolean sIsP010SupportedFlagsInitialized = false; private static final Object sIsP010SupportedLock = new Object(); /** * Checks if the device supports decoding 10-bit AV1. */ @SuppressWarnings("AndroidFrameworkCompatChange") // This is not an app-visible API. private static boolean isP010SupportedForAV1() { synchronized (sIsP010SupportedForAV1Lock) { if (sIsP010SupportedForAV1Initialized) { synchronized (sIsP010SupportedLock) { if (sIsP010SupportedFlagsInitialized) { return sIsP010SupportedForAV1; } checkP010SupportforAV1HEVC(); return sIsP010SupportedForAV1; } } sIsP010SupportedForAV1Initialized = true; return sIsP010SupportedForAV1 = isP010SupportedforMime("video/av01"); /** * Checks if the device supports decoding 10-bit HEVC. * This method is called by JNI. */ @SuppressWarnings("unused") private static boolean isP010SupportedForHEVC() { synchronized (sIsP010SupportedLock) { if (sIsP010SupportedFlagsInitialized) { return sIsP010SupportedForHEVC; } checkP010SupportforAV1HEVC(); return sIsP010SupportedForHEVC; } } /** * Checks if the device supports decoding 10-bit for the given mime type. */ private static boolean isP010SupportedforMime(String mime) { private static void checkP010SupportforAV1HEVC() { MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS); for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) { if (mediaCodecInfo.isEncoder()) { continue; } for (String mediaType : mediaCodecInfo.getSupportedTypes()) { if (mediaType.equalsIgnoreCase(mime)) { if (mediaType.equalsIgnoreCase("video/av01") || mediaType.equalsIgnoreCase("video/hevc")) { MediaCodecInfo.CodecCapabilities codecCapabilities = mediaCodecInfo.getCapabilitiesForType(mediaType); for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) { if (codecCapabilities.colorFormats[i] == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) { return true; if (mediaType.equalsIgnoreCase("video/av01")) { sIsP010SupportedForAV1 = true; } else { sIsP010SupportedForHEVC = true; } } } } } return false; } sIsP010SupportedFlagsInitialized = true; } /** Loading
libs/hwui/jni/BitmapFactory.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,14 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, decodeColorType = kN32_SkColorType; } // b/276879147, fallback to RGBA_8888 when decoding HEIF and P010 is not supported. if (decodeColorType == kRGBA_1010102_SkColorType && codec->getEncodedFormat() == SkEncodedImageFormat::kHEIF && env->CallStaticBooleanMethod(gImageDecoder_class, gImageDecoder_isP010SupportedForHEVCMethodID) == JNI_FALSE) { decodeColorType = kN32_SkColorType; } sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace( decodeColorType, prefColorSpace); Loading
libs/hwui/jni/BitmapFactory.h +5 −1 Original line number Diff line number Diff line #ifndef _ANDROID_GRAPHICS_BITMAP_FACTORY_H_ #define _ANDROID_GRAPHICS_BITMAP_FACTORY_H_ #include <SkEncodedImageFormat.h> #include "GraphicsJNI.h" #include "SkEncodedImageFormat.h" extern jclass gOptions_class; extern jfieldID gOptions_justBoundsFieldID; Loading @@ -26,6 +27,9 @@ extern jfieldID gOptions_bitmapFieldID; extern jclass gBitmapConfig_class; extern jmethodID gBitmapConfig_nativeToConfigMethodID; extern jclass gImageDecoder_class; extern jmethodID gImageDecoder_isP010SupportedForHEVCMethodID; jstring getMimeTypeAsJavaString(JNIEnv*, SkEncodedImageFormat); #endif // _ANDROID_GRAPHICS_BITMAP_FACTORY_H_
libs/hwui/jni/ImageDecoder.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <SkCodecAnimation.h> #include <SkColorSpace.h> #include <SkColorType.h> #include <SkEncodedImageFormat.h> #include <SkImageInfo.h> #include <SkRect.h> #include <SkSize.h> Loading @@ -48,7 +49,8 @@ using namespace android; static jclass gImageDecoder_class; jclass gImageDecoder_class; jmethodID gImageDecoder_isP010SupportedForHEVCMethodID; static jclass gSize_class; static jclass gDecodeException_class; static jclass gCanvas_class; Loading Loading @@ -298,6 +300,14 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong colorType = kN32_SkColorType; } // b/276879147, fallback to RGBA_8888 when decoding HEIF and P010 is not supported. if (colorType == kRGBA_1010102_SkColorType && decoder->mCodec->getEncodedFormat() == SkEncodedImageFormat::kHEIF && env->CallStaticBooleanMethod(gImageDecoder_class, gImageDecoder_isP010SupportedForHEVCMethodID) == JNI_FALSE) { colorType = kN32_SkColorType; } if (!decoder->setOutColorType(colorType)) { doThrowISE(env, "Failed to set out color type!"); return nullptr; Loading Loading @@ -540,6 +550,8 @@ int register_android_graphics_ImageDecoder(JNIEnv* env) { gImageDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ImageDecoder")); gImageDecoder_constructorMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "<init>", "(JIIZZ)V"); gImageDecoder_postProcessMethodID = GetMethodIDOrDie(env, gImageDecoder_class, "postProcessAndRelease", "(Landroid/graphics/Canvas;)I"); gImageDecoder_isP010SupportedForHEVCMethodID = GetStaticMethodIDOrDie(env, gImageDecoder_class, "isP010SupportedForHEVC", "()Z"); gSize_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/util/Size")); gSize_constructorMethodID = GetMethodIDOrDie(env, gSize_class, "<init>", "(II)V"); Loading