Added user-defined predicate to filter video codec implementations.
Ability to provide user defined predicate to disable particular codec in particular circumstances was added. This could help addressing mysterious crashes on specific Android devices. Bug: webrtc:10029 Change-Id: I7ad81f4b1351aa68f036c0ee3b6d32fbf0f697ed Reviewed-on: https://webrtc-review.googlesource.com/c/111781 Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25820}
This commit is contained in:

committed by
Commit Bot

parent
7f7e973362
commit
68478b8287
@ -189,6 +189,7 @@ if (is_android) {
|
|||||||
rtc_android_library("base_java") {
|
rtc_android_library("base_java") {
|
||||||
java_files = [
|
java_files = [
|
||||||
"api/org/webrtc/RefCounted.java",
|
"api/org/webrtc/RefCounted.java",
|
||||||
|
"api/org/webrtc/Predicate.java",
|
||||||
"src/java/org/webrtc/CalledByNative.java",
|
"src/java/org/webrtc/CalledByNative.java",
|
||||||
"src/java/org/webrtc/CalledByNativeUnchecked.java",
|
"src/java/org/webrtc/CalledByNativeUnchecked.java",
|
||||||
"src/java/org/webrtc/Histogram.java",
|
"src/java/org/webrtc/Histogram.java",
|
||||||
|
@ -10,10 +10,29 @@
|
|||||||
|
|
||||||
package org.webrtc;
|
package org.webrtc;
|
||||||
|
|
||||||
|
import android.media.MediaCodecInfo;
|
||||||
|
import java.util.Arrays;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/** Factory for Android hardware VideoDecoders. */
|
/** Factory for Android hardware VideoDecoders. */
|
||||||
public class HardwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory {
|
public class HardwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory {
|
||||||
|
private final static Predicate<MediaCodecInfo> defaultAllowedPredicate =
|
||||||
|
new Predicate<MediaCodecInfo>() {
|
||||||
|
private String[] prefixBlacklist =
|
||||||
|
Arrays.copyOf(MediaCodecUtils.SOFTWARE_IMPLEMENTATION_PREFIXES,
|
||||||
|
MediaCodecUtils.SOFTWARE_IMPLEMENTATION_PREFIXES.length);
|
||||||
|
@Override
|
||||||
|
public boolean test(MediaCodecInfo arg) {
|
||||||
|
final String name = arg.getName();
|
||||||
|
for (String prefix : prefixBlacklist) {
|
||||||
|
if (name.startsWith(prefix)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** Creates a HardwareVideoDecoderFactory that does not use surface textures. */
|
/** Creates a HardwareVideoDecoderFactory that does not use surface textures. */
|
||||||
@Deprecated // Not removed yet to avoid breaking callers.
|
@Deprecated // Not removed yet to avoid breaking callers.
|
||||||
public HardwareVideoDecoderFactory() {
|
public HardwareVideoDecoderFactory() {
|
||||||
@ -27,7 +46,21 @@ public class HardwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory {
|
|||||||
* this disables texture support.
|
* this disables texture support.
|
||||||
*/
|
*/
|
||||||
public HardwareVideoDecoderFactory(@Nullable EglBase.Context sharedContext) {
|
public HardwareVideoDecoderFactory(@Nullable EglBase.Context sharedContext) {
|
||||||
super(sharedContext, /* prefixWhitelist= */ new String[] {""},
|
this(sharedContext, /* codecAllowedPredicate= */ null);
|
||||||
/* prefixBlacklist= */ MediaCodecUtils.SOFTWARE_IMPLEMENTATION_PREFIXES);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a HardwareVideoDecoderFactory that supports surface texture rendering.
|
||||||
|
*
|
||||||
|
* @param sharedContext The textures generated will be accessible from this context. May be null,
|
||||||
|
* this disables texture support.
|
||||||
|
* @param codecAllowedPredicate predicate to filter codecs. It is combined with the default
|
||||||
|
* predicate that only allows hardware codecs.
|
||||||
|
*/
|
||||||
|
public HardwareVideoDecoderFactory(@Nullable EglBase.Context sharedContext,
|
||||||
|
@Nullable Predicate<MediaCodecInfo> codecAllowedPredicate) {
|
||||||
|
super(sharedContext,
|
||||||
|
(codecAllowedPredicate == null ? defaultAllowedPredicate
|
||||||
|
: codecAllowedPredicate.and(defaultAllowedPredicate)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,34 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
|
|||||||
@Nullable private final EglBase14.Context sharedContext;
|
@Nullable private final EglBase14.Context sharedContext;
|
||||||
private final boolean enableIntelVp8Encoder;
|
private final boolean enableIntelVp8Encoder;
|
||||||
private final boolean enableH264HighProfile;
|
private final boolean enableH264HighProfile;
|
||||||
|
@Nullable private final Predicate<MediaCodecInfo> codecAllowedPredicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a HardwareVideoEncoderFactory that supports surface texture encoding.
|
||||||
|
*
|
||||||
|
* @param sharedContext The textures generated will be accessible from this context. May be null,
|
||||||
|
* this disables texture support.
|
||||||
|
* @param enableIntelVp8Encoder true if Intel's VP8 encoder enabled.
|
||||||
|
* @param enableH264HighProfile true if H264 High Profile enabled.
|
||||||
|
*/
|
||||||
public HardwareVideoEncoderFactory(
|
public HardwareVideoEncoderFactory(
|
||||||
EglBase.Context sharedContext, boolean enableIntelVp8Encoder, boolean enableH264HighProfile) {
|
EglBase.Context sharedContext, boolean enableIntelVp8Encoder, boolean enableH264HighProfile) {
|
||||||
|
this(sharedContext, enableIntelVp8Encoder, enableH264HighProfile,
|
||||||
|
/* codecAllowedPredicate= */ null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a HardwareVideoEncoderFactory that supports surface texture encoding.
|
||||||
|
*
|
||||||
|
* @param sharedContext The textures generated will be accessible from this context. May be null,
|
||||||
|
* this disables texture support.
|
||||||
|
* @param enableIntelVp8Encoder true if Intel's VP8 encoder enabled.
|
||||||
|
* @param enableH264HighProfile true if H264 High Profile enabled.
|
||||||
|
* @param codecAllowedPredicate optional predicate to filter codecs. All codecs are allowed
|
||||||
|
* when predicate is not provided.
|
||||||
|
*/
|
||||||
|
public HardwareVideoEncoderFactory(EglBase.Context sharedContext, boolean enableIntelVp8Encoder,
|
||||||
|
boolean enableH264HighProfile, @Nullable Predicate<MediaCodecInfo> codecAllowedPredicate) {
|
||||||
// Texture mode requires EglBase14.
|
// Texture mode requires EglBase14.
|
||||||
if (sharedContext instanceof EglBase14.Context) {
|
if (sharedContext instanceof EglBase14.Context) {
|
||||||
this.sharedContext = (EglBase14.Context) sharedContext;
|
this.sharedContext = (EglBase14.Context) sharedContext;
|
||||||
@ -54,6 +79,7 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
|
|||||||
}
|
}
|
||||||
this.enableIntelVp8Encoder = enableIntelVp8Encoder;
|
this.enableIntelVp8Encoder = enableIntelVp8Encoder;
|
||||||
this.enableH264HighProfile = enableH264HighProfile;
|
this.enableH264HighProfile = enableH264HighProfile;
|
||||||
|
this.codecAllowedPredicate = codecAllowedPredicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -164,7 +190,7 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
|
|||||||
== null) {
|
== null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return isHardwareSupportedInCurrentSdk(info, type);
|
return isHardwareSupportedInCurrentSdk(info, type) && isMediaCodecAllowed(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the given MediaCodecInfo indicates a hardware module that is supported on the
|
// Returns true if the given MediaCodecInfo indicates a hardware module that is supported on the
|
||||||
@ -212,6 +238,13 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
|
|||||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
|
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isMediaCodecAllowed(MediaCodecInfo info) {
|
||||||
|
if (codecAllowedPredicate == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return codecAllowedPredicate.test(info);
|
||||||
|
}
|
||||||
|
|
||||||
private int getKeyFrameIntervalSec(VideoCodecType type) {
|
private int getKeyFrameIntervalSec(VideoCodecType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VP8: // Fallthrough intended.
|
case VP8: // Fallthrough intended.
|
||||||
|
@ -10,10 +10,33 @@
|
|||||||
|
|
||||||
package org.webrtc;
|
package org.webrtc;
|
||||||
|
|
||||||
|
import android.media.MediaCodecInfo;
|
||||||
|
import java.util.Arrays;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/** Factory for Android platform software VideoDecoders. */
|
/** Factory for Android platform software VideoDecoders. */
|
||||||
public class PlatformSoftwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory {
|
public class PlatformSoftwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory {
|
||||||
|
/**
|
||||||
|
* Default allowed predicate.
|
||||||
|
*/
|
||||||
|
private static final Predicate<MediaCodecInfo> defaultAllowedPredicate =
|
||||||
|
new Predicate<MediaCodecInfo>() {
|
||||||
|
private String[] prefixWhitelist =
|
||||||
|
Arrays.copyOf(MediaCodecUtils.SOFTWARE_IMPLEMENTATION_PREFIXES,
|
||||||
|
MediaCodecUtils.SOFTWARE_IMPLEMENTATION_PREFIXES.length);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(MediaCodecInfo arg) {
|
||||||
|
final String name = arg.getName();
|
||||||
|
for (String prefix : prefixWhitelist) {
|
||||||
|
if (name.startsWith(prefix)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a PlatformSoftwareVideoDecoderFactory that supports surface texture rendering.
|
* Creates a PlatformSoftwareVideoDecoderFactory that supports surface texture rendering.
|
||||||
*
|
*
|
||||||
@ -21,7 +44,6 @@ public class PlatformSoftwareVideoDecoderFactory extends MediaCodecVideoDecoderF
|
|||||||
* this disables texture support.
|
* this disables texture support.
|
||||||
*/
|
*/
|
||||||
public PlatformSoftwareVideoDecoderFactory(@Nullable EglBase.Context sharedContext) {
|
public PlatformSoftwareVideoDecoderFactory(@Nullable EglBase.Context sharedContext) {
|
||||||
super(sharedContext, /* prefixWhitelist= */ MediaCodecUtils.SOFTWARE_IMPLEMENTATION_PREFIXES,
|
super(sharedContext, defaultAllowedPredicate);
|
||||||
/* prefixBlacklist= */ new String[] {});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
73
sdk/android/api/org/webrtc/Predicate.java
Normal file
73
sdk/android/api/org/webrtc/Predicate.java
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.webrtc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a predicate (boolean-valued function) of one argument.
|
||||||
|
*/
|
||||||
|
public interface Predicate<T> {
|
||||||
|
/**
|
||||||
|
* Evaluates this predicate on the given argument.
|
||||||
|
*
|
||||||
|
* @param arg the input argument
|
||||||
|
* @return true if the input argument matches the predicate, otherwise false
|
||||||
|
*/
|
||||||
|
boolean test(T arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a composed predicate that represents a short-circuiting logical OR of this predicate
|
||||||
|
* and another. When evaluating the composed predicate, if this predicate is true, then the other
|
||||||
|
* predicate is not evaluated.
|
||||||
|
*
|
||||||
|
* @param other a predicate that will be logically-ORed with this predicate
|
||||||
|
* @return a composed predicate that represents the short-circuiting logical OR of this predicate
|
||||||
|
* and the other predicate
|
||||||
|
*/
|
||||||
|
default Predicate<T> or(Predicate<? super T> other) {
|
||||||
|
return new Predicate<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean test(T arg) {
|
||||||
|
return Predicate.this.test(arg) || other.test(arg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a composed predicate that represents a short-circuiting logical AND of this predicate
|
||||||
|
* and another.
|
||||||
|
*
|
||||||
|
* @param other a predicate that will be logically-ANDed with this predicate
|
||||||
|
* @return a composed predicate that represents the short-circuiting logical AND of this predicate
|
||||||
|
* and the other predicate
|
||||||
|
*/
|
||||||
|
default Predicate<T> and(Predicate<? super T> other) {
|
||||||
|
return new Predicate<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean test(T arg) {
|
||||||
|
return Predicate.this.test(arg) && other.test(arg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a predicate that represents the logical negation of this predicate.
|
||||||
|
*
|
||||||
|
* @return a predicate that represents the logical negation of this predicate
|
||||||
|
*/
|
||||||
|
default Predicate<T> negate() {
|
||||||
|
return new Predicate<T>() {
|
||||||
|
@Override
|
||||||
|
public boolean test(T arg) {
|
||||||
|
return !Predicate.this.test(arg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -28,22 +28,20 @@ class MediaCodecVideoDecoderFactory implements VideoDecoderFactory {
|
|||||||
private static final String TAG = "MediaCodecVideoDecoderFactory";
|
private static final String TAG = "MediaCodecVideoDecoderFactory";
|
||||||
|
|
||||||
private final @Nullable EglBase.Context sharedContext;
|
private final @Nullable EglBase.Context sharedContext;
|
||||||
private final String[] prefixWhitelist;
|
private final @Nullable Predicate<MediaCodecInfo> codecAllowedPredicate;
|
||||||
private final String[] prefixBlacklist;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediaCodecVideoDecoderFactory will support codecs whitelisted excluding those blacklisted.
|
* MediaCodecVideoDecoderFactory with support of codecs filtering.
|
||||||
*
|
*
|
||||||
* @param sharedContext The textures generated will be accessible from this context. May be null,
|
* @param sharedContext The textures generated will be accessible from this context. May be null,
|
||||||
* this disables texture support.
|
* this disables texture support.
|
||||||
* @param prefixWhitelist List of codec prefixes to be whitelisted.
|
* @param codecAllowedPredicate optional predicate to test if codec allowed. All codecs are
|
||||||
* @param prefixBlacklist List of codec prefixes to be blacklisted.
|
* allowed when predicate is not provided.
|
||||||
*/
|
*/
|
||||||
public MediaCodecVideoDecoderFactory(
|
public MediaCodecVideoDecoderFactory(@Nullable EglBase.Context sharedContext,
|
||||||
@Nullable EglBase.Context sharedContext, String[] prefixWhitelist, String[] prefixBlacklist) {
|
@Nullable Predicate<MediaCodecInfo> codecAllowedPredicate) {
|
||||||
this.sharedContext = sharedContext;
|
this.sharedContext = sharedContext;
|
||||||
this.prefixWhitelist = Arrays.copyOf(prefixWhitelist, prefixWhitelist.length);
|
this.codecAllowedPredicate = codecAllowedPredicate;
|
||||||
this.prefixBlacklist = Arrays.copyOf(prefixBlacklist, prefixBlacklist.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@ -123,25 +121,14 @@ class MediaCodecVideoDecoderFactory implements VideoDecoderFactory {
|
|||||||
== null) {
|
== null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return isWhitelisted(name) && !isBlacklisted(name);
|
return isCodecAllowed(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isWhitelisted(String name) {
|
private boolean isCodecAllowed(MediaCodecInfo info) {
|
||||||
for (String prefix : prefixWhitelist) {
|
if (codecAllowedPredicate == null) {
|
||||||
if (name.startsWith(prefix)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return codecAllowedPredicate.test(info);
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isBlacklisted(String name) {
|
|
||||||
for (String prefix : prefixBlacklist) {
|
|
||||||
if (name.startsWith(prefix)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isH264HighProfileSupported(MediaCodecInfo info) {
|
private boolean isH264HighProfileSupported(MediaCodecInfo info) {
|
||||||
|
Reference in New Issue
Block a user