diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 351ad90d04..5e35a9ca8c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,5 +1,136 @@ # Release notes +### Unreleased changes + +* Common Library: +* ExoPlayer: + * 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)). + * Reduce default values for `bufferForPlaybackMs` and + `bufferForPlaybackAfterRebufferMs` in `DefaultLoadControl` to 1000 and + 2000 ms respectively. +* Transformer: + * Update parameters of `VideoFrameProcessor.registerInputStream` and + `VideoFrameProcessor.Listener.onInputStreamRegistered` to use `Format`. + * Add support for transmuxing into alternative backwards compatible + formats. +* Extractors: +* DataSource: +* Audio: + * Do not bypass `SonicAudioProcessor` when `SpeedChangingAudioProcessor` + is configured with default parameters. +* Video: + * Rollback of using `MediaCodecAdapter` supplied pixel aspect ratio values + when provided while processing `onOutputFormatChanged` + ([#1371](https://github.com/androidx/media/pull/1371)). +* Text: +* Metadata: +* Image: +* DRM: +* Effect: + * Moved the functionality of `OverlaySettings` into + `StaticOverlaySettings`. `OverlaySettings` can be subclassed to allow + dynamic overlay settings. +* Muxers: +* IMA extension: +* Session: + * Add 'Context' as a parameter to + 'MediaButtonReceiver.shouldStartForegroundService` + ([#1887](https://github.com/androidx/media/issues/1887)). +* UI: + * Add `PlayerSurface` Composable to `media3-ui-compose` module. + * Add `PlayPauseButtonState`, `NextButtonState`, `PreviousButtonState`, + `RepeatButtonState`, `ShuffleButtonState` classes and the corresponding + `rememberPlayPauseButtonState`, `rememberNextButtonState`, + `rememberPreviousButtonState`, `rememberRepeatButtonState`, + `rememberShuffleButtonState` Composables to `media3-ui-compose` module. +* Downloads: +* OkHttp Extension: +* Cronet Extension: +* RTMP Extension: +* HLS Extension: +* DASH Extension: + * Add AC-4 Level-4 format support for DASH + ([#1898](https://github.com/androidx/media/pull/1898)). +* Smooth Streaming Extension: +* RTSP Extension: +* Decoder Extensions (FFmpeg, VP9, AV1, etc.): + * Add the MPEG-H decoder module which uses the native MPEG-H decoder + module to decode MPEG-H audio + ([#1826](https://github.com/androidx/media/pull/1826)). +* MIDI extension: +* Leanback extension: +* Cast Extension: +* Test Utilities: +* Demo app: + * Add `MinimalControls` (`PlayPauseButton`, `NextButton`, + `PreviousButton`) and `ExtraControls` (`RepeatButton`, `ShuffleButton`) + Composable UI elements to `demo-compose` utilizing + `PlayPauseButtonState`, `NextButtonState`, `PreviousButtonState`, + `RepeatButtonState`, `ShuffleButtonState`. +* Remove deprecated symbols: + * Remove deprecated `AudioMixer.create()` method. Use + `DefaultAudioMixer.Factory().create()` instead. + * Remove the following deprecated `Transformer.Builder` methods: + * `setTransformationRequest()`, use `setAudioMimeType()`, + `setVideoMimeType()`, and `setHdrMode()` instead. + * `setAudioProcessors()`, set the audio processor in an + `EditedMediaItem.Builder.setEffects()`, and pass it to + `Transformer.start()` instead. + * `setVideoEffects()`, set video effect in an + `EditedMediaItem.Builder.setEffects()`, and pass it to + `Transformer.start()` instead. + * `setRemoveAudio()`, use `EditedMediaItem.Builder.setRemoveAudio()` + to remove the audio from the `EditedMediaItem` passed to + `Transformer.start()` instead. + * `setRemoveVideo()`, use `EditedMediaItem.Builder.setRemoveVideo()` + to remove the video from the `EditedMediaItem` passed to + `Transformer.start()` instead. + * `setFlattenForSlowMotion()`, use + `EditedMediaItem.Builder.setFlattenForSlowMotion()` to flatten the + `EditedMediaItem` passed to `Transformer.start()` instead. + * `setListener()`, use `addListener()`, `removeListener()` or + `removeAllListeners()` instead. + * Remove the following deprecated `Tansformer.Listener` methods: + * `onTransformationCompleted(MediaItem)`, use + `onCompleted(Composition, ExportResult)` instead. + * `onTransformationCompleted(MediaItem, TransformationResult)`, use + `onCompleted(Composition, ExportResult)` instead. + * `onTransformationError(MediaItem, Exception)`, use + `onError(Composition, ExportResult, ExportException)` instead. + * `onTransformationError(MediaItem, TransformationException)`, use + `onError(Composition, ExportResult, ExportException)` instead. + * `onTransformationError(MediaItem, TransformationResult, + TransformationException)`, use `onError(Composition, ExportResult, + ExportException)` instead. + * `onFallbackApplied(MediaItem, TransformationRequest, + TransformationRequest)`, use `onFallbackApplied(Composition, + TransformationRequest, TransformationRequest)` instead. + * Remove deprecated `TransformationResult` class. Use `ExportResult` + instead. + * Remove deprecated `TransformationException` class. Use `ExportException` + instead. + * Remove deprecated `Transformer.PROGRESS_STATE_NO_TRANSFORMATION`. Use + `Transformer.PROGRESS_STATE_NOT_STARTED` instead. + * Remove deprecated `Transformer.setListener()`. Use + `Transformer.addListener()`, `Transformer.removeListener()` or + `Transformer.removeAllListeners()` instead. + * Remove deprecated `Transformer.startTransformation()`. Use + `Transformer.start(MediaItem, String)` instead. + * Remove deprecated `SingleFrameGlShaderProgram`. Use + `BaseGlShaderProgram` instead. + ## 1.5 ### 1.5.0 (2024-11-27) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java index c9e9884358..8b35b004f4 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java @@ -1362,17 +1362,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer ? mediaFormat.getInteger(KEY_CROP_BOTTOM) - mediaFormat.getInteger(KEY_CROP_TOP) + 1 : mediaFormat.getInteger(MediaFormat.KEY_HEIGHT); } - pixelWidthHeightRatio = format.pixelWidthHeightRatio; - if (Util.SDK_INT >= 30 - && mediaFormat != null - && mediaFormat.containsKey(MediaFormat.KEY_PIXEL_ASPECT_RATIO_WIDTH) - && mediaFormat.containsKey(MediaFormat.KEY_PIXEL_ASPECT_RATIO_HEIGHT)) { - pixelWidthHeightRatio = - (float) mediaFormat.getInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_WIDTH) - / mediaFormat.getInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_HEIGHT); - } - // The decoder applies the rotation when rendering to the surface. For 90 and 270 degree // rotations, we need to flip the width, height and pixel aspect ratio to reflect the rotation // that was applied. diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/MediaCodecVideoRendererTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/MediaCodecVideoRendererTest.java index 1954a14697..7f92d7efad 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/MediaCodecVideoRendererTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/MediaCodecVideoRendererTest.java @@ -50,7 +50,6 @@ import androidx.media3.common.MimeTypes; import androidx.media3.common.TrackGroup; import androidx.media3.common.VideoSize; import androidx.media3.common.util.Clock; -import androidx.media3.common.util.Util; import androidx.media3.decoder.CryptoInfo; import androidx.media3.exoplayer.DecoderCounters; import androidx.media3.exoplayer.ExoPlaybackException; @@ -101,7 +100,6 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.Shadows; -import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowDisplay; import org.robolectric.shadows.ShadowLooper; import org.robolectric.shadows.ShadowSystemClock; @@ -116,7 +114,6 @@ public class MediaCodecVideoRendererTest { .setSampleMimeType(MimeTypes.VIDEO_H264) .setWidth(1920) .setHeight(1080) - .setPixelWidthHeightRatio(1.0f) .build(); private static final TrackGroup TRACK_GROUP_H264 = new TrackGroup(VIDEO_H264); @@ -750,84 +747,6 @@ public class MediaCodecVideoRendererTest { new VideoSize(VIDEO_H264.width, VIDEO_H264.height, VIDEO_H264.pixelWidthHeightRatio)); } - @Config(minSdk = 30) - @Test - public void - render_withMediaCodecModifyingPixelAspectRatioWidthHeight_sendsVideoSizeChangeWithMediaFormatValues() - throws Exception { - MediaCodecAdapter.Factory codecAdapterFactory = - configuration -> - new ForwardingSynchronousMediaCodecAdapter( - new SynchronousMediaCodecAdapter.Factory().createAdapter(configuration)) { - @Override - public MediaFormat getOutputFormat() { - MediaFormat mediaFormat = adapter.getOutputFormat(); - if (Util.SDK_INT >= 30) { - // Change to 9:16 Ratio - mediaFormat.setInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_WIDTH, 9); - mediaFormat.setInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_HEIGHT, 16); - } - return mediaFormat; - } - }; - MediaCodecVideoRenderer mediaCodecVideoRendererWithCustomAdapter = - new MediaCodecVideoRenderer( - ApplicationProvider.getApplicationContext(), - codecAdapterFactory, - mediaCodecSelector, - /* allowedJoiningTimeMs= */ 0, - /* enableDecoderFallback= */ false, - /* eventHandler= */ new Handler(testMainLooper), - /* eventListener= */ eventListener, - /* maxDroppedFramesToNotify= */ 1) { - @Override - protected @Capabilities int supportsFormat( - MediaCodecSelector mediaCodecSelector, Format format) { - return RendererCapabilities.create(C.FORMAT_HANDLED); - } - }; - mediaCodecVideoRendererWithCustomAdapter.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT); - mediaCodecVideoRendererWithCustomAdapter.handleMessage( - Renderer.MSG_SET_VIDEO_OUTPUT, new Surface(new SurfaceTexture(/* texName= */ 0))); - FakeSampleStream fakeSampleStream = - new FakeSampleStream( - new DefaultAllocator(/* trimOnReset= */ true, /* individualAllocationSize= */ 1024), - /* mediaSourceEventDispatcher= */ null, - DrmSessionManager.DRM_UNSUPPORTED, - new DrmSessionEventListener.EventDispatcher(), - /* initialFormat= */ VIDEO_H264, - ImmutableList.of( - oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM)); - fakeSampleStream.writeData(/* startPositionUs= */ 0); - mediaCodecVideoRendererWithCustomAdapter.enable( - RendererConfiguration.DEFAULT, - new Format[] {VIDEO_H264}, - fakeSampleStream, - /* positionUs= */ 0, - /* joining= */ false, - /* mayRenderStartOfStream= */ true, - /* startPositionUs= */ 0, - /* offsetUs= */ 0, - new MediaSource.MediaPeriodId(new Object())); - mediaCodecVideoRendererWithCustomAdapter.setCurrentStreamFinal(); - mediaCodecVideoRendererWithCustomAdapter.start(); - - int positionUs = 0; - do { - mediaCodecVideoRendererWithCustomAdapter.render( - positionUs, SystemClock.elapsedRealtime() * 1000); - positionUs += 10; - } while (!mediaCodecVideoRendererWithCustomAdapter.isEnded()); - shadowOf(testMainLooper).idle(); - - verify(eventListener) - .onVideoSizeChanged( - new VideoSize( - VIDEO_H264.width, - VIDEO_H264.height, - /* pixelWidthHeightRatio= */ VIDEO_H264.pixelWidthHeightRatio * (9.0f / 16.0f))); - } - @Test public void render_withMultipleQueued_sendsVideoSizeChangedWithCorrectPixelAspectRatioWhenMultipleQueued() @@ -1984,7 +1903,7 @@ public class MediaCodecVideoRendererTest { private abstract static class ForwardingSynchronousMediaCodecAdapter implements MediaCodecAdapter { - protected final MediaCodecAdapter adapter; + private final MediaCodecAdapter adapter; ForwardingSynchronousMediaCodecAdapter(MediaCodecAdapter adapter) { this.adapter = adapter;