Commit graph

530 commits

Author SHA1 Message Date
ibaker
b5a1efdbce ForwardingTimeline: Implement & finalize some methods
`equals`, `hashCode`, and `getPeriodByUid` are correctly implemented on
`Timeline`. Overriding these in a way that maintains correctness is
fiddly, so this CL prevents that for the 'simple' case of subclasses of
`ForwardingTimeline`. Implementations of `Timeline` that need to
override these methods for performance should extend `Timeline` or
`AbstractConcatenatedTimeline` instead of `ForwardingTimeline`.

PiperOrigin-RevId: 703035721
2024-12-05 02:24:19 -08:00
ibaker
92e0b5978f Add ForwardingTimelineTest
PiperOrigin-RevId: 703029260
2024-12-05 01:59:07 -08:00
rohks
e927d7b986 Fix ReplacingCuesResolver.discardCuesBeforeTimeUs to retain active cue
The method previously discarded the cue that was active at `timeUs`,
meaning it had started before but had not ended by `timeUs`.

Issue: androidx/media#1939

#cherrypick

PiperOrigin-RevId: 702707611
2024-12-04 06:51:12 -08:00
ibaker
876abe315b Increase library target SDK to 31
This only affects the default SDK level that Robolectric tests run at.
Also upgrade the Robolectric version to 4.14.1 to pick up
4f32042afe
which is needed for async `ShadowMediaCodec` support (the default in
ExoPlayer from API 31+).

Some tests fail on Robolectric at API 31. This change configures them to
continue running on API 30, so the failures can be investigated and
fixed in follow-up changes.

PiperOrigin-RevId: 702357124
2024-12-03 08:57:53 -08:00
tianyifeng
148641f049 Move BasePreloadManager.Listener to a top level PreloadManagerListener
PiperOrigin-RevId: 702351887
2024-12-03 08:38:35 -08:00
ibaker
18d156fe3c Configure ProgressiveMediaSource with a Format for subtitles
This means we can complete preparation (and trigger track selection)
before opening a `DataSource`, which then means we only end up loading
the data for a selected subtitle track (instead of all tracks as
currently happens).

By making preparation trivial in this case (with no reasonable cause
of error), we can also remove the `suppressPrepareError` option added in
b3290eff10.

This change also fixes the implementation of
`ProgressiveMediaPeriod.maybeStartDeferredRetry` to only short-circuit
return `false` if the chosen track is not audio or video **and** there
is at least one audio or video track in this period.

Issue: androidx/media#1721
PiperOrigin-RevId: 702275968
2024-12-03 03:40:49 -08:00
ibaker
25c927e9f3 Standardize ForwardingXXX tests
Add missing ones for `ForwardingExtractorInput` and `ForwardingSeekMap`.
`ForwardingTimeline` is a bit more fiddly, so it's left for a follow-up
change.

PiperOrigin-RevId: 701988492
2024-12-02 09:12:53 -08:00
kimvde
852091f2d9 Implement DefaultVideoSink.isEnded
To do that, I had to add VideoFrameRenderControl.signalEndOfInput() and
isEnded() to match the VideoSink interface.

PiperOrigin-RevId: 700957098
2024-11-28 02:27:50 -08:00
ibaker
46578ee0a6 MP3: Use bytes field from VBRI frame instead of deriving from ToC
The previous code assumed that the `VBRI` Table of Contents (ToC)
covers all the MP3 data in the file. In a file with an invalid VBRI ToC
where this isn't the case, this results in playback silently stopping
mid-playback (and either advancing to the next item, or continuing to
count up the playback clock forever). This change considers the `bytes`
field to determine the end of the MP3 data, in addition to deriving it
from the ToC. If they disagree we log a warning and take the max value.
This is because we handle accidentally reading non-MP3 data at the end
(or hitting EoF) better than stopping reading valid MP3 data partway
through.

Issue: androidx/media#1904

#cherrypick

PiperOrigin-RevId: 700319250
2024-11-26 06:18:29 -08:00
michaelkatz
5282fe3125 Rollback of 854566dbfe
PiperOrigin-RevId: 698730105
2024-11-21 04:29:19 -08:00
kimvde
8be2556efd Implement DefaultVideoSink.setStreamTimestampInfo
To do this, refactor stream start position handling so that
VideoFrameRenderControl is only passed a start position when it should
be applied, and therefore doesn't need to take a timestamp associated
with each start position anymore

PiperOrigin-RevId: 697544416
2024-11-18 02:01:52 -08:00
tianyifeng
0143884cd7 Deflake the DefaultPreloadManagerTest
From [ the last change in `DefaultPreloadManagerTest`](2b54b1ebbe), the preloadManager began to use a separate `preloadThread` in `release_returnZeroCount_sourcesAndRendererCapabilitiesListReleased`, which unveils a bug in `PreloadMediaSource`. When `PreloadMediaSource.releasePreloadMediaSource` is called, `preloadHandler` will post a `Runnable` on the preload looper to release the internal resources. Before this `Runnable` is executed, it is possible that the [`stopPreloading`](https://github.com/androidx/media/blob/main/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/preload/PreloadMediaSource.java#L442) method is executed just as the result of preloading has completed. This is expected to remove the posted `Runnable`s for further preloading, however, the posted `Runnable` for releasing will also be removed from the message queue.

Ideally we should use `postDelayed(runnable, token, delayMillis)` to post the runnables so that the token will be useful to identify which messages to remove in `removeCallbacksAndMessages(token)`, but that `postDelayed` method is only available from API 28. So in this change we are using a separate handler for releasing, and then the call of `preloadHandler.removeCallbacksAndMessages` won't impact the runnable for releasing.

#cherrypick

PiperOrigin-RevId: 696894483
2024-11-15 08:22:54 -08:00
bachinger
1af0b5b432 Add handleContentTimelineChanged to AdsLoader
The new callback allows an app to read data from the content
timeline to populate the `AdPlaybackState`. To avoid a deadlock
between the `AdMediaSource` waiting for the `AdPlaybackState` and
the app waiting for the content `Timeline`, a boolean flag
`useLazyContentSourcePreparation` is introduced to tell the
`AdsMediaSource` to prepare the content source immediately
to make the `Timeline` available.

A unit test verifies that in none of the cases (lazy preparation or
immediate preparation) a `Timeline` without ad data is leaked to the
caller. This ensures that in the case of a preroll, the player won't
initially and accidentally read content media data before starting to
load the preroll ad. While the content source is prepared early, no
content media period must be created before the preroll starts.

PiperOrigin-RevId: 696885392
2024-11-15 07:49:41 -08:00
kimvde
64e92cb8e1 Various refactorings in VideoFrameRenderControl
- Rename a few methods/variable to improve readability.
- Refactor how video size changes are tracked. This will simplify the
  upcoming logic to refactor the timestamp logic in
  VideoFrameRenderControl because we will use the same logic for
  outputVideoSize and for outputStreamStartPositionUs.

PiperOrigin-RevId: 696026515
2024-11-13 01:15:58 -08:00
michaelkatz
0c982a7994 Fix error where non-enabled renderers were set to final
If the renderer has no stream, then it should not be called with `setCurrentStreamFinal` on it.

PiperOrigin-RevId: 695284225
2024-11-11 04:35:25 -08:00
michaelkatz
b329806859 Fix unit test that confirms AAC_LC passthrough is unsupported
PiperOrigin-RevId: 694494792
2024-11-08 07:49:11 -08:00
tianyifeng
2b54b1ebbe Release internal components on preload thread in DefaultPreloadManager
The `RendererCapabilities` and `TrackSelector` objects are accessed on the preload thread during the preloading, when releasing them, they need to be released on the same thread. Otherwise, it is possible that they have already released on the application thread, while the PreloadMediaSource still tries to access them on the preload thread before the source is released.

#cherrypick

PiperOrigin-RevId: 694173131
2024-11-07 10:50:22 -08:00
tonihei
5336d71c22 Add TestPlayerRunHelper run(player).untilFullyBuffered
This simplifies some common test setup steps that rely on
a fully buffered player before making further test progress.

PiperOrigin-RevId: 693651493
2024-11-06 02:45:51 -08:00
rohks
261ca326c5 Move MediaExtractorCompatTest from test/ to androidTest/
The test has been moved to an instrumentation test as it relies on APIs that vary by SDK version. Robolectric’s emulation lacks sufficient realism in some cases, which impacts test accuracy. By using an instrumentation test, we ensure that the tests run in a real Android environment, providing reliable results for SDK-dependent APIs.

PiperOrigin-RevId: 692933259
2024-11-04 05:42:45 -08:00
ibaker
aebf822c3c Enable lint errors in exoplayer tests
Follow-up to 76db936d68

PiperOrigin-RevId: 692925617
2024-11-04 05:08:34 -08:00
rohks
d8ad18383d Optimize sample metadata handling in MediaExtractorCompat
Restructured sample metadata management in `MediaExtractorCompat` to maintain a queue of `SampleMetadata` objects, each containing `timeUs`, `flags`, `size`, and `trackIndex`, rather than storing only track indices.

Introduced a pooling mechanism for `SampleMetadata` to reduce object allocation and improve memory efficiency. The new `SampleMetaDataQueue` centralizes metadata for easier access and management, eliminating the need to allocate a buffer or peek into the `SampleQueue` to retrieve sample metadata.

This change does not change existing behavior, it optimizes the internal structure, and existing tests already verify the relevant APIs.

PiperOrigin-RevId: 692285581
2024-11-01 14:07:11 -07:00
ibaker
b5db8a6cbe Fix empty LoadEventInfo.uri passed to onLoadStarted
This affects both `AnalyticsListener` and `MediaSourceEventListener`

This was introduced by d051b4b993

Also fix a missing 'load started' event for HLS media playlists (this
was also introduced by d051b4b993).

PiperOrigin-RevId: 691580183
2024-10-30 15:52:48 -07:00
rohks
df07fa35d8 Populate MediaFormat.KEY_DURATION in MediaExtractorCompat
Previously, `getTrackFormat()` in `MediaExtractorCompat` returned a `MediaFormat` without setting `MediaFormat.KEY_DURATION`. With this change:

- `MediaFormat.KEY_DURATION` is set based on the track's duration, if available.
- If the track duration is unset, the duration from the seek map is used as a fallback.
- When neither duration is set, `MediaFormat.KEY_DURATION` remains unset.

This ensures that `MediaFormat.KEY_DURATION` is populated when possible, enhancing duration information availability.

PiperOrigin-RevId: 691395114
2024-10-30 06:29:47 -07:00
kimvde
14094b5094 Fix offset passed to VideoFrameReleaseControl
In some cases, the streamOffsetUs was passed to
VideoFrameReleaseControl.getFrameReleaseAction() but it should be the
streamStartPositionUs.

PiperOrigin-RevId: 691040172
2024-10-29 09:04:35 -07:00
Ian Baker
683a5b8403 Fix review comments 2024-10-25 10:58:48 +01:00
Ian Baker
7cf500bc2d Fix compilation of MergingMediaSourceTest 2024-10-25 10:58:29 +01:00
Ian Baker
d3298391b2 Fix onLoadStarted event accumulation in DefaultAnalyticsCollectorTest 2024-10-25 10:58:29 +01:00
Colin Kho
5581529bfb Use long as test constant for DefaultAnalyticsCollectorTest 2024-10-25 10:58:28 +01:00
Colin Kho
16f65cee58 Deprecate onLoadStarted w/o retry count on AnalyticsListener 2024-10-25 10:58:28 +01:00
Colin Kho
5dbe1efa9e Treat onLoadStarted with retryCount to be a new method rather than redirect calls 2024-10-25 10:58:28 +01:00
Colin Kho
8adcd35c75 Incorporate MediaSourceEventListener.onLoadStarted with retryCount parameter with backward compatibility 2024-10-25 10:58:25 +01:00
michaelkatz
2f198c4c06 Implement getDurationToProgressUs for DecoderAudioRenderer
Add `DecoderAudioRenderer.getDurationToProgressUs()` so that `ExoPlayer`, if set with `experimentalSetDynamicSchedulingEnabled()`, will dynamically schedule its main work loop to when the `DecoderAudioRenderer` can make progress.

PiperOrigin-RevId: 689377247
2024-10-24 07:46:42 -07:00
kimvde
d25a423888 Remove unused parameter from VideoFrameRenderControl.FrameRenderer
PiperOrigin-RevId: 689281689
2024-10-24 01:27:20 -07:00
ibaker
7b66209bca Add missing overrides in DefaultTrackSelector.Parameters.Builder
Also add a test for this to avoid missing any others in future. Also
flesh out the existing test for the deprecated builder, to assert the
return type is correctly updated.

PiperOrigin-RevId: 688948768
2024-10-23 07:08:03 -07:00
ibaker
b04b37074b Add video language to DefaultTrackSelector
PiperOrigin-RevId: 688155680
2024-10-21 09:02:19 -07:00
rohks
0ecd35e24c Improve error logging for IllegalClippingException
Added start and end time details to the error message for `REASON_START_EXCEEDS_END`, helping to debug cases where the start time exceeds the end time.

PiperOrigin-RevId: 688117440
2024-10-21 06:45:35 -07:00
tonihei
513ebf67b7 Add initial playWhenReady setting and tests
Also includes a new test for a similar logic that already exists
for speed changes.
2024-10-18 18:00:55 +01:00
ibaker
2f01900e83 Release the Surface at the end of every playback test
Without this an error is logged which obfuscates real test failures.

PiperOrigin-RevId: 687302953
2024-10-18 08:01:50 -07:00
ibaker
64e0397811 De-flake new test for ProgressiveMediaSource.suppressPrepareError
This test was added in b3290eff10

#cherrypick

PiperOrigin-RevId: 686918104
2024-10-17 08:11:01 -07:00
ibaker
49dec5db8b Ignore renderer errors from text/metadata tracks
Before this change:

* With legacy subtitle decoding (at render time), load errors (e.g. HTTP
  404) would result playback completely failing, while parse errors
  (e.g. invalid  WebVTT data) would be silently ignored, so playback
  would continue without subtitles.
* With new subtitle decoding (at extraction time), both load and parse
  errors would result in playback completely failing.

This change means that now neither load nor parse errors in text or
metadata tracks stop playback from continuing. Instead the error'd track
is disabled until the end of the current period.

With new subtitle decoding, both load and parse errors happen during
loading/extraction, and so are emitted to the app via
`MediaSourceEventListener.onLoadError` and
`AnalyticsListener.onLoadError`. With legacy subtitle decoding, only
load errors are emitted via these listeners and parsing errors continue
to be silently ignored.

Issue: androidx/media#1722
PiperOrigin-RevId: 686902979
2024-10-17 07:15:22 -07:00
ibaker
191bc094a5 Propagate events from secondary children in MergingMediaSource
These events are always reported with the primary child period ID,
because this is the same ID used in the parent `MergingMediaSource`'s
Timeline.

This ensures that e.g. loading errors from sideloaded subtitles (which
uses `MergingMediaSource`) are now reported via
`AnalyticsListener.onLoadError`.

It results in non-error events being reported from these children too,
which will result in more `onLoadStarted` and `onLoadCompleted` events
being reported (one for each child).

Issue: androidx/media#1722
PiperOrigin-RevId: 686901439
2024-10-17 07:10:59 -07:00
ibaker
b3290eff10 Allow ProgressiveMediaSource to optionally suppress prepare errors
Use this for sideloaded subtitles, so preparation can still complete
despite an error from e.g. `DataSource.open`. In this case, no subtitle
tracks will be emitted.

Issue: androidx/media#1722
PiperOrigin-RevId: 686888588
2024-10-17 06:20:11 -07:00
michaelkatz
2a1e71b203 Reduce needless loading period resets in clipping mediasource playlists
When a `SampleQueue` is prepared prior to playback, the start position may be less than the timestamp of the first sample in the queue and still be valid. This scenario can come about with specific clipping values and if all samples are sync samples. Currently, with `ClippingMediaPeriods` around `ProgressiveMediaPeriods`, if the `SampleQueue` has already been reset through the seekTo operation in `onPrepared`, then in the aforementioned scenario the seekTo operation in `handleDiscontinuity` will remove all samples and reset the loading periods unnecessarily.

The solution is that if the `ProgressiveMediaPeriod` has already handled a seekTo operation for the same position and the sample queue has not been read yet, then loading does not need to be reset.

The tests in `MergingPlaylistPlaybackTest` were specifically causing this behavior through its setup of `MergingMediaSources` around clipped `FilteringMediaSources`. Since the video content was not 'all sync samples', there would always be a discontinuity to handle and the audio content being 'all sync samples' would start with samples post start time.

These changes also remove the flakiness from the `MergingPlaylistPlaybackTest`.

PiperOrigin-RevId: 686858444
2024-10-17 04:20:50 -07:00
ibaker
d2ccace75c Remove allocator param from MediaSourceTestRunner constructor
Currently every test in the library passes `null` here, which seems to
end up being passed into non-null places in the library. This change
removes the parameter and instead initializes the field to a
`DefaultAllocator` instance in the same way that `DefaultLoadControl`
creates one.

PiperOrigin-RevId: 686823273
2024-10-17 02:00:08 -07:00
kimvde
37cd008c01 Remove unnecessary method in VideoFrameRenderControl
PiperOrigin-RevId: 685681192
2024-10-14 06:10:33 -07:00
michaelkatz
1c4ee06ad6 Remove Renderer[] from LoadControl.onTracksSelected
The `DefaultLoadControl` implementation of onTracksSelected only utilizes the `Renderer[]` parameter for use in stream type, of which it can collect from the `ExoTrackSelection[]` parameter.

PiperOrigin-RevId: 685677726
2024-10-14 05:56:24 -07:00
tianyifeng
98dc7f2def Add DefaultPreloadManager.Builder
The `DefaultPreloadManager.Builder` is able to build the `DefaultPreloadManager` and `ExoPlayer` instances with the consistently shared configurations. Apps can:

* Simply setup the `DefaultPreloadManager` and `ExoPlayer` with all default configurations via `build()` and `buildExoPlayer()`;
* Or customize the shared configurations by the setters on `DefaultPreloadManager.Builder` and setup via `build()` and `buildExoPlayer()`;
* Or customize the player-only configurations for `ExoPlayer` via `buildExoPlayer(ExoPlayer.Builder)`.

PiperOrigin-RevId: 684852808
2024-10-11 08:55:25 -07:00
tonihei
b27cbe60b9 Add release callback and generic class to handle type casting 2024-10-11 11:00:45 +01:00
tonihei
15a6906877 Formatting and javadoc 2024-10-09 13:50:30 +01:00
Colin Kho
10bb2e1501 Allow Injection of custom Executor in ProgressiveMediaSource 2024-10-09 13:50:29 +01:00