1 /* 2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.webrtc; 12 13 import android.annotation.TargetApi; 14 import android.media.MediaCodecInfo; 15 import android.media.MediaCodecInfo.CodecCapabilities; 16 import android.os.Build; 17 import android.support.annotation.Nullable; 18 import java.util.HashMap; 19 import java.util.Map; 20 21 /** Container class for static constants and helpers used with MediaCodec. */ 22 // We are forced to use the old API because we want to support API level < 21. 23 @SuppressWarnings("deprecation") 24 class MediaCodecUtils { 25 private static final String TAG = "MediaCodecUtils"; 26 27 // Prefixes for supported hardware encoder/decoder component names. 28 static final String EXYNOS_PREFIX = "OMX.Exynos."; 29 static final String INTEL_PREFIX = "OMX.Intel."; 30 static final String NVIDIA_PREFIX = "OMX.Nvidia."; 31 static final String QCOM_PREFIX = "OMX.qcom."; 32 static final String[] SOFTWARE_IMPLEMENTATION_PREFIXES = { 33 "OMX.google.", "OMX.SEC.", "c2.android"}; 34 35 // NV12 color format supported by QCOM codec, but not declared in MediaCodec - 36 // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h 37 static final int COLOR_QCOM_FORMATYVU420PackedSemiPlanar32m4ka = 0x7FA30C01; 38 static final int COLOR_QCOM_FORMATYVU420PackedSemiPlanar16m4ka = 0x7FA30C02; 39 static final int COLOR_QCOM_FORMATYVU420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03; 40 static final int COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04; 41 42 // Color formats supported by hardware decoder - in order of preference. 43 static final int[] DECODER_COLOR_FORMATS = new int[] {CodecCapabilities.COLOR_FormatYUV420Planar, 44 CodecCapabilities.COLOR_FormatYUV420SemiPlanar, 45 CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, 46 MediaCodecUtils.COLOR_QCOM_FORMATYVU420PackedSemiPlanar32m4ka, 47 MediaCodecUtils.COLOR_QCOM_FORMATYVU420PackedSemiPlanar16m4ka, 48 MediaCodecUtils.COLOR_QCOM_FORMATYVU420PackedSemiPlanar64x32Tile2m8ka, 49 MediaCodecUtils.COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m}; 50 51 // Color formats supported by hardware encoder - in order of preference. 52 static final int[] ENCODER_COLOR_FORMATS = { 53 MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, 54 MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, 55 MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, 56 MediaCodecUtils.COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m}; 57 58 // Color formats supported by texture mode encoding - in order of preference. 59 static final int[] TEXTURE_COLOR_FORMATS = getTextureColorFormats(); 60 getTextureColorFormats()61 private static int[] getTextureColorFormats() { 62 if (Build.VERSION.SDK_INT >= 18) { 63 return new int[] {MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface}; 64 } else { 65 return new int[] {}; 66 } 67 } 68 selectColorFormat( int[] supportedColorFormats, CodecCapabilities capabilities)69 static @Nullable Integer selectColorFormat( 70 int[] supportedColorFormats, CodecCapabilities capabilities) { 71 for (int supportedColorFormat : supportedColorFormats) { 72 for (int codecColorFormat : capabilities.colorFormats) { 73 if (codecColorFormat == supportedColorFormat) { 74 return codecColorFormat; 75 } 76 } 77 } 78 return null; 79 } 80 codecSupportsType(MediaCodecInfo info, VideoCodecMimeType type)81 static boolean codecSupportsType(MediaCodecInfo info, VideoCodecMimeType type) { 82 for (String mimeType : info.getSupportedTypes()) { 83 if (type.mimeType().equals(mimeType)) { 84 return true; 85 } 86 } 87 return false; 88 } 89 getCodecProperties(VideoCodecMimeType type, boolean highProfile)90 static Map<String, String> getCodecProperties(VideoCodecMimeType type, boolean highProfile) { 91 switch (type) { 92 case VP8: 93 case VP9: 94 return new HashMap<String, String>(); 95 case H264: 96 return H264Utils.getDefaultH264Params(highProfile); 97 default: 98 throw new IllegalArgumentException("Unsupported codec: " + type); 99 } 100 } 101 isHardwareAccelerated(MediaCodecInfo info)102 static boolean isHardwareAccelerated(MediaCodecInfo info) { 103 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 104 return isHardwareAcceleratedQOrHigher(info); 105 } 106 return !isSoftwareOnly(info); 107 } 108 109 @TargetApi(29) isHardwareAcceleratedQOrHigher(android.media.MediaCodecInfo codecInfo)110 private static boolean isHardwareAcceleratedQOrHigher(android.media.MediaCodecInfo codecInfo) { 111 return codecInfo.isHardwareAccelerated(); 112 } 113 isSoftwareOnly(android.media.MediaCodecInfo codecInfo)114 static boolean isSoftwareOnly(android.media.MediaCodecInfo codecInfo) { 115 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 116 return isSoftwareOnlyQOrHigher(codecInfo); 117 } 118 String name = codecInfo.getName(); 119 for (String prefix : SOFTWARE_IMPLEMENTATION_PREFIXES) { 120 if (name.startsWith(prefix)) { 121 return true; 122 } 123 } 124 return false; 125 } 126 127 @TargetApi(29) isSoftwareOnlyQOrHigher(android.media.MediaCodecInfo codecInfo)128 private static boolean isSoftwareOnlyQOrHigher(android.media.MediaCodecInfo codecInfo) { 129 return codecInfo.isSoftwareOnly(); 130 } 131 MediaCodecUtils()132 private MediaCodecUtils() { 133 // This class should not be instantiated. 134 } 135 } 136