Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix regression for non-embedded text tracks #3290

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion src/core/events/CoreEvents.js
Expand Up @@ -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';
Expand Down
25 changes: 4 additions & 21 deletions src/streaming/StreamProcessor.js
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
32 changes: 22 additions & 10 deletions src/streaming/controllers/ScheduleController.js
Expand Up @@ -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;
}

Expand All @@ -186,18 +182,34 @@ 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 {
const replacement = replaceRequestArray.shift();

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;
}
}
Expand Down
41 changes: 19 additions & 22 deletions src/streaming/text/NotFragmentedTextBufferController.js
Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down
47 changes: 7 additions & 40 deletions test/unit/streaming.text.NotFragmentedTextBufferController.js
Expand Up @@ -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';
Expand All @@ -18,7 +17,6 @@ const streamInfo = {
};
const eventBus = EventBus(context).getInstance();
const objectUtils = ObjectUtils(context).getInstance();
const initCache = InitCache(context).getInstance();

describe('NotFragmentedTextBufferController', function () {

Expand Down Expand Up @@ -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);
});
});
Expand Down