Skip to content

Commit

Permalink
DRY up VideoSource code (#3353)
Browse files Browse the repository at this point in the history
  • Loading branch information
mourner authored and Lucas Wojciechowski committed Oct 12, 2016
1 parent 41e2f9f commit ee827ba
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 97 deletions.
14 changes: 7 additions & 7 deletions js/source/image_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
},

Expand Down
96 changes: 6 additions & 90 deletions js/source/video_source.js
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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,

/**
Expand All @@ -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<Array<number>>} 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() {
Expand Down

0 comments on commit ee827ba

Please sign in to comment.