Skip to content

Commit

Permalink
Remove dead code related to MediaCodec now minSdk is 21
Browse files Browse the repository at this point in the history
This removes several workarounds that are no longer needed, including
`codecNeedsMonoChannelCountWorkaround` which has been permanently
disabled since the (incomplete) minSdk 19 clean-up in fb74383.

PiperOrigin-RevId: 652495578
  • Loading branch information
icbaker authored and copybara-github committed Jul 15, 2024
1 parent 1bb8d5f commit bb9ff30
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 252 deletions.
2 changes: 1 addition & 1 deletion api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,7 @@ package androidx.media3.common {
field public static final androidx.media3.common.VideoSize UNKNOWN;
field @IntRange(from=0) public final int height;
field @FloatRange(from=0, fromInclusive=false) public final float pixelWidthHeightRatio;
field @IntRange(from=0, to=359) public final int unappliedRotationDegrees;
field @Deprecated @IntRange(from=0, to=359) public final int unappliedRotationDegrees;
field @IntRange(from=0) public final int width;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,10 @@ public final class VideoSize {
public final int height;

/**
* Clockwise rotation in degrees that the application should apply for the video for it to be
* rendered in the correct orientation.
*
* <p>Is 0 if unknown or if no rotation is needed.
*
* <p>Player should apply video rotation internally, in which case unappliedRotationDegrees is 0.
* But when a player can't apply the rotation, for example before API level 21, the unapplied
* rotation is reported by this field for application to handle.
*
* <p>Applications that use {@link android.view.TextureView} can apply the rotation by calling
* {@link android.view.TextureView#setTransform}.
* @deprecated Rotation is handled internally by the player, so this is always zero.
*/
@IntRange(from = 0, to = 359)
@Deprecated
public final int unappliedRotationDegrees;

/**
Expand All @@ -73,21 +64,33 @@ public final class VideoSize {
*/
@UnstableApi
public VideoSize(@IntRange(from = 0) int width, @IntRange(from = 0) int height) {
this(width, height, DEFAULT_UNAPPLIED_ROTATION_DEGREES, DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO);
this(width, height, DEFAULT_PIXEL_WIDTH_HEIGHT_RATIO);
}

/**
* Creates a new instance.
*
* @param width The video width in pixels.
* @param height The video height in pixels.
* @param unappliedRotationDegrees Clockwise rotation in degrees that the application should apply
* for the video for it to be rendered in the correct orientation. See {@link
* #unappliedRotationDegrees}.
* @param pixelWidthHeightRatio The width to height ratio of each pixel. For the normal case of
* square pixels this will be equal to 1.0. Different values are indicative of anamorphic
* content.
*/
@SuppressWarnings("deprecation") // Calling through to deprecated constructor
@UnstableApi
public VideoSize(
@IntRange(from = 0) int width,
@IntRange(from = 0) int height,
@FloatRange(from = 0, fromInclusive = false) float pixelWidthHeightRatio) {
this(width, height, DEFAULT_UNAPPLIED_ROTATION_DEGREES, pixelWidthHeightRatio);
}

/**
* @deprecated Use {@link VideoSize#VideoSize(int, int, float)} instead. {@code
* unappliedRotationDegrees} is not needed on API 21+.
*/
@SuppressWarnings("deprecation") // Setting deprecate field
@Deprecated
@UnstableApi
public VideoSize(
@IntRange(from = 0) int width,
Expand All @@ -100,6 +103,7 @@ public VideoSize(
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
}

@SuppressWarnings("deprecation") // Including deprecated field in equality
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
Expand All @@ -115,6 +119,7 @@ public boolean equals(@Nullable Object obj) {
return false;
}

@SuppressWarnings("deprecation") // Including deprecated field in hashCode
@Override
public int hashCode() {
int result = 7;
Expand All @@ -130,6 +135,7 @@ public int hashCode() {
private static final String FIELD_UNAPPLIED_ROTATION_DEGREES = Util.intToStringMaxRadix(2);
private static final String FIELD_PIXEL_WIDTH_HEIGHT_RATIO = Util.intToStringMaxRadix(3);

@SuppressWarnings("deprecation") // Including deprecated field in bundle
@UnstableApi
public Bundle toBundle() {
Bundle bundle = new Bundle();
Expand All @@ -141,6 +147,7 @@ public Bundle toBundle() {
}

/** Restores a {@code VideoSize} from a {@link Bundle}. */
@SuppressWarnings("deprecation") // Parsing deprecated field from bundle
@UnstableApi
public static VideoSize fromBundle(Bundle bundle) {
int width = bundle.getInt(FIELD_WIDTH, DEFAULT_WIDTH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public void roundTripViaBundle_ofVideoSizeUnknown_yieldsEqualInstance() {
}

@Test
@SuppressWarnings("deprecation") // Testing bundling of deprecated field.
public void roundTripViaBundle_ofArbitraryVideoSize_yieldsEqualInstance() {
VideoSize videoSize =
new VideoSize(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
import androidx.media3.common.util.TraceUtil;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import androidx.media3.container.NalUnitUtil;
import androidx.media3.decoder.CryptoConfig;
import androidx.media3.decoder.DecoderInputBuffer;
import androidx.media3.decoder.DecoderInputBuffer.InsufficientCapacityException;
Expand Down Expand Up @@ -170,7 +169,7 @@ public DecoderInitializationException(
format.sampleMimeType,
secureDecoderRequired,
mediaCodecInfo,
Util.SDK_INT >= 21 ? getDiagnosticInfoV21(cause) : null,
(cause instanceof CodecException) ? ((CodecException) cause).getDiagnosticInfo() : null,
/* fallbackDecoderInitializationException= */ null);
}

Expand Down Expand Up @@ -203,15 +202,6 @@ private DecoderInitializationException copyWithFallbackException(
fallbackException);
}

@RequiresApi(21)
@Nullable
private static String getDiagnosticInfoV21(@Nullable Throwable cause) {
if (cause instanceof CodecException) {
return ((CodecException) cause).getDiagnosticInfo();
}
return null;
}

private static String buildCustomDiagnosticInfo(int errorCode) {
String sign = errorCode < 0 ? "neg_" : "";
String packageName = "androidx.media3.exoplayer.mediacodec";
Expand Down Expand Up @@ -373,13 +363,9 @@ private static String buildCustomDiagnosticInfo(int errorCode) {
@Nullable private DecoderInitializationException preferredDecoderInitializationException;
@Nullable private MediaCodecInfo codecInfo;
private @AdaptationWorkaroundMode int codecAdaptationWorkaroundMode;
private boolean codecNeedsDiscardToSpsWorkaround;
private boolean codecNeedsFlushWorkaround;
private boolean codecNeedsSosFlushWorkaround;
private boolean codecNeedsEosFlushWorkaround;
private boolean codecNeedsEosOutputExceptionWorkaround;
private boolean codecNeedsEosBufferTimestampWorkaround;
private boolean codecNeedsMonoChannelCountWorkaround;
private boolean codecNeedsAdaptationWorkaroundBuffer;
private boolean shouldSkipAdaptationWorkaroundOutputBuffer;
private boolean codecNeedsEosPropagation;
Expand Down Expand Up @@ -898,9 +884,10 @@ && shouldContinueRendering(renderStartTimeMs)) {}
}
decoderCounters.ensureUpdated();
} catch (IllegalStateException e) {
if (isMediaCodecException(e)) {
if (e instanceof CodecException) {
onCodecError(e);
boolean isRecoverable = Util.SDK_INT >= 21 && isRecoverableMediaCodecExceptionV21(e);
boolean isRecoverable =
(e instanceof CodecException) && ((CodecException) e).isRecoverable();
if (isRecoverable) {
releaseCodec();
}
Expand Down Expand Up @@ -945,7 +932,6 @@ protected boolean flushOrReleaseCodec() {
return false;
}
if (codecDrainAction == DRAIN_ACTION_REINITIALIZE
|| codecNeedsFlushWorkaround
|| (codecNeedsSosFlushWorkaround && !codecHasOutputMediaFormat)
|| (codecNeedsEosFlushWorkaround && codecReceivedEos)) {
releaseCodec();
Expand Down Expand Up @@ -1020,13 +1006,9 @@ protected void resetCodecStateForRelease() {
codecHasOutputMediaFormat = false;
codecOperatingRate = CODEC_OPERATING_RATE_UNSET;
codecAdaptationWorkaroundMode = ADAPTATION_WORKAROUND_MODE_NEVER;
codecNeedsDiscardToSpsWorkaround = false;
codecNeedsFlushWorkaround = false;
codecNeedsSosFlushWorkaround = false;
codecNeedsEosFlushWorkaround = false;
codecNeedsEosOutputExceptionWorkaround = false;
codecNeedsEosBufferTimestampWorkaround = false;
codecNeedsMonoChannelCountWorkaround = false;
codecNeedsEosPropagation = false;
codecRegisteredOnBufferAvailableListener = false;
codecReconfigured = false;
Expand Down Expand Up @@ -1238,9 +1220,7 @@ private void initCodec(MediaCodecInfo codecInfo, @Nullable MediaCrypto crypto) t
TraceUtil.beginSection("createCodec:" + codecName);
codec = codecAdapterFactory.createAdapter(configuration);
codecRegisteredOnBufferAvailableListener =
Util.SDK_INT >= 21
&& Api21.registerOnBufferAvailableListener(
codec, new MediaCodecRendererCodecAdapterListener());
codec.registerOnBufferAvailableListener(new MediaCodecRendererCodecAdapterListener());
} finally {
TraceUtil.endSection();
}
Expand All @@ -1258,14 +1238,9 @@ private void initCodec(MediaCodecInfo codecInfo, @Nullable MediaCrypto crypto) t
this.codecOperatingRate = codecOperatingRate;
codecInputFormat = inputFormat;
codecAdaptationWorkaroundMode = codecAdaptationWorkaroundMode(codecName);
codecNeedsDiscardToSpsWorkaround =
codecNeedsDiscardToSpsWorkaround(codecName, checkNotNull(codecInputFormat));
codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
codecNeedsSosFlushWorkaround = codecNeedsSosFlushWorkaround(codecName);
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecName);
codecNeedsMonoChannelCountWorkaround = false;
codecNeedsEosPropagation =
codecNeedsEosPropagationWorkaround(codecInfo) || getCodecNeedsEosPropagation();
if (checkNotNull(codec).needsReconfiguration()) {
Expand Down Expand Up @@ -1462,13 +1437,6 @@ private boolean feedInputBuffer() throws ExoPlaybackException {
if (bufferEncrypted) {
buffer.cryptoInfo.increaseClearDataFirstSubSampleBy(adaptiveReconfigurationBytes);
}
if (codecNeedsDiscardToSpsWorkaround && !bufferEncrypted) {
NalUnitUtil.discardToSps(checkNotNull(buffer.data));
if (checkNotNull(buffer.data).position() == 0) {
return true;
}
codecNeedsDiscardToSpsWorkaround = false;
}

long presentationTimeUs = buffer.timeUs;

Expand Down Expand Up @@ -1950,7 +1918,7 @@ private boolean updateCodecOperatingRate(@Nullable Format format) throws ExoPlay
private boolean drainAndFlushCodec() {
if (codecReceivedBuffers) {
codecDrainState = DRAIN_STATE_SIGNAL_END_OF_STREAM;
if (codecNeedsFlushWorkaround || codecNeedsEosFlushWorkaround) {
if (codecNeedsEosFlushWorkaround) {
codecDrainAction = DRAIN_ACTION_REINITIALIZE;
return false;
} else {
Expand All @@ -1973,7 +1941,7 @@ private boolean drainAndFlushCodec() {
private boolean drainAndUpdateCodecDrmSessionV23() throws ExoPlaybackException {
if (codecReceivedBuffers) {
codecDrainState = DRAIN_STATE_SIGNAL_END_OF_STREAM;
if (codecNeedsFlushWorkaround || codecNeedsEosFlushWorkaround) {
if (codecNeedsEosFlushWorkaround) {
codecDrainAction = DRAIN_ACTION_REINITIALIZE;
return false;
} else {
Expand Down Expand Up @@ -2060,12 +2028,6 @@ private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs)
outputBuffer.position(outputBufferInfo.offset);
outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size);
}
if (codecNeedsEosBufferTimestampWorkaround
&& outputBufferInfo.presentationTimeUs == 0
&& (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0
&& largestQueuedPresentationTimeUs != C.TIME_UNSET) {
outputBufferInfo.presentationTimeUs = lastBufferInStreamPresentationTimeUs;
}
isDecodeOnlyOutputBuffer = outputBufferInfo.presentationTimeUs < getLastResetPositionUs();
isLastOutputBuffer =
lastBufferInStreamPresentationTimeUs != C.TIME_UNSET
Expand Down Expand Up @@ -2138,9 +2100,6 @@ private void processOutputMediaFormatChanged() {
shouldSkipAdaptationWorkaroundOutputBuffer = true;
return;
}
if (codecNeedsMonoChannelCountWorkaround) {
mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
}
codecOutputMediaFormat = mediaFormat;
codecOutputMediaFormatChanged = true;
}
Expand Down Expand Up @@ -2557,44 +2516,6 @@ private boolean isDecodeOnly(long startTimeUs, long frameTimeUs) {
/* startTimeUs= */ startTimeUs, /* frameTimeUs= */ frameTimeUs));
}

private static boolean isMediaCodecException(IllegalStateException error) {
if (Util.SDK_INT >= 21 && isMediaCodecExceptionV21(error)) {
return true;
}
StackTraceElement[] stackTrace = error.getStackTrace();
return stackTrace.length > 0 && stackTrace[0].getClassName().equals("android.media.MediaCodec");
}

@RequiresApi(21)
private static boolean isMediaCodecExceptionV21(IllegalStateException error) {
return error instanceof MediaCodec.CodecException;
}

@RequiresApi(21)
private static boolean isRecoverableMediaCodecExceptionV21(IllegalStateException error) {
if (error instanceof MediaCodec.CodecException) {
return ((MediaCodec.CodecException) error).isRecoverable();
}
return false;
}

/**
* Returns whether the decoder is known to fail when flushed.
*
* <p>If true is returned, the renderer will work around the issue by releasing the decoder and
* instantiating a new one rather than flushing the current instance.
*
* <p>See [Internal: b/8347958, b/8543366].
*
* @param name The name of the decoder.
* @return True if the decoder is known to fail when flushed.
*/
private static boolean codecNeedsFlushWorkaround(String name) {
return Util.SDK_INT == 19
&& Util.MODEL.startsWith("SM-G800")
&& ("OMX.Exynos.avc.dec".equals(name) || "OMX.Exynos.avc.dec.secure".equals(name));
}

/**
* Returns a mode that specifies when the adaptation workaround should be enabled.
*
Expand Down Expand Up @@ -2628,23 +2549,6 @@ private static boolean codecNeedsFlushWorkaround(String name) {
}
}

/**
* Returns whether the decoder is an H.264/AVC decoder known to fail if NAL units are queued
* before the codec specific data.
*
* <p>If true is returned, the renderer will work around the issue by discarding data up to the
* SPS.
*
* @param name The name of the decoder.
* @param format The {@link Format} used to configure the decoder.
* @return True if the decoder is known to fail if NAL units are queued before CSD.
*/
private static boolean codecNeedsDiscardToSpsWorkaround(String name, Format format) {
return Util.SDK_INT < 21
&& format.initializationData.isEmpty()
&& "OMX.MTK.VIDEO.DECODER.AVC".equals(name);
}

/**
* Returns whether the decoder is known to behave incorrectly if flushed prior to having output a
* {@link MediaFormat}.
Expand Down Expand Up @@ -2708,24 +2612,6 @@ private static boolean codecNeedsEosFlushWorkaround(String name) {
|| "OMX.amlogic.avc.decoder.awesome.secure".equals(name)));
}

/**
* Returns whether the decoder may output a non-empty buffer with timestamp 0 as the end of stream
* buffer.
*
* <p>See <a href="https://github.com/google/ExoPlayer/issues/5045">GitHub issue #5045</a>.
*/
private static boolean codecNeedsEosBufferTimestampWorkaround(String codecName) {
return Util.SDK_INT < 21
&& "OMX.SEC.mp3.dec".equals(codecName)
&& "samsung".equals(Util.MANUFACTURER)
&& (Util.DEVICE.startsWith("baffin")
|| Util.DEVICE.startsWith("grand")
|| Util.DEVICE.startsWith("fortuna")
|| Util.DEVICE.startsWith("gprimelte")
|| Util.DEVICE.startsWith("j2y18lte")
|| Util.DEVICE.startsWith("ms01"));
}

/**
* Returns whether the decoder may throw an {@link IllegalStateException} from {@link
* MediaCodec#dequeueOutputBuffer(MediaCodec.BufferInfo, long)} or {@link
Expand Down Expand Up @@ -2763,15 +2649,6 @@ public OutputStreamInfo(
}
}

@RequiresApi(21)
private static final class Api21 {
@DoNotInline
public static boolean registerOnBufferAvailableListener(
MediaCodecAdapter codec, MediaCodecRendererCodecAdapterListener listener) {
return codec.registerOnBufferAvailableListener(listener);
}
}

@RequiresApi(31)
private static final class Api31 {
private Api31() {}
Expand Down
Loading

0 comments on commit bb9ff30

Please sign in to comment.