Skip to content

Commit

Permalink
Add a working test for a basic ondemand SegmentTemplate. Getting a Re…
Browse files Browse the repository at this point in the history
…presentation is far harder than expected - DashManifestModel methods starting with getAdaptation... doesn't mean it'll get an adaptation, and it generally expects things to have happened in e.g. DashAdapter or DashHandler that augment the default objects before it works... Also always calculates full list of segments for an ondemand stream.
  • Loading branch information
Lloyd Wallis committed Aug 6, 2016
1 parent 250a018 commit 941b325
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 592 deletions.
1 change: 1 addition & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"devel" : true,
"browser": true,
"loopfunc" : true,
"multistr": true,

This comment has been minimized.

Copy link
@davemevans

davemevans Aug 8, 2016

FYI: this option has been deprecated. Whether we will move to a jshint version that cares is another matter ...

This comment has been minimized.

Copy link
@LloydW93

LloydW93 Aug 8, 2016

Then I guess we should move to having the MPDs as individual files, rather than an MPDfiles.js file...

"predef" : [
"it",
"describe",
Expand Down
7 changes: 4 additions & 3 deletions externals/xml2json.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,11 @@ function X2JS(matchers, attrPrefix, ignoreRoot) {
i,
len;

// get the first node that isn't a comment
// get the first node that we understand
for(i = 0, len = node.childNodes.length; i < len; i += 1) {
if (node.childNodes[i].nodeType !== DOMNodeTypes.COMMENT_NODE) {
child = node.childNodes[i];
let cNode = node.childNodes[i];
if (cNode.nodeType == DOMNodeTypes.ELEMENT_NODE || cNode.nodeType == DOMNodeTypes.TEXT_NODE || cNode.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) {

This comment has been minimized.

Copy link
@davemevans

davemevans Aug 8, 2016

Better than my solution. But do we understand CDATA?

This comment has been minimized.

Copy link
@LloydW93

LloydW93 Aug 8, 2016

This is just the set of nodes that xml2json actually parses later in the file. The node DOM library I added in this PR for testing outputs a Processing Instruction as the first body element, which xml2json doesn't understand how to process, and drops.

This comment has been minimized.

Copy link
@davemevans
child = cNode;
break;
}
}
Expand Down
3 changes: 2 additions & 1 deletion package.json
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"mocha": "^2.3.4",
"sinon": "^1.17.2",
"time-grunt": "^1.2.0",
"uglify-js": "^2.4.21"
"uglify-js": "^2.4.21",
"xmldom": "^0.1.22"
},
"dependencies": {
"codem-isoboxer": "0.2.2",
Expand Down
14 changes: 14 additions & 0 deletions src/core/Debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,25 @@ function Debug() {
eventBus.trigger(Events.LOG, {message: message});
}

/**
* Returns window.performance.now(), if available
* Otherwise falls back to Date()
* mocha doesn't have window.performance and it's possible some UAs don't either
*/
function timer() {

This comment has been minimized.

Copy link
@davemevans

davemevans Aug 8, 2016

👍 👍 👍

if (typeof performance !== "undefined") {
return performance.now();
} else {
return (new Date()).getTime();
}
}

instance = {
log: log,
setLogTimestampVisible: setLogTimestampVisible,
setLogToBrowserConsole: setLogToBrowserConsole,
getLogToBrowserConsole: getLogToBrowserConsole,
timer: timer
};

setup();
Expand Down
10 changes: 6 additions & 4 deletions src/dash/parser/DashParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ import SegmentValuesMap from './maps/SegmentValuesMap';
function DashParser(/*config*/) {

const context = this.context;
const log = Debug(context).getInstance().log;
const debug = Debug(context).getInstance();
const log = debug.log;
const timer = debug.timer;
const errorHandler = ErrorHandler(context).getInstance();

let instance,
Expand All @@ -69,19 +71,19 @@ function DashParser(/*config*/) {
var manifest;

try {
const startTime = window.performance.now();
const startTime = timer();

manifest = converter.xml_str2json(data);

if (!manifest) {
throw new Error('parser error');
}

const jsonTime = window.performance.now();
const jsonTime = timer();

objectIron.run(manifest);

const ironedTime = window.performance.now();
const ironedTime = timer();

xlinkController.setMatchers(matchers);
xlinkController.setIron(objectIron);
Expand Down
2 changes: 1 addition & 1 deletion src/dash/utils/SegmentsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export function decideSegmentListRangeForTemplate(timelineConverter, isDynamic,
};
var currentSegmentList = representation.segments;
var availabilityLowerLimit = 2 * duration;
var availabilityUpperLimit = givenAvailabilityUpperLimit || Math.max(2 * minBufferTime, 10 * duration);
var availabilityUpperLimit = givenAvailabilityUpperLimit || Number.POSITIVE_INFINITY;

var originAvailabilityTime = NaN;
var originSegment = null;
Expand Down
56 changes: 55 additions & 1 deletion test/dash.SegmentsGetterSpec.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,54 @@
import ObjectsHelper from './helpers/ObjectsHelper';
import VoHelper from './helpers/VOHelper';
import MPDfiles from './helpers/MPDfiles';

import SegmentsGetter from '../src/dash/utils/SegmentsGetter';
import DashParser from '../src/dash/parser/DashParser';
import DashManifestModel from '../src/dash/models/DashManifestModel';
import TimelineConverter from '../src/dash/utils/TimelineConverter';

const expect = require('chai').expect;
const DOMParser = require('xmldom').DOMParser;

describe('SegmentsGetter', function () {
const objectsHelper = new ObjectsHelper();
const voHelper = new VoHelper();

const createSegmentsGetter = (isDynamic) => {
const context = {};
const config = {};
const config = {
timelineConverter: createTimelineConverter()
};

return SegmentsGetter(context).create(config, !!isDynamic);
};

const createDashParser = () => {
const context = {};

return DashParser(context).create();
};

const createDashManifestModel = () => {
return DashManifestModel({}).getInstance();
};

const createTimelineConverter = () => {
return TimelineConverter({}).getInstance();
};

const parseManifest = xmlStr => {
const manifest = createDashParser().parse(xmlStr, objectsHelper.getDummyXlinkController());
manifest.loadedTime = {getTime: () => 0};
return manifest;
};

beforeEach(() => {
global.window = {
DOMParser: DOMParser
};
});

it('should not regenerate segments for a static MPD if they are already there', () => {
const segmentsGetter = createSegmentsGetter(false);
const representation = voHelper.createRepresentation('audio');
Expand All @@ -29,4 +64,23 @@ describe('SegmentsGetter', function () {
expect(segments[1]).to.deep.equal(voHelper.createSegment(1));
expect(segments.length).to.equal(2);
});

it('should calculate the correct number of segments for an ondemand SegmentTemplate manifest', (done) => {
const model = createDashManifestModel();
const timelineConverter = createTimelineConverter();
const manifest = parseManifest(MPDfiles.bbcrdtestcard);
const mpd = model.getMpd(manifest);
const period = model.getRegularPeriods(manifest, mpd)[0];
const adaptationIndex = model.getIndexForAdaptation(model.getAdaptationForType(manifest, 0, 'video'), manifest, period.index);
const adaptationSet = model.getAdaptationsForPeriod(manifest, period)[adaptationIndex];
const representations = model.getRepresentationsForAdaptation(manifest, adaptationSet);
const representation = representations[representations.length - 1];

representation.segmentAvailabilityRange = timelineConverter.calcSegmentAvailabilityRange(representation, model.getIsDynamic(manifest));

createSegmentsGetter().getSegments(representation, 0, 0, (representation, segments) => {
expect(segments.length).to.equal(938);
done();
});
});
});
Loading

1 comment on commit 941b325

@davemevans
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.