Index: talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java |
diff --git a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java |
index d481d194650f9f4a485393dbc544ab33cebce6e7..749f12956e67d5037e9598fcc3cff0782d6dcec1 100644 |
--- a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java |
+++ b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java |
@@ -38,6 +38,8 @@ import android.os.Bundle; |
import android.util.Log; |
import java.nio.ByteBuffer; |
+import java.util.Arrays; |
+import java.util.List; |
// Java-side of peerconnection_jni.cc:MediaCodecVideoEncoder. |
// This class is an implementation detail of the Java PeerConnection API. |
@@ -70,6 +72,13 @@ public class MediaCodecVideoEncoder { |
// List of supported HW H.264 codecs. |
private static final String[] supportedH264HwCodecPrefixes = |
{"OMX.qcom." }; |
+ // List of devices with poor H.264 encoder quality. |
+ private static final String[] H264_HW_EXCEPTION_MODELS = new String[] { |
+ // HW H.264 encoder on Galaxy S4 generates 2 times lower bitrate comparing |
+ // to target. |
+ "SAMSUNG-SGH-I337", |
+ }; |
+ |
// Bitrate modes - should be in sync with OMX_VIDEO_CONTROLRATETYPE defined |
// in OMX_Video.h |
private static final int VIDEO_ControlRateVariable = 1; |
@@ -105,8 +114,21 @@ public class MediaCodecVideoEncoder { |
private static EncoderProperties findHwEncoder( |
String mime, String[] supportedHwCodecPrefixes) { |
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) |
- return null; // MediaCodec.setParameters is missing. |
+ // MediaCodec.setParameters is missing for JB and below, so bitrate |
+ // can not be adjusted dynamically. |
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { |
+ return null; |
+ } |
+ |
+ // Check if device is in H.264 exception list. |
+ if (mime.equals(H264_MIME_TYPE)) { |
+ List<String> exceptionModels = Arrays.asList(H264_HW_EXCEPTION_MODELS); |
+ if (exceptionModels.contains(Build.MODEL)) { |
+ Log.w(TAG, "Model: " + Build.MODEL + |
+ " has black listed H.264 encoder."); |
+ return null; |
+ } |
+ } |
for (int i = 0; i < MediaCodecList.getCodecCount(); ++i) { |
MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); |
@@ -196,13 +218,16 @@ public class MediaCodecVideoEncoder { |
EncoderProperties properties = null; |
String mime = null; |
int keyFrameIntervalSec = 0; |
+ int bitrateMode = 0; |
if (type == VideoCodecType.VIDEO_CODEC_VP8) { |
mime = VP8_MIME_TYPE; |
properties = findHwEncoder(VP8_MIME_TYPE, supportedVp8HwCodecPrefixes); |
keyFrameIntervalSec = 100; |
+ bitrateMode = VIDEO_ControlRateConstant; |
} else if (type == VideoCodecType.VIDEO_CODEC_H264) { |
mime = H264_MIME_TYPE; |
properties = findHwEncoder(H264_MIME_TYPE, supportedH264HwCodecPrefixes); |
+ bitrateMode = VIDEO_ControlRateVariable; |
keyFrameIntervalSec = 20; |
} |
if (properties == null) { |
@@ -212,7 +237,7 @@ public class MediaCodecVideoEncoder { |
try { |
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); |
format.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * kbps); |
- format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); |
+ format.setInteger("bitrate-mode", bitrateMode); |
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat); |
format.setInteger(MediaFormat.KEY_FRAME_RATE, fps); |
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, keyFrameIntervalSec); |