- Support setting the user-agent in CronetDataSource
- Support setting the default user-agent in CronetEngineWrapper
- Use the underlying network stack's default user-agent by
default. Many applications will configure the underlying
CronetEngine or OkHttpClient with a user-agent that they
expect to be used throughout their app, so always overriding
this with our own default, on reflection, is not the best
thing to do!
Issue: #8395
PiperOrigin-RevId: 350921963
BatchBuffer has three different clear methods (clear, flush,
batchWasConsumed), and it's not hugely clear what each of them
does. In general, BatchBuffer owning the sample buffer seems
more complicated than having the caller own it, particularly
when it can be "pending" inside of the batch buffer.
This change moves ownership of the sample buffer to the
caller. BatchBuffer is simplified as a result. There are also
two behaviour changes:
1. The buffer's timeUs field is now set to the first sample's
timestamp, rather than the last sample's.
2. A key-frame in the middle of the batch no longer causes the
batch buffer to be considered a key-frame. Which seems like
the right thing to do, because the batched data cannot be
decoded independently of whatever came before it.
PiperOrigin-RevId: 350921306
*** Original commit ***
Merge #8401: Initialize Format.codecs from HEVC SPS NAL unit (#8393)
Imported from GitHub PR https://github.com/google/ExoPlayer/pull/8401
This will allow ExoPlayer to check if video track's profile and level are supported by decoder when playing progressive media sources.
Merge e582fb91b73c7c95e754167140211d5473c36d14 into 1347d572ef
Issue: #8393
***
PiperOrigin-RevId: 350871621
I think this was missed when integrating DefaultMediaSourceFactory with
SingleSampleMediaSource.Factory in
315ba6f324
Issue: #8430
#minor-release
PiperOrigin-RevId: 350759580
There is a race condition when initializing the downloads database. The
constructor of the DownloadManager kicks-off the database initialization
in its internal thread, but at the same time an app can try to access
the database directly through the manager's download index, e.g. doing
DonwloadManager manager = new ...
manager.getDownloadIndex().getDownload("id");
might enter DefaultDownloadIndex.ensureInitialized() from two threads.
When upgrading the downloads table from version 2 to version 3, the
first thread that enters the database transaction in ensureInitialized()
will drop and recreate the table using the v3 schema. Then, the second
thread will attempt to read from the newly created table using the v2
schema, which will fail.
This race condition was not introduced in 2.12 but was there already.
However, prior to 2.12, the code only dropped and re-created and the
table and did not attempt to read any data. Hence, if the race condition
happened, the code would drop and create the table twice, but no error
would occur.
Issue: #8420
#minor-release
PiperOrigin-RevId: 350745463
Imported from GitHub PR https://github.com/google/ExoPlayer/pull/8401
This will allow ExoPlayer to check if video track's profile and level are supported by decoder when playing progressive media sources.
Merge e582fb91b73c7c95e754167140211d5473c36d14 into 1347d572ef
Issue: #8393
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/ExoPlayer/pull/8401 from equeim:hevc-codecs e582fb91b73c7c95e754167140211d5473c36d14
PiperOrigin-RevId: 350738065
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: 350590722
Without this feature it's impossible to nicely merge multiple sources
with different durations if these durations are not known exactly
before the start of playback.
Issue: #8422
PiperOrigin-RevId: 350567625
This allows to set preferences based on MIME type for video and audio.
The MIME type preference is applied after other explicit preferences
and restrictions (e.g. language or max resolution), but before implicit
preferences like bitrate.
Issue: #8320
PiperOrigin-RevId: 350550543
Add assertion to check an output format has been propagated before
returning an output buffer when operating MediaCodec in asynchronous
mode.
PiperOrigin-RevId: 350534918
`stop(true)` is almost the same as `clearMediaItems(); stop();`, except that
any player error isn't cleared. Clearing media items more clearly expresses the
intent.
PiperOrigin-RevId: 350516748
In many cases we just used "playback speed" as a detailed Javadoc
parameter or return type definition. This doesn't define which scale
the speed is using.
PlaybackParameters as the main point to set the speed already uses a
more precise wording to describe the value as a factor by which playback
will be sped up.
This change replaces other usages of "playback speed" with this wording
whereever we would usually add a unit, keeping "playback speed" for
summary statements etc to reference the general concept that doesn't
usually require a unit.
PiperOrigin-RevId: 350379139
The experimental setting shows positive results and can be turned
on by default. To avoid adaptation between HLS audio formats without
bitrates, we need to ensure that only formats with bitrates are
considered for adaptation.
Also added tests for these features.
Issue: #5111
PiperOrigin-RevId: 350315296
The AsynchronousMediaCodecCallback has logic to retain a pending
output format in case flush() is called. This commit fixes a case where
calling flush() again while an output format is pending would nullify
the pending output format.
A unit test is added in AsynchronousMediaCodecCallback but not the
AsynchronousMediaCodecAdapter. That is because the adapter operates
directly on top of MediaCodec, but Robolectric's ShadowMediaCodec
produces an output format on every MediaCodec.start(). This is
unrealistic when operating MediaCodec in asynchronous mode where we
need to call MediaCodec.start() after every MediaCodec.flush().
PiperOrigin-RevId: 350176659
- The AdaptiveTrackSelection doesn't need to use the experimental
terminolgy because the code is always triggered if there are multiple
adaptive selections.
- It's also confusing to pass the state on the outside after the object
creation, so moving everything into a simple control flow again where
the adaptation checkpoints are passed in via the constructor.
- Instead of triple arrays, we can use more readable named structures.
- The calculation of the checkpoints can be cleaned up to be more
readable by moving things to helper methods.
- The reserved bandwidth from all fixed track selections is really just
a special case of multiple parallel adaptataions. So this logic doesn't
need to be separate.
- The whole logic also didn't have test coverage so far. Added tests
for the actual adaptation using these checkpoints and the builder
calculating the checkpoints.
Overall this should be a no-op change.
PiperOrigin-RevId: 350162834
In this change -
Handling the sequence number discontinuity in caption channel packet header.
The processCurrentPacket returns if the packet length does not match with the currentIndex. That assumption is wrong. As per spec the the packet can end on reception of next cc_type = 0x3.
if responseCode and responseMessage ara available always throws an InvalidResponseCodeException instead of HttpDataSourceException, so in onPlayerError method the http status code and message can be used to decide what will be the next step.
This will allow ExoPlayer to check if video track's profile
and level are supported by decoder when playing progressive media sources.
Also fix typo in AvcConfig.
*** Original commit ***
DataSource.open() throws if already opened.
Update DataSource implementations to throw an error if open() is called
when the DataSource is already open.
***
PiperOrigin-RevId: 348783425
Estimating the playback frame-rate, querying the display refresh rate, and
setting the surface frame-rate, are all closely related to one another. In
particular because setting the surface frame-rate can directly cause the
display refresh rate to change. It therefore makes sense to move surface
frame-rate adjustment into the helper.
This also makes it easier to re-use the logic in other video renderers.
PiperOrigin-RevId: 348455864
This replaces all the duplicated logic previously implemented in
FakeSampleStream and more closely follows the pattern of how
SampleStreams are used from real MediaPeriods.
Some tests needed adjustments because using real the SampleQueue
improved behaviour:
- Waiting for isLoading is only needed once even across period
boundaries because the real SampleQueue doesn't have the on/off
pattern.
- AnalyticsCollectorTest.playlistOperations() was wrongly asserting
that some pre-buffering events. The new version is more intuitively
correct we pre-buffer the second item during the initial loading
phase (thus period1seq1) and keep the buffer in the queue after
the removal operation.
PiperOrigin-RevId: 348440255
The delta updates loose information about previous init segments.
Until this is properly fixed, we can avoid the problem by not
using delta updates.
Issue: #5011
PiperOrigin-RevId: 348023895
If we have trailing parts the available window should reach to
the end of all trailing parts and not only to the last finished
segment.
Issue: #5011
PiperOrigin-RevId: 347996626
I decided not to migrate all the tests in one CL to keep the diff
manageable. I'll make follow-up CLs to migrate the tests, and eventually
delete TeeCodec and all associated logic.
I couldn't completely remove the dump diff because
ShadowMediaCodec.getCodecInfo() (which would give me access to the MIME
type) doesn't seem to work properly - it returned video/avc when
name=exotest.audio.aac, and looking into the code it looks like there's
some native methods that are missing shadow implementations.
PiperOrigin-RevId: 347991956
The adaptive period currently extends the base (non-adaptive) period
to share common MediaPeriod boilerplate code.
However, once we start using the real SampleQueue in FakeMediaPeriod
the common code becomes even less and the overhead to support
multiple stream implementation from the base class is no longer
worth it. Thus, this change removes the class hierarchy and copies
the common parts to FakeAdaptiveMediaPeriod.
PiperOrigin-RevId: 347990468
This was added due to a misunderstanding - we're more interested in
testing the edge case of trying to read the last zero bytes of a
non-zero-byte resource.
In a future change I want to be able test reading a subrange, so each
TestResource will need to be at least N bytes long.
PiperOrigin-RevId: 347980843
PlaybackStatsListener has a method whose original intention was to be
called when the player is releaed to finish all pending sessions.
However, this also meant that later events (e.g. onVideoDecoderDisabled)
could create new sessions because the old one was already finished.
Use the new onPlayerReleased callback to implement this properly and to
fix the unintentional new session creation.
PiperOrigin-RevId: 347809527
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
In order to ensure we can update the values for new manifests but still use
the user provided override, we need to save the original and the updated MediaItem
seperately.
And in order to incorporate the existing logic for the min/max supported live
offset, which we already use to correct the target offset, also move both places
together so that all the adjustment happens in one place.
Logical adjustments to the previous min/max supported live offset:
- Use the user-provided MediaItem values if set
- Use the newly parsed ServiceDescription values if available.
- Limit the minimum to 0 if the current time is in the window and we can
assume to have low-latency stream.
- Add minBufferTime from the manifest to ensure we don't reduce the live
offset below this value.
Issue: #4904
PiperOrigin-RevId: 339452816
Logic for determining if (and how) decoders can be adapted is
currently split between renderers and MediaCodecInfo. This change
centralizes the majority of the logic in MediaCodecInfo.
This change also fixes a bug in MediaCodecAudioRenderer when computing
max values for the codec. Previously, max values would not be increased
to account for potential adaptation to another stream in the case that
the codec needs to be flushed for the adaptation to occur.
PiperOrigin-RevId: 339133416
Refactor the AsynchronousMediaCoderAdapter and move the callback thread
out of the adapter so that implementation of async callback and and
async queueing are consistent design-wise.
PiperOrigin-RevId: 338637837
This change fixes format creation for traditional preparation of streams
where the master playlist contains more than one codec string per track
type.
Issue: #7877
PiperOrigin-RevId: 338538693
When disabling a TsExtractor track type because of a missing codec
in the master playlist, look through the entire codecs string
instead of checking the first codec with matching type.
Issue: #7877
PiperOrigin-RevId: 338530046
The current caluclation was comparing Unix time with period time.
Fix it by always comparing against period time.
Issue: #4904
PiperOrigin-RevId: 338235754
We currently implicitly rely on the internal playback thread to not send
new updates after the player got released. This may not always be ensured
since we let the release call timeout. For the timeout case, there may
still be a pending operation returning much later when it unstuck itself.
Fix this and potential other edge cases by explicitly removing all listeners
and preventing new listeners from being added after the release.
PiperOrigin-RevId: 338217220
Skip assets with >2 audio channels - this isn't
currently supported by ShadowAudioSystem. I'll add these when support is
available.
Also skip sample_ac4_protected.mp4 because DRM isn't supported in this
test environment either.
PiperOrigin-RevId: 338023738
I added the TS playback tests for these assets without adding support
for the relevant MIME types to ShadowMediaCodec.
Also remove test assets with more than 2 audio channels - this isn't
currently supported by ShadowAudioSystem. I'll re-add these when support
is available.
PiperOrigin-RevId: 338023290
The available duration used a "live edge" that was calculated in
the previous iteration and was thus quite old. Also it also used
the end of the last available segment, but the actually available
duration for buffering needs to be clamped to the current live edge
for low-latency streams.
Issue: #4904
PiperOrigin-RevId: 337812621
ExoPlayerImpl and CastPlayer repeat the same logic. Moving the listener
and event handling to a common util class allows to reuse the same code
and add unit tests for this logic.
The change is a functional no-op.
PiperOrigin-RevId: 337812358
This was causing issues old devices where the class
inheriting StreamEventCallback was loaded even though
it was not used.
Instead use an anonymous class that seem to be loaded
more lazily.
PiperOrigin-RevId: 337252687
The 'implementation' dependency causes problems when resolving
ListenableFuture in contexts that also include the
com.google.guava:listenablefuture:1.0 dependency.
Issue: #7905
Issue: #7997
Issue: #7993
PiperOrigin-RevId: 337093024
This moves TestUtil#runMainLooperUntil and
TestUtil#createRobolectricConditionVariable to a new RobolectricUtil
class.
Also move testutil classes that use Robolectric-related utils classes
(e.g. TestPlayerRunHelper, TestDownloadManagerListener).
PiperOrigin-RevId: 336864959
1. The first time the player controls are are made visible,
there is no animation.
2. The first time the player controls are made visible, the
"select tracks" button isn't displayed. When tapping to
subsequently hide the player controls, the button briefly
becomes visible and then is hidden again. This bug is due
to state in StyledPlayerControlViewLayoutManager being
out of sync, resulting in StyledPlayerControlView's
onVisibilityChange not being called properly.
After this change both of these issues should be resolved.
PiperOrigin-RevId: 336704031
We stopped using using this MIME type in
74a9d8f680
This broke subtitle decoding in some cases (Issue: #7985), which I
fixed in
7b8895d655.
After some discussion we've decided SubtitleDecoderFactory shouldn't
depend on Format.containerMimeType (since the samples have already been
extracted by this point, so the container shouldn't matter). So this
change fixes DashManifestParser to use MimeTypes.APPLICATION_MP4VTT (and
reverts the no-longer-needed SubtitleDecoderFactory change).
PiperOrigin-RevId: 336668450
TestExoPlayerBuilder can be used from both emulator and robolectric
tests, TestPlayerRunHelper uses Robolectric Looper behaviour, meaning
it can be moved to the robolectricutils module in a follow-up change.
PiperOrigin-RevId: 336634225
Adjusted the bottom layout of StyledPlayerControlView :
- Enlarged bottom button's height to make tapping easier.
- Extended greyed background area to upper edge of seekbar.
- Gave padding between bottom edge of the overall layout and bottom buttons.
- Reduced horizontal margins between bottom buttons.
PiperOrigin-RevId: 336041160
Previously, the overflow button was always shown at the bottom in StyledPlayerControlView
and hided the settings cog even when there is enough space.
With this change, the settings cog moves out from overflow and
the overflow button is shown only when the buttom space is not enough.
PiperOrigin-RevId: 336029179
Experiments showed the timeout is beneficial to avoid ANRs and
we can thus enable the feature by default.
Also add configuration to set the timeout if required.
Issue: #5887
PiperOrigin-RevId: 335652506
Using a timeout prevents ANRs in cases where the underlying platform
gets blocked forever, so we enable this feature by default.
Issue: #4352
PiperOrigin-RevId: 335642485
This is in preparation for supporting playlists of ads media sources using
ImaAdsLoader.
Existing ways of passing ad tags should still function but are deprecated (and
won't be supported with playlists).
Issue: #3750
PiperOrigin-RevId: 335618364
`subtitle` is only guaranteed to be non-null if
`nextSubtitleEventIndex != C.INDEX_UNSET`. The null check added in
0efec5f6c1
was too early.
Issue: #8017
PiperOrigin-RevId: 334777742
This was broken by 74a9d8f680
because DashManifestParser switched to setting Format.sampleMimeType to
text/vtt while SubtitleDecoderFactory was still expecting
application/x-mp4-vtt. This change teaches SubtitleDecoderFactory to
check both Format.containerMimeType and Format.sampleMimeType.
I'll investigate a follow-up change to remove
MimeTypes.APPLICATION_MP4VTT completely (it's currently still used in
AtomParsers).
Issue: #7985
PiperOrigin-RevId: 334771672
In the test, a real instance of SimpleExoplayer plays two identical Mp3 files.
The GaplessMp3Decoder will write randomized data to decoder output on receiving
input. The test compares the bytes written by the decoder with the bytes
received by the AudioTrack, to verify that the trimming of encoder delay/
padding is correctly carried out.
Test mp3 has delay 576 frames and padding 1404 frames. File generated from:
ffmpeg -f lavfi -i "sine=frequency=1000:duration=1" test.mp3
This change needs robolectric version 4.5, which is not currently released (2020 Sep 30).
PiperOrigin-RevId: 334648486
When I moved ParsableByteArray#data behind a getter I replaced some
assignments with calls to reset(byte[]):
ce2e6e2fd6
reset(byte[]) deliberately sets `limit` to `data.length`, in order to
handle cases that were reassigning `data` but not updating `limit`.
However OggPacket was already using `limit` to track where to write
'new' data into the array, so changing `limit` to `data.length` caused
us to try and write new data beyond the end of the array.
I looked at other uses of reset(byte[]) in ce2e6e2fd6
and condluded the only other usage in MatroskaExtractor is legit and
shouldn't be updated like this (because MatroskaExtractor previously
*wasn't* correctly updating/maintaining `limit`).
Issue: #7992
PiperOrigin-RevId: 334601586
Non-realtime AudioTrack playback speed was not taken into account when
extrapolating the old mode's position, causing the position not to
advance smoothly.
This should be a no-op when not using AudioTrack playback params for
speed adjustment.
Issue: #7982
PiperOrigin-RevId: 334151163
Remove the SynchronousMediaCodecBufferEnqueuer interface
since we only keep the AsynchronousMediaCodecBufferEnqueuer
implementation.
PiperOrigin-RevId: 333701115
Retry AudioTrack init and write for 100ms before
giving up and aborting playback.
This was tested by throwing every 2 init/write and
making sure playback did not stopped.
#exo-offload
PiperOrigin-RevId: 333536841
This issue has been observed on a test app stress
testing setEndOfStream.
The issue has not been observed on ExoPlayer,
probably due to timing differences, but it is fixed
preventively.
#exo-offload
PiperOrigin-RevId: 333472136
This seems to be an exact copy of sample.adts. Update the test to use
the same sample but just output to a different dump file.
PiperOrigin-RevId: 333469714
We have a workaround for uneven sample stream durarions in playlists that
assumes a renderer allows playback if it's reading ahead or waiting for
the next stream.
652c2f9c18 changed this logic to no longer require to
wait until the next stream is prepared due to a change in how we advance
media periods in the queue. However, the code falsely still requires the
next stream to exist (even if it's not prepared). This can cause a stuck
buffering state when the difference in the duration of the streams is more
than what we buffer ahead because we never create the next stream in such
a case.
Note: DefaultMediaClock.shouldUseStandaloneClock has roughly the same logic
and also doesn't require the next stream to be present.
Also fix a test that seemed to rely on this stuck buffering case to test
stuck buffering detection. Changed the test to not read the end of stream
to ensure it runs into the desired stuck buffering case.
Issue:#7943
PiperOrigin-RevId: 333050285
This allows to use the same logic from multiple places without duplicating
it, encapsulates in its logical place, and allows to change the available
segments based on the new availabilityTimeOffset value.
The overall effect of this change is a no-op.
PiperOrigin-RevId: 333044186
Without this patch, playback would be frozen indefinitely
until the user manually pauses and unpauses it.
This has the side effect of disabling offload until
the next stop due to the workaround of
disabling offload when it encounters a failure.
As an audio server crash is considered very
infrequent, especially in stable conditions like
an audio only playback, it is unlikely that disabling
offload is an issue.
PiperOrigin-RevId: 332857094
I didn't copy-paste the whole of
https://github.com/google/guava/wiki/UsingProGuardWithGuava because
this line seems relevant based on our current usage.
Lots of that file seems to relate to classes that are strongly
discouraged on Android:
https://github.com/google/guava/wiki/Android#specifics
I've only added this to the `common` module, since everyone that uses
ExoPlayer must depend on that. This avoids duplicating this line into
every module that has a Guava dependency.
Also remove some other warning suppressions that are defined in both
`core` and `common`.
Issue: #7904
PiperOrigin-RevId: 332203086
This value is needed to figure out the last available segment for
low-latency live streaming. It may be present in each BaseURL tag
and each SegmentList or SegmentTemplate, with the latter one taking
precedence.
The value is saved as part of MultiSegmentBase where it will be used
to retrieve the last available segment index in future changes.
PiperOrigin-RevId: 331809871
This test is intended to check that DefaultLoadControl will cause
playback to fail as "stuck buffering" rather than OOM-ing, in the
case that its target buffer size is reached and playback still
hasn't started.
Unfortunately, the target buffer size is ~130MB, and when running
on some setups an OOM actually ends up happening before this much
memory is allocated.
This change makes the target buffer size much smaller to avoid the
problem.
PiperOrigin-RevId: 331748208
This may remove available memory from other tests running in the same
process. Instead, create the huge buffer when needed so it can be GCed
immediately.
PiperOrigin-RevId: 330960844
When passing in ExtractorFactory instances to SimpleExoPlayer.Builder or
DefaultMediaSourceFactory, we currently need to pass in one other
instance (RenderersFactory or DataSource.Factory), that developers will
often set to its default. To avoid specifying these defaults, these new
convience methods allow to just set the ExtractorsFactory if required.
PiperOrigin-RevId: 330908002
This allows to customize extractor flags more easily when setting up the player.
In addition, we need to provide a way to pass in the ExtractorFactory through
the constructor chain starting in SimpleExoPlayer so that removing the
DefaultExtractorsFactory is possible for R8.
PiperOrigin-RevId: 330472935
- Use a setter, which is consistent with how other optional
components are passed.
- Remove nesting where a provider provides another provider.
Since AdSupportProvider then only provides one thing, it
can be renamed to AdsLoaderProvider, which more clearly
expresses what it provides.
PiperOrigin-RevId: 330396334
- Prevent buffering when clicking ffwd button at the end of stream
- Set VR button disabled when listener is not registered
PiperOrigin-RevId: 330039336
In maybeInitCodecWithFallback, it caches availableCodecInfos with mediaCryptoRequiresSecureDecoder and inputFormat as inputs, and won't clear it if shouldInitCodec is false, resulting in a case where availableCodecInfos is not null and codec is null.
When we have a new format, it's reasonable to clear availableCodecInfos if codec is null. Otherwise we might not be able to properly initialize a new codec.
PiperOrigin-RevId: 329971796
This CL fixes two bugs:
- Play/pause button toggling looked inconsistent when playback fails.
When player state goes into idle, play button should dispatch
playwhenready again.
- Clicking play button at the end of stream should restart playback.
But previously it changed playwhenready state and so playback has
been paused. This CL fix it.
PiperOrigin-RevId: 329675660
1. Add EventLogger right away in PlayerActivity, else it doesn't log
playWhenReady being initially set to true.
2. Remove EventLogger logging for the audio position advancing. It's
redundant with isPlaying logging unless you're very specifically
interested in the timing difference.
3. Remove unnecessary comment in Player.
4. Fix Timeline Javadoc.
PiperOrigin-RevId: 328983944
In 2.11.2 to 2.11.5, we considered all AAC streams as consisting
only of sync samples. In 2.11.6+, we considered no AAC streams as
consisting of sync samples, because the property is not guaranteed
specifically for xHE-AAC. This will have caused a small regression
is seek speed for some types of media.
This change brings back the optimization for AAC, specifically
excluding only xHE-AAC (and cases where we don't know what type of
AAC we're dealing with).
PiperOrigin-RevId: 328950697
To play slow motion streams where the audio has been recorded at
slower speeds, it is necessary to be able to resample (rather than
time-stretch) the audio. This change undeprecates back the previously
deprecated PlaybackParameters class to allow apps to set pitch.
PiperOrigin-RevId: 328703116
We currently always reset everything if playingPeriod != readingPeriod.
However, this is only needed when the pausing is actually required, i.e.,
if the feature is enabled and we are in the last period of the window.
PiperOrigin-RevId: 328141242
Currently the audio renderer can become ready before the AudioTrack
actually has enough data to play something, which means that the
player may transition to the ready state before audio starts
playing. This makes the player's current state transition not very
useful for detecting when audio actually starts playing.
This change adds a new event to notify apps when the audio position
is increasing after a pause or seek/flush/reset event, and includes
an estimate of the system time at which audio playout started.
Issue: #7577
PiperOrigin-RevId: 327810040
This allows us to more easily create different dumps derived from the
same assets.
This moves media/source files from `assets/` to `assets/media/` and
dump files from `assets/` to `assets/extractordumps/` and
`assets/audiosinkdumps/` as appropriate. I intend to add
`assets/playbackdumps/` in a future CL.
PiperOrigin-RevId: 326986283
There were two bugs in StyledPlayerControlView:
- Center icons are shown when toggling control view in minimal mode.
- `StyledControlView#setShow{*}Button` methods and corresponding
`set_show_*_button` attributes didn't work properly.
This CL fixes bugs by controlling the buttons' visibility in one place,
StyledPlayerControlViewLayoutManager.
PiperOrigin-RevId: 326567213
AudioTrack.setPlaybackParams can be used to adjust playback speed.
This is preferable to application-level speed adjustment (currently
implemented in ExoPlayer) from API 23 because the speed change
occurs in the mixer, which means that the audio track buffer doesn't
need to drain out before the speed adjustment takes effect.
Issue: #7502
PiperOrigin-RevId: 326392301
formatSupport is a 2-dimensional int array but it's documented as
being indexed by 3 things. This seems to be a copy-paste mistake in
e97b8347eb
selectAllTracks() takes a 3-dimensional array with the same
3-indexed documentation, which makes sense there.
Also rename formatSupports -> formatSupport for consistency.
PiperOrigin-RevId: 325779435
Use a dedicated boolean to track if we've notified the current surface,
rather than re-using rendereredFirstFrameAfterReset.
PiperOrigin-RevId: 325757948
Find sbgp and sgpd boxes with grouping_type == seig in the case they don't
come first. Previoulsy we would only find them if they came first.
Issue: Issue: #7716
PiperOrigin-RevId: 325407819
*** Original commit ***
Rollback of bf5e6c7862
*** Original commit ***
Pass startPositionUs into Renderer.replaceStream
Plumb this down into BaseRenderer.onStreamChanged and use it when
deciding whether to render the first frame of a new period.
***
***
PiperOrigin-RevId: 325251261
*** Original commit ***
Rollback of bf5e6c7862
*** Original commit ***
Pass startPositionUs into Renderer.replaceStream
Plumb this down into BaseRenderer.onStreamChanged and use it when
deciding whether to render the first frame of a new period.
***
***
PiperOrigin-RevId: 325218588
- Attach types for placeholder sessions. If a placeholder session will be
attached and a downstream renderer doesn't know what to do with it, then
this attachment is necessary to correctly determine that the renderer
does not support the track.
- Attach types to sample formats. Without this, if playback fails due to
a CryptoException, the ExoPlaybackException that gets thrown spuriously
indicates that the format's DRM type was not supported.
PiperOrigin-RevId: 325214745
Having both in the trun box is not allowed (see section section 8.8.8.1
of ISO/IEC 14496-12:2015) but this CL makes the code more robust in case
this happens. Before this change, the first sample flag was not read,
making subsequent reads incorrect.
Issue: #7698
PiperOrigin-RevId: 325212160
The sniffer sniffs boxes at the start of the file to try and determine
whether the file is fragmented. However, if the file is extremely short
then it's possible that sniffing will try and read beyond the end of
the file, resulting i EOFException being thrown.
In general it's OK for sniffing to throw EOFException if the file is
not of the correct type. The problem in this case is that EOFException
can be thrown for an actual MP4 file, due to the sniffer continuing up
sniff atoms up to bytesToSearch in case the file is fragmented.
PiperOrigin-RevId: 325205389
The term "passthrough" was heavily overloaded. For clarity, split most
of its usage to different terms:
* codec "bypass": no MediaCodec is used
* "direct playback": no decoding occurs (but decryption may or may not)
* "decrypt only codec": a MediaCodec used only to decrypt, not decode
* "offload": playback to an offload AudioTrack.
* "passthrough" is now only used in the sense of playing encoded audio
* to a non offload AudioTrack.
PiperOrigin-RevId: 324984612
We are not able to associate a codecs attribute to an EXT-X-MEDIA tag if
there is no variant with a matching AUDIO GROUP-ID. Lack of codecs string
prevents chunkless preparation from determining the track type.
Issue: #7678
PiperOrigin-RevId: 324822415
It seems generally useful to have access to the decoder in
getOutputFormat. We're currently working around lack of access
by using member variables in the concrete audio extension
renderers. In the case of the Ffmpeg extension, holding a
reference to the decoder is preventing it from being garbage
collected when the decoder is released by the base class.
PiperOrigin-RevId: 324799670
After discarding upstream we shouldn't reuse the extractor from the
(newly) last media chunk because the extractor may have been reused
already by the discarded chunks.
Also add an assertion to SampleQueue that prevents the hard-to-detect
failure mode of overlapping sample byte ranges.
Issue: #7690
PiperOrigin-RevId: 324785093
This callback was not notified before, which could theoretically lead to ad
loading timing out. In practice it doesn't currently happen because the timeout
appears to start when the ad cue point is reached, not when loadAd is called.
We notify onLoaded when the ad media period is prepared (for HTML5 the
recommendation is to notify on the HTMLMediaElement 'canplay' event, which this
roughly corresponds to).
PiperOrigin-RevId: 324568407
Issue: #7244 added this feature to HLS. This change is the exact copy
in ChunkSampleStream to add the same support to the other adaptive
formats.
Note that ChunkSampleStream doesn't support slicing, so we can't cancel
a read-from chunk, and we need to prevent reading into an already
canceled chunk load so that the chunk can be automatically discarded
after the cancelation.
Issue: #2848
PiperOrigin-RevId: 324179972
Wrapping MediaCodec ISEs in MediaCodecDecoderException lets us attach
MediaCodecInfo, which contains lots of useful information such as the
MediaCodec name, the codec capabilities, etc.
PiperOrigin-RevId: 323575782
*** Original commit ***
Pass startPositionUs into Renderer.replaceStream
Plumb this down into BaseRenderer.onStreamChanged and use it when
deciding whether to render the first frame of a new period.
***
PiperOrigin-RevId: 323447253
It's potentially confusing that this resets both position & limit, so
require callers to pass `limit` explicitly, or call setPosition(0)
if that's actually what they intended.
This makes enforcing the limit in an upcoming change slightly safer.
PiperOrigin-RevId: 323340485
This allows us to enforce the limit because the array can only be
reassigned through reset(byte[]) or reset(byte[], int) (which update
the limit)
PiperOrigin-RevId: 323339960
This removes Supplier, Function and Predicate. Consumer is kept because
Guava doesn't have an equivalent (Java 8 does, but we can't use that
yet).
#exofixit
PiperOrigin-RevId: 323324392
MP3 is last in the sniffing order now, so I think it's fine to do this
without worrying about impacting on other file types.
PiperOrigin-RevId: 322996771
We currently mix point-based systems with Comparable-based systems.
This switches all scoring to using Comparable and modernizes it by
using ComparisonChain.
Using Comparator chains is more maintainable than point systems because
the reader doesn't have to think about all combinatorial combinations
of points.
PiperOrigin-RevId: 322766278
These callbacks were only necessary to track the queue in AnalyticsCollector and there is no other known benefit of having them.
PiperOrigin-RevId: 322535274
This commit duplicates some code from the testutils module
in common test in order to break the dependency from testutils.
PiperOrigin-RevId: 322366013
This only manifests when turning ParsableByteArray#data into a getData()
method but I'm fixing it beforehand to avoid introducing changes into a
big refactoring change.
#exofixit
PiperOrigin-RevId: 322342497
The dependency is only used to create a dialog in
TrackSelectionDialogBuilder that is compatible with newer styling
options.
This dependendy adds over 500Kb to the apk (even if unused) and we
shoudn't force this on an app. Instead make the dependency optional by
automatically falling back to the platform version if the AndroidX one
doesn't exist.
Issue: #7357
PiperOrigin-RevId: 322143005
getExoMediaCryptoType will only return null for drmInitData == null and
track types for which placeholder sessions are not used. This change
will allow renderers to abstract themselves from format.drmInitData.
PiperOrigin-RevId: 322131219
Replace `type` with (optional) `mimeType` and add `keySetId` in
DownloadRequest. The DownloadHelper infers the downloading method (DASH,
HLS, SmoothStreaming or Progressive) from the content's MIME type and
URI.
PiperOrigin-RevId: 322117384
The logic to clear the playlist is currently duplicated in various
reset methods so that calls to player.stop(true) can clear the playlist.
This can be deduplicated by clearing the playlist as a seperate
operation that reuses the existing code.
PiperOrigin-RevId: 321578759
We currently try to call onAdPlaybackStarted even if the ad session
is not created yet and if not, we never call the callback afterwards.
Make sure to update and create the current session before trying to
send onAdPlaybackStarted.
As a result, we can merge updateSessions into the existing
handleTimelineChanged and handleDiscontinuity calls as they always
need to be called together.
PiperOrigin-RevId: 321383860
Float values are allowed to be > 0dbfs,
it is just not nominal as it will might
distort the signal when played without
attenuation.
This is also consistent with
[AudioTrack.write(FloatBuffer)](https://developer.android.com/reference/android/media/AudioTrack#write(float[],%20int,%20int,%20int)) that explicitly
allows it up to 3dbfs.
PiperOrigin-RevId: 321345077
The method has been called from two call sites in EPII triggered by EPII.updatePeriods(). The first call site was calling it when the MediaSourceList is empty or not yet prepared. This can be removed because if empty or not prepared no source ever could have thrown yet.
The second call site was checking for potential source refresh exceptions when queue.getNextMediaPeriodInfo() returns null when trying to getting the next loading period. Looking into all reasons for why the method returns null, none of them is caused by an exception of a media source. The reasons are:
- if we are at the last period of the timeline
- if the defaultPosition of the next period in the timeline is null (if the window.durationUs == C.TIME_UNSET or defaultPositionProjectionUs is projected beyond the duration of the window)
- if we are waiting for an ad uri to arrive (period.isAdAvailable(...) == false)
- if we are waiting for the ad group count to be updated (adCountInCurrentAdGroup == C.LENGTH_UNSET)
The above reasons are not caused by a source error and may be resolved when doSomeWork is called the next time. Hence it is save to remove the calls to maybeThrowSourceInfoRefreshError().
Beside this, an actual sourceInfoRefreshError will be reported by maskingMediaSource.maybeThrowPrepareError(), which is called each time doSomeWork() is called and the playing period is not yet prepared (EPII:L836). So the player is notified by source errors that way, which confirms removing the above calls is fine.
PiperOrigin-RevId: 321331777
Plumb this down into BaseRenderer.onStreamChanged and use it when
deciding whether to render the first frame of a new period.
PiperOrigin-RevId: 321175627
This change masks playbackInfo.periodId and playbackInfo.loadingPeriodId for operations which change these periods (set/add/remove sources and seeks).
Because this masking is reflected in the playbackInfo object, player attributes can be retrieved without the maskingXyz variables in EPI. This has the advantage that the playbackInfo object always reflects the public state of the player even when operations are still pending. The maskingXyz variables in EPI are only required for the deprecated use case of an initial seek in an empty timeline.
PiperOrigin-RevId: 321160092
In order to use DeviceInfo class in media2, this CL moves the class to
common module. It didn't move the other file in the same package,
DeviceListener, as it's for DeviceComponent but media2 SessionPlayer
doesn't have components as it is already flattened. PlayerCallback will
have equivalent methods of DeviceListener.
PiperOrigin-RevId: 321154997
The method currently advances the read position and returns the number
of skipped samples. This prevents checking how many samples are skipped
before the operation is executed.
Instead, we have a new method that returns the number of to be skipped
samples and a skip method that executes the skipping.
PiperOrigin-RevId: 320953439
- DefaultAudioSink always supports floating point input. Make it
advertise this fact.
- Remove the ability to enable/disable floating point output in
FfmpegAudioRenderer, since this ability is now also provided on
DefaultAudioSink.
- Let FfmpegAudioRenderer query the sink to determine whether it
will output floating point PCM directly or resample it to 16-bit
PCM.
PiperOrigin-RevId: 320945360
CSS background-color isn't inherited to inner HTML elements by default:
https://developer.mozilla.org/en-US/docs/Web/CSS/background-color
But Android Span styling assumes an outer BackgroundColorSpan will
affect inner spans. This usually doesn't make a difference, because
HTML elements are transparent by default, so there's an implicit
inheritance by just being able to see through to the 'outer' element
underneath. However this doesn't work if the inner element sits outside
the bounding box of the outer element, e.g. <rt> (ruby text, sits above/below)
or a <span> with font-size > 100%.
END_PUBLIC
Demo of <rt> and font-size problems: http://go/cpl/ruby-backgrounds/1
Demo of CSS inheritance: http://go/cpl/css-inheritance/1
PiperOrigin-RevId: 320915999
Previously, the automatically selected subtitle track
has not been marked (with check mark) in subtitle track list,
just like audio track.
But, in subtitle track option UI, there is no 'auto' option,
which is different from audio track selection menu.
This CL marks the auto selected subtitle track name in the cc list.
PiperOrigin-RevId: 320802575
Sharing the Handler has led to it being accidentally used for purposes
beyond the original intention.
Instead for EPII -> EPI communication: Call methods directly on
ExoPlayerImpl that then post from the playback thread to the
application thread.
And for the MediaSourceList and Queue initialization, create a dedicated
Handler based on the same applicationLooper.
PiperOrigin-RevId: 320590527
Also flip DefaultDrmSessionManager#prepare()/release() into guard
clauses.
Suggestions from review comments on:
316f8a88cd
PiperOrigin-RevId: 320572462
AdDisplayContainer now takes the video ad player at construction time,
and obstructions are registered/unregistered via a new method. Also
'content complete' is now notified via ad callbacks rather than the
AdsLoader.
PiperOrigin-RevId: 320567666
DecoderCounters are reset in onEnabled, but the way the local
counters in MediaCodecVideoRenderers were reset assumed the
DecoderCounters were reset in onStarted.
PiperOrigin-RevId: 320440991
Building on the Format that was provided on the input side of the
decoder creates a format that's a mixture of the formats on the
input and output sides of the decoder. This change instead builds
a PCM format from scratch.
PiperOrigin-RevId: 320405656
The renderers are currently constructing formats that consist of their
input format with added PCM encoding. Such formats are not self-consistent,
and this only works because DefaultAudioSink ignores the rest of the
format if the format has a PCM encoding. It would not work if the sink
implementation checked the MIME type, for example, which wouldn't be a
strange or incorrect thing for it to do.
The more correct approach is to construct a new format that properly
represents the PCM that will be provided to the sink.
This change also renames supportsOutput to supportsFormat, because
AudioSink itself has both an input and an output side, and this method
is actually evaluating support on the input side of the sink.
PiperOrigin-RevId: 320396089
This is useful for subclasses to easily query the point up to which
they should only decode (but not render) content, rather than each
subclass having to have its own startPositionUs and update it in
onPositionReset.
PiperOrigin-RevId: 320163677
*** Original commit ***
Stop parsing unsupported WebVTT CSS properties
The spec lists an exhaustive list of CSS properties that should be
recognised, all others must be ignored:
https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element
***
PiperOrigin-RevId: 320150427
*** Original commit ***
Rollback of 0943886cbd
*** Original commit ***
Use last queue format instead of previous decision to select new track
We currently use the save...
***
PiperOrigin-RevId: 320015109
*** Original commit ***
Use last queue format instead of previous decision to select new track
We currently use the saved selectionIndex to base our new track
selection decision on. This index might be stale if the previous
selection didn't result in a queue update (e.g. when loading live
streams where the new chunk isn't available yet).
Fix this by using the format of the last chunk to make the new decision.
Issue: #7582
***
PiperOrigin-RevId: 319991676
We currently use the saved selectionIndex to base our new track
selection decision on. This index might be stale if the previous
selection didn't result in a queue update (e.g. when loading live
streams where the new chunk isn't available yet).
Fix this by using the format of the last chunk to make the new decision.
Issue: #7582
PiperOrigin-RevId: 319957980
The wait time parameter is an implementation detail where we can just
provide a default.
In addition, we should also force the evaluation when the last chunk
in the queue changed to ensure it is always evaluated before starting
to load a new chunk.
Issue: #7582
PiperOrigin-RevId: 319949251
ExoMediaCrypto with the sole purpose of being unsupported. So all
renderers checking whether the type is supported will report
encrypted content as unsupported, unless the source producing
the format replaces it with a valid value.
PiperOrigin-RevId: 319824703
This is a partial revert of 0a2bacb7b7. I've added a comment
explaining why the code path is necessary after all, to avoid
future confusion.
PiperOrigin-RevId: 319822696
Clearing the exception puts the SimpleDecoder into a silent failure
state - the decoder thread is dead (because decode() has returned
false) but it's still possible to queue buffers to the decoder (they
just never get decoded). This partially reverts
4107375c9d
Also always recreate the decoder when handling an error in TextRenderer
This ensures we can try and decode a later subtitle sample after
encountering a decode error. This behaviour is what nulling out the
exception in SimpleDecoder.flush() was trying to achieve. We need to
ensure we don't start passing data to the new decoder until we've
hit the next key frame, so we throw away any non-keyframe samples
inside TextRenderer#render().
Issue: #7590
PiperOrigin-RevId: 319785908
We currently try to keep track of the playback queue (MediaPeriodQueue)
by listening to onMediaPeriodCreated/onMediaPeriodReleased events.
This approach has some problems:
1. It's easily broken by custom MediaSources that don't report these
events correctly.
2. We need to make some assumptions about what the order of these
events actually means. For example it is currently important that
the playing period gets released last in MediaPeriodQueue.clear()
3. We don't see batched events (like MediaPeriodQueue.clear()), so that
it is impossible to keep the "last reading period" for example. This
information is needed to correctly associate renderer errors to
periods after the queue has been cleared.
All of these problems can be solved by directly tracking the queue.
This also makes the onMediaPeriodCreated/Released/ReadingStarted events
obsolete and they can be removed in a future change.
PiperOrigin-RevId: 319739993
The current code only works if the tts:ruby attributes are defined
directly on the in-line elements. This changes that so we also consider
tts:ruby attributes on `style` nodes referenced by ID.
PiperOrigin-RevId: 319515177
We don't need the renderer immediately after stopping, so the
renderer should not throw a checked exception until it's used again.
This is inline with the not throwing from disable().
Also, none of the known implementation throw an exception at the moment
and all reasonable base classes omit the throws clause already.
PiperOrigin-RevId: 319503643
They are all for Context.getSystemService that is allowed to return
null. In most cases where we need to service, we make an assertion that
it is available.
PiperOrigin-RevId: 319503557
The test was incorrectly assuming that with LooperMode.PAUSE,
HandlerThread instances needed explicit calls to execute
tasks. This commit fixes the test flakiness by manually pausing the
HandlerThead when needed.
PiperOrigin-RevId: 319411552
Without checking if getFramesPerEncodedSample fails,
the frame count becomes negative which leads to
hard to debug errors.
PiperOrigin-RevId: 319247618
Passthrough mode can use a codec or not, but
the code only mentioned "passthrough" in most cases,
making the specific mode confusing.
For example both `MediaCodecRenderer` and
it's derived class `MediaCodecAudioRenderer`
had a private `passthroughEnabled` field,
but they were used for the opposite modes!
This change renames all relevant variables/functions
to explicit `CodecPassthrough` or `Bypass`.
PiperOrigin-RevId: 319225235
The system services may return a null value if the service is
not available. Guard against this by falling back to default values.
PiperOrigin-RevId: 319187882
Issue: #7011
Issue: #6725
Issue: #7066
This also mitigates (but doesn't fix) Issue: #4133 because it
prevents a second key load after a short clear section.
PiperOrigin-RevId: 319184325
SampleStreams should always provide samples starting from a keyframe.
We do not have equivalent logic in any of our extension decoder renderers.
PiperOrigin-RevId: 319012365
The list of MediaSourceHolder in ExoPlayerImpl is only maintained to be able to create a PlaylistTimeline for masking. By keeping only the id and a snapshot of the timeline of the MediaSourceHolder in ExoPlayerImpl, parallel access is prevented and we still have sufficient information to create the masking timeline.
PiperOrigin-RevId: 319003837
We can't restore the previous state of the remaining chunk, so we can't
support discarding from spliced-in chunks. Mark this explicitly instead
of attempting to discard from the previous chunk.
PiperOrigin-RevId: 318983628
This fixes an issue where, even if captioning manager is disabled, the latest used captioning manager preference
related to text size is being applied.
In order to replicate:
1. Go to Captioning Preferences under device Settings and enable it
2. Change the text size to "very large"
3. Observe the selected text size is used for subtitles, for example in Youtube
4. Go to Captioning Preferences under device Settings and disable it
5. Observe the text size used for subtitles does not come back to normal, stays on "very large"
- Deprecate constructors that don't take an executor, to direct
developers toward the new ones. Callers can trivially pass
Runnable::run to one of the new ones if they want old behaviour.
- Add comment explaining warning suppression added in the CL that
added parallelised download support.
Issue: #5978
PiperOrigin-RevId: 318803296
This enhances readability, particularly as those methods will become
more complex when partially fragmented media will be supported.
PiperOrigin-RevId: 318795536
Previously only pcm encoding were stored in Format,
this was an issue as for audio passthrough and offload
lots of code needs to pass complex format informations
(encoding, sample rate, channel count, gapless metadata)
but could not use Format and each function was taking
each as different parameter.
By allowing Format to contain any encoding, and not only
pcmEncoding, it allows to pass a Format everywhere in ExoPlayer
code that needs a Format.
This patch does not have any functional change. It is only an internal refactor.
PiperOrigin-RevId: 318789444
Gapless offload is fixed in later R beta builds of all Pixels supporting R.
On the firsts R beta builds of Pixel 4, run the following command.
`setprop vendor.audio.offload.gapless.enabled true`.
It can not be enabled on the first Pixel 2 and 3 beta build.
PiperOrigin-RevId: 318436134
This it is enabled only on a list of
manually tested devices.
The list is empty in this CL.
*** Reason for rollforward ***
Fixed dependent cl was rolled forward.
*** Original change description ***
Rollback of 962e08d3be
*** Original commit ***
Add Offload gapless support
Confirmed to work on a Pixel 4 after enabling the feature:
`setprop vendor.audio.offload.gapless.enabled true`
***
***
PiperOrigin-RevId: 318433123
*** Reason for rollforward ***
Fixed dependent cl was rolled forward
*** Original change description ***
Rollback of 2aac0717d7
*** Original commit ***
Propagate format in supportsOutput
It is needed to know if gapless is needed,
as gapless offload might not be supported.
***
***
PiperOrigin-RevId: 318429321
*** Reason for rollforward ***
Rollforward after making sure the handler is created,
and that a test is written preventing a
similar regression.
*** Original change description ***
Rollback of b6f5a263f7
*** Original commit ***
Rollforward of commit 5612ac50a3.
*** Reason for rollforward ***
Rollforward after making sure the handler is created
from the playback thread and not from an app thread.
*** Original change description ***
Rollback of e1beb1d194
*** Original commit ***
PiperOrigin-RevId: 318274400
Ignore two tests in AsynchronousMediaCodecBufferEnqueuerTest
until the ShadowMediaCodec's behavior is updated to apply
input buffer ownership.
PiperOrigin-RevId: 318251859
The existing code moves a multi-line cue box by multiples of the height
of the whole cue box (incorrect), rather than multiples of the first
line of text (correct). These two are equivalent for single-line cues,
which is why I didn't initially spot the problem.
PiperOrigin-RevId: 318036793
Numerical lines conceptually map to a grid of lines in the viewport,
with the Cue text lines being aligned to one of the viewport lines.
It doesn't make sense to position a single-line cue differently based
on lineAnchor when it's expected to 'snap' to a particular line on the
viewport grid. So we redefine the position to be in terms of the cue
lines rather than the bounds of the cue box.
It's also not possible to always handle ANCHOR_TYPE_MIDDLE when
lineType=NUMBER (as it relies on the number of lines in the cue being
odd), so it's easier to ignore lineAnchor completely.
PiperOrigin-RevId: 318034664
This removes a lot of duplication from the module configuration,
avoids divergence, and makes sure that only the important differences
to the default are visible in each module file.
PiperOrigin-RevId: 318024823
Postrolls would be skipped because the period duration wasn't know at
the moment of resuming playback after backgrounding, so the position
wouldn't be resolved to resume the postroll ad.
We have the period duration stored in the AdPlaybackState, so we can
use that directly.
Issue: #7518
PiperOrigin-RevId: 317830418
They currently fall back to the main Looper if the current thread
doesn't have a Looper. All the changed Handlers are guaranteed to
be created on a thread with a Looper (mostly the ExoPlayer playback
Looper) and thus can make this stricter assumption. This makes it
easier to reason about the code as there are no ambiguities as to which
thread the Handler is running on.
PiperOrigin-RevId: 317334503
The setForeground mode method blocks in the same way as release
and should use the same timeout if configured.
In case the method runs into the timeout, a player error is reported.
PiperOrigin-RevId: 317283808
*** Original commit ***
Rename Util methods to clarify which Looper is used.
The method name didn't clarify that either the main or current
Looper is used.
***
PiperOrigin-RevId: 317283606
- It seems conceptually simpler for DefaultExtractorsFactory
- It seems unlikely we'll need to diverge the two. In the case of
workaround flags we can just have them be no-ops in the version
that doesn't need them.
PiperOrigin-RevId: 317151955
Looks like this change was introduced in
<unknown commit>
onKeysRemoved is currently not triggered in DefaultDrmSessionManager
as far as I can tell. It seems like it should be called from here.
PiperOrigin-RevId: 317072794
It seems more natural given we always end up instantiating a Matroska extractor,
not one that's specific to the WebM subset of Matroska. There's also no reason
not to support Matroska MIME types in DASH.
PiperOrigin-RevId: 316975451
*** Original commit ***
Rollforward of commit 5612ac50a3.
*** Reason for rollforward ***
Rollforward after making sure the handler is created
from the playback thread and not from an app thread.
*** Original change description ***
Rollback of e1beb1d194
*** Original commit ***
Expose experimental offload scheduling
Add a new scheduling mode that stops ExoPlayer main loop
when the audio offload buffer is full and resume it...
***
PiperOrigin-RevId: 316914147
*** Reason for rollforward ***
Rollforward after making sure the handler is created
from the playback thread and not from an app thread.
*** Original change description ***
Rollback of e1beb1d194
*** Original commit ***
Expose experimental offload scheduling
Add a new scheduling mode that stops ExoPlayer main loop
when the audio offload buffer is full and resume it when
it has been partially played.
This mode needs to be enabled and dissabled manually by the app
for now.
#exo-offload
***
***
PiperOrigin-RevId: 316898804
Ads can appear due to asynchronous ad tag requests completing after
earlier ads in a pod have loaded, so remove the requirement that the
ad count can't change. The MediaPeriodQueue should handling discarding
buffered content if an ad appears before already buffered content, so
I think this case is actually handled correctly by the core player
already.
Also remove the requirement that an ad URI can't change. This is a
defensive measure for now, but it's likely that a later fix in the IMA
SDK for an issue where loadAd is not called after preloading then
seeking before a preloaded ad plays will result in loadAd being called
more than once, and I think it's possible that the second call to
loadAd may have a different URI. Because the ad URI should only change
after an intermediate seek to another MediaPeriod, there shouldn't be
any problems with buffered data not getting discarded.
Issue: #7477
PiperOrigin-RevId: 316871371
The test was trying to synchronize a background decoding thread by
waiting for pending decode calls. However, the background thread needs
to fully queue the newly available output buffer before we can stop
waiting to ensure it's actually fully predictable. So we change the
pending wait to wait until the input buffer is cleared, which only
happens after the decoder is definitely done with it.
Also properly clean-up decoder (including shutting down the background
thread).
PiperOrigin-RevId: 316870659
- Leaving the TODO, since there are still MIME types we're unsure about.
- Removing AAC because xHE-AAC does not have this property. We may re-add
it with an additional profile check to exclude xHE-AAC in the future.
PiperOrigin-RevId: 316715147
We haven't seen it used anywhere in practice. It's a niche feature not
supported by any other extractors, and is one of the very few things
stopping us from simplifying MediaSource implementations to not set the
decodeOnly sample flag. This is a simplification that we want to make,
since the current mechanism doesn't work properly for cases where a
downstream decoder adjusts the buffer presentation timestamps so that
they're different on the output side than on the input side.
PiperOrigin-RevId: 316712302
This flag isn't needed anymore because the waiting for keys happens on
the source side and the source just returns NOTHING_READ under the
same conditions.
PiperOrigin-RevId: 316704214
We started using this method from other tests unrelated to
TestExoPlayer, so the method is better placed inside a generic Util
class.
PiperOrigin-RevId: 316675067
This change adds MediaSource.getMediaItem and deprecates MediaSource.getTag. For backwards compatibility, the tag is made available through the Window with `mediaItem.playbackProperties.tag` as well as in the deprecated `tag` attribute.
PiperOrigin-RevId: 316539752
Using the default offset as a magic constant makes tests hard to
understand. Improve that by looking up the value from the timeline or
setting it explicitly in multiple places, so the relationship becomes
clear.
PiperOrigin-RevId: 316421977
The correct order of initializing the MediaCodec should be (as per
documentation
https://developer.android.com/reference/android/media/MediaCodec#initialization)
"create -> setCallback -> configure -> start"
but the MediaCodecRenderer currently does
"create -> configure -> setCallback -> start"
MediaCodec implementations did not complain about this so far, but the
wrong sequence does not work with the MediaCodec in block mode (new mode
in Android R) and also the ShadowMediaCodec won't operate in
asynchronous mode otherwise. To initialize the MediaCodec in the correct
order, this commit adds configure() in the MediaCodecAdapter so the
MediaCodecRenderer can do:
adapter.configure(); // sets the callback and then configures the codec
adapter.start(); // starts the codec
PiperOrigin-RevId: 316127680
*** Original commit ***
Expose experimental offload scheduling
Add a new scheduling mode that stops ExoPlayer main loop
when the audio offload buffer is full and resume it when
it has been partially played.
This mode needs to be enabled and dissabled manually by the app
for now.
#exo-offload
***
PiperOrigin-RevId: 315948869
*** Original commit ***
Propagate format in supportsOutput
It is needed to know if gapless is needed,
as gapless offload might not be supported.
***
PiperOrigin-RevId: 315947888
*** Original commit ***
Add Offload gapless support
Confirmed to work on a Pixel 4 after enabling the feature:
`setprop vendor.audio.offload.gapless.enabled true`
***
PiperOrigin-RevId: 315946947
The test uses two items with period-in-window offsets and a non-zero default start position. The test also prepares the first item lazily so
that the start position (and thus the renderer offsets) need to change.
This is arguably the most complicated setup that needs to be tested.
PiperOrigin-RevId: 315903958
The order of source info refresh and onPrepared was accidentally
changed by ed88f4f1dd. This changes it back to the correct order
and adds a test
PiperOrigin-RevId: 315885164
Rename the DedicatedThreadAsyncMediaCodecAdapter to
AsynchronousMediaCodecAdapter as it is the only asynchronous adapter
implementation left after the clean-up.
PiperOrigin-RevId: 315873431
Add a new scheduling mode that stops ExoPlayer main loop
when the audio offload buffer is full and resume it when
it has been partially played.
This mode needs to be enabled and dissabled manually by the app
for now.
#exo-offload
PiperOrigin-RevId: 315860373
The option to cancel ongoing loads as part of the queue size evalation
was added recently. This split out the decision to a new method so that
a TrackSelection implementation can independently cancel loads and
discard upstream data. It also clarifies that evaluateQueueSize will
only be called if there is no ongoing load.
Issue: #2848
PiperOrigin-RevId: 315659735
If the previous chunk didn't finish loading, we need to find the appropriate
next chunk based on the current loading position (or the previous chunk's
start time if not independent).
PiperOrigin-RevId: 315658435
This change makes the media item argument in any constructors of the SinglePeriodTimeline non-null. Further a dummy media item is created for deprecated constructors using a tag only.
PiperOrigin-RevId: 315283842
ANSI/CTA-608-E R-2014 Annex B.5 says:
"The concept of a movable base row for a roll-up caption is new."
It means "new" compared to TC1 and TC2 (released in or before 1985).
Issue: #7475
PiperOrigin-RevId: 315258859
Output timestamps are calculated by the codec based on the buffers,
which is offset in Codec2. This adjusts the input timestamps as they
are passed in so they will match the output timestamps produced by
the MediaCodec.
PiperOrigin-RevId: 314963830
FakeMediaSource and FakeTimeline should put a media item to the window just as other media sources and timelines do. This change provides a fake media item for both of them.
Further the MaskingMediaSource needs to provide a media item for when the real timeline of the masked media source is not available. This can be easily done by using mediaSource.getMediaItem() once available. For now a dummy is used to make ExoPlayerTest run green. This can be easily change to use mediaSource.getMediaSource as soon as this method is defined by the MediaSource interface.
PiperOrigin-RevId: 314897474
bear_vorbis_gap.ogg is a copy of bear_vorbis.ogg with 10 garbage bytes
(DE AD BE EF DE AD BE EF DE AD) inserted before the second capture
pattern and 3 garbage bytes inserted at the end (DE AD BE).
Issue: #7230
PiperOrigin-RevId: 314715729
This change makes the media item of Timeline.Window non-null by providing a fallback media item in window.set(...). After having migrated all media sources this should not be needed anymore, but a fallback makes it more safe than just making the mediaItem argument of window.set(...) non-null (which is done in a following CL in this chain of CLs).
PiperOrigin-RevId: 314527983
Before loading a new chunk, the player will call reevaluateBuffer
anyway, so we don't have to do this directly after cancelation.
This simplifies some logic because we can remove the pending queue
size variable.
PiperOrigin-RevId: 314313268
If no deprecated methods on the factory is called, the media item instance that is passed to the createMediaSource method must be passed down to the constructor of the media source.
PiperOrigin-RevId: 314193865
This change applies the same approach of handling tag/streamKeys from factories like in the SmoothStreaming and Hls factories. It is functionally equivalent but improves readability.
PiperOrigin-RevId: 313771318
I was trying to understand why this isn't always checked and didn't
realise there was already a bug tracking this - this way a future
confused reader knows something isn't working quite as intended.
PiperOrigin-RevId: 313765935
If the sample times don't overlap and are independent, splicing makes no
difference because all samples (starting from the first one, which must be
a keyframe) will be appended to the end of the queue anyway.
PiperOrigin-RevId: 313594372
We aim to have the same media item instance published in the timeline that is passed to the createMediaSource(mediaItem) method. This means when the manifest uri is manually replaced by a developer, the media item published in the next timeline update is still the same.
Note: This leads to the fact that the manifest published in that timeline is loaded from a different URI than the URI of the media item in the same timeline.
PiperOrigin-RevId: 313375421
- The new CacheWriter is simplified somewhat
- Blocking on PriorityTaskManager.proceed is moved out of
CacheWriter and into the Downloader tasks. This is because
we want to shift only the caching parts of the Downloaders
onto their Executors, whilst keeping the blocking parts on
the main Downloader threads. Else we can end up "using"
the Executor threads indefinitely whilst they're blocked.
Issue: #5978
PiperOrigin-RevId: 313222923
Add an `_` in long constants.
Eg: 10000 => 10_000.
I'm proposing this change because I have had multiple
missread due to confusing the number of 0 in a long number.
More specifically, added an underscore to all number matching:
`final.*\ [0-9]{2,}000;`
PiperOrigin-RevId: 313186920
The test was flaky because it didn't wait for pending commands to finish
after pausing the test playback.
Also add more debug information to the toString() method because the
expected and actual state only differed in the nextAdGroupIndex in the
flaky case.
PiperOrigin-RevId: 313175919
Sometimes it's useful to be able to block until something on some other thread
"really has finished". This will be needed for moving caching operations onto
the executor in Downloader implementations, since we need to guarantee that
Downloader.download doesn't return until it's no longer modifying the
underlying cache.
One solution to this is of course just to not interrupt the thread that's
blocking on the condition variable, but there are cases where you do need to do
this in case the thread is at some other point in its execution. This is true
for Downloader implementations, where the Download.download thread will also
be blocking on PriorityTaskManager.proceed. Arranging to conditionally
interrupt the thread based on where it's got to is probably possible, but seems
complicated and error prone.
Issue: #5978
PiperOrigin-RevId: 313152413
Every timeline refresh currently assumes that it corresponds to a manifest
refresh and issues the respective load events. However, there are other
timeline updates that don't have a manifest refresh (e.g. ad state updates)and thus shouldn't issue these events.
PiperOrigin-RevId: 313150489
A recent change tried to make this condition clearer by using Integer.MAX_VALUE, but
this only works if the comparison also compares against larger values.
PiperOrigin-RevId: 312697530
The code that uses these variables is already commneted out. Android Studio
complains about unused variables and code and it's better to comment them
out as long as they are not used.
PiperOrigin-RevId: 312660512
This change adds an overloaded createMediaSource method which allows developers to pass in a media item with a in-memory manifest. Without this method the developer would not have a chance to pass in a non-dummy media item when using the factory for creting a DASH media source with an in-memory manifest.
PiperOrigin-RevId: 312660418
Previously if the AudioCapabilities reported that an encoding/channel count was
supported, DefaultAudioSink could try to play it via passthrough. However,
DefaultAudioSink does not support passthrough of every possible format (for
example, it's likely that AAC passthrough does not work given it's never been
tested and recent GitHub issues indicate that trying to use it leads to no
audio being played).
Add additional checks to make sure the encoding is in the list of encodings that
are known to work with passthrough in DefaultAudioSink.
issue:#7404
PiperOrigin-RevId: 312651358
*** Original commit ***
Remove set timeout on release() and setSurface()
Removes the experimental methods to set a timeout when
releasing the player and setting the surface.
***
PiperOrigin-RevId: 312647457
- To make it clear that cache keys are for whole resources
- To explicitly make it clear to implementors that deriving a cache key
from position and length is invalid. We've seen at least one developer
trying to do this [1], so it seems worthwhile to be explicit!
[1] https://github.com/google/ExoPlayer/issues/5978#issuecomment-618977036
Issue: #5978
PiperOrigin-RevId: 312643930
Guava is heavily optimized for Android and the impact on binary size
is minimal (and outweighed by the organic growth of the ExoPlayer
library).
This change also replaces Util.toArray() with Guava's Ints.toArray()
in order to introduce a Guava usage into a range of modules.
PiperOrigin-RevId: 312449093
This will replace the need to use CacheUtil.getCached, and is part of refactoring
CacheUtil to only do writing (it will be renamed to CacheWriter in a subsequent
change).
PiperOrigin-RevId: 312366040
- Remove scratchStyleMatches output parameter from WebvttCueParser.
- Switch from String[] to Set<String> for representing classes.
- In-line WebvttCssStyle.reset() since it's not used anywhere else.
PiperOrigin-RevId: 312249552
Added monitoring storage levels in RequirementsWatcher
Added dependency on extension-workmanager to the demo app to be able to test with WorkManagerScheduler
Added getSupportedRequirements method to Scheduler interface
Implemented getSupportedRequirements for schedulers
- The remove(DataSpec) method was confusing because it ignored
the DataSpec position and range, and instead removed all data
with a matching cache key.
- The remove(String) method seems better put directly on the
Cache interface.
PiperOrigin-RevId: 312113302
This is part of go/exoplayer-playlist-retrieval which aims for all MediaSources to associate the media item to the corresponding window. Media items need to be added to the timeline which then assigns it to the window.mediaItem attribute.
PiperOrigin-RevId: 312065023
The ad break time in seconds from IMA was "-1" for postrolls, but this didn't
match C.TIME_END_OF_SOURCE in the ad group times array.
Handle an ad break time of -1 directly by mapping it onto the last ad group,
instead of trying to look it up in the array.
PiperOrigin-RevId: 312064886
The new behaviour:
- If the session is successfully opened, an acquire event is dispatched
to all attached dispatchers.
- If acquire() is called but the session is already open, the acquire
event is dispatched only to the dispatcher provided in to acquire()
- If the session is successfully released, a release event is dispatched
to all attached dispatchers (in theory at most one should ever be
attached at this point).
- If release() is called but the session isn't released (because
referenceCount > 0) then a release event is dispatched only to the
dispatcher provided to release().
PiperOrigin-RevId: 312062422
Switch to snapshot Robolectric to pick up the latest version of shadows
required by MediaCodecVideoRendererTest and MediaCodecAudioRendererTest.
PiperOrigin-RevId: 312030332
Detect stuck buffering cases in ImaAdsLoader, and discard the ad group after
a timeout. This is intended to make the IMA extension more robust in the case
where an ad group unexpectedly doesn't load.
The timing out behavior is enabled by default but apps can choose to retain
the old behavior by setting an unset timeout on ImaAdsLoader.Builder.
PiperOrigin-RevId: 311729798
EventTime contains information about when an event happened and where
it belongs to. Both places can be fully described using timeline, window
index, media period id and position.
Right now, only the information for where the event belongs to is fully
contained in EventTime, whereas the time when the event happened only has
the position, and none of the other information (timeline, window, period).
This change adds the missing information, so that the EventTime can easily
be used without having access to the Player. This also ensures Event
metadata is self-contained and can be stored and reused later.
issue:#7332
PiperOrigin-RevId: 311727004
Some of the CSS font sizes are derived from the current view height, if
this calculation is done before the view has been measured then a zero
view height results in a zero px font size and no visible text.
This can happen when the view type is changed (and so the
WebViewSubtitleOutput has been recently added to the SubtitleView
ViewGroup).
PiperOrigin-RevId: 311552052
ANSI/CTA-608-E R-2014 spec defines exactly 32 columns on the screen,
and limits all lines to this length.
See 3.2.2 definition of 'Column'.
issue:#7341
PiperOrigin-RevId: 311549881
Some player setup steps that are likely to be only done once
should be moved into the Builder so that player setup can use
a consistent style (builder vs setters).
This also prevents some threading warning issues when the player
is built on a background thread (e.g. for dependency injection
frameworks) and setters can't be used due to threading restrictions.
PiperOrigin-RevId: 311487224
It displays images too, and in fact it's used exclusively to display
images in SubtitleWebView. It also doesn't use a TextView - so all round
a slightly confusing name.
Also rename SubtitleWebView to WebViewSubtitleOutput to match the same
pattern.
PiperOrigin-RevId: 311312758
This is useful for merging the FFmpeg video support pull request,
since it allows a Decoder base class implementation to catch
DecoderException rather than forcing it to catch Exception (i.e.,
everything). Note that unfortunately, Java doesn't allow catching
of a generic type (i.e., you cannot "catch (E e)") due to type
erasure.
PiperOrigin-RevId: 311300719
The only reason to require a context for creating an instance of
DefaultMediaSourceFactory is creating a user agent. DownloadHelper
has a bunch of static methods that need to instantiate a
DefaultMediaSourceFactory without a Context. By adding a setter for
the user agent we can remove that restriction and use a default user
agent.
PiperOrigin-RevId: 311291603
We aim for all SinglePeriodTimelines to set window.mediaItem and hence want to eliminate all constructors not passing a media item. The constructor removed in this CL is the easiest one to remove and fix in google3. It is still a breaking change for external ExoPlayer user who provide a custom media source with this timeline.
PiperOrigin-RevId: 311291493
It's very unlikely any onQueueInputBuffer implementations are looking
at the subsample encryption data, but from a correctness perspective
we should be passing a buffer object that's self-consistent.
PiperOrigin-RevId: 311011246
FFmpeg requires input buffers to be sized larger than the size
of the data they contain. This is to allow optimized decoder
implementations that read data in fixed size chunks, without
the risk of such decoders reading beyond the end of the buffer.
Issue: #2159
PiperOrigin-RevId: 310946866
We currently use the playback position in the current window, not the
position in the window the event belongs to. This creates confusing
outputs, e.g, window=1, mediaPos=100, even if the position refers to
window 0.
issue:#7332
PiperOrigin-RevId: 310896908
The tts:textAlign property only applies to <p> elements, which
correspond 1:1 with ExoPlayer Cue objects, so we can use
Cue.textAlignment to store this info instead of encoding it in
the span-styled text.
This will mean that TTML subtitles used with
SubtitleView#setApplyEmbeddedStyles(false) will start respecting
the tts:textAlign properties from the source data (currently this
information is stripped when we remove all span styling). I think this
is working-as-intended, we respect alignment of other subtitle types
(e.g. WebVTT) when applyEmbeddedStyles=false. We also respect all other
'positioning' related properties in this case e.g. Cue.position and
Cue.line.
PiperOrigin-RevId: 310895499
*** Original commit ***
Rollback of 70273a0361
*** Original commit ***
Assert incoming buffers are little endian in the DefaultAudioSink.
***
***
PiperOrigin-RevId: 310889382
When operating the MediaCodec in asynchronous mode, we are seeing
NPEs raised from the DefaultAudioSink because output buffers are pushed
to the DefaultAudioSink with the DefaultAudioSink not configured yet.
This is possible to happen if an output buffer is passed with
MediaCodecAudioRenderer.processOutputBuffer() before an output format
change.
One possible code path to trigger this is when an output format change
is pending and we flush MediaCodec (e.g. for a seek): the callback is
waiting in the looper's queue but we ignore all currently queued
callbacks after a flush().
This commit checks for a pending output format change during a flush():
if one exists, and the next MediaCodec output callback right after the
flush() is an output buffer (and not a new output format), then the
pending output format is propagated first.
The only adapter that needs to change is the
AsynchronousMediaCodecAdapter which previsouly deleted all pending
callbacks immediately on flush(). The AsynchronousMediaCodecAdapter now
needs to also handle every enqueued callback in order to identify is
there's a pending output format change.
Testing: added unit tests for the new code. I have verified that if we
pass an output buffer to the audio renderer before the output format, it
will result on the specific NPE, but I cannot reproduce the base
scenario (an output format change is pending when flushing) on a real
device because we can't know if an output format is indeed pending.
PiperOrigin-RevId: 310885283
We currently propagate only ColorInfo, but propagating the whole Format
is generally useful (e.g., to get the frame-rate on the output side of
the decoder).
PiperOrigin-RevId: 310359650
This allows properties to propagate when switching view types
(e.g. bottomPaddingFraction).
It also allows the style-stripping code to be pushed up to SubtitleView
and therefore shared.
PiperOrigin-RevId: 310353534
Fixes AsynchronousMediaCodecBufferEnqueuerTest broken tests by
enqueueing input buffers that have previously been dequeued from the
MediaCodec.
The test assumes that the shadow MediaCodec implementation can dequeue
at least 10 input buffers before queueing them back. Although fragile,
it seems to work with the current robolectric shadow MediaCodec. This is
at the moment preferred compared to making the test more complicated.
PiperOrigin-RevId: 310325096
Currently, DashMediaPeriod only takes into account as CEA-608 accessibility tags as embedded
closed captions tracks CEA-608. CEA-708 closed captions format is parsed when is present on
its own AdaptationSet, but not when is embedded as an accessibility tag in a video AdaptaticonSet.
Embedded CEA-708 support is added by parsing accessibility tags like the example below:
<Accessibility schemeIdUri="urn:scte:dash:cc:cea-708:2015" value="1=lang:eng;2=lang:deu"/>
<Accessibility schemeIdUri="urn:scte:dash:cc:cea-708:2015" value="1=lang:eng;2=lang:eng,war:1,er:1"/>
so it creates a new CEA-708 track for accessibility tags with schemeIdUri = urn:scte:dash:cc:cea-708:2015
and extract accessibilityChannel and language from value attribute.
Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
Some part of the audio pipeline in the DefaultAudioSink
(PCM processors) are expecting little endian buffers.
As a result, in order to behave like MediaCodec,
make sure the passthrough MediaCodec-bypass pipeline
also processes little endian output buffers.
PiperOrigin-RevId: 310172464
This aligns mkv with mp4, flv and ts extractors.
This issue was found when AAC in an MKV container was not offloaded
as format.codecs was null.
PiperOrigin-RevId: 310170759
Previously the input format values were used,
but it could be incorrect if two format change were
occurring in quick successions.
PiperOrigin-RevId: 310142675
These methods operate on a thread-safe collection and are thus
inherently thread-safe. This simplifies some player setup configurations
where initial listeners are added on a background thread (e.g. when
using a dependency injection framework).
PiperOrigin-RevId: 310113181
Users of addTextOutput should instead query the current cues if they
need them. This is more consistent with how other listeners are handled.
PiperOrigin-RevId: 310112241
We currently have DecoderVideoRenderer and VideoDecoderRenderer, which
is very confusing! This one is package private, so we can rename it to
remove some of the confusion.
Also fix some nullness issues.
PiperOrigin-RevId: 309964088
In passthrough MediaCodec is not used except if
the format has a DRM.
Nevertheless the code was still requiring that a
passthrough decoder be present even if it was not going to be
used (aka no drm).
PiperOrigin-RevId: 309947271
- Fix DecoderAudioRenderer to re-init codec if the DRM session changes.
- Add canKeepCodec to DecoderVideoRenderer. Previously it was assumed
that the decoder could be re-used, but this will not be true in all
cases for FfmpegVideoRenderer.
Issue: #7079
PiperOrigin-RevId: 309935278
If the condition isn't fulfilled, they currently block until the
test runner times out the test. Our usual approach is to timeout
in the test itself so that the error message is clearly showing the
blocked condition.
Also clean-up some documentation.
PiperOrigin-RevId: 309930198
Now that MediaCodec is not use in passthrough, no
MediaCodec should be created in this mode.
Additionally, do not instantiate a MediaCodec in passthrough
#exo-offload
PiperOrigin-RevId: 309916131
With sample prepare (non-chunkless) the `Format` object in the TrackGroup is derived from the data in the stream and data in the manifest. This change includes the roleFlags from the HLS manifest parse in the final derived format.
DownloadManager doesn't know enough about the Downloader implementations to
know that interrupting the thread is the right thing to do. In particular,
if a Downloader implementation wants to delegate work to additional worker
threads, then it will probably not want its main thread to be interrupted
on cancelation. Instead, it will want to cancel/interrupt its worker threads,
and keep its main thread blocked until work on those worker threads has
stopped (download() must not return whilst the Downloader is still touching
the cache).
This change moves control over what happens to the individual Downloader
implementations.
Issue: #5978
PiperOrigin-RevId: 309419177
- Stop throwing InterruptedException from CacheUtil. When a CacheUtil operation
throws or returns, the caller should always check its own state to determine
whether they canceled the operation. If a caller is trying to catch
InterruptedException separately to IOException to do something different in
that case, they're probably doing the wrong thing. So it's simpler, and probably
less error prone, just to throw an IOException in the case of interruption.
- Throwing InterruptedIOException is also consistent with what our Extractor and
DataSource implementations do.
Issue: #5978
PiperOrigin-RevId: 309411556
We keep an index hint for the next pending player message. This hint
wasn't updated correctly when messages are removed due to a timeline
update.
This change makes sure to only use the hint locally in one method so
that it doesn't need to be updated anywhere else and also adds the "hint"
suffix to the variable name to make it clearer that it's just a hint and
there are no guarantees this index actually exists anymore.
issue:#7278
PiperOrigin-RevId: 309217614
testSubtitleEventTimes/IndicesHelper make assertions that only happen
to be the same because values in two different constants match up. It
seems much better to explicitly put the assertions in each test.
The other assert methods are just obscuring the underlying call to
Truth.
PiperOrigin-RevId: 309022044
Steps 4-10 of https://www.w3.org/TR/webvtt1/#cue-computed-line
This part is harder to fit into our code structure because it depends on
how many cues are simultaneously visible - so it has to go in
WebvttSubtitle not WebvttCueParser (which only deals with individual
cues in isolation).
This removes the `isNormal()` method that was trying to approximate
the correct behaviour.
PiperOrigin-RevId: 309021686
adPlaybackState is now non-null, and the uninitialized case is covered by a new
boolean hasAdPlaybackState. Position progress updates are now non-null and
initialized with IMA's VIDEO_TIME_NOT_READY constant.
Also fix some misc code issues:
- Remove empty branch for SmoothStreaming (Android Studio warns about this).
- Tidy onTimelineChanged and onPositionDiscontinuity and the methods they call
to improve naming.
- Remove logging for IMA events after release, as these methods are expected to
be called in the current IMA SDK behavior.
PiperOrigin-RevId: 308977116
The player's initial PlaylistTimeline has no ad cue points, so its first
MediaPeriodId has no nextAdGroupIndex. When the AdsMediaSource provides its
first timeline, the cue points become known. For the case where a preroll cue
point appeared, the preroll was detected due to isAd changing on the
MediaPeriodId. For the case where a midroll/postroll cue point appeared, the
MediaPeriodId was actually treated as the same, which leads to keeping the
unclipped original MediaPeriod.
Fix this behavior by checking for nextAdGroupIndex becoming set or decreasing.
PiperOrigin-RevId: 308974490
Its only real purpose is to encapsulate a download ID, but it doesn't actually save
any code, and arguably makes it more complicated by having multiple lists of
Downloader instances, indexed by key, and also because it's another (undocumented)
class to understand.
This CL retains the multiple Downloader lists, but they will be flattened in a
child CL.
PiperOrigin-RevId: 308838026
This is equivalent to the method ExoPlayer provides. It's nice for consistency,
and for retrieving the looper from test code.
PiperOrigin-RevId: 308830288
DownloadRunner.getDownloader was creating Downloader instances before the actual
DownloadManager under test would have created them. Tests were then asserting and
manipulating these Downloader instances, which is quite confusing. In particular
FakeDownloader.assertDoesNotStart() is an assertion on a Downloader instance that
only makes sense when called on an instance that DownloadManager would not have
created by itself.
This change replaces FakeDownloader.assertDoesNotStart() with an assertion on
DownloadRunner that no Downloader instance has been created.
PiperOrigin-RevId: 308822398
- Assertion chaining is generally discouraged. For example, because it's harder
to determine which assertion failed given a line number.
- Also removed chaining of the form obj.actionX().assertY(), because it's easy
for someone editing the test to accidentally delete actionX() when deleting
assertY(), where-as actionX() may often be important for subsequent assertions.
PiperOrigin-RevId: 308820503
- Remove assertReleased and replace it with a proper condition variable
that's opened when Downloader.download or Download.remove finish. As
far as I can tell assertReleased was basically implementing "sleep for
10 seconds after the Downloader starts". Note fixing this properly
also makes the tests run much faster!
- Use ConditionVariable instead of CountDownLatch(1).
- Use AtomicInteger instead of volatile int because it's clearer and
allows removal of explanatory comments.
PiperOrigin-RevId: 308819204
- Improve documentation explaining the benefits of ExoPlayer's ConditionVariable
over the one that the platform provides
- Allow Clock injection
- Create TestUtil method for obtaining a ConditionVariable whose block(long)
method times out correctly when used in a Robolectric test
- Add basic unit tests for ConditionVariable
PiperOrigin-RevId: 308812698
A previous change added these getters to CacheDataSource, but it can
also be useful to retrieve these components directly from the factory.
This is useful for tasks where we're going to need to build multiple
CacheDataSource instances (e.g., to make requests in parallel), and
also need to operate directly on the same components. It's a bit more
natural to retrieve them from the factory than from an arbitrary
CacheDataSource in this case, since it can avoid unnatural code where
you create a CacheDataSource instance earlier than you would otherwise
just to use its getters, and/or create one just to use its getters and
then throw it away.
PiperOrigin-RevId: 308606020
- Executor is a superclass of ExecutorService, so this is arguably a little
more flexible.
- It removes the need to use null for direct execution, because Runnable::run
is a direct executor that can be trivially used instead.
- Removing the error-prone "cannot be a direct executor" restriction in the
parallel version of SegmentDownloader requires not relying on the futures
returned from ExecutorService.submit() anyway.
Issue: #5978
PiperOrigin-RevId: 308586620
Currently, this method is only supposed to be called before removing
the listener from the player or when releasing the player.
If called at other times, it will throw an exception later when
a playback session is ended automatically.
issue:#7193
PiperOrigin-RevId: 308254993
The method is used to finish a brief "seeking" state that can be removed entirely
now state changes for seeking are masked.
PiperOrigin-RevId: 308237009
Unmarshal from json to MediaItem instead of Sample. Further the playlist
of MediaItems is converted to Intent extras which are read by the
PlayerActivity.
PiperOrigin-RevId: 308141231
While most ExoPlayer code parsing ByteBuffers is called with buffers in big
endian, in certain situation, buffers in little endian are used too.
MediaCodec produced ByteBuffers are in little endian, while buffers
receive from the sources are in big endian (ByteBuffer's default).
As a result, some code called from AudioSink in passthrough parsed
bytebuffer in little endian. This is not correct because those
format are specified in BigEndian.
Changing the endianness of the ByteBuffer returned from MediaCodec
would impact a lot more code that can currently be tested in the
current COVID lockdown situation.
As a result, this patch instead make the parsing code independent
of the ByteBuffer.order() set. All the code that is called from
DefaultAudioSink now parses the buffer explicitly in Big Endian.
Additionally, the MPEG big endian header data of size 4 bytes was
retrieved with ByteBuffer.get, which only returns one byte.
PiperOrigin-RevId: 308116173
The first session should only be created once we have the media items
and/or called prepare. Otherwise the first session is created with
an EventTime having an empty timeline making it less useful.
issue:#7193
PiperOrigin-RevId: 308100555
Part of what makes these tests hard to deal with (imo) is being
unable to easily run a specific config, or seeing exactly which one
failed (because you always see only the first failure).
I put the parameters as a method on ExtractorAsserts to
reduce the boiler-plate required in each test class.
I'll migrate the extension FlacExtractorTest in a follow-up CL
PiperOrigin-RevId: 307785380
Something that helps a constructor always seemed a bit strange.
It's now possible to use CacheDataSource.Factory directly instead.
PiperOrigin-RevId: 307661930
In the same way it made sense to tie CacheKeyFactory and CacheDataSource
together in
7ea83d7167,
it makes sense to tie the PriorityTaskManager to the CacheDataSource as
well. This prevents error prone scenarios where one can end up being
passed around without (or with the wrong instance of) the other.
This change also internalizes use of PriorityDataSource directly into
CacheDataSource, rather than requiring the caller to chain things
themselves.
PiperOrigin-RevId: 307647290
The sample timestamps are currently rounded to milliseconds, only to
be multiplied by 1000 later. This causes rounding errors where the sample
timestamps don't match the timestamps in the seek table (which are already
in microseconds).
issue:#7086
PiperOrigin-RevId: 307630559
This change generalizes the concept of "reading parameter sets" to
"reading prefix NAL units", ahead of a change that will treat AUD
and suffix SEI NAL units in the same way.
The change also introduces some static isXxxNalUnit methods for
clarity.
Issue: #7113
PiperOrigin-RevId: 307376967
Audio processors are now flushed twice after reconfiguration.
The second flush call cleared the pending trim start bytes so
transitions between tracks were no longer gapless.
Fix this by removing logic to clear pending trim bytes on flush.
As a result we may trim data incorrectly if there is a flush
before any data has been handled for seeking to a non-zero
position, but this edge case will happen rarely and the effect
shouldn't be noticeable.
PiperOrigin-RevId: 307344357
This is the missing attribute to support all features of the Sample with MediaItem. Hence PlayerActivity can use the setMediaItems() method directly without creating actual media sources in the app code.
PiperOrigin-RevId: 307102036
This makes it easier to use the helper methods because the player doesn't
have to be assigned to a SimpleExoPlayer in all cases.
PiperOrigin-RevId: 307039126
Update the comment on a suppression of Field.get(null) which is safe
but blocked by the checker.
These suppressions were introduced in d1e0572448
PiperOrigin-RevId: 307036441
We currently check for shouldContinueLoading, which is the intention to load,
not playbackInfo.isLoading, which is the actual loading state, when detecting
stuck buffering issues.
They only differ if the LoadControl said stop loading (based on nextLoadPosition),
but there is still a load in flight (updating bufferedPosition). This may cause
the exception to be thrown in edge cases that are only temporary.
PiperOrigin-RevId: 307022608
This is required to migrate the PlayerActivity away from Sample to MediaItem. It hence needs adding buildUpon to MediaItem to mix in the customCacheKey and streamKeys before playback.
PiperOrigin-RevId: 306710643
This is a more specific ViewGroup subclass that handles some of the
layout logic automatically. It's designed to work best with a single
child view, as used here.
PiperOrigin-RevId: 306654947
Even though they are annotated as non-null, Java users can pass in null values.
So we should verify the input to fail fast.
PiperOrigin-RevId: 306425487
This is the first CL for the offline qoe reporting
feature. Refer to the design doc for full information.
Design doc: go/exoplayer-offline-qoe
PiperOrigin-RevId: 305459231
Create a Builder that creates SimpleExoPlayer instances with fake
components, suitable for testing.
Basically extracts the Builder from ExoPlayerTestRunner to a standalone
class that can be re-used.
PiperOrigin-RevId: 305458419
This CL is a renaming only. It's mostly about finding a decent naming for the internal Playlist class. The plan is to have a public Playlist class in the converged Player API, so we need to rename the internal one.
PiperOrigin-RevId: 305266196
If we're in the ducked state and updateAudioFocus is called with a
new state for which focus is no longer required, we should restore
the player back to full volume.
Issue: #7182
PiperOrigin-RevId: 305232155
These were introduced in c7164a30a0
In each case I checked that the groups are not optional,
so if they match they must be non-null.
PiperOrigin-RevId: 305213293
This avoids cases where audio focus is never successfully acquired
because another app is holding on to transient audio focus indefinitely.
Issue: #7182
PiperOrigin-RevId: 305108528
When ClippingMediaPeriod first tried to read a buffer, if its end
position was before the end of the stream and it was buffered to its end
position, it would sometimes erroneously signal end-of-stream for
protected content because the sample queue might be waiting for DRM keys
at this point.
Work around the issue temporarily by signaling this specific case back
to ClippingMediaPeriod via the DecoderInputBuffer.
There will likely be a cleaner fix as a result of adding support for
dynamic clip end points in the future, at which point this can be
reverted.
issue:#7188
PiperOrigin-RevId: 305081757
It's interesting WebVTT explicitly handles line & position differently
in horizontal-rl/lr and vertical-lr/rl contexts. position is always
measured from the left of the viewport, even for rtl text, but line in
vertical-rl is measured from the right of the viewport.
We don't have to make Cue match WebVTT (I can go change the WebVTT
decoding instead) but it seems a reasonable 'default' to follow.
PiperOrigin-RevId: 304353900
ExoPlayer needs a codec to decide among WEBVTT and TTML decoder mimeType.
Apple describes IMSC1 in MP4 in
[RFC-8216 Section 3.6](https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-04#section-3.6).
The DASH manifest specifies the SMPTE-TT captions in the codecs in the manifest
(from W3C [TTML Profiles for Internet Media Subtitles and Captions 1.1](https://www.w3.org/TR/ttml-imsc1.1/#general-0).
DASH just doesn't require the rendition linking, but HLS does.
Apple implies the CODECS attribute of the variant needs to be do this. That is
with SHOULD and MAY language to imply the codec to use for it in the
[Authoring Guidelines](https://developer.apple.com/documentation/http_live_streaming/hls_authoring_specification_for_apple_devices)
This change defaults to WebVTT if no codec is specifed (same as current behavior) otherwise it picks it from the variants
referencing the media.
Without this, URL-encoding is assumed, which means ampersand-codes are
not carried through to the underlying web page correctly.
PiperOrigin-RevId: 304163733
HlsSampleStreamWrapper currently calls HlsMediaChunk.init, which calls back
to HlsSampleStraemWrapper.init. This re-entrancy seems a bit confusing.
PiperOrigin-RevId: 304139462
Selection of a passthrough codec will rarely (if ever) need to be customized, so
remove this capability from MediaCodecInfo.
Applications can still customize whether passthrough is used by overriding
MediaCodecAudioRenderer.usePassthrough, which now also checks for a passthrough
codec.
#exo-offload
PiperOrigin-RevId: 303964682
This is used to generate the initialization vector for encrypting the
cache contents.
Startblock:
<unknown commit> is submitted
and then
3w have passed
PiperOrigin-RevId: 303932151
This avoids massive changes to method signatures to add throws. Also, took suggestion to make it an `IllegalStateException`.
Move the catch outside of the finally that sets `nextLoadPosition` (this allows for possible recovery by reseting the `Extractor` and `TimestampAdjuster`).
Lastly, took the suggestion to make a minimum value for the tolerance (especially usefull for very short i-Frame only segments).
CharSequence is used by Notification builders and allows to set Spannable text.
It's the base interface of the String class, so apps wouldn't be break after
the update.
PiperOrigin-RevId: 303731890
This is required to align google3's stub (currently marked non-null) with Checker Framework's.
More information: go/matcher-nullness-lsc
Tested:
TAP train for global presubmit queue
http://test/OCL:303344687:BASE:303326748:1585344475427:29edc250
PiperOrigin-RevId: 303709053
- They are always listed with their canonical names
- Considering aliases means that blacklisting a decoder can end up
not actually blacklisting it, since it may still be accessible
via an alias. It also means that our decoder fallback logic can
end up falling back to a decoder that we've already tried!
PiperOrigin-RevId: 303348297
This callback will be deprecated, so moving all usages to better callbacks.
Some usages are still remaining that are less straight-forward to update.
PiperOrigin-RevId: 303298834
OnSeekProcessed is documented to be called as soon as all neccessary state changes
as a result of the seek have been made. As we now mask the state changes directly
when calling seekTo, we can also call this callback immediately without changing
the semantics of the method.
Our tests often use this callback as a way to wait for the internal player
to receive all pending commands and then report back. This is a special test
requirement for cases where we want to make sure no further updates happen as
a result of the player handling commands. To facilitate that, a new action is
added with a more descriptive name that achieves the same goal.
PiperOrigin-RevId: 303296210
This moves the playlist API methods to the Player interface. Implementation is moved from ExoPlayerImpl to BasePlayer where possible.
Further the CastPlayer is changed to implement the Player interface. Proper migration of the Playermanager to not use the ConcatenatingMediaSource anymore follows in a separate, future CL.
PiperOrigin-RevId: 302937779
Most of these are no longer needed since aa9eb5abc9
Cleanup change automatically generated by error-prone refactoring
//java/com/google/devtools/staticanalysis/errorprone:UnnecessaryJavacSuppressWarnings_refactoring on targets third_party/java_src/android_libs/exoplayer/v2/... java/com/google/android/libraries/exoplayer/v2/...
PiperOrigin-RevId: 302916092
This is less confusing than having audio processing functionality (e.g., playback
speed adjustment) just "not work" for some pieces of media.
If this change is merged, I will update #6749 to also track making DefaultAudioSink
intelligently enable/disable float output depending on how the audio processors are
configured.
Issue: #7134
PiperOrigin-RevId: 302871568
We currently have multiple places in ExoPlayerImpl that assign PlaybackInfo
instances and then inform listeners of all current changes. This is not ideal
because it causes multiple issues:
1. Some changes may easily be forgotten, e.g. there are clearly some checks
missing to see if isPlaying changed (e.g. in seekTo or setMediaSources)
2. Some callbacks didn't check if the value actually changed before sending
the callback (e.g. for the timeline change in setMediaSources - if the
timeline is still the same, we shouldn't send a onTimelineChanged event).
3. Having multiple callbacks in a single Runnable changes the order of
listener invocations slightly: Currently all events for one listener will
be send first before moving to the next listener. It should however send
a single event to all listeners first before moving to the next event.
All these issues can be solved by always using updatePlaybackInfo and never
assigning playbackInfo directly in another place.
Some tests needed to be updated as well because of issues (2) and (3). Also
added a new test to cover issue (1).
PiperOrigin-RevId: 302844981
It's incorrect to use an AudioFormat returned from AudioProcessor.configure
unless the AudioProcessor is active.
Issue: #7134
PiperOrigin-RevId: 302674132
This is a no-op for DefaultAudioSink for now, because DefaultAudioSink
currently disables processing anyway if the input uses ENCODING_PCM_FLOAT.
Issue: #7134
PiperOrigin-RevId: 302670534
androidTest of core already has the dependency on its main. Without this
exclude, gradle complains about type duplication when merging dex saying
"Type X is defined multiple times".
PiperOrigin-RevId: 302641585
If the start time of the edit falls within a sample, start from that
sample rather than the next one. This ensures playback can start from
the correct point if the sample is a keyframe, rather than having to
start from the next one.
Issue: #7133
PiperOrigin-RevId: 302639115
- Show renderers with no tracks in EventLogger track logging
- Log renderer names in EventLogger track logging
- Add useful message to ExoPlaybackException instances (including
renderer name for renderer errors)
PiperOrigin-RevId: 302421616
If MaskingMediaSource masks a multi-window media source, it may be that a period
is removed while we are using an initial unprepared masking MediaPeriod. That
means it's not guaranteed that a timeline update still contains our
unpreparedMaskingMediaPeriod and we should ignore timeline updates where the
period is no longer present because the it will be removed anyway.
PiperOrigin-RevId: 302383787
- This change also adds support for VideoFrameMetadataListener in the
AV1 renderer
- This is a preliminary step prior to adding FfmpegVideoDecoder
Issue: #2159
PiperOrigin-RevId: 301702460
This is a necessary step for Decoder implementations to support
audio and video. MediaCodecRenderer.DecoderException is renamed
MediaCodecDecoderException and extends the new DecoderException
Issue: #2159
PiperOrigin-RevId: 301698238
We have two known scenarios where the app could create an OOM error and
we want to handle it gracefully:
1. The app continues to allocate memory but doesn't make any progress
in the buffered position. OOM should be prevented by the default
load control and it should eventually throw an exception.
2. An extractor tries to allocate a large amount of memory on the
Loader thread based on information it read in faulty media files.
In this case we should attempt to play remaining media and then
throw an exception.
Both cases are already handled correctly, but we don't have any tests
ensuring that we don't introduce regressions.
PiperOrigin-RevId: 301585700
This removes a workaround that always continues buffering and instead
detects if the LoadControl returns false even though we don't have
any buffer. If enabled by a flag, this condition throws an exception.
PiperOrigin-RevId: 301584239
The restriction that these classes only work with SimpleDecoders
is unnecessary. An FfmpegVideoRenderer will not be able to use a
SimpleDecoder, because the SimpleDecoder assumption that each input
buffer can be decoded immediately into a corresponding output is
not true for all video codecs that Ffmpeg supports (e.g., H264 does
not have this property). Generalizing SimpleDecoderVideoRenderer to
DecoderVideoRenderer will allow FfmpegVideoRenderer to still use
the base class, without having to use a SimpleDecoder.
This is a preliminary change toward being able to merge a version
of https://github.com/google/ExoPlayer/pull/7079.
Issue: #2159
PiperOrigin-RevId: 301412344
The test is flkay (2/1000 runs) because the decoder initialization
before and after the seek are not perfectly deterministic. I couldn't
find a way to make them deterministic, so slightly chaning the test
setup instead. The test setup change doesn't affect the scenario being
tested.
PiperOrigin-RevId: 301390491
When no tracks are selected (or only tracks of unknown type), the
target buffer size is calculated to be 0. This means the player
won't request to buffer more data, nor can it start playback and
will be stuck forever.
PiperOrigin-RevId: 301374229
The assertion about the expected formats doesn't really belong in a
fake, the assertions should be closer to the test method.
This gets in the way when I try and write a new test in
AnalyticsCollectorTest that doesn't use the expected, constant Format
(because i want to specify drmInitData) - but changing the expected
Format is tricky because it's hard-coded into the FakeVideoRenderer
inner class.
I replaced the assertion in FakeRenderer with assertions in test
methods that used to assert on the format count.
PiperOrigin-RevId: 301353072
Previously calling removeListener would remove all instances of that
listener. Now it only removes a single instance.
This probably should have been part of introducing the Multiset:
2bd4d61b9b
PiperOrigin-RevId: 301191940
Without this change there's confusing behaviour if you pass e.g.
AnalyticsCollector (which implements both DrmSessionEventListener and
MediaSourceEventListener) to MediaSource.addEventListener: It will
receive DRM events too, even though you never passed it to
MediaSource.addDrmEventListener.
Also add some tests for MediaSourceEventDispatcher.
PiperOrigin-RevId: 301169915
This prevents OOM errors for high bitrate streams that attempt to fill
the buffer regardless of the memory usage.
Also change the max buffer sizes to ensure this is a no-op for video
streams < 20Mbps and audio streams < 260kbps.
Issue:#6647
Issue:#7006
PiperOrigin-RevId: 300720299
After this change users of ExoPlayerImpl and SimpleExoPlayer can use the media item base playlist API which converts the media item to a media source.
It adds the media item based methods to the ExoPlayer instead of the Player interface. This avoids a big change in the CastPlayer which requires migrating the cast extension to the MediaItem of the core module (follow up CLs).
PiperOrigin-RevId: 300575567
This CL removes the prefixes to the tests added after a6d0caaa3c.
This CL is generated by following command
$ find -name '*Test.java' | xargs -I{} sed -i 's/^\ \ public\ void\ test\([A-Z]\)\(.*\)$/ public void \L\1\E\2/' {}
PiperOrigin-RevId: 300547504
This avoids duplicate events being dispatched to object foo if
addListener(foo) is called more than once.
Part of issue:#6765
PiperOrigin-RevId: 300529733
We currently have the following logic to update renderers during
period transitions:
1. Wait for the currently reading period to finish reading all its
streams.
a. Advance reading period.
b. Set all streams that can't be replaced to final.
c. If streams can be replaced, replace them now.
2. Wait until playback position reaches the transition point
a. Disable all unneeded renderers (or those that need
re-enabling).
b. Advance playing period.
c. Enable all new renderers (i.e. all except the ones where
we replaced streams directly in step 1c.
This logic causes delays because steps 2a and 2c can easily happen
before 2b. Doing this allows a smooth transition for cases where
renderers change or where they need to be re-enabled.
The new order after this change is:
1. Wait for currently reading period to finish reading.
a. Advance reading period.
b. Set all streams that can't be replaced to final.
2. Update reading renderers iteratively.
a. If streams can be replaced, replace them asap.
b. If renderes need to be disabled, do so as soon as the
respective renderer ended.
c. Once step b is fully finished, enable or re-enable all new
renderers.
3. Wait unril playback position reaches the transition point AND
all tasks in step 2 are done (i.e. all renderers are set up for the
playing period).
a. Advance playing period.
As a nice side effect, decoder enabled and disabled events are now
always reported for the reading period, which is more consistent with
other renderer callbacks.
PiperOrigin-RevId: 300526983
This list was meant to simplify some usages where we only want to
make operations on enabled renderers. However, keeping this list
up-to-date is slightly error-prone (because renderers aren't added
and removed from this list next to the corresponding enable and disable
calls) and it makes it hard to do more fine-grained changes that only
enable or disabled a single renderer at a time.
PiperOrigin-RevId: 300513788
After this change MediaClocks and ExoPlayerImplInternal don't depend on the deprecated PlaybackParameter anymore but only know about playbackSpeed.
PiperOrigin-RevId: 300428791
This change deprecates the PlaybackParameters and remove the skipSilenceField from the PlaybackParameters. This implies that enabling and disabling skipping silences needs to be done on the Player.AudioComponent after this change.
After submission of the change, all Player API changes are done which are required to bring playbackSpeed and skipSilenceEnabled in the converged Player API state.
PiperOrigin-RevId: 300420843
In the HLS Spec (https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-04#section-4.4.3.6), specifically this or condition of this statement:
"... defined by the EXT-X-MAP tag, or is located between the start of the resource
and the offset of the first I-frame segment in that resource."
Change adds code to add this "implicit" Media Initialization Segment if no EXT-X-MAP defines one explicitly.
Pull in change to default to not use i-Frames for base AdaptiveTrackSelection.
The expectation is a subclases, that support transitioning to iFrame, will select these tracks.
This was a change suggested by @ojw28 to allow adpative track selection to work with IFrame only `Variant` as any other adaptive seleted `Track` in the `TrackGroup`. This actually works quite well with the exceptions that:
1. IFrame only tracks do not contain the same Rendition Group references as other non-iframe only varaints (so track selection should disable these tracks even in other non-video renderers.
2. Adapting to iFrame tracks only based on bandwidth might not be so good (as often larger spacial resolution iFrame track might have higher bitrate then lower spacial resolution non-iframe only track).
This change includes one proposed workaround in the AdaptiveTrackSelection class (only use iFrame for higher playback speeds).
Backout making the original `FormatAdjustingSampleQueue` an outer class and combining the new timestamp checking logic. This way the diff from `HlsSampleStreamWrapper` to dev-v2 are easier to see.
Update with code review suggestions:
1. rename to HlsCheckedSampleQueue to HlsSampleQueue and combine with format adjusting class.
2. Copywrite in added classes
3. Capture additional items useful for recovery and reporting in the exception class
4. Remove extraneous logging
5. eliminate magic number (50 seconds) and use percentage of duration
WIP:
- eliminate null check for chunk (chunkless prepare starts load before sampleQueue are created)
- work out recovery strategy
Add a SampleQueue subclass that checks the timestamp range of media samples queued to it and reports an exception on load if the timestamp is outside of spec bounds.
(Smashed to a single commit prior to rebase)
*** Original commit ***
Rollback of 949bbcfb2e
*** Original commit ***
Add masking for playWhenReady.
Masking is needed as soon as updates to a value can happen both in EPI
and EPII. PlayWhenReady is currently not masked because all updates
happen in EPI only. As soon as we allow pausing at certain times
(e.g. end of a stream), playWhenReady c...
***
PiperOrigin-RevId: 300330307
*** Original commit ***
Add masking for playWhenReady.
Masking is needed as soon as updates to a value can happen both in EPI
and EPII. PlayWhenReady is currently not masked because all updates
happen in EPI only. As soon as we allow pausing at certain times
(e.g. end of a stream), playWhenReady changes may be triggered by EPII
as well and that's why we need masking.
To know when the value actually changed, we also need to update the
internal state to include whether playback is supppressed.
***
PiperOrigin-RevId: 300303307
Masking is needed as soon as updates to a value can happen both in EPI
and EPII. PlayWhenReady is currently not masked because all updates
happen in EPI only. As soon as we allow pausing at certain times
(e.g. end of a stream), playWhenReady changes may be triggered by EPII
as well and that's why we need masking.
To know when the value actually changed, we also need to update the
internal state to include whether playback is supppressed.
PiperOrigin-RevId: 300284613
Exceeding the period duration may mean that that playback transitions
to another item even if the player is currently paused.
PiperOrigin-RevId: 300133655
There is no need for that, updating them is often forgotten and
takes up too much line space. Replace by a single TAG per test class.
PiperOrigin-RevId: 300113072
This change uses mime types in a functionally equivalent way to how we used the extension hint so far.
Using a mimeType instead of the extension has some advantages. Most importantly mimeTypes are used by the cast SDK with which we want to achieve interoperability in the cast extension.
Using a mimeType instead of the extension hint further appears to be a bit more clear (which might be opinionated). Further mime types are a well known and widely used concept to identify file type on the internet and it provides asterix based generalizations (audio/*, */*) which could express the media type OTHER that ExoPlayer is using internally (no usage of asterix required so far though).
PiperOrigin-RevId: 300058945
handlePrepare/Stop/SetPlayReady can be merged together as they all
handle changes to the desires state of the player.
Also, simplify parts of the control flow by not mixing code that
determines if audio focus needs to be handled with code that actually
acquires or abandons the focus.
PiperOrigin-RevId: 299824857
Without this option it's impossible to merge periods covering
different timestamps (at least not without playback issues).
Issue:issue:#6103
PiperOrigin-RevId: 299817540
The new version fixes some warnings in Gradle builds. Also
add missing indirect compileOnly dependencies to fix some more warnings
Issue:issue:#7007
PiperOrigin-RevId: 298855510
This option marks streams as final such that renderers play them out
completely, then waits until this happened, and then sets the player
to paused. After that, the player can continue to read the next period
to quickly resume playback if needed.
PiperOrigin-RevId: 298824745
Update it to allow any listener class to be registered (and thus
require the caller of dispatch() to provide the type of listener
to call).
Maintain MediaSourceEventListener.EventDispatcher as a sub-class
for now so that all existing references continue to work. This
avoids creating a huge diff in one CL. The intention is to in-line
these incrementally.
This is pre-work for issue:#6765
PiperOrigin-RevId: 298818198
The default Robolectric Looper simulation mode is changing to PAUSED from LEGACY.
The following tests fail in this new mode, and are thus being defaulted to LEGACY.
For more details see go/robolectric-legacy-looper-mode-lsc
Cleanup change automatically generated by error-prone refactoring
//third_party/android/androidx_test/tools/errorprone/java/androidx/test/tools/errorprone:LegacyLooperModeConverter_refactoring
Tested:
TAP train for global presubmit queue
http://test/OCL:297627974:BASE:298600828:1583273401491:7d94dbaa
PiperOrigin-RevId: 298809656
DashMediaSource is created with Manifest data and streamKeys can be empty given that streamKeys are only created out of MediaItem inside DashMediaSource, and this particular implementation don't extract them out of MediaItem properties.
Tested=Verified playback works.
PiperOrigin-RevId: 298550021
This change adds the createMediaSource(MediaItem mediaItem) method to the MediaSourceFactory interface. It doesn't deprecate createMediaSource(Uri uri) to keep the cl smaller. Deprecation and removing calls to the deprecated method from within the library and extension follow in a separate CL.
PiperOrigin-RevId: 298352442
The test had two problems:
1. It posts messages using a Handler and we need to idle the main looper
to actually deliver this message.
2. SimpleDecoder uses a background thread that is not within our control
from the test. Ensure the decoding happens after we queue input buffers
by using a lock.
PiperOrigin-RevId: 298300175
This is one step toward following the google3's test naming convention.
See go/java-testing/getting_started#basic-test-template for details
why prefix test isn't necessary.
This CL is generated by following command
$ find -name '*Test.java' | xargs -I{} sed -i 's/^\ \ public\ void\ test\([A-Z]\)\(.*\)$/ public void \L\1\E\2/' {}
and then manually modified following tests where test method names conflict with test target.
- VorbisUtilTest
- VorbisReaderTest
- UtilTest
- DownloadManagerDashTest
- DefaultOggSeekerTest
- OggPageHeaderTest
- HlsMasterPlaylistParserTest
PiperOrigin-RevId: 298074653
We should only ignore seek to the current position if we are
currently READY or BUFFERING. Also, pending initial seek positions
should only be saved while we have an empty timeline, independent of
the player state.
Issue:#6886
PiperOrigin-RevId: 297813854
This is more accurate since it's just a placeholder and none of the
values is provided by the media.
It also allows to fix a problem in ClippingMediaSource where we
couldn't detect a clipping error because we didn't know if the
timeline is a placeholder or not.
Issue:#5924
PiperOrigin-RevId: 297813606
When a new Timeline arrives in the Player, we check whether we can keep
existing MediaPeriods. This check currently involves a condition that
checks if the MediaPeriod is already prepared. The only reason we do
that is to avoid calling MediaPeriod.seekToUs, which is not allowed
on an unprepared MediaPeriod.
It's better to keep the MediaPeriod to prevent restarting the
preparation process. The prepration check can move further down to the
place right before we would call seekToUs.
PiperOrigin-RevId: 297812584
AnalyticsCollector keeps a list of existing MediaPeriodInfo that need
to be updated to new Timelines when they arrive. This already
happens in all cases except that the playingMediaPeriod wasn't updated
when it didn't change during the timeline update.
PiperOrigin-RevId: 297812038
The positions were interchangeably used with window and period
positions. This change more clearly ensures that all positions in the
AdPlaybackState are based on periods and that we use the right adjustments
for all usages.
PiperOrigin-RevId: 297811633
This removes noisy data from the dump files and allows updating less
dump files if a format field is added, removed or updated.
PiperOrigin-RevId: 297617138
Parallel asynchronous calls to MediaCodec.queueSecureInputBuffer() may
produce garbled video on some platforms. This workaround synchronizes
calls to MediaCodec.queueSecureInputBuffer() so that only one call is
in flight.
PiperOrigin-RevId: 297601037
This change adds the callback onSkipSilenceEnabledChange to the AudioListener and calls it when changed by the user by calling setPlaybackParameters, or when changed internally by the DefaultAudioSink if the parameters are not applicable. It needs to be plumped through AudioSink, AudioRenderer to SEP which eventually calls the AudioListener.
No changes to the Player interface so far. The getter of skipSilenceEnabled is added to SimpleExoPlayer for completeness, but not yet to the Player interface. The setter is not yet exposed, but implemented as a private method for implementation reasons.
PiperOrigin-RevId: 297590291
DefaultLoadControl applies the same min buffer duration to audio
and video. By default, min buffer is set equal to max buffer (50 seconds).
PiperOrigin-RevId: 297324489
Note: The dump files will need updating again when the extractors
are modified to only set the appropriate bitrate. Enhancing the
test first is nice, because it means that in subsequent CLs the
dump file updates can be used to quickly see what's changed in
the output.
PiperOrigin-RevId: 297188367
- Avoid having ExtractorHolder expose the underlying extractor.
- Make ProgressiveMP inject a DataSource instead of a DefaultExtractor.
This CL should introduce no functional changes.
PiperOrigin-RevId: 296944788
This change deprecates PlaybackParameter in AudioSink and splits it into playbackSpeed and skipSilenceEnabled. These properties are set separately in a future CL. The playback speed will be set through the MediaClock, while skipSilenceEnabled will be set by sending a message to the audio renderer.
PiperOrigin-RevId: 296457043
- Deprecate old Format.createXXX methods
- Deprecate most Format.copyXXX methods
- Stop using deprecated Format.copyXXX methods in the library
Note: Replacing library usages of Format.createXXX method
will be done in follow up CLs. These changes aren't purely
mechanical because we need to decide which out of peakBitrate
and averageBitrate to set in each case where currently a
single bitrate is provided.
Issue: #2863
PiperOrigin-RevId: 296450935
It's not clear why we're currently outputting the format in both init()
and consume() - it seems likely that this was accidentally introduced
in <unknown commit>
when we started outputting the format in consume() but didn't remove it
from init().
The SCTE-35 TsExtractorTest doesn't pass with the current code because
when it seeks back to the beginning of the file init() is not called
again so the second pass through only sees one sample (and
ExtractorAsserts checks that seeking back to 0 produces the same output
as reading the file from the beginning).
I generated the SCTE-35 sample using TSDuck's tsp command:
$ tsp --add-input-stuffing 1/10 \
-I file testdata/src/test/assets/ts/sample.ts \
-P pmt --service 1 --add-programinfo-id 0x43554549 --add-pid 600/0x86 \
-P spliceinject --service 1 --files scte_35.xml --wait-first-batch \
-P filter --negate --pid 0x1FFF \
-O file testdata/src/test/assets/ts/sample_scte35.ts
This was adapted from the instructions in section 5.2.24.1 of the TSDuck
user manual: https://tsduck.io/download/docs/tsduck.pdf
PiperOrigin-RevId: 296217084
Not important, but when overriding a method that can return null,
it seems preferable to put @Override first, followed by what it's
overriding (which includes the @Nullable).
Also remove explicit @NonNull use in the core library. @NonNull is
propagated by default, so this is redundant.
PiperOrigin-RevId: 296188379
This is one step toward following the google3's test naming convention.
See go/java-testing/getting_started#basic-test-template for details
why prefix test isn't necessary.
This CL is generated by following command
$ find -name '*Test.java' | xargs -I{} sed -i 's/^\ \ public\ void\ test\([A-Z]\)\(.*\)$/ public void \L\1\E\2/' {}
PiperOrigin-RevId: 296169886
When copying CryptoInfo for asynchronous input buffer queueing,
re-use the destination CryptoInfo's arrays to avoid re-allocating
memory.
PiperOrigin-RevId: 295706771
Note on UnknownNull: Where there exists a generically typed
base class and both null and non-null types are permitted,
we need to clear the default non-null that's otherwise
propagated everywhere. This then lets the nullness of the
type work properly.
PiperOrigin-RevId: 295582444
CryptoInfo.iv length is always 16. When the actual initialization vector
is shorter, zero out the trailing bytes.
Issue: #6982
PiperOrigin-RevId: 295575845
Previously, the input buffer accessUnit count
was passed as the output of the audio processors
which did not make sense as the processors can
split buffers.
This patch passes the access unit count through a
member variable.
PiperOrigin-RevId: 295572577
This is closer to how our actual renderers look like and allows tests
to use a similar logic to show/suppress the first frame in follow-up changes.
PiperOrigin-RevId: 295557548
We will eventually remove the workaround from ExoPlayerImplInternal
added in
b84bde0252
and replace it by an error that gets thrown if the LoadControl behaves
badly.
PiperOrigin-RevId: 295556131
Previously that was implicit, it was the passthrough dance:
- MimeTypes.getEncoding(inputFormat) did not
implement RAW MIME, so it was returning INVALID_ENCODING for PCM
- and allowPassthrough was returning
MimeTypes.getEncoding() != INVALID_ENCODING
- which was setting codecInfo.passthrough, and passthroughEnabled.
Thus Util.isEncodingPcm(encoding) is the opposite of
(MimeTypes.getEncoding(inputFormat) != C.ENCODING_INVALID)
This was rather implicit and brittle as anyone
could add support for audio/RAW in
MimeTypes.getEncoding and break PCM playback.
As a result make it explicit that allowPassthrough
must always return false in PCM.
PiperOrigin-RevId: 295144013
Modify TrackOutput.sampleData() to accept SampleDataReader instead of ExtractorInput. SampleDataReader supports only read and skip calls, which all sampleData() implementations already restrict themselves to.
PiperOrigin-RevId: 294905155
Currently only one access unit can be written per
buffer write. This has been found to be power
inefficient in an offload situation.
#exo-offload
PiperOrigin-RevId: 294886188
This information isn't easily available to the player at the moment (or it
would need to revaluate this every time), so add it to MediaPeriodInfo similar
to the existing isLastInTimelinePeriod.
The player needs to know whether a MediaPeriod is the last in its Timeline
window if we want to add an option to pause at the end of a window.
PiperOrigin-RevId: 294877628
Add fields in DecoderCounters for computing the average video frame
processing offset.
The MediaCodecVideoRenderer reports the video frame processing offset
and the demo app presents it on the debug information.
PiperOrigin-RevId: 294677878
The transition in EPII happens based on the duration of the periods, not
the windows. So use this duration in case they are not the same.
Also make sure to send the message at duration-1 because the playback position
at the duration is technically already the first position in the next item.
PiperOrigin-RevId: 294669335
This simplifies sending messages to the end of a stream. This was
already possible, but users needed to wait until the duration is known
before sending the message. This duration resolution can happen as part of the message position resolution.
PiperOrigin-RevId: 294626984
Issue #6853
Previously the body of an HTTP response was not included in an
InvalidResponseCodeException. This change adds a field to store
the response body, and updates DefaultHttpDataSource to populate
this value.
Language is already applicable to image formats as well.
It can also apply to video formats. For example when the
video contains burnt in subtitles. Also, some animation
studios produce multiple variants of animations, in which
text within the scene itself (e.g., a signpost) is
replaced to be language specific.
PiperOrigin-RevId: 294500227
- Replace tests specific to HTTP request headers with tests that
more generally test constructor correctness.
- Add test specifically around the constructor that infers the
HTTP method from postBody, since that's a non-trivial bit of
constructor logic.
Note: In general, I'm not sure this type of test (i.e., testing a
bit of trivial copying through a constructor) is worth the cost
of writing and maintaining them. That said, checking the new
uriPositionOffset is calculated correctly is non-trivial, as is
the HTTP method inference, so keeping them for now.
PiperOrigin-RevId: 294488684
This is a preliminary step toward adding a DataSpec.Builder,
which is needed for sanity when adding DataSpec.customData.
The existing absoluteStreamPosition field is very error prone,
because anyone using a Builder to adjust the request position
will need to remember to adjust two values:
dataSpec
.buildUpon()
.setAbsoluteStreamPosition(x)
.setPosition(x)
.build();
Furthermore, the difference between position and
absoluteStreamPosition is irrelevant in nearly all cases. In
the core library, the difference is only relevant when initializing
AES encryption/decryption to write/read cache files.
Replacing absoluteStreamPosition with uriPositionOffset will
simplify the code block above to:
dataSpec
.buildUpon()
.setPosition(x)
.build();
PiperOrigin-RevId: 294485644
Currently, the subset of audio tracks for adaptation is selected
purely based on the size of the subset in the track group, completely
ignoring the previously selected best individual track.
This change ignores all tracks with a different configuration than the
previously selected best track.
PiperOrigin-RevId: 294231806
While the window in which a message or a seek position is resolved is
still a placeholder, we need to re-resolve the position using the
user intent (i.e. the window position) when the timeline updates.
PiperOrigin-RevId: 293346360
The period in this method is most likely prepopulated correctly, but
this assumption is very error-prone and we should populate it locally.
PiperOrigin-RevId: 293345873
This allows to simulate samples in a stream more accurately
particularly when streams are prepared at a non-zero position and
issuing a sample with position=0 is not expected.
Also makes seek more realistic by also issuing one sample again.
PiperOrigin-RevId: 293344081
Once we receive an update from a masked source, we first start the
preparation of an already pending period, and only then notify the
player of the new timeline. If the period prepares immediately inline,
the MediaPeriod.onPrepared callback arrives before the
onPlaylistUpdateRequested call in the Player. THis is the wrong order
and causes issues when the player tries to lookup information in the
timeline that doesn't exist yet.
This change fixes preroll playbacks before live streams.
PiperOrigin-RevId: 293340031
The functional change is to set the bitrate fields to Format.NO_VALUE
in the case that they're non-positive in the header data. Else it's
very easy to to take the fields and copy them directly into Format as
incorrect values.
Issue #2863
PiperOrigin-RevId: 292920141
This change deprecates Player.onPlayerStateChanged(boolean pwr, int state). It removes deprecation for trivial cases. I'll remove other deprecated usages (mostly in ui module) in follow-up CLs to not bloat this CL.
PiperOrigin-RevId: 292917872
This condition is trying to detect when it might be necessary
to switch from a non-secure to a secure codec. This is not
possible if the DRM session is unchanged, unless a different
codec is required for some other reason (e.g., H264 -> H265),
which is anyway handled by canKeepCodec below.
PiperOrigin-RevId: 292909126
*** Original commit ***
Rollback of 3c56b113e4
*** Original commit ***
Rollback of d48dc4c159
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic...
***
PiperOrigin-RevId: 292457964
Passing EXT-X-KEY DrmInitData through the FragmentedMp4Extractor
doesn't work for streams with key rotation, because an extractor
instance is used for multiple segments, but is only passed the
EXT-X-KEY DrmInitData corresponding to the first segment.
This change removes passing DrmInitData through the extractor,
and instead passes it via FormatAdjustingSampleQueue. This is
in-line with how manifest DrmInitData is handled during DASH
playbacks.
Issue: #6903
PiperOrigin-RevId: 292323429
This is a nice-regardless improvement to SampleQueue, which will
likely to used to fix the referenced issue. It makes it possible
for SampleQueue subclasses to support dynamic changes to format
adjustment in a non-hacky way.
Issue: #6903
PiperOrigin-RevId: 292314720
Fix outline style subtitle
When a ForegroundColorSpan changes the foreground color, it is also applied
to the outline painter. In order to keep the correct color, one needs to
filter out theses span. We do this with a new cue that is our text source
for the specific edgeLayout.
Take care to only apply background color once
Test: Manual check - Subtitle view can show custom color subtitles from specific Subtitle
Renderer and outline is shown correctly using user defined color.
Calling setViewType with the same view type as the
subtitleView is using would throw InvalidArgumentException
instead of being a noop.
PiperOrigin-RevId: 291937202
We currently have 3 states, but the NOT_SET state isn't needed
anymore. We can therefore replace the IntDef by a simple boolean.
PiperOrigin-RevId: 291926049
We currently apply new parameter checkpoints from an absolute media
time and then substract the current media start time again to retrieve
the media time offset for this playback parameter checkpoint.
However, the media start time may change when unexpected discontinuities
happen (the start time doesn't actually change, but we change it to
correct for this discontinuity). This then invalidates the absolute
media time in the playback parameter checkpoints (which should have been
corrected as well).
Avoid this problem by also only applying the new start position
from the checkpoint. We don't have to save the start position anymore
because it will cancel itself out.
Also add some documentation and code clarification for improved
readability.
PiperOrigin-RevId: 291923069
SubtitleView now becomes a ViewGroup that owns a SubtitleTextView. It
handles some common styling defaults, but delegates the underlying
values down into SubtitleTextView through the SubtitleView.Output
interface.
When I add a SubtitleWebView this will also be a ViewGroup containing
a WebView and will implement SubtitleView.Output and convert Cue styling
into HTML & CSS.
PiperOrigin-RevId: 291903294
It doesn't seem worth keeping the cap, since the device
will presumably stop receiving major version updates at
some point anyway.
Issue: #6899
PiperOrigin-RevId: 291899439
This seeker is only seeking to frames that have already been read by the
extractor for playback. Seeking to not-yet-read frames will be
implemented in another change.
Issue: #6787
PiperOrigin-RevId: 291888899
We currently only keep the requested next content start position while
we are playing ads. However, we should also keep at least before a content
period is fully prepared to not loose the information about the user intent.
PiperOrigin-RevId: 291705752
There are existing bugs that need this flag to know whether the
current information in the window is still a placeholder or can
already be relied on for further calculation.
This flag will probably only ever be set in DummyTimeline, so it's
not added to the window.set method to avoid updating all clients.
Issue:#5924
PiperOrigin-RevId: 291705637
It could either live in .util or .extractor, but since it's not needed
outside the extractor package in core (and the FLAC extension), and
FlacStreamMetadataTest uses a FLAC asset, it seems preferable to move it
into the extractor package.
PiperOrigin-RevId: 291372032
CeaUtil depends on TrackOutput so should live in the extractors package.
To avoid having Cea708Decoder depend on extractors, this change also
moves the initialization data building/parsing to CodecSpecificDataUtil.
PiperOrigin-RevId: 291348317
Using @Test(expected=...) is discouraged, since the test will pass if
any statement in the test method throws the expected exception.
PiperOrigin-RevId: 291338224
Since we have the Playlist layer on top, it's always guaranteed that a
new playlist item has a new uid. So we can just keep the old one in all
cases and don't have to be careful to delete it. The deletion was necessary
previously in case multiple MediaSources use the same uids.
PiperOrigin-RevId: 291152349
Move Cea708InitializationData functionality into CeaUtil and delete the
class.
Move CeaUtil to the util package as it needs to be used both in
extraction and decoding.
PiperOrigin-RevId: 291128220
The only remaining use is to provide the initial position for the first media
period in the queue. At this point, the value is always equivalent to
PlaybackInfo.positionUs because they are set together to the same value in
PlaybackInfo.copyWithNewPosition.
PiperOrigin-RevId: 290749294
We have a flag that gets turned on if the current playback position has been
reset, so that messages from this reset position can be triggered. This
mechanism isn't actually depending on the startPositionUs field because it
should always be triggered in the first iteration with the new position.
PiperOrigin-RevId: 290749201
There are a couple of problems with how positions in PlaybackInfo are set at
the moment:
1. PositionUs isn't allowed to be C.TIME_UNSET. This is prevented by always
resolving to the current default position if needed.
2. In some places a window position was used as a period position. Use correct
position resolution procedure.
3. When creating a placeholder position to restart playback, we used the first
period in a window, not the one where the default position is.
4. The start position for ads was in some cases set to 0 without checking
the ad resume position.
PiperOrigin-RevId: 290749042
I needed to use Cue.Builder instead of just SpannableStringBuilder for
the regionOutput values, so I could attach the vertical info where
appropriate (since this is a property of the Cue, not a span).
PiperOrigin-RevId: 290709294
If an exception is thrown between updating the timeline and updating
the position in playbackInfo, the state may be inconsistent.
Exceptions are expected to be thrown while updating the player state
and we should handle such cases in a consistent way.
Similar to how we handle the same situation in seekToInternal,
the state is updated in a final block such that it gets updated to the
latest state even if an error occurs. Moving both the timeline and
position update together also ensures they always stay consistent.
PiperOrigin-RevId: 290624020
This restructure moves all the position resolving code to a static method and
removes the dependency of the MediaPeriodQueue on having an up-to-date timeline.
Both steps allow simplified reasoning about the code as the static method can't change
the state of the player, and there is no risk the queue can use the wrong timeline.
These propoerties allow to fix a bug causing inconsistent states in a follow-up step.
PiperOrigin-RevId: 290616395
It's never assigned or accessed from outside the class.
It was added in
<unknown commit>
then the accessor was removed in
<unknown commit>
PiperOrigin-RevId: 290601998
This makes MPEG audio utilities similar to utilities we have for WAV,
AC-3 etc., and moves them out of the extractor package so that an
extractor module can be split out without needing to have a class in the
extractor package in the common library.
PiperOrigin-RevId: 290595089
*** Original commit ***
Rollback of ff89170b00
*** Original commit ***
Fix some logic in AnalyticsCollector.
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is...
***
PiperOrigin-RevId: 290593700
*** Original commit ***
Fix some logic in AnalyticsCollector.
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is empty or a seek is pending. Since adding all the playlist API methods to the player,
this is no longer the right choice. Moreover,...
***
PiperOrigin-RevId: 290312118
Currently both are updated by separate setters. If an exception is thrown between
the two setters, the state may not be consistent.
Avoid this problem by always setting them together.
PiperOrigin-RevId: 290293600
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is empty or a seek is pending. Since adding all the playlist API methods to the player,
this is no longer the right choice. Moreover, we don't have a definite API that tells
AnalyticsCollector when a playlist API call has been handled (and we don't want to
have one).
We can fix this by always using the current Player position information as the source
of truth (instead of the media period queue). This is definitely more correct and also
works while a masking operation is pending. To fill in the additional information from
the media period queue, we can look up a matching media period. This may not be the
first one in the list if an operation is pending.
The new methods are similar to the previous tryResolveWindowIndex method, but:
1. They are always used (i.e. the current Player state is the main source of truth)
2. They also check the correct ad playback state, that was just ignored previously.
PiperOrigin-RevId: 290284916
Currently seeks are basically ignored. However, it's more realistic to re-queue the
single sample if the seek is to position 0.
PiperOrigin-RevId: 290273564
*** Original commit ***
Rollback of d48dc4c159
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a...
***
PiperOrigin-RevId: 290273295
- Add additional Listener methods to DownloadManager, to inform of
changes to whether the downloads are paused or waiting for requirements.
- Only schedule the Scheduler if we really are waiting for requirements.
- Only restart the service if we're no longer waiting for requirements,
and if there are queued downloads that will now be restarted.
Previously the service would be restarted whenever the requirements
were met, regardless of whether there was any work to do.
- Restart service if it might be stopping, as well as if it's already
stopped. Also restart service if there's a download state change to a
state for which the service should be started, if.
Issue: #6798
PiperOrigin-RevId: 290270547
First cl towards DefaultMediaSourceFactory (<unknown commit>) does not change the MediaSourceFactory interface except adding @Nullable anotations to setters.
PiperOrigin-RevId: 290269640
Doing so prevent Codec which is a big object with
JNI to be garbage collected.
As the codec can not be hold in the listener, there
is no way to call release, as it must be called on
the same codec.
As a result the release method is also removed.
The downside is that at runtime some callbacks may be
dropped but it should be a short transitive state.
This also simplifies lifecycle of the listener as
the client does not have to know if release needs
to be called or not.
An alternative would have been to hold a weak ref,
but I deemed it too complicated for the
runtime gain.
PiperOrigin-RevId: 290231659
This fixes an issue where a DownloadService implementation
that allows foreground but doesn't provide a scheduler would
not be restarted in the case that it was still in memory but
classed as idle by the platform.
It also speeds up service restart in the case that a
scheduler is provided.
Issue: #6798
PiperOrigin-RevId: 290068960
This method has two use cases:
1. Seeking. Calls are immediately preceded by a call to rewind(), and
the returned value isn't important unless it's ADVANCED_FAILED (i.e.
the caller is only interested in success and failure).
2. Advancing. The return value is important unless it's ADVANCED_FAILED,
in which case the caller wants to treat it as 0.
This change creates separate methods for each use case. The new seekTo
methods automatically rewind and return a boolean. The updated advanceTo
method returns 0 directly in cases where ADVANCED_FAILED was returned.
Arguments that were always hard-coded to true by callers have also been
removed.
This change is a step toward one possible solution for #6155. How we'll
solve that issue is still up for discussion, but this change seems like
one we should make regardless!
Issue: #6155
PiperOrigin-RevId: 290053743
- DownloadManagerHelper now passes all downloads to the
DownloadService when the service is attached (and once
the downloads are known). The service then starts the
foreground notification updater if necessary. This fixes
the ref'd issue.
- Don't call getScheduler() if the service is background
only. This was already documented to be the case on the
DownloadService constructor.
- If the service is started in the foreground on SDK level
26 and higher, satisfy the condition to move the service
to the foreground in onStartCommand rather than in stop().
It's much more obviously correct, and should produce the
same end result.
Issue: #6798
PiperOrigin-RevId: 290050024
Currently the following sequence of events happens at automatic period transitions:
1. Update queue (=release old playing period)
2. Disable unused renderers
3. Enable newly needed renderers
This order requires difficult to follow workarounds in AnalyticsCollector for all
events related to step 2 (disable renderers). The current media period has already
been advanced so can't be used. The current workaround saves the last known playing
media period that was published as part of a PlaybackInfo update in ExoPlayerImpl.
This works in most cases, but is inherently wrong because the published state in
ExoPlayerImpl may be completely unrelated to the updates happening on the playback
thread (e.g. if many other operations are pending).
Simplify and fix this problem by changing the order of the events above:
1. Disable unused renderers.
2. Update queue
3. Enable newly needed renderers.
This way the current playing media period can be used for both renderer disable
and renderer enable events, thus it's correct in all cases and the workaround
in AnalyticsCollector can be removed.
PiperOrigin-RevId: 290037225
Whenever we set the maskingWindowIndex, we also need to set the masking period index
and the masking position. Otherwise it may cause exception when the period index
is used together with the masking timeline.
PiperOrigin-RevId: 290036973
This optimization allows a ChunkSampleStream to output track
formats as soon as they're parsed during an InitializationChunk
load, rather than waiting until after the InitializationChunk
load is completed.
In DASH VOD, a single InitializationChunk typically loads the
moov and sidx atoms in that order. Hence for long form content
where the sidx is a non-trivial size, this may result in the
track formats being output a non-negligible period of time
sooner than was previously the case. This allows downstream
renderers to start codec initialization sooner, potentially
decreasing startup latency.
For a single test stream on a fast & stable network, this
pretty consistently reduced elapsed time until both audio and
video codecs have been initialized from ~0.5s to ~0.3 seconds
on a Galaxy S8. For 5 test runs without and with these patches,
the eventTime logged by EventLogger for the second decoder
init were:
Without (secs): 0.47 0.47 0.45 0.48 0.46
With (secs) : 0.32 0.33 0.34 0.31 0.40
PiperOrigin-RevId: 289845089
The current order of operations means that the Format is only passed
to the chunk's output after the DataSource has been opened. This
means that establishing the network connection and the downstream
renderers initializing their codecs are effectively serialized to
occur one after the other.
In the new order, the Format is passed to the chunk's output before
the DataSource has been opened. This allows the downstream renderers
to initialize their codecs in parallel with the network connection
being established, and hence latency at the start of playback is
reduced.
PiperOrigin-RevId: 289841854
We currently have a currentMediaPeriodId and an activeSessionId that are more
or less tracking the same thing unless the current media period isn't "active" yet.
Simplify this logic by using a single currentSessionId field and the respective
isActive flag of this session. Also move all session creation and activation code in
the same method to make it easier to reason about the code.
This change also fixes a subtle bug where events after a seek to a new window
are not ignored as they should.
PiperOrigin-RevId: 289432181
As discovered whilst investigating #6798, there are cases
where these methods are not correctly. They were added as
convenience methods that could be overridden by concrete
DownloadService implementations, but since they don't work
properly it's preferable to require application code to
listen to their DownloadManager directly instead.
Notes:
- The original proposal to fix#6798 stored the state change
events in memory until they could be delivered. This approach
is not ideal because the events still end up being delivered
later than they should be. We also want to fix the root cause
in a different way that does not require doing this.
- This change does not fix#6798. It's a preparatory step.
Issue: #6798
PiperOrigin-RevId: 289418555
This change makes it clear the SampleQueue doesn't outlive
the wrapping PlayerTrackEmsgHandler, and releases it from
PlayerTrackEmsgHandler.release().
This change is a no-op because calling release() is the
same as reset() in this case (the behavior only differs if
a non-dummy DrmSessionManager is being used).
PiperOrigin-RevId: 289416622
As a result, onMediaChunkLoadStarted gets invoked on the loading thread, and
init on the playback thread, matching the thread access comments.
Issue:#6321
PiperOrigin-RevId: 289167981
Dash live streams require that the client has an accurate wall clock
time and in absence of a UTCTiming element, this is assumed to be the
NTP time.
This change adds NTP time offset resolution for DASH live streams
without such timing elements.
PiperOrigin-RevId: 289098796
Unfortunately devices such as the MI 8 do not provide an alternative
working decoder. Some Vivo devices do provide one though.
PiperOrigin-RevId: 288911897
This improves readability by making clearer that reading no bytes from
the input in readFrames() is an expected case if the buffer is full.
PiperOrigin-RevId: 288711841
Currently, seeks are only tracked if both the start and the end of the seek
is within the same window. This means no seeking state is reported if the
playback switches to a new window during the seek.
This problem is fixed by tracking seek start and end events in all cases,
but only report seeking state once the window becomes the foreground window.
PiperOrigin-RevId: 288706674
These make the interesting bits of each assertion harder to follow imo.
Also remove all the assertWithMessage() calls at the same time, Olly
convinced me these are rarely useful since you can click from the stack
trace to the failing line in the IDE.
PiperOrigin-RevId: 288470704
- Simulate IO exceptions in the test using FlacBinarySearchSeeker for
seeking in FlacExtractorTests. This makes the test slower but covers
more test cases.
PiperOrigin-RevId: 288285057
There's currently no rendering support for ruby text in SubtitleView
or SubtitlePainter, but this does have a visible impact with the
current implementation by stripping the ruby text from Cue.text
meaning it doesn't show up at all under the 'naive' rendering.
This is an improvement over the current behaviour of including
the ruby text in-line with the base text (no rubies is better than
wrongly rendered rubies).
PiperOrigin-RevId: 288280416
This typo was introduced in ddb70d96ad
when migrating a static method with parameter `durationUs` to an
instance method where the correct field to use was `blockDurationUs`
(but `durationUs` also exists).
The test that catches this was only added in 45013ece1e (and
therefore configured with the wrong expected output data).
issue:#6833
PiperOrigin-RevId: 288274197
It's not used. I was trying to work out how to correctly cascade my
text-combine-upright styling, but deleting the method seemed easier...
PiperOrigin-RevId: 287989480
I decided the flags bit was a bit unclear so I played around with this
It's also needed for more 'complex' assertions like colors - I didn't
want to just chuck in a fourth int parameter to create:
hasForegroundColorSpan(int start, int end, int flags, int color)
PiperOrigin-RevId: 287989424
Relying on the precedence of spans seems risky - I can't find it
defined anywhere. It might have changed in Android 6.0?
https://stackoverflow.com/q/34631851
PiperOrigin-RevId: 287989365
-- Optimize Mp4Extractor for AC-4
-- Optimize FragmentedMp4Extractor for AC-4
-- Add test case for AC-4 in MP4
-- Add test case for AC-4 in Fragmented MP4
It's unreliable for at least one IMA ADPCM file I've found.
Calculating the blockIndex to seek to using exact properties
also seems more robust.
Note this doesn't change anything for the existing PCM test,
since averageBytesPerSecond is set correctly. It does make
a difference for an upcoming IMA ADPCM test though.
PiperOrigin-RevId: 287814947
An experiment with this algorithm didn't show positive results. We can
therefore keep the simpler default algorithm.
Startblock:
<unknown commit> is submitted
PiperOrigin-RevId: 287807538
Where media segments are specified using byte ranges, it makes
sense that a server might return 416 (which we don't consider
for blacklisting) if the segment is unavailable, rather than
the 404 (which we do consider for blacklisting) that we expect
when media segments are only specified using a URL.
Issue: #6775
PiperOrigin-RevId: 286620698
The Download constructor considers it invalid to have a failure
reason if the download isn't in the failed state. Unfortunately,
calling DefaultDownloadIndex.removeAllDownloads when there's a
failed download will change the state without clearing the reason.
If the downloads are then read back from the DefaultDownloadIndex
we end up violating the Download constructor assertion.
This change clears the failed reason for any existing rows in the
invalid state, and also fixes the root cause that allows invalid
rows to enter the table in the first place.
Issue: #6785
PiperOrigin-RevId: 286576242
Without this @Nullable, potential subclasses can't override the
method to return null if they don't want to use the renderer as a
media clock.
Issue:#6792
PiperOrigin-RevId: 286545736
This class is only used to hold temporary data while we parse the
settings and text, so we don't need it outside the Parser class.
Also remove all state from WebvttCueParser - this increases
the number of allocations, but there are already many
and subtitles generally aren't very frequent (compared to
e.g. video frames).
PiperOrigin-RevId: 286200002
Add support for MP3 as an encoding format for passthrough.
This change does not change the observable
behavior of Exoplayer.
Also name the magics.
#exo-offload
PiperOrigin-RevId: 286146539
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a LoadControl lets playback get stuck. This includes the case where
DefaultLoadControl reaches its maximum buffer size and not even a mim...
***
PiperOrigin-RevId: 286071115
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a LoadControl lets playback get stuck. This includes the case where
DefaultLoadControl reaches its maximum buffer size and not even a mimimal buffer
duration.
PiperOrigin-RevId: 285979989
This offset allows to improve the calculated live offset because it
can take known client-server time offsets into account.
PiperOrigin-RevId: 285970738
I want to add fields related to vertical text support, and neither
adding another constructor nor updating all call-sites of existing
constructors seemed like attractive propositions.
PiperOrigin-RevId: 285956024
- Remove duplicated null assignments
- Move mediaCryptoRequiresSecureDecoder reset to be with all the
other mediaCrypto stuff.
PiperOrigin-RevId: 285955134
MultiLockAsyncMediaCodecAdapter is an implementation of the
MediaCodecAdapter that uses multiple locks to synchronize access to its
data compared to the single-lock approach used in
DedicatedThreadAsyncMediaCodecAdapter.
PiperOrigin-RevId: 285944702
- Make extractor output samples that are uniformly distributed
with respect to time, with a target of ~10 samples per second.
The old approach could in theory put every frame into its own
sample, which would be very inefficient downstream because we'd
need to pass them individually to MediaCodec. It could also put
data corresponding to a long duration of time into a single
sample (e.g. if the sample rate of the content is low), which
is bad downstream because we decide whether to set the decodeOnly
flag on a per sample basis. More generally, the new approach
is more predictable :).
- Stop using the WavSeekMap to get sample timestamps, and instead
calculate them directly from the number of frames output. It's
more obviously correct, particularly for data formats like IMA
ADPCM where we'll need to adjust the data prior to output.
PiperOrigin-RevId: 285750010
In MatroskaExtractor, if the last cue time exceeds the duration
specified in the header, then we end up generating a negative
duration chunk as the last item in the SeekMap. We should probably
not do this, so drop it instead.
Note: Matroska does have a CueDuration element, but it's not used
in the one problematic file I've found.
PiperOrigin-RevId: 285738418
Currently, resetting the internal state related to the codec in done in 4 places
in MediaCodecRenderer:
1. In the constructor to set some sensible initial default.
2. In flushOrReleaseCodec to reset state after flushing
3. In releaseCodec to reset state to default values for a released codec.
4. In initCodec to reset state to defaul values for a new codec.
There are actuall only two types of state reset operations:
1. Resetting state for a released codec, so that a new codec isn't influenced by
previous codecs.
2. Resetting state after flushing an existing codec. This is a subset of (1).
So to simplify the class, this change moves all state resets to two methods
corresponding to the two cases above.
PiperOrigin-RevId: 285731913
These are transitively provided by testutil's build.gradle.
This makes the core module consistent with the others like ui, hls, dash
PiperOrigin-RevId: 285729566
This may happen for example when trying to load unfinished live media
chunks that can only be loaded at real-time playback speed.
The flag can be used by the sources to indicate that network transfer
will knowingly be throttled, such that transfer listeners like the
bandwidth meter can take this information into account.
PiperOrigin-RevId: 285397100
Also change IcyInfo.rawMetatadata from String to byte[]
ICY doesn't specify the character encoding, and there are streams
not using UTF-8 (issue:#6753). It seems the default of at least one
server is ISO-8859-1 so let's support that as a fallback:
https://github.com/savonet/liquidsoap/issues/411#issuecomment-288759200
Also update IcyDecoder to skip strings it doesn't recognise at all
instead of decoding invalid characters.
The feed from issue:#6753 now decodes accents correctly:
EventLogger: ICY: title="D Pai - Le temps de la rentrée", url="null"
PiperOrigin-RevId: 285388522
We previously used Locale.fromLanguageTag and then toLanguageTag to automatically
filter out invalid tags and to replace deprecated tags. However, this only works
for API 21+.
This change does no longer rely on the platform methods and instead:
1. Keeps invalid tags as they are. This may help if developers rely on
non-spec-complaint language tags (for example, #6681).
2. Adds a list of deprcated tags and their modern replacements to our code
3. Normalizes some short codes that have been superseded by macrolanguage codes by
their macrolanguage equivalent.
Issue:#6681
PiperOrigin-RevId: 285384841
This has been broken since
c3d6be3afd
and broken for ICY (where I noticed the problem) since
5695bae9d8.
ICY symptom is that we see no repeated metadata, because the
Icy-MetaData:1 header doesn't make it to the server so we never get back
icy-metaint.
PiperOrigin-RevId: 285379234
The presentationTimeOffsetMs may be C.TIME_UNSET for VOD content
and shouldn't be used in calculations for the windowStartTime.
PiperOrigin-RevId: 285363095
Retrieve the sample number in the extractor instead of passing a holder
to FlacBinarySearchSeeker. This change makes the code easier to
understand and is required to implement the seeking from the seek table.
PiperOrigin-RevId: 285241862
- WavHeader is now immutable and contains only values parsed out
of the WAVE FMT chunk. It no longer contains a C.PcmEncoding
encoding, or mutable data bounds.
- WavHeaderReader now parses the WAVE header chunks without any
additional logic (e.g. validating the block alignment value,
which is format type dependent).
- The SeekMap part of WavHeader is split out into WavSeekMap.
PiperOrigin-RevId: 285232498
This returns the current offset to the live edge. The calculation is
non-intuitive enough to provide this convenience method.
PiperOrigin-RevId: 285171090
This avoids needing to jump through type paremeter hoops to create a
sub-classable Cue.Builder.
Cue should have a standard set of fields, because it will be
consumed by renderers that don't know what type it is. The
existing subclass fields are only used inside their respective
packages, so can be part of a wrapper object instead.
This lays the groundwork for converting Cue's multiple constructors
into a Builder pattern.
PiperOrigin-RevId: 284992135
Keyframe was rendered rather than skipped when performing
an exact seek to a non-zero position close to the start of
the stream.
PiperOrigin-RevId: 284798460
The nullness checker complains about Integers with @IntDef annotations
so replace pairs with custom pair types for the timed event records in
PlaybackStats.
PiperOrigin-RevId: 284731834
Caveats:
- Block additional data is ignored if the block is laced
and contains multiple samples. Note that this is not
a loss of functionality (SimpleBlock cannot have block
additional data, and lacing was previously completely
unsupported for Block)
- Subrip and ASS samples are dropped if they're in laced
blocks with multiple samples (I don't think this is
valid anyway)
Issue: #3026
PiperOrigin-RevId: 284545197
This change constrains the use of sample state member variables to
writeSampleData, finishWriteSampleData and resetWriteSampleData.
Using them elsewhere gets increasingly confusing when considering
features like lacing in full blocks. For example sampleBytesWritten
cannot be used when calling commitSampleToOutput in this case
because we need to write the sample data for multiple samples
before we commit any of them.
Issue: #3026
PiperOrigin-RevId: 284541942
Refator to lift a method to create (and destroy) the OnFrameRenderedListenerV23() and split destroying the Handler from removing the MediaCodec onFrameRenderedListener to avoid double call to codec.setOnFrameRenderedListener()
This makes the format metadata null (instead of an empty Metadata
object) when it is not provided, and is therefore consistent with the
other extractors behavior.
PiperOrigin-RevId: 284171148
The capture frame rate is currently available both via Format.metadata
and decoded in Format.frameRate. As the container Format.frameRate may
be useful to apps, only store the capture frame rate in metadata (apps
will need to decode it but can now access the container frame rate too).
PiperOrigin-RevId: 284165711
- Remove "lacing" from member variables. They're used even if
there is no lacing (and the fact that lacing is the way of
getting multiple samples into a block isn't important).
Issue: #3026
PiperOrigin-RevId: 284152447
- Change sampleHasReferenceBlock to a block reading variable, which is
what it is (the distinction didn't matter previously, but will do so
when we add lacing support in full blocks because there wont be a 1:1
relationship any more.
- Move sampleRead to be a reading state variable.
- Stop abbreviating "additional"
Issue: #3026
PiperOrigin-RevId: 284000937
An I/O error could occur while handling the start of an mdta box, in
which case retrying would cause another ContainerAtom to be added. Fix
this by skipping the mdta header before updating container atoms.
PiperOrigin-RevId: 284000715
Saves around 200 lines of code. High level overview:
- Rename SampleQueue to SampleDataQueue.
- Rename SampleMetadataQueue to SampleQueue.
This CL should not introduce behavior changes. The only significant
changes in synchronization should be:
+ Add synchronized keyword to isReady.
- Seems to be necessary.
+ Add synchronized keyword to SampleQueue.sampleMetadata.
- Before this change, SampleQueue.sampleMetadata could acquire the
SampleMetadataQueue lock three times in a single method call.
Other miscellaneous improvements:
+ Put all private methods at the bottom.
+ Move release() to the right category.
PiperOrigin-RevId: 283795844
This parameter is a little confusing, especially as the behaviour
can be surprising if the intended use-case isn't clear. This change
moves the description of the parameter into the class javadoc,
adds context/justification and slims down each method's
javadoc to refer to the class-level.
Related to investigating/fixing issue:#6700
PiperOrigin-RevId: 283724826
Finailzed logic to update the `SampleQueue` write positions (first index) to push these into `HlsMediaChunk` when the track is initially created (from the Extractor output) and as each new chunk is queued to load (`init()` callback).
Add lots of debuging prints that can come out for the final merge.
Code is very close to a clone of `ChunkSampleStream`.
DASH implements this feature, extend the feature for HLS as well. First change just drops video samples.
For demuxed audio the audio samples will continue to play out to match the
dropped video, so need to keep indexes in all the sample queues related to a chunk and discard them all.
This is a minor change ahead of merging a full variant of
https://github.com/google/ExoPlayer/pull/6706, to make
re-buffers less likely.
Also remove variable substitution when parsing
AVERAGE-BANDWIDTH (it's not required for integer attributes)
PiperOrigin-RevId: 283554106
Calls to new Handler() without arguments are deprecated as of the latest Android
version. Replace them by a Util.createHandler call similar to the ones we
already have.
PiperOrigin-RevId: 283532891
Fixes issue:#6700
sample_cbs_truncated.adts test file produced using
`$ split -b 31795 sample_truncated.adts` to remove the last 10 bytes
PiperOrigin-RevId: 283530136
If LoadControl.shouldContinueLoading returns false and the renderers are not
ready for playback using the already buffered data, playback is stuck.
To prevent this situation, we always continue loading if the buffer is almost
empty. We already have a similar workaround for when
LoadControl.shouldStartPlayback returns false even if loading stopped.
Having both workarounds allows playback to continue even if the LoadControl
tries to prevent loading and playing all the time.
PiperOrigin-RevId: 283516750
*** Original commit ***
Improve `Format` propagation within the `MediaCodecRenderer`.
For example, fix handling of pixel aspect ratio changes in
playlists where video resolution does not change.
Issue:#6646
***
PiperOrigin-RevId: 282903626
When transitioning to a new stream in a different format, the audio
processors are reconfigured. After this, they are drained and then
flushed so that they are ready to handle data in updated formats for the
new stream.
Before this change, some audio processors made the assumption that after
reconfiguration no more input would be queued in their old input format,
but this assumption is not correct: during draining more input may be
queued. Fix this behavior so that the new configuration is not referred
to while draining and only becomes active once flushed.
Issue: #6601
PiperOrigin-RevId: 282515359
flush() is guaranteed to be called in all these cases anyway.
Also clarify documentation for AudioProcessor-specific methods that can
change the 'active' flag.
Issue: #6601
PiperOrigin-RevId: 282515255
This simplifies the contract of configure and is in preparation for
fixing a bug where more input can't be queued when draining audio
processors for a configuration change.
Issue: #6601
PiperOrigin-RevId: 282514367
- Move property to DrmSession; it feels like a more natural place
for it to go (and provides greater flexibility).
- Change flags to a boolean.
PiperOrigin-RevId: 281758729
They are all marked with a JavaDoc comment and the @WorkerThread annotation
which is useful if apps are using threading annotations. All other public
methods in the same classes are marked with @AnyThread to avoid the impression
we forgot to annotate them.
PiperOrigin-RevId: 281490301
The current workaround seems to cause compilation errors inside the
testutils module in Android Studio. This seems to fix them.
This doesn't introduce a circular dependency because it's only
the tests in library-core depending on testutils.
PiperOrigin-RevId: 281318192
Note:
- Fixing this uncovers another bug in how audio processor draining
works, so the test playlist still doesn't play correctly after this
change.
- Once we reconfigure the audio sink based on the ExoPlayer Format
rather than the codec MediaFormat in a later change, this change can
be reverted.
Issue: #6601
PiperOrigin-RevId: 281264149
- Make NonNull, which is already the case when using the manager builder.
- Better document PLAYREADY_CUSTOM_DATA_KEY, now that newPlayReadyInstance
is no more.
PiperOrigin-RevId: 281079288
The implementation of writing HDR10+ static metadata assumed that the
application would use default (big endian) byte order for this metadata but
MediaCodec expects the order to match the specification CTA-861.3.
PiperOrigin-RevId: 281050806
Also remove the "do we really need to do this" comment for AAC.
Parsing from codec specific data is likely to be more robust, so
I think we should continue to do it for formats where we've seen
this problem.
Issue: #6648
PiperOrigin-RevId: 280575466
Previously the renderer EOS (aka last frame rendered), was reported as soon
as the last encoded frame was queued in the codec renderer.
This leaded to EOS reported too early.
PiperOrigin-RevId: 280456277
This speeds up downloads where segments have the same URL with different
byte ranges. We limit the merged segments to 20 seconds to ensure the download
progress of demuxed streams is roughly in line with the playable media duration.
Issue:#5978
PiperOrigin-RevId: 280410761
Clear state for one mode when entering the other in both SimpleExoPlayer
and SimpleDecoderVideoRenderer. The latter is redundant for the case of
renderers that are used inside SimpleExoPlayer, but seems nice to have.
- Entering Surface mode means receiving a non-null Surface, SurfaceHolder
or TextureView in SimpleExoPlayer, or a non-null Surface in
SimpleDecoderVideoRenderer.
- Entering VideoDecoderOutputBufferRenderer means receiving a non-null
VideoDecoderOutputBufferRenderer in SimpleExoPlayer and
SimpleDecoderVideoRenderer.
PiperOrigin-RevId: 280155151
This aligns the method naming and Javadoc. The only remaining
inconsistency I can see is that the initial reference count for
DrmSession is 0 rather than 1. Unfortunately I think it's not
trivial to get these aligned, because DefaultDrmSessionManager
relies on being able to do something between instantiation and
the DrmSession starting to open the session. In practice this
doesn't really matter, since DrmSessions will be obtained via the
manager, which does increment thee reference count to 1 to be
consistent with how ExoMediaDrm acquisition works.
PiperOrigin-RevId: 280136574
The handling of times wasn't really clear to me, hopefully this more
exhaustive documentation helps a bit.
Also assert the end timecode is the 'correct' length for the format.
PiperOrigin-RevId: 279922369
To trigger receiving the broadcast it's necessary to idle() the shadow
main looper, which has to be done from the test thread. Therefore this
change removes the send broadcast action and instead sends the broadcast
from the test thread.
PiperOrigin-RevId: 279660935
- This is for consistency with PlayerControlView.
- Also update PlayerNotificationManager notification if shuffle
mode changes. This is for consistency with what happens when
the repeat mode changes. By default the notification will be
unchanged, but custom implementations can extend and then
override createNotification, and given these modes change
infrequently it feels like we can just do this. The alternative
for achieving consistency would be to remove handling of repeat
mode changes.
Issue: #6582
PiperOrigin-RevId: 277925094
This means multiple failures are all logged, instead of the test
stopping when the first assertion fails. Makes tests like this with
lots of independent assertions much easier to work with.
I limited the expect to a single assertCues() call, otherwise
the error message gets very long and is hard to read, but I
still think this is an improvement.
PiperOrigin-RevId: 277523300
Cue's UNSET and null values should be used when the source data
doesn't specify *and* the spec doesn't provide a clear default.
In the WebVTT case, the defaults are clear, so we use them
explicitly.
PiperOrigin-RevId: 277522899
The framework opus decoder discards some samples after a call to
flush(). Because we flush a decoder that is being retained across an
input format change, this means that the start of audio gets truncated
when transitioning to a new opus stream. See also
https://android.googlesource.com/platform/frameworks/av/+/refs/heads/android10-release/media/libstagefright/codecs/opus/dec/SoftOpus.cpp.
Avoid this by recreating opus decoders instead of flushing them. It
seems fine to do this for all opus decoders as reinitialization should
be cheap, OEM-provided implementations may also discard samples and
playback shouldn't be interrupted on reinitialization due to the
downstream AudioTrack buffer.
PiperOrigin-RevId: 277458759
Update it to throw if hasNext() is false, to match Java's Iterator
interface.
This also simplifies the null-checking annotations required
PiperOrigin-RevId: 277059766
Also remove it from all tests, these aren't covered by the null-checker
Covered by the following package-info.java files:
- j/c/g/a/exoplayer2/ext/mediasession/package-info.java
- j/c/g/a/exoplayer2/package-info.java
- j/c/g/a/exoplayer2/offline/package-info.java
- j/c/g/a/exoplayer2/video/package-info.java
- j/c/g/a/exoplayer2/ui/package-info.java
PiperOrigin-RevId: 277038916
*** Original commit ***
Rollback of bf01ff0f60
*** Original commit ***
Use Float.NaN for Cue#DIMEN_UNSET
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it a...
***
PiperOrigin-RevId: 276674142
*** Original commit ***
Use Float.NaN for Cue#DIMEN_UNSET
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it accidentally.
***
PiperOrigin-RevId: 276315786
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it accidentally.
PiperOrigin-RevId: 276277784
With lots of int comparisons close together, this makes the error
messages much clearer and saves having to manually match up line
numbers.
Also make every @Test just throw Exception
PiperOrigin-RevId: 276079806
Without this, a subtitle track empty edit list used to offset the start of
subtitles is ignored.
Also the current code seems to depend on the order in which
we parse the tracks (audio first means we have gapless info when we parse
video track, while video first we wouldn't).
It's not clear why we can't handle both edit lists & gapless info
PiperOrigin-RevId: 276029744
- Leaving GvrAudioProcessor for now.
- Removing GvrPlayerActivity because it was never released. Also removing
related UI classes. These were released, but it's unlikely anyone would
have been using them directly.
PiperOrigin-RevId: 275822516
*** Original commit ***
Rollback of 4ad4e3e4fc
*** Original commit ***
Rollback of 3b22db33ba
*** Original commit ***
add top-level playlist API to ExoPlayer
Public design doc:
https://docs.google.com/document/d/11...
***
PiperOrigin-RevId: 275813737
ConditionVariable.block(timeout) doesn't work in Robolectric, because it
relies on the system clock which doesn't advance.
PiperOrigin-RevId: 275798281
@MonotonicNonNull is not useful if the variable is final, because it's only
assigned once and guaranteed to keep it's current nullability in the same
way as @MonotonicNonNull ensures it's kept non-null after checking.
This way, the workarounds can also be removed.
PiperOrigin-RevId: 275428656
GlViewGroup doesn't work properly as an actual ViewGroup. For example,
it doesn't support addition of child views after instantiation. This
change turns the class into a renderer, which is also more consistent
with other classes in the package.
PiperOrigin-RevId: 275322295
If an odd resolution is impossible in the specification itself, then we know
that the caller is passing invalid data. Round up on the assumption it's a
rounding error so that playback can proceed.
Issue: #6551
PiperOrigin-RevId: 275226813
Use composition instead.
This makes the null-handling more explicit & complete (previous implementation
tried to prevent null values, but didn't override all mutation methods
e.g. replace(), putIfAbsent() etc.)
PiperOrigin-RevId: 274778513
*** Original commit ***
Remove null-ness of muxedCaptionFormats list
Pre-work for removing HlsMasterPlaylist and HlsPlaylistParser from null-checking
blacklist.
***
PiperOrigin-RevId: 274591502
If a surface was previously passed to the player then an output buffer
renderer was set, we would remove surface callbacks but not clear the
surface on renderers that accept MSG_SET_SURFACE.
PiperOrigin-RevId: 274532266
download calls through to CacheUtil#cache, which handles skipping already downloaded bytes.
It is useful for callers to know that ProgressiveDownloader has this behavior - otherwise, they might reimplement the logic themselves.
I hope this behavior is something that can be part of the public API :)
PiperOrigin-RevId: 274202995
This is a proof of concept for cleanup we should do for all of
our DataSource implementations as we move toward stabilizing
parts of the API.
- Move all XDataSourceFactory classes to be inner classes.
- Remove chained constructors for XDataSourceFactory classes. Keep
required args going through constructors. Use setters for the
rest.
- Not applicable in this case, but we probably want to deprecate
all but the no-arg method for instantiating eac XDataSource
instance (with the all-arg method kept but with the intention
of making it package private).
PiperOrigin-RevId: 274162076
- Verifies that playWhenReady doesn't become true if audio focus
is denied.
- Also verifies there's no suppression reason in this case, because
the denial is permanent rather than temporary.
PiperOrigin-RevId: 274141099
When newIndex overlaps oldIndex with newstarttime < oldstarttime, according to the segNum of endtime
in newIndex and oldIndexLastSegnum to calculate the segmentNumShift.
It's confusing that app:played_color also modifies the colors
that derive from it, but the corresponding setter does not. It
seems generally clearer just to define constants.
PiperOrigin-RevId: 273249557
Move reusable code from LibvpxVideoRenderer to SimpleDecoderVideoRenderer.
Pass outputBuffer to renderOutputBuffer method instead of keeping the reference in the renderer.
PiperOrigin-RevId: 272899549
It's confusing that seekTo(player, windowIndex, positionMs) does
clamping, because it only makes sense if windowIndex is the current
window.
Note: This doesn't actually fix anything (other than code clarity).
In cases where we were passing other windowIndices, we always
passed 0 as the position and so the clamping logic wouldn't have
had any effect.
PiperOrigin-RevId: 272857104
We currently set it to shouldContinueLoading, which isn't correct if
shouldContinueLoading is set to false and we still have an ongoing load.
Change it to also be true if the media period is still loading.
PiperOrigin-RevId: 272823473