Commit Graph

256 Commits

Author SHA1 Message Date
Vincent Valot 6d76a135e5 feat: add modern EME support for FairPlay (#3776)
Add support for HLS com.apple.streamingkeydelivery through MSE/EME implementation.

Close #3346

## Tests
Tested on:
- Mac 11.6 Safari 15.2
- iOS 15.2 Safari 15.2
- Mac 11.6 Chrome 96 (for potential regressions on Widevine keySystem)

| Mode | DRM API | TS | CMAF (mono-key and multi-keys)
|---|---|---|---|
| file | EME |   |   |
| file | Legacy-prefixed |    |    |
| media-source | EME | **mux-js**: `encrypted` never fired<br />**real MSE**: `encrypted` event received, but with incorrect `sinf` initData (*1)  |   |
| media-source | Legacy-prefixed | **mux-js**: `webkitneedkey` never fired<br/>**real MSE**: TBD  | 🔴 fails to append media segment to SourceBuffer (init segment ok) `(video:4) – "failed fetch and append: code=3015"` |

## Support table 
| Mode | DRM API | TS | CMAF (mono-key and multi-keys)
|---|---|---|---|
| file | EME |   |   |
| file | Legacy-prefixed |    |    |
| media-source | EME | 🚫 `4040: HLS_MSE_ENCRYPTED_MP2T_NOT_SUPPORTED`  |   |
| media-source | Legacy-prefixed | 🚫 `4041: HLS_MSE_ENCRYPTED_LEGACY_APPLE_MEDIA_KEYS_NOT_SUPPORTED`  |🚫 `4041: HLS_MSE_ENCRYPTED_LEGACY_APPLE_MEDIA_KEYS_NOT_SUPPORTED` |

⚠️ Use EME APIs with multi-keys CMAF makes the video stalling with the audio continuing alone after a short time (~3 minutes in the stream, could be shorter, could be longer). Didn't find an explanation to that yet. I've observed the same behaviour with hls.js code so I don't think this is a player issue.
2022-02-07 11:17:22 -08:00
Theodore Abshire 264c842496 fix(image): Fix HLS image track issues
This makes the HLS parser honor more attributes for image tracks.
It also makes some changes to player.getImageTracks, so that the
returned track shows the size of a single thumbnail rather than the
entire sheet.

Closes #3840

Change-Id: I2ae096f455864201e08a85e29f0f02a3e06eb07f
2022-01-11 03:41:12 +00:00
Patrick Cruikshank 3e7a5b5f87 fix(hls): Fixes parsing of HLS 'DEFAULT' attribute (#3771)
Closes #3769
2021-12-06 00:36:06 -08:00
Theodore Abshire 9220c1f87d fix(hls): Made HLS notify segments after fit
Previously, the HLS parser would notify the presentation timeline
of the segments in the manifest before fitting the segments.
The HLS parser will also sometimes remove segments from the end of
a VOD asset if they do not fit within the playlist duration.
This could sometimes cause the presentation timeline and MediaSource
to have different opinions on how long the VOD asset was, which could
lead to the seek bar looking like the presentation stopped before the
end.

Closes #3733

Change-Id: I67fdc28a3f6eee158c9906359491fe6bb418e730
2021-11-03 16:16:35 -07:00
Theodore Abshire dd3748d599 fix: Enforce string-format of event data keys.
Previously, many events were being defined with a data dictionary
that used variable-type keys (e.g. {key: value}). This worked fine
in uncompiled mode, but in compiled mode it lead to those properties
being obfuscated.
This changes the FakeEvent constructor to take a map rather than an
object, so the compiler will force the keys to be strings.

Closes #3710

Change-Id: I67b1a391540a5ee21f0aaf940ae054d26f4c10a4
2021-10-25 12:40:32 -07:00
Casey Occhialini 221637a66c feat: Add Common Media Client Data (CMCD) logging support (#3662)
Add support for including Common Media Client Data (CMCD) in outgoing requests.

Fixes #3619

NOTE: The following fields have not been implemented: rtp, nrr, nor, dl

Co-authored-by: Dan Sparacio <daniel.sparacio@cbsinteractive.com>
2021-10-20 12:22:41 -07:00
Álvaro Velad Galván 52d68a29c8 feat(hls): Make default HLS audio/video codecs configurable (#3651) 2021-09-22 00:47:35 -07:00
Theodore Abshire 20f3cb0bc3 fix: Tolerate misaligned TS files
All TS packets are expected to start with the sync byte 0x47, and
TS files are expected to start at the start of a packet. Because of
that, we assumed that any TS file that did not start with the sync
byte of 0x47 is invalid.
However, it is possible that a TS file might not start on a sync
byte... perhaps the first few bytes got cut off, for some reason?
In those cases, it would be better to just drop that cut-off first
packet, instead of entirely rejecting the TS file.
This CL changes the HLS parser to keep looking forward for the
length of a few packets for the first sync byte, when parsing TS
files to try to find their start time.

Closes #3580

Change-Id: I0bace4b3a84398e09046828d749f3f025dfad26f
2021-09-15 11:19:00 -07:00
Álvaro Velad Galván 76480f9746 fix(HLS): Prioritize AVERAGE-BANDWIDTH over BANDWIDTH (#3428)
Related to conversation in #3422
2021-06-07 10:44:47 -07:00
Álvaro Velad Galván 2a4083bab8 feat: Add support to HLS Image Media Playlists (#3365)
Close: #2429
2021-06-02 10:53:32 -07:00
Michelle Zhuo 4c975621a0 feat(ll-hls): only request delta updates when server supports it
We should only request playlist delta updates when the lowLatencyMode is
enabled, and when the server supports the feature. We can check if the
playlist has a "CAN-SKIP-UNTIL" tag to know if the server supports that.

Issue #1525

Change-Id: I304a008aeb3a9e019f27304ba836d31538c94fbf
2021-04-15 03:06:03 +00:00
ismena 7e50866bb5 fix(dash): Fix stalls on a live dash stream.
In live streams, we can evict segments outside the availability window
faster than they disappear from the manifest. If that happens, we used
to evict them several times (add them back in and then evict again).
This caused the eviction counter to increase beyond what it should be
and we had trouble finding segments afterwards.

Closes #3139.

Change-Id: Iafebfaf8e1e9ebb09a64cdf7e09a882115fd8eb6
2021-04-14 19:41:30 +00:00
Michelle Zhuo 67a6745070 doc(hls): Minor enhancement of comments
Change-Id: Icf442f8ed5652edd2e1c14c4f72e3b00b6fee1d8
2021-04-13 14:16:20 -07:00
Suraj kumar (sk) 77140991f1 fix(hls): Assume MP4 if MIME type can't be deduced (#3325)
Fixes #3142
2021-04-13 13:56:02 -07:00
Michelle Zhuo 34c3133077 fix(ll-hls): get discontinuity sequence number with skipped segments
With playlist delta update, the discontinuity tag in the old playlist
might be skipped in the updated playlist. The discontinuity sequence
number is for the first (skipped) segment in the playlist, and we should
not use it directly to get the timestamp offset for the first listed
segment.
Instead, we can have a map of discon sequence number to the starting
media sequence number. And for the updated list, check if we have a
larger discon sequence number in the map, and its starting Media
sequence number is smaller than the segment's media sequence number.

Change-Id: I6c2e32160791b22afb87f40af4d246c5cabb6d7f
2021-04-07 19:23:00 +00:00
Michelle Zhuo 198a6d42f6 feat(MediaCap): Guess the codecs of multiplexd stream for MediaCap
If we have a multiplexd stream with audio and video, the video
codecs are a combined string containing both audio and video codecs.
Before sending the request to decodingInfo(), we should check which
codec is audio and which one is video.

This is a follow-up of commit 966a756.

Issue #1391

Change-Id: Ic9b1c5972a99f63a715c74ae068b85f43efac447
2021-03-30 14:43:25 -07:00
Michelle Zhuo acfa1a800c feat(MediaCap): get decodingInfo results before queryMediaKeys
Previously, we fill in the variants' drmInfos with the drm
configurations of |clearKeys|, |servers| and |advanced| during
initializing the DrmEngine, before we query the media keys.

Now we need to call |MediaCapabilities.decodingInfo()| to get the
mediaKeySystemAccess of the variants after the DrmEngine is
created and configured, and the drm values are filled in for the
variants, and before |DrmEngine.queryMediaKey_()|.

The steps would be:
0. StreamUtils.setDecodingInfo() should not be called before
   DrmEngine is initialized and configured.
1. Create and configure DrmEngine.
2. Fill in drm values for the variants with configurations.
3. Call StreamUtils.setDecodingInfo() to get the decodingInfo of
   the variants.
4. Use the decodingInfo results to set up the Drm mediaKeys in
   DrmEngine.
5. When StreamUtils.filterManifest() is called, we can reuse the
   decodingInfo results instead of calling decodingInfo again.

Previously we call filterManifest() when parsing the manifest, to
filter out the unsupported streams.
Now decodingInfo can tell us if a variant is supported and its
MediaKeys at once. When initializing the DrmEngine, we get the
decodingInfo results of the variants, and only use the supported
streams to set up the MediaKeys. After that, we filter the manifest
right after DrmEngine is initialized.
Thus, we can skip filterManifest() in manifest parsers.

Using decodingInfo to get media keys will be in the next CL.

Issue #1391

Change-Id: Ieb401a1e4dfbcc958f7a14fa96df546237b0f446
2021-03-23 23:41:51 +00:00
Michelle Zhuo 2d68453c7c fix(ll-hls): Only read PART-HOLD-BACK value when appropriate
PART-HOLD-BACK indicates the server-recommended minimum distance
from the end of the Playlist at which clients should begin to play
or to which they should seek when playing in Low-Latency Mode.

PART-HOLD-BACK is only required if the Playlist contains the
EXT-X-PART-INF tag.

Change-Id: Id430a38efdbc78f65e8d34ba125b02bdec6b7e59
2021-03-22 17:40:45 -07:00
ismena 9cca82bfd0 fix(hls): Fix content type detection when text codec are present.
Closes #3184

Change-Id: I42454318efa5e87eeff174e2f43218bb194c4c8d
2021-03-18 21:01:34 +00:00
Michelle Zhuo 57ee23812e feat(MediaCap): Use MediaCapabilities for supporting info
In StreamUtils, use MediaCapabilities.decodingInfo() instead of
MediaSource.isTypeSupported() to check if the stream is supported.

MediaCapabilities.decodingInfo() takes an
MediaDecodingConfiguration object as input, and returns a Promise
with a MediaCapabilitiesInfo object. The returned object tells us
whether decoding the media is supported, smooth, and
powerefficient.

Steps:
1. Create a MediaDecodingConfiguration object for each variant as
   the input.
2. Query the decodingInfo API with the config.
3. Get the 'supported' info from the decodingInfo result, to know
   whether the variant is supported.

Issue #1391

Change-Id: I8fc2d3ec6a9868f38269d550d35f45c298faae98
2021-03-12 21:41:53 +00:00
Álvaro Velad Galván b9b3cc8098 feat(dash): Add support for thumbnail tracks (#3145) 2021-03-02 13:36:09 -08:00
Álvaro Velad Galván f067ae10ac Parse spatial audio from manifest (#3148) 2021-02-24 09:28:33 -08:00
Michelle Zhuo 2371bd8591 fix: Fix build failures
1. Added hdr as a property in stream when constructing.
Fixes build failure from commit
71372869de .
PR #3116
Issue #2813

2. Fixed the test error from commit
d3640d1da1 .
PR #3044
Issue #3029

3. Fixed the new line with no other arguments from commit
0845843b65 .
PR #3060

Change-Id: I5833e49c1a95172742c4ec820960c9c5a7bf0cca
2021-02-02 14:02:12 -08:00
Álvaro Velad Galván 71372869de feat: Extract HDR metadata from HLS manifests (#3116)
In our isTypeSupported polyfill for Cast, we use the HEVC profile ("hevc1.2") as
an indication of the HDR transfer function, which is not always accurate.
The polyfill should stop assuming that 10-bit color HEVC means HDR, and remove
the extra eotf="smpte2084" parameter. Instead, the manifest parser should
extract HDR profile information from the DASH manifest and pass that info along
through the Stream object.

Issue #3116 .
2021-01-31 23:36:57 -08:00
Álvaro Velad Galván 1c9ab83ced Add support for "m4f" in HLS (#3111)
Closes #3099
2021-01-20 10:32:51 -08:00
Joey Parrish 562a2d567b chore: Strictly require jsdoc
This enables the eslint rule requiring jsdocs on all class
declarations, function declarations, and methods.

Unfortunately, there are two problems with this:

1. We don't use class _declarations_, we use class _expressions_,
which are not covered by this rule.  So it does not enforce jsdoc at
the class level.
2. We tend to document a class at the class-level, rather than at the
constructor.  But a constructor counts as a method for eslint, so it
requires docs on the constructor.  There is no way to configure it to
make an exception for trivial constructors.

So for all trivial (no-argument) constructors, we add empty jsdocs:
  /** */
  constructor() {

This was quicker and easier than setting up some alternative plugin in
eslint to make an exception for us.

The good news is that this rule caught several undocumented parameters
and places where the jsdoc comment was malformed.  So fixing those
also improves the compiler's ability to enforce types.

Change-Id: Icbc46ed690c94e53d354648a883119524f8fca45
2021-01-09 02:00:31 +00:00
Álvaro Velad Galván 28f35c251c feat(lowLatency): Add autoLowLatencyMode config (#2861)
With "lowLatencyMode" enabled, "rebufferingGoal" is set to 0.001, and inaccurateManifestTolerance is set to 0 by default. However, in some cases longer rebufferingGoal helps to avoid new rebuffering.
Besides  "lowLatencyMode", this code change adds the  "autoLowLatencyMode" config. When "lowLatencyMode" config is disabled and "autoLowLatencyMode" config is enabled, and the manifest provides low latency features, we automatically activate the lowLatencyMode.
If "lowLatencyMode" is enabled, "autoLowLatencyMode" has no effect.

Issue #1525
2020-11-12 11:07:19 -08:00
Álvaro Velad Galván 01998f3b99 Parse forced subtitles from manifest (#2938)
Issue #2122
Issue #2916
2020-10-27 14:00:48 -07:00
Joey Parrish ad009b6d2f fix(hls): Recognize the types of mp4a and mp4v extensions
The HLS content linked in #2907 uses the .mp4a extension for audio
segments, so it is helpful for us to be able to recognize the types of
these segments.  This adds both .mp4a and .mp4v to the extension maps
in the HLS parser.

Change-Id: I8f2e126691e552c34ff5da027fca32ed925a2bdf
2020-10-14 17:13:40 +00:00
Álvaro Velad Galván f7626ff60a fix(hls): Support multiple CHARACTERISTICS values in HLS (#2905)
Resolves #2903
2020-10-13 10:06:29 -07:00
Michelle Zhuo 20cc6b53a2 feat(ll-hls): Parse BYTERANGE-START tag
BYTERANGE-START is the byte offset of the first byte of a preload
hinted resource. This attribute is optional, and defaults to 0.

Example:
'#EXT-X-PART:DURATION=1.02,URI="fs271.mp4",BYTERANGE=18000@43000'
'#EXT-X-PRELOAD-HINT:TYPE=PART,URI="fs271.mp4",BYTERANGE-START=61000'

Issue #1525

Change-Id: Ib3f7feb6bd5d3fd09b89962c067029a448d020e7
2020-10-05 20:12:49 +00:00
Joey Parrish 3d9510af88 fix(HLS): Fix interpretation of DEFAULT and AUTOSELECT
Previously, we treated the mere presense of either the DEFAULT or
AUTOSELECT attributes as an indication of a primary language.
However, AUTOSELECT should not be used in this way at all, and both
attributes can have a value of NO, so mere presence or absence is not
enough.

Instead, we must check for DEFAULT=YES to indicate a primary language.

Fixes #2880

Change-Id: Ie107f079c06beb89ee5a6a51375af7a72fdd9021
2020-09-28 12:44:39 -07:00
Theodore Abshire 7941703c5a Fix(hls): Allow config to play video-only HLS.
If an HLS stream has no provided codec information in its manifest,
we previously defaulted to providing a best-guess video and audio
codec.  This, however, caused problems for video-only and audio-only
streams; Chrome does not like it if an audio codec is provided for
a stream with no audio at all, for example, and fails to append the
chunks.
This modifies the HLS parser to not provide a default video codec if
the 'disableVideo' config is set, and similarly to not provide a
default audio codec if 'disableAudio' is set.

Issue #2868

Change-Id: I7826fdb69f2e5290914ed2c0d1e109f9db94f80d
2020-09-26 06:04:00 +00:00
michellezhuo c17f427194 build: Add require and requireType
Add missing require and requireType for compiler upgrade.

Change-Id: Ie21418d93eb70c2213815638d6fd2d784cf6ef2e
2020-09-24 22:20:14 +00:00
Michelle Zhuo 281d3ed96f feat(LowLatency): Show warning if lowLatencyMode should be enabled
Updated the warning message.

Change-Id: Ifc655cfd11d617b87ff9d0f3a11b37eef12bfc86
2020-09-20 16:22:03 -07:00
Michelle Zhuo ac4fb76e05 feat(LowLatency): Show warning if lowLatencyMode should be enabled
If an HLS playlist contains partials segments, or a Dash playlist
has availabilityTimeOffset value, we check whether lowLatencyMode
is enabled. If not, we show a warning to remind the developer to
set the configuration.

Issue #1525

Change-Id: If7b851c32c325203870c33d868668e1a3dd3c8bf
2020-09-18 19:37:43 +00:00
Theodore Abshire 509e7b046a fix(manifest): Fix embedded captions vanishing.
Previously, on manifest updates, embedded captions would vanish in
single-period live DASH streams.  The problem was based on the
specific point in the load order that we added dummy text streams
to indicate the presence of embedded captions.
This modifies the PlayerInterface for manifest parsers to add a
new method passed in, makeTextStreamsForClosedCaptions, which
must be called by manifest parsers for new video streams.
This also completes an unfinished feature, where new video streams
which add new closed captions would not get corresponding
text streams.

Closes #2811

Change-Id: Iee7499ec950b363cf6839765cc2bd2d01743467d
2020-08-26 15:05:40 -07:00
Chris Fillmore da74965a37 fix(DRM): Check KEYID format in lowercase (#2790)
Closes #2789
2020-08-24 16:26:13 -07:00
slasktrat 1b40aa2532 fix: Recognize "wvtt" codec in HLS WebVTT tracks (#2778)
Co-authored-by: Espen Aa Ljosland <espen@ljosland.com>
2020-08-24 12:39:21 -07:00
michellezhuo e7965fe219 feat(LL-HLS):Set segment availability duration
When starting playback for HLS live, we have the availability window
same as the delay duration from live edge. Thus, the playback start time
is the same as availability window start, and falls behind the window as
the window keeps move forward.
This may cause the seeked partial segments to be unavailable.

To make our system more robust, we can skip checking if the segment fits
in the availability window. Instead, we can send the request anyway. If
the segment is not available, we can handle the 404 error and try to fetch
the segment again.
This would not require us to calculate the segment availability window
in advance.

Issue #1525

Change-Id: Ib9c0eca8e9db2d93404745d87a5171fcb5fdce20
2020-08-20 19:03:34 +00:00
Michelle Zhuo a22df6d18c feat(lowLatency): Move lowLatencyMode config to streaming configuration
1. Move the config field from ManifestConfiguration to StreamingConfiguration, since StreamingEngine will need it.
2. In manifest parsers, we get the value of lowLatencyMode config from the StreamingConfiguration.

Issue #1525

Change-Id: Iaa961b4e6799ecc1fcf3147b2fb992e86d4b043d
2020-08-20 03:33:46 +00:00
Álvaro Velad Galván 57ac167355 feat(hls): Add HLS PlayReady support (#2719)
Resolves #1145
2020-08-03 13:15:08 -07:00
michellezhuo a534dca883 feat(LL-HLS): Add configuration comments for low latency mode
1. In low latency mode, the playback start time from live edge is about
3 times partial segment duration, 3s for example. The rebufferingGoal of
2s would result in infinite buffering.

2. In low latency mode, do not allow drift for seeking. Only seek with
the presentation time.

Change-Id: Iee92727bf17dab8b52fae070522a5a2ec1621ffc
2020-07-22 17:00:15 +00:00
michellezhuo 3a14bcf72f fix[LL-HLS]: Set init segments for every segment
If the last segment in the media playlist contains only partial
segments, its init segment was not set, causing playback failing to
start, with 'Append: stream parsing failed' error.

Issue #1525

Change-Id: I0dab967fe55c9d792f102f4d49dda7f9437d8897
2020-07-22 16:58:51 +00:00
Jacob Trimble dc8b007d56 cleanup: Add missing requires.
This is a port of the internal changes: cr/321495405, cr/321592702,
and cr/321594488.

Change-Id: If6a4c4266ed10a70b01442974dbd19329bb5122e
2020-07-16 10:59:49 -07:00
michellezhuo 109973c7e2 feat(LL-HLS):Enable preload hinted segments
LL-HLS hints a resource that is needed to playback in the upcoming
update. It's available for request, and may not be available for
download yet.

A preload hinted resource is either a partial segment, or an init
segment. If it's an init segment, treat it the same way as the Map tag
in ManifestTextParser.
A preload hinted segment contains no duration information, so its
start time and end time are the same. It will be replaced by a partial
segment in the next update.
We should fetch and append the preload hinted segment the same way as a
partial segment.

Issue #1525

Change-Id: I1e30f216ecdc843c3cd01681629a8886383d0b22
2020-07-08 22:11:06 +00:00
michellezhuo ec3bf7aaa5 fix(HLS): Fix discontinuity timestamp offset
Closes #2687

Change-Id: I60e41341d1149eb8200bec71fa1bafb5be8e57c7
2020-07-07 14:12:47 -07:00
michellezhuo 965ef453b6 feat(LL-HLS):Enable Partial Segments streaming
Changed SegmentIndex and SegmentIterator to iterate through regular and
Partial SegmentReferences.

SegmentIndex:
merge(): Find all the old segments after the first new segment's start
time, and replace the old ones with new segments.

SegmentIterator:
Use the currentPosition and currentPartialPosition pointers to iterate
through the two-layer arrays.
current(): Get the current SegmentReference, and get its current Partial
SegmentReference if it has a Partial Segment list. Move to the next
regular segment if we reached the end of the current segment's partial
list.
next():
If the regular segment has a partial list, go to the next Partial
Segment. If reached the end of the current partial list, move to the
next regular segment.
If the regular segment doesn't have a partial list, move to the next
regular segment.

Issue #1525

Change-Id: Icb7f49e50314f15ea40bf3a74d008191ed1a9a6c
2020-07-06 00:34:55 +00:00
michellezhuo 1685b2cd83 feat(LL-HLS):Enable playlist delta update
Player can request delta updates to reduce the transfer cost.
Client: sends a request for playlist update with '_HLS_skip=YES'
parameter.
Server: replaces the older segments in the media playlist with
'EXT-X-SKIP' tag.

Issue #1525

Change-Id: I3643641d0cb97444ba1c00f06d9e113acba7b824
2020-07-06 00:33:06 +00:00
michellezhuo fb43b1f0fd feat(LL-HLS):Add support for Server Control Tag
For LL-HLS, use the value of 'PART-HOLD-BACK' in the Server Control tag
as the default presentation delay.
'PART-HOLD-BACK' is the server suggested min distance from the live
edge, and must be >= 3 * partial segment target duration.
It's always available when the playlist contains partial segments.

Issue #1525

Change-Id: I176188dbd39be0d038eee938d3e8358e54b8a3a8
2020-06-30 02:55:54 +00:00