The content in Issue: androidx/media#1863 has every sample incorrectly marked as a
sync sample in the MP4 metadata, which results in flushing the
re-ordering queue on every sample, so nothing gets re-ordered, so the
subtitles are garbled.
There are currently two "uses" for this call on every keyframe:
1. It offers a safety valve if we don't read a `maxNumReorderSamples`
value from the video. Without this, the queue will just keep growing
and end up swallowing all subtitle data (similar to the bug fixed by
39c734963f).
2. When we do read (or infer) a `maxNumReorderSamples` it means we can
emit samples from the queue slightly earlier - but this is pretty
marginal, given i think the max possible value for
`maxNumReorderSamples` is 16, so the most benefit we would get is 16
frames (~0.53s at 30fps) - in most cases we will have more than 0.5s
of buffer ahead of the playback position, so the subtitles will still
get shown at the right time with no problem.
(1) is resolved in this change by setting the queue size to zero (no
reordering) if we don't have a value for `maxNumReorderSamples`.
(2) has minimal impact, so we just accept it.
We may be able to inspect the NAL unit to determine IDR vs non-IDR
instead - we will consider this as a follow-up change, but given the
minimal impact of (2) we may not pursue this.
#cherrypick
PiperOrigin-RevId: 696583702
The behaviour was changed in 1.4.0 with 0f42dd4752,
so that the buffer timestamp is compared to `outputStartTimeUs` when
deciding whether to discard a "decode only" buffer before decoding
(instead of the deprecated/removed `isDecodeOnly` property). This breaks
when the buffer timestamp is `TIME_END_OF_SOURCE` (which is
`Long.MIN_VALUE`), because `TIME_END_OF_SOURCE < outputStartTimeUs` is
always true, so the end-of-stream buffer is never passed to the decoder
and on to `TextRenderer` where it is used to
[set `inputStreamEnded = true`](40f187e4b4/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java (L434-L436))
and so playback hangs.
#cherrypick
Issue: androidx/media#1863
PiperOrigin-RevId: 695767247
This ensures it works correctly when there are multiple SEI messages per
sample and the max size is set from e.g. H.264's
`max_num_reorder_frames`.
PiperOrigin-RevId: 694526152
Enable transformer to transmux into alternative sample MIME types.
For example, some Dolby Vision profiles have a backwards-compatible
AVC or HEVC layer. MV-HEVC is backwards compatible with HEVC.
This change enables Transformer to transmux into the backwards compatible
format to improve compatibility with legacy APIs such as
MediaMetadataRetriever.
PiperOrigin-RevId: 693667597
* Provide a helper Composable for remembering the state instance and launching the listening coroutine that observes the changes in the Player
* Add an example to demo-compose of using Shuffle- and Repeat- ButtonStates inside a Shuffle- and RepeatButton Composable.
* Reformat the MainActivity usage of `Shuffle` and `Repeat` buttons to form extra Player Controls and combine Prev/Play-Pause/Next with Shuffle/Repeat (Minimal controls + Extra controls = `PlayerControls`)
PiperOrigin-RevId: 692939825
* Provide a helper Composable for remembering the state instance and launching the listening coroutine that observes the changes in the Player
* Add an example to demo-compose of using Previous- and Next- ButtonStates inside a Previous- and NextButton Composable.
* Reformat the MainActivity usage of `Previous`, `PlayPause`, `Next` buttons to form Minimal Player Controls
PiperOrigin-RevId: 691943147
Provide a helper Composable for remembering the state instance and launching the listening coroutine that observes the changes in the Player
Add an example to demo-compose of using PlayPauseButtonState inside a PlayPauseButton Composable.
The smart State object has been deemed a preferred solution over collecting Flows due to queuing/timing/buffering limitations. Instead, it uses the new `Player.listen` suspending extension function to catch the relevant events.
PiperOrigin-RevId: 691879975
When transitioning to the next media position parameter checkpoint
we estimate the position because the audio processor chain no longer
provides access to the actual playout duration.
The estimate using the declared speed and the last checkpoint may
have drifted over time, so we currently estimate relative to the
next checkpoint, which is closer and presumably provides a better
estimate. However, this assumes that these checkpoint are perfectly
aligned without any position jumps.
The current approach has two issues:
- The next checkpoint may include a position jump by design, e.g.
if it was set for a new item in the playlist and the duration of
the current item wasn't perfectly accurate.
- The sudden switch between two estimation methods may cause a jump
in the output position, which is visible when we add new media
position checkpoints to the queue, not when we actually reach the
playback position of the checkpoint.
We can fix both issues by taking a slightly different approach:
- Continuously monitor the estimate using the current checkpoint. If
it starts drifting, we can adjust it directly. This way the estimate
is always aligned with the actual position.
- The change above means we can safely switch to using the estimate
based on the previous checkpoint. This way we don't have to make
assumptions about the next checkpoint and any position jumps will
only happen when we actually reach this checkpoint (which is more
what a user expects to see, e.g. at a playlist item transition).
Issue: androidx/media#1698
PiperOrigin-RevId: 690979859
Removed deprecated `Transformer.PROGRESS_STATE_NO_TRANSFORMATION`, `Transformer.setListener`, and `Transformer.startTransformation` from Transformer.
PiperOrigin-RevId: 690971992
This method is already called below in the
`else if (sps.isCompleted())` block which applies when
`hasOutputFormat == true`, but this is only ever entered if we are
parsing SPS and PPS NAL units **after** we've emitted a format, which
is only the case if
`DefaultTsPayloadReaderFactory.FLAG_DETECT_ACCESS_UNITS` is set (which
it isn't by default).
The equivalent call in `H265Reader` is already inside the
`if (!hasOutputFormat)` block, so doesn't need a similar fix.
#cherrypick
PiperOrigin-RevId: 689809529
This change:
1. Updates `DataSourceContractTest` to allow multiple "not found"
resources, and to include additional info (e.g. headers) on them.
2. Updates the contract test to assert that `DataSource.getUri()`
returns the expected (non-null) value for "not found" resources
between the failed `open()` call and a subsequent `close()` call.
The `DataSource` is 'open' at this point (since it needs to be
'closed' later), so `getUri()` must return non-null.
* This change also fixes some implementations to comply with this
contract. It also renames some imprecisely named `opened`
booleans that **don't** track whether the `DataSource` is open
or not.
3. Updates the contract test assertions to enforce that
`DataSource.getResponseHeaders()` returns any headers associated
with the 'not found' resource.
4. Configures `HttpDataSourceTestEnv` to provide both 404 and "server
not found" resources, with the former having expected headers
associated with it.
PiperOrigin-RevId: 689316121
The new `media3-ui-compose` module does not have any Material library dependencies, but will rely on androidx.compose + foundation/runtime/ui and other non-theming/opinionated libraries. Surface handling is one such usecase.
PiperOrigin-RevId: 689004504
Treats the media duration as unknown (`C.TIME_UNSET`) when all bytes are `-1` to prevent exceptions during playback.
Issue: androidx/media#1819
#cherrypick
PiperOrigin-RevId: 688103949
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
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
Childrens returned by the legacy service when a Media3
browser connects are cached and returned with the first
`getChildren` call in case the same `paranetid` is
requested.
In any other case the cache is immediately cleared.
#cherrypick
PiperOrigin-RevId: 686157511
Updated logic to walk forward in the timestamps array to include all frames within the valid edit duration, accounting for out-of-order frames. This ensures that no frames with timestamps less than `editMediaTime` + `editDuration` are incorrectly excluded.
Issue: androidx/media#1797
PiperOrigin-RevId: 686075680
When receiving an error from a legacy `MediaBrowserService` after
having successfully subscribed to a given `parentId`, the callback
needs to be asked to load the children again to receive an error
from the service.
Before this change such an error was dropped as a no-op by Media3
without the `MediaBrowser` giving a chance to react on such an error
being sent by the legacy service.
#cherrypick
PiperOrigin-RevId: 686052969
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
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