From 94f79ec7bc81b5593d6378834e0c118c8fc09cba Mon Sep 17 00:00:00 2001 From: Kanat Kiialbaev Date: Thu, 17 Oct 2024 14:17:23 -0400 Subject: [PATCH] add DefaultBlacklistedVideoDecoderFactory (#40) * add DefaultBlacklistedVideoDecoderFactory * use decoder.implementationName * fix compilation * fix logging * fix logging func call * fix imports + package --- sdk/android/BUILD.gn | 1 + ...DefaultBlacklistedVideoDecoderFactory.java | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 sdk/android/api/org/webrtc/DefaultBlacklistedVideoDecoderFactory.java diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index a7120b5f42..96ffa7dc0a 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -370,6 +370,7 @@ if (is_android) { "api/org/webrtc/DefaultVideoDecoderFactory.java", "api/org/webrtc/DefaultVideoEncoderFactory.java", "api/org/webrtc/WrappedVideoDecoderFactory.java", + "api/org/webrtc/DefaultBlacklistedVideoDecoderFactory.java", "api/org/webrtc/DefaultAlignedVideoEncoderFactory.java", "api/org/webrtc/SimulcastAlignedVideoEncoderFactory.java", ] diff --git a/sdk/android/api/org/webrtc/DefaultBlacklistedVideoDecoderFactory.java b/sdk/android/api/org/webrtc/DefaultBlacklistedVideoDecoderFactory.java new file mode 100644 index 0000000000..3b3874734a --- /dev/null +++ b/sdk/android/api/org/webrtc/DefaultBlacklistedVideoDecoderFactory.java @@ -0,0 +1,79 @@ +package org.webrtc; + +import androidx.annotation.Nullable; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +public class DefaultBlacklistedVideoDecoderFactory implements VideoDecoderFactory { + + private static final String TAG = "DefaultBlacklistedVideoDecoderFactory"; + + private static final Predicate defaultBlacklistedPredicate = + new Predicate() { + @Override + public boolean test(@Nullable VideoDecoder decoder) { + // if the decoder is Exynos VP9, then blacklist it + return isExynosVP9(decoder); + } + }; + + private final VideoDecoderFactory hardwareVideoDecoderFactory; + private final VideoDecoderFactory softwareVideoDecoderFactory; + private final VideoDecoderFactory platformSoftwareVideoDecoderFactory; + private final Predicate isHardwareDecoderBlacklisted; + + public DefaultBlacklistedVideoDecoderFactory(@Nullable EglBase.Context eglContext) { + this(eglContext, null); + } + + public DefaultBlacklistedVideoDecoderFactory( + @Nullable EglBase.Context eglContext, + @Nullable Predicate decoderBlacklistedPredicate) { + this.hardwareVideoDecoderFactory = new HardwareVideoDecoderFactory(eglContext); + this.softwareVideoDecoderFactory = new SoftwareVideoDecoderFactory(); + this.platformSoftwareVideoDecoderFactory = new PlatformSoftwareVideoDecoderFactory(eglContext); + this.isHardwareDecoderBlacklisted = decoderBlacklistedPredicate == null + ? defaultBlacklistedPredicate + : decoderBlacklistedPredicate.or(defaultBlacklistedPredicate); + } + + @Override + public VideoDecoder createDecoder(VideoCodecInfo codecType) { + VideoDecoder softwareDecoder = softwareVideoDecoderFactory.createDecoder(codecType); + VideoDecoder hardwareDecoder = hardwareVideoDecoderFactory.createDecoder(codecType); + if (softwareDecoder == null) { + softwareDecoder = platformSoftwareVideoDecoderFactory.createDecoder(codecType); + } + + if (isHardwareDecoderBlacklisted.test(hardwareDecoder)) { + Logging.d(TAG, "Hardware decoder is blacklisted: " + hardwareDecoder.getImplementationName()); + return softwareDecoder; + } + + if (hardwareDecoder != null && softwareDecoder != null) { + return new VideoDecoderFallback(softwareDecoder, hardwareDecoder); + } else { + return hardwareDecoder != null ? hardwareDecoder : softwareDecoder; + } + } + + @Override + public VideoCodecInfo[] getSupportedCodecs() { + Set supportedCodecInfos = new HashSet<>(); + supportedCodecInfos.addAll(Arrays.asList(softwareVideoDecoderFactory.getSupportedCodecs())); + supportedCodecInfos.addAll(Arrays.asList(hardwareVideoDecoderFactory.getSupportedCodecs())); + supportedCodecInfos.addAll(Arrays.asList(platformSoftwareVideoDecoderFactory.getSupportedCodecs())); + return supportedCodecInfos.toArray(new VideoCodecInfo[0]); + } + + private static boolean isExynosVP9(@Nullable VideoDecoder decoder) { + if (decoder == null) { + return false; + } + final String name = decoder.getImplementationName().toLowerCase(); + return name.contains("exynos") && name.contains("vp9"); + } +}