mirror of https://bitbucket.org/ausocean/av.git
mjpeg-player: fomatting and removed bootstrap.
This commit is contained in:
parent
fb11dde938
commit
372865132b
|
@ -19,7 +19,7 @@ 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).
|
||||
If not, see http://www.gnu.org/licenses.
|
||||
|
||||
For hls.js Copyright notice and license, see LICENSE file.
|
||||
*/
|
||||
|
@ -27,8 +27,8 @@ LICENSE
|
|||
// MTSDemuxer demultiplexes an MPEG-TS stream into its individual streams.
|
||||
// While it is possible that the MPEG-TS stream may contain many streams,
|
||||
// this demuxer will result in at most one stream of each type ie. video, audio, id3 metadata.
|
||||
class MTSDemuxer{
|
||||
constructor(){
|
||||
class MTSDemuxer {
|
||||
constructor() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ class MTSDemuxer{
|
|||
* @param {string} type 'audio' | 'video' | 'id3' | 'text'
|
||||
* @return {object} MTSDemuxer's internal track model.
|
||||
*/
|
||||
static createTrack (type) {
|
||||
static createTrack(type) {
|
||||
return {
|
||||
type,
|
||||
pid: -1,
|
||||
|
@ -56,7 +56,7 @@ class MTSDemuxer{
|
|||
}
|
||||
|
||||
// _getTracks returns this MTSDemuxer's tracks.
|
||||
_getTracks(){
|
||||
_getTracks() {
|
||||
return {
|
||||
video: this._videoTrack,
|
||||
audio: this._audioTrack,
|
||||
|
@ -67,7 +67,7 @@ class MTSDemuxer{
|
|||
// _syncOffset scans the first 'maxScanWindow' bytes and returns an offset to the beginning of the first three MTS packets,
|
||||
// or -1 if three are not found.
|
||||
// A TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47.
|
||||
static _syncOffset (data) {
|
||||
static _syncOffset(data) {
|
||||
const maxScanWindow = 1000; // 1000 is a reasonable number of bytes to search for the first MTS packets.
|
||||
const scanWindow = Math.min(maxScanWindow, data.length - 3 * 188);
|
||||
let i = 0;
|
||||
|
@ -232,14 +232,14 @@ class MTSDemuxer{
|
|||
}
|
||||
}
|
||||
|
||||
_parsePAT (data, offset) {
|
||||
_parsePAT(data, offset) {
|
||||
// Skip the PSI header and parse the first PMT entry.
|
||||
return (data[offset + 10] & 0x1F) << 8 | data[offset + 11];
|
||||
// console.log('PMT PID:' + this._pmtId);
|
||||
}
|
||||
|
||||
_parsePMT (data, offset) {
|
||||
let programInfoLength, pid, result = { audio: -1, video: -1, id3: -1},
|
||||
_parsePMT(data, offset) {
|
||||
let programInfoLength, pid, result = { audio: -1, video: -1, id3: -1 },
|
||||
sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2],
|
||||
tableEnd = offset + 3 + sectionLength - 4;
|
||||
// To determine where the table is, we have to figure out how
|
||||
|
@ -284,7 +284,7 @@ class MTSDemuxer{
|
|||
return result;
|
||||
}
|
||||
|
||||
_parsePES (stream) {
|
||||
_parsePES(stream) {
|
||||
let i = 0, frag, pesFlags, pesPrefix, pesLen, pesHdrLen, pesData, pesPts, pesDts, payloadStartOffset, data = stream.data;
|
||||
// Safety check.
|
||||
if (!stream || stream.size === 0) {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<title>Mjpeg Player</title>
|
||||
<script type="text/javascript" src="main.js"></script>
|
||||
<script type="module" src="player.js"></script>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||
</head>
|
||||
|
||||
<body style="height: 100%">
|
||||
|
|
|
@ -19,36 +19,36 @@ 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).
|
||||
If not, see http://www.gnu.org/licenses.
|
||||
*/
|
||||
|
||||
// MJPEGLexer lexes a byte array containing MJPEG into individual JPEGs.
|
||||
class MJPEGLexer{
|
||||
constructor(src){
|
||||
class MJPEGLexer {
|
||||
constructor(src) {
|
||||
this.src = src;
|
||||
this.off = 0;
|
||||
}
|
||||
|
||||
// read returns the next single frame.
|
||||
read(){
|
||||
read() {
|
||||
// Check if the src can contain at least the start and end flags (4B).
|
||||
if(this.off+4 > this.src.length){
|
||||
if (this.off + 4 > this.src.length) {
|
||||
return null;
|
||||
}
|
||||
// Iterate through bytes until the start flag is found.
|
||||
while(this.src[this.off] != 0xff || this.src[this.off+1] != 0xd8){
|
||||
while (this.src[this.off] != 0xff || this.src[this.off + 1] != 0xd8) {
|
||||
this.off++;
|
||||
if(this.off+4 > this.src.length){
|
||||
if (this.off + 4 > this.src.length) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Start after the start flag and loop until the end flag is found.
|
||||
let end = this.off+2;
|
||||
while(true){
|
||||
if(end+2 > this.src.length){
|
||||
let end = this.off + 2;
|
||||
while (true) {
|
||||
if (end + 2 > this.src.length) {
|
||||
return null;
|
||||
}
|
||||
if(this.src[end] == 0xff && this.src[end+1] == 0xd9){
|
||||
if (this.src[end] == 0xff && this.src[end + 1] == 0xd9) {
|
||||
break;
|
||||
}
|
||||
end++;
|
||||
|
@ -56,8 +56,8 @@ class MJPEGLexer{
|
|||
// Copy the frame's bytes to a new array to return.
|
||||
// Note: optimally this would return a reference but since we are in a worker thread,
|
||||
// the main thread doesn't have access to the ArrayBuffer that we are working with.
|
||||
let frame = this.src.slice(this.off, end+2);
|
||||
this.off = end+2
|
||||
let frame = this.src.slice(this.off, end + 2);
|
||||
this.off = end + 2
|
||||
return frame;
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ 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).
|
||||
If not, see http://www.gnu.org/licenses.
|
||||
*/
|
||||
|
||||
// play will process and play the chosen target file.
|
||||
|
@ -32,12 +32,12 @@ function play() {
|
|||
const player = new Worker("player.js");
|
||||
|
||||
let rate = document.getElementById('rate');
|
||||
if(rate.value && rate.value > 0){
|
||||
player.postMessage({msg:"setFrameRate", data: rate.value});
|
||||
if (rate.value && rate.value > 0) {
|
||||
player.postMessage({ msg: "setFrameRate", data: rate.value });
|
||||
}
|
||||
|
||||
player.onmessage = e => {
|
||||
switch(e.data.msg){
|
||||
switch (e.data.msg) {
|
||||
case "frame":
|
||||
const blob = new Blob([new Uint8Array(e.data.data)], {
|
||||
type: 'video/x-motion-jpeg'
|
||||
|
@ -56,13 +56,13 @@ function play() {
|
|||
}
|
||||
};
|
||||
|
||||
switch(input.name.split('.')[1]){
|
||||
switch (input.name.split('.')[1]) {
|
||||
case "mjpeg":
|
||||
case "mjpg":
|
||||
player.postMessage({msg:"loadMjpeg", data:event.target.result}, [event.target.result]);
|
||||
player.postMessage({ msg: "loadMjpeg", data: event.target.result }, [event.target.result]);
|
||||
break;
|
||||
case "ts":
|
||||
player.postMessage({msg:"loadMtsMjpeg", data:event.target.result}, [event.target.result]);
|
||||
player.postMessage({ msg: "loadMtsMjpeg", data: event.target.result }, [event.target.result]);
|
||||
break;
|
||||
default:
|
||||
console.error("unknown file format");
|
||||
|
|
|
@ -19,13 +19,13 @@ 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).
|
||||
If not, see http://www.gnu.org/licenses.
|
||||
*/
|
||||
|
||||
let frameRate = 30;
|
||||
|
||||
onmessage = e => {
|
||||
switch(e.data.msg){
|
||||
switch (e.data.msg) {
|
||||
case "setFrameRate":
|
||||
frameRate = e.data.data;
|
||||
break;
|
||||
|
@ -54,36 +54,36 @@ onmessage = e => {
|
|||
}
|
||||
};
|
||||
|
||||
class Player{
|
||||
constructor(buffer){
|
||||
class Player {
|
||||
constructor(buffer) {
|
||||
this.buffer = buffer;
|
||||
this.frameRate = frameRate;
|
||||
}
|
||||
|
||||
setFrameRate(rate){
|
||||
setFrameRate(rate) {
|
||||
this.frameRate = rate;
|
||||
}
|
||||
|
||||
start(){
|
||||
start() {
|
||||
let frame = this.buffer.read();
|
||||
if(frame != null){
|
||||
postMessage({msg:"frame", data:frame.buffer}, [frame.buffer]);
|
||||
setTimeout(() => { this.start();}, 1000/this.frameRate);
|
||||
if (frame != null) {
|
||||
postMessage({ msg: "frame", data: frame.buffer }, [frame.buffer]);
|
||||
setTimeout(() => { this.start(); }, 1000 / this.frameRate);
|
||||
} else {
|
||||
postMessage({msg:"stop"});
|
||||
postMessage({ msg: "stop" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FrameBuffer allows an array of subarrays (MJPEG frames) to be read one at a time.
|
||||
class FrameBuffer{
|
||||
constructor(src){
|
||||
class FrameBuffer {
|
||||
constructor(src) {
|
||||
this.src = src;
|
||||
this.off = 0;
|
||||
}
|
||||
|
||||
// read returns the next single frame.
|
||||
read(){
|
||||
read() {
|
||||
return this.src[this.off++];
|
||||
}
|
||||
}
|
1
go.mod
1
go.mod
|
@ -12,5 +12,4 @@ require (
|
|||
github.com/pkg/errors v0.8.1
|
||||
github.com/yobert/alsa v0.0.0-20180630182551-d38d89fa843e
|
||||
gocv.io/x/gocv v0.21.0
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
)
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1,5 +1,3 @@
|
|||
bitbucket.org/ausocean/iot v1.2.8 h1:m2UhfAbG/6RKPBzY4OJ5S7zLxTmuzyMKPNbu0qaxFIw=
|
||||
bitbucket.org/ausocean/iot v1.2.8/go.mod h1:wCLOYeEDCxDquneSZ/zTEcKGXZ6uan+6sgZyTMlNVDo=
|
||||
bitbucket.org/ausocean/iot v1.2.9 h1:3tzgiekH+Z0yXhkwnqBzxxe8qQJ2O7YTkz4s0T6stgw=
|
||||
bitbucket.org/ausocean/iot v1.2.9/go.mod h1:Q5FwaOKnCty3dVeVtki6DLwYa5vhNpOaeu1lwLyPCg8=
|
||||
bitbucket.org/ausocean/utils v1.2.11 h1:zA0FOaPjN960ryp8PKCkV5y50uWBYrIxCVnXjwbvPqg=
|
||||
|
|
Loading…
Reference in New Issue