32 Components.utils.import(
"resource://gre/modules/XPCOMUtils.jsm");
33 Components.utils.import(
"resource://app/jsmodules/ArrayConverter.jsm");
40 var newProps =
Cc[
"@songbirdnest.com/moz/xpcom/sbpropertybag;1"]
41 .createInstance(
Ci.nsIWritablePropertyBag2);
44 var sip =
Cc[
"@mozilla.org/supports-interface-pointer;1"]
45 .createInstance(
Ci.nsISupportsInterfacePointer);
46 sip.data = aPropertyBag;
47 if (sip.data instanceof
Ci.nsIPropertyBag) {
48 for each (var prop
in ArrayConverter.JSEnum(sip.data.enumerator)) {
49 newProps.setProperty(prop.name, prop.value);
54 for (var prop in aPropertyBag) {
55 newProps.setProperty(prop, aPropertyBag[prop]);
65 function F(aNumerator, aDenominator) {
67 numerator: aNumerator,
68 denominator: aDenominator,
79 var
range =
Cc[
"@songbirdnest.com/Songbird/Device/sbrange;1"]
80 .createInstance(
Ci.sbIDevCapRange);
81 if (aInput ===
null) {
85 if (aInput instanceof
Array) {
86 for each (let
val in aInput) {
91 range.Initialize(aInput.min, aInput.max, aInput.step);
100 inputUri:
"x-transcode-test:default-input",
102 containerType:
"container/default",
106 videoType:
"video/default",
110 frameRate:
F(30000, 1001),
112 getVideoPAR:
function videoFormat_getVideoPAR(aNum, aDenom) {
113 aNum.value = this.PAR.numerator;
114 aDenom.value = this.PAR.denominator;
116 getVideoFrameRate:
function videoFormat_getVideoFrameRate(aNum, aDenom) {
117 aNum.value = this.frameRate.numerator;
118 aDenom.value = this.frameRate.denominator;
123 audioType:
"audio/default",
137 containerType:
"application/ogg",
139 type:
"video/x-theora",
141 widths: {
min: 16, step: 16, max: 320},
142 heights: {
min: 16, step: 16, max: 240},
144 frameRates: [
F(15, 1),
F(30000, 1001)],
145 bitRates: {
min: 0, step:1, max: 4000000}
148 type:
"audio/x-vorbis",
149 bitRates: {
min: 0, step: 1, max: 400000},
150 sampleRates: [44100],
160 fileExtension:
"ogg",
161 videoEncoder:
"theoraenc",
162 audioEncoder:
"vorbisenc",
167 frameRate:
F(30000, 1001),
179 assertTrue(aBitrate >= aCaps.video.bitRates.min / 1000);
180 assertTrue(aBitrate <= aCaps.video.bitRates.max / 1000);
181 assertTrue(aBitrate >= aMin,
"Bitrate too low");
182 assertTrue(aBitrate <= aMax,
"Bitrate too high");
187 { description:
"default",
191 bitrate:
function(bitrate) {
198 "max-bitrate": 128000
203 { description:
"scale down with empty areas",
215 bitrate:
function(bitrate) {
222 { description:
"scale down with padding",
243 { description:
"scale up with empty areas",
252 widths: {
min: 320, max: 1024, step: 16},
253 heights: {
min: 240, max: 1024, step: 16}
263 { description:
"scale up with padding",
283 { description:
"reduce fps",
286 frameRate:
F(24000, 1001)
291 frameRates: [
F(15, 1),
F(60000, 1001)]
300 { description:
"increase fps",
303 frameRate:
F(24000, 1001)
308 frameRates: [
F(15, 1),
F(30000, 1001)]
313 frameRate:
F(30000, 1001)
317 { description:
"no change",
323 frameRate:
F(24000, 1001)
328 widths: {
min: 640, step: 1, max: 1024},
329 heights: {
min: 480, step: 1, max: 768},
330 PARs: [
F(1, 1),
F(2, 1),
F(3, 2)],
331 frameRates: {
min:
F(0, 1), max:
F(30000, 1001)},
332 bitRates: {
min: 1, step: 1, max: 2000000}
340 frameRate:
F(24000, 1001),
342 bitrate:
function(bitrate) {
351 { description:
"favour size over quality",
357 frameRate:
F(24000, 1001)
362 widths: {
min: 1, max: 720, step: 1},
363 heights: {
min: 1, max: 576, step: 1},
364 bitRates: {
min: 0, max: 1536000, step: 1},
365 frameRates: {
min:
F(0, 1), max:
F(30000, 1001)}
372 frameRate:
F(24000, 1001)
385 return ArrayConverter.nsIArray((aFractions instanceof
Array) ?
387 [aFractions.min, aFractions.max]);
395 log(
"Checking testcase [" + testcase.description +
"]");
398 Cc[
"@songbirdnest.com/Songbird/Mediacore/Transcode/Configurator/Device/GStreamer;1"]
399 .createInstance(
Ci.sbIDeviceTranscodingConfigurator);
400 assertTrue(configurator,
"failed to create configurator");
403 if (!testcase.hasOwnProperty(
"input")) {
407 if (!testcase.hasOwnProperty(
"caps")) {
411 if (!testcase.hasOwnProperty(
"output")) {
412 testcase.output = {};
415 for each (let prop
in [
"container",
"videoStream",
"audioStream"]) {
416 if (testcase.input.hasOwnProperty(prop)) {
420 for each (let prop
in [
"video",
"audio"]) {
421 if (testcase.caps.hasOwnProperty(prop)) {
425 for each (let prop
in [
"videoFormat",
"audioFormat"]) {
426 if (testcase.output.hasOwnProperty(prop)) {
433 configurator.inputUri =
newURI(testcase.input.inputUri);
436 configurator.inputFormat = testcase.input;
440 var videoCaps =
Cc[
"@songbirdnest.com/Songbird/Device/sbdevcapvideostream;1"]
441 .createInstance(
Ci.sbIDevCapVideoStream);
442 var videoSizes = [{
width: x.width,
height: x.height,
444 for each (x
in testcase.caps.video.explicitSizes)];
445 videoCaps.initialize(testcase.caps.video.type,
446 ArrayConverter.nsIArray(videoSizes),
450 !(testcase.caps.video.PARs instanceof
Array),
452 !(testcase.caps.video.frameRates instanceof
Array),
455 var audioCaps =
Cc[
"@songbirdnest.com/Songbird/Device/sbdevcapaudiostream;1"]
456 .createInstance(
Ci.sbIDevCapAudioStream);
457 audioCaps.initialize(testcase.caps.audio.type,
462 var formatType =
Cc[
"@songbirdnest.com/Songbird/Device/sbvideoformattype;1"]
463 .createInstance(
Ci.sbIVideoFormatType);
464 formatType.initialize(testcase.caps.containerType,
468 var caps =
Cc[
"@songbirdnest.com/Songbird/Device/DeviceCapabilities;1"]
469 .createInstance(
Ci.sbIDeviceCapabilities);
471 caps.setFunctionTypes([caps.FUNCTION_VIDEO_PLAYBACK], 1);
472 caps.addContentTypes(caps.FUNCTION_VIDEO_PLAYBACK, [caps.CONTENT_VIDEO], 1);
473 caps.addMimeTypes(caps.CONTENT_VIDEO, [testcase.caps.containerType], 1);
474 caps.AddFormatType(caps.CONTENT_VIDEO,
475 testcase.caps.containerType,
477 caps.configureDone();
480 configurator.device = #1= {
482 getPreference:
function device_getPreference(aPrefName) {
484 case "transcode.quality.video":
485 return testcase.hasOwnProperty(
"quality") ? testcase.quality : 0.5;
487 throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
491 configurator.determineOutputType();
498 configurator.configurate();
503 for (let prop in configurator.device.wrappedJSObject) {
504 if (prop !=
"wrappedJSObject") {
505 delete configurator.device.wrappedJSObject[prop];
508 delete configurator.device.wrappedJSObject.wrappedJSObject;
511 if (testcase.output.muxer !=
null) {
513 "expected configurator to use a muxer");
516 "expected muxer is not configured muxer");
520 "expected configurator to not use a muxer");
525 configurator.fileExtension,
526 "expected file extension is not configured file extension");
529 if (testcase.output.videoEncoder !=
null) {
531 configurator.videoEncoder,
532 "expected video encoder is not configured video encoder");
534 "expected configurator to use a video encoder");
536 let PARnum = {}, PARdenom = {}, FPSnum = {}, FPSdenom = {};
537 configurator.videoFormat.getVideoPAR(PARnum, PARdenom);
538 configurator.videoFormat.getVideoFrameRate(FPSnum, FPSdenom);
542 let propEnum = configurator.videoEncoderProperties.enumerator;
543 for each (let prop
in ArrayConverter.JSEnum(propEnum)) {
544 if (prop instanceof
Ci.nsIProperty) {
545 props.push(prop.name +
": " + prop.value);
548 log(
"Configurated video format: " +
549 configurator.videoFormat.videoWidth +
550 "x" + configurator.videoFormat.videoHeight +
551 " PAR " + PARnum.value +
":" + PARdenom.value +
552 " FPS " + FPSnum.value +
":" + FPSdenom.value +
553 " props: {" + props.join(
", ") +
"}");
557 configurator.videoFormat.videoWidth,
558 "video format width unexpected");
560 configurator.videoFormat.videoHeight,
561 "video format height unexpected");
562 assertEqual(testcase.output.videoFormat.PAR.numerator,
564 "video format PAR numerator unexpected");
565 assertEqual(testcase.output.videoFormat.PAR.denominator,
567 "video format PAR denominator unexpected");
568 assertEqual(testcase.output.videoFormat.frameRate.numerator,
570 "video format frame rate numerator unexpected");
571 assertEqual(testcase.output.videoFormat.frameRate.denominator,
573 "video format frame rate denominator unexpected");
575 assertTrue(configurator.videoEncoderProperties instanceof
Ci.nsIPropertyBag2);
576 for (let prop in testcase.output.videoFormat.properties) {
577 if (testcase.output.videoFormat.properties[prop] instanceof Function) {
578 let f = testcase.output.videoFormat.properties[prop];
579 let
val = configurator.videoEncoderProperties.get(prop);
583 assertEqual(testcase.output.videoFormat.properties[prop],
584 configurator.videoEncoderProperties.get(prop),
585 "video property " + prop +
" mismatch");
591 "expected configurator to not use a video encoder");
595 if (testcase.output.audioEncoder !=
null) {
597 configurator.audioEncoder,
598 "expected audio encoder is not configured audio encoder");
600 "expected configurator to use an audio encoder");
604 let propEnum = configurator.audioEncoderProperties.enumerator;
605 for each (let prop
in ArrayConverter.JSEnum(propEnum)) {
606 if (prop instanceof
Ci.nsIProperty) {
607 props.push(prop.name +
": " + prop.value);
610 log(
"Configurated audio format: " +
611 configurator.audioFormat.sampleRate +
"Hz " +
612 configurator.audioFormat.channels +
"ch" +
613 " props: {" + props.join(
", ") +
"}");
616 assertEqual(testcase.output.audioFormat.sampleRate,
617 configurator.audioFormat.sampleRate,
618 "audio format sample rate unexpected");
620 configurator.audioFormat.channels,
621 "audio format channels unexpected");
623 assertTrue(configurator.audioEncoderProperties instanceof
Ci.nsIPropertyBag2);
624 for (let prop in testcase.output.audioFormat.properties) {
625 assertEqual(testcase.output.audioFormat.properties[prop],
626 configurator.audioEncoderProperties.get(prop),
627 "video property " + prop +
" mismatch");
632 "expected configurator to not use an audio encoder");
function checkBitrate(aCaps, aBitrate, aMin, aMax)
function F(aNumerator, aDenominator)
Shorthand for creating a fraction.
sbOSDControlService prototype QueryInterface
function assertTrue(aTest, aMessage)
function sbDevCapRange(aInput)
Make a sbIDevCapRange The input can either be an array (in which case it's used as explicit values) o...
function assertEqual(aExpected, aActual, aMessage)
function CopyProperties(aPropertyBag)
Create a property bag, and do a shallow copy of another property bag if given.
function runTest()
Advanced DataRemote unit tests.
function fromFractionRange(aFractions)
this _dialogInput val(dateText)
function createLibrary(databaseGuid, databaseLocation)
function newURI(aURLString)
function assertFalse(aTest, aMessage)