From 6e86e4f1154c5f26ea343b635d3e218a3495da7e Mon Sep 17 00:00:00 2001 From: glaznev Date: Wed, 1 Oct 2014 10:17:47 -0700 Subject: [PATCH] Fix wrong selection of VP8 video decoder on some Samsung devices. - Create HW decoder using first codec in MediaCoedcList instead of using createDecoderByType function. Later may result in opening OMX.SEC.vp8.dec decoder, which can not be used for surface decoding. - Revert r279297 and mark all OMX.SEC.* codecs as non HW accelerated. BUG=408353, 396578 R=qinmin@chromium.org Review URL: https://codereview.chromium.org/605883002 Cr-Commit-Position: refs/heads/master@{#297667} --- .../org/chromium/media/MediaCodecBridge.java | 25 +++++++++ media/base/android/media_codec_bridge.cc | 55 +++++++++++++++---- media/base/android/media_codec_bridge.h | 7 +++ 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java index bf66aa389479c..ac2f73359b5b9 100644 --- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java +++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java @@ -181,6 +181,31 @@ private static CodecInfo[] getCodecsInfo() { return codecInfos.toArray(new CodecInfo[codecInfos.size()]); } + /** + * Get a name of default android codec. + */ + @SuppressWarnings("deprecation") + @CalledByNative + private static String getDefaultCodecName(String mime, int direction) { + String codecName = ""; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + try { + MediaCodec mediaCodec = null; + if (direction == MEDIA_CODEC_ENCODER) { + mediaCodec = MediaCodec.createEncoderByType(mime); + } else { + mediaCodec = MediaCodec.createDecoderByType(mime); + } + codecName = mediaCodec.getName(); + mediaCodec.release(); + } catch (Exception e) { + Log.w(TAG, "getDefaultCodecName: Failed to create MediaCodec: " + + mime + ", direction: " + direction, e); + } + } + return codecName; + } + @SuppressWarnings("deprecation") private static String getDecoderNameForMime(String mime) { int count = MediaCodecList.getCodecCount(); diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc index 3cbc9cc1e0dc8..eb30f28966196 100644 --- a/media/base/android/media_codec_bridge.cc +++ b/media/base/android/media_codec_bridge.cc @@ -121,6 +121,12 @@ bool MediaCodecBridge::SupportsSetParameters() { return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; } +// static +bool MediaCodecBridge::SupportsGetName() { + // MediaCodec.getName() is only available on JB MR2 and greater. + return base::android::BuildInfo::GetInstance()->sdk_int() >= 18; +} + // static std::vector MediaCodecBridge::GetCodecsInfo() { std::vector codecs_info; @@ -150,6 +156,20 @@ std::vector MediaCodecBridge::GetCodecsInfo() { return codecs_info; } +// static +std::string MediaCodecBridge::GetDefaultCodecName( + const std::string& mime_type, + MediaCodecDirection direction) { + if (!IsAvailable()) + return std::string(); + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef j_mime = ConvertUTF8ToJavaString(env, mime_type); + ScopedJavaLocalRef j_codec_name = + Java_MediaCodecBridge_getDefaultCodecName(env, j_mime.obj(), direction); + return ConvertJavaStringToUTF8(env, j_codec_name.obj()); +} + // static bool MediaCodecBridge::CanDecode(const std::string& codec, bool is_secure) { if (!IsAvailable()) @@ -175,19 +195,32 @@ bool MediaCodecBridge::IsKnownUnaccelerated(const std::string& mime_type, if (!IsAvailable()) return true; - std::string codec_type = AndroidMimeTypeToCodecType(mime_type); - std::vector codecs_info = - MediaCodecBridge::GetCodecsInfo(); - for (size_t i = 0; i < codecs_info.size(); ++i) { - if (codecs_info[i].codecs == codec_type && - codecs_info[i].direction == direction) { - // It would be nice if MediaCodecInfo externalized some notion of - // HW-acceleration but it doesn't. Android Media guidance is that the - // prefix below is always used for SW decoders, so that's what we use. - if (!StartsWithASCII(codecs_info[i].name, "OMX.google.", true)) - return false; + std::string codec_name; + if (SupportsGetName()) { + codec_name = GetDefaultCodecName(mime_type, direction); + } else { + std::string codec_type = AndroidMimeTypeToCodecType(mime_type); + std::vector codecs_info = + MediaCodecBridge::GetCodecsInfo(); + for (size_t i = 0; i < codecs_info.size(); ++i) { + if (codecs_info[i].codecs == codec_type && + codecs_info[i].direction == direction) { + codec_name = codecs_info[i].name; + break; + } } } + DVLOG(1) << __PRETTY_FUNCTION__ << "Default codec for " << mime_type << + " : " << codec_name; + // It would be nice if MediaCodecInfo externalized some notion of + // HW-acceleration but it doesn't. Android Media guidance is that the + // "OMX.google" prefix is always used for SW decoders, so that's what we + // use. "OMX.SEC.*" codec is Samsung software implementation - report it + // as unaccelerated as well. + if (codec_name.length() > 0) { + return (StartsWithASCII(codec_name, "OMX.google.", true) || + StartsWithASCII(codec_name, "OMX.SEC.", true)); + } return true; } diff --git a/media/base/android/media_codec_bridge.h b/media/base/android/media_codec_bridge.h index 2d046465d4e1f..da2348f497556 100644 --- a/media/base/android/media_codec_bridge.h +++ b/media/base/android/media_codec_bridge.h @@ -58,6 +58,9 @@ class MEDIA_EXPORT MediaCodecBridge { // Returns true if MediaCodec.setParameters() is available on the device. static bool SupportsSetParameters(); + // Returns true if MediaCodec.getName() is available on the device. + static bool SupportsGetName(); + // Returns whether MediaCodecBridge has a decoder that |is_secure| and can // decode |codec| type. static bool CanDecode(const std::string& codec, bool is_secure); @@ -74,6 +77,10 @@ class MEDIA_EXPORT MediaCodecBridge { // Get a list of supported codecs. static std::vector GetCodecsInfo(); + // Get default codec name for |mime_type|. + static std::string GetDefaultCodecName(const std::string& mime_type, + MediaCodecDirection direction); + virtual ~MediaCodecBridge(); // Resets both input and output, all indices previously returned in calls to