diff --git a/RELEASENOTES.md b/RELEASENOTES.md index aac69e1438..0f0af429d2 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,6 +1,11 @@ # Release notes # -### 2.10.6 (2019-10-18) ### +### 2.10.7 ### + +* 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) ### * Add `Player.onPlaybackSuppressionReasonChanged` to allow listeners to detect playbacks suppressions (e.g. transient audio focus loss) directly 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 f10f45ecf3..36db657956 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 @@ -434,13 +434,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; @@ -818,24 +839,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 8581f279d0..f5c6926c30 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 @@ -328,13 +328,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)