diff --git a/src/dom/dom.js b/src/dom/dom.js index b12a2750c8..04f8b33ba7 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -2135,7 +2135,11 @@ if (navigator.mediaDevices.getUserMedia === undefined) { * W3C documentation for possible properties. Different browsers support different * properties. * - * The second parameter, `callback`, is optional. It's a function to call once + * The 'flipped' property is an optional property which can be set to `{flipped:true}` + * to mirror the video output.If it is true then it means that video will be mirrored + * or flipped and if nothing is mentioned then by default it will be `false`. + * + * The second parameter,`callback`, is optional. It's a function to call once * the capture is ready for use. The callback function should have one * parameter, `stream`, that's a * MediaStream object. @@ -2148,6 +2152,8 @@ if (navigator.mediaDevices.getUserMedia === undefined) { * @param {String|Constant|Object} [type] type of capture, either AUDIO or VIDEO, * or a constraints object. Both video and audio * audio streams are captured by default. + * @param {Object} [flipped] flip the capturing video and mirror the output with `{flipped:true}`. By + * default it is false. * @param {Function} [callback] function to call once the stream * has loaded. * @return {p5.Element} new p5.Element object. @@ -2183,6 +2189,19 @@ if (navigator.mediaDevices.getUserMedia === undefined) { * } * * + *
+ * let capture;
+ *
+ * function setup() {
+ * // Create the video capture with mirrored output.
+ * capture = createCapture(VIDEO,{ flipped:true });
+ * capture.size(100,100);
+ * describe('A video stream from the webcam with flipped or mirrored output.');
+ * }
+ *
+ *
+ *
@@ -2212,7 +2231,7 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
p5.prototype.createCapture = function(...args) {
p5._validateParameters('createCapture', args);
- // return if getUserMedia is not supported by browser
+ // return if getUserMedia is not supported by the browser
if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) {
throw new DOMException('getUserMedia not supported in this browser');
}
@@ -2221,18 +2240,28 @@ p5.prototype.createCapture = function(...args) {
let useAudio = true;
let constraints;
let callback;
+ let flipped = false;
+
for (const arg of args) {
if (arg === p5.prototype.VIDEO) useAudio = false;
else if (arg === p5.prototype.AUDIO) useVideo = false;
- else if (typeof arg === 'object') constraints = arg;
- else if (typeof arg === 'function') callback = arg;
+ else if (typeof arg === 'object') {
+ if (arg.flipped !== undefined) {
+ flipped = arg.flipped;
+ delete arg.flipped;
+ }
+ constraints = Object.assign({}, constraints, arg);
+ }
+ else if (typeof arg === 'function') {
+ callback = arg;
+ }
}
- if (!constraints) constraints = { video: useVideo, audio: useAudio };
+ const videoConstraints = { video: useVideo, audio: useAudio };
+ constraints = Object.assign({}, videoConstraints, constraints);
const domElement = document.createElement('video');
// required to work in iOS 11 & up:
domElement.setAttribute('playsinline', '');
-
navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
try {
if ('srcObject' in domElement) {
@@ -2240,10 +2269,11 @@ p5.prototype.createCapture = function(...args) {
} else {
domElement.src = window.URL.createObjectURL(stream);
}
- } catch (err) {
+ }
+ catch(err) {
domElement.src = stream;
}
- }, console.log);
+ }, console.error);
const videoEl = addElement(domElement, this, true);
videoEl.loadedmetadata = false;
@@ -2253,6 +2283,9 @@ p5.prototype.createCapture = function(...args) {
if (domElement.width) {
videoEl.width = domElement.width;
videoEl.height = domElement.height;
+ if (flipped) {
+ videoEl.elt.style.transform = 'scaleX(-1)';
+ }
} else {
videoEl.width = videoEl.elt.width = domElement.videoWidth;
videoEl.height = videoEl.elt.height = domElement.videoHeight;
@@ -2261,9 +2294,11 @@ p5.prototype.createCapture = function(...args) {
if (callback) callback(domElement.srcObject);
});
+ videoEl.flipped=flipped;
return videoEl;
};
+
/**
* Creates a new p5.Element object.
*
@@ -4377,7 +4412,6 @@ class MediaElement extends p5.Element {
duration() {
return this.elt.duration;
}
-
_ensureCanvas() {
if (!this.canvas) {
this.canvas = document.createElement('canvas');
@@ -4398,11 +4432,14 @@ class MediaElement extends p5.Element {
}
this.drawingContext.clearRect(
- 0,
- 0,
- this.canvas.width,
- this.canvas.height
- );
+ 0, 0, this.canvas.width, this.canvas.height);
+
+ if (this.flipped === true) {
+ this.drawingContext.save();
+ this.drawingContext.scale(-1, 1);
+ this.drawingContext.translate(-this.canvas.width, 0);
+ }
+
this.drawingContext.drawImage(
this.elt,
0,
@@ -4410,6 +4447,11 @@ class MediaElement extends p5.Element {
this.canvas.width,
this.canvas.height
);
+
+ if (this.flipped === true) {
+ this.drawingContext.restore();
+ }
+
this.setModified(true);
this._frameOnCanvas = this._pInst.frameCount;
}