// https://github.com/TurboWarp/scratch-gui/blob/develop/src/lib/video/camera.js // https://github.com/TurboWarp/scratch-gui/blob/develop/src/lib/video/video-provider.js const getUserMedia = (opts) => { if (!navigator.mediaDevices) { return Promise.reject(new Error('video is not supported in this context (insecure domain?)')); } return navigator.mediaDevices.getUserMedia(opts); }; // Single Setup For All Video Streams used by the GUI // While VideoProvider uses a private _singleSetup // property to ensure that each instance of a VideoProvider // use the same setup, this ensures that all instances // of VideoProviders use a single stream. This way, closing a camera modal // does not affect the video on the stage, and a program running and disabling // video on the stage will not affect the camera modal's video. const requestStack = []; const requestVideoStream = videoDesc => { let streamPromise; if (requestStack.length === 0) { streamPromise = getUserMedia({ audio: false, video: videoDesc }); requestStack.push(streamPromise); } else if (requestStack.length > 0) { streamPromise = requestStack[0]; requestStack.push(true); } return streamPromise; }; const requestDisableVideo = () => { requestStack.pop(); if (requestStack.length > 0) return false; return true; }; class VideoProvider { constructor() { this.mirror = true; this._frameCacheTimeout = 16; /** * DOM Video element * @private */ this._video = null; /** * Usermedia stream track * @private */ this._track = null; /** * Stores some canvas/frame data per resolution/mirror states */ this._workspace = []; } static get FORMAT_IMAGE_DATA() { return 'image-data'; } static get FORMAT_CANVAS() { return 'canvas'; } /** * Dimensions the video stream is analyzed at after its rendered to the * sample canvas. * @type {Array.} */ static get DIMENSIONS() { return [480, 360]; } /** * Order preview drawable is inserted at in the renderer. * @type {number} */ static get ORDER() { return 1; } /** * Get the HTML video element containing the stream */ get video() { return this._video; } /** * Request video be enabled. Sets up video, creates video skin and enables preview. * * @return {Promise.