ExoPlayer assumed 4-bytes for length in two places (by assuming the
length is the same as the 4-byte NAL start code):
1. In `AvcConfig` we transform length-delimited to start-delimited
before writing into `initializationData`, and then skip
'nal unit length field' bytes when parsing from `initializationData`
(when we should skip 'start code length' bytes instead).
2. In `Mp4Extractor.readSample` we modify the local variable
`sampleSize` to fix the difference between length field length and
start code length, but **only on the first attempt to read a
sample**. If we are resuming in the middle of reading a sample (after
a recoverable I/O error), this fix for `sampleSize` is not done,
which means we end up missing the last 2-3 bytes of the sample when
the NAL length is 1-2 bytes.
* This is fixed by moving the `sampleSize` 'fixing' code to outside
the `if (sampleCurrentNalBytesRemaining == 0)` block.
* `FragmentedMp4Extractor` has very similar code, but uses a
field for `sampleSize`, rather than a local, so doesn't look
vulnerable to the same problem (though I haven't totally
tested this).
This change adds a test file with 2-byte NAL lengths, generated by
hacking the media3 muxer to emit 2-byte NAL lengths and transforming
`sample.mp4` using the transformer demo app.
PiperOrigin-RevId: 713709203
If `experimentalSetEnableMediaCodecVideoRendererPrewarming` is set with `true`, `DefaultRenderersFactory` will provide `ExoPlayer` with a secondary `MediaCodecVideoRenderer` for use in pre-warming through its `createSecondaryRenderer` and `buildSecondaryVideoRenderer` implementations. `ExoPlayer` will then pre-process video of subsequent media items to reduce media item transition latency.
PiperOrigin-RevId: 713605911
DASH periods can have a duration that is less than the end of the
last chunk in the period. In these cases, the sample data needs to
be clipped to the declared period duration. This already happens
IF the period duration is known at the point where we start loading
the media chunk. However, if the duration becomes known later or is
reduced (e.g. in a live stream), the existing media chunks are not
clipped. This causes unclean transitions across periods where the
player tries to transition to the next period, but renderers struggle
to output all the remaining surplus samples that should have been
clipped.
This can be fixed by asking ChunkSampleStream to discard surplus
samples that were loaded beyond a clipped duration when evaluating
the sample queue between chunk loads.
Issue: androidx/media#1698
PiperOrigin-RevId: 713288221
It captures some information needed for the UI logic related to rendering of the video track (and later images) to the surface.
Supporting `EVENT_RENDERED_FIRST_FRAME` helps improve the UX by covering the surface with an overlay (scrim/shutter) until the first frame is ready. This helps avoid sudden flickering during MediaItem transitions.
PiperOrigin-RevId: 712889568
We previously parsed an arbitrary number of decimal places, but assumed
the value was in milliseconds, which doesn't make sense if there is
greater or fewer than 3. This change restricts the parsing to match
exactly 3, meaning the millisecond assumption is always true.
The WebVTT spec requires there to be exactly 3 decimal places:
https://www.w3.org/TR/webvtt1/#webvtt-timestamp
The SubRip spec is less clearly defined, but the Wikipedia article
defines it as having exactly 3 decimal places
(https://en.wikipedia.org/wiki/SubRip#Format) and ExoPlayer has always
assumed 3 decimal places (anything else is already handled incorrectly),
so this change just ensures we don't show subtitles at the wrong time.
Issue: androidx/media#1997
PiperOrigin-RevId: 712885023
For the [0.5; 1) speed range, the combination of having a "slow down"
speed (i.e. more output frames than input frames), and Sonic potentially
needing to copy more input frames that are available in the input buffer
can lead to an unexpected underflow.
Specifically, the underflow happens in Sonic#queueEndOfStream() when the
following conditions are met (skipping some minor ones):
1. `inputFrameCount < remainingInputToCopyFrameCount`
2. `0.5f <= speed < 1`.
3. `outputFrameCount <
(inputFrameCount / remainingInputToCopyFrameCount) / 2`.
This underflow caused `SonicAudioProcessor#isEnded()` to return a false
negative (because `getOutputSize() != 0`), which would stall the
`DefaultAudioSink` waiting for processing to end after EOS.
In practical terms, the underflow is relatively easy to reproduce if we
consume all of Sonic's output and then immediately queue EOS without
queueing any more input in between. This should cause both
`inputFrameCount` and `outputFrameCount` to drop to 0.
PiperOrigin-RevId: 711773565
Added a new `usePlatformDiagnostics` in Transformer. This parameter enables/disables forwarding editing events and performance data to the platform.
This is pre-work for metrics support in Transformer. In the following CLs, metrics collection and forwarding will be implemented.
PiperOrigin-RevId: 707930368
This enables `AdsMediaSource` to be used with a live media
source that has a growing `AdPlaybackState` to which ad groups
can be appended.
Before this change, `AdsMediaSource` asserted that the number
of ad groups was kept the same, else an exception was thrown.
After this change, the assertion checks the validity of the
update and throws in case the update isn't considered valid.
An update is valid if ad groups are appended to the existing
`AdPlaybackState` or ads are appended to existing ad groups.
Further the `adGroupIndex` and `timeUs`of an existing ad
group can not be changed and once a media item is set for a
given ad, that media item can't be changed either.
PiperOrigin-RevId: 707244455
Both classes provide utilities widely used by apps that are not
yet available in Media3. This change imports the existing logic as
it is with style adjustments to the Media3 codebase.
PiperOrigin-RevId: 707067512
There are reproducible issues with codec timeouts when using
this API, so we disable it entirely until we know more about
potential fixes and where they are available.
Issue: androidx/media#1641
#cherrypick
PiperOrigin-RevId: 707025950
`MediaCodecVideoRenderer` will skip frames if a surface has not been set and video frame presentation time is early but too close to the current playback position. In the case that the `VideoFrameReleaseControl` says to `FRAME_RELEASE_TRY_AGAIN_LATER`, these frames should not be skipped.
PiperOrigin-RevId: 706711734
Metadata does not provide a `toBundle` method. It implements
`Parcelable` which is not safe for IPCs between binaries with
potentially different class definitions (e.g. two apps built from
different versions of media3).
If we get a use case to bundle metadata as well, then the `Metadata`
class needs to provide a `toBundle()` method.
PiperOrigin-RevId: 705920231
Before this change, the value of the `dwLength` in the stream header was
interpreted as the number of chunks in the file. Seeking and timestamp
calculation use the media duration and total chunk count. However, in some
files the `dwLength` field appears not to store the number of chunks. For
example, there are CBR MP3 and AC3 files where this field seems to store the
total number of bytes of compressed media instead. That caused seeking and
timestamp calculation to give much smaller values than expected (because the
`dwLength` is very large), which broke seeking.
Work around this using the `idx1` index header if present. We only support
audio formats where every audio sample is a sync sample in AVI, and all chunks
should therefore be listed in this index. Based on testing on many sample AVI
files this gives a reliable total chunk count and fixes seeking.
The test media file is a transcoded version of Big Buck Bunny but manually
edited to overwrite the length, rate and sample size header files to simulate
the error case.
PiperOrigin-RevId: 705103651
`AudioTrackPositionTracker.pause` "re-arms" the event, to ensure it
fires again when playback resumes. However the `AudioTrack` position
advances by about 100ms **after** `AudioTrack.pause()`, which
consistently causes the event to fire immediately after pausing (and
then **not** after a subsequent resumption).
This change checks whether the `AudioTrack` is paused before firing
the event, to avoid this spurious trigger.
PiperOrigin-RevId: 704759929
`RenderersFactory#createSecondaryRenderer` can be implemented to provide secondary renderers for pre-warming. These renderers must match their primaries in terms of reported track type support and `RendererCapabilities`.
If a secondary renderer is provided, ExoPlayer will enable it for a subsequent media item as soon as its `MediaPeriod` is prepared. This will cause the renderer to start decoding and processing content so that it is ready to play as soon as playback transitions to that media item.
PiperOrigin-RevId: 704326302
After removing `Transformer.Builder.setFlattenForSlowMotion()`, there is no need to keep `flattenForSlowMotion` in Transformer since it's now set in `EditedMediaItem`.
The change also includes making `audioProcessors` and `videoEffects` attributes final.
PiperOrigin-RevId: 703076023
* Select an encoder that supports HDR editing.
* Set KEY_PROFILE to an HDR10 option
* Use DecodeOneFrameUtil test util to return the MediaCodec format,
which includes HDR_STATIC_INFO
PiperOrigin-RevId: 702752639
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
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
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
SpeedChangingAudioProcessor is redundantly bypassing SonicAudioProcessor
when the speed is set to 1f. SpeedChangingAudioProcessor should not make
assumptions about the underlying audio processing and moreover should
not be bypassing any AudioProcessor based on parameter values. Default
parameter values are a valid state for an active AudioProcessor.
Sonic already handles the "default case" state by just copying the input
buffer onto the output buffer.
This CL also simplifies SonicAudioProcessor, which would mark itself as
inactive when configured with a valid set of default parameters. The API
contract for `isActive()` makes no mention about parameter state, which
makes changes in `isActive()` after applying new valid parameters quite
unintuitive.
PiperOrigin-RevId: 698000500