From a2087467a6b9f458e4f7cbf94dda52db848bf75b Mon Sep 17 00:00:00 2001 From: Bertrand Berthelot Date: Mon, 15 Jun 2020 08:57:17 +0200 Subject: [PATCH] Fix regression for non-embedded text tracks (displayed twice) (#3290) --- src/core/events/CoreEvents.js | 1 - src/streaming/StreamProcessor.js | 25 ++-------- .../controllers/ScheduleController.js | 32 +++++++++---- .../text/NotFragmentedTextBufferController.js | 41 ++++++++-------- ....text.NotFragmentedTextBufferController.js | 47 +++---------------- 5 files changed, 52 insertions(+), 94 deletions(-) diff --git a/src/core/events/CoreEvents.js b/src/core/events/CoreEvents.js index 7ccf03bfc2..fc581abc7d 100644 --- a/src/core/events/CoreEvents.js +++ b/src/core/events/CoreEvents.js @@ -74,7 +74,6 @@ class CoreEvents extends EventsBase { this.STREAM_BUFFERING_COMPLETED = 'streamBufferingCompleted'; this.STREAM_COMPLETED = 'streamCompleted'; this.TEXT_TRACKS_QUEUE_INITIALIZED = 'textTracksQueueInitialized'; - this.TIMED_TEXT_REQUESTED = 'timedTextRequested'; this.TIME_SYNCHRONIZATION_COMPLETED = 'timeSynchronizationComplete'; this.URL_RESOLUTION_FAILED = 'urlResolutionFailed'; this.VIDEO_CHUNK_RECEIVED = 'videoChunkReceived'; diff --git a/src/streaming/StreamProcessor.js b/src/streaming/StreamProcessor.js index bb9b27bbc8..dc11be7889 100644 --- a/src/streaming/StreamProcessor.js +++ b/src/streaming/StreamProcessor.js @@ -169,10 +169,6 @@ function StreamProcessor(config) { settings: settings }); - if (adapter && adapter.getIsTextTrack(mimeType)) { - eventBus.on(Events.TIMED_TEXT_REQUESTED, onTimedTextRequested, this); - } - scheduleController.initialize(hasVideoTrack); streamInitialized = false; @@ -223,10 +219,6 @@ function StreamProcessor(config) { eventBus.off(Events.BUFFER_CLEARED, onBufferCleared, instance); eventBus.off(Events.SEEK_TARGET, onSeekTarget, instance); - if (adapter && adapter.getIsTextTrack(mimeType)) { - eventBus.off(Events.TIMED_TEXT_REQUESTED, onTimedTextRequested, this); - } - resetInitialSettings(); type = null; streamInfo = null; @@ -442,7 +434,9 @@ function StreamProcessor(config) { } function onInitFragmentNeeded(e) { - if (!e.sender || e.sender.getType() !== type || e.sender.getStreamId() !== streamInfo.id) return; + if (!e.sender || e.mediaType !== type || e.streamId !== streamInfo.id) return; + + if (adapter.getIsTextTrack(mimeType) && !textController.isTextEnabled()) return; if (bufferController && e.representationId) { if (!bufferController.appendInitSegment(e.representationId)) { @@ -454,7 +448,7 @@ function StreamProcessor(config) { } function onMediaFragmentNeeded(e) { - if (e.sender.getType() !== type || e.sender.getStreamId() !== streamInfo.id) return; + if (!e.sender || e.mediaType !== type || e.streamId !== streamInfo.id) return; let request; @@ -525,17 +519,6 @@ function StreamProcessor(config) { return request; } - function onTimedTextRequested(e) { - if (e.streamId !== streamInfo.id) return; - - //if subtitles are disabled, do not download subtitles file. - if (textController.isTextEnabled()) { - const representation = representationController ? representationController.getRepresentationForQuality(e.index) : null; - const request = indexHandler ? indexHandler.getInitRequest(getMediaInfo(), representation) : null; - scheduleController.processInitRequest(request); - } - } - function onMediaFragmentLoaded(e) { const chunk = e.chunk; if (chunk.streamId !== streamInfo.id || chunk.mediaInfo.type != type) return; diff --git a/src/streaming/controllers/ScheduleController.js b/src/streaming/controllers/ScheduleController.js index 3c491e033e..21d8619c61 100644 --- a/src/streaming/controllers/ScheduleController.js +++ b/src/streaming/controllers/ScheduleController.js @@ -157,13 +157,9 @@ function ScheduleController(config) { function schedule() { if (isStopped || isFragmentProcessingInProgress || (playbackController.isPaused() && !settings.get().streaming.scheduleWhilePaused) || - ((type === Constants.FRAGMENTED_TEXT || type === Constants.TEXT) && !textController.isTextEnabled())) { - logger.debug('Schedule stop!'); - return; - } - - if (bufferController.getIsBufferingCompleted()) { - logger.debug('Schedule stop because buffering is completed!'); + ((type === Constants.FRAGMENTED_TEXT || type === Constants.TEXT) && !textController.isTextEnabled()) || + bufferController.getIsBufferingCompleted()) { + stop(); return; } @@ -186,7 +182,12 @@ function ScheduleController(config) { } else { logger.debug('Quality has changed, get init request for representationid = ' + currentRepresentationInfo.id); } - eventBus.trigger(Events.INIT_FRAGMENT_NEEDED, { sender: instance, representationId: currentRepresentationInfo.id }); + eventBus.trigger(Events.INIT_FRAGMENT_NEEDED, { + sender: instance, + streamId: streamId, + mediaType: type, + representationId: currentRepresentationInfo.id + }); lastInitQuality = currentRepresentationInfo.quality; checkPlaybackQuality = false; } else { @@ -194,10 +195,21 @@ function ScheduleController(config) { if (replacement && replacement.isInitializationRequest()) { // To be sure the specific init segment had not already been loaded - eventBus.trigger(Events.INIT_FRAGMENT_NEEDED, { sender: instance, representationId: replacement.representationId }); + eventBus.trigger(Events.INIT_FRAGMENT_NEEDED, { + sender: instance, + streamId: streamId, + mediaType: type, + representationId: replacement.representationId + }); checkPlaybackQuality = false; } else { - eventBus.trigger(Events.MEDIA_FRAGMENT_NEEDED, { sender: instance, seekTarget: seekTarget, replacement: replacement }); + eventBus.trigger(Events.MEDIA_FRAGMENT_NEEDED, { + sender: instance, + streamId: streamId, + mediaType: type, + seekTarget: seekTarget, + replacement: replacement + }); checkPlaybackQuality = true; } } diff --git a/src/streaming/text/NotFragmentedTextBufferController.js b/src/streaming/text/NotFragmentedTextBufferController.js index 54bbf0ee09..f7079002ff 100644 --- a/src/streaming/text/NotFragmentedTextBufferController.js +++ b/src/streaming/text/NotFragmentedTextBufferController.js @@ -150,17 +150,25 @@ function NotFragmentedTextBufferController(config) { function onDataUpdateCompleted(e) { if (e.sender.getStreamId() !== streamInfo.id || e.sender.getType() !== type || e.error) return; - const currentRepresentation = e.sender.getCurrentRepresentation(); + if (initCache.extract(streamInfo.id, e.currentRepresentation.id) !== null) { + return; + } - const chunk = initCache.extract(streamInfo.id, currentRepresentation ? currentRepresentation.id : null); + // Representation has changed, clear buffer + isBufferingCompleted = false; - if (!chunk) { - eventBus.trigger(Events.TIMED_TEXT_REQUESTED, { - index: 0, - streamId: streamInfo.id, - sender: e.sender - }); //TODO make index dynamic if referring to MP? - } + // // Text data file is contained in initialization segment + eventBus.trigger(Events.INIT_FRAGMENT_NEEDED, { + sender: instance, + streamId: streamInfo.id, + mediaType: type, + representationId: e.currentRepresentation.id + }); + } + + function appendInitSegment(representationId) { + // If text data file already in cache then no need to append it again + return initCache.extract(streamInfo.id, representationId) !== null; } function onInitFragmentLoaded(e) { @@ -169,24 +177,13 @@ function NotFragmentedTextBufferController(config) { initCache.save(e.chunk); buffer.append(e.chunk); + isBufferingCompleted = true; + eventBus.trigger(Events.STREAM_COMPLETED, { request: e.request }); } - function appendInitSegment(representationId) { - const chunk = initCache.extract(streamInfo.id, representationId); - - if (!chunk) { - console.log('trigger TIMED_TEXT_REQUESTED'); - eventBus.trigger(Events.TIMED_TEXT_REQUESTED, { - index: 0, - streamId: streamInfo.id, - sender: instance - }); - } - } - function getRangeAt() { return null; } diff --git a/test/unit/streaming.text.NotFragmentedTextBufferController.js b/test/unit/streaming.text.NotFragmentedTextBufferController.js index ac95e1d5c4..b23a21423c 100644 --- a/test/unit/streaming.text.NotFragmentedTextBufferController.js +++ b/test/unit/streaming.text.NotFragmentedTextBufferController.js @@ -2,7 +2,6 @@ import NotFragmentedTextBufferController from '../../src/streaming/text/NotFragm import ObjectUtils from '../../src/streaming/utils/ObjectUtils'; import EventBus from '../../src/core/EventBus'; import Events from '../../src/core/events/Events'; -import InitCache from '../../src/streaming/utils/InitCache'; import ErrorHandlerMock from './mocks/ErrorHandlerMock'; import StreamProcessorMock from './mocks/StreamProcessorMock'; @@ -18,7 +17,6 @@ const streamInfo = { }; const eventBus = EventBus(context).getInstance(); const objectUtils = ObjectUtils(context).getInstance(); -const initCache = InitCache(context).getInstance(); describe('NotFragmentedTextBufferController', function () { @@ -127,57 +125,26 @@ describe('NotFragmentedTextBufferController', function () { }); }); - describe('Method appendInitSegment', function () { - // it('should not append init data to source buffer if data have already been cached', function () { - // let chunk = { - // bytes: 'initData', - // quality: 2, - // mediaInfo: { - // type: testType - // }, - // streamId: 'streamId', - // representationId: 'representationId' - // }; - - // initCache.save(chunk); - // notFragmentedTextBufferController.createBuffer(mockMediaInfoArr); - // const buffer = notFragmentedTextBufferController.getBuffer().getBuffer(); - // notFragmentedTextBufferController.appendInitSegment(chunk.representationId); - // expect(buffer.chunk).to.equal(null); - // }); - - it('should trigger TIMED_TEXT_REQUESTED if no init data is cached', function (done) { - - // reset cache - initCache.reset(); - - let onInitRequest = function () { - eventBus.off(Events.TIMED_TEXT_REQUESTED, onInitRequest); - done(); - }; - eventBus.on(Events.TIMED_TEXT_REQUESTED, onInitRequest, this); - - notFragmentedTextBufferController.appendInitSegment('representationId'); - }); - }); - describe('Event DATA_UPDATE_COMPLETED Handler', function () { - it('should trigger TIMED_TEXT_REQUESTED', function (done) { + it('should trigger INIT_FRAGMENT_NEEDED', function (done) { let event = { sender: { getType: function () { return testType; }, getStreamId: function () { return streamInfo.id; }, getCurrentRepresentation: function () { return { id: 0}; } - } + }, + streamId: streamInfo.id, + mediaType: testType, + currentRepresentation: { id: 0} }; let onEvent = function () { - eventBus.off(Events.TIMED_TEXT_REQUESTED, onEvent); + eventBus.off(Events.INIT_FRAGMENT_NEEDED, onEvent); done(); }; - eventBus.on(Events.TIMED_TEXT_REQUESTED, onEvent, this); + eventBus.on(Events.INIT_FRAGMENT_NEEDED, onEvent, this); eventBus.trigger(Events.DATA_UPDATE_COMPLETED, event); }); });