Skip to content

Commit

Permalink
708 caption signaling (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
gkatsev authored May 28, 2021
1 parent 23087dc commit 671bef4
Show file tree
Hide file tree
Showing 7 changed files with 371 additions and 3 deletions.
65 changes: 64 additions & 1 deletion src/inheritAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ export const parseCaptionServiceMetadata = (service) => {
const values = service.value.split(';');

return values.map((value) => {
let channel; let language;
let channel;
let language;

// default language to value
language = value;
Expand All @@ -215,6 +216,68 @@ export const parseCaptionServiceMetadata = (service) => {

return {channel, language};
});
} else if (service.schemeIdUri === 'urn:scte:dash:cc:cea-708:2015') {
const values = service.value.split(';');

return values.map((value) => {
const flags = {
// service or channel number 1-63
'channel': undefined,

// language is a 3ALPHA per ISO 639.2/B
// field is required
'language': undefined,

// BIT 1/0 or ?
// default value is 1, meaning 16:9 aspect ratio, 0 is 4:3, ? is unknown
'aspectRatio': 1,

// BIT 1/0
// easy reader flag indicated the text is tailed to the needs of beginning readers
// default 0, or off
'easyReader': 0,

// BIT 1/0
// If 3d metadata is present (CEA-708.1) then 1
// default 0
'3D': 0
};

if (/=/.test(value)) {

const [channel, opts = ''] = value.split('=');

flags.channel = channel;
flags.language = value;

opts.split(',').forEach((opt) => {
const [name, val] = opt.split(':');

if (name === 'lang') {
flags.language = val;

// er for easyReadery
} else if (name === 'er') {
flags.easyReader = Number(val);

// war for wide aspect ratio
} else if (name === 'war') {
flags.aspectRatio = Number(val);

} else if (name === '3D') {
flags['3D'] = Number(val);
}
});
} else {
flags.language = value;
}

if (flags.channel) {
flags.channel = 'SERVICE' + flags.channel;
}

return flags;
});
}
};

Expand Down
18 changes: 17 additions & 1 deletion src/toM3u8.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,29 @@ const organizeCaptionServices = (captionServices) => captionServices.reduce((svc
return svcObj;
}

svc.forEach(({channel, language}) => {
svc.forEach((service) => {
const {
channel,
language
} = service;

svcObj[language] = {
autoselect: false,
default: false,
instreamId: channel,
language
};

if (service.hasOwnProperty('aspectRatio')) {
svcObj[language].aspectRatio = service.aspectRatio;
}
if (service.hasOwnProperty('easyReader')) {
svcObj[language].easyReader = service.easyReader;
}
if (service.hasOwnProperty('3D')) {
svcObj[language]['3D'] = service['3D'];
}

});

return svcObj;
Expand Down
8 changes: 8 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import maatVttSegmentTemplate from './manifests/maat_vtt_segmentTemplate.mpd';
import segmentBaseTemplate from './manifests/segmentBase.mpd';
import segmentListTemplate from './manifests/segmentList.mpd';
import cc608CaptionsTemplate from './manifests/608-captions.mpd';
import cc708CaptionsTemplate from './manifests/708-captions.mpd';
import locationTemplate from './manifests/location.mpd';
import locationsTemplate from './manifests/locations.mpd';
import multiperiod from './manifests/multiperiod.mpd';
Expand All @@ -27,6 +28,9 @@ import {
import {
parsedManifest as cc608CaptionsManifest
} from './manifests/608-captions.js';
import {
parsedManifest as cc708CaptionsManifest
} from './manifests/708-captions.js';
import {
parsedManifest as multiperiodManifest
} from './manifests/multiperiod.js';
Expand Down Expand Up @@ -77,6 +81,10 @@ QUnit.test('has parse', function(assert) {
name: '608-captions',
input: cc608CaptionsTemplate,
expected: cc608CaptionsManifest
}, {
name: '708-captions',
input: cc708CaptionsTemplate,
expected: cc708CaptionsManifest
}, {
name: 'multiperiod',
input: multiperiod,
Expand Down
193 changes: 193 additions & 0 deletions test/inheritAttributes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,199 @@ QUnit.test('parsed 608 metadata', function(assert) {
}], 'eng;CC3');
});

QUnit.test('parsed 708 metadata', function(assert) {
const getmd = (value) => ({
schemeIdUri: 'urn:scte:dash:cc:cea-708:2015',
value
});

const assertServices = (services, expected, message) => {
if (!services) {
assert.notOk(expected, message);
return;
}

services.forEach((service, i) => {
assert.deepEqual(service, expected[i], message);
});
};

assertServices(parseCaptionServiceMetadata({
schemeIdUri: 'random scheme',
value: 'eng'
}), undefined, 'dont parse incorrect scheme for 708');

assertServices(parseCaptionServiceMetadata(getmd('eng')), [{
'channel': undefined,
'language': 'eng',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}], 'simple eng');

assertServices(parseCaptionServiceMetadata(getmd('eng;swe')), [{
'channel': undefined,
'language': 'eng',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'swe',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}], 'eng;swe');

assertServices(parseCaptionServiceMetadata(getmd('1=lang:eng;2=lang:swe')), [{
'channel': 'SERVICE1',
'language': 'eng',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': 'SERVICE2',
'language': 'swe',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}], '1=lang:eng;2=lang:swe');

assertServices(parseCaptionServiceMetadata(getmd('1=lang:eng;swe')), [{
'channel': 'SERVICE1',
'language': 'eng',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'swe',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}], 'mixed 1=lang:eng;swe');

assertServices(parseCaptionServiceMetadata(getmd('1=lang:eng;2=lang:eng,war:1,er:1')), [{
'channel': 'SERVICE1',
'language': 'eng',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': 'SERVICE2',
'language': 'eng',
'aspectRatio': 1,
'easyReader': 1,
'3D': 0
}], '1=lang:eng;2=lang:eng,war:1,er:1');

assertServices(parseCaptionServiceMetadata(getmd('1=lang:eng,war:0;2=lang:eng,3D:1,er:1')), [{
'channel': 'SERVICE1',
'language': 'eng',
'aspectRatio': 0,
'easyReader': 0,
'3D': 0
}, {
'channel': 'SERVICE2',
'language': 'eng',
'aspectRatio': 1,
'easyReader': 1,
'3D': 1
}], '1=lang:eng,war:0;2=lang:eng,3D:1,er:1');

assertServices(parseCaptionServiceMetadata(getmd('eng;fre;spa;jpn;deu;swe;kor;lat;zho;heb;rus;ara;hin;por;tur')), [{
'channel': undefined,
'language': 'eng',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'fre',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'spa',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'jpn',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'deu',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'swe',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'kor',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'lat',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'zho',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'heb',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'rus',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'ara',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'hin',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'por',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}, {
'channel': undefined,
'language': 'tur',
'aspectRatio': 1,
'easyReader': 0,
'3D': 0
}], 'make sure that parsing 15 services works');
});

QUnit.module('inheritAttributes');

QUnit.test('needs at least one Period', function(assert) {
Expand Down
2 changes: 1 addition & 1 deletion test/manifests/608-captions.mpd
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"></Role>
<Representation bandwidth="449000" codecs="avc1.420015" frameRate="2997/125" height="270" id="482" width="482" >
<SegmentBase></SegmentBase>
</Representation>
</Representation>
<BaseURL>1080p.ts</BaseURL>
<SegmentBase>
<RepresentationIndex sourceURL="1080p.sidx"/>
Expand Down
Loading

0 comments on commit 671bef4

Please sign in to comment.