Merge "Fallback to RGBA_8888 when P010 is not supported" into udc-dev

This commit is contained in:
Xiao Huang
2023-04-21 09:09:28 +00:00
committed by Android (Google) Code Review
4 changed files with 56 additions and 13 deletions

View File

@@ -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;
@@ -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;
}
/**

View File

@@ -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);

View File

@@ -1,8 +1,9 @@
#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;
@@ -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_

View File

@@ -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>
@@ -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;
@@ -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;
@@ -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");