Move last-buffer timestamp fix to better location

PiperOrigin-RevId: 340915538
This commit is contained in:
olly 2020-11-05 21:19:20 +00:00 committed by Andrew Lewis
parent 477eae3c57
commit 1fb675e876
2 changed files with 50 additions and 62 deletions

View file

@ -94,7 +94,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
private int codecMaxInputSize;
private boolean codecNeedsDiscardChannelsWorkaround;
private boolean codecNeedsEosBufferTimestampWorkaround;
/** Codec used for DRM decryption only in passthrough and offload. */
@Nullable private Format decryptOnlyCodecFormat;
@ -318,7 +317,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
float codecOperatingRate) {
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
MediaFormat mediaFormat =
getMediaFormat(format, codecInfo.codecMimeType, codecMaxInputSize, codecOperatingRate);
codecAdapter.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
@ -571,13 +569,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
Format format)
throws ExoPlaybackException {
checkNotNull(buffer);
if (codec != null
&& codecNeedsEosBufferTimestampWorkaround
&& bufferPresentationTimeUs == 0
&& (bufferFlags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0
&& getLargestQueuedPresentationTimeUs() != C.TIME_UNSET) {
bufferPresentationTimeUs = getLargestQueuedPresentationTimeUs();
}
if (decryptOnlyCodecFormat != null
&& (bufferFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
@ -782,24 +773,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|| Util.DEVICE.startsWith("heroqlte"));
}
/**
* 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"));
}
private final class AudioSinkListener implements AudioSink.Listener {
@Override

View file

@ -321,6 +321,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private boolean codecNeedsSosFlushWorkaround;
private boolean codecNeedsEosFlushWorkaround;
private boolean codecNeedsEosOutputExceptionWorkaround;
private boolean codecNeedsEosBufferTimestampWorkaround;
private boolean codecNeedsMonoChannelCountWorkaround;
private boolean codecNeedsAdaptationWorkaroundBuffer;
private boolean shouldSkipAdaptationWorkaroundOutputBuffer;
@ -898,6 +899,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codecNeedsSosFlushWorkaround = false;
codecNeedsEosFlushWorkaround = false;
codecNeedsEosOutputExceptionWorkaround = false;
codecNeedsEosBufferTimestampWorkaround = false;
codecNeedsMonoChannelCountWorkaround = false;
codecNeedsEosPropagation = false;
codecReconfigured = false;
@ -1089,6 +1091,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codecNeedsSosFlushWorkaround = codecNeedsSosFlushWorkaround(codecName);
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecName);
codecNeedsMonoChannelCountWorkaround =
codecNeedsMonoChannelCountWorkaround(codecName, codecInputFormat);
codecNeedsEosPropagation =
@ -1746,6 +1749,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
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 = largestQueuedPresentationTimeUs;
}
isDecodeOnlyOutputBuffer = isDecodeOnlyBuffer(outputBufferInfo.presentationTimeUs);
isLastOutputBuffer =
lastBufferInStreamPresentationTimeUs == outputBufferInfo.presentationTimeUs;
@ -1928,18 +1937,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
pendingOutputEndOfStream = true;
}
/** Returns the largest queued input presentation time, in microseconds. */
protected final long getLargestQueuedPresentationTimeUs() {
return largestQueuedPresentationTimeUs;
}
/**
* Returns the start position of the output {@link SampleStream}, in renderer time microseconds.
*/
protected final long getOutputStreamStartPositionUs() {
return outputStreamStartPositionUs;
}
/**
* Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link
* #processOutputBuffer(long, long, MediaCodec, ByteBuffer, int, int, int, long, boolean, boolean,
@ -2272,6 +2269,23 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
&& "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}.
*
* <p>If true is returned, the renderer will work around the issue by instantiating a new decoder
* when this case occurs.
*
* <p>See [Internal: b/141097367].
*
* @param name The name of the decoder.
* @return True if the decoder is known to behave incorrectly if flushed prior to having output a
* {@link MediaFormat}. False otherwise.
*/
private static boolean codecNeedsSosFlushWorkaround(String name) {
return Util.SDK_INT == 29 && "c2.android.aac.decoder".equals(name);
}
/**
* Returns whether the decoder is known to handle the propagation of the {@link
* MediaCodec#BUFFER_FLAG_END_OF_STREAM} flag incorrectly on the host device.
@ -2316,12 +2330,30 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
/**
* Returns whether the decoder may throw an {@link IllegalStateException} from
* {@link MediaCodec#dequeueOutputBuffer(MediaCodec.BufferInfo, long)} or
* {@link MediaCodec#releaseOutputBuffer(int, boolean)} after receiving an input
* buffer with {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} set.
* <p>
* See [Internal: b/17933838].
* 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
* MediaCodec#releaseOutputBuffer(int, boolean)} after receiving an input buffer with {@link
* MediaCodec#BUFFER_FLAG_END_OF_STREAM} set.
*
* <p>See [Internal: b/17933838].
*
* @param name The name of the decoder.
* @return True if the decoder may throw an exception after receiving an end-of-stream buffer.
@ -2348,21 +2380,4 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return Util.SDK_INT <= 18 && format.channelCount == 1
&& "OMX.MTK.AUDIO.DECODER.MP3".equals(name);
}
/**
* Returns whether the decoder is known to behave incorrectly if flushed prior to having output a
* {@link MediaFormat}.
*
* <p>If true is returned, the renderer will work around the issue by instantiating a new decoder
* when this case occurs.
*
* <p>See [Internal: b/141097367].
*
* @param name The name of the decoder.
* @return True if the decoder is known to behave incorrectly if flushed prior to having output a
* {@link MediaFormat}. False otherwise.
*/
private static boolean codecNeedsSosFlushWorkaround(String name) {
return Util.SDK_INT == 29 && "c2.android.aac.decoder".equals(name);
}
}