@@ -2135,7 +2135,11 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
2135
2135
* W3C documentation</a> for possible properties. Different browsers support different
2136
2136
* properties.
2137
2137
*
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
2139
2143
* the capture is ready for use. The callback function should have one
2140
2144
* parameter, `stream`, that's a
2141
2145
* <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) {
2148
2152
* @param {String|Constant|Object } [type] type of capture, either AUDIO or VIDEO,
2149
2153
* or a constraints object. Both video and audio
2150
2154
* 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.
2151
2157
* @param {Function } [callback] function to call once the stream
2152
2158
* has loaded.
2153
2159
* @return {p5.Element } new <a href="#/p5.Element">p5.Element</a> object.
@@ -2183,6 +2189,19 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
2183
2189
* }
2184
2190
* </code>
2185
2191
* </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>
2186
2205
*
2187
2206
* <div class='notest norender'>
2188
2207
* <code>
@@ -2212,7 +2231,7 @@ if (navigator.mediaDevices.getUserMedia === undefined) {
2212
2231
p5 . prototype . createCapture = function ( ...args ) {
2213
2232
p5 . _validateParameters ( 'createCapture' , args ) ;
2214
2233
2215
- // return if getUserMedia is not supported by browser
2234
+ // return if getUserMedia is not supported by the browser
2216
2235
if ( ! ( navigator . mediaDevices && navigator . mediaDevices . getUserMedia ) ) {
2217
2236
throw new DOMException ( 'getUserMedia not supported in this browser' ) ;
2218
2237
}
@@ -2221,29 +2240,40 @@ p5.prototype.createCapture = function(...args) {
2221
2240
let useAudio = true ;
2222
2241
let constraints ;
2223
2242
let callback ;
2243
+ let flipped = false ;
2244
+
2224
2245
for ( const arg of args ) {
2225
2246
if ( arg === p5 . prototype . VIDEO ) useAudio = false ;
2226
2247
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
+ }
2229
2258
}
2230
- if ( ! constraints ) constraints = { video : useVideo , audio : useAudio } ;
2231
2259
2260
+ const videoConstraints = { video : useVideo , audio : useAudio } ;
2261
+ constraints = Object . assign ( { } , videoConstraints , constraints ) ;
2232
2262
const domElement = document . createElement ( 'video' ) ;
2233
2263
// required to work in iOS 11 & up:
2234
2264
domElement . setAttribute ( 'playsinline' , '' ) ;
2235
-
2236
2265
navigator . mediaDevices . getUserMedia ( constraints ) . then ( function ( stream ) {
2237
2266
try {
2238
2267
if ( 'srcObject' in domElement ) {
2239
2268
domElement . srcObject = stream ;
2240
2269
} else {
2241
2270
domElement . src = window . URL . createObjectURL ( stream ) ;
2242
2271
}
2243
- } catch ( err ) {
2272
+ }
2273
+ catch ( err ) {
2244
2274
domElement . src = stream ;
2245
2275
}
2246
- } , console . log ) ;
2276
+ } , console . error ) ;
2247
2277
2248
2278
const videoEl = addElement ( domElement , this , true ) ;
2249
2279
videoEl . loadedmetadata = false ;
@@ -2253,6 +2283,9 @@ p5.prototype.createCapture = function(...args) {
2253
2283
if ( domElement . width ) {
2254
2284
videoEl . width = domElement . width ;
2255
2285
videoEl . height = domElement . height ;
2286
+ if ( flipped ) {
2287
+ videoEl . elt . style . transform = 'scaleX(-1)' ;
2288
+ }
2256
2289
} else {
2257
2290
videoEl . width = videoEl . elt . width = domElement . videoWidth ;
2258
2291
videoEl . height = videoEl . elt . height = domElement . videoHeight ;
@@ -2261,9 +2294,11 @@ p5.prototype.createCapture = function(...args) {
2261
2294
2262
2295
if ( callback ) callback ( domElement . srcObject ) ;
2263
2296
} ) ;
2297
+ videoEl . flipped = flipped ;
2264
2298
return videoEl ;
2265
2299
} ;
2266
2300
2301
+
2267
2302
/**
2268
2303
* Creates a new <a href="#/p5.Element">p5.Element</a> object.
2269
2304
*
@@ -4377,7 +4412,6 @@ class MediaElement extends p5.Element {
4377
4412
duration ( ) {
4378
4413
return this . elt . duration ;
4379
4414
}
4380
-
4381
4415
_ensureCanvas ( ) {
4382
4416
if ( ! this . canvas ) {
4383
4417
this . canvas = document . createElement ( 'canvas' ) ;
@@ -4398,18 +4432,26 @@ class MediaElement extends p5.Element {
4398
4432
}
4399
4433
4400
4434
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
+
4406
4443
this . drawingContext . drawImage (
4407
4444
this . elt ,
4408
4445
0 ,
4409
4446
0 ,
4410
4447
this . canvas . width ,
4411
4448
this . canvas . height
4412
4449
) ;
4450
+
4451
+ if ( this . flipped === true ) {
4452
+ this . drawingContext . restore ( ) ;
4453
+ }
4454
+
4413
4455
this . setModified ( true ) ;
4414
4456
this . _frameOnCanvas = this . _pInst . frameCount ;
4415
4457
}
0 commit comments