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
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