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 androidx.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 = 60 new int[] {MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface}; 61 selectColorFormat( int[] supportedColorFormats, CodecCapabilities capabilities)62 static @Nullable Integer selectColorFormat( 63 int[] supportedColorFormats, CodecCapabilities capabilities) { 64 for (int supportedColorFormat : supportedColorFormats) { 65 for (int codecColorFormat : capabilities.colorFormats) { 66 if (codecColorFormat == supportedColorFormat) { 67 return codecColorFormat; 68 } 69 } 70 } 71 return null; 72 } 73 codecSupportsType(MediaCodecInfo info, VideoCodecMimeType type)74 static boolean codecSupportsType(MediaCodecInfo info, VideoCodecMimeType type) { 75 for (String mimeType : info.getSupportedTypes()) { 76 if (type.mimeType().equals(mimeType)) { 77 return true; 78 } 79 } 80 return false; 81 } 82 getCodecProperties(VideoCodecMimeType type, boolean highProfile)83 static Map<String, String> getCodecProperties(VideoCodecMimeType type, boolean highProfile) { 84 switch (type) { 85 case VP8: 86 case VP9: 87 case AV1: 88 return new HashMap<String, String>(); 89 case H264: 90 return H264Utils.getDefaultH264Params(highProfile); 91 default: 92 throw new IllegalArgumentException("Unsupported codec: " + type); 93 } 94 } 95 isHardwareAccelerated(MediaCodecInfo info)96 static boolean isHardwareAccelerated(MediaCodecInfo info) { 97 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 98 return isHardwareAcceleratedQOrHigher(info); 99 } 100 return !isSoftwareOnly(info); 101 } 102 103 @TargetApi(29) isHardwareAcceleratedQOrHigher(android.media.MediaCodecInfo codecInfo)104 private static boolean isHardwareAcceleratedQOrHigher(android.media.MediaCodecInfo codecInfo) { 105 return codecInfo.isHardwareAccelerated(); 106 } 107 isSoftwareOnly(android.media.MediaCodecInfo codecInfo)108 static boolean isSoftwareOnly(android.media.MediaCodecInfo codecInfo) { 109 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 110 return isSoftwareOnlyQOrHigher(codecInfo); 111 } 112 String name = codecInfo.getName(); 113 for (String prefix : SOFTWARE_IMPLEMENTATION_PREFIXES) { 114 if (name.startsWith(prefix)) { 115 return true; 116 } 117 } 118 return false; 119 } 120 121 @TargetApi(29) isSoftwareOnlyQOrHigher(android.media.MediaCodecInfo codecInfo)122 private static boolean isSoftwareOnlyQOrHigher(android.media.MediaCodecInfo codecInfo) { 123 return codecInfo.isSoftwareOnly(); 124 } 125 MediaCodecUtils()126 private MediaCodecUtils() { 127 // This class should not be instantiated. 128 } 129 } 130