From 372865132bd3f173839b6e1c54aa1a849ac3b417 Mon Sep 17 00:00:00 2001 From: Trek H Date: Thu, 2 Jan 2020 11:35:43 +1030 Subject: [PATCH] mjpeg-player: fomatting and removed bootstrap. --- cmd/mjpeg-player/hlsjs/mts-demuxer.js | 188 +++++++++++++------------- cmd/mjpeg-player/index.html | 1 - cmd/mjpeg-player/lex-mjpeg.js | 26 ++-- cmd/mjpeg-player/main.js | 30 ++-- cmd/mjpeg-player/player.js | 26 ++-- go.mod | 1 - go.sum | 2 - 7 files changed, 135 insertions(+), 139 deletions(-) diff --git a/cmd/mjpeg-player/hlsjs/mts-demuxer.js b/cmd/mjpeg-player/hlsjs/mts-demuxer.js index 443d3bcc..22ac59ca 100644 --- a/cmd/mjpeg-player/hlsjs/mts-demuxer.js +++ b/cmd/mjpeg-player/hlsjs/mts-demuxer.js @@ -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,11 +27,11 @@ 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(); } - + // init initialises MTSDemuxer's state. It can be used to reset an MTSDemuxer instance. init() { this.pmtParsed = false; @@ -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,10 +56,10 @@ class MTSDemuxer{ } // _getTracks returns this MTSDemuxer's tracks. - _getTracks(){ + _getTracks() { return { - video: this._videoTrack, - audio: this._audioTrack, + video: this._videoTrack, + audio: this._audioTrack, id3: this._id3Track }; } @@ -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; @@ -100,10 +100,10 @@ class MTSDemuxer{ parsePES = this._parsePES; const syncOffset = MTSDemuxer._syncOffset(data); - + // Don't parse last TS packet if incomplete. len -= (len + syncOffset) % 188; - + // Loop through TS packets. for (start = syncOffset; start < len; start += 188) { if (data[start] === 0x47) { @@ -122,84 +122,84 @@ class MTSDemuxer{ offset = start + 4; } switch (pid) { - case videoId: - if (pusi) { - if (videoData && (pes = parsePES(videoData)) && pes.pts !== undefined) { - videoTrack.data.push(pes.data); - // TODO: here pes contains data, pts, dts and len. Are all these needed? + case videoId: + if (pusi) { + if (videoData && (pes = parsePES(videoData)) && pes.pts !== undefined) { + videoTrack.data.push(pes.data); + // TODO: here pes contains data, pts, dts and len. Are all these needed? + } + videoData = { data: [], size: 0 }; } - videoData = { data: [], size: 0 }; - } - if (videoData) { - videoData.data.push(data.subarray(offset, start + 188)); - videoData.size += start + 188 - offset; - } - break; - case audioId: - if (pusi) { - if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) { - audioTrack.data.push(pes.data); + if (videoData) { + videoData.data.push(data.subarray(offset, start + 188)); + videoData.size += start + 188 - offset; } - audioData = { data: [], size: 0 }; - } - if (audioData) { - audioData.data.push(data.subarray(offset, start + 188)); - audioData.size += start + 188 - offset; - } - break; - case id3Id: - if (pusi) { - if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) { - id3Track.data.push(pes.data); + break; + case audioId: + if (pusi) { + if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) { + audioTrack.data.push(pes.data); + } + audioData = { data: [], size: 0 }; + } + if (audioData) { + audioData.data.push(data.subarray(offset, start + 188)); + audioData.size += start + 188 - offset; + } + break; + case id3Id: + if (pusi) { + if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) { + id3Track.data.push(pes.data); + } + id3Data = { data: [], size: 0 }; + } + if (id3Data) { + id3Data.data.push(data.subarray(offset, start + 188)); + id3Data.size += start + 188 - offset; + } + break; + case 0: + if (pusi) { + offset += data[offset] + 1; } - id3Data = { data: [], size: 0 }; - } - if (id3Data) { - id3Data.data.push(data.subarray(offset, start + 188)); - id3Data.size += start + 188 - offset; - } - break; - case 0: - if (pusi) { - offset += data[offset] + 1; - } - pmtId = this._pmtId = parsePAT(data, offset); - break; - case pmtId: - if (pusi) { - offset += data[offset] + 1; - } + pmtId = this._pmtId = parsePAT(data, offset); + break; + case pmtId: + if (pusi) { + offset += data[offset] + 1; + } - let parsedPIDs = parsePMT(data, offset); + let parsedPIDs = parsePMT(data, offset); - // Only update track id if track PID found while parsing PMT. - // This is to avoid resetting the PID to -1 in case track PID transiently disappears from the stream, - // this could happen in case of transient missing audio samples for example. - videoId = parsedPIDs.video; - if (videoId > 0) { - videoTrack.pid = videoId; - } - audioId = parsedPIDs.audio; - if (audioId > 0) { - audioTrack.pid = audioId; - } - id3Id = parsedPIDs.id3; - if (id3Id > 0) { - id3Track.pid = id3Id; - } + // Only update track id if track PID found while parsing PMT. + // This is to avoid resetting the PID to -1 in case track PID transiently disappears from the stream, + // this could happen in case of transient missing audio samples for example. + videoId = parsedPIDs.video; + if (videoId > 0) { + videoTrack.pid = videoId; + } + audioId = parsedPIDs.audio; + if (audioId > 0) { + audioTrack.pid = audioId; + } + id3Id = parsedPIDs.id3; + if (id3Id > 0) { + id3Track.pid = id3Id; + } - if (unknownPIDs && !pmtParsed) { - // Reparse from beginning. - unknownPIDs = false; - // We set it to -188, the += 188 in the for loop will reset start to 0. - start = syncOffset - 188; - } - pmtParsed = this.pmtParsed = true; - break; - default: - unknownPIDs = true; - break; + if (unknownPIDs && !pmtParsed) { + // Reparse from beginning. + unknownPIDs = false; + // We set it to -188, the += 188 in the for loop will reset start to 0. + start = syncOffset - 188; + } + pmtParsed = this.pmtParsed = true; + break; + default: + unknownPIDs = true; + break; } } else { console.error('TS packet did not start with 0x47'); @@ -214,7 +214,7 @@ class MTSDemuxer{ // Either pesPkts null or PES truncated, keep it for next frag parsing. videoTrack.pesData = videoData; } - + if (audioData && (pes = parsePES(audioData)) && pes.pts !== undefined) { audioTrack.data.push(pes.data); audioTrack.pesData = null; @@ -222,7 +222,7 @@ class MTSDemuxer{ // Either pesPkts null or PES truncated, keep it for next frag parsing. audioTrack.pesData = audioData; } - + if (id3Data && (pes = parsePES(id3Data)) && pes.pts !== undefined) { id3Track.data.push(pes.data); id3Track.pesData = null; @@ -232,16 +232,16 @@ 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}, - sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2], - tableEnd = offset + 3 + sectionLength - 4; + _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 // long the program info descriptors are. programInfoLength = (data[offset + 10] & 0x0f) << 8 | data[offset + 11]; @@ -253,16 +253,16 @@ class MTSDemuxer{ case 0x1c: // MJPEG case 0xdb: // SAMPLE-AES AVC. case 0x1b: // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video). - if (result.video === -1) { - result.video = pid; - } + if (result.video === -1) { + result.video = pid; + } break; case 0xcf: // SAMPLE-AES AAC. case 0x0f: // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio). case 0xd2: // ADPCM audio. case 0x03: // ISO/IEC 11172-3 (MPEG-1 audio). case 0x24: - // console.warn('HEVC stream type found, not supported for now'); + // console.warn('HEVC stream type found, not supported for now'); case 0x04: // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio). if (result.audio === -1) { result.audio = pid; @@ -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) { diff --git a/cmd/mjpeg-player/index.html b/cmd/mjpeg-player/index.html index c2e08128..064f436c 100644 --- a/cmd/mjpeg-player/index.html +++ b/cmd/mjpeg-player/index.html @@ -6,7 +6,6 @@ Mjpeg Player - diff --git a/cmd/mjpeg-player/lex-mjpeg.js b/cmd/mjpeg-player/lex-mjpeg.js index 36c128f5..4d5be7e9 100644 --- a/cmd/mjpeg-player/lex-mjpeg.js +++ b/cmd/mjpeg-player/lex-mjpeg.js @@ -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; } } \ No newline at end of file diff --git a/cmd/mjpeg-player/main.js b/cmd/mjpeg-player/main.js index dcc68f0d..037b31ed 100644 --- a/cmd/mjpeg-player/main.js +++ b/cmd/mjpeg-player/main.js @@ -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,17 +56,17 @@ function play() { } }; - switch(input.name.split('.')[1]){ - case "mjpeg": - case "mjpg": - 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]); - break; - default: - console.error("unknown file format"); - break; + switch (input.name.split('.')[1]) { + case "mjpeg": + case "mjpg": + 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]); + break; + default: + console.error("unknown file format"); + break; } }; reader.onerror = error => reject(error); diff --git a/cmd/mjpeg-player/player.js b/cmd/mjpeg-player/player.js index 3ad0c811..34ff75ab 100644 --- a/cmd/mjpeg-player/player.js +++ b/cmd/mjpeg-player/player.js @@ -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++]; } } \ No newline at end of file diff --git a/go.mod b/go.mod index 1ab98014..67c14597 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index e6eee428..26f1493b 100644 --- a/go.sum +++ b/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=