Moving the fullscreen button around depending on modes is quite error
prone. There is currently a bug where the order of the settings cog
and fullscreen button can end up being swapped around as a result of
moving the fullscreen button to the minimal controls and back again.
It's less error prone just to have a second fullscreen button that's
always part of the minimal controls.
PiperOrigin-RevId: 347639484
- In slow motion videos flattened by Samsung, the saut box is kept but
only have the 4 first bytes (author field).
- In Samsung normal videos, the recording mode is zero.
In these cases, skip this box.
PiperOrigin-RevId: 347577303
Previously the `AdTagLoader` only had one listener which meant that updates
that should affect all periods with matching identifiers in the timeline only
affected the last-attached one. Fix this by having `AdTagLoader` track all its
listeners.
Issue: #3750
PiperOrigin-RevId: 347571323
Currently we don't remove the AnalyticsListeners registed to
SimpleExoPlayer after calling release. We didn't do this mainly
because there are messages triggered as part of the release that
still cause interesting events (e.g. decoderDisabled with the
final counters, final dropped counts etc).
However, we should fully release/remove the listeners once these
pending events are delivered to:
1. Not leak listener implementations (e.g. if the listener is an
Activity)
2. Ensure we don't send future events that may cause listeners
to unintentionally access released or nulled variables. This
could happen for example if someone calls a player method
after the player was released.
In addition, we can add a onPlayerReleased callback to
AnalyticsListener to allow implementations to clean themselves up
once all pending events are delivered.
PiperOrigin-RevId: 347434344
Fixed the verticalAnchorType and horizontalAnchorType calculation
The anchorID 0, 1 and 2 should correspond to verticalAnchorType=ANCHOR_TYPE_START, anchorID 3, 4, 5 is ANCHOR_TYPE_MIDDLE, anchorID 6, 7 and 8 is ANCHOR_TYPE_END
The anchorID 0, 3 and 6 should correspond to horizzonatlAnchor=ANCHOR_TYPE_START, anchorID 1, 4, 7 is ANCHOR_TYPE_MIDDLE, anchorID 2, 5 and 8 is ANCHOR_TYPE_END
- Re-layer layout so that the central controls end up on
top (and, more importantly, have preference for receiving
touch input) if the view is so small that elements start
to overlap. This requires splitting the background and
the controls themselves.
- Fix bug that could cause the scrubber to not be hidden
in minimal mode, if the mode is entered when the controls
are not visible.
- Fix positioning of minimal controls.
- Remove scrubber padding in minimal mode, since the scrubber
- Remove unused bar_gravity value.
PiperOrigin-RevId: 347008789
- Replace some magic constants with use of layout gravity where possible
- Remove some attributes that are set in code anyway
- Remove some attributes that are set to their default values
- Inline transport controls
- Minor naming cleanup
PiperOrigin-RevId: 346980595
When a listener is removed or released we may not have called
onEvents for events that happened before this point. To ensure
listeners don't miss events we need to trigger a final onEvents
with all events we have happened so far (if any).
PiperOrigin-RevId: 346553030
Fix Matroska, Heif, FLAC, Ogg, Opus, Vorbis
extractor nullness check.
There should be no functional change.
Every media that fail to be parsed should still fail.
Every media that parsed successfully should still succeed.
This refactor aims to push all nullness constraints up the call stack to clarify each API nullness contract. This ensures implementation and caller have to prove their respective contract close to where such logic is implemented. This also allows to fail early if an nullness contract is broken instead of deep in the call stack.
For example, by adding a requirement that all implementation of `StreamReader.readHeaders` have to initialize `setupData.format` if the return false, each overriding method is forced to prove this next to the logic initializing it. This also means the runtime check might not be needed because the nullnessChecker can prove itself the contract holds.
This is in contrast with adding a null check at the point of usage, which will not catch logic errors where they are produce, but later when they are perceived; making it harder to debug and catching the issue at run time instead of compile time.
#exofixit
PiperOrigin-RevId: 346163124
This will allow Player to move in common without
trackSelector and all its many dependency.
Currently all users of `getTrackSelector` are
downcasting it in `DefaultTrackSelector`, this change
thus does not break them.
Track selection API is intended to be reworked, methods
will be added to the currently empty interface.
#player-to-common
PiperOrigin-RevId: 346159765
Retrieve the capture frame rate and the SVC temporal layer count from
the smta box instead of the meta box because this is what Samsung do. It
is not guaranteed that the meta box will be present and will contain all
the necessary info in all slomo files.
PiperOrigin-RevId: 345639680
Previously the helper would constantly lose (or never establish) sync
for non-1x playback speeds. This changes the helper to account for
other playback speeds correctly.
PiperOrigin-RevId: 345458859
This was reported for SSA/ASS in PR #8265, but it seems to me the
SubRip part of the Matroska spec is similarly loose, so this change
handles null-terminated strings in both.
#minor-release
PiperOrigin-RevId: 345452667
The old tag reflects the original name of this class. It was renamed in
2017:
<unknown commit>
Possibly the old name was kept for compatibility with existing logs
analysis? I didn't see an explicit discussion of this in the review
comments of the rename change.
The current tag confused me slightly - I assumed a line was being
emitted by the android.media.AudioTrack rather than ExoPlayer's
DefaultAudioSink.
PiperOrigin-RevId: 345450056
The `AudioProcessor` interface requires that no more input is queued after
queueing end of stream, but `DefaultAudioSink` did queue more input and the
implementation of `SonicAudioProcessor` actually relied on this to drain output
at the end of the stream.
Fix this behavior by getting `Sonic` output in `getOutput` and having
`DefaultAudioSink` only queue input to processors that are not draining.
Also add TODOs to clean up audio processor implementations where the code
handles interaction that doesn't conform to the interface.
PiperOrigin-RevId: 345406478
As Player depends on VideoScalingMode, and
Renderer should not move to common,
to move Player to common, VideoScalingMode
needs to move first.
#player-to-common
PiperOrigin-RevId: 345314448
Changes MetadataRetriever and Transformer so that their
respective tests don't need to manually control the SystemClock
in order to execute taks posted with delay from Loader.
PiperOrigin-RevId: 345024140
Low latency streams potentially need to remove preload chunks in case they are removed from the playlist. Hence we need to schedule loading the next playlist even if the playlist is not a primary playlist.
Issue: #5011
PiperOrigin-RevId: 344995891
Previously `MediaPeriodQueue` would return null if an ad media URI hadn't
loaded yet, but this meant that the player could be stuck in `STATE_READY` if
an `AdsLoader` unexpectedly didn't provide an ad URI. Fix this behavior by
masking ad media periods. `MaskingMediaPeriod` no longer requires a
`MediaSource` to instantiate it.
This also fixes a specific case where playback gets stuck when using the IMA
extension with an empty ad where the IMA SDK unexpectedly doesn't notify the ad
group fetch error.
Issue: #8205
PiperOrigin-RevId: 344984824
The inner class was only used to obtain 3 distinct pieces of
information which is better handled by static methods.
#exofixit
PiperOrigin-RevId: 344767661
This method should be assumed to clear the data of the underlying array
(it will do this if the new limit > data.length).
This means it should only be called (directly) before writing into the
backing array.
It shouldn't be used as a shorthand for position=0, limit=x - those
should be two explicit method calls.
Most of these changes are no-ops, but they make the code more correct.
The TS SectionReader can't be easily changed to be 'safe', because it
relies on sectionData maintaining state between iterations of the while
loop. Instead I've added comments justifying the existing code.
PiperOrigin-RevId: 344515340
This ensures we have full test coverage for proguard configs now.
The only configs not covered by tests are:
- IMA and OkHttp which copy recommended configs from the respective
library. I couldn't reproduce failures by removing them (and thus
couldn't write a test that ensures they are correct).
- Some dontwarn lines that just suppress warnings.
In addition, this change fixes a couple of related issues:
- Moved AV1 proguard config to correct module.
- Removed mentioning of deprecated ExtractorMediaSource from README
- Suppressed warning from IMA code that prevent proguarding under
strict rules
- Fixed wrong proguard exclusion in VP9 module.
- Moved FLAC exclusion (DefaultExtractorsFactory) to correct module.
- Added AlertDialog suppression for de-jetified code.
- Removed unusued dependency from UI module that causes large APK
size increase.
#exofixit
#minor-release
PiperOrigin-RevId: 344427532
Previously the PlaybackStatsListener needed to handle all events
individually, which required to keep some state of the player and
to resolve potentially transient state changes.
Using onEvents allows to channel all simultanous updates through
one method so that no transient player state and other
inconsistencies need to be handled. This makes the logic easier
to read.
In addition it also allows to resolve all simultaneous events to
use one EventTime (with one timestamp).
#exofixit
PiperOrigin-RevId: 344415459
In many cases it doesn't matter for the test itself how many windows
a timeline has, or even how the timeline of a MediaSource looks like.
And since we introduced the MediaItem-based APIs, single-window
Timelines are the only fully supported Timelines. Thus there is no
point in specifiying this explicitly.
Using these assumptions, we can remove some boilerplate when setting
up standard FakeTimelines or FakeMediaSources with a standard
FakeTimeline.
#exofixit
PiperOrigin-RevId: 344210395
The current code creates placeholder metadata elements if there is no
static metadata. This causes onStaticMetadataChanged callbacks even
if there is no metadata.
Instead, we can keep the empty list as the static metadata is already
documented to be an empty list if the metadata is unavailable.
#exofixit
PiperOrigin-RevId: 344071639
The ref'd issue was marked as a doucmentation candidate, but I think
the confusion likely arises from the lack of "next" and "previous" in
the method names. Our other UI components also support enabling each
button individually, so this also brings notifications in line with
those.
Issue: #6491
#exofixit
PiperOrigin-RevId: 344058969
* These grouping parentheses are unnecessary; it is unlikely the code will be misinterpreted without them
(see http://go/bugpattern/UnnecessaryParentheses) (2 times)
This CL looks good? Just LGTM and Approve it!
This CL doesn’t look good? This is what you can do:
* Suggest a fix on the CL (go/how-to-suggest-fix).
* Revert this CL, by replying "REVERT: <provide reason>"
* File a bug under go/error-prone-bug for category ErrorProneStyle if the change looks generally problematic.
* Revert this CL and not get a CL that cleans up these paths in the future by
replying "BLOCKLIST: <provide reason>". This is not reversible! We recommend to
opt out the respective paths in your CL Robot configuration instead:
go/clrobot-opt-out.
This CL was generated by CL Robot - a tool that cleans up code findings
(go/clrobot). The affected code paths have been enabled for CL Robot in //depot/google3/java/com/google/android/libraries/exoplayer/METADATA which is reachable following include_presubmits from //depot/google3/third_party/java_src/android_libs/exoplayer/METADATA.
Anything wrong with the signup? File a bug at go/clrobot-bug.
#codehealth
PiperOrigin-RevId: 344053269
- Remove restriction on `AdsMediaSource`s in playlists in `ExoPlayerImpl`.
- Allow playing playlists of `AdsMediaSource`s in the demo app.
- Add a sample with ads in a playlist in the demo app.
Issue: #3750
PiperOrigin-RevId: 344018774
*** Original commit ***
Suppress warnings in preparation for Checker Framework 3.7.1 upgrade.
LSC: go/checker-lsc
Tested:
TAP train for global presubmit queue
http://test/OCL:342788973:BASE:342817196:1605636478036:6c558c0c
***
PiperOrigin-RevId: 343895651
This saves a few lines of code and is nicer. We already did make sure to update the notification only once by posting because of b/145521438.
#exofixit
PiperOrigin-RevId: 343852256
The EventTime wasn't part of the onEvents callbacks so far because the
individual events may have different event times (e.g. if they relate to
different media periods). By adding a query method to obtain the
EventTime by event type, we can solve this issue.
#exofixit
PiperOrigin-RevId: 343818819
Mentioning the realtionship on every other callback makes
it easier for the casual developer to understand the
relationship between the methods and discover the existence
of onEvents.
PiperOrigin-RevId: 343811032
Previously, VideoFrameReleaseTimeHelper didn't receive PTS values for
frames that were skipped. This would lead to unnecessary sync loss when
encountering such buffers, because the helper would see a frame-rate
change (i.e., the next frame being significantly longer than previous
ones). After this change, VideoFrameReleaseTimeHelper is notified of
all frame PTS values, so it can retain sync in this case.
This change also propagates onStarted and onPositionReset to the helper.
This paves the way for decoupling frame-rate estimation from release
adjustment sync. Note that currently, loss of sync effectively resets
both. This is unnecessary. For example, if the renderer is paused and
later resumed, then release adjustment sync needs to be reset, but any
frame-rate estimate we have is still valid.
PiperOrigin-RevId: 343803531
*** Original commit ***
Update Styled non bottom buttons to be borderless.
This requires the parent of the background to draw and have padding large enough to support the size of the ripple.
The bottom buttons must remained bordered as the space around them is constrained.
***
PiperOrigin-RevId: 343531411
RunnableFutureTask is not reusable. Trying to reuse it meant that a
failure in one doWork() call would cause subsequent download() calls
to (a) not block until the runnable has finished executing (does not
apply when using a direct executor), and (b) throw the same failure
as thrown from the first doWork() call.
This could cause #8078 if the initial failure occurred before the
content length was resolved. Retries are not blocked on their work
completing due to (a), and the download would be marked as failed due
to (b). The work itself could then resolve the content length, which
causes the stack trace in this issue.
Issue: #8078
PiperOrigin-RevId: 343498252
This callback allows listeners to know when all simultanous changes
have been handled and the values reported through callbacks are
again completely consistent with value obtained from Player
getter calls.
PiperOrigin-RevId: 343476639
When a stream has duplicate timestamps we currently discard to
the last sample with the specified discardTo timestamp, but
it should be the first one to adhere to the method doc and the
intended usage.
#minor-release
PiperOrigin-RevId: 343458870
Background:
1. When the player has multiple audio renderers, by default they share a
single AudioSink.
2. When any new renderer is enabled, all disabled renderers are reset
prior to the new renderer being enabled. This is to give them a chance
to free up resources in case the renderer being enabled needs them. These
reset calls are expected to be no-ops for renderers that have never been
enabled.
The issue:
The problematic case arises when there are two audio renderers and a third
renderer (e.g., text) is being enabled. In this case, the disabled audio
renderer's reset call ends up resetting the AudioSink that's shared with the
enabled audio renderer. The enabled audio renderer is then unable to make
progress, causing playback to freeze.
This is a minimal fix that directly prevents the mentioned issue. There are
multiple follow-ups that would probably make sense:
1. Having ExoPlayerImplInternal track which renderers need to be reset, and
only resetting those renderers rather than all that are disabled. This
seems like a good thing to do regardless, rather than relying on those
calls being no-ops.
2. If we want to continue sharing AudioSink, we need to formalize this much
better and make sure we have good test coverage. Messages like
MSG_SET_VOLUME are also delivered to the AudioSink multiple times via
each of the renderers, which works currently because DefaultAudioSink
no-ops all but the first call in each case. This is pretty fragile though!
Issue: #8203
#minor-release
PiperOrigin-RevId: 343296081
Real apps probably aren't going to be allowing playback speed to be
set to anything other than the options listed in their UI, and so
this is not worth the complexity.
It also violates the idea that the UI should look the same regardless
of when the player is set on the view, since if it's set and then the
playback speed is changed to a listed option then the custom speed
remains, where-as if the speed is changed to a listed option and then
it's set, the custom speed will not be shown.
PiperOrigin-RevId: 343260450
*** Original commit ***
Suppress warnings in preparation for Checker Framework 3.7.1 upgrade.
LSC: go/checker-lsc
Tested:
tap_presubmit: http://test/OCL:342788975:BASE:342885903:1605667635149:7731b723
Some tests failed; test failures are believed to be unrelated to this CL
***
PiperOrigin-RevId: 343251530
ExoPlayer's traditional HLS preparation works by loading a chunk from each track
group, and then tries to use the sample information plus the master playlist
information to generate the preparation's resulting TrackGroups.
There are 3 possible scenarios:
- Supported case: Each variant has a single codec string per track type. We can
assign each track the codec string which matches the loaded sample's type.
- Supported case: Each variant has more than one codec string, but each track
group has a single track. This is the case when different languages use
different codecs. In this case, we can assign whichever codec matches the
loaded sample's mime type.
- Unsupported case: Each variant has more than one codec string, and track
groups contain more than one track. We are not able to safely map tracks to
codec strings because that would require loading a chunk from each track
(which would considerably delay preparation).
Broken in:
4783c329cc
PiperOrigin-RevId: 343072201
This only has a couple of simple tests for now. We'll add more tests
after we've written some concrete sub-class tests for various
DataSource implementations.
I've included a concrete FileDataSourceContractTest as a demonstration.
PiperOrigin-RevId: 342851187
This ensures the buffer is not full when the `DefaultLoadControl` determines
whether we should continue loading and thus prevents a false warning about
not having enough memory left.
PiperOrigin-RevId: 342616623
This requires the parent of the background to draw and have padding large enough to support the size of the ripple.
The bottom buttons must remained bordered as the space around them is constrained.
PiperOrigin-RevId: 342162231
Add experimental method to synchronize MediaCodec interactions
with asynchronous queueing. When the feature is enabled, interactions
such as MediaCodec.setOutputSurface() triggered by the
MediaCodecRenderer will wait until all input buffers pending queueing
are first submitted to the MediaCodec.
PiperOrigin-RevId: 341423837
To check what is safely possible we keep track of the live offset
corresponding to the buffered duration and only deecrease the
target offset to a safe margin from the buffered duration.
Also, while still possible (i.e. while the actual offset is larger
than the safe margin), we increase the target offset to the safe
margin to avoid rebuffers to start with.
Issue: #4904
PiperOrigin-RevId: 341396492
Add more MediaCodec methods to MediaCodedAdapter so that renderers
interact with the MediaCodec through the MediaCodecAdapter.
PiperOrigin-RevId: 341023452
- This change removes the last piece of logic that could cause deferred
codec release (i.e., where the decision to release was made in
processEndOfStream rather than in onInputFormatChanged.
- After this change, whether the codec will be released as a result of
a format change is always established in onInputFormatChanged.
PiperOrigin-RevId: 341012403
This fixes a case where updateCodecOperatingRate would configure
the decoder to be drained and then released, only for
onInputFormatChanged to override the drain action with something
else.
We've not seen any reports of this issue, which suggests that either
it's OK to not release the decoder in such cases, or that the
case doesn't happen very often. I suspect that it's both, but let's
restore the intended behaviour for now.
PiperOrigin-RevId: 340909132
This information is already available in the MappingTrackSelector,
but not currently forwarded to the TrackSelection.Factory.
This makes it more complicated (or impossible) to depend on period
or manifest information in the track selection (for example to only
select tracks which are cached for the current format).
PiperOrigin-RevId: 340605886
In a later change, the AdPlaybackState will include the playing adsId (set by
the AdsLoader) and the ads loader will use this to determine what ad
information is associated with the playing/next periods, to allow loading ads
in playlists.
Apps can continue to pass just a URI for an ad tag with their MediaItem, in
which case the associated playlist will request that ad tag just and the same
state will be used for all occurrences of the ad tag.
This change has breaking changes to the AdsLoader interface and removes
deprecated ways of passing the ad tag, as it's very likely to go into a major
release anyway and not needing to handle the deprecated cases simplifies
ImaAdsLoader.
Issue: #3750
PiperOrigin-RevId: 340438580
By default methods File.makeDir() and File.makeDirs() can return 'false' if file aleady exists or can not be created. Such silent ignore of the situation propagates misbehavior to the caller: CacheDataSink#173 : new FileOutputStream(file). And then it throws not correct exception type 'FileNotFoundException'. While correct exception should be 'no space left on the device'.
This can be fixed only with 'Files.createDirectories()' method that throws correct exception type.
1. Move logic to decide to re-initialize the codec rather than using
MediaCodec.setMediaDrmSession if (a) PlayReady is in use, and (b)
the new session is still provisioning. This would previously have
happened asynchronously after an input format change, after the
decoder has subsequently been flushed. After this change the logic
executes synchronously when the input format changes. This helps
with the ref'd bug, since we want to propagate reasons for codec
re-initialization through inputFormatChanged events.
2. Whilst moving the logic for re-initialization if PlayReady is
being used, I fixed a bug that would occur when switching from
[PlayReady --> non-PlayReady]. Re-use doesn't work in this case.
The old logic only checked for the [Something --> PlayReady] case.
3. Remove pointless codec flush if updating the DRM session having
not queued anything to the codec.
PiperOrigin-RevId: 340299790
- I don't think the session recovering later would work, because
the codec will be configured not to use it.
- I'm not sure session recovery makes sense in general, and our
implementations do not do this. Document it as a terminal state
for now.
PiperOrigin-RevId: 340204194
This avoids confusion that currently exists between "operating rate"
and "codec operating rate", which are different. It also tightens the
requirement of the value being passed to be more than a "hint". It's
already being used as more than a hint for setting the Surface frame
rate.
PiperOrigin-RevId: 340201829
Some content types always provide the license URL in the media.
The PlayReady example in the demo app doesn't provide a default
license URL for this reason, as an example.
#minor-release
PiperOrigin-RevId: 340125784
This change will be followed up by:
- Changes adding APIs to enable the use of MediaParser in each of the supported
media sources.
- Changes removing TODOs related to the change of the stable SDK to API 30.
PiperOrigin-RevId: 339556777