diff --git a/RELEASENOTES.md b/RELEASENOTES.md index bfc338cc0f..38d9b0a010 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -11,6 +11,22 @@ This release includes the following changes since the * Add a setter to `SntpClient` to set the max elapsed time since the last update after which the client is re-initialized ([#1794](https://github.com/androidx/media/pull/1794)). + * Consider language when selecting a video track. By default select a + 'main' video track that matches the language of the selected audio + track, if available. Explicit video language preferences can be + expressed with + `TrackSelectionParameters.Builder.setPreferredVideoLanguage(s)`. + * Add `selectedAudioLanguage` parameter to + `DefaultTrackSelector.selectVideoTrack()` method. + * Add `retryCount` parameter to `MediaSourceEventListener.onLoadStarted` + and corresponding `MediaSourceEventListener.EventDispatcher` methods. + * Fix bug where playlist items or periods in multi-period DASH streams + with durations that don't match the actual content could cause frame + freezes at the end of the item + ([#1698](https://github.com/androidx/media/issues/1698)). +* Transformer: + * Update parameters of `VideoFrameProcessor.registerInputStream` and + `VideoFrameProcessor.Listener.onInputStreamRegistered` to use `Format`. * Extractors: * Fix media duration parsing in `mdhd` box of MP4 files to handle `-1` values ([#1819](https://github.com/androidx/media/issues/1819)). diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java index aadbe5d945..d8ae700301 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java @@ -1732,28 +1732,31 @@ public final class DefaultAudioSink implements AudioSink { long playoutDurationSinceLastCheckpointUs = positionUs - mediaPositionParameters.audioTrackPositionUs; + long estimatedMediaDurationSinceLastCheckpointUs = + Util.getMediaDurationForPlayoutDuration( + playoutDurationSinceLastCheckpointUs, mediaPositionParameters.playbackParameters.speed); if (mediaPositionParametersCheckpoints.isEmpty()) { - long mediaDurationSinceLastCheckpointUs = + long actualMediaDurationSinceLastCheckpointUs = audioProcessorChain.getMediaDuration(playoutDurationSinceLastCheckpointUs); - return mediaPositionParameters.mediaTimeUs + mediaDurationSinceLastCheckpointUs; + long currentMediaPositionUs = + mediaPositionParameters.mediaTimeUs + actualMediaDurationSinceLastCheckpointUs; + long mediaDurationEstimateDiffUs = + actualMediaDurationSinceLastCheckpointUs - estimatedMediaDurationSinceLastCheckpointUs; + if (Math.abs(mediaDurationEstimateDiffUs) > 10000) { + // Update current media position parameters if the estimate drifted from the actual + // media duration created by the audio processor chain. This ensures the estimate is always + // fairly accurate and we can rely on it once we enter the else-branch below. + mediaPositionParameters = + new MediaPositionParameters( + mediaPositionParameters.playbackParameters, currentMediaPositionUs, positionUs); + } + return currentMediaPositionUs; } else { // The processor chain has been configured with new parameters, but we're still playing audio // that was processed using previous parameters. We can't scale the playout duration using the // processor chain in this case, so we fall back to scaling using the previous parameters' - // target speed instead. Since the processor chain may not have achieved the target speed - // precisely, we scale the duration to the next checkpoint (which will always be small) rather - // than the duration from the previous checkpoint (which may be arbitrarily large). This - // limits the amount of error that can be introduced due to a difference between the target - // and actual speeds. - MediaPositionParameters nextMediaPositionParameters = - mediaPositionParametersCheckpoints.getFirst(); - long playoutDurationUntilNextCheckpointUs = - nextMediaPositionParameters.audioTrackPositionUs - positionUs; - long mediaDurationUntilNextCheckpointUs = - Util.getMediaDurationForPlayoutDuration( - playoutDurationUntilNextCheckpointUs, - mediaPositionParameters.playbackParameters.speed); - return nextMediaPositionParameters.mediaTimeUs - mediaDurationUntilNextCheckpointUs; + // target speed instead. + return mediaPositionParameters.mediaTimeUs + estimatedMediaDurationSinceLastCheckpointUs; } }