Chromium Code Reviews| Index: media/base/android/java/src/org/chromium/media/MediaCodecUtil.java |
| diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java |
| index f6d97af9f23fd9c05cb4d45dcdbe26f5cffca74e..433bfae4626bb79729cadeac970a686b8ddc01b0 100644 |
| --- a/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java |
| +++ b/media/base/android/java/src/org/chromium/media/MediaCodecUtil.java |
| @@ -15,6 +15,8 @@ import org.chromium.base.annotations.CalledByNative; |
| import org.chromium.base.annotations.JNINamespace; |
| import org.chromium.base.annotations.MainDex; |
| +import java.util.Arrays; |
| +import java.util.List; |
| import java.util.Locale; |
| /** |
| @@ -22,7 +24,7 @@ import java.util.Locale; |
| */ |
| @JNINamespace("media") |
| class MediaCodecUtil { |
| - private static final String TAG = "MediaCodecUtil"; |
| + private static final String TAG = "cr_MediaCodecUtil"; |
| // Codec direction. Keep this in sync with media_codec_direction.h. |
| static final int MEDIA_CODEC_DECODER = 0; |
| @@ -356,4 +358,135 @@ class MediaCodecUtil { |
| } |
| return false; |
| } |
| + |
| + // Class describing supported media codec encoder properties. |
| + private static class MediaCodecProperties { |
|
watk
2016/10/01 01:06:54
I think this would be simpler if you used an enum
braveyao
2016/10/03 23:50:15
Done.
|
| + public final String codecPrefix; |
| + // Minimum Android SDK required for this codec to be used. |
| + public final int minSdk; |
| + |
| + MediaCodecProperties(String codecPrefix, int minSdk) { |
| + this.codecPrefix = codecPrefix; |
| + this.minSdk = minSdk; |
| + } |
| + } |
| + |
| + // List of supported HW VP8 encoders. |
| + private static final MediaCodecProperties sQcomVp8HwProperties = |
| + new MediaCodecProperties("OMX.qcom.", Build.VERSION_CODES.KITKAT); |
| + private static final MediaCodecProperties sExynosVp8HwProperties = |
| + new MediaCodecProperties("OMX.Exynos.", Build.VERSION_CODES.M); |
| + private static final MediaCodecProperties[] sVp8HwList = |
| + new MediaCodecProperties[] {sQcomVp8HwProperties, sExynosVp8HwProperties}; |
| + |
| + // List of supported HW H.264 encoders. |
| + private static final MediaCodecProperties sQcomH264HwProperties = |
| + new MediaCodecProperties("OMX.qcom.", Build.VERSION_CODES.KITKAT); |
| + private static final MediaCodecProperties sExynosH264HwProperties = |
| + new MediaCodecProperties("OMX.Exynos.", Build.VERSION_CODES.LOLLIPOP); |
| + private static final MediaCodecProperties[] sH264HwList = |
| + new MediaCodecProperties[] {sQcomH264HwProperties, sExynosH264HwProperties}; |
| + |
| + // List of devices with poor H.264 encoder quality. |
| + private static final String[] H264_HW_EXCEPTION_MODELS = new String[] { |
| + // HW H.264 encoder on below devices has poor bitrate control - actual bitrates deviates |
| + // a lot from the target value. |
| + "SAMSUNG-SGH-I337", "Nexus 7", "Nexus 4"}; |
|
watk
2016/10/01 01:06:54
"Blacklist" is a more common term for this. What a
braveyao
2016/10/03 23:50:15
Done.
|
| + |
| + /** |
| + * Creates MediaCodec encoder. |
| + * @param mime MIME type of the media. |
| + * @return CodecCreationInfo object |
| + */ |
| + static CodecCreationInfo createEncoder(String mime) { |
| + // Always return a valid CodecCreationInfo, its |mediaCodec| field will be null |
| + // if we cannot create the codec. |
| + CodecCreationInfo result = new CodecCreationInfo(); |
| + |
| + assert result.mediaCodec == null; |
|
watk
2016/10/01 01:06:54
I see that you copied this from above, but I don't
braveyao
2016/10/03 23:50:15
Done.
|
| + |
| + if (mime.equals(MimeTypes.VIDEO_H264)) { |
| + if (!findHwEncoder(MimeTypes.VIDEO_H264, sH264HwList)) return result; |
| + } else if (mime.equals(MimeTypes.VIDEO_VP8)) { |
| + if (!findHwEncoder(MimeTypes.VIDEO_VP8, sVp8HwList)) return result; |
| + } |
| + |
| + try { |
| + result.mediaCodec = MediaCodec.createEncoderByType(mime); |
| + result.supportsAdaptivePlayback = false; |
| + } catch (Exception e) { |
| + Log.e(TAG, "Failed to create MediaCodec: %s", mime, e); |
| + result.mediaCodec = null; |
|
watk
2016/10/01 01:06:54
This is already null?
braveyao
2016/10/03 23:50:15
Done.
|
| + } |
| + return result; |
| + } |
| + |
| + /** |
| + * This is a way to blacklist misbehaving devices. |
| + * @param mime MIME type as passed to mediaCodec.createEncoderByType(mime). |
| + * @param supportedHwCodecProperties MediaCodecProperties of the given MIME type. |
| + * @return true if this codec is supported for encoder on this device. |
| + */ |
| + private static boolean findHwEncoder( |
|
watk
2016/10/01 01:06:54
Rename this to isEncoderSupportedByDevice to mirro
braveyao
2016/10/03 23:50:14
Done.
|
| + String mime, MediaCodecProperties[] supportedHwCodecProperties) { |
| + // MediaCodec.setParameters is missing for JB and below, so bitrate |
| + // can not be adjusted dynamically. |
| + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { |
| + return false; |
| + } |
| + |
| + // Check if this is supported HW encoder. |
| + if (mime.equals(MimeTypes.VIDEO_H264)) { |
| + // Check if device is in H.264 exception list. |
| + List<String> exceptionModels = Arrays.asList(H264_HW_EXCEPTION_MODELS); |
| + if (exceptionModels.contains(Build.MODEL)) { |
| + Log.w(TAG, "Model: " + Build.MODEL + " has black listed H.264 encoder."); |
|
watk
2016/10/01 01:06:54
s/black listed/blacklisted
braveyao
2016/10/03 23:50:15
Done.
|
| + return false; |
| + } |
| + } |
| + |
| + MediaCodecListHelper codecListHelper = new MediaCodecListHelper(); |
| + int codecCount = codecListHelper.getCodecCount(); |
| + for (int i = 0; i < codecCount; ++i) { |
| + MediaCodecInfo info = codecListHelper.getCodecInfoAt(i); |
| + |
| + if (!info.isEncoder() || isSoftwareCodec(info.getName())) continue; |
| + |
| + String encoderName = null; |
| + for (String mimeType : info.getSupportedTypes()) { |
| + if (mimeType.equalsIgnoreCase(mime)) { |
| + encoderName = info.getName(); |
| + break; |
| + } |
| + } |
| + |
| + if (encoderName == null) { |
| + continue; // No HW support in this codec; try the next one. |
| + } |
| + |
| + for (MediaCodecProperties codecProperties : supportedHwCodecProperties) { |
| + if (encoderName.startsWith(codecProperties.codecPrefix)) { |
| + if (Build.VERSION.SDK_INT < codecProperties.minSdk) { |
| + Log.w(TAG, "Codec " + encoderName + " is disabled due to SDK version " |
| + + Build.VERSION.SDK_INT); |
| + continue; |
| + } |
| + Log.d(TAG, "Found target encoder for mime " + mime + " : " + encoderName); |
| + return true; |
| + } |
| + } |
| + } |
| + |
| + Log.w(TAG, "HW encoder for " + mime + " is not available on this device."); |
| + return false; |
| + } |
| + |
| + /** |
| + * Check if H264 HW accelerated encoder is supported. |
| + * @return true if HW encoder is found on this device. |
| + */ |
| + @CalledByNative |
| + static boolean isH264EncoderSupported() { |
| + return findHwEncoder(MimeTypes.VIDEO_H264, sH264HwList); |
| + } |
| } |