Commit f7c5e475 by olly Committed by Oliver Woodman

Prevent native crash in raw decoder

Playback will still fail if an input sample is larger
than 32K, but will now fail gracefully.

Issue: #4057

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=193951955
parent 895ac660
...@@ -268,6 +268,7 @@ public class DefaultRenderersFactory implements RenderersFactory { ...@@ -268,6 +268,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
ArrayList<Renderer> out) { ArrayList<Renderer> out) {
out.add( out.add(
new MediaCodecAudioRenderer( new MediaCodecAudioRenderer(
context,
MediaCodecSelector.DEFAULT, MediaCodecSelector.DEFAULT,
drmSessionManager, drmSessionManager,
/* playClearSamplesWithoutKeys= */ false, /* playClearSamplesWithoutKeys= */ false,
......
...@@ -85,6 +85,9 @@ public final class MediaCodecInfo { ...@@ -85,6 +85,9 @@ public final class MediaCodecInfo {
*/ */
public final boolean secure; public final boolean secure;
/** Whether this instance describes a passthrough codec. */
public final boolean passthrough;
/** /**
* Creates an instance representing an audio passthrough decoder. * Creates an instance representing an audio passthrough decoder.
* *
...@@ -96,6 +99,7 @@ public final class MediaCodecInfo { ...@@ -96,6 +99,7 @@ public final class MediaCodecInfo {
name, name,
/* mimeType= */ null, /* mimeType= */ null,
/* capabilities= */ null, /* capabilities= */ null,
/* passthrough= */ true,
/* forceDisableAdaptive= */ false, /* forceDisableAdaptive= */ false,
/* forceSecure= */ false); /* forceSecure= */ false);
} }
...@@ -111,7 +115,12 @@ public final class MediaCodecInfo { ...@@ -111,7 +115,12 @@ public final class MediaCodecInfo {
public static MediaCodecInfo newInstance(String name, String mimeType, public static MediaCodecInfo newInstance(String name, String mimeType,
CodecCapabilities capabilities) { CodecCapabilities capabilities) {
return new MediaCodecInfo( return new MediaCodecInfo(
name, mimeType, capabilities, /* forceDisableAdaptive= */ false, /* forceSecure= */ false); name,
mimeType,
capabilities,
/* passthrough= */ false,
/* forceDisableAdaptive= */ false,
/* forceSecure= */ false);
} }
/** /**
...@@ -130,18 +139,21 @@ public final class MediaCodecInfo { ...@@ -130,18 +139,21 @@ public final class MediaCodecInfo {
CodecCapabilities capabilities, CodecCapabilities capabilities,
boolean forceDisableAdaptive, boolean forceDisableAdaptive,
boolean forceSecure) { boolean forceSecure) {
return new MediaCodecInfo(name, mimeType, capabilities, forceDisableAdaptive, forceSecure); return new MediaCodecInfo(
name, mimeType, capabilities, /* passthrough= */ false, forceDisableAdaptive, forceSecure);
} }
private MediaCodecInfo( private MediaCodecInfo(
String name, String name,
@Nullable String mimeType, @Nullable String mimeType,
@Nullable CodecCapabilities capabilities, @Nullable CodecCapabilities capabilities,
boolean passthrough,
boolean forceDisableAdaptive, boolean forceDisableAdaptive,
boolean forceSecure) { boolean forceSecure) {
this.name = Assertions.checkNotNull(name); this.name = Assertions.checkNotNull(name);
this.mimeType = mimeType; this.mimeType = mimeType;
this.capabilities = capabilities; this.capabilities = capabilities;
this.passthrough = passthrough;
adaptive = !forceDisableAdaptive && capabilities != null && isAdaptive(capabilities); adaptive = !forceDisableAdaptive && capabilities != null && isAdaptive(capabilities);
tunneling = capabilities != null && isTunneling(capabilities); tunneling = capabilities != null && isTunneling(capabilities);
secure = forceSecure || (capabilities != null && isSecure(capabilities)); secure = forceSecure || (capabilities != null && isSecure(capabilities));
......
...@@ -129,7 +129,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -129,7 +129,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
*/ */
private static final long MAX_CODEC_HOTSWAP_TIME_MS = 1000; private static final long MAX_CODEC_HOTSWAP_TIME_MS = 1000;
/** The possible return values for {@link #canKeepCodec(MediaCodec, boolean, Format, Format)}. */ /**
* The possible return values for {@link #canKeepCodec(MediaCodec, MediaCodecInfo, Format,
* Format)}.
*/
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
KEEP_CODEC_RESULT_NO, KEEP_CODEC_RESULT_NO,
...@@ -885,7 +888,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -885,7 +888,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
boolean keepingCodec = false; boolean keepingCodec = false;
if (pendingDrmSession == drmSession && codec != null) { if (pendingDrmSession == drmSession && codec != null) {
switch (canKeepCodec(codec, codecInfo.adaptive, oldFormat, format)) { switch (canKeepCodec(codec, codecInfo, oldFormat, format)) {
case KEEP_CODEC_RESULT_NO: case KEEP_CODEC_RESULT_NO:
// Do nothing. // Do nothing.
break; break;
...@@ -962,13 +965,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -962,13 +965,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* <p>The default implementation returns {@link #KEEP_CODEC_RESULT_NO}. * <p>The default implementation returns {@link #KEEP_CODEC_RESULT_NO}.
* *
* @param codec The existing {@link MediaCodec} instance. * @param codec The existing {@link MediaCodec} instance.
* @param codecIsAdaptive Whether the codec is adaptive. * @param codecInfo A {@link MediaCodecInfo} describing the decoder.
* @param oldFormat The format for which the existing instance is configured. * @param oldFormat The format for which the existing instance is configured.
* @param newFormat The new format. * @param newFormat The new format.
* @return Whether the instance can be kept, and if it can whether it requires reconfiguration. * @return Whether the instance can be kept, and if it can whether it requires reconfiguration.
*/ */
protected @KeepCodecResult int canKeepCodec( protected @KeepCodecResult int canKeepCodec(
MediaCodec codec, boolean codecIsAdaptive, Format oldFormat, Format newFormat) { MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
return KEEP_CODEC_RESULT_NO; return KEEP_CODEC_RESULT_NO;
} }
......
...@@ -455,8 +455,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -455,8 +455,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override @Override
protected @KeepCodecResult int canKeepCodec( protected @KeepCodecResult int canKeepCodec(
MediaCodec codec, boolean codecIsAdaptive, Format oldFormat, Format newFormat) { MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
if (areAdaptationCompatible(codecIsAdaptive, oldFormat, newFormat) if (areAdaptationCompatible(codecInfo.adaptive, oldFormat, newFormat)
&& newFormat.width <= codecMaxValues.width && newFormat.width <= codecMaxValues.width
&& newFormat.height <= codecMaxValues.height && newFormat.height <= codecMaxValues.height
&& getMaxInputSize(newFormat) <= codecMaxValues.inputSize) { && getMaxInputSize(newFormat) <= codecMaxValues.inputSize) {
...@@ -922,50 +922,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -922,50 +922,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} }
/** /**
* Returns {@link CodecMaxValues} suitable for configuring a codec for {@code format} in a way
* that will allow possible adaptation to other compatible formats in {@code streamFormats}.
*
* @param codecInfo Information about the {@link MediaCodec} being configured.
* @param format The format for which the codec is being configured.
* @param streamFormats The possible stream formats.
* @return Suitable {@link CodecMaxValues}.
* @throws DecoderQueryException If an error occurs querying {@code codecInfo}.
*/
protected CodecMaxValues getCodecMaxValues(MediaCodecInfo codecInfo, Format format,
Format[] streamFormats) throws DecoderQueryException {
int maxWidth = format.width;
int maxHeight = format.height;
int maxInputSize = getMaxInputSize(format);
if (streamFormats.length == 1) {
// The single entry in streamFormats must correspond to the format for which the codec is
// being configured.
return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}
boolean haveUnknownDimensions = false;
for (Format streamFormat : streamFormats) {
if (areAdaptationCompatible(codecInfo.adaptive, format, streamFormat)) {
haveUnknownDimensions |= (streamFormat.width == Format.NO_VALUE
|| streamFormat.height == Format.NO_VALUE);
maxWidth = Math.max(maxWidth, streamFormat.width);
maxHeight = Math.max(maxHeight, streamFormat.height);
maxInputSize = Math.max(maxInputSize, getMaxInputSize(streamFormat));
}
}
if (haveUnknownDimensions) {
Log.w(TAG, "Resolutions unknown. Codec max resolution: " + maxWidth + "x" + maxHeight);
Point codecMaxSize = getCodecMaxSize(codecInfo, format);
if (codecMaxSize != null) {
maxWidth = Math.max(maxWidth, codecMaxSize.x);
maxHeight = Math.max(maxHeight, codecMaxSize.y);
maxInputSize = Math.max(maxInputSize,
getMaxInputSize(format.sampleMimeType, maxWidth, maxHeight));
Log.w(TAG, "Codec max resolution adjusted to: " + maxWidth + "x" + maxHeight);
}
}
return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}
/**
* Returns the framework {@link MediaFormat} that should be used to configure the decoder. * Returns the framework {@link MediaFormat} that should be used to configure the decoder.
* *
* @param format The format of media. * @param format The format of media.
...@@ -1011,6 +967,51 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1011,6 +967,51 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} }
/** /**
* Returns {@link CodecMaxValues} suitable for configuring a codec for {@code format} in a way
* that will allow possible adaptation to other compatible formats in {@code streamFormats}.
*
* @param codecInfo Information about the {@link MediaCodec} being configured.
* @param format The format for which the codec is being configured.
* @param streamFormats The possible stream formats.
* @return Suitable {@link CodecMaxValues}.
* @throws DecoderQueryException If an error occurs querying {@code codecInfo}.
*/
protected CodecMaxValues getCodecMaxValues(
MediaCodecInfo codecInfo, Format format, Format[] streamFormats)
throws DecoderQueryException {
int maxWidth = format.width;
int maxHeight = format.height;
int maxInputSize = getMaxInputSize(format);
if (streamFormats.length == 1) {
// The single entry in streamFormats must correspond to the format for which the codec is
// being configured.
return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}
boolean haveUnknownDimensions = false;
for (Format streamFormat : streamFormats) {
if (areAdaptationCompatible(codecInfo.adaptive, format, streamFormat)) {
haveUnknownDimensions |=
(streamFormat.width == Format.NO_VALUE || streamFormat.height == Format.NO_VALUE);
maxWidth = Math.max(maxWidth, streamFormat.width);
maxHeight = Math.max(maxHeight, streamFormat.height);
maxInputSize = Math.max(maxInputSize, getMaxInputSize(streamFormat));
}
}
if (haveUnknownDimensions) {
Log.w(TAG, "Resolutions unknown. Codec max resolution: " + maxWidth + "x" + maxHeight);
Point codecMaxSize = getCodecMaxSize(codecInfo, format);
if (codecMaxSize != null) {
maxWidth = Math.max(maxWidth, codecMaxSize.x);
maxHeight = Math.max(maxHeight, codecMaxSize.y);
maxInputSize =
Math.max(maxInputSize, getMaxInputSize(format.sampleMimeType, maxWidth, maxHeight));
Log.w(TAG, "Codec max resolution adjusted to: " + maxWidth + "x" + maxHeight);
}
}
return new CodecMaxValues(maxWidth, maxHeight, maxInputSize);
}
/**
* Returns a maximum video size to use when configuring a codec for {@code format} in a way * Returns a maximum video size to use when configuring a codec for {@code format} in a way
* that will allow possible adaptation to other compatible formats that are expected to have the * that will allow possible adaptation to other compatible formats that are expected to have the
* same aspect ratio, but whose sizes are unknown. * same aspect ratio, but whose sizes are unknown.
......
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