| Index: webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java
|
| diff --git a/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java b/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java
|
| index c2666a419ff072f6496dd52e7db4d3361e50f4b6..b3decbea9f26719c77f3286800bc365e753d10c7 100644
|
| --- a/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java
|
| +++ b/webrtc/sdk/android/api/org/webrtc/MediaCodecVideoEncoder.java
|
| @@ -70,6 +70,7 @@ public class MediaCodecVideoEncoder {
|
| private MediaCodec mediaCodec;
|
| private ByteBuffer[] outputBuffers;
|
| private EglBase14 eglBase;
|
| + private int profile;
|
| private int width;
|
| private int height;
|
| private Surface inputSurface;
|
| @@ -79,6 +80,9 @@ public class MediaCodecVideoEncoder {
|
| private static final String VP9_MIME_TYPE = "video/x-vnd.on2.vp9";
|
| private static final String H264_MIME_TYPE = "video/avc";
|
|
|
| + private static final int VIDEO_AVCProfileHigh = 8;
|
| + private static final int VIDEO_AVCLevel3 = 0x100;
|
| +
|
| // Type of bitrate adjustment for video encoder.
|
| public enum BitrateAdjustmentType {
|
| // No adjustment - video encoder has no known bitrate problem.
|
| @@ -92,6 +96,25 @@ public class MediaCodecVideoEncoder {
|
| DYNAMIC_ADJUSTMENT
|
| }
|
|
|
| + // Should be in sync with webrtc::H264::Profile.
|
| + public static enum H264Profile {
|
| + CONSTRAINED_BASELINE(0),
|
| + BASELINE(1),
|
| + MAIN(2),
|
| + CONSTRAINED_HIGH(3),
|
| + HIGH(4);
|
| +
|
| + private final int value;
|
| +
|
| + H264Profile(int value) {
|
| + this.value = value;
|
| + }
|
| +
|
| + public int getValue() {
|
| + return value;
|
| + }
|
| + }
|
| +
|
| // Class describing supported media codec properties.
|
| private static class MediaCodecProperties {
|
| public final String codecPrefix;
|
| @@ -143,6 +166,13 @@ public class MediaCodecVideoEncoder {
|
| private static final MediaCodecProperties[] h264HwList =
|
| new MediaCodecProperties[] {qcomH264HwProperties, exynosH264HwProperties};
|
|
|
| + // List of supported HW H.264 high profile encoders.
|
| + private static final MediaCodecProperties exynosH264HighProfileHwProperties =
|
| + new MediaCodecProperties(
|
| + "OMX.Exynos.", Build.VERSION_CODES.M, BitrateAdjustmentType.FRAMERATE_ADJUSTMENT);
|
| + private static final MediaCodecProperties[] h264HighProfileHwList =
|
| + new MediaCodecProperties[] {exynosH264HighProfileHwProperties};
|
| +
|
| // List of devices with poor H.264 encoder quality.
|
| // HW H.264 encoder on below devices has poor bitrate control - actual
|
| // bitrates deviates a lot from the target value.
|
| @@ -234,6 +264,11 @@ public class MediaCodecVideoEncoder {
|
| && (findHwEncoder(H264_MIME_TYPE, h264HwList, supportedColorList) != null);
|
| }
|
|
|
| + public static boolean isH264HighProfileHwSupported() {
|
| + return !hwEncoderDisabledTypes.contains(H264_MIME_TYPE)
|
| + && (findHwEncoder(H264_MIME_TYPE, h264HighProfileHwList, supportedColorList) != null);
|
| + }
|
| +
|
| public static boolean isVp8HwSupportedUsingTextures() {
|
| return !hwEncoderDisabledTypes.contains(VP8_MIME_TYPE)
|
| && (findHwEncoder(VP8_MIME_TYPE, vp8HwList(), supportedSurfaceColorList) != null);
|
| @@ -380,12 +415,14 @@ public class MediaCodecVideoEncoder {
|
| }
|
| }
|
|
|
| - boolean initEncode(VideoCodecType type, int width, int height, int kbps, int fps,
|
| + boolean initEncode(VideoCodecType type, int profile, int width, int height, int kbps, int fps,
|
| EglBase14.Context sharedContext) {
|
| final boolean useSurface = sharedContext != null;
|
| - Logging.d(TAG, "Java initEncode: " + type + " : " + width + " x " + height + ". @ " + kbps
|
| - + " kbps. Fps: " + fps + ". Encode from texture : " + useSurface);
|
| + Logging.d(TAG,
|
| + "Java initEncode: " + type + ". Profile: " + profile + " : " + width + " x " + height
|
| + + ". @ " + kbps + " kbps. Fps: " + fps + ". Encode from texture : " + useSurface);
|
|
|
| + this.profile = profile;
|
| this.width = width;
|
| this.height = height;
|
| if (mediaCodecThread != null) {
|
| @@ -394,6 +431,7 @@ public class MediaCodecVideoEncoder {
|
| EncoderProperties properties = null;
|
| String mime = null;
|
| int keyFrameIntervalSec = 0;
|
| + boolean configureH264HighProfile = false;
|
| if (type == VideoCodecType.VIDEO_CODEC_VP8) {
|
| mime = VP8_MIME_TYPE;
|
| properties = findHwEncoder(
|
| @@ -408,6 +446,16 @@ public class MediaCodecVideoEncoder {
|
| mime = H264_MIME_TYPE;
|
| properties = findHwEncoder(
|
| H264_MIME_TYPE, h264HwList, useSurface ? supportedSurfaceColorList : supportedColorList);
|
| + if (profile == H264Profile.CONSTRAINED_HIGH.getValue()) {
|
| + EncoderProperties h264HighProfileProperties = findHwEncoder(H264_MIME_TYPE,
|
| + h264HighProfileHwList, useSurface ? supportedSurfaceColorList : supportedColorList);
|
| + if (h264HighProfileProperties != null) {
|
| + Logging.d(TAG, "High profile H.264 encoder supported.");
|
| + configureH264HighProfile = true;
|
| + } else {
|
| + Logging.d(TAG, "High profile H.264 encoder requested, but not supported. Use baseline.");
|
| + }
|
| + }
|
| keyFrameIntervalSec = 20;
|
| }
|
| if (properties == null) {
|
| @@ -453,6 +501,10 @@ public class MediaCodecVideoEncoder {
|
| format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
|
| format.setInteger(MediaFormat.KEY_FRAME_RATE, targetFps);
|
| format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec);
|
| + if (configureH264HighProfile) {
|
| + format.setInteger("profile", VIDEO_AVCProfileHigh);
|
| + format.setInteger("level", VIDEO_AVCLevel3);
|
| + }
|
| Logging.d(TAG, " Format: " + format);
|
| mediaCodec = createByCodecName(properties.codecName);
|
| this.type = type;
|
| @@ -711,6 +763,12 @@ public class MediaCodecVideoEncoder {
|
| outputBuffers[result].position(info.offset);
|
| outputBuffers[result].limit(info.offset + info.size);
|
| configData.put(outputBuffers[result]);
|
| + // Log few SPS header bytes to check profile and level.
|
| + String spsData = "";
|
| + for (int i = 0; i < (info.size < 8 ? info.size : 8); i++) {
|
| + spsData += Integer.toHexString(configData.get(i) & 0xff) + " ";
|
| + }
|
| + Logging.d(TAG, spsData);
|
| // Release buffer back.
|
| mediaCodec.releaseOutputBuffer(result, false);
|
| // Query next output.
|
|
|