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 method allows a single Presentation Effect to resize portrait and landscape videos to a fixed resolution, while maintaining their orientations.
PiperOrigin-RevId: 737652909
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
These are common in robolectric playback tests, because our
`ShadowMediaCodecConfig` always returns empty buffers when 'decoding'
audio.
PiperOrigin-RevId: 736836767
The spec technically allows to mark adaptation sets with the switching
property if they allow seamless switching with non-overlapping
segments. This is typically only used for compatible content (e.g.
different codecs), but the spec allows it to be used for other
content as well (e.g. different languages, roles). ExoPlayer's concept
of a TrackGroup only allows formats with the same language and role
flags to be merged, so we should check that before merging.
Issue: androidx/media#2222
#cherrypick
PiperOrigin-RevId: 736564055
The matroska file works without further changes. The FLAC container
file works with `lib-flac-decoder` depending on a bundled `libflac`
implementation, but not when using
`androidx.media3.extractor.flac.FlacExtractor` with a `MediaCodec` FLAC
decoder because the media3 extractor doesn't support 32-bit FLAC yet.
The fix for that is in a follow-up change.
`bear_32bit.flac` was generated from `bear.flac` with `ffmpeg`:
```shell
$ ffmpeg \
-i bear.flac \
-c:a flac \
-sample_fmt s32 \
-strict experimental \
bear_32bit.flac
```
`bear-flac-32bit.mka` was generated by re-muxing `bear_32bit.flac`,
also with `ffmpeg` (trying to convert `bear-flac-24bit.mka` to 32-bit
didn't work, the resulting file was still 24-bit):
```shell
$ ffmpeg \
-i ../flac/bear_32bit.flac \
-c:a copy \
bear-flac-32bit.mka
```
Issue: androidx/media#2197
PiperOrigin-RevId: 736552251
This change uses the duration and byte count of the Xing frame, if
they're present, to estimate the bitrate of the stream. The seeking
will still be inaccurate (because we're doing CBR seeking in a VBR
stream), but it will be more accurate than basing the bitrate on the
first MP3 frame we read. It will also mean the duration reported is
accurate.
This change also ensures that if the Xing frame contains the number of
audio bytes but no ToC, the audio data length is still propagated into
the `XingSeeker` (and therefore into the `ConstantBitrateSeeker` too).
Issue: androidx/media#2194
PiperOrigin-RevId: 736100104
A problem was discovered in Composition demo app where after playing a composition using CompositionPlayer, pressing the "play" button again would not restart the playback. This issue has been resolved, just adding a test to make sure we're not missing any regressions.
PiperOrigin-RevId: 735793488
These tests show the current behaviour:
1. Without customization: not seekable
2. With 'enable CBR' flag:
* File length known: seekable but duration very incorrect
* File length unknown: not seekable (even though the Xing frame
contains the number of bytes in the mp3 stream).
Follow-up test changes will:
1. Add a test for the cbr-always case for this file (branched from the
files submitted in this change).
2. Add a new similar test asset with no ToC but with trailing garbage
bytes, to verify that the length from the Xing frame is used.
Then follow-up implementation changes will update Mp3Extractor to use
duration and byte length from a Xing frame when falling back to CBR
seeking.
Issue: androidx/media#2194
PiperOrigin-RevId: 734164879
When there is both audio and video track, then fragment
creation is driven by video track (a combination of duration
so far + next key frame). But if there is no video track, then
the duration so far drives the fragment creation.
Due to bug, when there is only audio track, only first
fragment was created as expected and then a new fragment is
created for every audio sample.
#cherrypick
PiperOrigin-RevId: 731257696
This was introduced in 841bdc6efe.
There's no need to cast the `char` (2 bytes) down to a `byte` in order
to pack it into an `int` (4 bytes) alongside a short (2 bytes).
We also don't need to use `short` to track the character count (max 4
with UTF-8) - a single byte is enough. This change also uses
`Ints.fromBytes` to avoid having to reason about how casting &
bit-shifting interact.
This change introduces a test which reproduces the failure reported in
Issue: androidx/media#2167.
#cherrypick
PiperOrigin-RevId: 730809219
Added tests for APIs `getDrmInitData()`, `getPsshInfo()`, `getLogSessionId()` and `setLogSessionId(LogSessionId)`.
The Widevine encrypted sample was created from already existing `sample_fragmented.mp4` using `mp4encrypt`.
PiperOrigin-RevId: 726881977
AV1 input buffers contain multiple compressed pictures.
Enable skipping only the last showable frame, while leaving
any reference pictures to be decoded later, as part of
the next decoder input buffer.
Partial skipping of AV1 input buffer is only applied when:
* fewer than 8 OBUs are delayed
* there's likely to be enough capacity in the decoder input buffer
for the next frame
PiperOrigin-RevId: 723496060
Parsing AV1 bitstreams allows us to identify frames that are
not used as reference, and improve seeking or frame dropping
behavior.
The AV1 bitstream format is relatively quick to parse
PiperOrigin-RevId: 723462680
When sample batching is disabled, copying of the ByteBuffer data
is not necessary as samples are written as they arrive.
Copying of the BufferInfo is necessary because the info is needed
for writing the moov atom.
The input ByteBuffer can be in little endian order, or have its
position set. AnnexBUtils now ensures big endian order before
inspecting bytes, and supports reading from a non-zero position.
This change reduces the amount of memory allocations by Mp4Muxer
in its default configuration
PiperOrigin-RevId: 723401822
The exception occurred when an edit list started at a non-sync frame with no preceding sync frame. The fix searches forward for the next sync frame in such cases, preventing the out-of-bounds access.
Issue: androidx/media#2062
#cherrypick
PiperOrigin-RevId: 720642687
Add an option to GlMatrixTransformation to choose the OpenGL texture
minification filter.
When mipmaps are requested, mipmaps are generated with
`glGenerateMipmap()`.
PiperOrigin-RevId: 720629807
The file in Issue: androidx/media#2052 contains a cue with the following timecode:
```
0:00:00:00,0:00:00:00
```
The content of this cue seems to be some 'converted by' metadata, i.e.
it's basically a comment and clearly not intended to be shown on
screen (since it has zero duration).
There is some fiddly logic later in `SsaParser` to support overlapping
cues with the old `Subtitle` structure [1], and this logic gets tripped
up by the start and end time being equal, which results in a
**single**, empty `List<Cue>` being added - which trips up another
assumption that every SSA cue line results in at least two `List<Cue>`
entries (one containing the cue text, and another containing an empty
list to signal the end of the cues).
This fiddly logic is no longer required, because overlapping
`CuesWithTiming` objects can now be merged in `TextRenderer`, so there
is a possible future simplification to `SsaParser` which removes a lot
of this complexity.
[1] Added in <unknown commit>
PiperOrigin-RevId: 718380386
This is aligned with the documentation of `MediaCodec` which says the
timestamp of a buffer with `BUFFER_FLAG_END_OF_STREAM` should be
ignored:
https://developer.android.com/reference/android/media/MediaCodec#end-of-stream-handling
Add a test that exercises this by clipping off the end of a sample with
CEA-608 captions, because this creates an EOS-flagged buffer with a
non-EOS timestamp.
Also add a straightforward playback test for the
`fragmented_captions.mp4` sample.
PiperOrigin-RevId: 715716036
Deprecate BundledChunkExtractor.experimentalParseWithinGopSampleDependencies
in favour of
ChunkExtractor.experimentalSetCodecsToParseWithinGopSampleDependencies
which takes a VideoCodecFlags IntDef flags that represent a set of codecs.
Add a DASH test using the new API with an H.265 video.
PiperOrigin-RevId: 714901602
Earlier muxer wrote a different entry for every chunk but as
per the spec (ISO 14496-12) exact same chunks can be combined
and only the first chunk number can be written.
PiperOrigin-RevId: 714154531
Add a new flag to FragmentedMp4Extractor
FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265
Read two bytes from H.265 videos to determine NAL unit type and
temporal layer id.
PiperOrigin-RevId: 714046987