Skip to content
This repository has been archived by the owner on Jan 29, 2019. It is now read-only.

Commit

Permalink
Support for multiple CEA608 tracks and HLS-provided track names
Browse files Browse the repository at this point in the history
Thanks to @imbcmdth for the help.
  • Loading branch information
squarebracket committed Aug 11, 2017
1 parent 9e6a1d9 commit 6a5ab9d
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 53 deletions.
4 changes: 3 additions & 1 deletion src/add-text-track-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ const addTextTrackData = function(sourceHandler, captionArray, metadataArray) {

if (captionArray) {
captionArray.forEach(function(caption) {
this.inbandTextTrack_.addCue(
let track = caption.stream;

this.inbandTextTracks_[track].addCue(
new Cue(
caption.startTime + this.timestampOffset,
caption.endTime + this.timestampOffset,
Expand Down
11 changes: 10 additions & 1 deletion src/cleanup-text-tracks.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ export const removeExistingTrack = function(player, kind, label) {
* @private
*/
export const cleanupTextTracks = function(player) {
removeExistingTrack(player, 'captions', 'cc1');
const tracks = player.remoteTextTracks() || [];

for (let i = tracks.length - 1; i >= 0; i--) {
const track = tracks[i];

if (track.kind === 'captions') {
player.removeRemoteTextTrack(track);
}
}

removeExistingTrack(player, 'metadata', 'Timed Metadata');
};
36 changes: 28 additions & 8 deletions src/create-text-tracks-if-necessary.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,34 @@ const createTextTracksIfNecessary = function(sourceBuffer, mediaSource, segment)

// create an in-band caption track if one is present in the segment
if (segment.captions &&
segment.captions.length &&
!sourceBuffer.inbandTextTrack_) {
removeExistingTrack(player, 'captions', 'cc1');
sourceBuffer.inbandTextTrack_ = player.addRemoteTextTrack({
kind: 'captions',
label: 'cc1'
}, false).track;
player.tech_.trigger({type: 'usage', name: 'hls-608'});
segment.captions.length) {
if (!sourceBuffer.inbandTextTracks_) {
sourceBuffer.inbandTextTracks_ = {};
}

for (let trackId in segment.captionTracks) {
if (!sourceBuffer.inbandTextTracks_[trackId]) {
player.tech_.trigger({type: 'usage', name: 'hls-608'});
let track = player.textTracks().getTrackById(trackId);

if (track) {
// Resuse an existing track with a CC# id because this was
// very likely created by videojs-contrib-hls from information
// in the m3u8 for us to use
sourceBuffer.inbandTextTracks_[trackId] = track;
} else {
// Otherwise, create a track with the default `CC#` label and
// without a language
removeExistingTrack(player, 'captions', trackId);

sourceBuffer.inbandTextTracks_[trackId] = player.addRemoteTextTrack({
kind: 'captions',
id: trackId,
label: trackId
}, false).track;
}
}
}
}

if (segment.metadata &&
Expand Down
8 changes: 6 additions & 2 deletions src/flash-source-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ export default class FlashSourceBuffer extends videojs.EventTarget {
// of a buffered-range and everything else is reset on seek
this.mediaSource_.player_.on('seeked', () => {
removeCuesFromTrack(0, Infinity, this.metadataTrack_);
removeCuesFromTrack(0, Infinity, this.inbandTextTrack_);
for (let track in this.inbandTextTracks_) {
removeCuesFromTrack(0, Infinity, this.inbandTextTracks_[track]);
}
});

this.mediaSource_.player_.tech_.hls.on('dispose', () => {
Expand Down Expand Up @@ -245,7 +247,9 @@ export default class FlashSourceBuffer extends videojs.EventTarget {
*/
remove(start, end) {
removeCuesFromTrack(start, end, this.metadataTrack_);
removeCuesFromTrack(start, end, this.inbandTextTrack_);
for (let track in this.inbandTextTracks_) {
removeCuesFromTrack(start, end, this.inbandTextTracks_[track]);
}
this.trigger({ type: 'update' });
this.trigger({ type: 'updateend' });
}
Expand Down
6 changes: 5 additions & 1 deletion src/virtual-source-buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,11 @@ export default class VirtualSourceBuffer extends videojs.EventTarget {
removeCuesFromTrack(start, end, this.metadataTrack_);

// Remove Any Captions
removeCuesFromTrack(start, end, this.inbandTextTrack_);
if (this.inbandTextTracks_) {
for (let track in this.inbandTextTracks_) {
removeCuesFromTrack(start, end, this.inbandTextTracks_[track]);
}
}
}

/**
Expand Down
36 changes: 30 additions & 6 deletions test/add-text-track-data.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ class MockTextTrack {
module('Text Track Data', {
beforeEach() {
this.sourceHandler = {
inbandTextTrack_: new MockTextTrack(),
inbandTextTracks_: {
CC1: new MockTextTrack(),
CC2: new MockTextTrack(),
CC3: new MockTextTrack(),
CC4: new MockTextTrack()
},
metadataTrack_: new MockTextTrack(),
mediaSource_: {
duration: NaN
Expand All @@ -27,17 +32,36 @@ module('Text Track Data', {

test('does nothing if no cues are specified', function() {
addTextTrackData(this.sourceHandler, [], []);
equal(this.sourceHandler.inbandTextTrack_.cues.length, 0, 'added no 608 cues');
equal(this.sourceHandler.inbandTextTracks_.CC1.cues.length, 0, 'added no 608 cues');
equal(this.sourceHandler.metadataTrack_.cues.length, 0, 'added no metadata cues');
});

test('creates cues for 608 captions', function() {
test('creates cues for 608 captions with "stream" property in ccX', function() {
addTextTrackData(this.sourceHandler, [{
startTime: 0,
endTime: 1,
text: 'caption text'
text: 'CC1 text',
stream: 'CC1'
}, {
startTime: 0,
endTime: 1,
text: 'CC2 text',
stream: 'CC2'
}, {
startTime: 0,
endTime: 1,
text: 'CC3 text',
stream: 'CC3'
}, {
startTime: 0,
endTime: 1,
text: 'CC4 text',
stream: 'CC4'
}], []);
equal(this.sourceHandler.inbandTextTrack_.cues.length, 1, 'added one 608 cues');
equal(this.sourceHandler.inbandTextTracks_.CC1.cues.length, 1, 'added one 608 cues to CC1');
equal(this.sourceHandler.inbandTextTracks_.CC2.cues.length, 1, 'added one 608 cues to CC2');
equal(this.sourceHandler.inbandTextTracks_.CC3.cues.length, 1, 'added one 608 cues to CC3');
equal(this.sourceHandler.inbandTextTracks_.CC4.cues.length, 1, 'added one 608 cues to CC4');
equal(this.sourceHandler.metadataTrack_.cues.length, 0, 'added no metadata cues');
});

Expand All @@ -46,6 +70,6 @@ test('creates cues for timed metadata', function() {
cueTime: 1,
frames: [{}]
}]);
equal(this.sourceHandler.inbandTextTrack_.cues.length, 0, 'added no 608 cues');
equal(this.sourceHandler.inbandTextTracks_.CC1.cues.length, 0, 'added no 608 cues');
equal(this.sourceHandler.metadataTrack_.cues.length, 1, 'added one metadata cues');
});
18 changes: 16 additions & 2 deletions test/flash.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ const unfakeSTO = function() {

// Create a WebWorker-style message that signals the transmuxer is done
const createDataMessage = function(data, audioData, metadata, captions) {
let captionTracks = {};

if (captions) {
captions.forEach((caption) => {
captionTracks[caption.stream] = true;
});
}
return {
data: {
action: 'data',
Expand All @@ -82,7 +89,8 @@ const createDataMessage = function(data, audioData, metadata, captions) {
}) : []
},
metadata,
captions
captions,
captionTracks
}
}
};
Expand Down Expand Up @@ -1051,7 +1059,8 @@ QUnit.test('cleans up WebVTT cues on hls dispose', function() {
let captions = [{
startTime: 1,
endTime: 3,
text: 'This is an in-band caption'
text: 'This is an in-band caption',
stream: 'CC1'
}];

metadata.dispatchType = 0x10;
Expand All @@ -1068,6 +1077,11 @@ QUnit.test('cleans up WebVTT cues on hls dispose', function() {
addedTracks.push(trackEl.track);
return trackEl;
},
textTracks() {
return {
getTrackById() {}
};
},
remoteTextTracks() {
return addedTracks;
},
Expand Down
Loading

0 comments on commit 6a5ab9d

Please sign in to comment.