diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index ee8500b9dc..2705791152 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -262,7 +262,6 @@ generate_jni("generated_java_audio_device_module_native_jni") { generate_jni("generated_video_jni") { sources = [ "api/org/webrtc/EncodedImage.java", - "api/org/webrtc/HardwareVideoEncoderFactory.java", "api/org/webrtc/MediaCodecVideoDecoder.java", "api/org/webrtc/MediaCodecVideoEncoder.java", "api/org/webrtc/VideoCodecInfo.java", @@ -278,6 +277,7 @@ generate_jni("generated_video_jni") { "api/org/webrtc/VideoSource.java", "api/org/webrtc/VideoTrack.java", "api/org/webrtc/YuvHelper.java", + "src/java/org/webrtc/H264Utils.java", "src/java/org/webrtc/NV12Buffer.java", "src/java/org/webrtc/NV21Buffer.java", "src/java/org/webrtc/NativeCapturerObserver.java", @@ -299,7 +299,7 @@ rtc_static_library("video_jni") { "src/jni/androidvideotracksource.h", "src/jni/encodedimage.cc", "src/jni/encodedimage.h", - "src/jni/hardwarevideoencoderfactory.cc", + "src/jni/h264utils.cc", "src/jni/jni_generator_helper.h", "src/jni/nativecapturerobserver.cc", "src/jni/nativecapturerobserver.h", @@ -879,6 +879,7 @@ rtc_android_library("video_java") { "api/org/webrtc/VideoDecoderFallback.java", "api/org/webrtc/VideoEncoderFallback.java", "src/java/org/webrtc/NV21Buffer.java", + "src/java/org/webrtc/H264Utils.java", "src/java/org/webrtc/VideoDecoderWrapper.java", "src/java/org/webrtc/VideoEncoderWrapper.java", "src/java/org/webrtc/WrappedNativeI420Buffer.java", diff --git a/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java b/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java index 751d1ea54d..b99b2155d4 100644 --- a/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java +++ b/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java @@ -79,15 +79,17 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory { MediaCodecUtils.ENCODER_COLOR_FORMATS, info.getCapabilitiesForType(mime)); if (type == VideoCodecType.H264) { - boolean isHighProfile = nativeIsSameH264Profile(input.params, - MediaCodecUtils.getCodecProperties(type, /* highProfile= */ true)) - && isH264HighProfileSupported(info); - boolean isBaselineProfile = nativeIsSameH264Profile( + boolean isHighProfile = H264Utils.isSameH264Profile( + input.params, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ true)); + boolean isBaselineProfile = H264Utils.isSameH264Profile( input.params, MediaCodecUtils.getCodecProperties(type, /* highProfile= */ false)); if (!isHighProfile && !isBaselineProfile) { return null; } + if (isHighProfile && !isH264HighProfileSupported(info)) { + return null; + } } return new HardwareVideoEncoder(codecName, type, surfaceColorFormat, yuvColorFormat, @@ -243,7 +245,4 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory { return enableH264HighProfile && Build.VERSION.SDK_INT > Build.VERSION_CODES.M && info.getName().startsWith(EXYNOS_PREFIX); } - - private static native boolean nativeIsSameH264Profile( - Map params1, Map params2); } diff --git a/sdk/android/src/java/org/webrtc/H264Utils.java b/sdk/android/src/java/org/webrtc/H264Utils.java new file mode 100644 index 0000000000..abb79c6582 --- /dev/null +++ b/sdk/android/src/java/org/webrtc/H264Utils.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 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; + +import java.util.Map; +import java.util.HashMap; + +/** Container for static helper functions related to dealing with H264 codecs. */ +class H264Utils { + public static final String H264_FMTP_PROFILE_LEVEL_ID = "profile-level-id"; + public static final String H264_FMTP_LEVEL_ASYMMETRY_ALLOWED = "level-asymmetry-allowed"; + public static final String H264_FMTP_PACKETIZATION_MODE = "packetization-mode"; + + public static final String H264_PROFILE_CONSTRAINED_BASELINE = "42e0"; + public static final String H264_PROFILE_CONSTRAINED_HIGH = "640c"; + public static final String H264_LEVEL_3_1 = "1f"; // 31 in hex. + public static final String H264_CONSTRAINED_HIGH_3_1 = + H264_PROFILE_CONSTRAINED_HIGH + H264_LEVEL_3_1; + public static final String H264_CONSTRAINED_BASELINE_3_1 = + H264_PROFILE_CONSTRAINED_BASELINE + H264_LEVEL_3_1; + + public static Map getDefaultH264Params(boolean isHighProfile) { + final Map params = new HashMap<>(); + params.put(VideoCodecInfo.H264_FMTP_LEVEL_ASYMMETRY_ALLOWED, "1"); + params.put(VideoCodecInfo.H264_FMTP_PACKETIZATION_MODE, "1"); + params.put(VideoCodecInfo.H264_FMTP_PROFILE_LEVEL_ID, + isHighProfile ? VideoCodecInfo.H264_CONSTRAINED_HIGH_3_1 + : VideoCodecInfo.H264_CONSTRAINED_BASELINE_3_1); + return params; + } + + public static VideoCodecInfo DEFAULT_H264_BASELINE_PROFILE_CODEC = + new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ false)); + public static VideoCodecInfo DEFAULT_H264_HIGH_PROFILE_CODEC = + new VideoCodecInfo("H264", getDefaultH264Params(/* isHighProfile= */ true)); + + public static boolean isSameH264Profile( + Map params1, Map params2) { + return nativeIsSameH264Profile(params1, params2); + } + + private static native boolean nativeIsSameH264Profile( + Map params1, Map params2); +} diff --git a/sdk/android/src/java/org/webrtc/MediaCodecUtils.java b/sdk/android/src/java/org/webrtc/MediaCodecUtils.java index 5b3ff602c8..6221a104dc 100644 --- a/sdk/android/src/java/org/webrtc/MediaCodecUtils.java +++ b/sdk/android/src/java/org/webrtc/MediaCodecUtils.java @@ -84,13 +84,7 @@ class MediaCodecUtils { case VP9: return new HashMap(); case H264: - Map properties = new HashMap<>(); - properties.put(VideoCodecInfo.H264_FMTP_LEVEL_ASYMMETRY_ALLOWED, "1"); - properties.put(VideoCodecInfo.H264_FMTP_PACKETIZATION_MODE, "1"); - properties.put(VideoCodecInfo.H264_FMTP_PROFILE_LEVEL_ID, - highProfile ? VideoCodecInfo.H264_CONSTRAINED_HIGH_3_1 - : VideoCodecInfo.H264_CONSTRAINED_BASELINE_3_1); - return properties; + return H264Utils.getDefaultH264Params(highProfile); default: throw new IllegalArgumentException("Unsupported codec: " + type); } diff --git a/sdk/android/src/jni/hardwarevideoencoderfactory.cc b/sdk/android/src/jni/h264utils.cc similarity index 52% rename from sdk/android/src/jni/hardwarevideoencoderfactory.cc rename to sdk/android/src/jni/h264utils.cc index 6404c189d6..d40266a55d 100644 --- a/sdk/android/src/jni/hardwarevideoencoderfactory.cc +++ b/sdk/android/src/jni/h264utils.cc @@ -1,5 +1,5 @@ /* - * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * 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 @@ -8,23 +8,21 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include +#include "sdk/android/src/jni/videocodecinfo.h" -#include "media/base/h264_profile_level_id.h" -#include "sdk/android/generated_video_jni/jni/HardwareVideoEncoderFactory_jni.h" -#include "sdk/android/native_api/jni/java_types.h" -#include "sdk/android/src/jni/jni_helpers.h" +#include "common_video/h264/profile_level_id.h" +#include "sdk/android/generated_video_jni/jni/H264Utils_jni.h" namespace webrtc { namespace jni { -static jboolean JNI_HardwareVideoEncoderFactory_IsSameH264Profile( - JNIEnv* jni, +static jboolean JNI_H264Utils_IsSameH264Profile( + JNIEnv* env, const JavaParamRef&, const JavaParamRef& params1, const JavaParamRef& params2) { - return H264::IsSameH264Profile(JavaToNativeStringMap(jni, params1), - JavaToNativeStringMap(jni, params2)); + return H264::IsSameH264Profile(JavaToNativeStringMap(env, params1), + JavaToNativeStringMap(env, params2)); } } // namespace jni