av/cmd/mjpeg-player/player.js

89 lines
2.5 KiB
JavaScript

/*
NAME
player.js
AUTHOR
Trek Hopton <trek@ausocean.org>
LICENSE
This file is Copyright (C) 2019 the Australian Ocean Lab (AusOcean)
It is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License in gpl.txt.
If not, see [GNU licenses](http://www.gnu.org/licenses).
*/
let frameRate = 30;
onmessage = e => {
switch(e.data.msg){
case "setFrameRate":
frameRate = e.data.data;
break;
case "loadMjpeg":
self.importScripts('./lex-mjpeg.js');
let mjpeg = new Uint8Array(e.data.data);
let lex = new MJPEGLexer(mjpeg);
player = new Player(lex);
player.setFrameRate(frameRate);
player.start();
break;
case "loadMtsMjpeg":
self.importScripts('./hlsjs/mts-demuxer.js');
let mtsMjpeg = new Uint8Array(e.data.data);
let demux = new MTSDemuxer();
let tracks = demux._getTracks();
demux.append(mtsMjpeg);
buf = new FrameBuffer(tracks.video.data);
player = new Player(buf);
player.setFrameRate(frameRate); //TODO: read frame rate from metadata.
player.start();
break;
default:
console.error("unknown message from main thread");
break;
}
};
class Player{
constructor(buffer){
this.buffer = buffer;
this.frameRate = frameRate;
}
setFrameRate(rate){
this.frameRate = rate;
}
start(){
let frame = this.buffer.read();
if(frame != null){
postMessage({msg:"frame", data:frame.buffer}, [frame.buffer]);
setTimeout(() => { this.start();}, 1000/this.frameRate);
} else {
postMessage({msg:"stop"});
}
}
}
// FrameBuffer allows an array of subarrays (MJPEG frames) to be read one at a time.
class FrameBuffer{
constructor(src){
this.src = src;
this.off = 0;
}
// read returns the next single frame.
read(){
return this.src[this.off++];
}
}