diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c0df1bca68..34521aa05b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -103,6 +103,8 @@ [#5658](https://github.com/google/ExoPlayer/issues/5658)). * Pass the codec output `MediaFormat` to `VideoFrameMetadataListener`. * Deprecate the GVR extension. +* Fix the start of audio getting truncated when transitioning to a new + item in a playlist of opus streams. ### 2.10.6 (2019-10-17) ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index c436d2b06d..34eb2a8fe4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -426,13 +426,34 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media } else if (codecInfo.isSeamlessAdaptationSupported( oldFormat, newFormat, /* isNewFormatComplete= */ true)) { return KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION; - } else if (areCodecConfigurationCompatible(oldFormat, newFormat)) { + } else if (canKeepCodecWithFlush(oldFormat, newFormat)) { return KEEP_CODEC_RESULT_YES_WITH_FLUSH; } else { return KEEP_CODEC_RESULT_NO; } } + /** + * Returns whether the codec can be flushed and reused when switching to a new format. Reuse is + * generally possible when the codec would be configured in an identical way after the format + * change (excluding {@link MediaFormat#KEY_MAX_INPUT_SIZE} and configuration that does not come + * from the {@link Format}). + * + * @param oldFormat The first format. + * @param newFormat The second format. + * @return Whether the codec can be flushed and reused when switching to a new format. + */ + protected boolean canKeepCodecWithFlush(Format oldFormat, Format newFormat) { + // Flush and reuse the codec if the audio format and initialization data matches. For Opus, we + // don't flush and reuse the codec because the decoder may discard samples after flushing, which + // would result in audio being dropped just after a stream change (see [Internal: b/143450854]). + return Util.areEqual(oldFormat.sampleMimeType, newFormat.sampleMimeType) + && oldFormat.channelCount == newFormat.channelCount + && oldFormat.sampleRate == newFormat.sampleRate + && oldFormat.initializationDataEquals(newFormat) + && !MimeTypes.AUDIO_OPUS.equals(oldFormat.sampleMimeType); + } + @Override public MediaClock getMediaClock() { return this; @@ -811,24 +832,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media return format.maxInputSize; } - /** - * Returns whether two {@link Format}s will cause the same codec to be configured in an identical - * way, excluding {@link MediaFormat#KEY_MAX_INPUT_SIZE} and configuration that does not come from - * the {@link Format}. - * - * @param oldFormat The first format. - * @param newFormat The second format. - * @return Whether the two formats will cause a codec to be configured in an identical way, - * excluding {@link MediaFormat#KEY_MAX_INPUT_SIZE} and configuration that does not come from - * the {@link Format}. - */ - protected boolean areCodecConfigurationCompatible(Format oldFormat, Format newFormat) { - return Util.areEqual(oldFormat.sampleMimeType, newFormat.sampleMimeType) - && oldFormat.channelCount == newFormat.channelCount - && oldFormat.sampleRate == newFormat.sampleRate - && oldFormat.initializationDataEquals(newFormat); - } - /** * Returns the framework {@link MediaFormat} that can be used to configure a {@link MediaCodec} * for decoding the given {@link Format} for playback. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index 25b1473263..601ddf9b9c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -384,13 +384,13 @@ public final class MediaCodecInfo { /** * Whether the decoder supports video with a given width, height and frame rate. - *
- * Must not be called if the device SDK version is less than 21. + * + *
Must not be called if the device SDK version is less than 21. * * @param width Width in pixels. * @param height Height in pixels. - * @param frameRate Optional frame rate in frames per second. Ignored if set to - * {@link Format#NO_VALUE} or any value less than or equal to 0. + * @param frameRate Optional frame rate in frames per second. Ignored if set to {@link + * Format#NO_VALUE} or any value less than or equal to 0. * @return Whether the decoder supports video with the given width, height and frame rate. */ @TargetApi(21)