- Move to builder naming.
- Propagate formats to the TrackOutput instances, rather than having
them be read through the Extractor. There was actually some weird
indexing going on here before (which happened to work, but wasn't
well defined).
As per http://tools.ietf.org/html/draft-pantos-http-live-streaming-04#section-5.2,
the initializaton vector (IV) of the AES decryption algorithm should be set to:
- the IV attribute value if present,
- the sequence number otherwise.
Currently, the IV is set once and use over all next media sequences
where the IV attribute is not set. The fix is to use the provided IV if
given or use the current media sequence number.
- It's probably easiest to think of this as a standalone HLS change, which is splitting out the "loading" and "consuming" sides of HlsExtractor and a good structural change in its own right. To do this, HlsExtractorWrapper becomes a final class implementing the consuming side. HlsExtractor becomes an interface defining the loading side.
- The bigger picture is that, hopefully, HlsExtractor will become a lightweight extractor interface that can be used throughout the library. Because it doesn't need to implement the consuming side, we'll save on having to re-implement the consuming side for every extractor (we'll probably need one consuming side implementation for HLS/DASH/SmoothStreaming, and a second one for everything else, both of which will use SampleQueue). It's expected that the HlsExtractor interface will need to change to accommodate all use cases.
- The next step in unification will be to try and have FragmentedMp4Extractor implement HlsExtractor (which will need renaming). Once this is done, I'll try and move the chunk package over to use the HlsExtractor interface.
- This is a step toward hopefully converging HLS and CHUNK packages.
- Add support for encrypted samples.
- Add support for appending from a DataSource.
Also remove uriIsFullStream. It's not doing anything particularly
useful, so I think it makes sense to remove it from the public API;
it's unlikely anyone is using it.
Issue: #329
Note: I'm fairly confident that NetworkLoadable.Parser implementations
can live without the inputEncoding being specified. But not completely
100%...
Issue: #311
Issue: #56
Clear stale blacklist in getChunkOperation before getting next variant.
This ensures:
1.- Player resilience to failures, always trying to look for a working
playlist that allows player to non stop playback.
2.- High quality blacklisted playlists can be reused in case they go up
after a failure. Player always trying to provide the best user
experience.
Added an expiration time field to playlists blacklisted to allow
Exoplayer to continue playback when playlists that failed were
recovered from a bad state.
In live environments, some times occur that primary encoder stop
working for a while. In that cases, HLS failover mechanism in the
player should detect the situation and “switch” to playlists served by
the backup encoder (in case a backup encoder exists). This was well
managed before these changes.
However, and to ensure a playback experience that can recover itself
from temporary issues, we cannot blacklist a playlist forever. When
streaming live events using HLS, it is quite typical that the player
needs to switch from primary to backup playlists, and from backup to
primary ones, from time to time to have playback working when temporary
issues in the network/encoder are happening. Most of the issues are
recoverable, so what I have implemented is a mechanism that makes
blacklisted playlist to be available again after a while (60 seconds).
Evaluation of this algorithm should happen just when something fails.
If player is working with a backup playlist, it shouldn’t switch to the
primary one at least something fail.
- Data needs to be unescaped before it's passed to SeiReader.
- SeiReader should loop over potentially multiple child messages.
- I also changed the sample passed to the EIA-608 renderer so that
it's the entire sei message payload. The first 8 bytes are
unnecessary, but it seems nicer conceptually to do it this way.
Issue: #295
Previous regular expression for extracting codec information was wrong,
given a line that defines a variant it added information from “CODEC=“
text to the end of the line (including also information about
RESOLUTION or alternate rendition groups as part of the CODEC field).
This is not causing a functional problem (at least known by me)
although is making codecs field storing information that is not related
with the codec.
- This change:
1. Extracts HlsExtractor interface from TsExtractor.
2. Adds AdtsExtractor for AAC/ADTS streams, which turned out to be
really easy.
Selection of the ADTS extractor relies on seeing the .aac extension.
This is at least guaranteed not to break anything that works already
(since no-one is going to be using .aac as the extension for something
that's not elementary AAC/ADTS).
Issue: #209
I think this is the limit of how far we should be pushing complexity
v.s. efficiency. It's a little complicated to understand, but probably
worth it since the H264 bitstream is the majority of the data.
Issue: #278
Use of Sample objects was inefficient for several reasons:
- Lots of objects (1 per sample, obviously).
- When switching up bitrates, there was a tendency for all Sample
instances to need to expand, which effectively led to our whole
media buffer being GC'd as each Sample discarded its byte[] to
obtain a larger one.
- When a keyframe was encountered, the Sample would typically need
to expand to accommodate it. Over time, this would lead to a
gradual increase in the population of Samples that were sized to
accommodate keyframes. These Sample instances were then typically
underutilized whenever recycled to hold a non-keyframe, leading
to inefficient memory usage.
This CL introduces RollingBuffer, which tightly packs pending sample
data into a byte[]s obtained from an underlying BufferPool. Which
fixes all of the above. There is still an issue where the total
memory allocation may grow when switching up bitrate, but we can
easily fix that from this point, if we choose to restrict the buffer
based on allocation size rather than time.
Issue: #278
- Remove TsExtractor's knowledge of Sample.
- Push handling of Sample objects into SampleQueue as much
as possible. This is a precursor to replacing Sample objects
with a different type of backing memory. Ideally, the
individual readers shouldn't know how the sample data is
stored. This is true after this CL, with the except of the
TODO in H264Reader.
- Avoid double-scanning every H264 sample for NAL units, by
moving the scan for SEI units from SeiReader into H264Reader.
Issue: #278
Reordering in the extractor isn't going to work well with the
optimizations I'm making there. This change moves sorting back
to the renderer, although keeps all of the renderer
simplifications. It's basically just moving where the sort
happens from one place to another.
1. AdtsReader would previously copy all data through an intermediate
adtsBuffer. This change eliminates the additional copy step, and
instead copies directly into Sample objects.
2. PesReader would previously accumulate a whole packet by copying
multiple TS packets into an intermediate buffer. This change
eliminates this copy step. After the change, TS packet buffers
are propagated directly to PesPayloadReaders, which are required
to handle partial payload data correctly. The copy steps in the
extractor are simplified from:
DataSource->Ts_BitArray->Pes_BitArray->Sample->SampleHolder
To:
DataSource->Ts_BitArray->Sample->SampleHolder
Issue: #278
- TsExtractor is now based on ParsableByteArray rather than BitArray.
This makes is much clearer that, for the most part, data is byte
aligned. It will allow us to optimize TsExtractor without worrying
about arbitrary bit offsets.
- BitArray is renamed ParsableBitArray for consistency, and is now
exclusively for bit-stream level reading.
- There are some temporary methods in ParsableByteArray that should be
cleared up once the optimizations are in place.
Issue: #278
This is the start of a sequence of changes to fix the ref'd
github issue. Currently TsExtractor involves multiple memory
copy steps:
DataSource->Ts_BitArray->Pes_BitArray->Sample->SampleHolder
This is inefficient, but more importantly, the copy into
Sample is problematic, because Samples are of dynamically
varying size. The way we end up expanding Sample objects to
be large enough to hold the data being written means that we
end up gradually expanding all Sample objects in the pool
(which wastes memory), and that we generate a lot of GC churn,
particularly when switching to a higher quality which can
trigger all Sample objects to expand.
The fix will be to reduce the copy steps to:
DataSource->TsPacket->SampleHolder
We will track Pes and Sample data with lists of pointers into
TsPackets, rather than actually copying the data. We will
recycle these pointers.
The following steps are approximately how the refactor will
progress:
1. Start reducing use of BitArray. It's going to be way too
complicated to track bit-granularity offsets into multiple packets,
and allow reading across packet boundaries. In practice reads
from Ts packets are all byte aligned except for small sections,
so we'll move over to using ParsableByteArray instead, so we
only need to track byte offsets.
2. Move TsExtractor to use ParsableByteArray except for small
sections where we really need bit-granularity offsets.
3. Do the actual optimization.
Issue: #278
Previously samples belonging to disabled tracks would just
accumulate in an arbitrarily long queue in TsExtractor. We
need to actively throw samples away from disabled tracks up
to the current playback position, so as to prevent this.
Issue: #174
I'm not sure exactly what the implications of this change are,
but I'd really hope that only one program in each stream is carrying
audio/video. For GoPro cameras, they expose the video stream in
the second program, for some reason.
Issue: #116
We've seen a few streams where this assertion fails. If you
just skip the packet, things appear to recover correctly in
all cases I've seen, so replacing failure with a warning.