Skip to content

Commit

Permalink
Merge pull request #2610 from Orange-OpenSource/fix-NotFragmented-sub…
Browse files Browse the repository at this point in the history
…titles

Update not fragmented subtitles management
  • Loading branch information
epiclabsDASH committed Jun 8, 2018
2 parents a0e8eb7 + f7b2cb3 commit 70c83b7
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 45 deletions.
36 changes: 15 additions & 21 deletions src/streaming/Stream.js
Expand Up @@ -256,10 +256,6 @@ function Stream(config) {
}
}

function getMimeTypeOrType(mediaInfo) {
return mediaInfo.type === Constants.TEXT ? mediaInfo.mimeType : mediaInfo.type;
}

function isMediaSupported(mediaInfo) {
const type = mediaInfo.type;
let codec,
Expand Down Expand Up @@ -306,7 +302,7 @@ function Stream(config) {
trackChangedEvent = e;
manifestUpdater.refreshManifest();
} else {
processor.updateMediaInfo(mediaInfo);
processor.selectMediaInfo(mediaInfo);
if (mediaInfo.type !== Constants.FRAGMENTED_TEXT) {
abrController.updateTopQualityIndex(mediaInfo);
processor.switchTrackAsked();
Expand All @@ -317,7 +313,7 @@ function Stream(config) {

function createStreamProcessor(mediaInfo, allMediaForType, mediaSource, optionalSettings) {
let streamProcessor = StreamProcessor(context).create({
type: getMimeTypeOrType(mediaInfo),
type: mediaInfo.type,
mimeType: mediaInfo.mimeType,
timelineConverter: timelineConverter,
adapter: adapter,
Expand Down Expand Up @@ -358,13 +354,11 @@ function Stream(config) {
if (allMediaForType[i].index === mediaInfo.index) {
idx = i;
}
streamProcessor.updateMediaInfo(allMediaForType[i]); //creates text tracks for all adaptations in one stream processor
}
if (mediaInfo.type === Constants.FRAGMENTED_TEXT) {
streamProcessor.updateMediaInfo(allMediaForType[idx]); //sets the initial media info
streamProcessor.addMediaInfo(allMediaForType[i]); //creates text tracks for all adaptations in one stream processor
}
streamProcessor.selectMediaInfo(allMediaForType[idx]); //sets the initial media info
} else {
streamProcessor.updateMediaInfo(mediaInfo);
streamProcessor.addMediaInfo(mediaInfo, true);
}
}

Expand Down Expand Up @@ -515,13 +509,13 @@ function Stream(config) {

function getMediaInfo(type) {
const ln = streamProcessors.length;
let mediaCtrl = null;
let streamProcessor = null;

for (let i = 0; i < ln; i++) {
mediaCtrl = streamProcessors[i];
streamProcessor = streamProcessors[i];

if (mediaCtrl.getType() === type) {
return mediaCtrl.getMediaInfo();
if (streamProcessor.getType() === type) {
return streamProcessor.getMediaInfo();
}
}

Expand Down Expand Up @@ -591,14 +585,14 @@ function Stream(config) {
let arr = [];

let type,
controller;
streamProcessor;

for (let i = 0; i < ln; i++) {
controller = streamProcessors[i];
type = controller.getType();
streamProcessor = streamProcessors[i];
type = streamProcessor.getType();

if (type === Constants.AUDIO || type === Constants.VIDEO || type === Constants.FRAGMENTED_TEXT) {
arr.push(controller);
if (type === Constants.AUDIO || type === Constants.VIDEO || type === Constants.FRAGMENTED_TEXT || type === Constants.TEXT) {
arr.push(streamProcessor);
}
}

Expand All @@ -624,7 +618,7 @@ function Stream(config) {
let streamProcessor = streamProcessors[i];
let mediaInfo = adapter.getMediaInfoForType(streamInfo, streamProcessor.getType());
abrController.updateTopQualityIndex(mediaInfo);
streamProcessor.updateMediaInfo(mediaInfo);
streamProcessor.addMediaInfo(mediaInfo, true);
}

if (trackChangedEvent) {
Expand Down
16 changes: 13 additions & 3 deletions src/streaming/StreamProcessor.js
Expand Up @@ -104,6 +104,7 @@ function StreamProcessor(config) {
bufferController = createBufferControllerForType(type);
scheduleController = ScheduleController(context).create({
type: type,
mimeType: mimeType,
metricsModel: metricsModel,
adapter: adapter,
dashMetrics: dashMetrics,
Expand Down Expand Up @@ -243,14 +244,21 @@ function StreamProcessor(config) {
return stream ? stream.getEventController() : null;
}

function updateMediaInfo(newMediaInfo) {
function selectMediaInfo(newMediaInfo) {
if (newMediaInfo !== mediaInfo && (!newMediaInfo || !mediaInfo || (newMediaInfo.type === mediaInfo.type))) {
mediaInfo = newMediaInfo;
}
adapter.updateData(this);
}

function addMediaInfo(newMediaInfo, selectNewMediaInfo) {
if (mediaInfoArr.indexOf(newMediaInfo) === -1) {
mediaInfoArr.push(newMediaInfo);
}
adapter.updateData(this);

if (selectNewMediaInfo) {
this.selectMediaInfo(newMediaInfo);
}
}

function getMediaInfoArr() {
Expand Down Expand Up @@ -332,6 +340,7 @@ function StreamProcessor(config) {
} else {
controller = TextBufferController(context).create({
type: type,
mimeType: mimeType,
metricsModel: metricsModel,
mediaPlayerModel: mediaPlayerModel,
manifestModel: manifestModel,
Expand Down Expand Up @@ -368,7 +377,8 @@ function StreamProcessor(config) {
isBufferingCompleted: isBufferingCompleted,
createBuffer: createBuffer,
getStreamInfo: getStreamInfo,
updateMediaInfo: updateMediaInfo,
selectMediaInfo: selectMediaInfo,
addMediaInfo: addMediaInfo,
switchTrackAsked: switchTrackAsked,
getMediaInfoArr: getMediaInfoArr,
getMediaInfo: getMediaInfo,
Expand Down
2 changes: 1 addition & 1 deletion src/streaming/controllers/ScheduleController.js
Expand Up @@ -106,7 +106,7 @@ function ScheduleController(config) {
textController: textController
});

if (dashManifestModel.getIsTextTrack(type)) {
if (dashManifestModel.getIsTextTrack(config.mimeType)) {
eventBus.on(Events.TIMED_TEXT_REQUESTED, onTimedTextRequested, this);
}

Expand Down
29 changes: 20 additions & 9 deletions src/streaming/text/NotFragmentedTextBufferController.js
Expand Up @@ -46,6 +46,7 @@ function NotFragmentedTextBufferController(config) {

let errHandler = config.errHandler;
let type = config.type;
let mimeType = config.mimeType;
let streamProcessor = config.streamProcessor;

let instance,
Expand Down Expand Up @@ -86,7 +87,7 @@ function NotFragmentedTextBufferController(config) {
if (!initialized) {
const textBuffer = buffer.getBuffer();
if (textBuffer.hasOwnProperty(Constants.INITIALIZE)) {
textBuffer.initialize(type, streamProcessor);
textBuffer.initialize(mimeType, streamProcessor);
}
initialized = true;
}
Expand Down Expand Up @@ -158,26 +159,36 @@ function NotFragmentedTextBufferController(config) {
return;
}

eventBus.trigger(Events.TIMED_TEXT_REQUESTED, {
index: 0,
sender: e.sender
}); //TODO make index dynamic if referring to MP?
const chunk = initCache.extract(streamProcessor.getStreamInfo().id, e.sender.getCurrentRepresentation().id);

if (!chunk) {
eventBus.trigger(Events.TIMED_TEXT_REQUESTED, {
index: 0,
sender: e.sender
}); //TODO make index dynamic if referring to MP?
}
}

function onInitFragmentLoaded(e) {
if (e.fragmentModel !== streamProcessor.getFragmentModel() || (!e.chunk.bytes)) {
return;
}

initCache.save(e.chunk);
buffer.append(e.chunk);

eventBus.trigger(Events.STREAM_COMPLETED, {
request: e.request,
fragmentModel: e.fragmentModel
});
}

function switchInitData(streamId, representationId) {
const chunk = initCache.extract(streamId, representationId);
if (chunk) {
buffer.append(chunk);
} else {
eventBus.trigger(Events.INIT_REQUESTED, {

if (!chunk) {
eventBus.trigger(Events.TIMED_TEXT_REQUESTED, {
index: 0,
sender: instance
});
}
Expand Down
1 change: 1 addition & 0 deletions src/streaming/text/TextBufferController.js
Expand Up @@ -67,6 +67,7 @@ function TextBufferController(config) {
// in this case, internal buffer controller is a not fragmented text controller object
_BufferControllerImpl = NotFragmentedTextBufferController(context).create({
type: config.type,
mimeType: config.mimeType,
errHandler: config.errHandler,
streamProcessor: config.streamProcessor
});
Expand Down
20 changes: 20 additions & 0 deletions src/streaming/text/TextController.js
Expand Up @@ -225,6 +225,8 @@ function TextController() {
let config = textSourceBuffer.getConfig();
let fragmentModel = config.fragmentModel;
let fragmentedTracks = config.fragmentedTracks;
let mediaInfosArr,
streamProcessor;

let oldTrackIdx = textTracks.getCurrentTrackIdx();
if (oldTrackIdx !== idx) {
Expand All @@ -250,6 +252,24 @@ function TextController() {
}
}
}
} else if (currentTrackInfo && !currentTrackInfo.isFragmented) {
const streamProcessors = streamController.getActiveStreamProcessors();
for (let i = 0; i < streamProcessors.length; i++) {
if (streamProcessors[i].getType() === Constants.TEXT) {
streamProcessor = streamProcessors[i];
mediaInfosArr = streamProcessor.getMediaInfoArr();
break;
}
}

if (streamProcessor && mediaInfosArr) {
for (let i = 0; i < mediaInfosArr.length; i++) {
if (mediaInfosArr[i].index === currentTrackInfo.index && mediaInfosArr[i].lang === currentTrackInfo.lang) {
streamProcessor.selectMediaInfo(mediaInfosArr[i]);
break;
}
}
}
}
}

Expand Down
11 changes: 7 additions & 4 deletions src/streaming/text/TextSourceBuffer.js
Expand Up @@ -84,7 +84,7 @@ function TextSourceBuffer() {
logger = Debug(context).getInstance().getLogger(instance);
}

function initialize(type, streamProcessor) {
function initialize(mimeType, streamProcessor) {
parser = null;
fragmentModel = null;
initializationSegmentReceived = false;
Expand All @@ -101,7 +101,7 @@ function TextSourceBuffer() {
videoModel: videoModel
});
textTracks.initialize();
isFragmented = !dashManifestModel.getIsTextTrack(type);
isFragmented = !dashManifestModel.getIsTextTrack(mimeType);
boxParser = BoxParser(context).getInstance();
fragmentedTextBoxParser = FragmentedTextBoxParser(context).getInstance();
fragmentedTextBoxParser.setConfig({
Expand Down Expand Up @@ -302,7 +302,7 @@ function TextSourceBuffer() {

textTrackInfo.captionData = captionData;
textTrackInfo.lang = mediaInfo.lang;
textTrackInfo.label = mediaInfo.id; // AdaptationSet id (an unsigned int)
textTrackInfo.label = mediaInfo.id ? mediaInfo.id : mediaInfo.index; // AdaptationSet id (an unsigned int) as it's optionnal parameter, use mediaInfo.index
textTrackInfo.index = mediaInfo.index; // AdaptationSet index in manifest
textTrackInfo.isTTML = checkTTML();
textTrackInfo.defaultTrack = getIsDefault(mediaInfo);
Expand Down Expand Up @@ -407,7 +407,10 @@ function TextSourceBuffer() {

try {
result = getParser(codecType).parse(ccContent, 0);
createTextTrackFromMediaInfo(result, mediaInfo);
for (i = 0; i < mediaInfos.length; i++) {
createTextTrackFromMediaInfo(null, mediaInfos[i]);
}
textTracks.addCaptions(textTracks.getCurrentTrackIdx(), 0, result);
} catch (e) {
errHandler.timedTextError(e, 'parse', ccContent);
}
Expand Down
2 changes: 2 additions & 0 deletions test/unit/mocks/StreamControllerMock.js
Expand Up @@ -46,6 +46,8 @@ class StreamControllerMock {
setConfig() {}

reset() {}

getActiveStreamProcessors() { return [];}
}

export default StreamControllerMock;
13 changes: 7 additions & 6 deletions test/unit/streaming.text.NotFragmentedTextBufferController.js
Expand Up @@ -133,7 +133,7 @@ describe('NotFragmentedTextBufferController', function () {
});

describe('Method switchInitData', function () {
it('should append init data to source buffer if data have been cached', function () {
it('should not append init data to source buffer if data have already been cached', function () {
let chunk = {
bytes: 'initData',
quality: 2,
Expand All @@ -148,19 +148,19 @@ describe('NotFragmentedTextBufferController', function () {
notFragmentedTextBufferController.createBuffer(mockMediaInfo);
const buffer = notFragmentedTextBufferController.getBuffer().getBuffer();
notFragmentedTextBufferController.switchInitData(chunk.streamId, chunk.representationId);
expect(buffer.chunk).to.equal(chunk.bytes);
expect(buffer.chunk).to.equal(null);
});

it('should trigger INIT_REQUESTED if no init data is cached', function (done) {
it('should trigger TIMED_TEXT_REQUESTED if no init data is cached', function (done) {

// reset cache
initCache.reset();

let onInitRequest = function () {
eventBus.off(Events.INIT_REQUESTED, onInitRequest);
eventBus.off(Events.TIMED_TEXT_REQUESTED, onInitRequest);
done();
};
eventBus.on(Events.INIT_REQUESTED, onInitRequest, this);
eventBus.on(Events.TIMED_TEXT_REQUESTED, onInitRequest, this);

notFragmentedTextBufferController.switchInitData('streamId', 'representationId');
});
Expand All @@ -172,7 +172,8 @@ describe('NotFragmentedTextBufferController', function () {

let event = {
sender: {
getStreamProcessor: function () { return streamProcessorMock; }
getStreamProcessor: function () { return streamProcessorMock; },
getCurrentRepresentation: function () { return { id: 0}; }
}
};

Expand Down
5 changes: 4 additions & 1 deletion test/unit/streaming.text.TextController.js
Expand Up @@ -6,6 +6,7 @@ import EventBus from '../../src/core/EventBus';
import Events from '../../src/core/events/Events';

import VideoModelMock from './mocks/VideoModelMock';
import StreamControllerMock from './mocks/StreamControllerMock';

const expect = require('chai').expect;
const context = {};
Expand All @@ -16,6 +17,7 @@ const eventBus = EventBus(context).getInstance();
describe('TextController', function () {

let videoModelMock = new VideoModelMock();
let streamControllerMock = new StreamControllerMock();
let textTracks;
let textController;

Expand All @@ -27,7 +29,8 @@ describe('TextController', function () {

textController = TextController(context).getInstance();
textController.setConfig({
videoModel: videoModelMock
videoModel: videoModelMock,
streamController: streamControllerMock
});
});

Expand Down

0 comments on commit 70c83b7

Please sign in to comment.