Skip to content

Commit

Permalink
fix(hls): Handle unaligned HLS streams on VOD
Browse files Browse the repository at this point in the history
This reverts the HLS parser to using per-stream mediaSequenceToStartTime
values for VOD, which will allow us to play unaligned HLS streams on
that sort of content.

Issue shaka-project#4308
  • Loading branch information
theodab committed Sep 29, 2022
1 parent 8f6b55a commit 3d37535
Showing 1 changed file with 28 additions and 5 deletions.
33 changes: 28 additions & 5 deletions lib/hls/hls_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ shaka.hls.HlsParser = class {
* that each stream of a type (video, audio, etc) has the same mappings of
* sequence number to start time.
* This map stores those relationships.
* Only used during livestreams; we do not assume that VOD content is
* synchronized in that way.
* @private {!Map.<string, !Map.<number, number>>}
*/
this.mediaSequenceToStartTimeByType_ = new Map();
Expand Down Expand Up @@ -313,6 +315,19 @@ shaka.hls.HlsParser = class {
}
}

/**
* @param {!shaka.hls.HlsParser.StreamInfo} streamInfo
* @return {!Map.<number, number>}
* @private
*/
getMediaSequenceToStartTimeFor_(streamInfo) {
if (this.isLive_()) {
return this.mediaSequenceToStartTimeByType_.get(streamInfo.type);
} else {
return streamInfo.mediaSequenceToStartTime;
}
}

/**
* Updates a stream.
*
Expand Down Expand Up @@ -350,7 +365,7 @@ shaka.hls.HlsParser = class {
const stream = streamInfo.stream;

const mediaSequenceToStartTime =
this.mediaSequenceToStartTimeByType_.get(streamInfo.type);
this.getMediaSequenceToStartTimeFor_(streamInfo);
const segments = this.createSegments_(
streamInfo.verbatimMediaPlaylistUri, playlist, stream.type,
stream.mimeType, mediaSequenceToStartTime, mediaVariables);
Expand Down Expand Up @@ -410,7 +425,7 @@ shaka.hls.HlsParser = class {
goog.asserts.assert(segmentIndex,
'Only loaded streams should be synced');
const mediaSequenceToStartTime =
this.mediaSequenceToStartTimeByType_.get(streamInfo.type);
this.getMediaSequenceToStartTimeFor_(streamInfo);
const segment0 = segmentIndex.earliestReference();
if (segment0) {
// This looks inefficient, but iteration order is insertion order.
Expand Down Expand Up @@ -533,7 +548,7 @@ shaka.hls.HlsParser = class {
'Negative maxTimestamp after adjustment!');

const mediaSequenceToStartTime =
this.mediaSequenceToStartTimeByType_.get(streamInfo.type);
this.getMediaSequenceToStartTimeFor_(streamInfo);
for (const [key, value] of mediaSequenceToStartTime) {
mediaSequenceToStartTime.set(key, value + offset);
}
Expand Down Expand Up @@ -1524,6 +1539,7 @@ shaka.hls.HlsParser = class {
// These values are filled out or updated after lazy-loading:
absoluteMediaPlaylistUri: initialMediaPlaylistUri,
maxTimestamp: 0,
mediaSequenceToStartTime: new Map(),
canSkipSegments: false,
hasEndList: false,
firstSequenceNumber: -1,
Expand Down Expand Up @@ -1565,6 +1581,8 @@ shaka.hls.HlsParser = class {
streamInfo.maxTimestamp = realStreamInfo.maxTimestamp;
streamInfo.canSkipSegments = realStreamInfo.canSkipSegments;
streamInfo.hasEndList = realStreamInfo.hasEndList;
streamInfo.mediaSequenceToStartTime =
realStreamInfo.mediaSequenceToStartTime;
stream.segmentIndex = realStream.segmentIndex;
stream.encrypted = realStream.encrypted;
stream.drmInfos = realStream.drmInfos;
Expand Down Expand Up @@ -1793,8 +1811,8 @@ shaka.hls.HlsParser = class {
shaka.util.Error.Code.HLS_KEYFORMATS_NOT_SUPPORTED);
}

const mediaSequenceToStartTime =
this.mediaSequenceToStartTimeByType_.get(type);
const mediaSequenceToStartTime = this.isLive_() ?
this.mediaSequenceToStartTimeByType_.get(type) : new Map();
const segments = this.createSegments_(verbatimMediaPlaylistUri, playlist,
type, mimeType, mediaSequenceToStartTime, mediaVariables);

Expand Down Expand Up @@ -1836,6 +1854,7 @@ shaka.hls.HlsParser = class {
canSkipSegments,
hasEndList: false,
firstSequenceNumber: -1,
mediaSequenceToStartTime,
};
}

Expand Down Expand Up @@ -2981,6 +3000,7 @@ shaka.hls.HlsParser = class {
* verbatimMediaPlaylistUri: string,
* absoluteMediaPlaylistUri: string,
* maxTimestamp: number,
* mediaSequenceToStartTime: !Map.<number, number>,
* canSkipSegments: boolean,
* hasEndList: boolean,
* firstSequenceNumber: number
Expand All @@ -3003,6 +3023,9 @@ shaka.hls.HlsParser = class {
* and updated to reflect any redirects.
* @property {number} maxTimestamp
* The maximum timestamp found in the stream.
* @property {!Map.<number, number>} mediaSequenceToStartTime
* A map of media sequence numbers to media start times.
* Only used for VOD content.
* @property {boolean} canSkipSegments
* True if the server supports delta playlist updates, and we can send a
* request for a playlist that can skip older media segments.
Expand Down

0 comments on commit 3d37535

Please sign in to comment.