|
@@ -35,6 +35,8 @@ import { Frame } from './frame';
|
35
|
35
|
import { Tracker } from '../trackers/tracker';
|
36
|
36
|
import { Time } from './time';
|
37
|
37
|
import { Source } from '../sources/source';
|
|
38
|
+import { VideoSource } from '../sources/video-source';
|
|
39
|
+import { CanvasSource } from '../sources/canvas-source';
|
38
|
40
|
import { asap } from '../utils/asap';
|
39
|
41
|
|
40
|
42
|
/** Session mode */
|
|
@@ -107,6 +109,9 @@ export class Session extends AREventTarget<SessionEventType>
|
107
|
109
|
/** Rendering viewport */
|
108
|
110
|
private readonly _viewport: Viewport;
|
109
|
111
|
|
|
112
|
+ /** Primary source of data */
|
|
113
|
+ private readonly _primarySource: VideoSource | CanvasSource;
|
|
114
|
+
|
110
|
115
|
/** Time Manager */
|
111
|
116
|
private _time: Time;
|
112
|
117
|
|
|
@@ -161,9 +166,12 @@ export class Session extends AREventTarget<SessionEventType>
|
161
|
166
|
if(mode != 'immersive' && mode != 'inline')
|
162
|
167
|
throw new IllegalArgumentError(`Invalid session mode "${mode}"`);
|
163
|
168
|
|
|
169
|
+ // find the primary source of data
|
|
170
|
+ this._primarySource = this._findPrimarySource(sources);
|
|
171
|
+
|
164
|
172
|
// setup the viewport
|
165
|
173
|
this._viewport = viewport;
|
166
|
|
- this._viewport._init(() => this.media.size, mode);
|
|
174
|
+ this._viewport._init(() => this._media.size, mode);
|
167
|
175
|
|
168
|
176
|
// setup the main loop
|
169
|
177
|
this._setupUpdateLoop();
|
|
@@ -283,10 +291,6 @@ export class Session extends AREventTarget<SessionEventType>
|
283
|
291
|
}).then(() => {
|
284
|
292
|
|
285
|
293
|
// validate sources of data
|
286
|
|
- const videoSources = sources.filter(source => source._type == 'video');
|
287
|
|
- if(videoSources.length != 1)
|
288
|
|
- throw new IllegalArgumentError(`One video source of data must be provided`);
|
289
|
|
-
|
290
|
294
|
for(let i = sources.length - 1; i >= 0; i--) {
|
291
|
295
|
if(sources.indexOf(sources[i]) < i)
|
292
|
296
|
throw new IllegalArgumentError(`Found repeated sources of data`);
|
|
@@ -424,21 +428,6 @@ export class Session extends AREventTarget<SessionEventType>
|
424
|
428
|
}
|
425
|
429
|
|
426
|
430
|
/**
|
427
|
|
- * The underlying media (generally a camera stream)
|
428
|
|
- * @internal
|
429
|
|
- */
|
430
|
|
- get media(): SpeedyMedia
|
431
|
|
- {
|
432
|
|
- for(let i = this._sources.length - 1; i >= 0; i--) {
|
433
|
|
- if(this._sources[i]._type == 'video')
|
434
|
|
- return this._sources[i]._data as SpeedyMedia;
|
435
|
|
- }
|
436
|
|
-
|
437
|
|
- // this shouldn't happen
|
438
|
|
- throw new IllegalOperationError(`Invalid input source`);
|
439
|
|
- }
|
440
|
|
-
|
441
|
|
- /**
|
442
|
431
|
* Session mode
|
443
|
432
|
*/
|
444
|
433
|
get mode(): SessionMode
|
|
@@ -495,6 +484,35 @@ export class Session extends AREventTarget<SessionEventType>
|
495
|
484
|
}
|
496
|
485
|
|
497
|
486
|
/**
|
|
487
|
+ * Find the primary source of data (generally a camera stream)
|
|
488
|
+ * @param sources
|
|
489
|
+ * @returns the primary source
|
|
490
|
+ */
|
|
491
|
+ private _findPrimarySource(sources: Source[]): VideoSource | CanvasSource
|
|
492
|
+ {
|
|
493
|
+ // prefer video sources
|
|
494
|
+ for(let i = 0; i < sources.length; i++) {
|
|
495
|
+ if(sources[i]._type == 'video')
|
|
496
|
+ return sources[i] as VideoSource;
|
|
497
|
+ }
|
|
498
|
+ for(let i = 0; i < sources.length; i++) {
|
|
499
|
+ if(sources[i]._type == 'canvas')
|
|
500
|
+ return sources[i] as CanvasSource;
|
|
501
|
+ }
|
|
502
|
+
|
|
503
|
+ // this shouldn't happen
|
|
504
|
+ throw new IllegalOperationError(`No primary source of data was found!`);
|
|
505
|
+ }
|
|
506
|
+
|
|
507
|
+ /**
|
|
508
|
+ * The media of the primary source of data
|
|
509
|
+ */
|
|
510
|
+ private get _media(): SpeedyMedia
|
|
511
|
+ {
|
|
512
|
+ return this._primarySource._data;
|
|
513
|
+ }
|
|
514
|
+
|
|
515
|
+ /**
|
498
|
516
|
* Attach a tracker to the session
|
499
|
517
|
* @param tracker
|
500
|
518
|
*/
|
|
@@ -517,11 +535,11 @@ export class Session extends AREventTarget<SessionEventType>
|
517
|
535
|
const canvas = this._viewport._backgroundCanvas;
|
518
|
536
|
const ctx = canvas.getContext('2d', { alpha: false });
|
519
|
537
|
|
520
|
|
- if(ctx && this.media.type != 'data') {
|
|
538
|
+ if(ctx && this._media.type != 'data') {
|
521
|
539
|
ctx.imageSmoothingEnabled = false;
|
522
|
540
|
|
523
|
541
|
// draw user media
|
524
|
|
- const image = this.media.source as CanvasImageSource;
|
|
542
|
+ const image = this._media.source as CanvasImageSource;
|
525
|
543
|
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
|
526
|
544
|
|
527
|
545
|
// render output image(s)
|