235 lines
10 KiB
Java
235 lines
10 KiB
Java
package org.webrtc;
|
|
|
|
import android.media.MediaCodecInfo;
|
|
import android.media.MediaCodecList;
|
|
import android.os.Build;
|
|
import androidx.annotation.Nullable;
|
|
import c.a.c;
|
|
import h0.c.s0;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import org.webrtc.EglBase;
|
|
import org.webrtc.EglBase14;
|
|
import org.webrtc.VideoEncoderFactory;
|
|
public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
|
|
private static final List<String> H264_HW_EXCEPTION_MODELS = Arrays.asList("SAMSUNG-SGH-I337", "Nexus 7", "Nexus 4");
|
|
private static final int QCOM_VP8_KEY_FRAME_INTERVAL_ANDROID_L_MS = 15000;
|
|
private static final int QCOM_VP8_KEY_FRAME_INTERVAL_ANDROID_M_MS = 20000;
|
|
private static final int QCOM_VP8_KEY_FRAME_INTERVAL_ANDROID_N_MS = 15000;
|
|
private static final String TAG = "HardwareVideoEncoderFactory";
|
|
@Nullable
|
|
private final Predicate<MediaCodecInfo> codecAllowedPredicate;
|
|
private final boolean enableH264HighProfile;
|
|
private final boolean enableIntelVp8Encoder;
|
|
@Nullable
|
|
private final EglBase14.Context sharedContext;
|
|
|
|
/* renamed from: org.webrtc.HardwareVideoEncoderFactory$1 reason: invalid class name */
|
|
public static /* synthetic */ class AnonymousClass1 {
|
|
public static final /* synthetic */ int[] $SwitchMap$org$webrtc$VideoCodecMimeType;
|
|
|
|
static {
|
|
VideoCodecMimeType.values();
|
|
int[] iArr = new int[3];
|
|
$SwitchMap$org$webrtc$VideoCodecMimeType = iArr;
|
|
try {
|
|
iArr[VideoCodecMimeType.VP8.ordinal()] = 1;
|
|
} catch (NoSuchFieldError unused) {
|
|
}
|
|
try {
|
|
$SwitchMap$org$webrtc$VideoCodecMimeType[VideoCodecMimeType.VP9.ordinal()] = 2;
|
|
} catch (NoSuchFieldError unused2) {
|
|
}
|
|
try {
|
|
$SwitchMap$org$webrtc$VideoCodecMimeType[VideoCodecMimeType.H264.ordinal()] = 3;
|
|
} catch (NoSuchFieldError unused3) {
|
|
}
|
|
}
|
|
}
|
|
|
|
public HardwareVideoEncoderFactory(EglBase.Context context, boolean z2, boolean z3) {
|
|
this(context, z2, z3, null);
|
|
}
|
|
|
|
public HardwareVideoEncoderFactory(EglBase.Context context, boolean z2, boolean z3, @Nullable Predicate<MediaCodecInfo> predicate) {
|
|
if (context instanceof EglBase14.Context) {
|
|
this.sharedContext = (EglBase14.Context) context;
|
|
} else {
|
|
Logging.w(TAG, "No shared EglBase.Context. Encoders will not use texture mode.");
|
|
this.sharedContext = null;
|
|
}
|
|
this.enableIntelVp8Encoder = z2;
|
|
this.enableH264HighProfile = z3;
|
|
this.codecAllowedPredicate = predicate;
|
|
}
|
|
|
|
@Deprecated
|
|
public HardwareVideoEncoderFactory(boolean z2, boolean z3) {
|
|
this(null, z2, z3);
|
|
}
|
|
|
|
private BitrateAdjuster createBitrateAdjuster(VideoCodecMimeType videoCodecMimeType, String str) {
|
|
return str.startsWith(MediaCodecUtils.EXYNOS_PREFIX) ? videoCodecMimeType == VideoCodecMimeType.VP8 ? new DynamicBitrateAdjuster() : new FramerateBitrateAdjuster() : new BaseBitrateAdjuster();
|
|
}
|
|
|
|
@Nullable
|
|
private MediaCodecInfo findCodecForType(VideoCodecMimeType videoCodecMimeType) {
|
|
int i = 0;
|
|
while (true) {
|
|
MediaCodecInfo mediaCodecInfo = null;
|
|
if (i >= MediaCodecList.getCodecCount()) {
|
|
return null;
|
|
}
|
|
try {
|
|
mediaCodecInfo = MediaCodecList.getCodecInfoAt(i);
|
|
} catch (IllegalArgumentException e) {
|
|
Logging.e(TAG, "Cannot retrieve encoder codec info", e);
|
|
}
|
|
if (mediaCodecInfo != null && mediaCodecInfo.isEncoder() && isSupportedCodec(mediaCodecInfo, videoCodecMimeType)) {
|
|
return mediaCodecInfo;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
private int getForcedKeyFrameIntervalMs(VideoCodecMimeType videoCodecMimeType, String str) {
|
|
if (videoCodecMimeType != VideoCodecMimeType.VP8 || !str.startsWith(MediaCodecUtils.QCOM_PREFIX)) {
|
|
return 0;
|
|
}
|
|
int i = Build.VERSION.SDK_INT;
|
|
if (!(i == 21 || i == 22)) {
|
|
if (i == 23) {
|
|
return QCOM_VP8_KEY_FRAME_INTERVAL_ANDROID_M_MS;
|
|
}
|
|
if (i <= 23) {
|
|
return 0;
|
|
}
|
|
}
|
|
return 15000;
|
|
}
|
|
|
|
private int getKeyFrameIntervalSec(VideoCodecMimeType videoCodecMimeType) {
|
|
int ordinal = videoCodecMimeType.ordinal();
|
|
if (ordinal == 0 || ordinal == 1) {
|
|
return 100;
|
|
}
|
|
if (ordinal == 2) {
|
|
return 20;
|
|
}
|
|
throw new IllegalArgumentException("Unsupported VideoCodecMimeType " + videoCodecMimeType);
|
|
}
|
|
|
|
private boolean isH264HighProfileSupported(MediaCodecInfo mediaCodecInfo) {
|
|
return this.enableH264HighProfile && Build.VERSION.SDK_INT > 23 && mediaCodecInfo.getName().startsWith(MediaCodecUtils.EXYNOS_PREFIX);
|
|
}
|
|
|
|
private boolean isHardwareSupportedInCurrentSdk(MediaCodecInfo mediaCodecInfo, VideoCodecMimeType videoCodecMimeType) {
|
|
int ordinal = videoCodecMimeType.ordinal();
|
|
if (ordinal == 0) {
|
|
return isHardwareSupportedInCurrentSdkVp8(mediaCodecInfo);
|
|
}
|
|
if (ordinal == 1) {
|
|
return isHardwareSupportedInCurrentSdkVp9(mediaCodecInfo);
|
|
}
|
|
if (ordinal != 2) {
|
|
return false;
|
|
}
|
|
return isHardwareSupportedInCurrentSdkH264(mediaCodecInfo);
|
|
}
|
|
|
|
private boolean isHardwareSupportedInCurrentSdkH264(MediaCodecInfo mediaCodecInfo) {
|
|
for (String str : c.b) {
|
|
if (str.equalsIgnoreCase(Build.MODEL)) {
|
|
return false;
|
|
}
|
|
}
|
|
if (Build.VERSION.SDK_INT >= 29) {
|
|
return mediaCodecInfo.isHardwareAccelerated();
|
|
}
|
|
String lowerCase = mediaCodecInfo.getName().toLowerCase(Locale.ROOT);
|
|
for (String str2 : c.a) {
|
|
if (lowerCase.startsWith(str2)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean isHardwareSupportedInCurrentSdkVp8(MediaCodecInfo mediaCodecInfo) {
|
|
String name = mediaCodecInfo.getName();
|
|
return name.startsWith(MediaCodecUtils.QCOM_PREFIX) || (name.startsWith(MediaCodecUtils.EXYNOS_PREFIX) && Build.VERSION.SDK_INT >= 23) || (name.startsWith(MediaCodecUtils.INTEL_PREFIX) && this.enableIntelVp8Encoder);
|
|
}
|
|
|
|
private boolean isHardwareSupportedInCurrentSdkVp9(MediaCodecInfo mediaCodecInfo) {
|
|
String name = mediaCodecInfo.getName();
|
|
return (name.startsWith(MediaCodecUtils.QCOM_PREFIX) || name.startsWith(MediaCodecUtils.EXYNOS_PREFIX)) && Build.VERSION.SDK_INT >= 24;
|
|
}
|
|
|
|
private boolean isMediaCodecAllowed(MediaCodecInfo mediaCodecInfo) {
|
|
Predicate<MediaCodecInfo> predicate = this.codecAllowedPredicate;
|
|
if (predicate == null) {
|
|
return true;
|
|
}
|
|
return predicate.test(mediaCodecInfo);
|
|
}
|
|
|
|
private boolean isSupportedCodec(MediaCodecInfo mediaCodecInfo, VideoCodecMimeType videoCodecMimeType) {
|
|
return MediaCodecUtils.codecSupportsType(mediaCodecInfo, videoCodecMimeType) && MediaCodecUtils.selectColorFormat(MediaCodecUtils.ENCODER_COLOR_FORMATS, mediaCodecInfo.getCapabilitiesForType(videoCodecMimeType.mimeType())) != null && isHardwareSupportedInCurrentSdk(mediaCodecInfo, videoCodecMimeType) && isMediaCodecAllowed(mediaCodecInfo);
|
|
}
|
|
|
|
@Override // org.webrtc.VideoEncoderFactory
|
|
@Nullable
|
|
public VideoEncoder createEncoder(VideoCodecInfo videoCodecInfo) {
|
|
VideoCodecMimeType valueOf = VideoCodecMimeType.valueOf(videoCodecInfo.name);
|
|
MediaCodecInfo findCodecForType = findCodecForType(valueOf);
|
|
if (findCodecForType == null) {
|
|
return null;
|
|
}
|
|
String name = findCodecForType.getName();
|
|
String mimeType = valueOf.mimeType();
|
|
Integer selectColorFormat = MediaCodecUtils.selectColorFormat(MediaCodecUtils.TEXTURE_COLOR_FORMATS, findCodecForType.getCapabilitiesForType(mimeType));
|
|
Integer selectColorFormat2 = MediaCodecUtils.selectColorFormat(MediaCodecUtils.ENCODER_COLOR_FORMATS, findCodecForType.getCapabilitiesForType(mimeType));
|
|
if (valueOf == VideoCodecMimeType.H264) {
|
|
boolean isSameH264Profile = H264Utils.isSameH264Profile(videoCodecInfo.params, MediaCodecUtils.getCodecProperties(valueOf, true));
|
|
boolean isSameH264Profile2 = H264Utils.isSameH264Profile(videoCodecInfo.params, MediaCodecUtils.getCodecProperties(valueOf, false));
|
|
if (!isSameH264Profile && !isSameH264Profile2) {
|
|
return null;
|
|
}
|
|
if (isSameH264Profile && !isH264HighProfileSupported(findCodecForType)) {
|
|
return null;
|
|
}
|
|
}
|
|
return new HardwareVideoEncoder(new MediaCodecWrapperFactoryImpl(), name, valueOf, selectColorFormat, selectColorFormat2, videoCodecInfo.params, getKeyFrameIntervalSec(valueOf), getForcedKeyFrameIntervalMs(valueOf, name), createBitrateAdjuster(valueOf, name), this.sharedContext);
|
|
}
|
|
|
|
@Override // org.webrtc.VideoEncoderFactory
|
|
public /* synthetic */ VideoEncoderFactory.VideoEncoderSelector getEncoderSelector() {
|
|
return s0.a(this);
|
|
}
|
|
|
|
@Override // org.webrtc.VideoEncoderFactory
|
|
public /* synthetic */ VideoCodecInfo[] getImplementations() {
|
|
return s0.b(this);
|
|
}
|
|
|
|
@Override // org.webrtc.VideoEncoderFactory
|
|
public VideoCodecInfo[] getSupportedCodecs() {
|
|
ArrayList arrayList = new ArrayList();
|
|
VideoCodecMimeType[] videoCodecMimeTypeArr = {VideoCodecMimeType.VP8, VideoCodecMimeType.VP9, VideoCodecMimeType.H264};
|
|
for (int i = 0; i < 3; i++) {
|
|
VideoCodecMimeType videoCodecMimeType = videoCodecMimeTypeArr[i];
|
|
MediaCodecInfo findCodecForType = findCodecForType(videoCodecMimeType);
|
|
if (findCodecForType != null) {
|
|
String name = videoCodecMimeType.name();
|
|
if (videoCodecMimeType == VideoCodecMimeType.H264 && isH264HighProfileSupported(findCodecForType)) {
|
|
arrayList.add(new VideoCodecInfo(name, MediaCodecUtils.getCodecProperties(videoCodecMimeType, true)));
|
|
}
|
|
arrayList.add(new VideoCodecInfo(name, MediaCodecUtils.getCodecProperties(videoCodecMimeType, false)));
|
|
}
|
|
}
|
|
return (VideoCodecInfo[]) arrayList.toArray(new VideoCodecInfo[arrayList.size()]);
|
|
}
|
|
}
|