speedy-vision
Version:
GPU-accelerated Computer Vision for JavaScript
99 lines (87 loc) • 3.16 kB
JavaScript
/*
* speedy-vision.js
* GPU-accelerated Computer Vision for JavaScript
* Copyright 2020-2022 Alexandre Martins <alemartf(at)gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* image-input.js
* Gets an image into a pipeline
*/
import { SpeedyPipelineNode, SpeedyPipelineSourceNode } from '../../pipeline-node';
import { SpeedyPipelineMessageType, SpeedyPipelineMessageWithImage } from '../../pipeline-message';
import { InputPort, OutputPort } from '../../pipeline-portbuilder';
import { SpeedyGPU } from '../../../../gpu/speedy-gpu';
import { SpeedyTexture } from '../../../../gpu/speedy-texture';
import { SpeedyMedia } from '../../../speedy-media';
import { Utils } from '../../../../utils/utils';
import { ImageFormat } from '../../../../utils/types';
import { IllegalArgumentError, IllegalOperationError } from '../../../../utils/errors';
import { SpeedyPromise } from '../../../speedy-promise';
// Constants
const UPLOAD_BUFFER_SIZE = 2; // how many textures we allocate for uploading data
/**
* Gets an image into a pipeline
*/
export class SpeedyPipelineNodeImageSource extends SpeedyPipelineSourceNode
{
/**
* Constructor
* @param {string} [name] name of the node
*/
constructor(name = undefined)
{
super(name, UPLOAD_BUFFER_SIZE, [
OutputPort().expects(SpeedyPipelineMessageType.Image)
]);
/** @type {SpeedyMedia|null} source media */
this._media = null;
/** @type {number} texture index */
this._textureIndex = 0;
}
/**
* Source media
* @returns {SpeedyMedia|null}
*/
get media()
{
return this._media;
}
/**
* Source media
* @param {SpeedyMedia|null} media
*/
set media(media)
{
if(media !== null && !(media instanceof SpeedyMedia))
throw new IllegalArgumentError(`Not a SpeedyMedia: ${media}`);
this._media = media;
}
/**
* Run the specific task of this node
* @param {SpeedyGPU} gpu
* @returns {void|SpeedyPromise<void>}
*/
_run(gpu)
{
if(this._media == null)
throw new IllegalOperationError(`Did you forget to set the media of ${this.fullName}?`);
// use round-robin to mitigate WebGL's implicit synchronization
// and maybe minimize texture upload times
this._textureIndex = (this._textureIndex + 1) % this._tex.length;
// upload texture
const outputTexture = this._tex[this._textureIndex];
gpu.upload(this._media._source, outputTexture);
this.output().swrite(outputTexture, this._media._format);
}
}