Commit 15c2f9c3 by Oliver Woodman

Explicitly set max input size for H264 decoders.

This works around an issue where some devices, such as the Acer Iconia,
don't allocate large enough input buffers for H264.

Issue: #616
Issue: #714
parent decb7f58
...@@ -196,7 +196,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem ...@@ -196,7 +196,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
} }
@Override @Override
protected void configureCodec(MediaCodec codec, String codecName, protected void configureCodec(MediaCodec codec, String codecName, boolean codecIsAdaptive,
android.media.MediaFormat format, android.media.MediaCrypto crypto) { android.media.MediaFormat format, android.media.MediaCrypto crypto) {
String mimeType = format.getString(android.media.MediaFormat.KEY_MIME); String mimeType = format.getString(android.media.MediaFormat.KEY_MIME);
if (RAW_DECODER_NAME.equals(codecName) && !MimeTypes.AUDIO_RAW.equals(mimeType)) { if (RAW_DECODER_NAME.equals(codecName) && !MimeTypes.AUDIO_RAW.equals(mimeType)) {
......
...@@ -269,10 +269,11 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -269,10 +269,11 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
* *
* @param codec The {@link MediaCodec} to configure. * @param codec The {@link MediaCodec} to configure.
* @param codecName The name of the codec. * @param codecName The name of the codec.
* @param codecIsAdaptive Whether the codec is adaptive.
* @param format The format for which the codec is being configured. * @param format The format for which the codec is being configured.
* @param crypto For drm protected playbacks, a {@link MediaCrypto} to use for decryption. * @param crypto For drm protected playbacks, a {@link MediaCrypto} to use for decryption.
*/ */
protected void configureCodec(MediaCodec codec, String codecName, protected void configureCodec(MediaCodec codec, String codecName, boolean codecIsAdaptive,
android.media.MediaFormat format, MediaCrypto crypto) { android.media.MediaFormat format, MediaCrypto crypto) {
codec.configure(format, null, crypto, 0); codec.configure(format, null, crypto, 0);
} }
...@@ -320,28 +321,29 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer ...@@ -320,28 +321,29 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
DecoderInitializationException.NO_SUITABLE_DECODER_ERROR)); DecoderInitializationException.NO_SUITABLE_DECODER_ERROR));
} }
String decoderName = decoderInfo.name; String codecName = decoderInfo.name;
codecIsAdaptive = decoderInfo.adaptive; codecIsAdaptive = decoderInfo.adaptive;
codecNeedsEosPropagationWorkaround = codecNeedsEosPropagationWorkaround(decoderName); codecNeedsEosPropagationWorkaround = codecNeedsEosPropagationWorkaround(codecName);
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(decoderName); codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
try { try {
long codecInitializingTimestamp = SystemClock.elapsedRealtime(); long codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createByCodecName(" + decoderName + ")"); TraceUtil.beginSection("createByCodecName(" + codecName + ")");
codec = MediaCodec.createByCodecName(decoderName); codec = MediaCodec.createByCodecName(codecName);
TraceUtil.endSection(); TraceUtil.endSection();
TraceUtil.beginSection("configureCodec"); TraceUtil.beginSection("configureCodec");
configureCodec(codec, decoderName, format.getFrameworkMediaFormatV16(), mediaCrypto); configureCodec(codec, codecName, codecIsAdaptive, format.getFrameworkMediaFormatV16(),
mediaCrypto);
TraceUtil.endSection(); TraceUtil.endSection();
TraceUtil.beginSection("codec.start()"); TraceUtil.beginSection("codec.start()");
codec.start(); codec.start();
TraceUtil.endSection(); TraceUtil.endSection();
long codecInitializedTimestamp = SystemClock.elapsedRealtime(); long codecInitializedTimestamp = SystemClock.elapsedRealtime();
notifyDecoderInitialized(decoderName, codecInitializedTimestamp, notifyDecoderInitialized(codecName, codecInitializedTimestamp,
codecInitializedTimestamp - codecInitializingTimestamp); codecInitializedTimestamp - codecInitializingTimestamp);
inputBuffers = codec.getInputBuffers(); inputBuffers = codec.getInputBuffers();
outputBuffers = codec.getOutputBuffers(); outputBuffers = codec.getOutputBuffers();
} catch (Exception e) { } catch (Exception e) {
notifyAndThrowDecoderInitError(new DecoderInitializationException(format, e, decoderName)); notifyAndThrowDecoderInitError(new DecoderInitializationException(format, e, codecName));
} }
codecHotswapTimeMs = getState() == TrackRenderer.STATE_STARTED ? codecHotswapTimeMs = getState() == TrackRenderer.STATE_STARTED ?
SystemClock.elapsedRealtime() : -1; SystemClock.elapsedRealtime() : -1;
......
...@@ -21,6 +21,7 @@ import com.google.android.exoplayer.util.MimeTypes; ...@@ -21,6 +21,7 @@ import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.TraceUtil; import com.google.android.exoplayer.util.TraceUtil;
import com.google.android.exoplayer.util.Util; import com.google.android.exoplayer.util.Util;
import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCrypto; import android.media.MediaCrypto;
...@@ -378,8 +379,9 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer { ...@@ -378,8 +379,9 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
// Override configureCodec to provide the surface. // Override configureCodec to provide the surface.
@Override @Override
protected void configureCodec(MediaCodec codec, String codecName, protected void configureCodec(MediaCodec codec, String codecName, boolean codecIsAdaptive,
android.media.MediaFormat format, MediaCrypto crypto) { android.media.MediaFormat format, MediaCrypto crypto) {
maybeSetMaxInputSize(format, codecIsAdaptive);
codec.configure(format, surface, crypto, 0); codec.configure(format, surface, crypto, 0);
codec.setVideoScalingMode(videoScalingMode); codec.setVideoScalingMode(videoScalingMode);
} }
...@@ -548,6 +550,29 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer { ...@@ -548,6 +550,29 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
maybeNotifyDrawnToSurface(); maybeNotifyDrawnToSurface();
} }
@SuppressLint("InlinedApi")
private void maybeSetMaxInputSize(android.media.MediaFormat format, boolean codecIsAdaptive) {
if (!MimeTypes.VIDEO_H264.equals(format.getString(android.media.MediaFormat.KEY_MIME))) {
// Only set a max input size for H264 for now.
return;
}
if (format.containsKey(android.media.MediaFormat.KEY_MAX_INPUT_SIZE)) {
// Already set. The source of the format may know better, so do nothing.
return;
}
int maxHeight = format.getInteger(android.media.MediaFormat.KEY_HEIGHT);
if (codecIsAdaptive && format.containsKey(android.media.MediaFormat.KEY_MAX_HEIGHT)) {
maxHeight = Math.max(maxHeight, format.getInteger(android.media.MediaFormat.KEY_MAX_HEIGHT));
}
int maxWidth = format.getInteger(android.media.MediaFormat.KEY_WIDTH);
if (codecIsAdaptive && format.containsKey(android.media.MediaFormat.KEY_MAX_WIDTH)) {
maxWidth = Math.max(maxHeight, format.getInteger(android.media.MediaFormat.KEY_MAX_WIDTH));
}
// H264 requires compression ratio of at least 2, and uses macroblocks.
int maxInputSize = ((maxWidth + 15) / 16) * ((maxHeight + 15) / 16) * 192;
format.setInteger(android.media.MediaFormat.KEY_MAX_INPUT_SIZE, maxInputSize);
}
private void maybeNotifyVideoSizeChanged() { private void maybeNotifyVideoSizeChanged() {
if (eventHandler == null || eventListener == null if (eventHandler == null || eventListener == null
|| (lastReportedWidth == currentWidth && lastReportedHeight == currentHeight || (lastReportedWidth == currentWidth && lastReportedHeight == currentHeight
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment