Chromium Code Reviews| 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..87f9b30ae88d497445fcdaf3fe71fde410b745aa 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 |
|
brandtr
2017/06/15 09:04:05
nit: end comment with period.
AlexG
2017/06/15 23:01:12
Done.
|
| + 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"); |
|
brandtr
2017/06/15 09:04:05
nit: period.
AlexG
2017/06/15 23:01:12
Done.
|
| + 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; |