mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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
This commit is contained in:
parent
decb7f58c7
commit
15c2f9c328
3 changed files with 38 additions and 11 deletions
|
|
@ -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
|
||||||
*
|
*
|
||||||
* @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
|
||||||
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;
|
||||||
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 {
|
||||||
|
|
||||||
// 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 {
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue