- SimpleExoPlayer now always generates a session ID at
construction time. This ID is used indefinitely, including
for tunneling, unless a call to setAudioSessionId is made
to change it.
- DefaultTrackSelector support for enabling tunneling has
been changed to a boolean, since tunneling now uses the
same session ID as non-tunneled mode.
- Since the session ID is now always set at the top level,
internal propagation of generated session IDs is no longer
necessary, and so is removed.
PiperOrigin-RevId: 351349687
Whether a resource resolves to a known length or not is more than just
a property of the resource & data source - for example if
`DataSpec.flags` contains `ALLOW_GZIP` then the length might be
unresolved. More generally, a `DataSource` could randomly return
`C.UNKNOWN_LENGTH` from `open()` 50% of the time and still fulfil the
`DataSource` interface. This makes it ~impossible to write a meaningful
assertion aroun this.
So this change relaxes the assertion slightly to more closely match the
definition of the `DataSource` interface.
We leave the `resolveToUnknownLength` toggle in
`WebServerDispatcher.Resource` because this is still useful for
simulating the case of a server that is serving a file it doesn't
know the length of.
PiperOrigin-RevId: 351124246
BatchBuffer has three different clear methods (clear, flush,
batchWasConsumed), and it's not hugely clear what each of them
does. In general, BatchBuffer owning the sample buffer seems
more complicated than having the caller own it, particularly
when it can be "pending" inside of the batch buffer.
This change moves ownership of the sample buffer to the
caller. BatchBuffer is simplified as a result. There are also
two behaviour changes:
1. The buffer's timeUs field is now set to the first sample's
timestamp, rather than the last sample's.
2. A key-frame in the middle of the batch no longer causes the
batch buffer to be considered a key-frame. Which seems like
the right thing to do, because the batched data cannot be
decoded independently of whatever came before it.
PiperOrigin-RevId: 350921306
Without this feature it's impossible to nicely merge multiple sources
with different durations if these durations are not known exactly
before the start of playback.
Issue: #8422
PiperOrigin-RevId: 350567625
This allows to set preferences based on MIME type for video and audio.
The MIME type preference is applied after other explicit preferences
and restrictions (e.g. language or max resolution), but before implicit
preferences like bitrate.
Issue: #8320
PiperOrigin-RevId: 350550543
Add assertion to check an output format has been propagated before
returning an output buffer when operating MediaCodec in asynchronous
mode.
PiperOrigin-RevId: 350534918
The experimental setting shows positive results and can be turned
on by default. To avoid adaptation between HLS audio formats without
bitrates, we need to ensure that only formats with bitrates are
considered for adaptation.
Also added tests for these features.
Issue: #5111
PiperOrigin-RevId: 350315296
The AsynchronousMediaCodecCallback has logic to retain a pending
output format in case flush() is called. This commit fixes a case where
calling flush() again while an output format is pending would nullify
the pending output format.
A unit test is added in AsynchronousMediaCodecCallback but not the
AsynchronousMediaCodecAdapter. That is because the adapter operates
directly on top of MediaCodec, but Robolectric's ShadowMediaCodec
produces an output format on every MediaCodec.start(). This is
unrealistic when operating MediaCodec in asynchronous mode where we
need to call MediaCodec.start() after every MediaCodec.flush().
PiperOrigin-RevId: 350176659
- The AdaptiveTrackSelection doesn't need to use the experimental
terminolgy because the code is always triggered if there are multiple
adaptive selections.
- It's also confusing to pass the state on the outside after the object
creation, so moving everything into a simple control flow again where
the adaptation checkpoints are passed in via the constructor.
- Instead of triple arrays, we can use more readable named structures.
- The calculation of the checkpoints can be cleaned up to be more
readable by moving things to helper methods.
- The reserved bandwidth from all fixed track selections is really just
a special case of multiple parallel adaptataions. So this logic doesn't
need to be separate.
- The whole logic also didn't have test coverage so far. Added tests
for the actual adaptation using these checkpoints and the builder
calculating the checkpoints.
Overall this should be a no-op change.
PiperOrigin-RevId: 350162834
*** Original commit ***
DataSource.open() throws if already opened.
Update DataSource implementations to throw an error if open() is called
when the DataSource is already open.
***
PiperOrigin-RevId: 348783425
This replaces all the duplicated logic previously implemented in
FakeSampleStream and more closely follows the pattern of how
SampleStreams are used from real MediaPeriods.
Some tests needed adjustments because using real the SampleQueue
improved behaviour:
- Waiting for isLoading is only needed once even across period
boundaries because the real SampleQueue doesn't have the on/off
pattern.
- AnalyticsCollectorTest.playlistOperations() was wrongly asserting
that some pre-buffering events. The new version is more intuitively
correct we pre-buffer the second item during the initial loading
phase (thus period1seq1) and keep the buffer in the queue after
the removal operation.
PiperOrigin-RevId: 348440255
I decided not to migrate all the tests in one CL to keep the diff
manageable. I'll make follow-up CLs to migrate the tests, and eventually
delete TeeCodec and all associated logic.
I couldn't completely remove the dump diff because
ShadowMediaCodec.getCodecInfo() (which would give me access to the MIME
type) doesn't seem to work properly - it returned video/avc when
name=exotest.audio.aac, and looking into the code it looks like there's
some native methods that are missing shadow implementations.
PiperOrigin-RevId: 347991956
The adaptive period currently extends the base (non-adaptive) period
to share common MediaPeriod boilerplate code.
However, once we start using the real SampleQueue in FakeMediaPeriod
the common code becomes even less and the overhead to support
multiple stream implementation from the base class is no longer
worth it. Thus, this change removes the class hierarchy and copies
the common parts to FakeAdaptiveMediaPeriod.
PiperOrigin-RevId: 347990468
This was added due to a misunderstanding - we're more interested in
testing the edge case of trying to read the last zero bytes of a
non-zero-byte resource.
In a future change I want to be able test reading a subrange, so each
TestResource will need to be at least N bytes long.
PiperOrigin-RevId: 347980843
PlaybackStatsListener has a method whose original intention was to be
called when the player is releaed to finish all pending sessions.
However, this also meant that later events (e.g. onVideoDecoderDisabled)
could create new sessions because the old one was already finished.
Use the new onPlayerReleased callback to implement this properly and to
fix the unintentional new session creation.
PiperOrigin-RevId: 347809527
Currently we don't remove the AnalyticsListeners registed to
SimpleExoPlayer after calling release. We didn't do this mainly
because there are messages triggered as part of the release that
still cause interesting events (e.g. decoderDisabled with the
final counters, final dropped counts etc).
However, we should fully release/remove the listeners once these
pending events are delivered to:
1. Not leak listener implementations (e.g. if the listener is an
Activity)
2. Ensure we don't send future events that may cause listeners
to unintentionally access released or nulled variables. This
could happen for example if someone calls a player method
after the player was released.
In addition, we can add a onPlayerReleased callback to
AnalyticsListener to allow implementations to clean themselves up
once all pending events are delivered.
PiperOrigin-RevId: 347434344
When a listener is removed or released we may not have called
onEvents for events that happened before this point. To ensure
listeners don't miss events we need to trigger a final onEvents
with all events we have happened so far (if any).
PiperOrigin-RevId: 346553030