The API is a lot more useful if apps can rely on the fact
that the gain is linear and applied to all channels.
This is already guaranty by AudioTrack and should be too
by any reasonable implementation.
PiperOrigin-RevId: 359706113
Given we're proposing to make reading from the end a non-error case,
it's important to check that we return the right thing from open(),
and that we read the right thing (i.e., nothing) once opened.
For now, this test allows quite a bit of permissiveness, in line
with other related tests. This will be tightened up in due course.
PiperOrigin-RevId: 359504075
Allow offload of gapless content even if gapless offload is not known to be supported by the device.
This is not exposed in the high level DefaultRendererFactory as most
users are expected to prefer fidelity to power savings.
PiperOrigin-RevId: 359336407
The constant values are the same, so this is a no-op, but for
correctness, we should pass the defined constant that the API
documents itself to accept.
PiperOrigin-RevId: 359293471
The new name reflects that it also waits for previously-used renderers
to be disabled.
Also fix some broken javadoc. These methods changed signature in
ea347a464a
PiperOrigin-RevId: 359253177
The concept of Renderers is not needed in the
Player interface. Move it to ExoPlayer.
This should not break most users as they use SimpleExoPlayer.
PiperOrigin-RevId: 359220977
Currently, this only asserts that *if* an exception is thrown, it
must be a position-out-of-range exception as determined by
DataSourceException.isCausedByPositionOutOfRange.
Issue: #7326
PiperOrigin-RevId: 359092124
Assert that an exception is not thrown from DataSource.open
if the DataSpec's start position is valid but its end position
extends beyond the end of the data.
HTTP based DataSource implementations have no good way of
knowing when this is the case, so it makes sense to make this
the required behaviour, rather than requiring an exception to
be thrown or allowing both.
There are also use cases where the caller may want to use the
end position as an upper bound, without knowing for sure how
long the content is. An example of this use case is wanting to
pre-cache the first N bytes of a stream. This implies that any
exception should be thrown after reading to the end of the
data, rather than preemptively in open.
Issue: #7326
PiperOrigin-RevId: 359063721
- If DataSource.close fails then it's unknown whether the underlying file was
written to the cache. We should assume that it has not been.
- Always re-query cachedBytes at the start of CacheWriter.cache, since its
current value may be incorrect if a previous failure was the result of a
file not being written to the cache.
PiperOrigin-RevId: 359039109
- Make it a property of the DataSource, not of the resource.
- Apply it only when a contract test reads using an
unbounded DataSpec.
PiperOrigin-RevId: 358997735
When we add DRM pre-acquire support to SampleQueue, we'll dispatch
twice the number of acquire and release events. This is slightly
confusing, since there's the same number of
DrmSessionManager#acquireSession() calls.
We can mitigate this by only dispatching each acquire and release
event to at most one EventDispatcher.
This also changes the events fired when playing a stream with both audio
and video encrypted with the same keys (even without pre-acquisition).
Before: The EventDispatcher would see 2 aquires, 1 key load and 2
release events.
After: The EventDispatcher will see 1 acquire, 1 key load and 1 release.
PiperOrigin-RevId: 358804502
This is a no-op assuming the class is always used correctly.
When release causes referenceCount to reach zero there can be at most
one EventDispatcher still connected (which is the one that must be
passed to that final release() call), so we can always pass the event
directly to the EventDispatcher passed in to release().
PiperOrigin-RevId: 358794004
There are two different patterns we use at the moment:
1. Call both deprecated and non-deprecated method from call site with
no default method implementation body.
2. Use default method of non-deprecated method to call deprecated
method.
Pattern 1 is easier to reason about as it makes the calls more explicit,
so changing all usages of pattern 2 to pattern 1.
PiperOrigin-RevId: 358769803
This adds an optional DrmSessionManager#preacquireSession() method
and implements it on DefaultDrmSessionManager.
The manager doesn't promise to keep the preacquired sessions alive, and
will proactively release them if a ResourceBusyException suggests the
device is running out of available sessions in the underlying framework.
In a future change, SampleQueue will preacquire sessions on the loading
thread and keep track of preacquired 'references', releasing them
when seeking or clearing the queue.
Issue: #4133
PiperOrigin-RevId: 358381616
We already report these errors through callbacks to interested listeners.
However, to ease debugging with bugreports and local error detection,
it's helpful to also log these non-fatal execptions to logcat. Otherwise
nothing in logcat indicates that the player recovered from an exception.
Issue: #6384
PiperOrigin-RevId: 357923899
This is preferable to just logging to LogCat so that listeners can
report this to analytics systems if required.
Issue: #6384
PiperOrigin-RevId: 357906079
The SampleStream.readData contract is that when reading a sample
with a flags-only buffer, the buffer timestamp and flags should
be set and the read position should not be advanced.
#minor-release
PiperOrigin-RevId: 357842130
This type is different to the selection reason, which is
dynamic (i.e., corresponds to the individual selected track,
which can change during playback). The static type is
exposed via TrackSelection, where-as the selection reason
will be internal to the core (i.e., player) module.
PiperOrigin-RevId: 357578201
These have limited value, and are confusing because they're only
actually used if the override only selects a single track (if the
override is an adaptive selection then the values are never used).
The simpliest path forward is to remove them.
PiperOrigin-RevId: 357573186
The source can be used in compositions (in fact, every source is
automatically used in an internal composition when constructing the
playlist), and there is not really a concept of top-level media source
any more since the Player supports playlists.
The actual restriction is that the content media source needs to have
exactly one period to be able to create a SinglePeriodAdTimeline.
#minor-release
PiperOrigin-RevId: 357544191
If keepalive is disabled the existing code over-eagerly releases
DrmSession instances. This is arguably OK since a (Default)DrmSession
should be released before its (Default)Manager is released
(since the underlying MediaDrm instance might be released when the
manager is released). And if all sessions are released before the
manager is released then `sessions` is empty, so the loop is a no-op.
Issue: #8576
#minor-release
PiperOrigin-RevId: 356955308
The `DrmConfiguration.sessionForClearTypes` property is often used
to ensure a secure decoder is used for clear ads played in encrypted
content. This is because some devices show black frames when switching
decoders.
Before this change the DRM config isn't propagated down when
constructing the ad media source, meaning
`DrmSessionManager.DRM_UNSUPPORTED` is always used, which will
cause playback to switch from secure to clear decoder when transitioning
to an ad break (ignoring the MediaItem `sessionForClearTypes` option.
Issue: #8568
#minor-release
PiperOrigin-RevId: 356951124
It's used by the UI and mediasession modules. We may be able to move
it into the UI module if/when the mediasession module goes away.
PiperOrigin-RevId: 356734939
Without this a new manager is instantiated for every item in a playlist,
meaning the impact of caching improvements to DefaultDrmSessionManager
are reduced (since the cache doesn't persist across playlist items).
With this change, playlists of items with identical DRM config will use
the same manager instance (and thus share existing sessions).
Issue: #8523
#minor-release
PiperOrigin-RevId: 356690852
ControlDispatcher and DefaultControlDispatcher also need
to move to common for the UI module. As does PlaybackPreparer,
although that will be removed entirely in a future release.
PiperOrigin-RevId: 356467394
- When throwing a recoverable error from a renderer, it's important to understand
exactly how the player will attempt recovery. Clarify the documentation to
make this explicit.
- Rename some methods/constants to make it clear that error recovery is specific
to renderer errors. The current recovery mechanism only makes sense for
renderer errors. Making the naming renderer specific avoids reader doubt that
the implementation doesn't appear to be generic enough for other types of
errors.
PiperOrigin-RevId: 355650945
Before, the level was set to null in this case.
MediaCodecUtil.getCodecProfileAndLevel() was therefore returning null
and the fallback to AVC/HEVC was not enabled in MediaCodecVideoRenderer.
Issue:#8530
#minor-release
PiperOrigin-RevId: 355574499
Without this no error is currently logged or propagated to EventLogger.
The propagation doesn't happen because
MergingMediaSource.ForwardingEventListener only propagates events
originating from the "main" source in the merge:
<unknown commit>
#minor-release
PiperOrigin-RevId: 354902467
This also moves DefaultHttpDataSource to common, which seems
sensible, else non-player components that need a DataSource
don't have any useful concrete implementations. We should
think about moving some of the other concrete implementations
to common as well.
PiperOrigin-RevId: 354738925
- The order of sample stream (and thus the order in which loads are
triggered) currently depends on a Set and thus on the hash codes
of the objects that change with every run. Changing to a List solves
this problem.
- The FakeAdaptiveDataSet directly created a static Random (with random
seed) to compute the variation of chunk sizes. Changing this to an
injected Random object that can always be initialized with the same
seed also removed this randomness from the tests.
PiperOrigin-RevId: 353878661
This is achieved by only triggering one message at a time. After
triggering a message we send another to ourselves to know when the
following message can be triggered.
Other required changes:
- The messages need to be sorted correctly (by time and creation order)
- To prevent deadlocks when one thread is waiting for another,
we need to add new method to Clock to indicate that the current
thread is about to wait. This then allows us to trigger messages
from other threads in FakeClock.
- AnalyticsCollectorTest needed some adjustments:
- onTimelineChanged now deterministically arrives after the initial
timline is already known, so some of the period information changes
from window only to full period info.
- The playlistOperations test suffers from a bug that the first frame
is rendered too early and that's why we now get additional events.
PiperOrigin-RevId: 353877832
Currently only delayed messages are handled. Change this to handling
all messages so that we have more control over their execution order.
This requires adding a new wrapper type for the Message to support
the obtainMessage + sendToTarget use case.
PiperOrigin-RevId: 353876557
They only require common. This allows their use for non-playback networking
without requiring the user to depend on the whole of core. I will also make
the same change for Cronet, although this needs a little more work.
PiperOrigin-RevId: 353649388
`TrackSelection` had mutation methods which were to be called only
internally by ExoPlayer components but were exposed in the
public `Player` interface.
The mutation methods have been moved out of `TrackSelection`
to a new class `ExoTrackSelection`.
Current track related read-only method have also been moved out,
because they are actually something quite unclear.
Even for a single item playlist, it's the track being buffered rather
than the track being played, which is unclear.
But when you have a playlist it starts to get really confusing,
because if the next item is being buffered, then it's actually
the last track to be buffered in the currently playing item.
As a final aside, the implementations don't do proper thread synchronization
to ensure visibility of updated state by the calling thread.
Exposing those mutable methods in the public `Player` interface
was problematic because they leaking internal concepts of `ExoPlayer`.
This is also required to minimize the `Player` interface for long term
stability.
`ExoTrackSelection` is a subclass of `TrackSelection`.
This is not ideal as an `TrackSelection` implementation could
break the current immutability.
This was done in order for this refactor to be simpler.
A future patch will fully split the two classes.
All `MediaPeriod` and `Sources` had to be updated to use the new
`TrackSelection` dynamic aspect class name.
An alternative would have been to break ExoPlayer's public API, keeping
`TrackSelection` as the dynamic aspect name, and calling the public static
aspect class `TrackSelectionState` or similar.
Nevertheless, while it would have impacted less files, it would have
many more small apps and casual users of ExoPlayer.
#player-to-common
PiperOrigin-RevId: 353637924
`ImaAdsLoader` only loads ad media URLs once playback of the preceding ad (if
any) has started, and this behavior is likely to be similar for other ad loader
implementations due to limits on how long before an ad plays it is meant to be
loaded. This is problematic for very short ads followed by an ad because the ad
will load to the end but load control may not allow playback to start due to
the total buffered duration being low.
Fix this by allowing playback to start regardless of load control if we are
waiting for an ad media period to prepare.
An alternative fix would be to fake the ad progress in the `ImaAdsLoader` to
trigger loading the next ad, but this would only allow one ad to load ahead (so
the problem would remain for two short ads in a row followed by another ad).
Issue: #8492
PiperOrigin-RevId: 353600088
This is necessary for the child cl that `TrackSelection`
in two distinct class. It avoids to split the array
version of such class too.
TrackSelectionArray exist to have an immutable array of TrackSelection.
Internal users are trusted to not mutate the array.
One drawback of this approach is that a `TrackSelectionArray`
has to be allocated on the boundary of the `Player` interface.
This should not be a performance issue as this only happens
on trackSelection changes, when the user calls
`Player.getCurrentTrackSelections` and on
`updateLoadControlTrackSelection`.
#player-to-common
PiperOrigin-RevId: 353582654
This field changed name during the code review, but these names and
references weren't updated to match.
Also use an ImmutableSet since the field is a Set.
PiperOrigin-RevId: 353021268
This ensures the message devilery is governed by the clock.
Also replace setting a Handler with a Looper to facilititate this
change.
PiperOrigin-RevId: 353019729
Codecs are not used by this test because PCM uses codec bypass,
but performing the setup is still necessary to have the test
verify that this is indeed the case!
PiperOrigin-RevId: 352965739
The output dumps are intentionally empty because the playback
is using bypass modes.
Still adding a AUDIO_RAW decoder to the ShadowMediaCodecConfig to
ensure that we would output samples if bypass mode were disabled.
PiperOrigin-RevId: 352794959
Also move it to the `drm` package, and extract a
`DrmSessionManagerProvider` interface.
I'll add `MediaSourceFactory.setDrmSessionProvider()` in a follow-up
change.
Issue: #8466
PiperOrigin-RevId: 352582559
This prevents trying to post the response to possibly dead threads,
which causes an IllegalStateException to be logged.
Issue: #8328
PiperOrigin-RevId: 352388155
- Once the ability to add debug listeners is removed, analyticsCollector
is the only component that needs to receive the events. Hence it is
called directly.
- It seemed less confusing to do the same thing for (non-debug) video and
audio events, and to have AnalyticsCollector no longer implement
VideoListener and AudioListener directly. This clears up confusion that
arises as a result of the debug and non-debug interfaces defining the
same methods in some cases, and having to be careful not to end up
calling the corresponding AnalyticsCollector method twice.
PiperOrigin-RevId: 351835491
AnalyticsCollector is allowed to be subclassed to simplify adding
new events that make use of the EventTime generation.
Clean up the subclassing interface to simplify this:
- Make generateCurrentPlayerMediaPeriodEventTime protected. This is
arguably the most useful method for extended clients. Other
generateXXXEventTime methods are left private as they can't be
useful for extensions because they require some integration into
the ExoPlayer playback thread to make sense. So keeping them
private to cause less confusion.
- Some existing callback handling should be final as all the others.
- Adding @CallSuper to all lifecycle management methods that might
be helpful to subclasses but require to call the super method.
- Make sendEvent protected to let subclasses use the simple
event sending method.
PiperOrigin-RevId: 351766369
The VideoDecoderOutputBufferRenderer will be set
automatically when setVideoSurfaceView is called on a
VideoDecoderGLSurfaceView.
#player-to-common
PiperOrigin-RevId: 351742601
The cache, being static, is updated every time a new MimeType is encountered.
The static cache needs to be cleared between tests that register codecs through
ShadowMediaCodec, or the subsequent tests could possibly pick up a wrong codec.
PiperOrigin-RevId: 351576018
A previous release note has already noted to use ProgressiveMediaSource
instead of this whole class, so adding a specific release note seems
unnecessary for this one.
PiperOrigin-RevId: 351353979
- SimpleExoPlayer now always generates a session ID at
construction time. This ID is used indefinitely, including
for tunneling, unless a call to setAudioSessionId is made
to change it.
- DefaultTrackSelector support for enabling tunneling has
been changed to a boolean, since tunneling now uses the
same session ID as non-tunneled mode.
- Since the session ID is now always set at the top level,
internal propagation of generated session IDs is no longer
necessary, and so is removed.
PiperOrigin-RevId: 351349687
The ExoPlaybackException types are locations from where the exception
is coming from and not the type of exception itself, which should be
denoted by different exception classes.
To avoid a mixture of error types and class checks, the timeout
exceptions should use their own class and be of type RENDERER as this
is where the timeout actually happens.
PiperOrigin-RevId: 351337699
This allows the respective components to adapt to the speed changes
if desired.
To avoid frequent updates to the media codec operating rate, we also
forward the target speed to the renderers so that this value can be set
based on the target speed and not the current speed.
PiperOrigin-RevId: 351336401
Catching OOM errors is bad practise unless there is a specific known
cause that tried to allocate a large amount of memory. Without this
known cause with a large allocation, the source of the error is
likely somewhere else in the app and every random small further
allocation may lead to additional OOM errors (for example b/145134199).
We have three known causes in ExoPlayer:
1. Source allocations based on unexpected values in streams. This is
caught on the loader thread and reported as an
UnexpectedLoaderException.
2. Output buffer allocations by non-MediaCodec decoders. These are
caught in SimpleDecoder on the decoder thread and reported as
UnexpectedDecodeException.
3. Input buffer allocations by non-MediaCodc decoders in their
constructors. These are currently caught on a higher-level and
reported as ExoPlaybackException.TYPE_OUT_OF_MEMORY.
For consistency and to prevent catching OOM errors without known cause
we can remove the generic TYPE_OUT_OF_MEMORY and catch the specific
exception where it occurs to report it as an
ExoPlaybackException.TYPE_RENDERER. This also has the added advantage
that the format metadata is added to the exception.
PiperOrigin-RevId: 351326688
Whether a resource resolves to a known length or not is more than just
a property of the resource & data source - for example if
`DataSpec.flags` contains `ALLOW_GZIP` then the length might be
unresolved. More generally, a `DataSource` could randomly return
`C.UNKNOWN_LENGTH` from `open()` 50% of the time and still fulfil the
`DataSource` interface. This makes it ~impossible to write a meaningful
assertion aroun this.
So this change relaxes the assertion slightly to more closely match the
definition of the `DataSource` interface.
We leave the `resolveToUnknownLength` toggle in
`WebServerDispatcher.Resource` because this is still useful for
simulating the case of a server that is serving a file it doesn't
know the length of.
PiperOrigin-RevId: 351124246
This is a partial revert of
46598a46fd
The change from reset(int) to setPosition/Limit() in this file was
incorrect, the reset(int) call is important because it ensures
`bitmapData` is large enough for the `buffer.readBytes` call on L188.
Issue: #8417
PiperOrigin-RevId: 351110038
- 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
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
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.
*** 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
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
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
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
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
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
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
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
- 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
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
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
*** 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
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
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
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
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
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
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
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
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
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
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 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
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
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
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
*** 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
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
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
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
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
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
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
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
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
- 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
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
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
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
*** 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
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
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
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
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
- 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
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