From 27049ac9352caf0ee110097bef48950ad2701629 Mon Sep 17 00:00:00 2001 From: Anurag Kalia Date: Tue, 11 Jun 2019 19:56:45 +0530 Subject: [PATCH 1/5] Issue-1983: Add user hooks into HLS parser plugin Add `onSegmentParsed` to playerInterface for manifest parsers. This callback will be triggered to communicate custom metadata of the segment when it is being parsed in the manifest, and can be read on using the event 'segmentparsed'. Right now, only HLS is using this to communicate tags associated with each segment. --- AUTHORS | 1 + CONTRIBUTORS | 1 + externs/shaka/manifest_parser.js | 3 +++ lib/hls/hls_parser.js | 36 ++++++++++++++++++++++++++------ lib/media/segment_index.js | 10 +++++++++ lib/offline/storage.js | 1 + lib/player.js | 26 +++++++++++++++++++++++ 7 files changed, 72 insertions(+), 6 deletions(-) diff --git a/AUTHORS b/AUTHORS index df40777dd5..064957e8f2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,6 +24,7 @@ Google Inc. <*@google.com> Edgeware AB <*@edgeware.tv> Gil Gonen Giuseppe Samela +Hotstar <*@hotstar.com> Itay Kinnrot Jason Palmer Jesper Haug Karsrud diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 6a33e3d9c0..ef700389d2 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -25,6 +25,7 @@ Aaron Vaage Alvaro Velad Galvan Andy Hochhaus +Anurag Kalia Benjamin Wallberg Boris Cupac Bryan Huh diff --git a/externs/shaka/manifest_parser.js b/externs/shaka/manifest_parser.js index 211072f3d7..47483826ad 100644 --- a/externs/shaka/manifest_parser.js +++ b/externs/shaka/manifest_parser.js @@ -59,6 +59,7 @@ shaka.extern.ManifestParser = function() {}; * filterNewPeriod: function(shaka.extern.Period), * filterAllPeriods: function(!Array.), * onTimelineRegionAdded: function(shaka.extern.TimelineRegionInfo), + * onSegmentParsed: function(string, number, *), * onEvent: function(!Event), * onError: function(!shaka.util.Error) * }} @@ -77,6 +78,8 @@ shaka.extern.ManifestParser = function() {}; * Should be called on all Periods so that they can be filtered. * @property {function(shaka.extern.TimelineRegionInfo)} onTimelineRegionAdded * Should be called when a new timeline region is added. + * @property {function(string, number, *)} onSegmentParsed + * Should be called with segment metadata when a new segment is parsed. * @property {function(!Event)} onEvent * Should be called to raise events. * @property {function(!shaka.util.Error)} onError diff --git a/lib/hls/hls_parser.js b/lib/hls/hls_parser.js index 3d8318f127..45469dee95 100644 --- a/lib/hls/hls_parser.js +++ b/lib/hls/hls_parser.js @@ -287,7 +287,9 @@ shaka.hls.HlsParser = class { playlist, startPosition, stream.mimeType, - stream.codecs); + stream.codecs, + stream.id, + streamInfo.segmentIndex.getAll()); streamInfo.segmentIndex.replace(segments); @@ -1167,8 +1169,11 @@ shaka.hls.HlsParser = class { const startPosition = mediaSequenceTag ? Number(mediaSequenceTag.value) : 0; + const nextStreamId = this.globalId_++; + const segments = await this.createSegments_( - verbatimMediaPlaylistUri, playlist, startPosition, mimeType, codecs); + verbatimMediaPlaylistUri, playlist, startPosition, mimeType, codecs, + nextStreamId, []); const minTimestamp = segments[0].startTime; const lastEndTime = segments[segments.length - 1].endTime; @@ -1186,7 +1191,7 @@ shaka.hls.HlsParser = class { /** @type {shaka.extern.Stream} */ const stream = { - id: this.globalId_++, + id: nextStreamId, originalId: name, createSegmentIndex: () => Promise.resolve(), findSegmentPosition: (i) => segmentIndex.find(i), @@ -1435,16 +1440,25 @@ shaka.hls.HlsParser = class { * @param {number} startPosition * @param {string} mimeType * @param {string} codecs + * @param {number} streamId + * @param {Array.} existingSegmentRefs * @return {!Promise>} * @private */ async createSegments_( - verbatimMediaPlaylistUri, playlist, startPosition, mimeType, codecs) { + verbatimMediaPlaylistUri, playlist, startPosition, mimeType, codecs, + streamId, existingSegmentRefs) { /** @type {Array.} */ const hlsSegments = playlist.segments; - /** @type {!Array.} */ + /** @type {Array.} */ const references = []; + let exisitingRefCount = 0; + if (existingSegmentRefs.length > 0) { + const earlierStartPosition = existingSegmentRefs[0].getPosition(); + exisitingRefCount = existingSegmentRefs.length - + (startPosition - earlierStartPosition); + } goog.asserts.assert(hlsSegments.length, 'Playlist should have segments!'); // We may need to look at the media itself to determine a segment start // time. @@ -1463,12 +1477,22 @@ shaka.hls.HlsParser = class { initSegmentRef, firstSegmentRef, mimeType, codecs); shaka.log.debug('First segment', firstSegmentUri.split('/').pop(), 'starts at', firstStartTime); - for (let i = 0; i < hlsSegments.length; ++i) { + + // Append brand-new segments + for (let i = references.length; i < hlsSegments.length; ++i) { const hlsSegment = hlsSegments[i]; const previousReference = references[references.length - 1]; const startTime = (i == 0) ? firstStartTime : previousReference.endTime; const position = startPosition + i; + if (i >= exisitingRefCount) { + // Only fire this event for brand new segments + this.playerInterface_.onSegmentParsed( + 'application/vnd.apple.mpegurl', + streamId, + hlsSegment); + } + const reference = this.createSegmentReference_( playlist, previousReference, diff --git a/lib/media/segment_index.js b/lib/media/segment_index.js index abebfb8815..3e6f23f860 100644 --- a/lib/media/segment_index.js +++ b/lib/media/segment_index.js @@ -107,6 +107,16 @@ shaka.media.SegmentIndex = class { return this.references_[index]; } + /** + * Get all the SegmentReferences + * + * @return {Array.} existing segment references + * @export + */ + getAll() { + return this.references_; + } + /** * Offset all segment references by a fixed amount. diff --git a/lib/offline/storage.js b/lib/offline/storage.js index 2b0742c49f..74d56dc322 100644 --- a/lib/offline/storage.js +++ b/lib/offline/storage.js @@ -797,6 +797,7 @@ shaka.offline.Storage = class { filterNewPeriod: () => {}, onTimelineRegionAdded: () => {}, + onSegmentParsed: () => {}, onEvent: () => {}, // Used to capture an error from the manifest parser. We will check the diff --git a/lib/player.js b/lib/player.js index 04dd24fa72..9a48f99a3c 100644 --- a/lib/player.js +++ b/lib/player.js @@ -1451,6 +1451,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget { // manifest). onTimelineRegionAdded: (region) => this.regionTimeline_.addRegion(region), + // Called to signal new segment metadata upon parsing in the manifest + // segment metadata can vary depending on mimeType and streamId + onSegmentParsed: (mimeType, streamId, segment) => this.onSegmentParsed_( + mimeType, streamId, segment), + onEvent: (event) => this.dispatchEvent(event), onError: (error) => this.onError_(error), }; @@ -4249,6 +4254,27 @@ shaka.Player = class extends shaka.util.FakeEventTarget { } } + /** + * Callback from player + * + * @param {string} mimeType of the manifest-parser + * @param {number} streamId to which the segment belongs + * @param {*} segment segment metadata (format depends on mimeType+segment) + * @private + */ + + onSegmentParsed_(mimeType, streamId, segment) { + const eventData = { + mimeType, + streamId, + segment, + }; + + this.dispatchEvent( + new shaka.util.FakeEvent('segmentparsed', eventData) + ); + } + /** * Callback from AbrManager. * From d794b4a805cb275940ccb269b3264811b35473bd Mon Sep 17 00:00:00 2001 From: Anurag Kalia Date: Wed, 12 Jun 2019 17:53:35 +0530 Subject: [PATCH 2/5] Add unit tests for onSegmentParsed --- .../dash_parser_content_protection_unit.js | 1 + test/dash/dash_parser_live_unit.js | 1 + test/dash/dash_parser_manifest_unit.js | 1 + test/dash/dash_parser_segment_base_unit.js | 1 + .../dash/dash_parser_segment_template_unit.js | 1 + test/hls/hls_live_unit.js | 71 +++++++++++++++++++ test/hls/hls_parser_unit.js | 11 +++ test/test/util/dash_parser_util.js | 2 + test/test/util/util.js | 35 +++++++++ 9 files changed, 124 insertions(+) diff --git a/test/dash/dash_parser_content_protection_unit.js b/test/dash/dash_parser_content_protection_unit.js index 7e61199317..b550a36dcc 100644 --- a/test/dash/dash_parser_content_protection_unit.js +++ b/test/dash/dash_parser_content_protection_unit.js @@ -47,6 +47,7 @@ describe('DashParser ContentProtection', () => { filterNewPeriod: () => {}, filterAllPeriods: () => {}, onTimelineRegionAdded: fail, // Should not have any EventStream elements. + onSegmentParsed: fail, onEvent: fail, onError: fail, }; diff --git a/test/dash/dash_parser_live_unit.js b/test/dash/dash_parser_live_unit.js index adc97dcc02..7087352512 100644 --- a/test/dash/dash_parser_live_unit.js +++ b/test/dash/dash_parser_live_unit.js @@ -47,6 +47,7 @@ describe('DashParser Live', () => { filterNewPeriod: () => {}, filterAllPeriods: () => {}, onTimelineRegionAdded: fail, // Should not have any EventStream elements. + onSegmentParsed: fail, onEvent: fail, onError: fail, }; diff --git a/test/dash/dash_parser_manifest_unit.js b/test/dash/dash_parser_manifest_unit.js index 010bd28e85..68bc93ee4b 100644 --- a/test/dash/dash_parser_manifest_unit.js +++ b/test/dash/dash_parser_manifest_unit.js @@ -38,6 +38,7 @@ describe('DashParser Manifest', () => { filterNewPeriod: () => {}, filterAllPeriods: () => {}, onTimelineRegionAdded: fail, // Should not have any EventStream elements. + onSegmentParsed: fail, onEvent: shaka.test.Util.spyFunc(onEventSpy), onError: fail, }; diff --git a/test/dash/dash_parser_segment_base_unit.js b/test/dash/dash_parser_segment_base_unit.js index 126bcfc3b7..d798b4ac51 100644 --- a/test/dash/dash_parser_segment_base_unit.js +++ b/test/dash/dash_parser_segment_base_unit.js @@ -42,6 +42,7 @@ describe('DashParser SegmentBase', () => { filterNewPeriod: () => {}, filterAllPeriods: () => {}, onTimelineRegionAdded: fail, // Should not have any EventStream elements. + onSegmentParsed: fail, onEvent: fail, onError: fail, }; diff --git a/test/dash/dash_parser_segment_template_unit.js b/test/dash/dash_parser_segment_template_unit.js index ba436040e5..822d026e1a 100644 --- a/test/dash/dash_parser_segment_template_unit.js +++ b/test/dash/dash_parser_segment_template_unit.js @@ -36,6 +36,7 @@ describe('DashParser SegmentTemplate', () => { filterNewPeriod: () => {}, filterAllPeriods: () => {}, onTimelineRegionAdded: fail, // Should not have any EventStream elements. + onSegmentParsed: fail, onEvent: fail, onError: fail, }; diff --git a/test/hls/hls_live_unit.js b/test/hls/hls_live_unit.js index 27e56a3c3a..314538b5d0 100644 --- a/test/hls/hls_live_unit.js +++ b/test/hls/hls_live_unit.js @@ -124,12 +124,22 @@ describe('HlsParser live', () => { onError: fail, onEvent: fail, onTimelineRegionAdded: fail, + onSegmentParsed: fail, }; parser = new shaka.hls.HlsParser(); parser.configure(config); }); + /** @type {!jasmine.Spy} */ + let onSegmentParsedSpy; + + beforeEach(() => { + onSegmentParsedSpy = jasmine.createSpy('onSegmentParsed'); + playerInterface.onSegmentParsed = + shaka.test.Util.spyFunc(onSegmentParsedSpy); + }); + afterEach(() => { // HLS parser stop is synchronous. parser.stop(); @@ -555,6 +565,67 @@ describe('HlsParser live', () => { master, media, [ref1], mediaWithAdditionalSegment, [ref1, ref2]); }); + it('triggers segment parsed callbacks as segments appear', () => { + const mediaWithAdditionalSegment = [ + '#EXTM3U\n', + '#EXT-X-PLAYLIST-TYPE:EVENT\n', + '#EXT-X-TARGETDURATION:5\n', + '#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n', + '#EXTINF:2,\n', + 'main.mp4\n', + '#EXT-X-CUE:DURATION="201.467",ID="0",TYPE="SpliceOut",', + 'TIME="414.171"\n', + '#EXTINF:2,\n', + 'main2.mp4\n', + ].join(''); + + fakeNetEngine + .setResponseText('test:/master', master) + .setResponseText('test:/video', media) + .setResponseValue('test:/init.mp4', initSegmentData) + .setResponseValue('test:/main.mp4', segmentData); + + const spy = jasmine.createSpy('start'); + parser.start('test:/master', playerInterface) + .then(Util.spyFunc(spy), fail); + PromiseMock.flush(); + + expect(onSegmentParsedSpy).toHaveBeenCalledTimes(1); + expect(onSegmentParsedSpy).toHaveBeenCalledWith( + 'application/vnd.apple.mpegurl', + 1, + new shaka.hls.Segment( + 'test:/main.mp4', + [ + new shaka.hls.Tag(/* id */ 1, 'EXTINF', [], '2'), + ]) + ); + + // Replace the entries with the updated values. + fakeNetEngine + .setResponseText('test:/video', mediaWithAdditionalSegment); + + delayForUpdatePeriod(); + + expect(onSegmentParsedSpy).toHaveBeenCalledTimes(2); + expect(onSegmentParsedSpy).toHaveBeenCalledWith( + 'application/vnd.apple.mpegurl', + 1, + new shaka.hls.Segment( + 'test:/main2.mp4', + [ + new shaka.hls.Tag(/* id */ 1, 'EXTINF', [], '2'), + new shaka.hls.Tag(/* id */ 2, 'EXT-X-CUE', [ + new shaka.hls.Attribute('DURATION', '201.467'), + new shaka.hls.Attribute('ID', '0'), + new shaka.hls.Attribute('TYPE', 'SpliceOut'), + new shaka.hls.Attribute('TIME', '414.171'), + ]), + ] + ) + ); + }); + it('evicts removed segments', () => { const ref1 = ManifestParser.makeReference('test:/main.mp4', 0, 2, 4); diff --git a/test/hls/hls_parser_unit.js b/test/hls/hls_parser_unit.js index 09dbe9ac7c..469f8d44de 100644 --- a/test/hls/hls_parser_unit.js +++ b/test/hls/hls_parser_unit.js @@ -91,12 +91,23 @@ describe('HlsParser', () => { onError: fail, onEvent: fail, onTimelineRegionAdded: fail, + onSegmentParsed: fail, }; parser = new shaka.hls.HlsParser(); parser.configure(config); }); + /** @type {!jasmine.Spy} */ + let onSegmentParsedSpy; + + beforeEach(() => { + onSegmentParsedSpy = jasmine.createSpy('onSegmentParsed'); + playerInterface.onSegmentParsed = + shaka.test.Util.spyFunc(onSegmentParsedSpy); + }); + + /** * @param {string} master * @param {string} media diff --git a/test/test/util/dash_parser_util.js b/test/test/util/dash_parser_util.js index 5eca238cb7..0843a64cb3 100644 --- a/test/test/util/dash_parser_util.js +++ b/test/test/util/dash_parser_util.js @@ -50,6 +50,7 @@ shaka.test.Dash = class { filterNewPeriod: () => {}, filterAllPeriods: () => {}, onTimelineRegionAdded: fail, // Should not have any EventStream elements. + onSegmentParsed: fail, onEvent: fail, onError: fail, }; @@ -77,6 +78,7 @@ shaka.test.Dash = class { filterNewPeriod: () => {}, filterAllPeriods: () => {}, onTimelineRegionAdded: fail, // Should not have any EventStream elements. + onSegmentParsed: fail, onEvent: fail, onError: fail, }; diff --git a/test/test/util/util.js b/test/test/util/util.js index 9e5f312a12..f16726f01f 100644 --- a/test/test/util/util.js +++ b/test/test/util/util.js @@ -226,6 +226,40 @@ shaka.test.Util = class { return undefined; } + /** + * Custom comparer for HLS segments. + * @param {*} first + * @param {*} second + * @return {boolean|undefined} + */ + + static compareHlsSegments(first, second) { + const isHlsSegment = first instanceof shaka.hls.Segment && + second instanceof shaka.hls.Segment; + + if (isHlsSegment) { + return first.absoluteUri === second.absoluteUri && + compareTagsArray(first.tags, second.tags); + } + + return undefined; + + + function compareTagsArray(tags1, tags2) { + if (tags1 instanceof Array && tags2 instanceof Array) { + try { + const tagsAsString = (tagsArray) => tagsArray.map((tags) => + tags.toString()).sort().join(','); + + return tagsAsString(tags1) === tagsAsString(tags2); + } catch (e) { + return false; + } + } + return false; + } + } + /** * Fetches the resource at the given URI. * @@ -475,5 +509,6 @@ shaka.test.Util.customMatchers_ = { beforeEach(() => { jasmine.addCustomEqualityTester(shaka.test.Util.compareReferences); + jasmine.addCustomEqualityTester(shaka.test.Util.compareHlsSegments); jasmine.addMatchers(shaka.test.Util.customMatchers_); }); From df301ce7c327836135254b12c5d212299150a2da Mon Sep 17 00:00:00 2001 From: Anurag Kalia Date: Sat, 15 Jun 2019 03:15:39 +0530 Subject: [PATCH 3/5] Refactoring and documentation 1. Refactor code+comments to make changes clearer 2. Document SegmentParsedEvent 3. Modify the format of SegmentParsedEvent --- lib/hls/hls_parser.js | 16 ++++++++++------ lib/player.js | 19 ++++++++++++++++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/hls/hls_parser.js b/lib/hls/hls_parser.js index 45469dee95..5103cc9c2c 100644 --- a/lib/hls/hls_parser.js +++ b/lib/hls/hls_parser.js @@ -1452,12 +1452,15 @@ shaka.hls.HlsParser = class { const hlsSegments = playlist.segments; /** @type {Array.} */ const references = []; - let exisitingRefCount = 0; + // number of segment references in both the last and the current playlist + let reappearingRefsCount = 0; if (existingSegmentRefs.length > 0) { const earlierStartPosition = existingSegmentRefs[0].getPosition(); - exisitingRefCount = existingSegmentRefs.length - - (startPosition - earlierStartPosition); + // number of segment references in the last but not the current playlist + // (in HLS, segments are dropped only from the beginning of the playlist) + const droppedRefsCount = startPosition - earlierStartPosition; + reappearingRefsCount = existingSegmentRefs.length - droppedRefsCount; } goog.asserts.assert(hlsSegments.length, 'Playlist should have segments!'); // We may need to look at the media itself to determine a segment start @@ -1479,14 +1482,15 @@ shaka.hls.HlsParser = class { 'starts at', firstStartTime); // Append brand-new segments - for (let i = references.length; i < hlsSegments.length; ++i) { + for (let i = 0; i < hlsSegments.length; ++i) { const hlsSegment = hlsSegments[i]; const previousReference = references[references.length - 1]; const startTime = (i == 0) ? firstStartTime : previousReference.endTime; const position = startPosition + i; - if (i >= exisitingRefCount) { - // Only fire this event for brand new segments + if (i >= reappearingRefsCount) { + // Segment references which appeared only in the current playlist: + // Fire 'segmentparsed' event for them. this.playerInterface_.onSegmentParsed( 'application/vnd.apple.mpegurl', streamId, diff --git a/lib/player.js b/lib/player.js index 9a48f99a3c..85dd450aed 100644 --- a/lib/player.js +++ b/lib/player.js @@ -266,6 +266,17 @@ goog.require('shaka.util.StreamUtils'); * @exportDoc */ +/** + * @event shaka.Player.SegmentParsedEvent + * @description Optionally fired from inside a manifest parser plugin if a newly + * parsed segment has some extra metadata. It emits mime type of the parser, + * id of the stream that segment belonged to, and segment data (format may + * differ according to manifest parser). + * @property {string} type + * 'segmentparsed' + * @exportDoc + */ + /** * @event shaka.Player.StreamingEvent @@ -4265,9 +4276,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget { onSegmentParsed_(mimeType, streamId, segment) { const eventData = { - mimeType, - streamId, - segment, + detail: { + mimeType, + streamId, + segment, + }, }; this.dispatchEvent( From 1540464035280f64c45024e24edbd749e5f4b240 Mon Sep 17 00:00:00 2001 From: Anurag Kalia Date: Sat, 15 Jun 2019 10:07:47 +0530 Subject: [PATCH 4/5] Added type jsdoc + Changed SegmentParsedEvent Removed the nested 'detail' property to match other events. --- lib/hls/hls_parser.js | 12 +++++++++--- lib/player.js | 26 ++++++++++++++------------ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/hls/hls_parser.js b/lib/hls/hls_parser.js index 5103cc9c2c..8cda7011bc 100644 --- a/lib/hls/hls_parser.js +++ b/lib/hls/hls_parser.js @@ -1452,13 +1452,19 @@ shaka.hls.HlsParser = class { const hlsSegments = playlist.segments; /** @type {Array.} */ const references = []; - // number of segment references in both the last and the current playlist + /** + * Number of segment references in both the last and the current playlist. + * @type {number} + */ let reappearingRefsCount = 0; if (existingSegmentRefs.length > 0) { const earlierStartPosition = existingSegmentRefs[0].getPosition(); - // number of segment references in the last but not the current playlist - // (in HLS, segments are dropped only from the beginning of the playlist) + /** + * Number of segment references in the last but not the current playlist + * (in HLS, segments are dropped only from the beginning of the playlist). + * @type {number} + */ const droppedRefsCount = startPosition - earlierStartPosition; reappearingRefsCount = existingSegmentRefs.length - droppedRefsCount; } diff --git a/lib/player.js b/lib/player.js index 85dd450aed..d8ac3c4f75 100644 --- a/lib/player.js +++ b/lib/player.js @@ -269,11 +269,15 @@ goog.require('shaka.util.StreamUtils'); /** * @event shaka.Player.SegmentParsedEvent * @description Optionally fired from inside a manifest parser plugin if a newly - * parsed segment has some extra metadata. It emits mime type of the parser, - * id of the stream that segment belonged to, and segment data (format may - * differ according to manifest parser). + * parsed segment has some extra metadata. * @property {string} type * 'segmentparsed' + * @property {string} mimeType + * Mime type of the manifest parser. + * @property {number} streamId + * Id of the stream that segment belonged to. + * @property {*} segmentData + * Its format depends on the manifest parser. * @exportDoc */ @@ -4268,19 +4272,17 @@ shaka.Player = class extends shaka.util.FakeEventTarget { /** * Callback from player * - * @param {string} mimeType of the manifest-parser - * @param {number} streamId to which the segment belongs - * @param {*} segment segment metadata (format depends on mimeType+segment) + * @param {string} mimeType Mime type of the manifest parser. + * @property {number} streamId Id of the stream that segment belonged to. + * @property {*} segmentData Its format depends on the manifest parser. * @private */ - onSegmentParsed_(mimeType, streamId, segment) { + onSegmentParsed_(mimeType, streamId, segmentData) { const eventData = { - detail: { - mimeType, - streamId, - segment, - }, + mimeType, + streamId, + segmentData, }; this.dispatchEvent( From b83c2dbd2e2506d60f09b62b6d2feaccf63f6b96 Mon Sep 17 00:00:00 2001 From: Anurag Kalia Date: Sun, 16 Jun 2019 11:30:28 +0530 Subject: [PATCH 5/5] Fix: Build errors because of jsdoc --- lib/hls/hls_parser.js | 2 +- lib/player.js | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/hls/hls_parser.js b/lib/hls/hls_parser.js index 8cda7011bc..5efa5fbdbb 100644 --- a/lib/hls/hls_parser.js +++ b/lib/hls/hls_parser.js @@ -1450,7 +1450,7 @@ shaka.hls.HlsParser = class { streamId, existingSegmentRefs) { /** @type {Array.} */ const hlsSegments = playlist.segments; - /** @type {Array.} */ + /** @type {!Array.} */ const references = []; /** * Number of segment references in both the last and the current playlist. diff --git a/lib/player.js b/lib/player.js index d8ac3c4f75..6e04878538 100644 --- a/lib/player.js +++ b/lib/player.js @@ -4273,11 +4273,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget { * Callback from player * * @param {string} mimeType Mime type of the manifest parser. - * @property {number} streamId Id of the stream that segment belonged to. - * @property {*} segmentData Its format depends on the manifest parser. + * @param {number} streamId Id of the stream that segment belonged to. + * @param {*} segmentData Its format depends on the manifest parser. * @private */ - onSegmentParsed_(mimeType, streamId, segmentData) { const eventData = { mimeType,