Add support for H264 high-profile in injectable video encoder.
BUG=webrtc:7760
Review-Url: https://codereview.webrtc.org/3007133002
Cr-Original-Commit-Position: refs/heads/master@{#19774}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: c36daecd7785585cbd6665b8527e307bdb109992
diff --git a/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java b/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java
index ea84bc4..9324ba3 100644
--- a/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java
+++ b/sdk/android/api/org/webrtc/HardwareVideoEncoderFactory.java
@@ -14,13 +14,11 @@
import static org.webrtc.MediaCodecUtils.INTEL_PREFIX;
import static org.webrtc.MediaCodecUtils.QCOM_PREFIX;
-import android.media.MediaCodec;
import android.media.MediaCodecInfo;
-import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecList;
import android.os.Build;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -41,20 +39,6 @@
private static final List<String> H264_HW_EXCEPTION_MODELS =
Arrays.asList("SAMSUNG-SGH-I337", "Nexus 7", "Nexus 4");
- // Keys for H264 VideoCodecInfo properties.
- private static final String H264_FMTP_PROFILE_LEVEL_ID = "profile-level-id";
- private static final String H264_FMTP_LEVEL_ASYMMETRY_ALLOWED = "level-asymmetry-allowed";
- private static final String H264_FMTP_PACKETIZATION_MODE = "packetization-mode";
-
- // Supported H264 profile ids and levels.
- private static final String H264_PROFILE_CONSTRAINED_BASELINE = "4200";
- private static final String H264_PROFILE_CONSTRAINED_HIGH = "640c";
- private static final String H264_LEVEL_3_1 = "1f"; // 31 in hex.
- private static final String H264_CONSTRAINED_BASELINE_3_1 =
- H264_PROFILE_CONSTRAINED_BASELINE + H264_LEVEL_3_1;
- private static final String H264_CONSTRAINED_HIGH_3_1 =
- H264_PROFILE_CONSTRAINED_HIGH + H264_LEVEL_3_1;
-
private final EglBase14.Context sharedContext;
private final boolean enableIntelVp8Encoder;
private final boolean enableH264HighProfile;
@@ -93,9 +77,9 @@
: MediaCodecUtils.TEXTURE_COLOR_FORMATS,
info.getCapabilitiesForType(mime));
- return new HardwareVideoEncoder(codecName, type, colorFormat, getKeyFrameIntervalSec(type),
- getForcedKeyFrameIntervalMs(type, codecName), createBitrateAdjuster(type, codecName),
- sharedContext);
+ return new HardwareVideoEncoder(codecName, type, colorFormat, input.params,
+ getKeyFrameIntervalSec(type), getForcedKeyFrameIntervalMs(type, codecName),
+ createBitrateAdjuster(type, codecName), sharedContext);
}
@Override
@@ -250,10 +234,11 @@
return new HashMap<String, String>();
case H264:
Map<String, String> properties = new HashMap<>();
- properties.put(H264_FMTP_LEVEL_ASYMMETRY_ALLOWED, "1");
- properties.put(H264_FMTP_PACKETIZATION_MODE, "1");
- properties.put(H264_FMTP_PROFILE_LEVEL_ID,
- highProfile ? H264_CONSTRAINED_HIGH_3_1 : H264_CONSTRAINED_BASELINE_3_1);
+ 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;
default:
throw new IllegalArgumentException("Unsupported codec: " + type);
diff --git a/sdk/android/api/org/webrtc/VideoCodecInfo.java b/sdk/android/api/org/webrtc/VideoCodecInfo.java
index d8ac182..70295b7 100644
--- a/sdk/android/api/org/webrtc/VideoCodecInfo.java
+++ b/sdk/android/api/org/webrtc/VideoCodecInfo.java
@@ -16,6 +16,19 @@
* Represent a video codec as encoded in SDP.
*/
public class VideoCodecInfo {
+ // Keys for H264 VideoCodecInfo properties.
+ 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 = "4200";
+ 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 final int payload;
public final String name;
public final Map<String, String> params;
diff --git a/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java b/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java
index 08c09c7..f3be4cb 100644
--- a/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java
+++ b/sdk/android/src/java/org/webrtc/HardwareVideoEncoder.java
@@ -20,10 +20,8 @@
import android.view.Surface;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Arrays;
import java.util.Deque;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
@@ -40,6 +38,9 @@
// constant until API level 21.
private static final String KEY_BITRATE_MODE = "bitrate-mode";
+ private static final int VIDEO_AVC_PROFILE_HIGH = 8;
+ private static final int VIDEO_AVC_LEVEL_3 = 0x100;
+
private static final int MAX_VIDEO_FRAMERATE = 30;
// See MAX_ENCODER_Q_SIZE in androidmediaencoder_jni.cc.
@@ -51,6 +52,7 @@
private final String codecName;
private final VideoCodecType codecType;
private final int colorFormat;
+ private final Map<String, String> params;
private final ColorFormat inputColorFormat;
// Base interval for generating key frames.
private final int keyFrameIntervalSec;
@@ -115,11 +117,12 @@
* @throws IllegalArgumentException if colorFormat is unsupported
*/
public HardwareVideoEncoder(String codecName, VideoCodecType codecType, int colorFormat,
- int keyFrameIntervalSec, int forceKeyFrameIntervalMs, BitrateAdjuster bitrateAdjuster,
- EglBase14.Context textureContext) {
+ Map<String, String> params, int keyFrameIntervalSec, int forceKeyFrameIntervalMs,
+ BitrateAdjuster bitrateAdjuster, EglBase14.Context textureContext) {
this.codecName = codecName;
this.codecType = codecType;
this.colorFormat = colorFormat;
+ this.params = params;
if (textureContext == null) {
this.inputColorFormat = ColorFormat.valueOf(colorFormat);
} else {
@@ -169,6 +172,22 @@
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
format.setInteger(MediaFormat.KEY_FRAME_RATE, bitrateAdjuster.getAdjustedFramerate());
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec);
+ if (codecType == VideoCodecType.H264) {
+ String profileLevelId = params.get(VideoCodecInfo.H264_FMTP_PROFILE_LEVEL_ID);
+ if (profileLevelId == null) {
+ profileLevelId = VideoCodecInfo.H264_CONSTRAINED_BASELINE_3_1;
+ }
+ switch (profileLevelId) {
+ case VideoCodecInfo.H264_CONSTRAINED_HIGH_3_1:
+ format.setInteger("profile", VIDEO_AVC_PROFILE_HIGH);
+ format.setInteger("level", VIDEO_AVC_LEVEL_3);
+ break;
+ case VideoCodecInfo.H264_CONSTRAINED_BASELINE_3_1:
+ break;
+ default:
+ Logging.w(TAG, "Unknown profile level id: " + profileLevelId);
+ }
+ }
Logging.d(TAG, "Format: " + format);
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);