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
This will replace the need to use CacheUtil.getCached, and is part of refactoring
CacheUtil to only do writing (it will be renamed to CacheWriter in a subsequent
change).
PiperOrigin-RevId: 312366040
- Remove scratchStyleMatches output parameter from WebvttCueParser.
- Switch from String[] to Set<String> for representing classes.
- In-line WebvttCssStyle.reset() since it's not used anywhere else.
PiperOrigin-RevId: 312249552
Added monitoring storage levels in RequirementsWatcher
Added dependency on extension-workmanager to the demo app to be able to test with WorkManagerScheduler
Added getSupportedRequirements method to Scheduler interface
Implemented getSupportedRequirements for schedulers
- The remove(DataSpec) method was confusing because it ignored
the DataSpec position and range, and instead removed all data
with a matching cache key.
- The remove(String) method seems better put directly on the
Cache interface.
PiperOrigin-RevId: 312113302
This is part of go/exoplayer-playlist-retrieval which aims for all MediaSources to associate the media item to the corresponding window. Media items need to be added to the timeline which then assigns it to the window.mediaItem attribute.
PiperOrigin-RevId: 312065023
The new behaviour:
- If the session is successfully opened, an acquire event is dispatched
to all attached dispatchers.
- If acquire() is called but the session is already open, the acquire
event is dispatched only to the dispatcher provided in to acquire()
- If the session is successfully released, a release event is dispatched
to all attached dispatchers (in theory at most one should ever be
attached at this point).
- If release() is called but the session isn't released (because
referenceCount > 0) then a release event is dispatched only to the
dispatcher provided to release().
PiperOrigin-RevId: 312062422
Switch to snapshot Robolectric to pick up the latest version of shadows
required by MediaCodecVideoRendererTest and MediaCodecAudioRendererTest.
PiperOrigin-RevId: 312030332
Detect stuck buffering cases in ImaAdsLoader, and discard the ad group after
a timeout. This is intended to make the IMA extension more robust in the case
where an ad group unexpectedly doesn't load.
The timing out behavior is enabled by default but apps can choose to retain
the old behavior by setting an unset timeout on ImaAdsLoader.Builder.
PiperOrigin-RevId: 311729798
EventTime contains information about when an event happened and where
it belongs to. Both places can be fully described using timeline, window
index, media period id and position.
Right now, only the information for where the event belongs to is fully
contained in EventTime, whereas the time when the event happened only has
the position, and none of the other information (timeline, window, period).
This change adds the missing information, so that the EventTime can easily
be used without having access to the Player. This also ensures Event
metadata is self-contained and can be stored and reused later.
issue:#7332
PiperOrigin-RevId: 311727004
ANSI/CTA-608-E R-2014 spec defines exactly 32 columns on the screen,
and limits all lines to this length.
See 3.2.2 definition of 'Column'.
issue:#7341
PiperOrigin-RevId: 311549881
Some player setup steps that are likely to be only done once
should be moved into the Builder so that player setup can use
a consistent style (builder vs setters).
This also prevents some threading warning issues when the player
is built on a background thread (e.g. for dependency injection
frameworks) and setters can't be used due to threading restrictions.
PiperOrigin-RevId: 311487224
This is useful for merging the FFmpeg video support pull request,
since it allows a Decoder base class implementation to catch
DecoderException rather than forcing it to catch Exception (i.e.,
everything). Note that unfortunately, Java doesn't allow catching
of a generic type (i.e., you cannot "catch (E e)") due to type
erasure.
PiperOrigin-RevId: 311300719
The only reason to require a context for creating an instance of
DefaultMediaSourceFactory is creating a user agent. DownloadHelper
has a bunch of static methods that need to instantiate a
DefaultMediaSourceFactory without a Context. By adding a setter for
the user agent we can remove that restriction and use a default user
agent.
PiperOrigin-RevId: 311291603
We aim for all SinglePeriodTimelines to set window.mediaItem and hence want to eliminate all constructors not passing a media item. The constructor removed in this CL is the easiest one to remove and fix in google3. It is still a breaking change for external ExoPlayer user who provide a custom media source with this timeline.
PiperOrigin-RevId: 311291493
It's very unlikely any onQueueInputBuffer implementations are looking
at the subsample encryption data, but from a correctness perspective
we should be passing a buffer object that's self-consistent.
PiperOrigin-RevId: 311011246
FFmpeg requires input buffers to be sized larger than the size
of the data they contain. This is to allow optimized decoder
implementations that read data in fixed size chunks, without
the risk of such decoders reading beyond the end of the buffer.
Issue: #2159
PiperOrigin-RevId: 310946866
We currently use the playback position in the current window, not the
position in the window the event belongs to. This creates confusing
outputs, e.g, window=1, mediaPos=100, even if the position refers to
window 0.
issue:#7332
PiperOrigin-RevId: 310896908
The tts:textAlign property only applies to <p> elements, which
correspond 1:1 with ExoPlayer Cue objects, so we can use
Cue.textAlignment to store this info instead of encoding it in
the span-styled text.
This will mean that TTML subtitles used with
SubtitleView#setApplyEmbeddedStyles(false) will start respecting
the tts:textAlign properties from the source data (currently this
information is stripped when we remove all span styling). I think this
is working-as-intended, we respect alignment of other subtitle types
(e.g. WebVTT) when applyEmbeddedStyles=false. We also respect all other
'positioning' related properties in this case e.g. Cue.position and
Cue.line.
PiperOrigin-RevId: 310895499
*** Original commit ***
Rollback of 70273a0361
*** Original commit ***
Assert incoming buffers are little endian in the DefaultAudioSink.
***
***
PiperOrigin-RevId: 310889382
When operating the MediaCodec in asynchronous mode, we are seeing
NPEs raised from the DefaultAudioSink because output buffers are pushed
to the DefaultAudioSink with the DefaultAudioSink not configured yet.
This is possible to happen if an output buffer is passed with
MediaCodecAudioRenderer.processOutputBuffer() before an output format
change.
One possible code path to trigger this is when an output format change
is pending and we flush MediaCodec (e.g. for a seek): the callback is
waiting in the looper's queue but we ignore all currently queued
callbacks after a flush().
This commit checks for a pending output format change during a flush():
if one exists, and the next MediaCodec output callback right after the
flush() is an output buffer (and not a new output format), then the
pending output format is propagated first.
The only adapter that needs to change is the
AsynchronousMediaCodecAdapter which previsouly deleted all pending
callbacks immediately on flush(). The AsynchronousMediaCodecAdapter now
needs to also handle every enqueued callback in order to identify is
there's a pending output format change.
Testing: added unit tests for the new code. I have verified that if we
pass an output buffer to the audio renderer before the output format, it
will result on the specific NPE, but I cannot reproduce the base
scenario (an output format change is pending when flushing) on a real
device because we can't know if an output format is indeed pending.
PiperOrigin-RevId: 310885283
We currently propagate only ColorInfo, but propagating the whole Format
is generally useful (e.g., to get the frame-rate on the output side of
the decoder).
PiperOrigin-RevId: 310359650
This allows properties to propagate when switching view types
(e.g. bottomPaddingFraction).
It also allows the style-stripping code to be pushed up to SubtitleView
and therefore shared.
PiperOrigin-RevId: 310353534
Fixes AsynchronousMediaCodecBufferEnqueuerTest broken tests by
enqueueing input buffers that have previously been dequeued from the
MediaCodec.
The test assumes that the shadow MediaCodec implementation can dequeue
at least 10 input buffers before queueing them back. Although fragile,
it seems to work with the current robolectric shadow MediaCodec. This is
at the moment preferred compared to making the test more complicated.
PiperOrigin-RevId: 310325096
Some part of the audio pipeline in the DefaultAudioSink
(PCM processors) are expecting little endian buffers.
As a result, in order to behave like MediaCodec,
make sure the passthrough MediaCodec-bypass pipeline
also processes little endian output buffers.
PiperOrigin-RevId: 310172464
Previously the input format values were used,
but it could be incorrect if two format change were
occurring in quick successions.
PiperOrigin-RevId: 310142675
These methods operate on a thread-safe collection and are thus
inherently thread-safe. This simplifies some player setup configurations
where initial listeners are added on a background thread (e.g. when
using a dependency injection framework).
PiperOrigin-RevId: 310113181
Users of addTextOutput should instead query the current cues if they
need them. This is more consistent with how other listeners are handled.
PiperOrigin-RevId: 310112241
We currently have DecoderVideoRenderer and VideoDecoderRenderer, which
is very confusing! This one is package private, so we can rename it to
remove some of the confusion.
Also fix some nullness issues.
PiperOrigin-RevId: 309964088
In passthrough MediaCodec is not used except if
the format has a DRM.
Nevertheless the code was still requiring that a
passthrough decoder be present even if it was not going to be
used (aka no drm).
PiperOrigin-RevId: 309947271
- Fix DecoderAudioRenderer to re-init codec if the DRM session changes.
- Add canKeepCodec to DecoderVideoRenderer. Previously it was assumed
that the decoder could be re-used, but this will not be true in all
cases for FfmpegVideoRenderer.
Issue: #7079
PiperOrigin-RevId: 309935278
If the condition isn't fulfilled, they currently block until the
test runner times out the test. Our usual approach is to timeout
in the test itself so that the error message is clearly showing the
blocked condition.
Also clean-up some documentation.
PiperOrigin-RevId: 309930198
Now that MediaCodec is not use in passthrough, no
MediaCodec should be created in this mode.
Additionally, do not instantiate a MediaCodec in passthrough
#exo-offload
PiperOrigin-RevId: 309916131
DownloadManager doesn't know enough about the Downloader implementations to
know that interrupting the thread is the right thing to do. In particular,
if a Downloader implementation wants to delegate work to additional worker
threads, then it will probably not want its main thread to be interrupted
on cancelation. Instead, it will want to cancel/interrupt its worker threads,
and keep its main thread blocked until work on those worker threads has
stopped (download() must not return whilst the Downloader is still touching
the cache).
This change moves control over what happens to the individual Downloader
implementations.
Issue: #5978
PiperOrigin-RevId: 309419177
- Stop throwing InterruptedException from CacheUtil. When a CacheUtil operation
throws or returns, the caller should always check its own state to determine
whether they canceled the operation. If a caller is trying to catch
InterruptedException separately to IOException to do something different in
that case, they're probably doing the wrong thing. So it's simpler, and probably
less error prone, just to throw an IOException in the case of interruption.
- Throwing InterruptedIOException is also consistent with what our Extractor and
DataSource implementations do.
Issue: #5978
PiperOrigin-RevId: 309411556
We keep an index hint for the next pending player message. This hint
wasn't updated correctly when messages are removed due to a timeline
update.
This change makes sure to only use the hint locally in one method so
that it doesn't need to be updated anywhere else and also adds the "hint"
suffix to the variable name to make it clearer that it's just a hint and
there are no guarantees this index actually exists anymore.
issue:#7278
PiperOrigin-RevId: 309217614
testSubtitleEventTimes/IndicesHelper make assertions that only happen
to be the same because values in two different constants match up. It
seems much better to explicitly put the assertions in each test.
The other assert methods are just obscuring the underlying call to
Truth.
PiperOrigin-RevId: 309022044
Steps 4-10 of https://www.w3.org/TR/webvtt1/#cue-computed-line
This part is harder to fit into our code structure because it depends on
how many cues are simultaneously visible - so it has to go in
WebvttSubtitle not WebvttCueParser (which only deals with individual
cues in isolation).
This removes the `isNormal()` method that was trying to approximate
the correct behaviour.
PiperOrigin-RevId: 309021686
adPlaybackState is now non-null, and the uninitialized case is covered by a new
boolean hasAdPlaybackState. Position progress updates are now non-null and
initialized with IMA's VIDEO_TIME_NOT_READY constant.
Also fix some misc code issues:
- Remove empty branch for SmoothStreaming (Android Studio warns about this).
- Tidy onTimelineChanged and onPositionDiscontinuity and the methods they call
to improve naming.
- Remove logging for IMA events after release, as these methods are expected to
be called in the current IMA SDK behavior.
PiperOrigin-RevId: 308977116
The player's initial PlaylistTimeline has no ad cue points, so its first
MediaPeriodId has no nextAdGroupIndex. When the AdsMediaSource provides its
first timeline, the cue points become known. For the case where a preroll cue
point appeared, the preroll was detected due to isAd changing on the
MediaPeriodId. For the case where a midroll/postroll cue point appeared, the
MediaPeriodId was actually treated as the same, which leads to keeping the
unclipped original MediaPeriod.
Fix this behavior by checking for nextAdGroupIndex becoming set or decreasing.
PiperOrigin-RevId: 308974490
Its only real purpose is to encapsulate a download ID, but it doesn't actually save
any code, and arguably makes it more complicated by having multiple lists of
Downloader instances, indexed by key, and also because it's another (undocumented)
class to understand.
This CL retains the multiple Downloader lists, but they will be flattened in a
child CL.
PiperOrigin-RevId: 308838026
This is equivalent to the method ExoPlayer provides. It's nice for consistency,
and for retrieving the looper from test code.
PiperOrigin-RevId: 308830288
DownloadRunner.getDownloader was creating Downloader instances before the actual
DownloadManager under test would have created them. Tests were then asserting and
manipulating these Downloader instances, which is quite confusing. In particular
FakeDownloader.assertDoesNotStart() is an assertion on a Downloader instance that
only makes sense when called on an instance that DownloadManager would not have
created by itself.
This change replaces FakeDownloader.assertDoesNotStart() with an assertion on
DownloadRunner that no Downloader instance has been created.
PiperOrigin-RevId: 308822398
- Assertion chaining is generally discouraged. For example, because it's harder
to determine which assertion failed given a line number.
- Also removed chaining of the form obj.actionX().assertY(), because it's easy
for someone editing the test to accidentally delete actionX() when deleting
assertY(), where-as actionX() may often be important for subsequent assertions.
PiperOrigin-RevId: 308820503
- Remove assertReleased and replace it with a proper condition variable
that's opened when Downloader.download or Download.remove finish. As
far as I can tell assertReleased was basically implementing "sleep for
10 seconds after the Downloader starts". Note fixing this properly
also makes the tests run much faster!
- Use ConditionVariable instead of CountDownLatch(1).
- Use AtomicInteger instead of volatile int because it's clearer and
allows removal of explanatory comments.
PiperOrigin-RevId: 308819204
- Improve documentation explaining the benefits of ExoPlayer's ConditionVariable
over the one that the platform provides
- Allow Clock injection
- Create TestUtil method for obtaining a ConditionVariable whose block(long)
method times out correctly when used in a Robolectric test
- Add basic unit tests for ConditionVariable
PiperOrigin-RevId: 308812698
A previous change added these getters to CacheDataSource, but it can
also be useful to retrieve these components directly from the factory.
This is useful for tasks where we're going to need to build multiple
CacheDataSource instances (e.g., to make requests in parallel), and
also need to operate directly on the same components. It's a bit more
natural to retrieve them from the factory than from an arbitrary
CacheDataSource in this case, since it can avoid unnatural code where
you create a CacheDataSource instance earlier than you would otherwise
just to use its getters, and/or create one just to use its getters and
then throw it away.
PiperOrigin-RevId: 308606020
- Executor is a superclass of ExecutorService, so this is arguably a little
more flexible.
- It removes the need to use null for direct execution, because Runnable::run
is a direct executor that can be trivially used instead.
- Removing the error-prone "cannot be a direct executor" restriction in the
parallel version of SegmentDownloader requires not relying on the futures
returned from ExecutorService.submit() anyway.
Issue: #5978
PiperOrigin-RevId: 308586620
Currently, this method is only supposed to be called before removing
the listener from the player or when releasing the player.
If called at other times, it will throw an exception later when
a playback session is ended automatically.
issue:#7193
PiperOrigin-RevId: 308254993
The method is used to finish a brief "seeking" state that can be removed entirely
now state changes for seeking are masked.
PiperOrigin-RevId: 308237009
Unmarshal from json to MediaItem instead of Sample. Further the playlist
of MediaItems is converted to Intent extras which are read by the
PlayerActivity.
PiperOrigin-RevId: 308141231
While most ExoPlayer code parsing ByteBuffers is called with buffers in big
endian, in certain situation, buffers in little endian are used too.
MediaCodec produced ByteBuffers are in little endian, while buffers
receive from the sources are in big endian (ByteBuffer's default).
As a result, some code called from AudioSink in passthrough parsed
bytebuffer in little endian. This is not correct because those
format are specified in BigEndian.
Changing the endianness of the ByteBuffer returned from MediaCodec
would impact a lot more code that can currently be tested in the
current COVID lockdown situation.
As a result, this patch instead make the parsing code independent
of the ByteBuffer.order() set. All the code that is called from
DefaultAudioSink now parses the buffer explicitly in Big Endian.
Additionally, the MPEG big endian header data of size 4 bytes was
retrieved with ByteBuffer.get, which only returns one byte.
PiperOrigin-RevId: 308116173
The first session should only be created once we have the media items
and/or called prepare. Otherwise the first session is created with
an EventTime having an empty timeline making it less useful.
issue:#7193
PiperOrigin-RevId: 308100555
Something that helps a constructor always seemed a bit strange.
It's now possible to use CacheDataSource.Factory directly instead.
PiperOrigin-RevId: 307661930
In the same way it made sense to tie CacheKeyFactory and CacheDataSource
together in
7ea83d7167,
it makes sense to tie the PriorityTaskManager to the CacheDataSource as
well. This prevents error prone scenarios where one can end up being
passed around without (or with the wrong instance of) the other.
This change also internalizes use of PriorityDataSource directly into
CacheDataSource, rather than requiring the caller to chain things
themselves.
PiperOrigin-RevId: 307647290
Audio processors are now flushed twice after reconfiguration.
The second flush call cleared the pending trim start bytes so
transitions between tracks were no longer gapless.
Fix this by removing logic to clear pending trim bytes on flush.
As a result we may trim data incorrectly if there is a flush
before any data has been handled for seeking to a non-zero
position, but this edge case will happen rarely and the effect
shouldn't be noticeable.
PiperOrigin-RevId: 307344357
This is the missing attribute to support all features of the Sample with MediaItem. Hence PlayerActivity can use the setMediaItems() method directly without creating actual media sources in the app code.
PiperOrigin-RevId: 307102036
This makes it easier to use the helper methods because the player doesn't
have to be assigned to a SimpleExoPlayer in all cases.
PiperOrigin-RevId: 307039126
Update the comment on a suppression of Field.get(null) which is safe
but blocked by the checker.
These suppressions were introduced in d1e0572448
PiperOrigin-RevId: 307036441
We currently check for shouldContinueLoading, which is the intention to load,
not playbackInfo.isLoading, which is the actual loading state, when detecting
stuck buffering issues.
They only differ if the LoadControl said stop loading (based on nextLoadPosition),
but there is still a load in flight (updating bufferedPosition). This may cause
the exception to be thrown in edge cases that are only temporary.
PiperOrigin-RevId: 307022608
This is required to migrate the PlayerActivity away from Sample to MediaItem. It hence needs adding buildUpon to MediaItem to mix in the customCacheKey and streamKeys before playback.
PiperOrigin-RevId: 306710643
Even though they are annotated as non-null, Java users can pass in null values.
So we should verify the input to fail fast.
PiperOrigin-RevId: 306425487
This is the first CL for the offline qoe reporting
feature. Refer to the design doc for full information.
Design doc: go/exoplayer-offline-qoe
PiperOrigin-RevId: 305459231
Create a Builder that creates SimpleExoPlayer instances with fake
components, suitable for testing.
Basically extracts the Builder from ExoPlayerTestRunner to a standalone
class that can be re-used.
PiperOrigin-RevId: 305458419
This CL is a renaming only. It's mostly about finding a decent naming for the internal Playlist class. The plan is to have a public Playlist class in the converged Player API, so we need to rename the internal one.
PiperOrigin-RevId: 305266196
If we're in the ducked state and updateAudioFocus is called with a
new state for which focus is no longer required, we should restore
the player back to full volume.
Issue: #7182
PiperOrigin-RevId: 305232155
These were introduced in c7164a30a0
In each case I checked that the groups are not optional,
so if they match they must be non-null.
PiperOrigin-RevId: 305213293
This avoids cases where audio focus is never successfully acquired
because another app is holding on to transient audio focus indefinitely.
Issue: #7182
PiperOrigin-RevId: 305108528
When ClippingMediaPeriod first tried to read a buffer, if its end
position was before the end of the stream and it was buffered to its end
position, it would sometimes erroneously signal end-of-stream for
protected content because the sample queue might be waiting for DRM keys
at this point.
Work around the issue temporarily by signaling this specific case back
to ClippingMediaPeriod via the DecoderInputBuffer.
There will likely be a cleaner fix as a result of adding support for
dynamic clip end points in the future, at which point this can be
reverted.
issue:#7188
PiperOrigin-RevId: 305081757
It's interesting WebVTT explicitly handles line & position differently
in horizontal-rl/lr and vertical-lr/rl contexts. position is always
measured from the left of the viewport, even for rtl text, but line in
vertical-rl is measured from the right of the viewport.
We don't have to make Cue match WebVTT (I can go change the WebVTT
decoding instead) but it seems a reasonable 'default' to follow.
PiperOrigin-RevId: 304353900
Selection of a passthrough codec will rarely (if ever) need to be customized, so
remove this capability from MediaCodecInfo.
Applications can still customize whether passthrough is used by overriding
MediaCodecAudioRenderer.usePassthrough, which now also checks for a passthrough
codec.
#exo-offload
PiperOrigin-RevId: 303964682
This is used to generate the initialization vector for encrypting the
cache contents.
Startblock:
<unknown commit> is submitted
and then
3w have passed
PiperOrigin-RevId: 303932151
This avoids massive changes to method signatures to add throws. Also, took suggestion to make it an `IllegalStateException`.
Move the catch outside of the finally that sets `nextLoadPosition` (this allows for possible recovery by reseting the `Extractor` and `TimestampAdjuster`).
Lastly, took the suggestion to make a minimum value for the tolerance (especially usefull for very short i-Frame only segments).
This is required to align google3's stub (currently marked non-null) with Checker Framework's.
More information: go/matcher-nullness-lsc
Tested:
TAP train for global presubmit queue
http://test/OCL:303344687:BASE:303326748:1585344475427:29edc250
PiperOrigin-RevId: 303709053
- They are always listed with their canonical names
- Considering aliases means that blacklisting a decoder can end up
not actually blacklisting it, since it may still be accessible
via an alias. It also means that our decoder fallback logic can
end up falling back to a decoder that we've already tried!
PiperOrigin-RevId: 303348297
This callback will be deprecated, so moving all usages to better callbacks.
Some usages are still remaining that are less straight-forward to update.
PiperOrigin-RevId: 303298834
OnSeekProcessed is documented to be called as soon as all neccessary state changes
as a result of the seek have been made. As we now mask the state changes directly
when calling seekTo, we can also call this callback immediately without changing
the semantics of the method.
Our tests often use this callback as a way to wait for the internal player
to receive all pending commands and then report back. This is a special test
requirement for cases where we want to make sure no further updates happen as
a result of the player handling commands. To facilitate that, a new action is
added with a more descriptive name that achieves the same goal.
PiperOrigin-RevId: 303296210
This moves the playlist API methods to the Player interface. Implementation is moved from ExoPlayerImpl to BasePlayer where possible.
Further the CastPlayer is changed to implement the Player interface. Proper migration of the Playermanager to not use the ConcatenatingMediaSource anymore follows in a separate, future CL.
PiperOrigin-RevId: 302937779
Most of these are no longer needed since aa9eb5abc9
Cleanup change automatically generated by error-prone refactoring
//java/com/google/devtools/staticanalysis/errorprone:UnnecessaryJavacSuppressWarnings_refactoring on targets third_party/java_src/android_libs/exoplayer/v2/... java/com/google/android/libraries/exoplayer/v2/...
PiperOrigin-RevId: 302916092
This is less confusing than having audio processing functionality (e.g., playback
speed adjustment) just "not work" for some pieces of media.
If this change is merged, I will update #6749 to also track making DefaultAudioSink
intelligently enable/disable float output depending on how the audio processors are
configured.
Issue: #7134
PiperOrigin-RevId: 302871568
We currently have multiple places in ExoPlayerImpl that assign PlaybackInfo
instances and then inform listeners of all current changes. This is not ideal
because it causes multiple issues:
1. Some changes may easily be forgotten, e.g. there are clearly some checks
missing to see if isPlaying changed (e.g. in seekTo or setMediaSources)
2. Some callbacks didn't check if the value actually changed before sending
the callback (e.g. for the timeline change in setMediaSources - if the
timeline is still the same, we shouldn't send a onTimelineChanged event).
3. Having multiple callbacks in a single Runnable changes the order of
listener invocations slightly: Currently all events for one listener will
be send first before moving to the next listener. It should however send
a single event to all listeners first before moving to the next event.
All these issues can be solved by always using updatePlaybackInfo and never
assigning playbackInfo directly in another place.
Some tests needed to be updated as well because of issues (2) and (3). Also
added a new test to cover issue (1).
PiperOrigin-RevId: 302844981
It's incorrect to use an AudioFormat returned from AudioProcessor.configure
unless the AudioProcessor is active.
Issue: #7134
PiperOrigin-RevId: 302674132
This is a no-op for DefaultAudioSink for now, because DefaultAudioSink
currently disables processing anyway if the input uses ENCODING_PCM_FLOAT.
Issue: #7134
PiperOrigin-RevId: 302670534
androidTest of core already has the dependency on its main. Without this
exclude, gradle complains about type duplication when merging dex saying
"Type X is defined multiple times".
PiperOrigin-RevId: 302641585
- Show renderers with no tracks in EventLogger track logging
- Log renderer names in EventLogger track logging
- Add useful message to ExoPlaybackException instances (including
renderer name for renderer errors)
PiperOrigin-RevId: 302421616
If MaskingMediaSource masks a multi-window media source, it may be that a period
is removed while we are using an initial unprepared masking MediaPeriod. That
means it's not guaranteed that a timeline update still contains our
unpreparedMaskingMediaPeriod and we should ignore timeline updates where the
period is no longer present because the it will be removed anyway.
PiperOrigin-RevId: 302383787
- This change also adds support for VideoFrameMetadataListener in the
AV1 renderer
- This is a preliminary step prior to adding FfmpegVideoDecoder
Issue: #2159
PiperOrigin-RevId: 301702460
This is a necessary step for Decoder implementations to support
audio and video. MediaCodecRenderer.DecoderException is renamed
MediaCodecDecoderException and extends the new DecoderException
Issue: #2159
PiperOrigin-RevId: 301698238
We have two known scenarios where the app could create an OOM error and
we want to handle it gracefully:
1. The app continues to allocate memory but doesn't make any progress
in the buffered position. OOM should be prevented by the default
load control and it should eventually throw an exception.
2. An extractor tries to allocate a large amount of memory on the
Loader thread based on information it read in faulty media files.
In this case we should attempt to play remaining media and then
throw an exception.
Both cases are already handled correctly, but we don't have any tests
ensuring that we don't introduce regressions.
PiperOrigin-RevId: 301585700
This removes a workaround that always continues buffering and instead
detects if the LoadControl returns false even though we don't have
any buffer. If enabled by a flag, this condition throws an exception.
PiperOrigin-RevId: 301584239
The restriction that these classes only work with SimpleDecoders
is unnecessary. An FfmpegVideoRenderer will not be able to use a
SimpleDecoder, because the SimpleDecoder assumption that each input
buffer can be decoded immediately into a corresponding output is
not true for all video codecs that Ffmpeg supports (e.g., H264 does
not have this property). Generalizing SimpleDecoderVideoRenderer to
DecoderVideoRenderer will allow FfmpegVideoRenderer to still use
the base class, without having to use a SimpleDecoder.
This is a preliminary change toward being able to merge a version
of https://github.com/google/ExoPlayer/pull/7079.
Issue: #2159
PiperOrigin-RevId: 301412344
The test is flkay (2/1000 runs) because the decoder initialization
before and after the seek are not perfectly deterministic. I couldn't
find a way to make them deterministic, so slightly chaning the test
setup instead. The test setup change doesn't affect the scenario being
tested.
PiperOrigin-RevId: 301390491
When no tracks are selected (or only tracks of unknown type), the
target buffer size is calculated to be 0. This means the player
won't request to buffer more data, nor can it start playback and
will be stuck forever.
PiperOrigin-RevId: 301374229
The assertion about the expected formats doesn't really belong in a
fake, the assertions should be closer to the test method.
This gets in the way when I try and write a new test in
AnalyticsCollectorTest that doesn't use the expected, constant Format
(because i want to specify drmInitData) - but changing the expected
Format is tricky because it's hard-coded into the FakeVideoRenderer
inner class.
I replaced the assertion in FakeRenderer with assertions in test
methods that used to assert on the format count.
PiperOrigin-RevId: 301353072
Previously calling removeListener would remove all instances of that
listener. Now it only removes a single instance.
This probably should have been part of introducing the Multiset:
2bd4d61b9b
PiperOrigin-RevId: 301191940
Without this change there's confusing behaviour if you pass e.g.
AnalyticsCollector (which implements both DrmSessionEventListener and
MediaSourceEventListener) to MediaSource.addEventListener: It will
receive DRM events too, even though you never passed it to
MediaSource.addDrmEventListener.
Also add some tests for MediaSourceEventDispatcher.
PiperOrigin-RevId: 301169915
This prevents OOM errors for high bitrate streams that attempt to fill
the buffer regardless of the memory usage.
Also change the max buffer sizes to ensure this is a no-op for video
streams < 20Mbps and audio streams < 260kbps.
Issue:#6647
Issue:#7006
PiperOrigin-RevId: 300720299
After this change users of ExoPlayerImpl and SimpleExoPlayer can use the media item base playlist API which converts the media item to a media source.
It adds the media item based methods to the ExoPlayer instead of the Player interface. This avoids a big change in the CastPlayer which requires migrating the cast extension to the MediaItem of the core module (follow up CLs).
PiperOrigin-RevId: 300575567
This avoids duplicate events being dispatched to object foo if
addListener(foo) is called more than once.
Part of issue:#6765
PiperOrigin-RevId: 300529733
We currently have the following logic to update renderers during
period transitions:
1. Wait for the currently reading period to finish reading all its
streams.
a. Advance reading period.
b. Set all streams that can't be replaced to final.
c. If streams can be replaced, replace them now.
2. Wait until playback position reaches the transition point
a. Disable all unneeded renderers (or those that need
re-enabling).
b. Advance playing period.
c. Enable all new renderers (i.e. all except the ones where
we replaced streams directly in step 1c.
This logic causes delays because steps 2a and 2c can easily happen
before 2b. Doing this allows a smooth transition for cases where
renderers change or where they need to be re-enabled.
The new order after this change is:
1. Wait for currently reading period to finish reading.
a. Advance reading period.
b. Set all streams that can't be replaced to final.
2. Update reading renderers iteratively.
a. If streams can be replaced, replace them asap.
b. If renderes need to be disabled, do so as soon as the
respective renderer ended.
c. Once step b is fully finished, enable or re-enable all new
renderers.
3. Wait unril playback position reaches the transition point AND
all tasks in step 2 are done (i.e. all renderers are set up for the
playing period).
a. Advance playing period.
As a nice side effect, decoder enabled and disabled events are now
always reported for the reading period, which is more consistent with
other renderer callbacks.
PiperOrigin-RevId: 300526983
This list was meant to simplify some usages where we only want to
make operations on enabled renderers. However, keeping this list
up-to-date is slightly error-prone (because renderers aren't added
and removed from this list next to the corresponding enable and disable
calls) and it makes it hard to do more fine-grained changes that only
enable or disabled a single renderer at a time.
PiperOrigin-RevId: 300513788
After this change MediaClocks and ExoPlayerImplInternal don't depend on the deprecated PlaybackParameter anymore but only know about playbackSpeed.
PiperOrigin-RevId: 300428791
This change deprecates the PlaybackParameters and remove the skipSilenceField from the PlaybackParameters. This implies that enabling and disabling skipping silences needs to be done on the Player.AudioComponent after this change.
After submission of the change, all Player API changes are done which are required to bring playbackSpeed and skipSilenceEnabled in the converged Player API state.
PiperOrigin-RevId: 300420843
Update with code review suggestions:
1. rename to HlsCheckedSampleQueue to HlsSampleQueue and combine with format adjusting class.
2. Copywrite in added classes
3. Capture additional items useful for recovery and reporting in the exception class
4. Remove extraneous logging
5. eliminate magic number (50 seconds) and use percentage of duration
WIP:
- eliminate null check for chunk (chunkless prepare starts load before sampleQueue are created)
- work out recovery strategy
Add a SampleQueue subclass that checks the timestamp range of media samples queued to it and reports an exception on load if the timestamp is outside of spec bounds.
(Smashed to a single commit prior to rebase)
*** Original commit ***
Rollback of 949bbcfb2e
*** Original commit ***
Add masking for playWhenReady.
Masking is needed as soon as updates to a value can happen both in EPI
and EPII. PlayWhenReady is currently not masked because all updates
happen in EPI only. As soon as we allow pausing at certain times
(e.g. end of a stream), playWhenReady c...
***
PiperOrigin-RevId: 300330307
*** Original commit ***
Add masking for playWhenReady.
Masking is needed as soon as updates to a value can happen both in EPI
and EPII. PlayWhenReady is currently not masked because all updates
happen in EPI only. As soon as we allow pausing at certain times
(e.g. end of a stream), playWhenReady changes may be triggered by EPII
as well and that's why we need masking.
To know when the value actually changed, we also need to update the
internal state to include whether playback is supppressed.
***
PiperOrigin-RevId: 300303307
Masking is needed as soon as updates to a value can happen both in EPI
and EPII. PlayWhenReady is currently not masked because all updates
happen in EPI only. As soon as we allow pausing at certain times
(e.g. end of a stream), playWhenReady changes may be triggered by EPII
as well and that's why we need masking.
To know when the value actually changed, we also need to update the
internal state to include whether playback is supppressed.
PiperOrigin-RevId: 300284613
Exceeding the period duration may mean that that playback transitions
to another item even if the player is currently paused.
PiperOrigin-RevId: 300133655
There is no need for that, updating them is often forgotten and
takes up too much line space. Replace by a single TAG per test class.
PiperOrigin-RevId: 300113072
This change uses mime types in a functionally equivalent way to how we used the extension hint so far.
Using a mimeType instead of the extension has some advantages. Most importantly mimeTypes are used by the cast SDK with which we want to achieve interoperability in the cast extension.
Using a mimeType instead of the extension hint further appears to be a bit more clear (which might be opinionated). Further mime types are a well known and widely used concept to identify file type on the internet and it provides asterix based generalizations (audio/*, */*) which could express the media type OTHER that ExoPlayer is using internally (no usage of asterix required so far though).
PiperOrigin-RevId: 300058945
handlePrepare/Stop/SetPlayReady can be merged together as they all
handle changes to the desires state of the player.
Also, simplify parts of the control flow by not mixing code that
determines if audio focus needs to be handled with code that actually
acquires or abandons the focus.
PiperOrigin-RevId: 299824857
Without this option it's impossible to merge periods covering
different timestamps (at least not without playback issues).
Issue:issue:#6103
PiperOrigin-RevId: 299817540
The new version fixes some warnings in Gradle builds. Also
add missing indirect compileOnly dependencies to fix some more warnings
Issue:issue:#7007
PiperOrigin-RevId: 298855510
This option marks streams as final such that renderers play them out
completely, then waits until this happened, and then sets the player
to paused. After that, the player can continue to read the next period
to quickly resume playback if needed.
PiperOrigin-RevId: 298824745
Update it to allow any listener class to be registered (and thus
require the caller of dispatch() to provide the type of listener
to call).
Maintain MediaSourceEventListener.EventDispatcher as a sub-class
for now so that all existing references continue to work. This
avoids creating a huge diff in one CL. The intention is to in-line
these incrementally.
This is pre-work for issue:#6765
PiperOrigin-RevId: 298818198
The default Robolectric Looper simulation mode is changing to PAUSED from LEGACY.
The following tests fail in this new mode, and are thus being defaulted to LEGACY.
For more details see go/robolectric-legacy-looper-mode-lsc
Cleanup change automatically generated by error-prone refactoring
//third_party/android/androidx_test/tools/errorprone/java/androidx/test/tools/errorprone:LegacyLooperModeConverter_refactoring
Tested:
TAP train for global presubmit queue
http://test/OCL:297627974:BASE:298600828:1583273401491:7d94dbaa
PiperOrigin-RevId: 298809656
This change adds the createMediaSource(MediaItem mediaItem) method to the MediaSourceFactory interface. It doesn't deprecate createMediaSource(Uri uri) to keep the cl smaller. Deprecation and removing calls to the deprecated method from within the library and extension follow in a separate CL.
PiperOrigin-RevId: 298352442
The test had two problems:
1. It posts messages using a Handler and we need to idle the main looper
to actually deliver this message.
2. SimpleDecoder uses a background thread that is not within our control
from the test. Ensure the decoding happens after we queue input buffers
by using a lock.
PiperOrigin-RevId: 298300175
This is one step toward following the google3's test naming convention.
See go/java-testing/getting_started#basic-test-template for details
why prefix test isn't necessary.
This CL is generated by following command
$ find -name '*Test.java' | xargs -I{} sed -i 's/^\ \ public\ void\ test\([A-Z]\)\(.*\)$/ public void \L\1\E\2/' {}
and then manually modified following tests where test method names conflict with test target.
- VorbisUtilTest
- VorbisReaderTest
- UtilTest
- DownloadManagerDashTest
- DefaultOggSeekerTest
- OggPageHeaderTest
- HlsMasterPlaylistParserTest
PiperOrigin-RevId: 298074653
We should only ignore seek to the current position if we are
currently READY or BUFFERING. Also, pending initial seek positions
should only be saved while we have an empty timeline, independent of
the player state.
Issue:#6886
PiperOrigin-RevId: 297813854
This is more accurate since it's just a placeholder and none of the
values is provided by the media.
It also allows to fix a problem in ClippingMediaSource where we
couldn't detect a clipping error because we didn't know if the
timeline is a placeholder or not.
Issue:#5924
PiperOrigin-RevId: 297813606
When a new Timeline arrives in the Player, we check whether we can keep
existing MediaPeriods. This check currently involves a condition that
checks if the MediaPeriod is already prepared. The only reason we do
that is to avoid calling MediaPeriod.seekToUs, which is not allowed
on an unprepared MediaPeriod.
It's better to keep the MediaPeriod to prevent restarting the
preparation process. The prepration check can move further down to the
place right before we would call seekToUs.
PiperOrigin-RevId: 297812584
AnalyticsCollector keeps a list of existing MediaPeriodInfo that need
to be updated to new Timelines when they arrive. This already
happens in all cases except that the playingMediaPeriod wasn't updated
when it didn't change during the timeline update.
PiperOrigin-RevId: 297812038
The positions were interchangeably used with window and period
positions. This change more clearly ensures that all positions in the
AdPlaybackState are based on periods and that we use the right adjustments
for all usages.
PiperOrigin-RevId: 297811633
Parallel asynchronous calls to MediaCodec.queueSecureInputBuffer() may
produce garbled video on some platforms. This workaround synchronizes
calls to MediaCodec.queueSecureInputBuffer() so that only one call is
in flight.
PiperOrigin-RevId: 297601037
This change adds the callback onSkipSilenceEnabledChange to the AudioListener and calls it when changed by the user by calling setPlaybackParameters, or when changed internally by the DefaultAudioSink if the parameters are not applicable. It needs to be plumped through AudioSink, AudioRenderer to SEP which eventually calls the AudioListener.
No changes to the Player interface so far. The getter of skipSilenceEnabled is added to SimpleExoPlayer for completeness, but not yet to the Player interface. The setter is not yet exposed, but implemented as a private method for implementation reasons.
PiperOrigin-RevId: 297590291
DefaultLoadControl applies the same min buffer duration to audio
and video. By default, min buffer is set equal to max buffer (50 seconds).
PiperOrigin-RevId: 297324489
Note: The dump files will need updating again when the extractors
are modified to only set the appropriate bitrate. Enhancing the
test first is nice, because it means that in subsequent CLs the
dump file updates can be used to quickly see what's changed in
the output.
PiperOrigin-RevId: 297188367
- Avoid having ExtractorHolder expose the underlying extractor.
- Make ProgressiveMP inject a DataSource instead of a DefaultExtractor.
This CL should introduce no functional changes.
PiperOrigin-RevId: 296944788
This change deprecates PlaybackParameter in AudioSink and splits it into playbackSpeed and skipSilenceEnabled. These properties are set separately in a future CL. The playback speed will be set through the MediaClock, while skipSilenceEnabled will be set by sending a message to the audio renderer.
PiperOrigin-RevId: 296457043
- Deprecate old Format.createXXX methods
- Deprecate most Format.copyXXX methods
- Stop using deprecated Format.copyXXX methods in the library
Note: Replacing library usages of Format.createXXX method
will be done in follow up CLs. These changes aren't purely
mechanical because we need to decide which out of peakBitrate
and averageBitrate to set in each case where currently a
single bitrate is provided.
Issue: #2863
PiperOrigin-RevId: 296450935
Not important, but when overriding a method that can return null,
it seems preferable to put @Override first, followed by what it's
overriding (which includes the @Nullable).
Also remove explicit @NonNull use in the core library. @NonNull is
propagated by default, so this is redundant.
PiperOrigin-RevId: 296188379
This is one step toward following the google3's test naming convention.
See go/java-testing/getting_started#basic-test-template for details
why prefix test isn't necessary.
This CL is generated by following command
$ find -name '*Test.java' | xargs -I{} sed -i 's/^\ \ public\ void\ test\([A-Z]\)\(.*\)$/ public void \L\1\E\2/' {}
PiperOrigin-RevId: 296169886
When copying CryptoInfo for asynchronous input buffer queueing,
re-use the destination CryptoInfo's arrays to avoid re-allocating
memory.
PiperOrigin-RevId: 295706771
Note on UnknownNull: Where there exists a generically typed
base class and both null and non-null types are permitted,
we need to clear the default non-null that's otherwise
propagated everywhere. This then lets the nullness of the
type work properly.
PiperOrigin-RevId: 295582444
CryptoInfo.iv length is always 16. When the actual initialization vector
is shorter, zero out the trailing bytes.
Issue: #6982
PiperOrigin-RevId: 295575845
Previously, the input buffer accessUnit count
was passed as the output of the audio processors
which did not make sense as the processors can
split buffers.
This patch passes the access unit count through a
member variable.
PiperOrigin-RevId: 295572577
This is closer to how our actual renderers look like and allows tests
to use a similar logic to show/suppress the first frame in follow-up changes.
PiperOrigin-RevId: 295557548
We will eventually remove the workaround from ExoPlayerImplInternal
added in
b84bde0252
and replace it by an error that gets thrown if the LoadControl behaves
badly.
PiperOrigin-RevId: 295556131
Previously that was implicit, it was the passthrough dance:
- MimeTypes.getEncoding(inputFormat) did not
implement RAW MIME, so it was returning INVALID_ENCODING for PCM
- and allowPassthrough was returning
MimeTypes.getEncoding() != INVALID_ENCODING
- which was setting codecInfo.passthrough, and passthroughEnabled.
Thus Util.isEncodingPcm(encoding) is the opposite of
(MimeTypes.getEncoding(inputFormat) != C.ENCODING_INVALID)
This was rather implicit and brittle as anyone
could add support for audio/RAW in
MimeTypes.getEncoding and break PCM playback.
As a result make it explicit that allowPassthrough
must always return false in PCM.
PiperOrigin-RevId: 295144013
Modify TrackOutput.sampleData() to accept SampleDataReader instead of ExtractorInput. SampleDataReader supports only read and skip calls, which all sampleData() implementations already restrict themselves to.
PiperOrigin-RevId: 294905155
Currently only one access unit can be written per
buffer write. This has been found to be power
inefficient in an offload situation.
#exo-offload
PiperOrigin-RevId: 294886188
This information isn't easily available to the player at the moment (or it
would need to revaluate this every time), so add it to MediaPeriodInfo similar
to the existing isLastInTimelinePeriod.
The player needs to know whether a MediaPeriod is the last in its Timeline
window if we want to add an option to pause at the end of a window.
PiperOrigin-RevId: 294877628
Add fields in DecoderCounters for computing the average video frame
processing offset.
The MediaCodecVideoRenderer reports the video frame processing offset
and the demo app presents it on the debug information.
PiperOrigin-RevId: 294677878
The transition in EPII happens based on the duration of the periods, not
the windows. So use this duration in case they are not the same.
Also make sure to send the message at duration-1 because the playback position
at the duration is technically already the first position in the next item.
PiperOrigin-RevId: 294669335
This simplifies sending messages to the end of a stream. This was
already possible, but users needed to wait until the duration is known
before sending the message. This duration resolution can happen as part of the message position resolution.
PiperOrigin-RevId: 294626984
Issue #6853
Previously the body of an HTTP response was not included in an
InvalidResponseCodeException. This change adds a field to store
the response body, and updates DefaultHttpDataSource to populate
this value.
This is a preliminary step toward adding a DataSpec.Builder,
which is needed for sanity when adding DataSpec.customData.
The existing absoluteStreamPosition field is very error prone,
because anyone using a Builder to adjust the request position
will need to remember to adjust two values:
dataSpec
.buildUpon()
.setAbsoluteStreamPosition(x)
.setPosition(x)
.build();
Furthermore, the difference between position and
absoluteStreamPosition is irrelevant in nearly all cases. In
the core library, the difference is only relevant when initializing
AES encryption/decryption to write/read cache files.
Replacing absoluteStreamPosition with uriPositionOffset will
simplify the code block above to:
dataSpec
.buildUpon()
.setPosition(x)
.build();
PiperOrigin-RevId: 294485644
Currently, the subset of audio tracks for adaptation is selected
purely based on the size of the subset in the track group, completely
ignoring the previously selected best individual track.
This change ignores all tracks with a different configuration than the
previously selected best track.
PiperOrigin-RevId: 294231806
While the window in which a message or a seek position is resolved is
still a placeholder, we need to re-resolve the position using the
user intent (i.e. the window position) when the timeline updates.
PiperOrigin-RevId: 293346360
The period in this method is most likely prepopulated correctly, but
this assumption is very error-prone and we should populate it locally.
PiperOrigin-RevId: 293345873
This allows to simulate samples in a stream more accurately
particularly when streams are prepared at a non-zero position and
issuing a sample with position=0 is not expected.
Also makes seek more realistic by also issuing one sample again.
PiperOrigin-RevId: 293344081
Once we receive an update from a masked source, we first start the
preparation of an already pending period, and only then notify the
player of the new timeline. If the period prepares immediately inline,
the MediaPeriod.onPrepared callback arrives before the
onPlaylistUpdateRequested call in the Player. THis is the wrong order
and causes issues when the player tries to lookup information in the
timeline that doesn't exist yet.
This change fixes preroll playbacks before live streams.
PiperOrigin-RevId: 293340031
This change deprecates Player.onPlayerStateChanged(boolean pwr, int state). It removes deprecation for trivial cases. I'll remove other deprecated usages (mostly in ui module) in follow-up CLs to not bloat this CL.
PiperOrigin-RevId: 292917872
This condition is trying to detect when it might be necessary
to switch from a non-secure to a secure codec. This is not
possible if the DRM session is unchanged, unless a different
codec is required for some other reason (e.g., H264 -> H265),
which is anyway handled by canKeepCodec below.
PiperOrigin-RevId: 292909126
*** Original commit ***
Rollback of 3c56b113e4
*** Original commit ***
Rollback of d48dc4c159
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic...
***
PiperOrigin-RevId: 292457964
This is a nice-regardless improvement to SampleQueue, which will
likely to used to fix the referenced issue. It makes it possible
for SampleQueue subclasses to support dynamic changes to format
adjustment in a non-hacky way.
Issue: #6903
PiperOrigin-RevId: 292314720
We currently have 3 states, but the NOT_SET state isn't needed
anymore. We can therefore replace the IntDef by a simple boolean.
PiperOrigin-RevId: 291926049
We currently apply new parameter checkpoints from an absolute media
time and then substract the current media start time again to retrieve
the media time offset for this playback parameter checkpoint.
However, the media start time may change when unexpected discontinuities
happen (the start time doesn't actually change, but we change it to
correct for this discontinuity). This then invalidates the absolute
media time in the playback parameter checkpoints (which should have been
corrected as well).
Avoid this problem by also only applying the new start position
from the checkpoint. We don't have to save the start position anymore
because it will cancel itself out.
Also add some documentation and code clarification for improved
readability.
PiperOrigin-RevId: 291923069
It doesn't seem worth keeping the cap, since the device
will presumably stop receiving major version updates at
some point anyway.
Issue: #6899
PiperOrigin-RevId: 291899439
We currently only keep the requested next content start position while
we are playing ads. However, we should also keep at least before a content
period is fully prepared to not loose the information about the user intent.
PiperOrigin-RevId: 291705752
There are existing bugs that need this flag to know whether the
current information in the window is still a placeholder or can
already be relied on for further calculation.
This flag will probably only ever be set in DummyTimeline, so it's
not added to the window.set method to avoid updating all clients.
Issue:#5924
PiperOrigin-RevId: 291705637
It could either live in .util or .extractor, but since it's not needed
outside the extractor package in core (and the FLAC extension), and
FlacStreamMetadataTest uses a FLAC asset, it seems preferable to move it
into the extractor package.
PiperOrigin-RevId: 291372032
CeaUtil depends on TrackOutput so should live in the extractors package.
To avoid having Cea708Decoder depend on extractors, this change also
moves the initialization data building/parsing to CodecSpecificDataUtil.
PiperOrigin-RevId: 291348317
Using @Test(expected=...) is discouraged, since the test will pass if
any statement in the test method throws the expected exception.
PiperOrigin-RevId: 291338224
Since we have the Playlist layer on top, it's always guaranteed that a
new playlist item has a new uid. So we can just keep the old one in all
cases and don't have to be careful to delete it. The deletion was necessary
previously in case multiple MediaSources use the same uids.
PiperOrigin-RevId: 291152349
Move Cea708InitializationData functionality into CeaUtil and delete the
class.
Move CeaUtil to the util package as it needs to be used both in
extraction and decoding.
PiperOrigin-RevId: 291128220
The only remaining use is to provide the initial position for the first media
period in the queue. At this point, the value is always equivalent to
PlaybackInfo.positionUs because they are set together to the same value in
PlaybackInfo.copyWithNewPosition.
PiperOrigin-RevId: 290749294
We have a flag that gets turned on if the current playback position has been
reset, so that messages from this reset position can be triggered. This
mechanism isn't actually depending on the startPositionUs field because it
should always be triggered in the first iteration with the new position.
PiperOrigin-RevId: 290749201
There are a couple of problems with how positions in PlaybackInfo are set at
the moment:
1. PositionUs isn't allowed to be C.TIME_UNSET. This is prevented by always
resolving to the current default position if needed.
2. In some places a window position was used as a period position. Use correct
position resolution procedure.
3. When creating a placeholder position to restart playback, we used the first
period in a window, not the one where the default position is.
4. The start position for ads was in some cases set to 0 without checking
the ad resume position.
PiperOrigin-RevId: 290749042
I needed to use Cue.Builder instead of just SpannableStringBuilder for
the regionOutput values, so I could attach the vertical info where
appropriate (since this is a property of the Cue, not a span).
PiperOrigin-RevId: 290709294
If an exception is thrown between updating the timeline and updating
the position in playbackInfo, the state may be inconsistent.
Exceptions are expected to be thrown while updating the player state
and we should handle such cases in a consistent way.
Similar to how we handle the same situation in seekToInternal,
the state is updated in a final block such that it gets updated to the
latest state even if an error occurs. Moving both the timeline and
position update together also ensures they always stay consistent.
PiperOrigin-RevId: 290624020
This restructure moves all the position resolving code to a static method and
removes the dependency of the MediaPeriodQueue on having an up-to-date timeline.
Both steps allow simplified reasoning about the code as the static method can't change
the state of the player, and there is no risk the queue can use the wrong timeline.
These propoerties allow to fix a bug causing inconsistent states in a follow-up step.
PiperOrigin-RevId: 290616395
It's never assigned or accessed from outside the class.
It was added in
<unknown commit>
then the accessor was removed in
<unknown commit>
PiperOrigin-RevId: 290601998
This makes MPEG audio utilities similar to utilities we have for WAV,
AC-3 etc., and moves them out of the extractor package so that an
extractor module can be split out without needing to have a class in the
extractor package in the common library.
PiperOrigin-RevId: 290595089
*** Original commit ***
Rollback of ff89170b00
*** Original commit ***
Fix some logic in AnalyticsCollector.
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is...
***
PiperOrigin-RevId: 290593700
*** Original commit ***
Fix some logic in AnalyticsCollector.
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is empty or a seek is pending. Since adding all the playlist API methods to the player,
this is no longer the right choice. Moreover,...
***
PiperOrigin-RevId: 290312118
Currently both are updated by separate setters. If an exception is thrown between
the two setters, the state may not be consistent.
Avoid this problem by always setting them together.
PiperOrigin-RevId: 290293600
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is empty or a seek is pending. Since adding all the playlist API methods to the player,
this is no longer the right choice. Moreover, we don't have a definite API that tells
AnalyticsCollector when a playlist API call has been handled (and we don't want to
have one).
We can fix this by always using the current Player position information as the source
of truth (instead of the media period queue). This is definitely more correct and also
works while a masking operation is pending. To fill in the additional information from
the media period queue, we can look up a matching media period. This may not be the
first one in the list if an operation is pending.
The new methods are similar to the previous tryResolveWindowIndex method, but:
1. They are always used (i.e. the current Player state is the main source of truth)
2. They also check the correct ad playback state, that was just ignored previously.
PiperOrigin-RevId: 290284916
Currently seeks are basically ignored. However, it's more realistic to re-queue the
single sample if the seek is to position 0.
PiperOrigin-RevId: 290273564
*** Original commit ***
Rollback of d48dc4c159
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a...
***
PiperOrigin-RevId: 290273295
- Add additional Listener methods to DownloadManager, to inform of
changes to whether the downloads are paused or waiting for requirements.
- Only schedule the Scheduler if we really are waiting for requirements.
- Only restart the service if we're no longer waiting for requirements,
and if there are queued downloads that will now be restarted.
Previously the service would be restarted whenever the requirements
were met, regardless of whether there was any work to do.
- Restart service if it might be stopping, as well as if it's already
stopped. Also restart service if there's a download state change to a
state for which the service should be started, if.
Issue: #6798
PiperOrigin-RevId: 290270547
First cl towards DefaultMediaSourceFactory (<unknown commit>) does not change the MediaSourceFactory interface except adding @Nullable anotations to setters.
PiperOrigin-RevId: 290269640
Doing so prevent Codec which is a big object with
JNI to be garbage collected.
As the codec can not be hold in the listener, there
is no way to call release, as it must be called on
the same codec.
As a result the release method is also removed.
The downside is that at runtime some callbacks may be
dropped but it should be a short transitive state.
This also simplifies lifecycle of the listener as
the client does not have to know if release needs
to be called or not.
An alternative would have been to hold a weak ref,
but I deemed it too complicated for the
runtime gain.
PiperOrigin-RevId: 290231659
This fixes an issue where a DownloadService implementation
that allows foreground but doesn't provide a scheduler would
not be restarted in the case that it was still in memory but
classed as idle by the platform.
It also speeds up service restart in the case that a
scheduler is provided.
Issue: #6798
PiperOrigin-RevId: 290068960
This method has two use cases:
1. Seeking. Calls are immediately preceded by a call to rewind(), and
the returned value isn't important unless it's ADVANCED_FAILED (i.e.
the caller is only interested in success and failure).
2. Advancing. The return value is important unless it's ADVANCED_FAILED,
in which case the caller wants to treat it as 0.
This change creates separate methods for each use case. The new seekTo
methods automatically rewind and return a boolean. The updated advanceTo
method returns 0 directly in cases where ADVANCED_FAILED was returned.
Arguments that were always hard-coded to true by callers have also been
removed.
This change is a step toward one possible solution for #6155. How we'll
solve that issue is still up for discussion, but this change seems like
one we should make regardless!
Issue: #6155
PiperOrigin-RevId: 290053743
- DownloadManagerHelper now passes all downloads to the
DownloadService when the service is attached (and once
the downloads are known). The service then starts the
foreground notification updater if necessary. This fixes
the ref'd issue.
- Don't call getScheduler() if the service is background
only. This was already documented to be the case on the
DownloadService constructor.
- If the service is started in the foreground on SDK level
26 and higher, satisfy the condition to move the service
to the foreground in onStartCommand rather than in stop().
It's much more obviously correct, and should produce the
same end result.
Issue: #6798
PiperOrigin-RevId: 290050024
Currently the following sequence of events happens at automatic period transitions:
1. Update queue (=release old playing period)
2. Disable unused renderers
3. Enable newly needed renderers
This order requires difficult to follow workarounds in AnalyticsCollector for all
events related to step 2 (disable renderers). The current media period has already
been advanced so can't be used. The current workaround saves the last known playing
media period that was published as part of a PlaybackInfo update in ExoPlayerImpl.
This works in most cases, but is inherently wrong because the published state in
ExoPlayerImpl may be completely unrelated to the updates happening on the playback
thread (e.g. if many other operations are pending).
Simplify and fix this problem by changing the order of the events above:
1. Disable unused renderers.
2. Update queue
3. Enable newly needed renderers.
This way the current playing media period can be used for both renderer disable
and renderer enable events, thus it's correct in all cases and the workaround
in AnalyticsCollector can be removed.
PiperOrigin-RevId: 290037225
Whenever we set the maskingWindowIndex, we also need to set the masking period index
and the masking position. Otherwise it may cause exception when the period index
is used together with the masking timeline.
PiperOrigin-RevId: 290036973
This optimization allows a ChunkSampleStream to output track
formats as soon as they're parsed during an InitializationChunk
load, rather than waiting until after the InitializationChunk
load is completed.
In DASH VOD, a single InitializationChunk typically loads the
moov and sidx atoms in that order. Hence for long form content
where the sidx is a non-trivial size, this may result in the
track formats being output a non-negligible period of time
sooner than was previously the case. This allows downstream
renderers to start codec initialization sooner, potentially
decreasing startup latency.
For a single test stream on a fast & stable network, this
pretty consistently reduced elapsed time until both audio and
video codecs have been initialized from ~0.5s to ~0.3 seconds
on a Galaxy S8. For 5 test runs without and with these patches,
the eventTime logged by EventLogger for the second decoder
init were:
Without (secs): 0.47 0.47 0.45 0.48 0.46
With (secs) : 0.32 0.33 0.34 0.31 0.40
PiperOrigin-RevId: 289845089
The current order of operations means that the Format is only passed
to the chunk's output after the DataSource has been opened. This
means that establishing the network connection and the downstream
renderers initializing their codecs are effectively serialized to
occur one after the other.
In the new order, the Format is passed to the chunk's output before
the DataSource has been opened. This allows the downstream renderers
to initialize their codecs in parallel with the network connection
being established, and hence latency at the start of playback is
reduced.
PiperOrigin-RevId: 289841854
We currently have a currentMediaPeriodId and an activeSessionId that are more
or less tracking the same thing unless the current media period isn't "active" yet.
Simplify this logic by using a single currentSessionId field and the respective
isActive flag of this session. Also move all session creation and activation code in
the same method to make it easier to reason about the code.
This change also fixes a subtle bug where events after a seek to a new window
are not ignored as they should.
PiperOrigin-RevId: 289432181
As discovered whilst investigating #6798, there are cases
where these methods are not correctly. They were added as
convenience methods that could be overridden by concrete
DownloadService implementations, but since they don't work
properly it's preferable to require application code to
listen to their DownloadManager directly instead.
Notes:
- The original proposal to fix#6798 stored the state change
events in memory until they could be delivered. This approach
is not ideal because the events still end up being delivered
later than they should be. We also want to fix the root cause
in a different way that does not require doing this.
- This change does not fix#6798. It's a preparatory step.
Issue: #6798
PiperOrigin-RevId: 289418555
Dash live streams require that the client has an accurate wall clock
time and in absence of a UTCTiming element, this is assumed to be the
NTP time.
This change adds NTP time offset resolution for DASH live streams
without such timing elements.
PiperOrigin-RevId: 289098796
Unfortunately devices such as the MI 8 do not provide an alternative
working decoder. Some Vivo devices do provide one though.
PiperOrigin-RevId: 288911897
This improves readability by making clearer that reading no bytes from
the input in readFrames() is an expected case if the buffer is full.
PiperOrigin-RevId: 288711841
Currently, seeks are only tracked if both the start and the end of the seek
is within the same window. This means no seeking state is reported if the
playback switches to a new window during the seek.
This problem is fixed by tracking seek start and end events in all cases,
but only report seeking state once the window becomes the foreground window.
PiperOrigin-RevId: 288706674
These make the interesting bits of each assertion harder to follow imo.
Also remove all the assertWithMessage() calls at the same time, Olly
convinced me these are rarely useful since you can click from the stack
trace to the failing line in the IDE.
PiperOrigin-RevId: 288470704
- Simulate IO exceptions in the test using FlacBinarySearchSeeker for
seeking in FlacExtractorTests. This makes the test slower but covers
more test cases.
PiperOrigin-RevId: 288285057
There's currently no rendering support for ruby text in SubtitleView
or SubtitlePainter, but this does have a visible impact with the
current implementation by stripping the ruby text from Cue.text
meaning it doesn't show up at all under the 'naive' rendering.
This is an improvement over the current behaviour of including
the ruby text in-line with the base text (no rubies is better than
wrongly rendered rubies).
PiperOrigin-RevId: 288280416
This typo was introduced in ddb70d96ad
when migrating a static method with parameter `durationUs` to an
instance method where the correct field to use was `blockDurationUs`
(but `durationUs` also exists).
The test that catches this was only added in 45013ece1e (and
therefore configured with the wrong expected output data).
issue:#6833
PiperOrigin-RevId: 288274197
It's not used. I was trying to work out how to correctly cascade my
text-combine-upright styling, but deleting the method seemed easier...
PiperOrigin-RevId: 287989480
I decided the flags bit was a bit unclear so I played around with this
It's also needed for more 'complex' assertions like colors - I didn't
want to just chuck in a fourth int parameter to create:
hasForegroundColorSpan(int start, int end, int flags, int color)
PiperOrigin-RevId: 287989424
Relying on the precedence of spans seems risky - I can't find it
defined anywhere. It might have changed in Android 6.0?
https://stackoverflow.com/q/34631851
PiperOrigin-RevId: 287989365
-- Optimize Mp4Extractor for AC-4
-- Optimize FragmentedMp4Extractor for AC-4
-- Add test case for AC-4 in MP4
-- Add test case for AC-4 in Fragmented MP4
It's unreliable for at least one IMA ADPCM file I've found.
Calculating the blockIndex to seek to using exact properties
also seems more robust.
Note this doesn't change anything for the existing PCM test,
since averageBytesPerSecond is set correctly. It does make
a difference for an upcoming IMA ADPCM test though.
PiperOrigin-RevId: 287814947
An experiment with this algorithm didn't show positive results. We can
therefore keep the simpler default algorithm.
Startblock:
<unknown commit> is submitted
PiperOrigin-RevId: 287807538
Where media segments are specified using byte ranges, it makes
sense that a server might return 416 (which we don't consider
for blacklisting) if the segment is unavailable, rather than
the 404 (which we do consider for blacklisting) that we expect
when media segments are only specified using a URL.
Issue: #6775
PiperOrigin-RevId: 286620698
The Download constructor considers it invalid to have a failure
reason if the download isn't in the failed state. Unfortunately,
calling DefaultDownloadIndex.removeAllDownloads when there's a
failed download will change the state without clearing the reason.
If the downloads are then read back from the DefaultDownloadIndex
we end up violating the Download constructor assertion.
This change clears the failed reason for any existing rows in the
invalid state, and also fixes the root cause that allows invalid
rows to enter the table in the first place.
Issue: #6785
PiperOrigin-RevId: 286576242
Without this @Nullable, potential subclasses can't override the
method to return null if they don't want to use the renderer as a
media clock.
Issue:#6792
PiperOrigin-RevId: 286545736
This class is only used to hold temporary data while we parse the
settings and text, so we don't need it outside the Parser class.
Also remove all state from WebvttCueParser - this increases
the number of allocations, but there are already many
and subtitles generally aren't very frequent (compared to
e.g. video frames).
PiperOrigin-RevId: 286200002
Add support for MP3 as an encoding format for passthrough.
This change does not change the observable
behavior of Exoplayer.
Also name the magics.
#exo-offload
PiperOrigin-RevId: 286146539
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a LoadControl lets playback get stuck. This includes the case where
DefaultLoadControl reaches its maximum buffer size and not even a mim...
***
PiperOrigin-RevId: 286071115
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a LoadControl lets playback get stuck. This includes the case where
DefaultLoadControl reaches its maximum buffer size and not even a mimimal buffer
duration.
PiperOrigin-RevId: 285979989
This offset allows to improve the calculated live offset because it
can take known client-server time offsets into account.
PiperOrigin-RevId: 285970738
I want to add fields related to vertical text support, and neither
adding another constructor nor updating all call-sites of existing
constructors seemed like attractive propositions.
PiperOrigin-RevId: 285956024
- Remove duplicated null assignments
- Move mediaCryptoRequiresSecureDecoder reset to be with all the
other mediaCrypto stuff.
PiperOrigin-RevId: 285955134
MultiLockAsyncMediaCodecAdapter is an implementation of the
MediaCodecAdapter that uses multiple locks to synchronize access to its
data compared to the single-lock approach used in
DedicatedThreadAsyncMediaCodecAdapter.
PiperOrigin-RevId: 285944702
- Make extractor output samples that are uniformly distributed
with respect to time, with a target of ~10 samples per second.
The old approach could in theory put every frame into its own
sample, which would be very inefficient downstream because we'd
need to pass them individually to MediaCodec. It could also put
data corresponding to a long duration of time into a single
sample (e.g. if the sample rate of the content is low), which
is bad downstream because we decide whether to set the decodeOnly
flag on a per sample basis. More generally, the new approach
is more predictable :).
- Stop using the WavSeekMap to get sample timestamps, and instead
calculate them directly from the number of frames output. It's
more obviously correct, particularly for data formats like IMA
ADPCM where we'll need to adjust the data prior to output.
PiperOrigin-RevId: 285750010
In MatroskaExtractor, if the last cue time exceeds the duration
specified in the header, then we end up generating a negative
duration chunk as the last item in the SeekMap. We should probably
not do this, so drop it instead.
Note: Matroska does have a CueDuration element, but it's not used
in the one problematic file I've found.
PiperOrigin-RevId: 285738418
Currently, resetting the internal state related to the codec in done in 4 places
in MediaCodecRenderer:
1. In the constructor to set some sensible initial default.
2. In flushOrReleaseCodec to reset state after flushing
3. In releaseCodec to reset state to default values for a released codec.
4. In initCodec to reset state to defaul values for a new codec.
There are actuall only two types of state reset operations:
1. Resetting state for a released codec, so that a new codec isn't influenced by
previous codecs.
2. Resetting state after flushing an existing codec. This is a subset of (1).
So to simplify the class, this change moves all state resets to two methods
corresponding to the two cases above.
PiperOrigin-RevId: 285731913
These are transitively provided by testutil's build.gradle.
This makes the core module consistent with the others like ui, hls, dash
PiperOrigin-RevId: 285729566
This may happen for example when trying to load unfinished live media
chunks that can only be loaded at real-time playback speed.
The flag can be used by the sources to indicate that network transfer
will knowingly be throttled, such that transfer listeners like the
bandwidth meter can take this information into account.
PiperOrigin-RevId: 285397100
Also change IcyInfo.rawMetatadata from String to byte[]
ICY doesn't specify the character encoding, and there are streams
not using UTF-8 (issue:#6753). It seems the default of at least one
server is ISO-8859-1 so let's support that as a fallback:
https://github.com/savonet/liquidsoap/issues/411#issuecomment-288759200
Also update IcyDecoder to skip strings it doesn't recognise at all
instead of decoding invalid characters.
The feed from issue:#6753 now decodes accents correctly:
EventLogger: ICY: title="D Pai - Le temps de la rentrée", url="null"
PiperOrigin-RevId: 285388522
We previously used Locale.fromLanguageTag and then toLanguageTag to automatically
filter out invalid tags and to replace deprecated tags. However, this only works
for API 21+.
This change does no longer rely on the platform methods and instead:
1. Keeps invalid tags as they are. This may help if developers rely on
non-spec-complaint language tags (for example, #6681).
2. Adds a list of deprcated tags and their modern replacements to our code
3. Normalizes some short codes that have been superseded by macrolanguage codes by
their macrolanguage equivalent.
Issue:#6681
PiperOrigin-RevId: 285384841
This has been broken since
c3d6be3afd
and broken for ICY (where I noticed the problem) since
5695bae9d8.
ICY symptom is that we see no repeated metadata, because the
Icy-MetaData:1 header doesn't make it to the server so we never get back
icy-metaint.
PiperOrigin-RevId: 285379234
Retrieve the sample number in the extractor instead of passing a holder
to FlacBinarySearchSeeker. This change makes the code easier to
understand and is required to implement the seeking from the seek table.
PiperOrigin-RevId: 285241862
- WavHeader is now immutable and contains only values parsed out
of the WAVE FMT chunk. It no longer contains a C.PcmEncoding
encoding, or mutable data bounds.
- WavHeaderReader now parses the WAVE header chunks without any
additional logic (e.g. validating the block alignment value,
which is format type dependent).
- The SeekMap part of WavHeader is split out into WavSeekMap.
PiperOrigin-RevId: 285232498
This returns the current offset to the live edge. The calculation is
non-intuitive enough to provide this convenience method.
PiperOrigin-RevId: 285171090
This avoids needing to jump through type paremeter hoops to create a
sub-classable Cue.Builder.
Cue should have a standard set of fields, because it will be
consumed by renderers that don't know what type it is. The
existing subclass fields are only used inside their respective
packages, so can be part of a wrapper object instead.
This lays the groundwork for converting Cue's multiple constructors
into a Builder pattern.
PiperOrigin-RevId: 284992135
Keyframe was rendered rather than skipped when performing
an exact seek to a non-zero position close to the start of
the stream.
PiperOrigin-RevId: 284798460
The nullness checker complains about Integers with @IntDef annotations
so replace pairs with custom pair types for the timed event records in
PlaybackStats.
PiperOrigin-RevId: 284731834
Caveats:
- Block additional data is ignored if the block is laced
and contains multiple samples. Note that this is not
a loss of functionality (SimpleBlock cannot have block
additional data, and lacing was previously completely
unsupported for Block)
- Subrip and ASS samples are dropped if they're in laced
blocks with multiple samples (I don't think this is
valid anyway)
Issue: #3026
PiperOrigin-RevId: 284545197
This change constrains the use of sample state member variables to
writeSampleData, finishWriteSampleData and resetWriteSampleData.
Using them elsewhere gets increasingly confusing when considering
features like lacing in full blocks. For example sampleBytesWritten
cannot be used when calling commitSampleToOutput in this case
because we need to write the sample data for multiple samples
before we commit any of them.
Issue: #3026
PiperOrigin-RevId: 284541942
Refator to lift a method to create (and destroy) the OnFrameRenderedListenerV23() and split destroying the Handler from removing the MediaCodec onFrameRenderedListener to avoid double call to codec.setOnFrameRenderedListener()
This makes the format metadata null (instead of an empty Metadata
object) when it is not provided, and is therefore consistent with the
other extractors behavior.
PiperOrigin-RevId: 284171148
The capture frame rate is currently available both via Format.metadata
and decoded in Format.frameRate. As the container Format.frameRate may
be useful to apps, only store the capture frame rate in metadata (apps
will need to decode it but can now access the container frame rate too).
PiperOrigin-RevId: 284165711
- Remove "lacing" from member variables. They're used even if
there is no lacing (and the fact that lacing is the way of
getting multiple samples into a block isn't important).
Issue: #3026
PiperOrigin-RevId: 284152447
- Change sampleHasReferenceBlock to a block reading variable, which is
what it is (the distinction didn't matter previously, but will do so
when we add lacing support in full blocks because there wont be a 1:1
relationship any more.
- Move sampleRead to be a reading state variable.
- Stop abbreviating "additional"
Issue: #3026
PiperOrigin-RevId: 284000937
An I/O error could occur while handling the start of an mdta box, in
which case retrying would cause another ContainerAtom to be added. Fix
this by skipping the mdta header before updating container atoms.
PiperOrigin-RevId: 284000715
Saves around 200 lines of code. High level overview:
- Rename SampleQueue to SampleDataQueue.
- Rename SampleMetadataQueue to SampleQueue.
This CL should not introduce behavior changes. The only significant
changes in synchronization should be:
+ Add synchronized keyword to isReady.
- Seems to be necessary.
+ Add synchronized keyword to SampleQueue.sampleMetadata.
- Before this change, SampleQueue.sampleMetadata could acquire the
SampleMetadataQueue lock three times in a single method call.
Other miscellaneous improvements:
+ Put all private methods at the bottom.
+ Move release() to the right category.
PiperOrigin-RevId: 283795844
This parameter is a little confusing, especially as the behaviour
can be surprising if the intended use-case isn't clear. This change
moves the description of the parameter into the class javadoc,
adds context/justification and slims down each method's
javadoc to refer to the class-level.
Related to investigating/fixing issue:#6700
PiperOrigin-RevId: 283724826
Calls to new Handler() without arguments are deprecated as of the latest Android
version. Replace them by a Util.createHandler call similar to the ones we
already have.
PiperOrigin-RevId: 283532891
Fixes issue:#6700
sample_cbs_truncated.adts test file produced using
`$ split -b 31795 sample_truncated.adts` to remove the last 10 bytes
PiperOrigin-RevId: 283530136
If LoadControl.shouldContinueLoading returns false and the renderers are not
ready for playback using the already buffered data, playback is stuck.
To prevent this situation, we always continue loading if the buffer is almost
empty. We already have a similar workaround for when
LoadControl.shouldStartPlayback returns false even if loading stopped.
Having both workarounds allows playback to continue even if the LoadControl
tries to prevent loading and playing all the time.
PiperOrigin-RevId: 283516750
*** Original commit ***
Improve `Format` propagation within the `MediaCodecRenderer`.
For example, fix handling of pixel aspect ratio changes in
playlists where video resolution does not change.
Issue:#6646
***
PiperOrigin-RevId: 282903626
When transitioning to a new stream in a different format, the audio
processors are reconfigured. After this, they are drained and then
flushed so that they are ready to handle data in updated formats for the
new stream.
Before this change, some audio processors made the assumption that after
reconfiguration no more input would be queued in their old input format,
but this assumption is not correct: during draining more input may be
queued. Fix this behavior so that the new configuration is not referred
to while draining and only becomes active once flushed.
Issue: #6601
PiperOrigin-RevId: 282515359
flush() is guaranteed to be called in all these cases anyway.
Also clarify documentation for AudioProcessor-specific methods that can
change the 'active' flag.
Issue: #6601
PiperOrigin-RevId: 282515255
This simplifies the contract of configure and is in preparation for
fixing a bug where more input can't be queued when draining audio
processors for a configuration change.
Issue: #6601
PiperOrigin-RevId: 282514367
- Move property to DrmSession; it feels like a more natural place
for it to go (and provides greater flexibility).
- Change flags to a boolean.
PiperOrigin-RevId: 281758729
They are all marked with a JavaDoc comment and the @WorkerThread annotation
which is useful if apps are using threading annotations. All other public
methods in the same classes are marked with @AnyThread to avoid the impression
we forgot to annotate them.
PiperOrigin-RevId: 281490301
The current workaround seems to cause compilation errors inside the
testutils module in Android Studio. This seems to fix them.
This doesn't introduce a circular dependency because it's only
the tests in library-core depending on testutils.
PiperOrigin-RevId: 281318192
Note:
- Fixing this uncovers another bug in how audio processor draining
works, so the test playlist still doesn't play correctly after this
change.
- Once we reconfigure the audio sink based on the ExoPlayer Format
rather than the codec MediaFormat in a later change, this change can
be reverted.
Issue: #6601
PiperOrigin-RevId: 281264149
- Make NonNull, which is already the case when using the manager builder.
- Better document PLAYREADY_CUSTOM_DATA_KEY, now that newPlayReadyInstance
is no more.
PiperOrigin-RevId: 281079288
The implementation of writing HDR10+ static metadata assumed that the
application would use default (big endian) byte order for this metadata but
MediaCodec expects the order to match the specification CTA-861.3.
PiperOrigin-RevId: 281050806
Also remove the "do we really need to do this" comment for AAC.
Parsing from codec specific data is likely to be more robust, so
I think we should continue to do it for formats where we've seen
this problem.
Issue: #6648
PiperOrigin-RevId: 280575466
Previously the renderer EOS (aka last frame rendered), was reported as soon
as the last encoded frame was queued in the codec renderer.
This leaded to EOS reported too early.
PiperOrigin-RevId: 280456277
This speeds up downloads where segments have the same URL with different
byte ranges. We limit the merged segments to 20 seconds to ensure the download
progress of demuxed streams is roughly in line with the playable media duration.
Issue:#5978
PiperOrigin-RevId: 280410761
Clear state for one mode when entering the other in both SimpleExoPlayer
and SimpleDecoderVideoRenderer. The latter is redundant for the case of
renderers that are used inside SimpleExoPlayer, but seems nice to have.
- Entering Surface mode means receiving a non-null Surface, SurfaceHolder
or TextureView in SimpleExoPlayer, or a non-null Surface in
SimpleDecoderVideoRenderer.
- Entering VideoDecoderOutputBufferRenderer means receiving a non-null
VideoDecoderOutputBufferRenderer in SimpleExoPlayer and
SimpleDecoderVideoRenderer.
PiperOrigin-RevId: 280155151
This aligns the method naming and Javadoc. The only remaining
inconsistency I can see is that the initial reference count for
DrmSession is 0 rather than 1. Unfortunately I think it's not
trivial to get these aligned, because DefaultDrmSessionManager
relies on being able to do something between instantiation and
the DrmSession starting to open the session. In practice this
doesn't really matter, since DrmSessions will be obtained via the
manager, which does increment thee reference count to 1 to be
consistent with how ExoMediaDrm acquisition works.
PiperOrigin-RevId: 280136574
The handling of times wasn't really clear to me, hopefully this more
exhaustive documentation helps a bit.
Also assert the end timecode is the 'correct' length for the format.
PiperOrigin-RevId: 279922369
To trigger receiving the broadcast it's necessary to idle() the shadow
main looper, which has to be done from the test thread. Therefore this
change removes the send broadcast action and instead sends the broadcast
from the test thread.
PiperOrigin-RevId: 279660935
This means multiple failures are all logged, instead of the test
stopping when the first assertion fails. Makes tests like this with
lots of independent assertions much easier to work with.
I limited the expect to a single assertCues() call, otherwise
the error message gets very long and is hard to read, but I
still think this is an improvement.
PiperOrigin-RevId: 277523300
Cue's UNSET and null values should be used when the source data
doesn't specify *and* the spec doesn't provide a clear default.
In the WebVTT case, the defaults are clear, so we use them
explicitly.
PiperOrigin-RevId: 277522899
The framework opus decoder discards some samples after a call to
flush(). Because we flush a decoder that is being retained across an
input format change, this means that the start of audio gets truncated
when transitioning to a new opus stream. See also
https://android.googlesource.com/platform/frameworks/av/+/refs/heads/android10-release/media/libstagefright/codecs/opus/dec/SoftOpus.cpp.
Avoid this by recreating opus decoders instead of flushing them. It
seems fine to do this for all opus decoders as reinitialization should
be cheap, OEM-provided implementations may also discard samples and
playback shouldn't be interrupted on reinitialization due to the
downstream AudioTrack buffer.
PiperOrigin-RevId: 277458759
Also remove it from all tests, these aren't covered by the null-checker
Covered by the following package-info.java files:
- j/c/g/a/exoplayer2/ext/mediasession/package-info.java
- j/c/g/a/exoplayer2/package-info.java
- j/c/g/a/exoplayer2/offline/package-info.java
- j/c/g/a/exoplayer2/video/package-info.java
- j/c/g/a/exoplayer2/ui/package-info.java
PiperOrigin-RevId: 277038916
*** Original commit ***
Rollback of bf01ff0f60
*** Original commit ***
Use Float.NaN for Cue#DIMEN_UNSET
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it a...
***
PiperOrigin-RevId: 276674142
*** Original commit ***
Use Float.NaN for Cue#DIMEN_UNSET
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it accidentally.
***
PiperOrigin-RevId: 276315786
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it accidentally.
PiperOrigin-RevId: 276277784
With lots of int comparisons close together, this makes the error
messages much clearer and saves having to manually match up line
numbers.
Also make every @Test just throw Exception
PiperOrigin-RevId: 276079806
Without this, a subtitle track empty edit list used to offset the start of
subtitles is ignored.
Also the current code seems to depend on the order in which
we parse the tracks (audio first means we have gapless info when we parse
video track, while video first we wouldn't).
It's not clear why we can't handle both edit lists & gapless info
PiperOrigin-RevId: 276029744