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