From ee827bab57824d473115380e4425823e89965995 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Thu, 13 Oct 2016 01:40:50 +0300 Subject: [PATCH] DRY up VideoSource code (#3353) --- js/source/image_source.js | 14 +++--- js/source/video_source.js | 96 +++------------------------------------ 2 files changed, 13 insertions(+), 97 deletions(-) diff --git a/js/source/image_source.js b/js/source/image_source.js index 8448d3478e2..38f3578406d 100644 --- a/js/source/image_source.js +++ b/js/source/image_source.js @@ -131,23 +131,23 @@ ImageSource.prototype = util.inherit(Evented, /** @lends ImageSource.prototype * }, prepare: function() { - if (!this._loaded || !this.image || !this.image.complete) return; - if (!this.tile) return; - - var painter = this.map.painter; - var gl = painter.gl; + if (!this.tile || !this._loaded || !this.image || !this.image.complete) return; + this._prepareImage(this.map.painter.gl, this.image); + }, + _prepareImage: function (gl, image) { if (!this._prepared) { + this._prepared = true; this.tile.texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, this.tile.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.image); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); } else { gl.bindTexture(gl.TEXTURE_2D, this.tile.texture); - gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.image); + gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image); } }, diff --git a/js/source/video_source.js b/js/source/video_source.js index a46a4c45942..3cd640717bd 100644 --- a/js/source/video_source.js +++ b/js/source/video_source.js @@ -1,15 +1,8 @@ 'use strict'; var util = require('../util/util'); -var TileCoord = require('./tile_coord'); -var LngLat = require('../geo/lng_lat'); -var Point = require('point-geometry'); -var Evented = require('../util/evented'); var ajax = require('../util/ajax'); -var EXTENT = require('../data/bucket').EXTENT; -var RasterBoundsArray = require('../render/draw_raster').RasterBoundsArray; -var Buffer = require('../data/buffer'); -var VertexArrayObject = require('../render/vertex_array_object'); +var ImageSource = require('./image_source'); module.exports = VideoSource; @@ -80,10 +73,7 @@ function VideoSource(id, options, dispatcher, eventedParent) { }.bind(this)); } -VideoSource.prototype = util.inherit(Evented, /** @lends VideoSource.prototype */{ - minzoom: 0, - maxzoom: 22, - tileSize: 512, +VideoSource.prototype = util.inherit(ImageSource, /** @lends VideoSource.prototype */{ roundZoom: true, /** @@ -107,92 +97,18 @@ VideoSource.prototype = util.inherit(Evented, /** @lends VideoSource.prototype * /** * Sets the video's coordinates and re-renders the map. * + * @method setCoordinates * @param {Array>} coordinates Four geographical coordinates, * represented as arrays of longitude and latitude numbers, which define the corners of the video. * The coordinates start at the top left corner of the video and proceed in clockwise order. * They do not have to represent a rectangle. * @returns {VideoSource} this */ - setCoordinates: function(coordinates) { - this.coordinates = coordinates; - - // Calculate which mercator tile is suitable for rendering the video in - // and create a buffer with the corner coordinates. These coordinates - // may be outside the tile, because raster tiles aren't clipped when rendering. - - var map = this.map; - var cornerZ0Coords = coordinates.map(function(coord) { - return map.transform.locationCoordinate(LngLat.convert(coord)).zoomTo(0); - }); - - var centerCoord = this.centerCoord = util.getCoordinatesCenter(cornerZ0Coords); - centerCoord.column = Math.round(centerCoord.column); - centerCoord.row = Math.round(centerCoord.row); - - this.minzoom = this.maxzoom = centerCoord.zoom; - this.coord = new TileCoord(centerCoord.zoom, centerCoord.column, centerCoord.row); - this._tileCoords = cornerZ0Coords.map(function(coord) { - var zoomedCoord = coord.zoomTo(centerCoord.zoom); - return new Point( - Math.round((zoomedCoord.column - centerCoord.column) * EXTENT), - Math.round((zoomedCoord.row - centerCoord.row) * EXTENT)); - }); - - this.fire('data', {dataType: 'source'}); - return this; - }, - - _setTile: function (tile) { - this._prepared = false; - this.tile = tile; - var maxInt16 = 32767; - var array = new RasterBoundsArray(); - array.emplaceBack(this._tileCoords[0].x, this._tileCoords[0].y, 0, 0); - array.emplaceBack(this._tileCoords[1].x, this._tileCoords[1].y, maxInt16, 0); - array.emplaceBack(this._tileCoords[3].x, this._tileCoords[3].y, 0, maxInt16); - array.emplaceBack(this._tileCoords[2].x, this._tileCoords[2].y, maxInt16, maxInt16); - - this.tile.buckets = {}; - - this.tile.boundsBuffer = new Buffer(array.serialize(), RasterBoundsArray.serialize(), Buffer.BufferType.VERTEX); - this.tile.boundsVAO = new VertexArrayObject(); - this.tile.state = 'loaded'; - }, + // setCoordiates inherited from ImageSource prepare: function() { - if (this.video.readyState < 2) return; // not enough data for current position - if (!this.tile) return; - - var gl = this.map.painter.gl; - if (!this._prepared) { - this._prepared = true; - this.tile.texture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this.tile.texture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.video); - } else { - gl.bindTexture(gl.TEXTURE_2D, this.tile.texture); - gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.video); - } - - this._currentTime = this.video.currentTime; - }, - - loadTile: function(tile, callback) { - // We have a single tile -- whoose coordinates are this.coord -- that - // covers the video frame we want to render. If that's the one being - // requested, set it up with the image; otherwise, mark the tile as - // `errored` to indicate that we have no data for it. - if (this.coord && this.coord.toString() === tile.coord.toString()) { - this._setTile(tile); - callback(null); - } else { - tile.state = 'errored'; - callback(null); - } + if (!this.tile || this.video.readyState < 2) return; // not enough data for current position + this._prepareImage(this.map.painter.gl, this.video); }, serialize: function() {