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:
parent
c6b1041d67
commit
c36daecd77
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user