This is a step towards unifying ShadowMediaCodecConfig structure to accommodate both ExoPlayer and Transcoding codecs configuration.
This change abstracts the codec information to a separate `CodecInfo` class. This allows having codecs with the same information configured with different configurations (passthrough/frame-dropping, decoder/encoder). It also does the following:
* Replaces the map of default codecs with public static final CodecInfo constants for each codec.
* Modifies the ShadowMediaCodecConfig constructor to accept a set of CodecImpls instead of mime types.
* Updates factory methods to reflect the constructor change.
* Updates addSupportedMimeTypes to addDecoder, taking a CodecInfo instead of a mimeType.
This is a non-functional change.
PiperOrigin-RevId: 739857883
We currently assume SW codecs are capable of playing all resolutions
and frame rates up to their declared supported maximum values, even
though the are likely not able to keep up playback smoothly for higher
resolutions. For HW codecs we can check PerformancePoints to declare
them as EXCEEDS_CAPABILITIES if they technically support a format but
are not performant enough. We can do the same for SW codecs by
checking getAchievableFrameRatesFor.
PiperOrigin-RevId: 739253653
Previously, `exportSuccess_populatesEditingEndedEvent` and `exportError_populatesEditingEndedEvent` used an AtomicReference to capture the EditingEndedEvent. However, this led to a race condition where `EditingEndedEvent` was accessed before it was set in the `onMetricsReported` callback, resulting in a NullPointerException. This change replaces the AtomicReference with a SettableFuture to ensure the test waits for the event to be reported before asserting its value.
PiperOrigin-RevId: 739146511
This is a step towards unifying ShadowMediaCodecConfig structure to accomodate both ExoPlayer and Transcoding codecs configuration.
ExoPlayer's `CodecConfig.Codec` implementation, due to b/174737370, discards all audio samples. This issue is only applicable for ExoPlayer tests and doesn't impact transcoding tests. To accomodate for having transcoding codecs, 2 fields were added to CodecImpl: `isPassThrough` that specifies whether we want to drop frames/samples or not, and `isEncoder` that specifies whether we are configuring a decoder or an encoder.
This is a non-functional refactor.
PiperOrigin-RevId: 739112659
CodecDbLite is a repository of chipset-specific codec recommendations.
Initially, these recommendations will focus on video encoders,
specifically choosing the right encoder to use on a given chipset
and the B-frame configuration to use with that encoder.
PiperOrigin-RevId: 738895394
Language codes in the `mdhd` box are stored as three 5-bit values, each representing a letter ('a' to 'z') using an offset of `0x60`. If the decoded characters are not in this range, the language should be treated as undefined.
PiperOrigin-RevId: 738470544
This commit implements the `getPlaylistMetadata()` and `setPlaylistMetadata()` methods in the `CastPlayer` class.
The new implementations are based on what is done in `ExoPlayerImpl`.
The comment sounds like it is worried the next header won't fit after
`limit` and before the end of `data`, but the code was previously only
checking the space between `position` and `limit`. This led to some
unnecessary copies.
Running the Robolectric `FlacExtractorTest.sample()` test in only the
'partial reads' and I/O errors case (worst case for this bug) results
in 57271 copies without this fix, and 19 copies with it.
Sample of the first 10 copies before this fix, showing a copy is made
for every byte read from the input:
```
W/ibaker: Making a copy. input.position=8881, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8882, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8883, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8884, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8885, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8886, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8887, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8888, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8889, data.length=32768, pos=1, lim=1
W/ibaker: Making a copy. input.position=8890, data.length=32768, pos=1, lim=1
```
And the first 10 copies after the fix:
```
W/ibaker: Making a copy. input.position=41648, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=74401, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=107154, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=139907, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=172660, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=41648, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=74401, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=107154, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=139907, data.length=32768, pos=32753, lim=32768
W/ibaker: Making a copy. input.position=172660, data.length=32768, pos=32753, lim=32768
```
PiperOrigin-RevId: 738341007
The goal is to get rid of VideoSink.onRendererEnabled so that this
interface becomes renderer-agnostic. Indeed, for multi video sequences,
the DefaultVideoSink won't receive input from a single renderer anymore.
This is a no-op refactoring
PiperOrigin-RevId: 738296515
Pass the temporary CookieHandler as a parameter instead of setting it as a temporary process-default. This avoids a rare race condition, where the player is sending a request with preserveCookies option and runs the `CookieHandler.getDefault()` before a different thread sets a default cookie handler. Over 5 or so lines of code the new default might be reverted to null - this is now fixed.
PiperOrigin-RevId: 738052152
Ideally, we'd find a more targeted exclusion as it may depend on
specific codecs. The current workaround should help with the
reported issues that are limited to Xiaomi and OPPO.
Issue: androidx/media#2059
#cherrypick
PiperOrigin-RevId: 738017969
With a [previous change](f05e6a7d6e), we makes `hasPendingData()` return `false` once we've found that the `AudioTrack` has played out all the written frames, to avoid it permanently stays `true` even when the source has ended. However, this is aggressive as the audio output device can still have latency in playing out those frames. So `hasPendingData()` should stay `true` a bit longer (for the duration of `latencyUs`) until finally turn to `false`, as well as the `getCurrentPositionUs()` should increment smoothly without a jump for the duration of `latencyUs`.
PiperOrigin-RevId: 738004292
This test is failing in <unknown commit> when the following happens in
PlaybackVideoGraphWrapper:
- Both InputVideoSinks call onInputStreamChanged with startPosition
1000000000000
- Before the first VideoGraph output frame is available, both
InputVideoSinks call onInputStreamChanged with startPosition
1000000200000. This incorrectly erases startPosition
1000000000000 from TimedValueQueue streamStartPositionsUs. Indeed, when
1000000200000 is added for the second time, the whole queue is cleared
because this new value is not strictly greater than the previous one.
This start position logic should only be used for single-sequence
rendering. Disable the test until this is fixed.
PiperOrigin-RevId: 737982504
We currently pretend to be ready when using a placeholder
surface irrespective of whether the renderer is actually
ready to immediately render when a surface is attached.
This causes issues in two ways:
- Apps don't know when a player without a surface can be
connected to a surface and immediately start playing
- A paused player without a surface will use the 1 second
default doSomeWork loop, causing any pending decoding
to be extremely slow (see Issue: androidx/media#1973).
The fix is to let the placeholder surface case use the same
paths as the regular surface and with marking the first
frame as available as soon as the codec output buffer for it
is pending and ready for release.
PiperOrigin-RevId: 737942496
This brings the parts related to video frame release decision making
in a single place and simplifies the calling side in
MediaCodecVideoRenderer.
PiperOrigin-RevId: 737941729
This fixes the following issue: in CompositionPlayer, if the
Composition was containing a looping sequence with duration larger than
all the other sequences, the Composition duration was set to the
looping sequence duration. This is incorrect because looping sequences
should be clipped to match the other sequences.
PiperOrigin-RevId: 737927987
This method allows a single Presentation Effect to resize portrait and landscape videos to a fixed resolution, while maintaining their orientations.
PiperOrigin-RevId: 737652909
By using this setter, the duration of the background audio doesn't need
to be computed anymore. It will also repeat the audio track if the video
track is longer.
PiperOrigin-RevId: 737621668
We currently throw an exception if the start time exceeds the
auto-detected end time at the duration even though an app can't
know this in advance in all cases. We should still throw an
exception if app-provided input values are non-sensical, but
auto-adjust the start time to the duration if needed similar to
how we already adjust the end time.
PiperOrigin-RevId: 737585207
Previously we only enable `SeekParameter.*_SYNC` for HLS when `EXT-X-INDEPENDENT-SEGMENTS` is set in the playlist. However, this condition can actually be loosened. To seek in HLS, we need to download the segment in which the resolved seek position locates under any circumstance. If `SeekParameter.PREVIOUS_SYNC` or `SeekParameter.CLOSEST_SYNC` is passed, and that segment happens to start with sync samples, then the seek can be done quicker with that adjusted seek position. And if that segment doesn't start with sync samples, then the behaviour will be the same as we set the adjusted seek position to the exact original position. But we still cannot safely enable `SeekParameter.NEXT_SYNC` as it will potentially cause the seeking to miss more content than seeking to the exact position.
Issue: androidx/media#2209
PiperOrigin-RevId: 737580861
This transforms the reported format support from `supported=YES` to
`supported=NO_EXCEEDS_CAPABILITIES`. Playback is still attempted in the
main demo app, and hangs as described in
https://github.com/androidx/media/issues/2197#issuecomment-2722322954.
PiperOrigin-RevId: 737568955
Before this change, exporting a Composition with all looping sequences
would result in a runtime exception due to a divide-by-zero exception
in TransformerInternal.
PiperOrigin-RevId: 737568877
Without this, 32-bit files fail to play with `Playback stuck buffering
and not loading`. With this change, playback works on devices where the
`MediaCodec` FLAC decoder supports 32-bit, and crashes on devices with a
`MediaCodec` FLAC decoder that does not support 32-bit.
A follow-up change will aim to transform the 'unsupported' case from a
crash into a report that the track format is not supported.
32-bit support was only fully incorporated into the spec when RFC 9639
was [published in December
2024](https://xiph.org/flac/2024/12/19/rfc-9639-published.html), and
it was been supported by `libflac` (for encode and decode) [since
September 2022](https://xiph.org/flac/2022/09/09/flac-1-4-0-released.html).
The original version of this `FlacExtractor` was written before either
of these, so only supported up to 24-bit.
Issue: androidx/media#2197
PiperOrigin-RevId: 737559285