mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Move last-buffer timestamp fix to better location
PiperOrigin-RevId: 340915538
This commit is contained in:
parent
477eae3c57
commit
1fb675e876
2 changed files with 50 additions and 62 deletions
|
|
@ -94,7 +94,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
|
|
||||||
private int codecMaxInputSize;
|
private int codecMaxInputSize;
|
||||||
private boolean codecNeedsDiscardChannelsWorkaround;
|
private boolean codecNeedsDiscardChannelsWorkaround;
|
||||||
private boolean codecNeedsEosBufferTimestampWorkaround;
|
|
||||||
/** Codec used for DRM decryption only in passthrough and offload. */
|
/** Codec used for DRM decryption only in passthrough and offload. */
|
||||||
@Nullable private Format decryptOnlyCodecFormat;
|
@Nullable private Format decryptOnlyCodecFormat;
|
||||||
|
|
||||||
|
|
@ -318,7 +317,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
float codecOperatingRate) {
|
float codecOperatingRate) {
|
||||||
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
|
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
|
||||||
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
|
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
|
||||||
codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
|
|
||||||
MediaFormat mediaFormat =
|
MediaFormat mediaFormat =
|
||||||
getMediaFormat(format, codecInfo.codecMimeType, codecMaxInputSize, codecOperatingRate);
|
getMediaFormat(format, codecInfo.codecMimeType, codecMaxInputSize, codecOperatingRate);
|
||||||
codecAdapter.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
|
codecAdapter.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
|
||||||
|
|
@ -571,13 +569,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
Format format)
|
Format format)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
checkNotNull(buffer);
|
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
|
if (decryptOnlyCodecFormat != null
|
||||||
&& (bufferFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
&& (bufferFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
||||||
|
|
@ -782,24 +773,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
|| Util.DEVICE.startsWith("heroqlte"));
|
|| 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 {
|
private final class AudioSinkListener implements AudioSink.Listener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
private boolean codecNeedsSosFlushWorkaround;
|
private boolean codecNeedsSosFlushWorkaround;
|
||||||
private boolean codecNeedsEosFlushWorkaround;
|
private boolean codecNeedsEosFlushWorkaround;
|
||||||
private boolean codecNeedsEosOutputExceptionWorkaround;
|
private boolean codecNeedsEosOutputExceptionWorkaround;
|
||||||
|
private boolean codecNeedsEosBufferTimestampWorkaround;
|
||||||
private boolean codecNeedsMonoChannelCountWorkaround;
|
private boolean codecNeedsMonoChannelCountWorkaround;
|
||||||
private boolean codecNeedsAdaptationWorkaroundBuffer;
|
private boolean codecNeedsAdaptationWorkaroundBuffer;
|
||||||
private boolean shouldSkipAdaptationWorkaroundOutputBuffer;
|
private boolean shouldSkipAdaptationWorkaroundOutputBuffer;
|
||||||
|
|
@ -898,6 +899,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
codecNeedsSosFlushWorkaround = false;
|
codecNeedsSosFlushWorkaround = false;
|
||||||
codecNeedsEosFlushWorkaround = false;
|
codecNeedsEosFlushWorkaround = false;
|
||||||
codecNeedsEosOutputExceptionWorkaround = false;
|
codecNeedsEosOutputExceptionWorkaround = false;
|
||||||
|
codecNeedsEosBufferTimestampWorkaround = false;
|
||||||
codecNeedsMonoChannelCountWorkaround = false;
|
codecNeedsMonoChannelCountWorkaround = false;
|
||||||
codecNeedsEosPropagation = false;
|
codecNeedsEosPropagation = false;
|
||||||
codecReconfigured = false;
|
codecReconfigured = false;
|
||||||
|
|
@ -1089,6 +1091,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
codecNeedsSosFlushWorkaround = codecNeedsSosFlushWorkaround(codecName);
|
codecNeedsSosFlushWorkaround = codecNeedsSosFlushWorkaround(codecName);
|
||||||
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
|
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
|
||||||
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
|
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
|
||||||
|
codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecName);
|
||||||
codecNeedsMonoChannelCountWorkaround =
|
codecNeedsMonoChannelCountWorkaround =
|
||||||
codecNeedsMonoChannelCountWorkaround(codecName, codecInputFormat);
|
codecNeedsMonoChannelCountWorkaround(codecName, codecInputFormat);
|
||||||
codecNeedsEosPropagation =
|
codecNeedsEosPropagation =
|
||||||
|
|
@ -1746,6 +1749,12 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
outputBuffer.position(outputBufferInfo.offset);
|
outputBuffer.position(outputBufferInfo.offset);
|
||||||
outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size);
|
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);
|
isDecodeOnlyOutputBuffer = isDecodeOnlyBuffer(outputBufferInfo.presentationTimeUs);
|
||||||
isLastOutputBuffer =
|
isLastOutputBuffer =
|
||||||
lastBufferInStreamPresentationTimeUs == outputBufferInfo.presentationTimeUs;
|
lastBufferInStreamPresentationTimeUs == outputBufferInfo.presentationTimeUs;
|
||||||
|
|
@ -1928,18 +1937,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
pendingOutputEndOfStream = true;
|
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
|
* Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link
|
||||||
* #processOutputBuffer(long, long, MediaCodec, ByteBuffer, int, int, int, long, boolean, boolean,
|
* #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);
|
&& "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
|
* 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.
|
* 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
|
* Returns whether the decoder may output a non-empty buffer with timestamp 0 as the end of stream
|
||||||
* {@link MediaCodec#dequeueOutputBuffer(MediaCodec.BufferInfo, long)} or
|
* buffer.
|
||||||
* {@link MediaCodec#releaseOutputBuffer(int, boolean)} after receiving an input
|
*
|
||||||
* buffer with {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} set.
|
* <p>See <a href="https://github.com/google/ExoPlayer/issues/5045">GitHub issue #5045</a>.
|
||||||
* <p>
|
*/
|
||||||
* See [Internal: b/17933838].
|
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.
|
* @param name The name of the decoder.
|
||||||
* @return True if the decoder may throw an exception after receiving an end-of-stream buffer.
|
* @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
|
return Util.SDK_INT <= 18 && format.channelCount == 1
|
||||||
&& "OMX.MTK.AUDIO.DECODER.MP3".equals(name);
|
&& "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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue