The new version fixes some warnings in Gradle builds. Also
add missing indirect compileOnly dependencies to fix some more warnings
Issue:issue:#7007
PiperOrigin-RevId: 298855510
This option marks streams as final such that renderers play them out
completely, then waits until this happened, and then sets the player
to paused. After that, the player can continue to read the next period
to quickly resume playback if needed.
PiperOrigin-RevId: 298824745
Update it to allow any listener class to be registered (and thus
require the caller of dispatch() to provide the type of listener
to call).
Maintain MediaSourceEventListener.EventDispatcher as a sub-class
for now so that all existing references continue to work. This
avoids creating a huge diff in one CL. The intention is to in-line
these incrementally.
This is pre-work for issue:#6765
PiperOrigin-RevId: 298818198
The default Robolectric Looper simulation mode is changing to PAUSED from LEGACY.
The following tests fail in this new mode, and are thus being defaulted to LEGACY.
For more details see go/robolectric-legacy-looper-mode-lsc
Cleanup change automatically generated by error-prone refactoring
//third_party/android/androidx_test/tools/errorprone/java/androidx/test/tools/errorprone:LegacyLooperModeConverter_refactoring
Tested:
TAP train for global presubmit queue
http://test/OCL:297627974:BASE:298600828:1583273401491:7d94dbaa
PiperOrigin-RevId: 298809656
DashMediaSource is created with Manifest data and streamKeys can be empty given that streamKeys are only created out of MediaItem inside DashMediaSource, and this particular implementation don't extract them out of MediaItem properties.
Tested=Verified playback works.
PiperOrigin-RevId: 298550021
This change adds the createMediaSource(MediaItem mediaItem) method to the MediaSourceFactory interface. It doesn't deprecate createMediaSource(Uri uri) to keep the cl smaller. Deprecation and removing calls to the deprecated method from within the library and extension follow in a separate CL.
PiperOrigin-RevId: 298352442
The test had two problems:
1. It posts messages using a Handler and we need to idle the main looper
to actually deliver this message.
2. SimpleDecoder uses a background thread that is not within our control
from the test. Ensure the decoding happens after we queue input buffers
by using a lock.
PiperOrigin-RevId: 298300175
This is one step toward following the google3's test naming convention.
See go/java-testing/getting_started#basic-test-template for details
why prefix test isn't necessary.
This CL is generated by following command
$ find -name '*Test.java' | xargs -I{} sed -i 's/^\ \ public\ void\ test\([A-Z]\)\(.*\)$/ public void \L\1\E\2/' {}
and then manually modified following tests where test method names conflict with test target.
- VorbisUtilTest
- VorbisReaderTest
- UtilTest
- DownloadManagerDashTest
- DefaultOggSeekerTest
- OggPageHeaderTest
- HlsMasterPlaylistParserTest
PiperOrigin-RevId: 298074653
We should only ignore seek to the current position if we are
currently READY or BUFFERING. Also, pending initial seek positions
should only be saved while we have an empty timeline, independent of
the player state.
Issue:#6886
PiperOrigin-RevId: 297813854
This is more accurate since it's just a placeholder and none of the
values is provided by the media.
It also allows to fix a problem in ClippingMediaSource where we
couldn't detect a clipping error because we didn't know if the
timeline is a placeholder or not.
Issue:#5924
PiperOrigin-RevId: 297813606
When a new Timeline arrives in the Player, we check whether we can keep
existing MediaPeriods. This check currently involves a condition that
checks if the MediaPeriod is already prepared. The only reason we do
that is to avoid calling MediaPeriod.seekToUs, which is not allowed
on an unprepared MediaPeriod.
It's better to keep the MediaPeriod to prevent restarting the
preparation process. The prepration check can move further down to the
place right before we would call seekToUs.
PiperOrigin-RevId: 297812584
AnalyticsCollector keeps a list of existing MediaPeriodInfo that need
to be updated to new Timelines when they arrive. This already
happens in all cases except that the playingMediaPeriod wasn't updated
when it didn't change during the timeline update.
PiperOrigin-RevId: 297812038
The positions were interchangeably used with window and period
positions. This change more clearly ensures that all positions in the
AdPlaybackState are based on periods and that we use the right adjustments
for all usages.
PiperOrigin-RevId: 297811633
This removes noisy data from the dump files and allows updating less
dump files if a format field is added, removed or updated.
PiperOrigin-RevId: 297617138
Parallel asynchronous calls to MediaCodec.queueSecureInputBuffer() may
produce garbled video on some platforms. This workaround synchronizes
calls to MediaCodec.queueSecureInputBuffer() so that only one call is
in flight.
PiperOrigin-RevId: 297601037
This change adds the callback onSkipSilenceEnabledChange to the AudioListener and calls it when changed by the user by calling setPlaybackParameters, or when changed internally by the DefaultAudioSink if the parameters are not applicable. It needs to be plumped through AudioSink, AudioRenderer to SEP which eventually calls the AudioListener.
No changes to the Player interface so far. The getter of skipSilenceEnabled is added to SimpleExoPlayer for completeness, but not yet to the Player interface. The setter is not yet exposed, but implemented as a private method for implementation reasons.
PiperOrigin-RevId: 297590291
DefaultLoadControl applies the same min buffer duration to audio
and video. By default, min buffer is set equal to max buffer (50 seconds).
PiperOrigin-RevId: 297324489
Note: The dump files will need updating again when the extractors
are modified to only set the appropriate bitrate. Enhancing the
test first is nice, because it means that in subsequent CLs the
dump file updates can be used to quickly see what's changed in
the output.
PiperOrigin-RevId: 297188367
- Avoid having ExtractorHolder expose the underlying extractor.
- Make ProgressiveMP inject a DataSource instead of a DefaultExtractor.
This CL should introduce no functional changes.
PiperOrigin-RevId: 296944788
This change deprecates PlaybackParameter in AudioSink and splits it into playbackSpeed and skipSilenceEnabled. These properties are set separately in a future CL. The playback speed will be set through the MediaClock, while skipSilenceEnabled will be set by sending a message to the audio renderer.
PiperOrigin-RevId: 296457043
- Deprecate old Format.createXXX methods
- Deprecate most Format.copyXXX methods
- Stop using deprecated Format.copyXXX methods in the library
Note: Replacing library usages of Format.createXXX method
will be done in follow up CLs. These changes aren't purely
mechanical because we need to decide which out of peakBitrate
and averageBitrate to set in each case where currently a
single bitrate is provided.
Issue: #2863
PiperOrigin-RevId: 296450935
It's not clear why we're currently outputting the format in both init()
and consume() - it seems likely that this was accidentally introduced
in <unknown commit>
when we started outputting the format in consume() but didn't remove it
from init().
The SCTE-35 TsExtractorTest doesn't pass with the current code because
when it seeks back to the beginning of the file init() is not called
again so the second pass through only sees one sample (and
ExtractorAsserts checks that seeking back to 0 produces the same output
as reading the file from the beginning).
I generated the SCTE-35 sample using TSDuck's tsp command:
$ tsp --add-input-stuffing 1/10 \
-I file testdata/src/test/assets/ts/sample.ts \
-P pmt --service 1 --add-programinfo-id 0x43554549 --add-pid 600/0x86 \
-P spliceinject --service 1 --files scte_35.xml --wait-first-batch \
-P filter --negate --pid 0x1FFF \
-O file testdata/src/test/assets/ts/sample_scte35.ts
This was adapted from the instructions in section 5.2.24.1 of the TSDuck
user manual: https://tsduck.io/download/docs/tsduck.pdf
PiperOrigin-RevId: 296217084
Not important, but when overriding a method that can return null,
it seems preferable to put @Override first, followed by what it's
overriding (which includes the @Nullable).
Also remove explicit @NonNull use in the core library. @NonNull is
propagated by default, so this is redundant.
PiperOrigin-RevId: 296188379
This is one step toward following the google3's test naming convention.
See go/java-testing/getting_started#basic-test-template for details
why prefix test isn't necessary.
This CL is generated by following command
$ find -name '*Test.java' | xargs -I{} sed -i 's/^\ \ public\ void\ test\([A-Z]\)\(.*\)$/ public void \L\1\E\2/' {}
PiperOrigin-RevId: 296169886
When copying CryptoInfo for asynchronous input buffer queueing,
re-use the destination CryptoInfo's arrays to avoid re-allocating
memory.
PiperOrigin-RevId: 295706771
Note on UnknownNull: Where there exists a generically typed
base class and both null and non-null types are permitted,
we need to clear the default non-null that's otherwise
propagated everywhere. This then lets the nullness of the
type work properly.
PiperOrigin-RevId: 295582444
CryptoInfo.iv length is always 16. When the actual initialization vector
is shorter, zero out the trailing bytes.
Issue: #6982
PiperOrigin-RevId: 295575845
Previously, the input buffer accessUnit count
was passed as the output of the audio processors
which did not make sense as the processors can
split buffers.
This patch passes the access unit count through a
member variable.
PiperOrigin-RevId: 295572577
This is closer to how our actual renderers look like and allows tests
to use a similar logic to show/suppress the first frame in follow-up changes.
PiperOrigin-RevId: 295557548
We will eventually remove the workaround from ExoPlayerImplInternal
added in
b84bde0252
and replace it by an error that gets thrown if the LoadControl behaves
badly.
PiperOrigin-RevId: 295556131
Previously that was implicit, it was the passthrough dance:
- MimeTypes.getEncoding(inputFormat) did not
implement RAW MIME, so it was returning INVALID_ENCODING for PCM
- and allowPassthrough was returning
MimeTypes.getEncoding() != INVALID_ENCODING
- which was setting codecInfo.passthrough, and passthroughEnabled.
Thus Util.isEncodingPcm(encoding) is the opposite of
(MimeTypes.getEncoding(inputFormat) != C.ENCODING_INVALID)
This was rather implicit and brittle as anyone
could add support for audio/RAW in
MimeTypes.getEncoding and break PCM playback.
As a result make it explicit that allowPassthrough
must always return false in PCM.
PiperOrigin-RevId: 295144013
Modify TrackOutput.sampleData() to accept SampleDataReader instead of ExtractorInput. SampleDataReader supports only read and skip calls, which all sampleData() implementations already restrict themselves to.
PiperOrigin-RevId: 294905155
Currently only one access unit can be written per
buffer write. This has been found to be power
inefficient in an offload situation.
#exo-offload
PiperOrigin-RevId: 294886188
This information isn't easily available to the player at the moment (or it
would need to revaluate this every time), so add it to MediaPeriodInfo similar
to the existing isLastInTimelinePeriod.
The player needs to know whether a MediaPeriod is the last in its Timeline
window if we want to add an option to pause at the end of a window.
PiperOrigin-RevId: 294877628
Add fields in DecoderCounters for computing the average video frame
processing offset.
The MediaCodecVideoRenderer reports the video frame processing offset
and the demo app presents it on the debug information.
PiperOrigin-RevId: 294677878
The transition in EPII happens based on the duration of the periods, not
the windows. So use this duration in case they are not the same.
Also make sure to send the message at duration-1 because the playback position
at the duration is technically already the first position in the next item.
PiperOrigin-RevId: 294669335
This simplifies sending messages to the end of a stream. This was
already possible, but users needed to wait until the duration is known
before sending the message. This duration resolution can happen as part of the message position resolution.
PiperOrigin-RevId: 294626984
Issue #6853
Previously the body of an HTTP response was not included in an
InvalidResponseCodeException. This change adds a field to store
the response body, and updates DefaultHttpDataSource to populate
this value.
Language is already applicable to image formats as well.
It can also apply to video formats. For example when the
video contains burnt in subtitles. Also, some animation
studios produce multiple variants of animations, in which
text within the scene itself (e.g., a signpost) is
replaced to be language specific.
PiperOrigin-RevId: 294500227
- Replace tests specific to HTTP request headers with tests that
more generally test constructor correctness.
- Add test specifically around the constructor that infers the
HTTP method from postBody, since that's a non-trivial bit of
constructor logic.
Note: In general, I'm not sure this type of test (i.e., testing a
bit of trivial copying through a constructor) is worth the cost
of writing and maintaining them. That said, checking the new
uriPositionOffset is calculated correctly is non-trivial, as is
the HTTP method inference, so keeping them for now.
PiperOrigin-RevId: 294488684
This is a preliminary step toward adding a DataSpec.Builder,
which is needed for sanity when adding DataSpec.customData.
The existing absoluteStreamPosition field is very error prone,
because anyone using a Builder to adjust the request position
will need to remember to adjust two values:
dataSpec
.buildUpon()
.setAbsoluteStreamPosition(x)
.setPosition(x)
.build();
Furthermore, the difference between position and
absoluteStreamPosition is irrelevant in nearly all cases. In
the core library, the difference is only relevant when initializing
AES encryption/decryption to write/read cache files.
Replacing absoluteStreamPosition with uriPositionOffset will
simplify the code block above to:
dataSpec
.buildUpon()
.setPosition(x)
.build();
PiperOrigin-RevId: 294485644
Currently, the subset of audio tracks for adaptation is selected
purely based on the size of the subset in the track group, completely
ignoring the previously selected best individual track.
This change ignores all tracks with a different configuration than the
previously selected best track.
PiperOrigin-RevId: 294231806
While the window in which a message or a seek position is resolved is
still a placeholder, we need to re-resolve the position using the
user intent (i.e. the window position) when the timeline updates.
PiperOrigin-RevId: 293346360
The period in this method is most likely prepopulated correctly, but
this assumption is very error-prone and we should populate it locally.
PiperOrigin-RevId: 293345873
This allows to simulate samples in a stream more accurately
particularly when streams are prepared at a non-zero position and
issuing a sample with position=0 is not expected.
Also makes seek more realistic by also issuing one sample again.
PiperOrigin-RevId: 293344081
Once we receive an update from a masked source, we first start the
preparation of an already pending period, and only then notify the
player of the new timeline. If the period prepares immediately inline,
the MediaPeriod.onPrepared callback arrives before the
onPlaylistUpdateRequested call in the Player. THis is the wrong order
and causes issues when the player tries to lookup information in the
timeline that doesn't exist yet.
This change fixes preroll playbacks before live streams.
PiperOrigin-RevId: 293340031
The functional change is to set the bitrate fields to Format.NO_VALUE
in the case that they're non-positive in the header data. Else it's
very easy to to take the fields and copy them directly into Format as
incorrect values.
Issue #2863
PiperOrigin-RevId: 292920141
This change deprecates Player.onPlayerStateChanged(boolean pwr, int state). It removes deprecation for trivial cases. I'll remove other deprecated usages (mostly in ui module) in follow-up CLs to not bloat this CL.
PiperOrigin-RevId: 292917872
This condition is trying to detect when it might be necessary
to switch from a non-secure to a secure codec. This is not
possible if the DRM session is unchanged, unless a different
codec is required for some other reason (e.g., H264 -> H265),
which is anyway handled by canKeepCodec below.
PiperOrigin-RevId: 292909126
*** Original commit ***
Rollback of 3c56b113e4
*** Original commit ***
Rollback of d48dc4c159
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic...
***
PiperOrigin-RevId: 292457964
Passing EXT-X-KEY DrmInitData through the FragmentedMp4Extractor
doesn't work for streams with key rotation, because an extractor
instance is used for multiple segments, but is only passed the
EXT-X-KEY DrmInitData corresponding to the first segment.
This change removes passing DrmInitData through the extractor,
and instead passes it via FormatAdjustingSampleQueue. This is
in-line with how manifest DrmInitData is handled during DASH
playbacks.
Issue: #6903
PiperOrigin-RevId: 292323429
This is a nice-regardless improvement to SampleQueue, which will
likely to used to fix the referenced issue. It makes it possible
for SampleQueue subclasses to support dynamic changes to format
adjustment in a non-hacky way.
Issue: #6903
PiperOrigin-RevId: 292314720
Fix outline style subtitle
When a ForegroundColorSpan changes the foreground color, it is also applied
to the outline painter. In order to keep the correct color, one needs to
filter out theses span. We do this with a new cue that is our text source
for the specific edgeLayout.
Take care to only apply background color once
Test: Manual check - Subtitle view can show custom color subtitles from specific Subtitle
Renderer and outline is shown correctly using user defined color.
Calling setViewType with the same view type as the
subtitleView is using would throw InvalidArgumentException
instead of being a noop.
PiperOrigin-RevId: 291937202
We currently have 3 states, but the NOT_SET state isn't needed
anymore. We can therefore replace the IntDef by a simple boolean.
PiperOrigin-RevId: 291926049
We currently apply new parameter checkpoints from an absolute media
time and then substract the current media start time again to retrieve
the media time offset for this playback parameter checkpoint.
However, the media start time may change when unexpected discontinuities
happen (the start time doesn't actually change, but we change it to
correct for this discontinuity). This then invalidates the absolute
media time in the playback parameter checkpoints (which should have been
corrected as well).
Avoid this problem by also only applying the new start position
from the checkpoint. We don't have to save the start position anymore
because it will cancel itself out.
Also add some documentation and code clarification for improved
readability.
PiperOrigin-RevId: 291923069
SubtitleView now becomes a ViewGroup that owns a SubtitleTextView. It
handles some common styling defaults, but delegates the underlying
values down into SubtitleTextView through the SubtitleView.Output
interface.
When I add a SubtitleWebView this will also be a ViewGroup containing
a WebView and will implement SubtitleView.Output and convert Cue styling
into HTML & CSS.
PiperOrigin-RevId: 291903294
It doesn't seem worth keeping the cap, since the device
will presumably stop receiving major version updates at
some point anyway.
Issue: #6899
PiperOrigin-RevId: 291899439
This seeker is only seeking to frames that have already been read by the
extractor for playback. Seeking to not-yet-read frames will be
implemented in another change.
Issue: #6787
PiperOrigin-RevId: 291888899
We currently only keep the requested next content start position while
we are playing ads. However, we should also keep at least before a content
period is fully prepared to not loose the information about the user intent.
PiperOrigin-RevId: 291705752
There are existing bugs that need this flag to know whether the
current information in the window is still a placeholder or can
already be relied on for further calculation.
This flag will probably only ever be set in DummyTimeline, so it's
not added to the window.set method to avoid updating all clients.
Issue:#5924
PiperOrigin-RevId: 291705637
It could either live in .util or .extractor, but since it's not needed
outside the extractor package in core (and the FLAC extension), and
FlacStreamMetadataTest uses a FLAC asset, it seems preferable to move it
into the extractor package.
PiperOrigin-RevId: 291372032
CeaUtil depends on TrackOutput so should live in the extractors package.
To avoid having Cea708Decoder depend on extractors, this change also
moves the initialization data building/parsing to CodecSpecificDataUtil.
PiperOrigin-RevId: 291348317
Using @Test(expected=...) is discouraged, since the test will pass if
any statement in the test method throws the expected exception.
PiperOrigin-RevId: 291338224
Since we have the Playlist layer on top, it's always guaranteed that a
new playlist item has a new uid. So we can just keep the old one in all
cases and don't have to be careful to delete it. The deletion was necessary
previously in case multiple MediaSources use the same uids.
PiperOrigin-RevId: 291152349
Move Cea708InitializationData functionality into CeaUtil and delete the
class.
Move CeaUtil to the util package as it needs to be used both in
extraction and decoding.
PiperOrigin-RevId: 291128220
The only remaining use is to provide the initial position for the first media
period in the queue. At this point, the value is always equivalent to
PlaybackInfo.positionUs because they are set together to the same value in
PlaybackInfo.copyWithNewPosition.
PiperOrigin-RevId: 290749294
We have a flag that gets turned on if the current playback position has been
reset, so that messages from this reset position can be triggered. This
mechanism isn't actually depending on the startPositionUs field because it
should always be triggered in the first iteration with the new position.
PiperOrigin-RevId: 290749201
There are a couple of problems with how positions in PlaybackInfo are set at
the moment:
1. PositionUs isn't allowed to be C.TIME_UNSET. This is prevented by always
resolving to the current default position if needed.
2. In some places a window position was used as a period position. Use correct
position resolution procedure.
3. When creating a placeholder position to restart playback, we used the first
period in a window, not the one where the default position is.
4. The start position for ads was in some cases set to 0 without checking
the ad resume position.
PiperOrigin-RevId: 290749042
I needed to use Cue.Builder instead of just SpannableStringBuilder for
the regionOutput values, so I could attach the vertical info where
appropriate (since this is a property of the Cue, not a span).
PiperOrigin-RevId: 290709294
If an exception is thrown between updating the timeline and updating
the position in playbackInfo, the state may be inconsistent.
Exceptions are expected to be thrown while updating the player state
and we should handle such cases in a consistent way.
Similar to how we handle the same situation in seekToInternal,
the state is updated in a final block such that it gets updated to the
latest state even if an error occurs. Moving both the timeline and
position update together also ensures they always stay consistent.
PiperOrigin-RevId: 290624020
This restructure moves all the position resolving code to a static method and
removes the dependency of the MediaPeriodQueue on having an up-to-date timeline.
Both steps allow simplified reasoning about the code as the static method can't change
the state of the player, and there is no risk the queue can use the wrong timeline.
These propoerties allow to fix a bug causing inconsistent states in a follow-up step.
PiperOrigin-RevId: 290616395
It's never assigned or accessed from outside the class.
It was added in
<unknown commit>
then the accessor was removed in
<unknown commit>
PiperOrigin-RevId: 290601998
This makes MPEG audio utilities similar to utilities we have for WAV,
AC-3 etc., and moves them out of the extractor package so that an
extractor module can be split out without needing to have a class in the
extractor package in the common library.
PiperOrigin-RevId: 290595089
*** Original commit ***
Rollback of ff89170b00
*** Original commit ***
Fix some logic in AnalyticsCollector.
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is...
***
PiperOrigin-RevId: 290593700
*** Original commit ***
Fix some logic in AnalyticsCollector.
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is empty or a seek is pending. Since adding all the playlist API methods to the player,
this is no longer the right choice. Moreover,...
***
PiperOrigin-RevId: 290312118
Currently both are updated by separate setters. If an exception is thrown between
the two setters, the state may not be consistent.
Avoid this problem by always setting them together.
PiperOrigin-RevId: 290293600
All events issued from ExoPlayerImpl (i.e. Player.EventListener events) currently
try to use the media period data from the playing media period as set in the
playback thread queue. This is only correct as long as there no pending masking
operations in ExoPlayerImpl. That's why we currently disable this whenever the timeline
is empty or a seek is pending. Since adding all the playlist API methods to the player,
this is no longer the right choice. Moreover, we don't have a definite API that tells
AnalyticsCollector when a playlist API call has been handled (and we don't want to
have one).
We can fix this by always using the current Player position information as the source
of truth (instead of the media period queue). This is definitely more correct and also
works while a masking operation is pending. To fill in the additional information from
the media period queue, we can look up a matching media period. This may not be the
first one in the list if an operation is pending.
The new methods are similar to the previous tryResolveWindowIndex method, but:
1. They are always used (i.e. the current Player state is the main source of truth)
2. They also check the correct ad playback state, that was just ignored previously.
PiperOrigin-RevId: 290284916
Currently seeks are basically ignored. However, it's more realistic to re-queue the
single sample if the seek is to position 0.
PiperOrigin-RevId: 290273564
*** Original commit ***
Rollback of d48dc4c159
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a...
***
PiperOrigin-RevId: 290273295
- Add additional Listener methods to DownloadManager, to inform of
changes to whether the downloads are paused or waiting for requirements.
- Only schedule the Scheduler if we really are waiting for requirements.
- Only restart the service if we're no longer waiting for requirements,
and if there are queued downloads that will now be restarted.
Previously the service would be restarted whenever the requirements
were met, regardless of whether there was any work to do.
- Restart service if it might be stopping, as well as if it's already
stopped. Also restart service if there's a download state change to a
state for which the service should be started, if.
Issue: #6798
PiperOrigin-RevId: 290270547
First cl towards DefaultMediaSourceFactory (<unknown commit>) does not change the MediaSourceFactory interface except adding @Nullable anotations to setters.
PiperOrigin-RevId: 290269640
Doing so prevent Codec which is a big object with
JNI to be garbage collected.
As the codec can not be hold in the listener, there
is no way to call release, as it must be called on
the same codec.
As a result the release method is also removed.
The downside is that at runtime some callbacks may be
dropped but it should be a short transitive state.
This also simplifies lifecycle of the listener as
the client does not have to know if release needs
to be called or not.
An alternative would have been to hold a weak ref,
but I deemed it too complicated for the
runtime gain.
PiperOrigin-RevId: 290231659
This fixes an issue where a DownloadService implementation
that allows foreground but doesn't provide a scheduler would
not be restarted in the case that it was still in memory but
classed as idle by the platform.
It also speeds up service restart in the case that a
scheduler is provided.
Issue: #6798
PiperOrigin-RevId: 290068960
This method has two use cases:
1. Seeking. Calls are immediately preceded by a call to rewind(), and
the returned value isn't important unless it's ADVANCED_FAILED (i.e.
the caller is only interested in success and failure).
2. Advancing. The return value is important unless it's ADVANCED_FAILED,
in which case the caller wants to treat it as 0.
This change creates separate methods for each use case. The new seekTo
methods automatically rewind and return a boolean. The updated advanceTo
method returns 0 directly in cases where ADVANCED_FAILED was returned.
Arguments that were always hard-coded to true by callers have also been
removed.
This change is a step toward one possible solution for #6155. How we'll
solve that issue is still up for discussion, but this change seems like
one we should make regardless!
Issue: #6155
PiperOrigin-RevId: 290053743
- DownloadManagerHelper now passes all downloads to the
DownloadService when the service is attached (and once
the downloads are known). The service then starts the
foreground notification updater if necessary. This fixes
the ref'd issue.
- Don't call getScheduler() if the service is background
only. This was already documented to be the case on the
DownloadService constructor.
- If the service is started in the foreground on SDK level
26 and higher, satisfy the condition to move the service
to the foreground in onStartCommand rather than in stop().
It's much more obviously correct, and should produce the
same end result.
Issue: #6798
PiperOrigin-RevId: 290050024
Currently the following sequence of events happens at automatic period transitions:
1. Update queue (=release old playing period)
2. Disable unused renderers
3. Enable newly needed renderers
This order requires difficult to follow workarounds in AnalyticsCollector for all
events related to step 2 (disable renderers). The current media period has already
been advanced so can't be used. The current workaround saves the last known playing
media period that was published as part of a PlaybackInfo update in ExoPlayerImpl.
This works in most cases, but is inherently wrong because the published state in
ExoPlayerImpl may be completely unrelated to the updates happening on the playback
thread (e.g. if many other operations are pending).
Simplify and fix this problem by changing the order of the events above:
1. Disable unused renderers.
2. Update queue
3. Enable newly needed renderers.
This way the current playing media period can be used for both renderer disable
and renderer enable events, thus it's correct in all cases and the workaround
in AnalyticsCollector can be removed.
PiperOrigin-RevId: 290037225
Whenever we set the maskingWindowIndex, we also need to set the masking period index
and the masking position. Otherwise it may cause exception when the period index
is used together with the masking timeline.
PiperOrigin-RevId: 290036973
This optimization allows a ChunkSampleStream to output track
formats as soon as they're parsed during an InitializationChunk
load, rather than waiting until after the InitializationChunk
load is completed.
In DASH VOD, a single InitializationChunk typically loads the
moov and sidx atoms in that order. Hence for long form content
where the sidx is a non-trivial size, this may result in the
track formats being output a non-negligible period of time
sooner than was previously the case. This allows downstream
renderers to start codec initialization sooner, potentially
decreasing startup latency.
For a single test stream on a fast & stable network, this
pretty consistently reduced elapsed time until both audio and
video codecs have been initialized from ~0.5s to ~0.3 seconds
on a Galaxy S8. For 5 test runs without and with these patches,
the eventTime logged by EventLogger for the second decoder
init were:
Without (secs): 0.47 0.47 0.45 0.48 0.46
With (secs) : 0.32 0.33 0.34 0.31 0.40
PiperOrigin-RevId: 289845089
The current order of operations means that the Format is only passed
to the chunk's output after the DataSource has been opened. This
means that establishing the network connection and the downstream
renderers initializing their codecs are effectively serialized to
occur one after the other.
In the new order, the Format is passed to the chunk's output before
the DataSource has been opened. This allows the downstream renderers
to initialize their codecs in parallel with the network connection
being established, and hence latency at the start of playback is
reduced.
PiperOrigin-RevId: 289841854
We currently have a currentMediaPeriodId and an activeSessionId that are more
or less tracking the same thing unless the current media period isn't "active" yet.
Simplify this logic by using a single currentSessionId field and the respective
isActive flag of this session. Also move all session creation and activation code in
the same method to make it easier to reason about the code.
This change also fixes a subtle bug where events after a seek to a new window
are not ignored as they should.
PiperOrigin-RevId: 289432181
As discovered whilst investigating #6798, there are cases
where these methods are not correctly. They were added as
convenience methods that could be overridden by concrete
DownloadService implementations, but since they don't work
properly it's preferable to require application code to
listen to their DownloadManager directly instead.
Notes:
- The original proposal to fix#6798 stored the state change
events in memory until they could be delivered. This approach
is not ideal because the events still end up being delivered
later than they should be. We also want to fix the root cause
in a different way that does not require doing this.
- This change does not fix#6798. It's a preparatory step.
Issue: #6798
PiperOrigin-RevId: 289418555
This change makes it clear the SampleQueue doesn't outlive
the wrapping PlayerTrackEmsgHandler, and releases it from
PlayerTrackEmsgHandler.release().
This change is a no-op because calling release() is the
same as reset() in this case (the behavior only differs if
a non-dummy DrmSessionManager is being used).
PiperOrigin-RevId: 289416622
As a result, onMediaChunkLoadStarted gets invoked on the loading thread, and
init on the playback thread, matching the thread access comments.
Issue:#6321
PiperOrigin-RevId: 289167981
Dash live streams require that the client has an accurate wall clock
time and in absence of a UTCTiming element, this is assumed to be the
NTP time.
This change adds NTP time offset resolution for DASH live streams
without such timing elements.
PiperOrigin-RevId: 289098796
Unfortunately devices such as the MI 8 do not provide an alternative
working decoder. Some Vivo devices do provide one though.
PiperOrigin-RevId: 288911897
This improves readability by making clearer that reading no bytes from
the input in readFrames() is an expected case if the buffer is full.
PiperOrigin-RevId: 288711841
Currently, seeks are only tracked if both the start and the end of the seek
is within the same window. This means no seeking state is reported if the
playback switches to a new window during the seek.
This problem is fixed by tracking seek start and end events in all cases,
but only report seeking state once the window becomes the foreground window.
PiperOrigin-RevId: 288706674
These make the interesting bits of each assertion harder to follow imo.
Also remove all the assertWithMessage() calls at the same time, Olly
convinced me these are rarely useful since you can click from the stack
trace to the failing line in the IDE.
PiperOrigin-RevId: 288470704
- Simulate IO exceptions in the test using FlacBinarySearchSeeker for
seeking in FlacExtractorTests. This makes the test slower but covers
more test cases.
PiperOrigin-RevId: 288285057
There's currently no rendering support for ruby text in SubtitleView
or SubtitlePainter, but this does have a visible impact with the
current implementation by stripping the ruby text from Cue.text
meaning it doesn't show up at all under the 'naive' rendering.
This is an improvement over the current behaviour of including
the ruby text in-line with the base text (no rubies is better than
wrongly rendered rubies).
PiperOrigin-RevId: 288280416
This typo was introduced in ddb70d96ad
when migrating a static method with parameter `durationUs` to an
instance method where the correct field to use was `blockDurationUs`
(but `durationUs` also exists).
The test that catches this was only added in 45013ece1e (and
therefore configured with the wrong expected output data).
issue:#6833
PiperOrigin-RevId: 288274197
It's not used. I was trying to work out how to correctly cascade my
text-combine-upright styling, but deleting the method seemed easier...
PiperOrigin-RevId: 287989480
I decided the flags bit was a bit unclear so I played around with this
It's also needed for more 'complex' assertions like colors - I didn't
want to just chuck in a fourth int parameter to create:
hasForegroundColorSpan(int start, int end, int flags, int color)
PiperOrigin-RevId: 287989424
Relying on the precedence of spans seems risky - I can't find it
defined anywhere. It might have changed in Android 6.0?
https://stackoverflow.com/q/34631851
PiperOrigin-RevId: 287989365
-- Optimize Mp4Extractor for AC-4
-- Optimize FragmentedMp4Extractor for AC-4
-- Add test case for AC-4 in MP4
-- Add test case for AC-4 in Fragmented MP4
It's unreliable for at least one IMA ADPCM file I've found.
Calculating the blockIndex to seek to using exact properties
also seems more robust.
Note this doesn't change anything for the existing PCM test,
since averageBytesPerSecond is set correctly. It does make
a difference for an upcoming IMA ADPCM test though.
PiperOrigin-RevId: 287814947
An experiment with this algorithm didn't show positive results. We can
therefore keep the simpler default algorithm.
Startblock:
<unknown commit> is submitted
PiperOrigin-RevId: 287807538
Where media segments are specified using byte ranges, it makes
sense that a server might return 416 (which we don't consider
for blacklisting) if the segment is unavailable, rather than
the 404 (which we do consider for blacklisting) that we expect
when media segments are only specified using a URL.
Issue: #6775
PiperOrigin-RevId: 286620698
The Download constructor considers it invalid to have a failure
reason if the download isn't in the failed state. Unfortunately,
calling DefaultDownloadIndex.removeAllDownloads when there's a
failed download will change the state without clearing the reason.
If the downloads are then read back from the DefaultDownloadIndex
we end up violating the Download constructor assertion.
This change clears the failed reason for any existing rows in the
invalid state, and also fixes the root cause that allows invalid
rows to enter the table in the first place.
Issue: #6785
PiperOrigin-RevId: 286576242
Without this @Nullable, potential subclasses can't override the
method to return null if they don't want to use the renderer as a
media clock.
Issue:#6792
PiperOrigin-RevId: 286545736
This class is only used to hold temporary data while we parse the
settings and text, so we don't need it outside the Parser class.
Also remove all state from WebvttCueParser - this increases
the number of allocations, but there are already many
and subtitles generally aren't very frequent (compared to
e.g. video frames).
PiperOrigin-RevId: 286200002
Add support for MP3 as an encoding format for passthrough.
This change does not change the observable
behavior of Exoplayer.
Also name the magics.
#exo-offload
PiperOrigin-RevId: 286146539
*** Original commit ***
Move getting-stuck-prevention into DefaultLoadControl.
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a LoadControl lets playback get stuck. This includes the case where
DefaultLoadControl reaches its maximum buffer size and not even a mim...
***
PiperOrigin-RevId: 286071115
We recently added code that prevents getting stuck if the buffer is low and
the LoadControl refuses to continue loading (b84bde0252).
Move this logic into DefaultLoadControl to keep the workaround, and also apply the
maximum buffer size check in bytes if enabled. ExoPlayerImplInternal will now
throw if a LoadControl lets playback get stuck. This includes the case where
DefaultLoadControl reaches its maximum buffer size and not even a mimimal buffer
duration.
PiperOrigin-RevId: 285979989
This offset allows to improve the calculated live offset because it
can take known client-server time offsets into account.
PiperOrigin-RevId: 285970738
I want to add fields related to vertical text support, and neither
adding another constructor nor updating all call-sites of existing
constructors seemed like attractive propositions.
PiperOrigin-RevId: 285956024
- Remove duplicated null assignments
- Move mediaCryptoRequiresSecureDecoder reset to be with all the
other mediaCrypto stuff.
PiperOrigin-RevId: 285955134
MultiLockAsyncMediaCodecAdapter is an implementation of the
MediaCodecAdapter that uses multiple locks to synchronize access to its
data compared to the single-lock approach used in
DedicatedThreadAsyncMediaCodecAdapter.
PiperOrigin-RevId: 285944702
- Make extractor output samples that are uniformly distributed
with respect to time, with a target of ~10 samples per second.
The old approach could in theory put every frame into its own
sample, which would be very inefficient downstream because we'd
need to pass them individually to MediaCodec. It could also put
data corresponding to a long duration of time into a single
sample (e.g. if the sample rate of the content is low), which
is bad downstream because we decide whether to set the decodeOnly
flag on a per sample basis. More generally, the new approach
is more predictable :).
- Stop using the WavSeekMap to get sample timestamps, and instead
calculate them directly from the number of frames output. It's
more obviously correct, particularly for data formats like IMA
ADPCM where we'll need to adjust the data prior to output.
PiperOrigin-RevId: 285750010
In MatroskaExtractor, if the last cue time exceeds the duration
specified in the header, then we end up generating a negative
duration chunk as the last item in the SeekMap. We should probably
not do this, so drop it instead.
Note: Matroska does have a CueDuration element, but it's not used
in the one problematic file I've found.
PiperOrigin-RevId: 285738418
Currently, resetting the internal state related to the codec in done in 4 places
in MediaCodecRenderer:
1. In the constructor to set some sensible initial default.
2. In flushOrReleaseCodec to reset state after flushing
3. In releaseCodec to reset state to default values for a released codec.
4. In initCodec to reset state to defaul values for a new codec.
There are actuall only two types of state reset operations:
1. Resetting state for a released codec, so that a new codec isn't influenced by
previous codecs.
2. Resetting state after flushing an existing codec. This is a subset of (1).
So to simplify the class, this change moves all state resets to two methods
corresponding to the two cases above.
PiperOrigin-RevId: 285731913
These are transitively provided by testutil's build.gradle.
This makes the core module consistent with the others like ui, hls, dash
PiperOrigin-RevId: 285729566
This may happen for example when trying to load unfinished live media
chunks that can only be loaded at real-time playback speed.
The flag can be used by the sources to indicate that network transfer
will knowingly be throttled, such that transfer listeners like the
bandwidth meter can take this information into account.
PiperOrigin-RevId: 285397100
Also change IcyInfo.rawMetatadata from String to byte[]
ICY doesn't specify the character encoding, and there are streams
not using UTF-8 (issue:#6753). It seems the default of at least one
server is ISO-8859-1 so let's support that as a fallback:
https://github.com/savonet/liquidsoap/issues/411#issuecomment-288759200
Also update IcyDecoder to skip strings it doesn't recognise at all
instead of decoding invalid characters.
The feed from issue:#6753 now decodes accents correctly:
EventLogger: ICY: title="D Pai - Le temps de la rentrée", url="null"
PiperOrigin-RevId: 285388522
We previously used Locale.fromLanguageTag and then toLanguageTag to automatically
filter out invalid tags and to replace deprecated tags. However, this only works
for API 21+.
This change does no longer rely on the platform methods and instead:
1. Keeps invalid tags as they are. This may help if developers rely on
non-spec-complaint language tags (for example, #6681).
2. Adds a list of deprcated tags and their modern replacements to our code
3. Normalizes some short codes that have been superseded by macrolanguage codes by
their macrolanguage equivalent.
Issue:#6681
PiperOrigin-RevId: 285384841
This has been broken since
c3d6be3afd
and broken for ICY (where I noticed the problem) since
5695bae9d8.
ICY symptom is that we see no repeated metadata, because the
Icy-MetaData:1 header doesn't make it to the server so we never get back
icy-metaint.
PiperOrigin-RevId: 285379234
The presentationTimeOffsetMs may be C.TIME_UNSET for VOD content
and shouldn't be used in calculations for the windowStartTime.
PiperOrigin-RevId: 285363095
Retrieve the sample number in the extractor instead of passing a holder
to FlacBinarySearchSeeker. This change makes the code easier to
understand and is required to implement the seeking from the seek table.
PiperOrigin-RevId: 285241862
- WavHeader is now immutable and contains only values parsed out
of the WAVE FMT chunk. It no longer contains a C.PcmEncoding
encoding, or mutable data bounds.
- WavHeaderReader now parses the WAVE header chunks without any
additional logic (e.g. validating the block alignment value,
which is format type dependent).
- The SeekMap part of WavHeader is split out into WavSeekMap.
PiperOrigin-RevId: 285232498
This returns the current offset to the live edge. The calculation is
non-intuitive enough to provide this convenience method.
PiperOrigin-RevId: 285171090
This avoids needing to jump through type paremeter hoops to create a
sub-classable Cue.Builder.
Cue should have a standard set of fields, because it will be
consumed by renderers that don't know what type it is. The
existing subclass fields are only used inside their respective
packages, so can be part of a wrapper object instead.
This lays the groundwork for converting Cue's multiple constructors
into a Builder pattern.
PiperOrigin-RevId: 284992135
Keyframe was rendered rather than skipped when performing
an exact seek to a non-zero position close to the start of
the stream.
PiperOrigin-RevId: 284798460
The nullness checker complains about Integers with @IntDef annotations
so replace pairs with custom pair types for the timed event records in
PlaybackStats.
PiperOrigin-RevId: 284731834
Caveats:
- Block additional data is ignored if the block is laced
and contains multiple samples. Note that this is not
a loss of functionality (SimpleBlock cannot have block
additional data, and lacing was previously completely
unsupported for Block)
- Subrip and ASS samples are dropped if they're in laced
blocks with multiple samples (I don't think this is
valid anyway)
Issue: #3026
PiperOrigin-RevId: 284545197
This change constrains the use of sample state member variables to
writeSampleData, finishWriteSampleData and resetWriteSampleData.
Using them elsewhere gets increasingly confusing when considering
features like lacing in full blocks. For example sampleBytesWritten
cannot be used when calling commitSampleToOutput in this case
because we need to write the sample data for multiple samples
before we commit any of them.
Issue: #3026
PiperOrigin-RevId: 284541942
Refator to lift a method to create (and destroy) the OnFrameRenderedListenerV23() and split destroying the Handler from removing the MediaCodec onFrameRenderedListener to avoid double call to codec.setOnFrameRenderedListener()
This makes the format metadata null (instead of an empty Metadata
object) when it is not provided, and is therefore consistent with the
other extractors behavior.
PiperOrigin-RevId: 284171148
The capture frame rate is currently available both via Format.metadata
and decoded in Format.frameRate. As the container Format.frameRate may
be useful to apps, only store the capture frame rate in metadata (apps
will need to decode it but can now access the container frame rate too).
PiperOrigin-RevId: 284165711
- Remove "lacing" from member variables. They're used even if
there is no lacing (and the fact that lacing is the way of
getting multiple samples into a block isn't important).
Issue: #3026
PiperOrigin-RevId: 284152447
- Change sampleHasReferenceBlock to a block reading variable, which is
what it is (the distinction didn't matter previously, but will do so
when we add lacing support in full blocks because there wont be a 1:1
relationship any more.
- Move sampleRead to be a reading state variable.
- Stop abbreviating "additional"
Issue: #3026
PiperOrigin-RevId: 284000937
An I/O error could occur while handling the start of an mdta box, in
which case retrying would cause another ContainerAtom to be added. Fix
this by skipping the mdta header before updating container atoms.
PiperOrigin-RevId: 284000715
Saves around 200 lines of code. High level overview:
- Rename SampleQueue to SampleDataQueue.
- Rename SampleMetadataQueue to SampleQueue.
This CL should not introduce behavior changes. The only significant
changes in synchronization should be:
+ Add synchronized keyword to isReady.
- Seems to be necessary.
+ Add synchronized keyword to SampleQueue.sampleMetadata.
- Before this change, SampleQueue.sampleMetadata could acquire the
SampleMetadataQueue lock three times in a single method call.
Other miscellaneous improvements:
+ Put all private methods at the bottom.
+ Move release() to the right category.
PiperOrigin-RevId: 283795844
This parameter is a little confusing, especially as the behaviour
can be surprising if the intended use-case isn't clear. This change
moves the description of the parameter into the class javadoc,
adds context/justification and slims down each method's
javadoc to refer to the class-level.
Related to investigating/fixing issue:#6700
PiperOrigin-RevId: 283724826
Finailzed logic to update the `SampleQueue` write positions (first index) to push these into `HlsMediaChunk` when the track is initially created (from the Extractor output) and as each new chunk is queued to load (`init()` callback).
Add lots of debuging prints that can come out for the final merge.
Code is very close to a clone of `ChunkSampleStream`.
DASH implements this feature, extend the feature for HLS as well. First change just drops video samples.
For demuxed audio the audio samples will continue to play out to match the
dropped video, so need to keep indexes in all the sample queues related to a chunk and discard them all.
This is a minor change ahead of merging a full variant of
https://github.com/google/ExoPlayer/pull/6706, to make
re-buffers less likely.
Also remove variable substitution when parsing
AVERAGE-BANDWIDTH (it's not required for integer attributes)
PiperOrigin-RevId: 283554106
Calls to new Handler() without arguments are deprecated as of the latest Android
version. Replace them by a Util.createHandler call similar to the ones we
already have.
PiperOrigin-RevId: 283532891
Fixes issue:#6700
sample_cbs_truncated.adts test file produced using
`$ split -b 31795 sample_truncated.adts` to remove the last 10 bytes
PiperOrigin-RevId: 283530136
If LoadControl.shouldContinueLoading returns false and the renderers are not
ready for playback using the already buffered data, playback is stuck.
To prevent this situation, we always continue loading if the buffer is almost
empty. We already have a similar workaround for when
LoadControl.shouldStartPlayback returns false even if loading stopped.
Having both workarounds allows playback to continue even if the LoadControl
tries to prevent loading and playing all the time.
PiperOrigin-RevId: 283516750
*** Original commit ***
Improve `Format` propagation within the `MediaCodecRenderer`.
For example, fix handling of pixel aspect ratio changes in
playlists where video resolution does not change.
Issue:#6646
***
PiperOrigin-RevId: 282903626
When transitioning to a new stream in a different format, the audio
processors are reconfigured. After this, they are drained and then
flushed so that they are ready to handle data in updated formats for the
new stream.
Before this change, some audio processors made the assumption that after
reconfiguration no more input would be queued in their old input format,
but this assumption is not correct: during draining more input may be
queued. Fix this behavior so that the new configuration is not referred
to while draining and only becomes active once flushed.
Issue: #6601
PiperOrigin-RevId: 282515359
flush() is guaranteed to be called in all these cases anyway.
Also clarify documentation for AudioProcessor-specific methods that can
change the 'active' flag.
Issue: #6601
PiperOrigin-RevId: 282515255
This simplifies the contract of configure and is in preparation for
fixing a bug where more input can't be queued when draining audio
processors for a configuration change.
Issue: #6601
PiperOrigin-RevId: 282514367
- Move property to DrmSession; it feels like a more natural place
for it to go (and provides greater flexibility).
- Change flags to a boolean.
PiperOrigin-RevId: 281758729
They are all marked with a JavaDoc comment and the @WorkerThread annotation
which is useful if apps are using threading annotations. All other public
methods in the same classes are marked with @AnyThread to avoid the impression
we forgot to annotate them.
PiperOrigin-RevId: 281490301
The current workaround seems to cause compilation errors inside the
testutils module in Android Studio. This seems to fix them.
This doesn't introduce a circular dependency because it's only
the tests in library-core depending on testutils.
PiperOrigin-RevId: 281318192
Note:
- Fixing this uncovers another bug in how audio processor draining
works, so the test playlist still doesn't play correctly after this
change.
- Once we reconfigure the audio sink based on the ExoPlayer Format
rather than the codec MediaFormat in a later change, this change can
be reverted.
Issue: #6601
PiperOrigin-RevId: 281264149
- Make NonNull, which is already the case when using the manager builder.
- Better document PLAYREADY_CUSTOM_DATA_KEY, now that newPlayReadyInstance
is no more.
PiperOrigin-RevId: 281079288
The implementation of writing HDR10+ static metadata assumed that the
application would use default (big endian) byte order for this metadata but
MediaCodec expects the order to match the specification CTA-861.3.
PiperOrigin-RevId: 281050806
Also remove the "do we really need to do this" comment for AAC.
Parsing from codec specific data is likely to be more robust, so
I think we should continue to do it for formats where we've seen
this problem.
Issue: #6648
PiperOrigin-RevId: 280575466
Previously the renderer EOS (aka last frame rendered), was reported as soon
as the last encoded frame was queued in the codec renderer.
This leaded to EOS reported too early.
PiperOrigin-RevId: 280456277
This speeds up downloads where segments have the same URL with different
byte ranges. We limit the merged segments to 20 seconds to ensure the download
progress of demuxed streams is roughly in line with the playable media duration.
Issue:#5978
PiperOrigin-RevId: 280410761
Clear state for one mode when entering the other in both SimpleExoPlayer
and SimpleDecoderVideoRenderer. The latter is redundant for the case of
renderers that are used inside SimpleExoPlayer, but seems nice to have.
- Entering Surface mode means receiving a non-null Surface, SurfaceHolder
or TextureView in SimpleExoPlayer, or a non-null Surface in
SimpleDecoderVideoRenderer.
- Entering VideoDecoderOutputBufferRenderer means receiving a non-null
VideoDecoderOutputBufferRenderer in SimpleExoPlayer and
SimpleDecoderVideoRenderer.
PiperOrigin-RevId: 280155151
This aligns the method naming and Javadoc. The only remaining
inconsistency I can see is that the initial reference count for
DrmSession is 0 rather than 1. Unfortunately I think it's not
trivial to get these aligned, because DefaultDrmSessionManager
relies on being able to do something between instantiation and
the DrmSession starting to open the session. In practice this
doesn't really matter, since DrmSessions will be obtained via the
manager, which does increment thee reference count to 1 to be
consistent with how ExoMediaDrm acquisition works.
PiperOrigin-RevId: 280136574
The handling of times wasn't really clear to me, hopefully this more
exhaustive documentation helps a bit.
Also assert the end timecode is the 'correct' length for the format.
PiperOrigin-RevId: 279922369
To trigger receiving the broadcast it's necessary to idle() the shadow
main looper, which has to be done from the test thread. Therefore this
change removes the send broadcast action and instead sends the broadcast
from the test thread.
PiperOrigin-RevId: 279660935
- This is for consistency with PlayerControlView.
- Also update PlayerNotificationManager notification if shuffle
mode changes. This is for consistency with what happens when
the repeat mode changes. By default the notification will be
unchanged, but custom implementations can extend and then
override createNotification, and given these modes change
infrequently it feels like we can just do this. The alternative
for achieving consistency would be to remove handling of repeat
mode changes.
Issue: #6582
PiperOrigin-RevId: 277925094
This means multiple failures are all logged, instead of the test
stopping when the first assertion fails. Makes tests like this with
lots of independent assertions much easier to work with.
I limited the expect to a single assertCues() call, otherwise
the error message gets very long and is hard to read, but I
still think this is an improvement.
PiperOrigin-RevId: 277523300
Cue's UNSET and null values should be used when the source data
doesn't specify *and* the spec doesn't provide a clear default.
In the WebVTT case, the defaults are clear, so we use them
explicitly.
PiperOrigin-RevId: 277522899
The framework opus decoder discards some samples after a call to
flush(). Because we flush a decoder that is being retained across an
input format change, this means that the start of audio gets truncated
when transitioning to a new opus stream. See also
https://android.googlesource.com/platform/frameworks/av/+/refs/heads/android10-release/media/libstagefright/codecs/opus/dec/SoftOpus.cpp.
Avoid this by recreating opus decoders instead of flushing them. It
seems fine to do this for all opus decoders as reinitialization should
be cheap, OEM-provided implementations may also discard samples and
playback shouldn't be interrupted on reinitialization due to the
downstream AudioTrack buffer.
PiperOrigin-RevId: 277458759
Update it to throw if hasNext() is false, to match Java's Iterator
interface.
This also simplifies the null-checking annotations required
PiperOrigin-RevId: 277059766
Also remove it from all tests, these aren't covered by the null-checker
Covered by the following package-info.java files:
- j/c/g/a/exoplayer2/ext/mediasession/package-info.java
- j/c/g/a/exoplayer2/package-info.java
- j/c/g/a/exoplayer2/offline/package-info.java
- j/c/g/a/exoplayer2/video/package-info.java
- j/c/g/a/exoplayer2/ui/package-info.java
PiperOrigin-RevId: 277038916
*** Original commit ***
Rollback of bf01ff0f60
*** Original commit ***
Use Float.NaN for Cue#DIMEN_UNSET
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it a...
***
PiperOrigin-RevId: 276674142
*** Original commit ***
Use Float.NaN for Cue#DIMEN_UNSET
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it accidentally.
***
PiperOrigin-RevId: 276315786
Float.MIN_VALUE is very close to zero:
"A constant holding the smallest positive nonzero value of type float"
https://developer.android.com/reference/java/lang/Float.html#MIN_VALUE
Float.NaN more clearly conveys this is an invalid number,
and will also more clearly carry over if we do maths on it accidentally.
PiperOrigin-RevId: 276277784
With lots of int comparisons close together, this makes the error
messages much clearer and saves having to manually match up line
numbers.
Also make every @Test just throw Exception
PiperOrigin-RevId: 276079806
Without this, a subtitle track empty edit list used to offset the start of
subtitles is ignored.
Also the current code seems to depend on the order in which
we parse the tracks (audio first means we have gapless info when we parse
video track, while video first we wouldn't).
It's not clear why we can't handle both edit lists & gapless info
PiperOrigin-RevId: 276029744
- Leaving GvrAudioProcessor for now.
- Removing GvrPlayerActivity because it was never released. Also removing
related UI classes. These were released, but it's unlikely anyone would
have been using them directly.
PiperOrigin-RevId: 275822516
*** Original commit ***
Rollback of 4ad4e3e4fc
*** Original commit ***
Rollback of 3b22db33ba
*** Original commit ***
add top-level playlist API to ExoPlayer
Public design doc:
https://docs.google.com/document/d/11...
***
PiperOrigin-RevId: 275813737
ConditionVariable.block(timeout) doesn't work in Robolectric, because it
relies on the system clock which doesn't advance.
PiperOrigin-RevId: 275798281
@MonotonicNonNull is not useful if the variable is final, because it's only
assigned once and guaranteed to keep it's current nullability in the same
way as @MonotonicNonNull ensures it's kept non-null after checking.
This way, the workarounds can also be removed.
PiperOrigin-RevId: 275428656
GlViewGroup doesn't work properly as an actual ViewGroup. For example,
it doesn't support addition of child views after instantiation. This
change turns the class into a renderer, which is also more consistent
with other classes in the package.
PiperOrigin-RevId: 275322295
If an odd resolution is impossible in the specification itself, then we know
that the caller is passing invalid data. Round up on the assumption it's a
rounding error so that playback can proceed.
Issue: #6551
PiperOrigin-RevId: 275226813
Use composition instead.
This makes the null-handling more explicit & complete (previous implementation
tried to prevent null values, but didn't override all mutation methods
e.g. replace(), putIfAbsent() etc.)
PiperOrigin-RevId: 274778513
*** Original commit ***
Remove null-ness of muxedCaptionFormats list
Pre-work for removing HlsMasterPlaylist and HlsPlaylistParser from null-checking
blacklist.
***
PiperOrigin-RevId: 274591502
If a surface was previously passed to the player then an output buffer
renderer was set, we would remove surface callbacks but not clear the
surface on renderers that accept MSG_SET_SURFACE.
PiperOrigin-RevId: 274532266
download calls through to CacheUtil#cache, which handles skipping already downloaded bytes.
It is useful for callers to know that ProgressiveDownloader has this behavior - otherwise, they might reimplement the logic themselves.
I hope this behavior is something that can be part of the public API :)
PiperOrigin-RevId: 274202995
This is a proof of concept for cleanup we should do for all of
our DataSource implementations as we move toward stabilizing
parts of the API.
- Move all XDataSourceFactory classes to be inner classes.
- Remove chained constructors for XDataSourceFactory classes. Keep
required args going through constructors. Use setters for the
rest.
- Not applicable in this case, but we probably want to deprecate
all but the no-arg method for instantiating eac XDataSource
instance (with the all-arg method kept but with the intention
of making it package private).
PiperOrigin-RevId: 274162076
- Verifies that playWhenReady doesn't become true if audio focus
is denied.
- Also verifies there's no suppression reason in this case, because
the denial is permanent rather than temporary.
PiperOrigin-RevId: 274141099
When newIndex overlaps oldIndex with newstarttime < oldstarttime, according to the segNum of endtime
in newIndex and oldIndexLastSegnum to calculate the segmentNumShift.
It's confusing that app:played_color also modifies the colors
that derive from it, but the corresponding setter does not. It
seems generally clearer just to define constants.
PiperOrigin-RevId: 273249557
Move reusable code from LibvpxVideoRenderer to SimpleDecoderVideoRenderer.
Pass outputBuffer to renderOutputBuffer method instead of keeping the reference in the renderer.
PiperOrigin-RevId: 272899549
It's confusing that seekTo(player, windowIndex, positionMs) does
clamping, because it only makes sense if windowIndex is the current
window.
Note: This doesn't actually fix anything (other than code clarity).
In cases where we were passing other windowIndices, we always
passed 0 as the position and so the clamping logic wouldn't have
had any effect.
PiperOrigin-RevId: 272857104
We currently set it to shouldContinueLoading, which isn't correct if
shouldContinueLoading is set to false and we still have an ongoing load.
Change it to also be true if the media period is still loading.
PiperOrigin-RevId: 272823473
This method allows the player to figure out whether we still have an ongoing
load even if LoadControl.shouldContinueLoading returns false.
PiperOrigin-RevId: 272445577
This ensures a more consistent playback behavior no matter if an item is the
first playlist item or a later one. For example, each playlist item gets its
own onRenderedFirstFrame callback and other logic within the renderer that
force renders the first frame more quickly is also triggered.
PiperOrigin-RevId: 272434814
This doesn't change the current behaviour, just adds a clear error message
to the developer with instructions on how to avoid it.
Issue:#6470
PiperOrigin-RevId: 272405556
*** Original commit ***
Modify EventMessageDecoder to return null if decoding fails (currently throws exceptions)
This matches the documentation on MetadataDecoder.decode:
"@return The decoded metadata object, or null if the metadata could not be decoded."
***
PiperOrigin-RevId: 272405287
Created the WakeLockManager for use in SimpleExoPlayer.
Added a setter in SimpleExoPlayer to adjust this functionality.
Issue:#5846
PiperOrigin-RevId: 272176998
This flag is currently merged into Window.isDynamic, which isn't always true
because
1. A window can be dynamic for other reasons (e.g. when the duration is still
missing).
2. A live stream can be become non-dynamic when it ends.
Issue:#2668
Issue:#5973
PiperOrigin-RevId: 271999378
Before: "Unexpected first three bytes of ID3 tag header: 6845556"
After: "Unexpected first three bytes of ID3 tag header: 0x687474"
PiperOrigin-RevId: 271949486
Adding this callback makes sense for completeness (we have similar callbacks
for all other playback state properties), and also to detect audio focus loss
while buffering which would currently trigger no callback because isPlaying
is still false.
Issue:#6203
PiperOrigin-RevId: 271347351
DrmSessionManagers may now be in released state, in which case they
may release their MediaDrm. In that case, it would be invalid to
forward method calls to the underlying MediaDrms. Users should
instead call these methods directly on the MediaDrm.
Issue:#4721
PiperOrigin-RevId: 270963393
This method should be used where we previously checked for active playback
by state==READY and playWhenReady=true. Using the new method ensures we take
audio focus into account for these usages.
Also update some method naming to avoid confusion with the isPlaying method.
Issue:#6203
PiperOrigin-RevId: 270910982
Inline invocations of these methods, which still leaks the MediaDrms.
However, it will be fixed once the DefaultDrmSessionManager API is finalized
and ExoMediaDrm.Providers are introduced.
Issue:#4721
PiperOrigin-RevId: 270681467
Remove the flag DataSpec.FLAG_ALLOW_ICY_METADATA. Instead, set the
header IcyHeaders.REQUEST_HEADER_ENABLE_METADATA_NAME in the DataSpec
httpRequestHeaders.
BUG:134034248
PiperOrigin-RevId: 270662676
In DefaultDashChunkSource.copyWithNewRepresentation, it will handle the logic that
new MPD manifest file is updated and calculate a newSegmentNumShift for furthermore
segNum index calculation in getSegmentUrl, when a shorter window MPD updated and then
back to a longer window MPD, copyWithNewRepresentation will go into the overlap case
but the new index actually contains the old index..
With the internal playlist some new situation may happen that were not possible before:
- handlePlaylistInfoRefreshed in EPII called in IDLE state
- handlePlaylistInfoRefreshed in EPII called in ENDED state with an empty playlist
- seeks in ENDED state with an empty playlist
PiperOrigin-RevId: 270316681
*** Original commit ***
Refactor HlsSampleStreamWrapper#track() to clarify the return paths
I found the original implementation quite hard to follow, and I believe this is functionally identical.
***
PiperOrigin-RevId: 270263186
This option allows to set the preferred text language and role flags based
on the user's accessiblity captioning settings.
Issue:#5749
PiperOrigin-RevId: 270233205
Allows streamlining the way we handle unsupported DRM. In general, either:
* The device does not support the CDM. For example, phones don't support
PlayReady.
* The device does not support the protection scheme. For example, API < 25
devices do not support AES-CBC.
Currently we handle both cases differently. A dummy ExoMediaDrm will allow
the existence of dummy DefaultDrmSessionManagers.
PiperOrigin-RevId: 269315687
Allows shared ownership of ExoMediaDrms. Shared ownership will
allow users to pre-create ExoMediaDrms in their apps, as opposed
to having the DrmSessionManager create the ExoMediaDrm.
Issue:#4721
PiperOrigin-RevId: 269305850
The player may suppress playback when waiting for audio focus even if the
state==Player.READY. There is currently no getter or callback to obtain this
piece of information for UI updates or analytics.
Also, it's a important derived state to know whether the playback position is
advancing. Add isPlaying and the corresponding callback to allow retrieving
this information more easily.
Issue:#6203
PiperOrigin-RevId: 268921721
We currently force render the first frame in all cases. However, when joining
video to an ongoing playback, there is no defined first frame and we should
rather drop frames if we are late until we caught up with the audio playback.
PiperOrigin-RevId: 268698093
When the queue is empty, we may still get multiple requests for a window
sequence number using the same periodUid. We should keep the initially
assigned number because no window change happened.
PiperOrigin-RevId: 268649009
The fLaC prefix is included in the initialization data output
from the MKV extractor, so this is highly likely ot be the
right thing to do.
Issue: #6397
PiperOrigin-RevId: 268244365
This allows to uniquely identify a window within a Timeline. The value is set
correctly for all Window instances, but is not used anywhere yet.
PiperOrigin-RevId: 267556516
We currently don't test if an ad needs to be played in case we are already
playing content.
This is to prevent recreating the current content period when
an ad is marked as skipped. We prefer playing until the designated ad group
position and appending another piece of content. This is less likely to cause
visible discontinuities in case the ad group position is at a key frame
boundary.
However, this means we currently miss updates that require us to play an ad
after a timeline update.
PiperOrigin-RevId: 267553459
Select a track with matching role flags even if someone specifies a preferred role flgs without providing a preferred language
Prefer track without captions or describing music and sound flag when no role flag preference is provided.
Removing this method requires custom MediaSource implementations to switch
to the new version. While this breaks the implmentation, it also avoids problems
with accidentely forwarding to the wrong method or with accidental stack
overflows when none of the two methods gets implemented.
It's unlikely any callers are affected because this is only the extended version
with the defaultProjectionPositionUs parameter that no caller except the
internal player will use.
PiperOrigin-RevId: 267323042
Include Dataspec.httpRequestHeaders in CronetDataSource,
and OkHttpDataSource. Updated documentation of
HttpDataSource.open() to suggest that it should set request
headers (in decreasing priority) from (1) the passed DataSpec,
(2) parameters set with setRequestProperty() and (3) default
parameters set in the HttpDataSource.Factory. No mechanism
has been put in place to enforce this.
PiperOrigin-RevId: 266895574
Sniffing is performed in ProgressiveMediaPeriod even if a single
extractor is provided. Skip it in that case to improve performances.
Issue:#6325
PiperOrigin-RevId: 266766373
The Javadoc for open() won't be read by anyone because it's an overridden method
of the interface and not called directly from application code.
Move doc to class documentation as this is a generic explanation about the
functionality of the class. Also added "all" to clarify that all the parameters
will be added and the order of preference just applies in case of key clashes.
PiperOrigin-RevId: 266753249
This is a no-op interim change to introduce key request error
handling customization. Following changes will allow users to
inject their own LoadErrorHandlingPolicy implementations.
Issue:#6334
PiperOrigin-RevId: 266344399
- Surface information provided by methods isHardwareAccelerated,
isSoftwareOnly and isVendor added in Android Q in MediaCodecInfo
class.
- Estimate this information based on the codec name for earlier API
levels.
Issue:#5839
PiperOrigin-RevId: 266334850
This generalizes our "does file still exist" check to also check
that the file is the expected length. If it's not, we don't trust
it. This avoids infinite recursion in CacheDataSource if a cache
file is truncated underneath the cache.
Issue: #6165
PiperOrigin-RevId: 265707928
Implementations of ForwardingTimeline may override any of the two variants of
this method. We need to ensure that the customized override is always called.
Add back the deprecated method and make it final to forward to the
non-deprecated method in all cases for ForwardingTimelines.
PiperOrigin-RevId: 265419830
The last selection criteria is the audio bitrate to prefer higher-quality
streams. We shouldn't apply this criterium though if the languages of the
tracks are different.
Issue:#6335
PiperOrigin-RevId: 265064756
The implementation can't work properly unless these methods are called by
subclasses, so annotate them to require calling the super implementation when
overriding.
PiperOrigin-RevId: 265017433
The error is closely related to the playback state IDLE and should be updated
in sync with the state to prevent unexpected event ordering and/or keeping the
error after re-preparation.
Issue:#5407
PiperOrigin-RevId: 265014630
Currently the value of FLAG_ALLOW_CACHE_FRAGMENTATION is defined as "1 << 4" but commented as "8". Either the value of FLAG_ALLOW_CACHE_FRAGMENTATION should be "1 << 3", or the comment should be 16. Here I am modifying the comment since it does not affect any current behavior.
PiperOrigin-RevId: 265011839
The app is able to pass a more specialized array type, so the Arrays.copyOf call
produces an array into which it's not valid to store arbitrary AudioProcessors.
Create a new array and copy into it to avoid this problem.
PiperOrigin-RevId: 264779164
This situation happens if the first chunk to load is already behind the end
of the stream. In this case, the preparation never completes because
HlsSampleStreamWrapper gets stuck in a prepared=false and loadingFinished=true
state.
Gracefully handle this situation by attempting to load the last chunk if still
unprepared to ensure that track information is obtained as far as possible.
Otherwise, it wouldn't be possible to play anything even when seeking back.
Issue:#6314
PiperOrigin-RevId: 264599465
Extract supplemental data from block additions in WebM/Matroska.
Allow storing supplemental data alongside samples in the SampleQueue and write
it as a separate field in DecoderInputBuffers.
Handle supplemental data in the VP9 extension by propagating it to the output
buffer.
Handle supplemental data for HDR10+ in MediaCodecVideoRenderer by passing it to
MediaCodec.setParameters, if supported by the component.
PiperOrigin-RevId: 264582805
There is no point in having this parameter as the tag should always be a single
immutable object instantiated at the time the Timeline is created or earlier.
So there is no preformance benefit and it's error-prone in case people
forget to set setTag=true.
PiperOrigin-RevId: 264117041
This solves various issues around event association for buffering and
error throwing around period discontinuities.
The main changes are:
- Logic around being "ready" at the end of a period no longer checks if the
next period is prepared.
- Advancing the playing period no longer checks if the next one is prepared.
- Prepare errors are always thrown for the playing period.
This changes the semantics and assumptions about the "playing" period:
1. The playing period can no longer assumed to be prepared.
2. We no longer have a case where the queue is non-empty and the playing or
reading periods are unassigned (=null).
Most other code changes ensure that these changed assumptions are handled.
Issue:#5407
PiperOrigin-RevId: 263776304
This matches the documentation on MetadataDecoder.decode:
"@return The decoded metadata object, or null if the metadata could not be decoded."
PiperOrigin-RevId: 263767144
Most users are likely to be only interested in the playlist items. So put the
Window definition first and explicitly mention that this is a playlist
item.
PiperOrigin-RevId: 263764515
The current ExoPlayerFactory is growing too big and usage becomes increasingly
complicated because it's not possible to set individual components without
specifying many other defaults.
Adding new builder classes makes building easier and more future-proof.
PiperOrigin-RevId: 263339078
entries are used in .equals(), so it's good to have them printed in toString() too (for test failures) and it makes logging easier too.
PiperOrigin-RevId: 263335503
The current max video buffer is 13MB which is too small for high quality
streams and doesn't allow the DefaultLoadControl to buffer up to its default
max buffer time of 50 seconds.
Also move util method and constants only used by DefaultLoadControl into this
class.
PiperOrigin-RevId: 263328088
We no longer need two modules as AndroidX-Test takes care of the system
abstraction and we no longer have Robolectric Handler/Looper workarounds.
PiperOrigin-RevId: 262363201
I think we need to start clearing the holder as part of the
DRM rework. When we do this, it'll only be valid to read
from the holder immediately after it's been populated.
PiperOrigin-RevId: 262362725
We're no longer tied to the emsg spec, so we can skip unused fields
and assume ms for duration.
Also remove @Nullable annotation from EventMessageEncoder#encode, it
seems the current implementation never returns null
PiperOrigin-RevId: 262135009
We already allow mixed mime type and mixed sample rate adaptation on request,
so for completeness, we can also allow mixed channel count adaptation.
Issue:#6257
PiperOrigin-RevId: 261930046
This also decouples EventMessageEncoder's serialization schema from the emesg spec (it happens to still match the emsg-v0 spec, but this is no longer required).
PiperOrigin-RevId: 261877918
If we keep streams in chunk sources after selecting new tracks, we also keep
a reference to a stale disabled TrackSelection object. Fix this by updating
the TrackSelection object when keeping the stream. The static part of the
selection (i.e. the subset of selected tracks) stays the same in all cases.
Issue:#6256
PiperOrigin-RevId: 261696082
We currently keep the sequence number if we don't reset the position. However,
the sequence number should be kept if we don't reset the state. Otherwise
re-prepare with position reset is counted as new playback although it's still
the same.
PiperOrigin-RevId: 261644924
- When in STATE_SEEK with targetGranule==0, seeking would exit
without checking that the input was positioned at the correct
place.
- Seeking could fail due to trying to read beyond the end of the
stream.
- Seeking was not robust against IO errors during the skip phase
that occurs after the binary search has sufficiently converged.
PiperOrigin-RevId: 261317035
Two tests have very low propability flakiness (1:1000) due to not waiting for
a seek in one case and the chance of already being ended in another case.
Fix these and also adjust wrong comments about state changes.
PiperOrigin-RevId: 261309976
These values can easily default to the empty track group and the empty
selection. As a result we can remove restrictions about not calling
holder.getTrackGroups before the period finished preparation.
PiperOrigin-RevId: 261280927
A previous change switched to calculation of the bitrate based on the
first MPEG audio header in the stream. This had the effect of fixing
seeking to be consistent with playing from the start for streams where
every frame has the same padding value, but broke streams where the
encoder (correctly) modifies the padding value to match the declared
bitrate in the header.
Issue: #6238
PiperOrigin-RevId: 261163904
Android considers ALAC initialization data to consider of the magic
cookie only, where-as FFmpeg requires a full atom. Standardize around
the Android definition, since it makes more sense (the magic cookie
being contained within an atom is container specific, where-as the
decoder shouldn't care what container the media stream is carried in)
Issue: #5938
PiperOrigin-RevId: 261124155
Checking inputPosition == 0 isn't sufficient because the synchronization
at the top of read() may advance the input (i.e. in the case where there's
some garbage prior to the seek frame).
PiperOrigin-RevId: 261086901
This factory was only needed in the past when we didn't have
AnalyticsCollector.setPlayer. Code becomes easier to use without this factory.
PiperOrigin-RevId: 261081860
This new annotation declares everything as non-null by default and can be
used as a package annotation in package-info.java.
In this change the core lib offline package and the mediasession extension is
annotated that way as initial example usage.
PiperOrigin-RevId: 260894548
DefaultMediaClock has currently two non-ideal behaviours:
1. One part of checking if it should use the renderer clock is checking whether
the associated renderer finished reading its stream. This only makes sense
if the renderer isn't already reading ahead into the next period. This can
be solved by forwarding if we are reading ahead to the sync command.
2. When switching from stand-alone to renderer clock we assume they are
exactly at the same position. This is true in theory, but in practise there
may be small differences due to the different natures of these clocks. To
prevent jumping backwards in time, we can temporarily stop the stand-alone
clock and only switch once the renderer clock reached the same position.
PiperOrigin-RevId: 260690468
Both periods are rarely updated in the same iteration. If they are, advancing
the reading period first seems more logical and also more efficient as it may
avoid one extra doSomeWork iteration.
PiperOrigin-RevId: 260463735
When using speed adjustment it was possible for playback to get stuck at a
period transition when the channel count changed: SonicAudioProcessor would be
drained at the point of the period transition in preparation for creating a new
AudioTrack with the new channel count, but during draining the incorrect (new)
channel count was used to calculate the output buffer size for pending data from
Sonic. This meant that, for example, if the channel count changed from stereo to
mono we could have an output buffer size that stored an non-integer number of
audio frames, and in turn this would cause writing to the AudioTrack to get
stuck as the AudioTrack would prevent writing a partial audio frame.
Use Sonic's current channel count when draining output to fix the issue.
PiperOrigin-RevId: 260156541
We keep track of the last publicly known playing period to report it as part
of events happening after the period has been released.
In cases where a period briefly becomes the playing one and is released
immediately afterwards, we currently don't save it as the "last known playing
one". Improve that by saving an explicit reference.
Issue:#5407
PiperOrigin-RevId: 259737218
Creating a period in MaskingMediaSource may result in delayed event reporting
depending on when the actual period gets created. To avoid event reporting
inaccuracies, report the mediaPeriodCreated and mediaPeriodReleased events
directly.
Issue:#5407
PiperOrigin-RevId: 259737170
This changes the logic in the following ways:
- If no preferred language is matched, prefer better scores for the selected
audio language.
- If a preferred language is matched, always prefer the better match
irrespective of default or forced flags.
- If a preferred language score and the isForced flag is the same, prefer
tracks with a better selected audio language match.
PiperOrigin-RevId: 259707430
Some variables were defined although they are the default and other things
were set-up in a non-sensible way, e.g. asserting that audio is selected
although no audio renderer is available, or using unset duration for
everything.
PiperOrigin-RevId: 259532782
PlaybackInfo changes are one of the last ones not masked and reported in the same
way as all other changes.
The main change to support this is to also mask the parameters set in
DefaultAudioSink.
PiperOrigin-RevId: 258787744
1. Using the Locale on API<21 doesn't make any sense because it's a no-op
anyway. Slightly restructured the code to avoid that.
2. API<21 often reports languages with non-standard underscores instead of
dashes. Normalize that too.
3. Some invalid language tags on API>21 get normalized to "und". Use original
tag in such a case.
Issue:#6153
PiperOrigin-RevId: 258773463
2-letter codes (ISO 639-1) are the standard Android normalization and thus we
should prefer them to 3-letter codes (although both are technically allowed
according the BCP47).
This helps in two ways:
1. It simplifies app interaction with our normalized language codes as the
Locale class makes it easy to convert a 2-letter to a 3-letter code but
not the other way round.
2. It better normalizes codes on API<21 where we previously had issues with
language+country codes (see tests).
3. It allows us to normalize both ISO 639-2/T and ISO 639-2/B codes to the same
language.
PiperOrigin-RevId: 258729728
If we use the default start position, we currently resolve it immediately
even if we need to play an ad first, and later try to project forward again
if we believe that the default start position should be used.
This causes problems if a specific start position is set and the later
projection after the preroll ad shouldn't take place.
The problem is solved by keeping the content position as TIME_UNSET (= default
position) if an ad needs to be played first. The content after the ad can
then be resolved to its current default position if needed.
PiperOrigin-RevId: 258583948
These methods helps to indicate that a media source isn't used to create new
periods in the immediate term and thus limited resources can be released.
PiperOrigin-RevId: 258373069
It's easy to forget to forward methods when using basic wrapping. For example,
ExtractorMediaSource.addEventListener is currently a no-op because it's not
forwarded.
PiperOrigin-RevId: 257757556
This is a temporary workaround until we have migrated all MediaSources uses.
This change avoids having to migrate all uses of MediaSources immediately.
PiperOrigin-RevId: 257459138
- Remove manifest argument from callbacks of Player.EventListener and
SourceInfoRefreshListener. Instead make it accessible through
Player.getCurrentManifest() and Timeline.Window.manifest.
- Fix all MediaSource implementation to include the manifest in the
Timeline instead of passing it to the SourceInfoRefreshListener.
- Refactor ExoPlayerTestRunner, FakeTimeline, FakeMediaSource to
reflect these changes and make tests pass.
PiperOrigin-RevId: 257359662
Sending MESSAGE_PREPARE_SOURCE should happen last in the constructor.
It was previously happening before initialization finished (and in
particular before pendingMediaPeriods was instantiated).
Issue: #6146
PiperOrigin-RevId: 257158275
We currently handle most the control code logic after handling special
characters. This includes filtering out repeated control codes and checking
for the correct channel. As the special character sets are control codes as well,
these checks should happen before parsing the characters.
Issue:#6133
PiperOrigin-RevId: 256993672
- Explicitly specify HTTP_METHOD_POST (previously this was
implicit as a result of the body data being non-null)
- Use null when there's no body data (it's converted to
null inside of the DataSpec constructor anyway)
PiperOrigin-RevId: 256573384
Currently, we sometimes apply new playback parameters directly and sometimes
through the list of playbackParameterCheckpoints. Only when using the checkpoints,
we also reset the offset and corresponding position for speedup position
calculation. However, these offsets need to be changed in all cases to prevent
calculation errors during speedup calculation[1].
This change channels all playback parameters changes through the checkpoints to
ensure the offsets get updated accordingly. This fixes an issue introduced in
31911ca54a.
[1] - The speed up is calculated using the ratio of input and output bytes in
SonicAudioProcessor.scaleDurationForSpeedUp. Whenever we set new playback
parameters to the audio processor these two counts are reset. If we don't reset
the offsets too, the scaled timestamp can be a large value compared to the input
and output bytes causing massive inaccuracies (like the +20 seconds in the
linked issue).
Issue:#6117
PiperOrigin-RevId: 256533780
The masking logic for unprepared MediaSources is currently part of
ConcatanatingMediaSource. Moving it to its own class nicely separates the
code responsibilities and allows reuse.
PiperOrigin-RevId: 256360904
1. Only output video starting from a keyframe
2. When calculating the timestamp offset to adjust live streams to start
at t=0, use the timestamp of the first tag from which a sample is actually
output, rather than just the first audio/video tag. The test streams in
the referenced GitHub issue start with a video tag whose packet type is
AVC_PACKET_TYPE_SEQUENCE_HEADER (i.e. does not contain a sample) and whose
timestamp is set to 0 (i.e. isn't set). The timestamp is set correctly on
tags that from which a sample is actually output.
Issue: #6111
PiperOrigin-RevId: 256147747
The total window and period count, as well as the period offset for each holder
are not actually needed and can be removed.
Also added a TODO to remove two other variables if possible.
PiperOrigin-RevId: 255945584