Skip to content

Commit b862aef

Browse files
authored
Merge pull request #6703 from Vishal2002/dev-vishal
Implement mirrored video feature for createCapture (#6441)
2 parents d7b5d58 + a300d25 commit b862aef

File tree

1 file changed

+56
-14
lines changed

1 file changed

+56
-14
lines changed

src/dom/dom.js

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,7 +2135,11 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
21352135
* W3C documentation</a> for possible properties. Different browsers support different
21362136
* properties.
21372137
*
2138-
* The second parameter, `callback`, is optional. It's a function to call once
2138+
* The 'flipped' property is an optional property which can be set to `{flipped:true}`
2139+
* to mirror the video output.If it is true then it means that video will be mirrored
2140+
* or flipped and if nothing is mentioned then by default it will be `false`.
2141+
*
2142+
* The second parameter,`callback`, is optional. It's a function to call once
21392143
* the capture is ready for use. The callback function should have one
21402144
* parameter, `stream`, that's a
21412145
* <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStream" target="_blank">MediaStream</a> object.
@@ -2148,6 +2152,8 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
21482152
* @param {String|Constant|Object} [type] type of capture, either AUDIO or VIDEO,
21492153
* or a constraints object. Both video and audio
21502154
* audio streams are captured by default.
2155+
* @param {Object} [flipped] flip the capturing video and mirror the output with `{flipped:true}`. By
2156+
* default it is false.
21512157
* @param {Function} [callback] function to call once the stream
21522158
* has loaded.
21532159
* @return {p5.Element} new <a href="#/p5.Element">p5.Element</a> object.
@@ -2183,6 +2189,19 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
21832189
* }
21842190
* </code>
21852191
* </div>
2192+
* <div class='notest'>
2193+
* <code>
2194+
* let capture;
2195+
*
2196+
* function setup() {
2197+
* // Create the video capture with mirrored output.
2198+
* capture = createCapture(VIDEO,{ flipped:true });
2199+
* capture.size(100,100);
2200+
* describe('A video stream from the webcam with flipped or mirrored output.');
2201+
* }
2202+
*
2203+
* </code>
2204+
* </div>
21862205
*
21872206
* <div class='notest norender'>
21882207
* <code>
@@ -2212,7 +2231,7 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
22122231
p5.prototype.createCapture = function(...args) {
22132232
p5._validateParameters('createCapture', args);
22142233

2215-
// return if getUserMedia is not supported by browser
2234+
// return if getUserMedia is not supported by the browser
22162235
if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) {
22172236
throw new DOMException('getUserMedia not supported in this browser');
22182237
}
@@ -2221,29 +2240,40 @@ p5.prototype.createCapture = function(...args) {
22212240
let useAudio = true;
22222241
let constraints;
22232242
let callback;
2243+
let flipped = false;
2244+
22242245
for (const arg of args) {
22252246
if (arg === p5.prototype.VIDEO) useAudio = false;
22262247
else if (arg === p5.prototype.AUDIO) useVideo = false;
2227-
else if (typeof arg === 'object') constraints = arg;
2228-
else if (typeof arg === 'function') callback = arg;
2248+
else if (typeof arg === 'object') {
2249+
if (arg.flipped !== undefined) {
2250+
flipped = arg.flipped;
2251+
delete arg.flipped;
2252+
}
2253+
constraints = Object.assign({}, constraints, arg);
2254+
}
2255+
else if (typeof arg === 'function') {
2256+
callback = arg;
2257+
}
22292258
}
2230-
if (!constraints) constraints = { video: useVideo, audio: useAudio };
22312259

2260+
const videoConstraints = { video: useVideo, audio: useAudio };
2261+
constraints = Object.assign({}, videoConstraints, constraints);
22322262
const domElement = document.createElement('video');
22332263
// required to work in iOS 11 & up:
22342264
domElement.setAttribute('playsinline', '');
2235-
22362265
navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
22372266
try {
22382267
if ('srcObject' in domElement) {
22392268
domElement.srcObject = stream;
22402269
} else {
22412270
domElement.src = window.URL.createObjectURL(stream);
22422271
}
2243-
} catch (err) {
2272+
}
2273+
catch(err) {
22442274
domElement.src = stream;
22452275
}
2246-
}, console.log);
2276+
}, console.error);
22472277

22482278
const videoEl = addElement(domElement, this, true);
22492279
videoEl.loadedmetadata = false;
@@ -2253,6 +2283,9 @@ p5.prototype.createCapture = function(...args) {
22532283
if (domElement.width) {
22542284
videoEl.width = domElement.width;
22552285
videoEl.height = domElement.height;
2286+
if (flipped) {
2287+
videoEl.elt.style.transform = 'scaleX(-1)';
2288+
}
22562289
} else {
22572290
videoEl.width = videoEl.elt.width = domElement.videoWidth;
22582291
videoEl.height = videoEl.elt.height = domElement.videoHeight;
@@ -2261,9 +2294,11 @@ p5.prototype.createCapture = function(...args) {
22612294

22622295
if (callback) callback(domElement.srcObject);
22632296
});
2297+
videoEl.flipped=flipped;
22642298
return videoEl;
22652299
};
22662300

2301+
22672302
/**
22682303
* Creates a new <a href="#/p5.Element">p5.Element</a> object.
22692304
*
@@ -4377,7 +4412,6 @@ class MediaElement extends p5.Element {
43774412
duration() {
43784413
return this.elt.duration;
43794414
}
4380-
43814415
_ensureCanvas() {
43824416
if (!this.canvas) {
43834417
this.canvas = document.createElement('canvas');
@@ -4398,18 +4432,26 @@ class MediaElement extends p5.Element {
43984432
}
43994433

44004434
this.drawingContext.clearRect(
4401-
0,
4402-
0,
4403-
this.canvas.width,
4404-
this.canvas.height
4405-
);
4435+
0, 0, this.canvas.width, this.canvas.height);
4436+
4437+
if (this.flipped === true) {
4438+
this.drawingContext.save();
4439+
this.drawingContext.scale(-1, 1);
4440+
this.drawingContext.translate(-this.canvas.width, 0);
4441+
}
4442+
44064443
this.drawingContext.drawImage(
44074444
this.elt,
44084445
0,
44094446
0,
44104447
this.canvas.width,
44114448
this.canvas.height
44124449
);
4450+
4451+
if (this.flipped === true) {
4452+
this.drawingContext.restore();
4453+
}
4454+
44134455
this.setModified(true);
44144456
this._frameOnCanvas = this._pInst.frameCount;
44154457
}

0 commit comments

Comments
 (0)