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(dash): dedup stream logic #3725

Closed
wants to merge 5 commits into from
Closed
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: 1 addition & 0 deletions AUTHORS
Expand Up @@ -31,6 +31,7 @@ Edgeware AB <*@edgeware.tv>
Esteban Dosztal <edosztal@gmail.com>
Fadomire <fadomire@gmail.com>
Gil Gonen <gil.gonen@gmail.com>
Giorgio Gamberoni <giorgio.gamberoni@gmail.com>
Giuseppe Samela <giuseppe.samela@gmail.com>
Google Inc. <*@google.com>
Itay Kinnrot <Itay.Kinnrot@Kaltura.com>
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS
Expand Up @@ -48,6 +48,7 @@ Esteban Dosztal <edosztal@gmail.com>
Fadomire <fadomire@gmail.com>
François Beaufort <fbeaufort@google.com>
Gil Gonen <gil.gonen@gmail.com>
Giorgio Gamberoni <giorgio.gamberoni@gmail.com>
Giuseppe Samela <giuseppe.samela@gmail.com>
Hichem Taoufik <hichem@code-it.fr>
Itay Kinnrot <itay.kinnrot@kaltura.com>
Expand Down
6 changes: 5 additions & 1 deletion lib/util/periods.js
Expand Up @@ -263,6 +263,7 @@ shaka.util.PeriodCombiner = class {
a1.label == a2.label &&
a1.codecs == a2.codecs &&
a1.mimeType == a2.mimeType &&
a1.originalId == a2.originalId &&
ArrayUtils.hasSameElements(a1.roles, a2.roles) &&
a1.audioSamplingRate == a2.audioSamplingRate &&
a1.primary == a2.primary) {
Expand Down Expand Up @@ -298,6 +299,7 @@ shaka.util.PeriodCombiner = class {
t1.label == t2.label &&
t1.codecs == t2.codecs &&
t1.mimeType == t2.mimeType &&
t1.originalId == t2.originalId &&
ArrayUtils.hasSameElements(t1.roles, t2.roles)) {
duplicate = true;
}
Expand Down Expand Up @@ -333,6 +335,7 @@ shaka.util.PeriodCombiner = class {
v1.codecs == v2.codecs &&
v1.mimeType == v2.mimeType &&
v1.label == v2.label &&
v1.originalId == v2.originalId &&
ArrayUtils.hasSameElements(v1.roles, v2.roles) &&
MapUtils.hasSameElements(v1.closedCaptions, v2.closedCaptions) &&
v1.bandwidth == v2.bandwidth) {
Expand Down Expand Up @@ -365,7 +368,8 @@ shaka.util.PeriodCombiner = class {
if (i1.id != i2.id &&
i1.width == i2.width &&
i1.codecs == i2.codecs &&
i1.mimeType == i2.mimeType) {
i1.mimeType == i2.mimeType &&
i1.originalId == i2.originalId) {
duplicate = true;
}
}
Expand Down
84 changes: 59 additions & 25 deletions test/util/periods_unit.js
Expand Up @@ -446,78 +446,111 @@ describe('PeriodCombiner', () => {
it('Filters out duplicate streams', async () => {
// v1 and v3 are duplicates
const v1 = makeVideoStream(1280);
v1.id = 1;
v1.frameRate = 30000/1001;
v1.originalId = 'v1';
v1.originalId = 'video/1280';
v1.bandwidth = 6200000;

const v2 = makeVideoStream(1920);
v2.id = 2;
v2.frameRate = 30000/1001;
v2.originalId = 'v2';
v2.originalId = 'video/1920';
v2.bandwidth = 8000000;

const v3 = makeVideoStream(1280);
v3.id = 3;
v3.frameRate = 30000/1001;
v3.originalId = 'v3';
v3.originalId = 'video/1280';
v3.bandwidth = 6200000;

// a1 and a2 are duplicates.
const a1 = makeAudioStream('en', /* channels= */ 2);
a1.originalId = 'a1';
a1.id = 1;
a1.originalId = 'audio/65106';
a1.bandwidth = 65106;
a1.roles = ['role1', 'role2'];
a1.codecs = 'mp4a.40.2';

const a2 = makeAudioStream('en', /* channels= */ 2);
a2.originalId = 'a2';
a2.id = 2;
a2.originalId = 'audio/65106';
a2.bandwidth = 65106;
a2.roles = ['role1', 'role2'];
a2.codecs = 'mp4a.40.2';

const a3 = makeAudioStream('en', /* channels= */ 2);
a3.originalId = 'a3';
a3.id = 3;
a3.originalId = 'audio/97065';
a3.bandwidth = 97065;
a3.roles = ['role1', 'role2'];
a2.codecs = 'mp4a.40.2';
a3.codecs = 'mp4a.40.2';

// a4 has a different label from a3, and should not
// be filtered out.
const a4 = makeAudioStream('en', /* channels= */ 2);
a4.originalId = 'a4';
a4.bandwidth = 97065;
a4.id = 4;
a4.originalId = 'audio/65106';
a4.bandwidth = 65106;
a4.roles = ['role1', 'role2'];
a4.label = 'Surround';
a4.codecs = 'mp4a.40.2';

// a5 has a different codec from a3, and should not
// be filtered out.
const a5 = makeAudioStream('en', /* channels= */ 2);
a5.originalId = 'a5';
a5.id = 5;
a5.originalId = 'audio/97065';
a5.bandwidth = 97065;
a5.roles = ['role1', 'role2'];
a5.codecs = 'ec-3';

// t1 and t3 are duplicates.
const t1 = makeTextStream('en');
t1.originalId = 't1';
t1.id = 1;
t1.originalId = 'text/en';
t1.language = 'en';
t1.mimeType = 'application/mp4';
t1.codecs = 'stpp';
t1.roles = ['role1'];

const t2 = makeTextStream('en');
t2.originalId = 't2';
t2.id = 2;
t2.originalId = 'text/en';
t2.language = 'en';
t2.mimeType = 'application/mp4';
t2.codecs = 'stpp';
t2.roles = ['role1', 'role2'];

const t3 = makeTextStream('en');
t3.originalId = 't3';
t3.id = 3;
t3.originalId = 'text/en';
t3.language = 'en';
t3.mimeType = 'application/mp4';
t3.codecs = 'stpp';
t3.roles = ['role1'];

// t4 has a different original Id from t3, and should not
// be filtered out.
const t4 = makeAudioStream('en', /* channels= */ 2);
t4.id = 4;
t4.originalId = 'text/en-us';
t4.language = 'en';
t4.mimeType = 'application/mp4';
t4.codecs = 'stpp';
t4.roles = ['role1'];

// i1 and i3 are duplicates.
const i1 = makeImageStream(240);
i1.originalId = 'i1';
i1.id = 1;
i1.originalId = 'image/240';

const i2 = makeImageStream(480);
i2.originalId = 'i2';
i2.id = 2;
i2.originalId = 'image/480';

const i3 = makeImageStream(240);
i3.originalId = 'i3';
i3.id = 3;
i3.originalId = 'image/240';

/** @type {!Array.<shaka.util.PeriodCombiner.Period>} */
const periods = [
Expand All @@ -539,6 +572,7 @@ describe('PeriodCombiner', () => {
t1,
t2,
t3,
t4,
],
imageStreams: [
i1,
Expand All @@ -553,33 +587,33 @@ describe('PeriodCombiner', () => {
expect(variants.length).toBe(8);

// v3 should've been filtered out
const videoIds = variants.map((v) => v.video.originalId);
const videoIds = variants.map((v) => v.video.id);
for (const id of videoIds) {
expect(id).not.toBe('v3');
expect(id).not.toBe(3);
}

// a2 should've been filtered out
const audioIds = variants.map((v) => v.audio.originalId);
const audioIds = variants.map((v) => v.audio.id);
for (const id of audioIds) {
expect(id).not.toBe('a2');
expect(id).not.toBe(2);
}

const textStreams = combiner.getTextStreams();
expect(textStreams.length).toBe(2);
expect(textStreams.length).toBe(3);

// t3 should've been filtered out
const textIds = textStreams.map((t) => t.originalId);
const textIds = textStreams.map((t) => t.id);
for (const id of textIds) {
expect(id).not.toBe('t3');
expect(id).not.toBe(3);
}

const imageStreams = combiner.getImageStreams();
expect(imageStreams.length).toBe(2);

// i3 should've been filtered out
const imageIds = imageStreams.map((i) => i.originalId);
const imageIds = imageStreams.map((i) => i.id);
for (const id of imageIds) {
expect(id).not.toBe('i3');
expect(id).not.toBe(3);
}
});

Expand Down