Add support for H264 high-profile in injectable video encoder.

BUG=webrtc:7760

Review-Url: https://codereview.webrtc.org/3007133002
Cr-Commit-Position: refs/heads/master@{#19774}
This commit is contained in:
sakal 2017-09-11 06:53:27 -07:00 committed by Commit Bot
parent c6b1041d67
commit c36daecd77
3 changed files with 46 additions and 29 deletions

View File

@ -14,13 +14,11 @@ import static org.webrtc.MediaCodecUtils.EXYNOS_PREFIX;
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 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
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 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
: 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 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
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);

View File

@ -16,6 +16,19 @@ import java.util.Map;
* 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;

View File

@ -20,10 +20,8 @@ import android.os.Bundle;
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 @@ class HardwareVideoEncoder implements VideoEncoder {
// 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 @@ class HardwareVideoEncoder implements VideoEncoder {
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 @@ class HardwareVideoEncoder implements VideoEncoder {
* @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 @@ class HardwareVideoEncoder implements VideoEncoder {
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);