Browse Source

develop

m7s
superxxd 2 years ago
parent
commit
2752477177
  1. 4
      build_decoder_264.sh
  2. 4
      build_decoder_264_265.sh
  3. 4
      build_decoder_265.sh
  4. 11
      doc/开发助记.md
  5. 118
      test/Player.js
  6. 46
      test/audio.js
  7. 127
      test/audiodc.js
  8. 16
      test/audiodec.js
  9. BIN
      test/audiodec.wasm
  10. 25
      test/common.js
  11. 73
      test/decoder.js
  12. 17
      test/decoder_____missle.js
  13. 405
      test/decoder_simd.js
  14. 0
      test/decoder_temple.js
  15. 600
      test/decoder_wx.js
  16. 2
      test/glue.js
  17. 160
      test/h265.js
  18. 284
      test/h265dc.js
  19. BIN
      test/libffmpeg_.wasm
  20. 1
      test/libffmpeg_265_js
  21. BIN
      test/libffmpeg_265_wasm
  22. 4
      test/main.html
  23. 41
      test/mqtt.js
  24. 3
      test/parameter.js
  25. 1
      test/prod.h265.asm.combine.js
  26. 1
      test/prod.h265.wasm.combine.js
  27. 3474
      test/prod.h265.wasm.js
  28. 484
      test/prod_decoder.js
  29. 3
      test/start.js
  30. 38
      test/video.js
  31. 1
      test/videodec_simd_noems6_.js
  32. BIN
      test/videodec_simd_noems6_.wasm
  33. 5639
      test/videodec_simd_noems6_h265.js
  34. BIN
      test/videodec_simd_noems6_h265.wasm
  35. 6214
      test/videodec_wx_h265.js
  36. BIN
      test/videodec_wx_h265.wasm
  37. 1
      web_decoder_simple

4
build_decoder_264.sh

@ -3,7 +3,7 @@ rm -r ffmpeg
mkdir -p ffmpeg mkdir -p ffmpeg
cd ../FFmpeg cd ../FFmpeg
make clean make clean
emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../decoder_wasm/ffmpeg --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic \ emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../webrtc_H265player/ffmpeg --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic \
--enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-swresample --disable-postproc --disable-avfilter \ --enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-swresample --disable-postproc --disable-avfilter \
--disable-programs --disable-logging --disable-everything \ --disable-programs --disable-logging --disable-everything \
--disable-ffplay --disable-ffprobe --disable-asm --disable-doc --disable-devices --disable-network \ --disable-ffplay --disable-ffprobe --disable-asm --disable-doc --disable-devices --disable-network \
@ -11,5 +11,5 @@ emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../
--enable-decoder=h264 --enable-parser=h264 --enable-decoder=h264 --enable-parser=h264
make make
make install make install
cd ../decoder_wasm cd ../webrtc_H265player
./build_decoder_wasm.sh 264 ./build_decoder_wasm.sh 264

4
build_decoder_264_265.sh

@ -3,7 +3,7 @@ rm -r ffmpeg
mkdir -p ffmpeg mkdir -p ffmpeg
cd ../FFmpeg cd ../FFmpeg
make clean make clean
emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../decoder_wasm/ffmpeg --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic \ emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../webrtc_H265player/ffmpeg --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic \
--enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-swresample --disable-postproc --disable-avfilter \ --enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-swresample --disable-postproc --disable-avfilter \
--disable-programs --disable-logging --disable-everything \ --disable-programs --disable-logging --disable-everything \
--disable-ffplay --disable-ffprobe --disable-asm --disable-doc --disable-devices --disable-network \ --disable-ffplay --disable-ffprobe --disable-asm --disable-doc --disable-devices --disable-network \
@ -12,5 +12,5 @@ emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../
--enable-decoder=h264 --enable-parser=h264 --enable-decoder=h264 --enable-parser=h264
make make
make install make install
cd ../decoder_wasm cd ../webrtc_H265player
./build_decoder_wasm.sh 264_265 ./build_decoder_wasm.sh 264_265

4
build_decoder_265.sh

@ -3,7 +3,7 @@ rm -r ffmpeg
mkdir -p ffmpeg mkdir -p ffmpeg
cd ../FFmpeg cd ../FFmpeg
make clean make clean
emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../decoder_wasm/ffmpeg --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic \ emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../webrtc_H265player/ffmpeg --enable-cross-compile --target-os=none --arch=x86_32 --cpu=generic \
--enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-swresample --disable-postproc --disable-avfilter \ --enable-gpl --enable-version3 --disable-avdevice --disable-avformat --disable-swresample --disable-postproc --disable-avfilter \
--disable-programs --disable-logging --disable-everything \ --disable-programs --disable-logging --disable-everything \
--disable-ffplay --disable-ffprobe --disable-asm --disable-doc --disable-devices --disable-network \ --disable-ffplay --disable-ffprobe --disable-asm --disable-doc --disable-devices --disable-network \
@ -11,5 +11,5 @@ emconfigure ./configure --cc="emcc" --cxx="em++" --ar="emar" --prefix=$(pwd)/../
--enable-decoder=hevc --enable-parser=hevc --enable-decoder=hevc --enable-parser=hevc
make make
make install make install
cd ../decoder_wasm cd ../webrtc_H265player
./build_decoder_wasm.sh 265 ./build_decoder_wasm.sh 265

11
doc/开发助记.md

@ -0,0 +1,11 @@
开启浏览器HEVC
[https://github.com/StaZhu/enable-chromium-hevc-hardware-decoding]()
[FFmpeg-Plus-OpenGL with ffmpeg 4.0 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/559313629)
[Video TEST PAGE HEVC (ibytedtos.com)](https://lf-tk-sg.ibytedtos.com/obj/tcs-client-sg/resources/video_demo_hevc.html)
[https://github.com/Bilibili/flv.js]()
[https://w3c.github.io/media-source/]()

118
test/Player.js

@ -8,7 +8,7 @@ self.importScripts("common.js");
// var USE_MISSILE = false; // var USE_MISSILE = false;
// var decoder_type; // var decoder_type;
// var DECODER_TYPE = kDecoder_decodeer_js; // var DECODER_TYPE = kDecoder_decodeer_js;
// var DECODER_TYPE = kDecoder_prod_h265_wasm_combine_js; // var DECODER_TYPE = kDecoder_wx_h265_wasm_combine_js;
var webglPlayer, canvas, videoWidth, videoHeight, yLength, uvLength; var webglPlayer, canvas, videoWidth, videoHeight, yLength, uvLength;
var LOG_LEVEL_JS = 0; var LOG_LEVEL_JS = 0;
var LOG_LEVEL_WASM = 1; var LOG_LEVEL_WASM = 1;
@ -20,7 +20,7 @@ function Player(){
this.decoder_type = DECODER_TYPE;//DECODER_H265; this.decoder_type = DECODER_TYPE;//DECODER_H265;
this.decoding = false; this.decoding = false;
this.webrtcplayerState = playerStateIdle; this.webrtcplayerState = playerStateIdle;
this.decodeInterval = 3; //编码定时器 this.decodeInterval = 5; //编码定时器
this.urgent = false; this.urgent = false;
this.destroied = false; this.destroied = false;
this.decoderworker=null; this.decoderworker=null;
@ -35,6 +35,30 @@ Player.prototype.startDecoder=function(decoder_type){
var self = this; var self = this;
self.setDecoder(decoder_type); self.setDecoder(decoder_type);
switch(decoder_type){ switch(decoder_type){
case kDecoder_simd_decoder_js:
self.decoderworker=new Worker("decoder_simd.js");
var req = {
t: kInitDecoderReq,
};
self.decoderworker.postMessage(req);
self.decoderworker.onmessage=function (evt) {
var objData = evt.data;
switch (objData.t) {
case kInitDecoderRsp:
self.onInitDecoder(objData);
break;
case kOpenDecoderRsp:
self.onOpenDecoder(objData);
break;
case kVideoFrame:
self.onVideoFrame(objData.d);
break;
default:
console.log("Unsupport messsage " + req.t);
}
}
break;
case kDecoder_decodeer_js: case kDecoder_decodeer_js:
self.decoderworker=new Worker("decoder.js"); self.decoderworker=new Worker("decoder.js");
var req = { var req = {
@ -49,35 +73,43 @@ Player.prototype.startDecoder=function(decoder_type){
break; break;
case kOpenDecoderRsp: case kOpenDecoderRsp:
self.onOpenDecoder(objData); self.onOpenDecoder(objData);
// this.displayLoop();
// var req = {
// t: kInitPlayerReq,
// };
// self.postMessage(req);
break; break;
case kVideoFrame: case kVideoFrame:
self.onVideoFrame(objData); self.onVideoFrame(objData.d);
break; break;
// case kVideoFrame_Missle:
// self.onVideoFrame_Missle(objData);
// break;
// case kprodVideoFrame:
// self.onVideoFrame_Prod(objData);
// break;
// case "decode":
// console.log("decode"+objData)
// break;
default: default:
console.log("Unsupport messsage " + req.t); console.log("Unsupport messsage " + req.t);
} }
} }
break; break;
// this.decoderworker=new Worker("decoder_missle.js"); // this.decoderworker=new Worker("decoder_missle.js");
case kDecoder_prod_h265_wasm_combine_js: case kDecoder_wx_h265_wasm_combine_js:
// this.decoderworker=new Worker("prod_decoder.js"); // this.decoderworker=new Worker("prod_decoder.js");
self.Module = {}; self.Module = {};
self.decoderworker=new Worker("glue.js");//prod.h265.wasm.combine.js"); self.decoderworker=new Worker("decoder_wx.js");
self.SetProdDecoder(self.decoderworker,self); // self.SetWxDecoder(self.decoderworker,self);
var req = {
t: kInitDecoderReq,
};
self.decoderworker.postMessage(req);
self.decoderworker.onmessage=function (evt) {
var objData = evt.data;
switch (objData.t) {
case kInitDecoderRsp:
self.onInitDecoder(objData);
break;
case kOpenDecoderRsp:
self.onOpenDecoder(objData);
break;
case kVideoFrame:
self.onVideoFrame(objData);
break;
default:
console.log("Unsupport messsage " + req.t);
}
}
break; break;
case kDecoder_missile_decoder_js: case kDecoder_missile_decoder_js:
self.decoderworker=new Worker("decoder_missle.js");//prod.h265.wasm.combine.js"); self.decoderworker=new Worker("decoder_missle.js");//prod.h265.wasm.combine.js");
@ -181,7 +213,7 @@ Player.prototype.InitMissleDecoder =function(){
// } // }
// } // }
// } // }
Player.prototype.SetProdDecoder = function (worker,self){ Player.prototype.SetWxDecoder = function (worker,self){
worker.onmessage = function(msg){ // 收到胶水代码返回来的消息的处理方式 worker.onmessage = function(msg){ // 收到胶水代码返回来的消息的处理方式
var data = msg.data; var data = msg.data;
var decodet1=new Date().getTime(); var decodet1=new Date().getTime();
@ -264,18 +296,31 @@ Player.prototype.reqOpenDecoder=function(){
}; };
this.decoderworker.postMessage(req); this.decoderworker.postMessage(req);
} }
Player.prototype.onFrameData = function (data, len) { Player.prototype.onFrameData = function (data, len,type) {
// console.log("Got data bytes=" + start + "-" + end + "."); // console.log("Got data bytes=" + start + "-" + end + ".");
if(this.decoder_type===kDecoder_prod_h265_wasm_combine_js){ if(this.decoder_type===kDecoder_wx_h265_wasm_combine_js){
this.decode(data); this.decode(data);
}else{ }else{
var objData = { var objData = {
t: kFeedDataReq, t: kFeedDataReq,
type:type,
d: data d: data
}; };
this.decoderworker.postMessage(objData, [objData.d]); this.decoderworker.postMessage(objData, [objData.d.packet.buffer]); //见h265dc.js
} }
} }
// Player.prototype.onFrameData = function (data, len) {
// // console.log("Got data bytes=" + start + "-" + end + ".");
// if(this.decoder_type===kDecoder_wx_h265_wasm_combine_js){
// this.decode(data);
// }else{
// var objData = {
// t: kFeedDataReq,
// d: data
// };
// this.decoderworker.postMessage(objData, [objData.d.packet]); //见h265.js
// }
// }
Player.prototype.startBuffering = function () { Player.prototype.startBuffering = function () {
this.buffering = true; this.buffering = true;
this.showLoading(); this.showLoading();
@ -292,21 +337,22 @@ Player.prototype.displayVideoFrame = function (frame) {
var audioTimestamp=0; var audioTimestamp=0;
var delay=0 var delay=0
// console.log("displayVideoFrame delay=" + delay + "=" + " " + frame.s + " - (" + audioCurTs + " + " + this.beginTimeOffset + ")" + "->" + audioTimestamp); console.log("displayVideoFrame" );//delay=" + delay + "=" + " " + frame.s + " - (" + audioCurTs + " + " + this.beginTimeOffset + ")" + "->" + audioTimestamp);
if (audioTimestamp <= 0 || delay <= 0) { if (audioTimestamp <= 0 || delay <= 0) {
this.renderVideoFrame(frame.d); this.renderVideoFrame(frame);
return true; return true;
} }
return false; return false;
}; };
Player.prototype.displayLoop = function() { Player.prototype.displayLoop = function() {
console.log("displayLoop") // console.log("displayLoop")
if (this.webrtcplayerState !== playerStateIdle) { if (this.webrtcplayerState !== playerStateIdle) {
requestAnimationFrame(this.displayLoop.bind(this)); requestAnimationFrame(this.displayLoop.bind(this));
} }
if(this.frameBuffer.length>0){ if(this.frameBuffer.length>0){
console.log("displayLoop ready to display: ",this.frameBuffer.length)
var frame = this.frameBuffer[0]; var frame = this.frameBuffer[0];
if (this.displayVideoFrame(frame)) { if (this.displayVideoFrame(frame)) {
this.frameBuffer.shift(); this.frameBuffer.shift();
@ -334,6 +380,13 @@ Player.prototype.renderVideoFrame = function (data) {
self.postMessage(playFrame,[playFrame.d.data.buffer]) self.postMessage(playFrame,[playFrame.d.data.buffer])
}; };
Player.prototype.onNetStatus = function (status){
var playStatus={
t: kplaterNetStatus,
s: status
}
self.postMessage(playStatus)
}
Player.prototype.getBufferTimerLength = function() { Player.prototype.getBufferTimerLength = function() {
if (!this.frameBuffer || this.frameBuffer.length == 0) { if (!this.frameBuffer || this.frameBuffer.length == 0) {
return 0; return 0;
@ -347,7 +400,7 @@ Player.prototype.bufferFrame = function (frame) {
// If not decoding, it may be frame before seeking, should be discarded. // If not decoding, it may be frame before seeking, should be discarded.
this.frameBuffer.push(frame); this.frameBuffer.push(frame);
console.log("bufferFrame pts:" + frame.s+" w:" + frame.d.width + ", h: " + frame.d.height); console.log("bufferFrame pts:" + frame.s+" w:" + frame.width + ", h: " + frame.height);
} }
Player.prototype.onVideoFrame = function (frame) { Player.prototype.onVideoFrame = function (frame) {
@ -373,9 +426,14 @@ Player.prototype.processReq = function (req) {
this.displayLoop(); this.displayLoop();
break; break;
case ksendPlayerVideoFrameReq: case ksendPlayerVideoFrameReq:
this.onFrameData(req.d,req.l); this.onFrameData(req.d,req.l,"VIDEO");
break; break;
case ksendPlayerAudioFrameReq:
this.onFrameData(req.d,req.l,"AUDIO");
break;
case kconnectStatusResponse:
this.onNetStatus(req.s);
break;
default: default:
console.log("Unsupport messsage " + req.t); console.log("Unsupport messsage " + req.t);
} }

46
test/audio.js

@ -1,9 +1,9 @@
var CHUNK_SIZE = 4096; var CHUNK_SIZE = 4096;
var file; // var file;
var filePos = 0; // var filePos = 0;
var audioContext; var audioContext;
var audioSource; var audioSource;
var fileBuffer = []; var audiobuffer = [];
var audioEl; var audioEl;
var mediaSource; var mediaSource;
var sourceBuffer; var sourceBuffer;
@ -18,11 +18,11 @@ function setAudioDecoder(decoder) {
audioDecoder = decoder audioDecoder = decoder
} }
function handleAudioFiles(files) { // function handleAudioFiles(files) {
var file_list = files; // var file_list = files;
var file_idx = 0; // var file_idx = 0;
loadFile(file_list, file_idx); // loadFile(file_list, file_idx);
} // }
function initWebAudio() { function initWebAudio() {
console.log('Init audio context') console.log('Init audio context')
@ -48,7 +48,7 @@ function initMSE() {
function sourceOpenCallback() { function sourceOpenCallback() {
console.log('Media Source Ready') console.log('Media Source Ready')
sourceBuffer = mediaSource.addSourceBuffer('audio/aac') sourceBuffer = mediaSource.addSourceBuffer('audio/ogg');//'audio/aac')
sourceBuffer.addEventListener('updateend', updateEndCallback, false) sourceBuffer.addEventListener('updateend', updateEndCallback, false)
loadNextChunk(); loadNextChunk();
} }
@ -89,8 +89,8 @@ function fastForword() {
} }
function webAudioCallback() { function webAudioCallback() {
fileBuffer.push(this.result) audiobuffer.push(this.result)
var audioBuffer = mergeBuffer(fileBuffer, filePos) var audioBuffer = mergeBuffer(audiobuffer, filePos)
console.log('File buffer size = ', audioBuffer.byteLength) console.log('File buffer size = ', audioBuffer.byteLength)
if(!audioContext) { if(!audioContext) {
initWebAudio(); initWebAudio();
@ -104,9 +104,9 @@ function webAudioCallback() {
}, 100); }, 100);
} }
function scriptNodeCallback() { function scriptNodeCallback(data,len) {
fileBuffer.push(this.result) audiobuffer.push(data)
var audioBuffer = mergeBuffer(fileBuffer, filePos) var audioBuffer = mergeBuffer(data, len)
console.log('File buffer size = ', audioBuffer.byteLength) console.log('File buffer size = ', audioBuffer.byteLength)
if(!audioContext) { if(!audioContext) {
initWebAudio(); initWebAudio();
@ -150,8 +150,8 @@ function scriptNodeCallback() {
}, 100); }, 100);
} }
function mseCallback() { function mseCallback(data) {
fileBuffer.push(this.result) audiobuffer.push(data)
if(!sourceBuffer.updating) { if(!sourceBuffer.updating) {
console.log('load next buffer in mse call back') console.log('load next buffer in mse call back')
loadNextBuffer() loadNextBuffer()
@ -166,8 +166,8 @@ function mseCallback() {
} }
function loadNextBuffer() { function loadNextBuffer() {
if (fileBuffer.length) { if (audiobuffer.length) {
sourceBuffer.appendBuffer(fileBuffer.shift()); sourceBuffer.appendBuffer(audiobuffer.shift());
} }
if (filePos === file.size && !sourceBuffer.updating) { if (filePos === file.size && !sourceBuffer.updating) {
// else close the stream // else close the stream
@ -183,11 +183,11 @@ function startMSEPlay() {
} }
function loadNextChunk() { function loadNextChunk() {
var reader = new FileReader(); // var reader = new FileReader();
reader.onload = audioDecoder === DECODER_WEBAUDIO ? scriptNodeCallback : mseCallback // reader.onload = audioDecoder === DECODER_WEBAUDIO ? scriptNodeCallback : mseCallback
var i_stream_size = read_file_slice(reader, file, filePos, CHUNK_SIZE); // var i_stream_size = read_file_slice(reader, file, filePos, CHUNK_SIZE);
filePos += i_stream_size; // filePos += i_stream_size;
console.log('Load file size', i_stream_size) // console.log('Load file size', i_stream_size)
} }
function appendBuffer(buffer1, buffer2) { function appendBuffer(buffer1, buffer2) {

127
test/audiodc.js

@ -0,0 +1,127 @@
var bReAudio=false;
var audioDC=null;
const AUDIO_START_STR="audio start";
const AUDIO_END_STR="audio end"
const AUDIO_DECODEC_TYPE_STR="decodctype";
// const PACKET_LEN_STR="Packetslen";
// const PACKET_COUNT_STR="packets";
// const AUDIO_PACKET_PTS="audiopts";
// const AUDIO_PACKET_REM_STR="rem";
var decodctype="";
var audiopts=0;
var audiodata=null;
var audiodatalen=0;
var audiopacket=0;
var audioreceivet1=new Date().getTime();
function initAudioDC(pc) {
console.log("initAACDC",Date());
audioDC = pc.createDataChannel("audiodc");
audioDC.onmessage = function (event) {
// console.log(bReAudio,":",event.data)
if(bReAudio){
if(isString(event.data)) {
console.log("reveive: "+event.data)
if(event.data.indexOf(AUDIO_END_STR)!=-1){
bReAudio=false;
console.log("frame ok",":",event.data," len:"+audiodatalen)
if(audiodatalen>0){
// const framepacket=new Uint8Array(audiodata)
const audiot2 = new Date().getTime()-audioreceivet1;
console.log("receive time:"+audiot2+" len:"+audiodatalen);
mseCallback(audiodata);
//scriptNodeCallback(audiodata,len);
// var data={
// audiopts: audiopts,
// size: audiodatalen,
// decodctype: decodctype,
// packet: audiodata
// };
// var req = {
// t: ksendPlayerAudioFrameReq,
// l: audiodatalen,
// d: data
// };
// player.postMessage(req,[req.d.packet]);
audiodata=null;
audiodatalen=0;
audiopacket=0;
audioreceivet1=new Date().getTime();
}
return;
}
}else{
if (audiodata != null) {
audiodata=appendBuffer(audiodata,event.data);
} else if (event.data.byteLength < expectLength) {
audiodata = event.data.slice(0);
} else {
audiodata=event.data;
}
audiodatalen+=event.data.byteLength;
audiopacket++;
console.log("packet: "+audiopacket+": t len"+audiodatalen)
return;
}
}
if(isString(event.data)) {
let startstring = event.data
console.log("reveive: "+startstring)
if(startstring.indexOf(AUDIO_START_STR)!=-1){
// console.log(event.data );
const startarray=startstring.split(",");
// startstr := "audio start ,decodctype:" + decodctypestr + ",Packetslen:" + strconv.Itoa(glength) + ",packets:" + strconv.Itoa(count) + ",rem:" + strconv.Itoa(rem)
for(let i=0;i<startarray.length;i++){
const parakv=startarray[i].split(":");
if(parakv!==null){
switch(parakv[0]){
case AUDIO_START_STR:
break;
case PACKET_PTS:
audiopts=parseInt(parakv[1])
break;
case AUDIO_DECODEC_TYPE_STR:
decodctype=parakv[1]
break;
}
}
}
// string.split(":")
bReAudio=true;
audiopacket=0;
return;
}
}
};
audioDC.onopen = function () {
console.log("audio datachannel open");
// setAudioDecoder(1) //mse 0 contex
// playAudio();
// var req = {
// t: kInitPlayerReq,
// };
// player.postMessage(req);
bWorking = true;
};
audioDC.onclose = function () {
console.log("audio datachannel close");
bWorking=false;
};
}

16
test/audiodec.js

File diff suppressed because one or more lines are too long

BIN
test/audiodec.wasm

Binary file not shown.

25
test/common.js

@ -32,9 +32,11 @@ const playerStatePausing = 2;
const kInitPlayerReq = 0; const kInitPlayerReq = 0;
const kstartPlayerCoderReq = 1; const kstartPlayerCoderReq = 1;
const ksendPlayerVideoFrameReq = 2; const ksendPlayerVideoFrameReq = 2;
const ksendPlayerAudioFrameReq = 3;
const kplayeVideoFrame = 3; const kconnectStatusResponse = 4;
const kendPlayerCoderReq = 4; const kplayeVideoFrame = 5;
const kendPlayerCoderReq = 6;
const kplaterNetStatus = 7;
//H265Transferreq //H265Transferreq
const kstartH265TransferReq = 0; const kstartH265TransferReq = 0;
@ -42,12 +44,15 @@ const kendH265TransferReq = 1;
//WASM decoder types //WASM decoder types
const kDecoder_decodeer_js = 0; const kDecoder_decodeer_js = 0;
const kDecoder_prod_h265_wasm_combine_js = 1; const kDecoder_wx_h265_wasm_combine_js = 1;
const kDecoder_missile_decoder_js =2; const kDecoder_missile_decoder_js =2;
const kDecoder_simd_decoder_js =3;
const MAX_FRAME_SIZE=10;
const MAX_FRAME_SIZE=60;
const DECODER_TYPE = kDecoder_decodeer_js; const MAX_DELETE_FRAME_SIZE=1000;
// const DECODER_TYPE = kDecoder_missile_decoder_js; //解码器类型定义
// const DECODER_TYPE = kDecoder_prod_h265_wasm_combine_js; const DECODER_TYPE = kDecoder_simd_decoder_js; //ffmpeg simd 优化
// const DECODER_TYPE = kDecoder_decodeer_js; //ffmpeg decoder
// const DECODER_TYPE = kDecoder_missile_decoder_js; //小老虎解码器
// const DECODER_TYPE = kDecoder_wx_h265_wasm_combine_js; //Wxplayer 解码器

73
test/decoder.js

@ -17,6 +17,7 @@ var decoder_type = DECODER_H265;
var pts=0; var pts=0;
H265Frame =[]; H265Frame =[];
AudioFrame =[];
function Decoder(){ function Decoder(){
// this.timer=null; // this.timer=null;
this.decodeTimer = null; this.decodeTimer = null;
@ -59,19 +60,29 @@ Decoder.prototype.uninitDecoder = function () {
// this.cacheBuffer = null; // this.cacheBuffer = null;
// } // }
}; };
const MIN_FRAME_FOR_DECODE=0
var decodet1=new Date().getTime(); var decodet1=new Date().getTime();
Decoder.prototype.decode=function(){ Decoder.prototype.decode=function(){
if(H265Frame.length>0){ if(H265Frame.length>MIN_FRAME_FOR_DECODE){
// decodet1=new Date().getTime();
// var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]);
// var size = typedArray.length
// console.log("decode len: " + size)
// var cacheBuffer = Module._malloc(size);
// Module.HEAPU8.set(typedArray, cacheBuffer);
decodet1=new Date().getTime(); decodet1=new Date().getTime();
var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]); var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]);
var packet=typedArray.d;
var size = typedArray.length var size = typedArray.size;
// console.log("decode len: " + size)
console.log("decode pts:",typedArray.pts," packet len:",size," H265Frame total",H265Frame.length)
var cacheBuffer = Module._malloc(size); var cacheBuffer = Module._malloc(size);
Module.HEAPU8.set(typedArray, cacheBuffer); Module.HEAPU8.set(packet, cacheBuffer);
// totalSize += size // totalSize += size
// console.log("[" + (++readerIndex) + "] Read len = ", size + ", Total size = " + totalSize) // console.log("[" + (++readerIndex) + "] Read len = ", size + ", Total size = " + totalSize)
// console.log(typedArray.toString(16));
Module._decodeData(cacheBuffer, size, pts++) Module._decodeData(cacheBuffer, size, typedArray.pts)
if (cacheBuffer != null) { if (cacheBuffer != null) {
Module._free(cacheBuffer); Module._free(cacheBuffer);
cacheBuffer = null; cacheBuffer = null;
@ -128,6 +139,14 @@ Decoder.prototype.displayVideoFrame = function displayVideoFrame(obj){
// decodet1=new Date().getTime(); // decodet1=new Date().getTime();
// displayVideoFrame(obj); // displayVideoFrame(obj);
} }
IsGreyData = function(data) {
var isgray=false;
var len=data.length<100?data.length:100;
for(var i=0; i<len;i++){
isgray=data[i]===128?true:false;
}
return isgray;
}
Decoder.prototype.decode_seq=function() { Decoder.prototype.decode_seq=function() {
var start_time = new Date(); var start_time = new Date();
@ -135,6 +154,18 @@ Decoder.prototype.decode_seq=function() {
var videoCallback = Module.addFunction(function (addr_y, addr_u, addr_v, stride_y, stride_u, stride_v, width, height, pts) { var videoCallback = Module.addFunction(function (addr_y, addr_u, addr_v, stride_y, stride_u, stride_v, width, height, pts) {
console.log("[%d]In video callback, size = %d * %d, pts = %d", ++videoSize, width, height, pts) console.log("[%d]In video callback, size = %d * %d, pts = %d", ++videoSize, width, height, pts)
let out_y = HEAPU8.subarray(addr_y, addr_y + stride_y * height) let out_y = HEAPU8.subarray(addr_y, addr_y + stride_y * height)
// if(IsGreyData(out_y)===true) {
// return;
// }
var isgray=false;
var len=out_y.length<100?out_y.length:100;
// for(var i=0; i<len;i++){
// isgray=out_y[i]===128?true:false;
// }
// if( isgray === true) {
// return;
// }
//if (out_y[0]===128 & out_y[0]===128 & out_y[0]===128 & out_y[0]===128
let out_u = HEAPU8.subarray(addr_u, addr_u + (stride_u * height) / 2) let out_u = HEAPU8.subarray(addr_u, addr_u + (stride_u * height) / 2)
let out_v = HEAPU8.subarray(addr_v, addr_v + (stride_v * height) / 2) let out_v = HEAPU8.subarray(addr_v, addr_v + (stride_v * height) / 2)
let buf_y = new Uint8Array(out_y) let buf_y = new Uint8Array(out_y)
@ -144,14 +175,15 @@ Decoder.prototype.decode_seq=function() {
data.set(buf_y, 0) data.set(buf_y, 0)
data.set(buf_u, buf_y.length) data.set(buf_u, buf_y.length)
data.set(buf_v, buf_y.length + buf_u.length) data.set(buf_v, buf_y.length + buf_u.length)
var obj = { var obj = {
s: pts,
data: data, data: data,
width, width,
height height
} }
var objData = { var objData = {
t: kVideoFrame, t: kVideoFrame,
s: pts,
d: obj d: obj
}; };
self.postMessage(objData, [objData.d.data.buffer]); self.postMessage(objData, [objData.d.data.buffer]);
@ -236,13 +268,27 @@ Decoder.prototype.decode_seq=function() {
} }
Decoder.prototype.sendVideoFrame = function(data,len){ Decoder.prototype.sendFrame = function(data,type){
var typedArray = new Uint8Array(data); // var typedArray = {
// pts: data.pts,
// size: data.size,
// d: new Uint8Array(data.packet)
// }
var typedArray = {
pts: data.pts,
size: data.size,
d: data.packet//new Uint8Array(data.packet)
}
// var typedArray = new Uint8Array(data.packet);
// if(H265Frame.length>MAX_FRAME_SIZE){ // if(H265Frame.length>MAX_FRAME_SIZE){
// H265Frame.shift(); // H265Frame.shift();
// } // }
H265Frame.push(typedArray) if(type==="VIDEO"){
H265Frame.push(typedArray)
}else if(type==="AUDIO"){
AUDIOFrame.push(typedArray)
}
// var size = typedArray.length // var size = typedArray.length
// var cacheBuffer = Module._malloc(size); // var cacheBuffer = Module._malloc(size);
// Module.HEAPU8.set(typedArray, cacheBuffer); // Module.HEAPU8.set(typedArray, cacheBuffer);
@ -299,7 +345,12 @@ Decoder.prototype.processReq = function (req) {
this.pauseDecoding(); this.pauseDecoding();
break; break;
case kFeedDataReq: case kFeedDataReq:
this.sendVideoFrame(req.d); this.sendFrame(req.d,req.type);
// if(req.type==="VIDEO"){
// this.sendVideoFrame(req.d);
// }else{
// this.sendAudioFrame(req.d);
// }
break; break;
// case kSeekToReq: // case kSeekToReq:
// this.seekTo(req.ms); // this.seekTo(req.ms);

17
test/decoder_____missle.js

File diff suppressed because one or more lines are too long

405
test/decoder_simd.js

@ -0,0 +1,405 @@
self.Module = {
onRuntimeInitialized: function () {
onWasmLoaded();
},
};
self.importScripts("common.js");
self.importScripts("videodec_simd_noems6_h265.js")
var pts=0;
H265Frame =[];
AUDIOFrame =[];
function Decoder(){
// this.timer=null;
this.decodeTimer = null;
this.wasmLoaded = false;
this.vtype = 'hevc'
this.format = 'annexb'
this.extraData = ""
this.tmpReqQue = [];
this.decodestatus=false;
this.lastpts = 0;
}
Decoder.prototype.cacheReq = function (req) {
if (req) {
this.tmpReqQue.push(req);
}
};
Decoder.prototype.onWasmLoaded = function () {
console.log("Wasm loaded.");
this.wasmLoaded = true;
while (this.tmpReqQue.length > 0) {
var req = this.tmpReqQue.shift();
this.processReq(req);
}
}
Decoder.prototype.initDecoder = function () {
var ret=0;
//void VideoDecoder::setCodec(string vtype, string format, string extra)
Module._codecInit()
console.log("initDecoder return " + ret + ".");
var objData = {
t: kInitDecoderRsp,
e: ret
};
self.postMessage(objData);
};
Decoder.prototype.uninitDecoder = function () {
var ret = 0;//Module._uninitDecoder();
Module._clear();
console.log("Uninit ffmpeg decoder return " + ret + ".");
};
// var data={
// pts: pts,
// size: size,
// iskeyframe: isKeyFrame,
// packet: h265data
// };
// var req = {
// t: ksendPlayerVideoFrameReq,
// l: h265datalen,
// d: data
// };
const MIN_H265FRAME_FOR_DECODE=0
var decodet1=new Date().getTime();
Decoder.prototype.decode=function(){
if(H265Frame.length>MIN_H265FRAME_FOR_DECODE){
// this.decodestatus=true;
decodet1=new Date().getTime();
var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]);
var packet=typedArray.d;
var size = typedArray.size;
// console.log("decode len: " + size)
console.log("decode pts:",typedArray.pts," packet len:",size," H265Frame total",H265Frame.length)
var cacheBuffer = Module._malloc(size);
Module.HEAPU8.set(packet, cacheBuffer);
//void VideoDecoder::decode(string input, unsigned int isKeyFrame, unsigned int timestamp)
Module._decode(cacheBuffer,size,typedArray.iskeyframe,typedArray.pts);
if (cacheBuffer != null) {
Module._free(cacheBuffer);
cacheBuffer = null;
}
H265Frame.shift();
}
}
Decoder.prototype.startDecoding = function (interval) {
console.log("Start decoding.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
}
this.decodeTimer = setInterval(this.decode, 0);//interval);
};
Decoder.prototype.pauseDecoding = function () {
console.log("Pause decoding.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
this.decodeTimer = null;
}
};
// Decoder.prototype.startdecode=function(){
// // this.timer = requestAnimationFrame(function fn() {
// // // if(this.decodertimer++>=60)
// // this.decodertimer=0;
// // this.decode();
// // requestAnimationFrame(fn);
// // })
// // move = parseInt(getComputedStyle(box).left);
// // if (move < 800) {
// // box.style.left = move + 8 + 'px';
// // requestAnimationFrame(fn);
// // } else {
// // cancelAnimationFrame(timer);
// }
Decoder.prototype.displayVideoFrame = function displayVideoFrame(obj){
// var obj = {
// data: data,
// width,
// height
// }
var objData = {
t: kVideoFrame,
s: pts,
d: obj
};
self.postMessage(objData, [objData.d.data.buffer]);
const t2 = new Date().getTime()-decodet1;
console.log("end decode time:"+t2+" len:"+size);//+" data:"+typedArray.toString(16));
// decodet1=new Date().getTime();
// displayVideoFrame(obj);
}
IsGreyData = function(data) {
var isgray=false;
var len=data.length<100?data.length:100;
for(var i=0; i<len;i++){
isgray=data[i]===128?true:false;
}
return isgray;
}
Decoder.prototype.decode_seq=function() {
//void(*VideoCallback)(unsigned char* data,int width, int height, long pts);
var videoCallback = Module.addFunction(function (yuvArray, width, height, pts) {
let size = width*height;
let halfSize = size>>2;
let yPtr = HEAPU32[(yuvArray>>2)];
let uPtr = HEAPU32[(yuvArray>>2) + 1];
let vPtr = HEAPU32[(yuvArray>>2) + 2];
let yBuf = HEAPU8.subarray(yPtr, yPtr + size);
let uBuf = HEAPU8.subarray(uPtr, uPtr + halfSize);
let vBuf = HEAPU8.subarray(vPtr, vPtr + halfSize);
// let datas = [Uint8Array.from(yBuf), Uint8Array.from(uBuf), Uint8Array.from(vBuf)];
let datas = new Uint8Array(yBuf.length + uBuf.length + vBuf.length)
// let out_u = HEAPU8.subarray(addr_u, addr_u + (stride_u * height) / 2)
// let out_v = HEAPU8.subarray(addr_v, addr_v + (stride_v * height) / 2)
// let buf_y = new Uint8Array(out_y)
// let buf_u = new Uint8Array(out_u)
// let buf_v = new Uint8Array(out_v)
// let data = new Uint8Array(buf_y.length + buf_u.length + buf_v.length)
datas.set(yBuf, 0)
datas.set(uBuf, yBuf.length)
datas.set(vBuf, yBuf.length + uBuf.length)
var obj = {
s: pts,
data: datas,
width,
height,
}
var objData = {
t: kVideoFrame,
d: obj
};
self.postMessage(objData, [objData.d.data.buffer]);
const t2 = new Date().getTime()-decodet1;
console.log("end decode simd time:"+t2,"pts",pts);//+" data:"+typedArray.toString(16));
},'viiii')
this.vtype="hevc";
this.format="annexb";
this.extraData="";
Module._setCodec(this.vtype,this.format,this.extraData,videoCallback);
// var ret = Module._openDecoder(decoder_type, videoCallback, LOG_LEVEL_WASM)
// if(ret == 0) {
console.log("openDecoder success");
// } else {
// console.error("openDecoder failed with error", ret);
// // return;
// }
var objData = {
t: kOpenDecoderRsp,
e: 0
};
self.postMessage(objData);
}
// Decoder.prototype.onVideoInfo=function(width,height){
// this.width=width;
// this.height=height;
// var objData={
// t: kVideoInfo,
// width: width,
// height: height
// };
// self.postMessage(objData);
// }
// Decoder.prototype.onYUVData = function (yuvArray,pts){
// let size = this.width*this.height;
// let halfSize = size>>2;
// let yPtr = HEAPU32[(yuvArray>>2)];
// let uPtr = HEAPU32[(yuvArray>>2) + 1];
// let vPtr = HEAPU32[(yuvArray>>2) + 2];
// let yBuf = HEAPU8.subarray(yPtr, yPtr + size);
// let uBuf = HEAPU8.subarray(uPtr, uPtr + halfSize);
// let vBuf = HEAPU8.subarray(vPtr, vPtr + halfSize);
// let datas = [Uint8Array.from(yBuf), Uint8Array.from(uBuf), Uint8Array.from(vBuf)];
// // let vFrame = {
// // pixelType:'I420',
// // datas: datas,
// // width: this.width,
// // height: this.height,
// // pts: pts
// // };
// // let out_u = HEAPU8.subarray(addr_u, addr_u + (stride_u * height) / 2)
// // let out_v = HEAPU8.subarray(addr_v, addr_v + (stride_v * height) / 2)
// // let buf_y = new Uint8Array(out_y)
// // let buf_u = new Uint8Array(out_u)
// // let buf_v = new Uint8Array(out_v)
// // let data = new Uint8Array(buf_y.length + buf_u.length + buf_v.length)
// // data.set(buf_y, 0)
// // data.set(buf_u, buf_y.length)
// // data.set(buf_v, buf_y.length + buf_u.length)
// var obj = {
// data: datas,
// width,
// height
// }
// var objData = {
// t: kVideoFrame,
// s: pts,
// d: obj
// };
// self.postMessage(objData, [objData.d.data.buffer]);
// const t2 = new Date().getTime()-decodet1;
// console.log("decode time:"+t2);//+" data:"+typedArray.toString(16));
// }
function findMinFrame(H265Frame){
var min=50000;
var index=0;
for(var i=0;i<H265Frame.length;i++){
if((H265Frame[i].iskeyframe!==true)){
if(H265Frame[i].size<min){
min=H265Frame[i].size
index=i
}
}
}
return index
}
Decoder.prototype.sendFrame = function(data,type){
// if(data.pts<=this.lastpts){
// return;
// }
this.lastpts=data.pts;
var typedArray = {
pts: data.pts,
iskeyframe: data.iskeyframe,
size: data.size,
// d: data.packet//
d: data.packet//new Uint8Array(data.packet)
}
console.log("sendFrame pts:",typedArray.pts)
// if(H265Frame.length>MAX_FRAME_SIZE){
// H265Frame.shift();
// }
if(type==="VIDEO"){
if(H265Frame.length>MAX_FRAME_SIZE){
var index=findMinFrame(H265Frame)
H265Frame = H265Frame.splice(index, 1)
// for(var i=0;i<H265Frame.length;i++)
// if((H265Frame[i].iskeyframe!==true)){
// // &&(H265Frame[i].size<MAX_DELETE_FRAME_SIZE)
// H265Frame = H265Frame.splice(i, 1)
// break
// //break;
// // H265Frame.shift();
// }
}
H265Frame.push(typedArray)
}else if(type==="AUDIO"){
AUDIOFrame.push(typedArray)
}
}
Decoder.prototype.closeDecoder = function () {
console.log("closeDecoder.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
this.decodeTimer = null;
console.log("Decode timer stopped.");
}
// var ret = Module._closeDecoder();
console.log("Close ffmpeg decoder return " + ret + ".");
var objData = {
t: kCloseDecoderRsp,
e: 0
};
self.postMessage(objData);
};
Decoder.prototype.processReq = function (req) {
// console.log("processReq " + req.t + ".");
switch (req.t) {
case kInitDecoderReq:
this.initDecoder();
break;
case kUninitDecoderReq:
this.uninitDecoder();
break;
case kOpenDecoderReq:
this.decode_seq();
break;
case kCloseDecoderReq:
this.closeDecoder();
break;
case kStartDecodingReq:
this.startDecoding(req.i);
break;
case kPauseDecodingReq:
this.pauseDecoding();
break;
case kFeedDataReq:
this.sendFrame(req.d,req.type);
break;
// case kSeekToReq:
// this.seekTo(req.ms);
// break;
default:
this.logger.logError("Unsupport messsage " + req.t);
}
};
self.decoder = new Decoder;
self.onmessage = function (evt) {
if (!self.decoder) {
console.log("[ER] Decoder not initialized!");
return;
}
var req = evt.data;
if (!self.decoder.wasmLoaded) {
self.decoder.cacheReq(req);
console.log("Temp cache req " + req.t + ".");
return;
}
self.decoder.processReq(req);
};
function onWasmLoaded() {
if (self.decoder) {
self.decoder.onWasmLoaded();
} else {
console.log("[ER] No decoder!");
}
}
function onVideoInfo(width,height){
if (self.decoder) {
self.decoder.onVideoInfo(width,height);
} else {
console.log("[ER] No decoder!");
}
}
function onYUVData (yuvArray,pts){
if (self.decoder) {
self.decoder.onYUVData(yuvArray,pts);
} else {
console.log("[ER] No decoder!");
}
}

0
test/decoder copy.js → test/decoder_temple.js

600
test/decoder_wx.js

@ -0,0 +1,600 @@
//https://juejin.cn/post/7050496511288803336
// mergeInto(LibraryManager.library,{
// onHeader: function(header){
// return jsonHeader(header);
// },
// onMediaInfo: function(mediaInfo) {
// console.log("onMediaInfo"+mediaInfo.toString(16));
// //Module.postMessage({ type: "mediaInfo", data: mediaInfo });
// },
// onAudioDataSize: function(data) {
// // Module.audioBufferSize = data.size;
// // Module.audioBuffer = Module._malloc(Module.audioBufferSize);
// // Module._codecSetAudioBuffer(Module.audioBuffer);
// },
// onAudioData: function(data) {
// // var timestamp = data.timestamp;
// // Module.audioTimestamps.push(timestamp);
// // var u8s = Module.HEAPU8.subarray(
// // Module.audioBuffer,
// // Module.audioBuffer + Module.audioBufferSize
// // );
// // var output = null;
// // if (supportSharedBuffer) {
// // output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
// // output.set(u8s);
// // } else {
// // output = new Uint8Array(u8s);
// // }
// // Module._free(Module.audioBuffer);
// // Module.audioBuffer = null;
// // Module.postMessage(
// // {
// // type: "audio",
// // data: {
// // buffer: output.buffer,
// // timestamp: timestamp
// // }
// // },
// // supportSharedBuffer ? undefined : [output.buffer]
// // );
// },
// onVideoDataSize: function(data) {
// console.log("onVideoDataSize"+data.toString(16));
// // if (Module.videoBuffer == null) {
// // Module.videoBufferSize = data.size;
// // Module.videoBuffer = Module._malloc(Module.videoBufferSize);
// // if (supportSharedBuffer) {
// // Module.videoSharedBuffer = new SharedArrayBuffer(data.size);
// // }
// // }
// // Module._codecSetVideoBuffer(Module.videoBuffer);
// },
// onVideoData: function(data) {
// console.log("onVideoData"+data.toString(16));
// // var timestamp = data.timestamp;
// // Module.videoTimestamps.push(timestamp);
// // var u8s = Module.HEAPU8.subarray(
// // Module.videoBuffer,
// // Module.videoBuffer + Module.videoBufferSize
// // );
// // var output = null;
// // if (supportSharedBuffer) {
// // output = new Uint8Array(Module.videoSharedBuffer);
// // output.set(u8s);
// // } else {
// // output = new Uint8Array(u8s);
// // }
// // Module.postMessage(
// // {
// // type: "video",
// // data: {
// // buffer: output.buffer,
// // timestamp: timestamp,
// // width: data.width,
// // height: data.height,
// // stride0: data.stride0,
// // stride1: data.stride1
// // }
// // },
// // supportSharedBuffer ? undefined : [output.buffer]
// // );
// },
// onComplete: function() {
// console.log("onComplete");
// // Module.postMessage({ type: "complete" });
// }
// })
var Module = {};
self.importScripts("common.js");
self.importScripts("videodec_wx_h265.js");
self.importScripts("raw-parser.js");
var isWorker = typeof importScripts == "function";
var bridgeName = "__CODE_BRIDGE__" + +new Date();
(isWorker ? self : window)[bridgeName] = {
onHeader: function(header) {
onHeader(header);
// Module.postMessage({ type: "header", data: header });
},
onMediaInfo: function(mediaInfo) {
onMediaInfo(mediaInfo);
// Module.postMessage({ type: "mediaInfo", data: mediaInfo });
},
onAudioDataSize: function(data) {
onAudioDataSize(data);
// Module.audioBufferSize = data.size;
// Module.audioBuffer = Module._malloc(Module.audioBufferSize);
// Module._codecSetAudioBuffer(Module.audioBuffer);
},
onAudioData: function(data) {
onVideoData(data);
// var timestamp = data.timestamp;
// Module.audioTimestamps.push(timestamp);
// var u8s = Module.HEAPU8.subarray(
// Module.audioBuffer,
// Module.audioBuffer + Module.audioBufferSize
// );
// var output = null;
// if (supportSharedBuffer) {
// output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
// output.set(u8s);
// } else {
// output = new Uint8Array(u8s);
// }
// Module._free(Module.audioBuffer);
// Module.audioBuffer = null;
// Module.postMessage(
// {
// type: "audio",
// data: {
// buffer: output.buffer,
// timestamp: timestamp
// }
// },
// supportSharedBuffer ? undefined : [output.buffer]
// );
},
onVideoDataSize: function(data) {
onAudioDataSize(data);
// if (Module.videoBuffer == null) {
// Module.videoBufferSize = data.size;
// Module.videoBuffer = Module._malloc(Module.videoBufferSize);
// if (supportSharedBuffer) {
// Module.videoSharedBuffer = new SharedArrayBuffer(data.size);
// }
// }
// Module._codecSetVideoBuffer(Module.videoBuffer);
},
onVideoData: function(data) {
onVideoData(data);
// var timestamp = data.timestamp;
// Module.videoTimestamps.push(timestamp);
// var u8s = Module.HEAPU8.subarray(
// Module.videoBuffer,
// Module.videoBuffer + Module.videoBufferSize
// );
// var output = null;
// if (supportSharedBuffer) {
// output = new Uint8Array(Module.videoSharedBuffer);
// output.set(u8s);
// } else {
// output = new Uint8Array(u8s);
// }
// Module.postMessage(
// {
// type: "video",
// data: {
// buffer: output.buffer,
// timestamp: timestamp,
// width: data.width,
// height: data.height,
// stride0: data.stride0,
// stride1: data.stride1
// }
// },
// supportSharedBuffer ? undefined : [output.buffer]
// );
},
onComplete: function() {
onComplete();
// Module.postMessage({ type: "complete" });
}
};
// var decoder_type = DECODER_H265;
var ptsIdx=0;
H265Frame =[];
function Decoder(){
// this.timer=null;
this.decodeTimer = null;
this.rawParserObj = null;
this.wasmLoaded = false;
this.tmpReqQue = [];
this.destroied = false;
// this.poddecoder = null;
this.supportSharedBuffer = false;
this.bridgeName = "__CODE_BRIDGE__" + +new Date();
this.audioTimestamps = []
this.videoTimestamps = []
this.audioBufferSize = 0
this.videoBufferSize = 0
this.audioBuffer = null
this.videoBuffer = null
this.videoSharedBuffer =null;
// var supportSharedBuffer = false;
try {
this.supportSharedBuffer = !!new SharedArrayBuffer(0);
} catch (e) {
// nothing to do...
}
// this.token = "base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1";
// this.version = '100.2.0';
}
Decoder.prototype.cacheReq = function (req) {
if (req) {
this.tmpReqQue.push(req);
}
};
Decoder.prototype.onWasmLoaded = function () {
console.log("Wasm loaded.");
this.wasmLoaded = true;
while (this.tmpReqQue.length > 0) {
var req = this.tmpReqQue.shift();
this.processReq(req);
}
}
Decoder.prototype.initDecoder = function () {
// var ret = Module._initDecoder(fileSize, this.coreLogLevel);
var ret=0;
console.log("initDecoder return " + ret + ".");
try {
this.supportSharedBuffer = !!new SharedArrayBuffer(0);
} catch (e) {
// nothing to do...
}
// this.bridgeName = "__CODE_BRIDGE__" + +new Date();
Module._codecInit();
var callbackStr = bridgeName.split("");
callbackStr = callbackStr
.map(function(v) {
return v.charCodeAt(0);
})
.concat(0);
var callbackStrData = Module._malloc(callbackStr.length - 1);
Module.HEAPU8.set(callbackStr, callbackStrData);
Module._codecSetBridgeName(callbackStrData);
var objData = {
t: kInitDecoderRsp,
e: ret
};
self.postMessage(objData);
};
Decoder.prototype.openDecoder = function () {
var objData = {
t: kOpenDecoderRsp,
e: 0
};
self.postMessage(objData);
}
Decoder.prototype.uninitDecoder = function () {
var ret = 0;//Module._uninitDecoder();
Module._codecFree();
console.log("Uninit ffmpeg decoder return " + ret + ".");
};
Decoder.prototype.onHeader = function(header) {
console.log("onHeader",header);
// Module.postMessage({ type: "header", data: header });
};
Decoder.prototype.onMediaInfo = function(mediaInfo) {
console.log("onMediaInfo",mediaInfo);
// Module.postMessage({ type: "mediaInfo", data: mediaInfo });
};
Decoder.prototype.onAudioDataSize = function(data) {
console.log("onAudioDataSize",data);
this.audioBufferSize = data.size;
this.audioBuffer = Module._malloc(this.audioBufferSize);
Module._codecSetAudioBuffer(this.audioBuffer);
};
Decoder.prototype.onAudioData = function(data) {
var timestamp = data.timestamp;
this.audioTimestamps.push(timestamp);
var u8s = Module.HEAPU8.subarray(
this.audioBuffer,
this.audioBuffer +this.audioBufferSize
);
var output = null;
if (supportSharedBuffer) {
output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
output.set(u8s);
} else {
output = new Uint8Array(u8s);
}
Module._free(this.audioBuffer);
this.audioBuffer = null;
// Module.postMessage(
// {
// type: "audio",
// data: {
// buffer: output.buffer,
// timestamp: timestamp
// }
// },
// supportSharedBuffer ? undefined : [output.buffer]
// );
};
Decoder.prototype.onVideoDataSize = function(data){
console.log("onAudioDataSize",data);
if (this.videoBuffer == null) {
this.videoBufferSize = data.size;
this.videoBuffer = Module._malloc(this.videoBufferSize);
if (this.supportSharedBuffer) {
this.videoSharedBuffer = new SharedArrayBuffer(data.size);
}
}
Module._codecSetVideoBuffer(this.videoBuffer);
}
Decoder.prototype.onVideoData = function(data) {
var timestamp = data.timestamp;
this.videoTimestamps.push(timestamp);
var u8s = Module.HEAPU8.subarray(
this.videoBuffer,
this.videoBuffer + this.videoBufferSize
);
var output = null;
if (this.supportSharedBuffer) {
output = new Uint8Array(this.videoSharedBuffer);
output.set(u8s);
} else {
output = new Uint8Array(u8s);
}
// Module.postMessage(
// {
// type: "video",
// data: {
// buffer: output.buffer,
// timestamp: timestamp,
// width: data.width,
// height: data.height,
// stride0: data.stride0,
// stride1: data.stride1
// }
// },
// supportSharedBuffer ? undefined : [output.buffer]
// );
var obj = {
data: output,
width: data.width,
height: data.height,
}
var objData = {
t: kprodVideoFrame,
s: timestamp,
stride0: data.stride0,
stride1: data.stride1,
d: obj
};
self.postMessage(objData, [objData.d.data.buffer]);
};
Decoder.prototype.onComplete=function() {
console.log("onComplete");
// Module.postMessage({ type: "complete" });
}
var decodet1=new Date().getTime();
Decoder.prototype.decodeVideo=function(){
if(H265Frame.length>0){
decodet1=new Date().getTime();
// var typedArray= H265Frame.shift();//H265Frame[0];//new Uint8Array(H265Frame[0]);
var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]);
var packet=typedArray.d;
var size = typedArray.size;
console.log("decode len: " + size)
var cacheBuffer = Module._malloc(size);
Module.HEAPU8.set(packet, cacheBuffer);
// var size = typedArray.length
// var cacheBuffer = Module._malloc(size);
// Module.HEAPU8.set(typedArray, cacheBuffer);
// this.audioTimestamps = [];
// this.videoTimestamps = [];
Module._codecDecode(cacheBuffer, size);
// this.decode(cacheBuffer)
if (cacheBuffer != null) {
Module._free(cacheBuffer);
cacheBuffer = null;
}
}
}
// Decoder.prototype.decodeVideo = function(){ // 对外api,解码一段数据
// }
// Decoder.prototype.decode = function(buffer){ // 对外api,解码一段数据
// var buffer = new Uint8Array(data.buffer);
// var data = Module._malloc(buffer.length);
// Module.HEAPU8.set(buffer, data);
// var now = +new Date();
// Module.audioTimestamps = [];
// Module.videoTimestamps = [];
// Module._codecDecode(data, buffer.length);
// // h265decode(buffer);
// // if(Module){
// // // Module.postMessage({
// // // type: 'decode',
// // // buffer: buffer,
// // // });
// // }
// }
Decoder.prototype.destroy = function(){ // 对外api,销毁解码器
this.destroied = true;
// if(Module){
// // window.URL.revokeObjectURL(this.url);
// Module.postMessage({type: 'destroy'});
// }
}
Decoder.prototype.startDecoding = function (interval) {
console.log("Start decoding.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
}
this.decodeTimer = setInterval(this.decodeVideo, 0);//interval);
};
Decoder.prototype.pauseDecoding = function () {
console.log("Pause decoding.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
this.decodeTimer = null;
}
};
Decoder.prototype.sendVideoFrame = function(data,len){
var typedArray = new Uint8Array(data);
if(H265Frame.length>MAX_FRAME_SIZE){
H265Frame.shift();
}
H265Frame.push(typedArray)
}
Decoder.prototype.closeDecoder = function () {
console.log("closeDecoder.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
this.decodeTimer = null;
console.log("Decode timer stopped.");
}
// var ret = Module._closeDecoder();
console.log("Close ffmpeg decoder return " + ret + ".");
var objData = {
t: kCloseDecoderRsp,
e: 0
};
self.postMessage(objData);
};
Decoder.prototype.processReq = function (req) {
// console.log("processReq " + req.t + ".");
switch (req.t) {
case kInitDecoderReq:
this.initDecoder();
break;
case kUninitDecoderReq:
this.uninitDecoder();
break;
case kOpenDecoderReq:
this.openDecoder();
break;
case kCloseDecoderReq:
this.closeDecoder();
break;
case kStartDecodingReq:
this.startDecoding(req.i);
break;
case kPauseDecodingReq:
this.pauseDecoding();
break;
case kFeedDataReq:
this.sendVideoFrame(req.d);
break;
// case kSeekToReq:
// this.seekTo(req.ms);
// break;
default:
this.logger.logError("Unsupport messsage " + req.t);
}
};
self.decoder = new Decoder;
self.onmessage = function (evt) {
if (!self.decoder) {
console.log("[ER] Decoder not initialized!");
return;
}
var req = evt.data;
if (!self.decoder.wasmLoaded) {
self.decoder.cacheReq(req);
console.log("Temp cache req " + req.t + ".");
return;
}
self.decoder.processReq(req);
};
function onWasmLoaded() {
if (self.decoder) {
self.decoder.onWasmLoaded();
} else {
console.log("[ER] No decoder!");
}
}
function onHeader(header){
if (self.decoder) {
self.decoder.onHeader(header);
} else {
console.log("[ER] No decoder!");
}
}
function onMediaInfo(mediaInfo){
if (self.decoder) {
self.decoder.onMediaInfo(mediaInfo);
} else {
console.log("[ER] No decoder!");
}
}
function onVideoDataSize(data) {
if (self.decoder) {
self.decoder.onVideoDataSize(data);
} else {
console.log("[ER] No decoder!");
}
}
function onVideoData(data) {
if (self.decoder) {
self.decoder.onVideoData(data);
} else {
console.log("[ER] No decoder!");
}
}
function onAudioDataSize(data) {
if (self.decoder) {
self.decoder.onAudioDataSize(data);
} else {
console.log("[ER] No decoder!");
}
}
function onAudioData(data) {
if (self.decoder) {
self.decoder.onAudioData(data);
} else {
console.log("[ER] No decoder!");
}
}
function onComplete() {
if (self.decoder) {
self.decoder.onComplete();
} else {
console.log("[ER] No decoder!");
}
}

2
test/glue.js

@ -46,7 +46,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE
LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK. LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.
*********************************************************/ *********************************************************/
self.importScripts("prod.h265.wasm.js"); // self.importScripts("prod.h265.wasm.js");
var supportSharedBuffer = false; var supportSharedBuffer = false;
try { try {
supportSharedBuffer = !!new SharedArrayBuffer(0); supportSharedBuffer = !!new SharedArrayBuffer(0);

160
test/h265.js

@ -1,160 +0,0 @@
//webrtc datachannel send h265 jpeg
var h265DC;
var bWorking=false;
var h265data=null;
var h265datalen=0;
var packet=0;
var expectLength = 4;
// var bserialopen = false
function isString(str){
return (typeof str=='string')&&str.constructor==String;
}
// function reportData (len, seq, data) {
// var objData = {
// t: kFileData,
// s: start,
// e: end,
// d: data,
// q: seq
// };
// postMessage(objData, [objData.d]);
// };
function hexToStr(hex,encoding) {
var trimedStr = hex.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
if (len % 2 !== 0) {
alert("Illegal Format ASCII Code!");
return "";
}
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(curCharCode);
}
// encoding为空时默认为utf-8
var bytesView = new Uint8Array(resultStr);
var str = new TextDecoder(encoding).decode(bytesView);
return str;
}
function dump_hex(h265data,h265datalen){
// console.log(h265data.toString());
var str="0x"
for (var i = 0; i < h265datalen; i ++ ) {
var byte =h265data.slice(i,i+1)[0];
str+=byte.toString(16)
str+=" "
// console.log((h265datalen+i).toString(16)+" ");
}
console.log(str);
}
function appendBuffer (buffer1, buffer2) {
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(new Uint8Array(buffer1), 0);
tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
return tmp.buffer;
};
function reportStream(size){
}
function stopH265(){
if(h265DC!==null){
h265DC.close();
}
}
var receivet1=new Date().getTime();
var bRecH265=false;
function initH265DC(pc,player) {
console.log("initH265DC",Date());
h265DC = pc.createDataChannel("h265");
// var ctx = canvas.getContext("2d");
h265DC.onmessage = function (event) {
// console.log(bRecH265,":",event.data)
if(bRecH265){
if(isString(event.data)) {
if(event.data.indexOf("h265 end")!=-1){
bRecH265=false;
console.log(bRecH265,":",event.data)
if(h265datalen>0){
const t2 = new Date().getTime()-receivet1;
console.log("receive time:"+t2+" len:"+h265datalen);
var req = {
t: ksendPlayerVideoFrameReq,
l: h265datalen,
d: h265data
};
player.postMessage(req,[req.d]);
h265data=null;
h265datalen=0;
packet=0;
receivet1=new Date().getTime();
}
return;
}
}else{
if (h265data != null) {
h265data=appendBuffer(h265data,event.data);
} else if (event.data.byteLength < expectLength) {
h265data = event.data.slice(0);
} else {
h265data=event.data;
}
h265datalen+=event.data.byteLength;
packet++;
console.log("reveive: "+packet+": t len"+h265datalen)
return;
}
}
if(isString(event.data)) {
if(event.data.indexOf("h265 start")!=-1){
// console.log(event.data );
bRecH265=true;
packet=0;
return;
}
}
};
h265DC.onopen = function () {
console.log("h265 datachannel open");
// var req = {
// t: kInitPlayerReq,
// };
// player.postMessage(req);
bWorking = true;
};
h265DC.onclose = function () {
console.log("h265 datachannel close");
bWorking=false;
};
}
function handleUpdates(canvas, dc) {
setInterval(function () {
if (bWorking){
dc.send(JSON.stringify({ type: "h265" })); // frame update request
}
}, 500);
};

284
test/h265dc.js

@ -0,0 +1,284 @@
//webrtc datachannel send h265 jpeg
// var packetkv={
// key
// }
// func GetFrameTypeName(frametype uint16) (string, error) {
// switch frametype {
// case NALU_H265_VPS:
// return "H265_FRAME_VPS", nil
// case NALU_H265_SPS:
// return "H265_FRAME_SPS", nil
// case NALU_H265_PPS:
// return "H265_FRAME_PPS", nil
// case NALU_H265_SEI:
// return "H265_FRAME_SEI", nil
// case NALU_H265_IFRAME:
// return "H265_FRAME_I", nil
// case NALU_H265_PFRAME:
// return "H265_FRAME_P", nil
// default:
// return "", errors.New("frametype unsupport")
// }
// }
const START_STR="h265 start";
const FRAME_TYPE_STR="FrameType";
const PACKET_LEN_STR="Packetslen";
const PACKET_COUNT_STR="packets";
const PACKET_PTS="pts";
const PACKET_REM_STR="rem";
const KEY_FRAME_TYPE="H265_FRAME_I"
var frameType="";
var isKeyFrame=false;
var pts=0;
var h265DC;
// var h265DC=new Array();
// var h265DC2;
// var h265DC3;
// var h265DC4;
var bWorking=false;
var h265dataFrame=[];
var h265data;
// var h265data2=null;
// var h265data3=null;
// var h265data4=null;
var dataIndex=0;
var h265datalen=0;
var packet=0;
var expectLength = 4;
var bFindFirstKeyFrame=false;
//var packetLens=0;
// startstr := "h265 start ,FrameType:" + frametypestr + ",Packetslen:" + strconv.Itoa(glength) + ",packets:" + strconv.Itoa(count) + ",rem:" + strconv.Itoa(rem)
// var bserialopen = false
function isString(str){
return (typeof str=='string')&&str.constructor==String;
}
// function reportData (len, seq, data) {
// var objData = {
// t: kFileData,
// s: start,
// e: end,
// d: data,
// q: seq
// };
// postMessage(objData, [objData.d]);
// };
function hexToStr(hex,encoding) {
var trimedStr = hex.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
if (len % 2 !== 0) {
alert("Illegal Format ASCII Code!");
return "";
}
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(curCharCode);
}
// encoding为空时默认为utf-8
var bytesView = new Uint8Array(resultStr);
var str = new TextDecoder(encoding).decode(bytesView);
return str;
}
function deepCopy(arr) {
const newArr = []
for(let i in arr) {
console.log(arr[i])
if (typeof arr[i] === 'object') {
newArr[i] = deepCopy(arr[i])
} else {
newArr[i] = arr[i]
}
}
console.log(newArr)
return newArr
}
function dump_hex(h265data,h265datalen){
// console.log(h265data.toString());
var str="0x"
for (var i = 0; i < h265datalen; i ++ ) {
var byte =h265data.slice(i,i+1)[0];
str+=byte.toString(16)
str+=" "
// console.log((h265datalen+i).toString(16)+" ");
}
console.log(str);
}
function appendBuffer (buffer1, buffer2) {
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(new Uint8Array(buffer1), 0);
tmp.set(new Uint8Array(buffer2), buffer1.byteLength);
return tmp.buffer;
};
function reportStream(size){
}
function stopH265(){
if(h265DC!==null){
h265DC.close();
}
}
var receivet1=new Date().getTime();
var bRecH265=false;
function initH265DC(pc,player) {
console.log("initH265DC",Date());
h265DC = pc.createDataChannel("h265");
// var ctx = canvas.getContext("2d");
h265DC.onmessage = function (event) {
// console.log(bRecH265,":",event.data)
if(bRecH265){
if(isString(event.data)) {
console.log("reveive: "+event.data)
if(event.data.indexOf("h265 end")!=-1){
bRecH265=false;
// console.log("frame ok",":",event.data," len:"+h265datalen)
if(h265datalen>0){
// const framepacket=new Uint8Array(h265data)
const t2 = new Date().getTime()-receivet1;
/*
return "H265_FRAME_VPS", nil
case NALU_H265_SPS:
return "H265_FRAME_SPS", nil
case NALU_H265_PPS:
return "H265_FRAME_PPS", nil
case NALU_H265_SEI:
return "H265_FRAME_SEI", nil
case NALU_H265_IFRAME:
return "H265_FRAME_I", nil
case NALU_H265_PFRAME:
return "H265_FRAME_P", nil
*/
if(frameType==="H265_FRAME_VPS"||frameType==="H265_FRAME_SPS"||frameType==="H265_FRAME_PPS"||frameType==="H265_FRAME_SEI"||frameType==="H265_FRAME_P")
console.log("receive time:"+t2+" len:"+h265datalen);
if(frameType==="H265_FRAME_P"&&!bFindFirstKeyFrame){
return
}
bFindFirstKeyFrame=true;
// h265dataFrame.push(new Uint8Array(h265data))
var dataFrame=new Uint8Array(h265data)//deepCopy(h265data)//h265dataFrame.shift()
var data={
pts: pts,
size: h265datalen,
iskeyframe: isKeyFrame,
packet: dataFrame//
// new Uint8Array(h265data)//h265data//new Uint8Array(h265data)
};
var req = {
t: ksendPlayerVideoFrameReq,
l: h265datalen,
d: data
};
player.postMessage(req,[req.d.packet.buffer]);
h265data=null;
h265datalen=0;
packet=0;
receivet1=new Date().getTime();
}
return;
}
}else{
if (h265data != null) {
h265data=appendBuffer(h265data,event.data);
} else if (event.data.byteLength < expectLength) {
h265data = event.data.slice(0);
} else {
h265data=event.data;
}
h265datalen+=event.data.byteLength;
packet++;
console.log("packet: "+packet+": t len"+h265datalen)
return;
}
}
if(isString(event.data)) {
let startstring = event.data
// console.log("reveive: "+startstring)
if(startstring.indexOf("h265 start")!=-1){
console.log(event.data );
const startarray=startstring.split(",");
// startstr := "h265 start ,FrameType:" + frametypestr + ",Packetslen:" + strconv.Itoa(glength) + ",packets:" + strconv.Itoa(count) + ",rem:" + strconv.Itoa(rem)
for(let i=0;i<startarray.length;i++){
const parakv=startarray[i].split(":");
if(parakv!==null){
switch(parakv[0]){
case START_STR:
break;
case PACKET_PTS:
pts=parseInt(parakv[1])
break;
case FRAME_TYPE_STR:
frameType=parakv[1]
if(frameType.indexOf(KEY_FRAME_TYPE)!==-1){
isKeyFrame=true;
}else{
isKeyFrame=false;
}
break;
case PACKET_LEN_STR:
break;
case PACKET_COUNT_STR:
break;
case PACKET_REM_STR:
break;
}
}
}
// string.split(":")
bRecH265=true;
packet=0;
return;
}
}
};
h265DC.onopen = function () {
console.log("h265 datachannel open");
// var req = {
// t: kInitPlayerReq,
// };
// player.postMessage(req);
bWorking = true;
};
h265DC.onclose = function () {
console.log("h265 datachannel close");
bWorking=false;
};
}
function handleUpdates(canvas, dc) {
setInterval(function () {
if (bWorking){
dc.send(JSON.stringify({ type: "h265" })); // frame update request
}
}, 500);
};

BIN
test/libffmpeg_.wasm

Binary file not shown.

1
test/libffmpeg_265_js

File diff suppressed because one or more lines are too long

BIN
test/libffmpeg_265_wasm

Binary file not shown.

4
test/main.html

@ -8,6 +8,7 @@
<meta name="apple-touch-fullscreen" content="yes" /> <meta name="apple-touch-fullscreen" content="yes" />
<meta name="format-detection" content="telephone=no, email=no" /> <meta name="format-detection" content="telephone=no, email=no" />
<link rel="stylesheet" href="styles/style.css"> <link rel="stylesheet" href="styles/style.css">
<text> webrtc datachannel H265 Player Demo 2022</text>
</head> </head>
<body> <body>
<!-- <div style="margin: 20px;"> <!-- <div style="margin: 20px;">
@ -28,6 +29,7 @@
</div> --> </div> -->
<div class="row"> <div class="row">
<form action="demo_form.html" method="get"> <form action="demo_form.html" method="get">
服务器名称: <input type="text" name="servername" id="serverId" value="rtmpserver1"> 服务器名称: <input type="text" name="servername" id="serverId" value="rtmpserver1">
拉 流 名 称: <input type="text" name="streamname" id="streamId" value="kvs"> 拉 流 名 称: <input type="text" name="streamname" id="streamId" value="kvs">
<!-- 设 备 名 称: <input type="text" name="devicename" id="deviceId" value="0A:2A:BE:6C:03:2E"> --> <!-- 设 备 名 称: <input type="text" name="devicename" id="deviceId" value="0A:2A:BE:6C:03:2E"> -->
@ -65,7 +67,7 @@
<!-- <canvas id="playCanvas" width="852" height="480"></canvas> <!-- <canvas id="playCanvas" width="852" height="480"></canvas>
--> -->
<!-- <div style="margin-top: 10px"> --> <!-- <div style="margin-top: 10px"> -->
<canvas id="playCanvas" width="852" height="480"></canvas> <canvas id="playCanvas" width="1280" height="720"></canvas>
<!-- </div> --> <!-- </div> -->
</div> </div>
<div class="sideBar"> <div class="sideBar">

41
test/mqtt.js

@ -7,7 +7,20 @@ var t = Date.now();
function sleep(d){ function sleep(d){
while(Date.now - t <= d); while(Date.now - t <= d);
} }
var bisOntrack = false;
function OnTrack(pc){
if(bisOntrack) return;
bisOntrack=true;
pc.ontrack = function (event) {
console.log("ontrack", event.track.kind)
var el = document.createElement(event.track.kind);
el.srcObject = event.streams[0];
el.autoplay = true;
// document.getElementById("remote-video").appendChild(el);
el.controls = false; // 显示
// el.autoplay = true;
}
}
function getStreamWebrtc(player) { function getStreamWebrtc(player) {
@ -15,9 +28,30 @@ function getStreamWebrtc(player) {
iceServers: ICEServerkvm,//ICEServer iceServers: ICEServerkvm,//ICEServer
}); });
// initH265Transfer(pc,player); // initH265Transfer(pc,player);
initH265DC(pc,player); if(bVideo) {
if(!bDecodeH264){
initH265DC(pc,player);
}else{
const { receivervideo } = pc.addTransceiver('video', { direction: 'recvonly' });
OnTrack(pc)
}
}
if(bAudio) {
// initAudioDC(pc);
const { receiveraudio } = pc.addTransceiver('audio', { direction: 'recvonly' });
OnTrack(pc)
}
// Populate SDP field when finished gathering // Populate SDP field when finished gathering
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState) pc.oniceconnectionstatechange = e => {
log(pc.iceConnectionState)
var state ={
t: kconnectStatusResponse,
s: pc.connectionState
}
player.postMessage(state)
}
pc.onicecandidate = event => { pc.onicecandidate = event => {
if (event.candidate === null) { if (event.candidate === null) {
@ -41,6 +75,7 @@ function getStreamWebrtc(player) {
} }
if (bAudio) { if (bAudio) {
msgdata["audio"] = true; msgdata["audio"] = true;
msgdata["mode"] = media_mode;
} }
msgdata["serial"] = false;//true; msgdata["serial"] = false;//true;

3
test/parameter.js

@ -43,7 +43,8 @@ function uuid() {
var subtopic = "server_cmd/" +SERVER_NAME+ "/"+ WEB_SEQID + "/#";//+"/"+deviceID //Control/00:13:14:01:D9:D5 var subtopic = "server_cmd/" +SERVER_NAME+ "/"+ WEB_SEQID + "/#";//+"/"+deviceID //Control/00:13:14:01:D9:D5
var pubtopic = "server_control" + "/" + SERVER_NAME; var pubtopic = "server_control" + "/" + SERVER_NAME;
let bVideo=true; let bVideo=true;
let bAudio=false; let bAudio=true;
let bDecodeH264 = false; //H264直接用webrtc
var bmqttStarted=false; var bmqttStarted=false;
var bWebrtc = false; var bWebrtc = false;
var bUseWebrtcP2P =true;//启动webrtc p2p 模式 var bUseWebrtcP2P =true;//启动webrtc p2p 模式

1
test/prod.h265.asm.combine.js

File diff suppressed because one or more lines are too long

1
test/prod.h265.wasm.combine.js

File diff suppressed because one or more lines are too long

3474
test/prod.h265.wasm.js

File diff suppressed because one or more lines are too long

484
test/prod_decoder.js

@ -1,484 +0,0 @@
// var isWorker = typeof importScripts == "function";
// var bridgeName = "__CODE_BRIDGE__" + +new Date();
// self.Module = {
// onRuntimeInitialized: function () {
// onWasmLoaded();
// },
// // onVideoDataSize: function () {
// // onVideoDataSize();
// // },
// // onVideoData: function () {
// // onVideoData();
// // },
// // onAudioDataSize: function () {
// // onAudioDataSize();
// // },
// // onAudioData: function () {
// // onAudioData();
// // },
// // };
// // var isWorker = typeof importScripts == "function";
// // var bridgeName = "__CODE_BRIDGE__" + +new Date();
// // [bridgeName] = {
// onHeader: function(header) {
// //Module.postMessage({ type: "header", data: header });
// },
// onMediaInfo: function(mediaInfo) {
// console.log("onMediaInfo"+mediaInfo.toString(16));
// //Module.postMessage({ type: "mediaInfo", data: mediaInfo });
// },
// onAudioDataSize: function(data) {
// // Module.audioBufferSize = data.size;
// // Module.audioBuffer = Module._malloc(Module.audioBufferSize);
// // Module._codecSetAudioBuffer(Module.audioBuffer);
// },
// onAudioData: function(data) {
// // var timestamp = data.timestamp;
// // Module.audioTimestamps.push(timestamp);
// // var u8s = Module.HEAPU8.subarray(
// // Module.audioBuffer,
// // Module.audioBuffer + Module.audioBufferSize
// // );
// // var output = null;
// // if (supportSharedBuffer) {
// // output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
// // output.set(u8s);
// // } else {
// // output = new Uint8Array(u8s);
// // }
// // Module._free(Module.audioBuffer);
// // Module.audioBuffer = null;
// // Module.postMessage(
// // {
// // type: "audio",
// // data: {
// // buffer: output.buffer,
// // timestamp: timestamp
// // }
// // },
// // supportSharedBuffer ? undefined : [output.buffer]
// // );
// },
// onVideoDataSize: function(data) {
// console.log("onVideoDataSize"+data.toString(16));
// // if (Module.videoBuffer == null) {
// // Module.videoBufferSize = data.size;
// // Module.videoBuffer = Module._malloc(Module.videoBufferSize);
// // if (supportSharedBuffer) {
// // Module.videoSharedBuffer = new SharedArrayBuffer(data.size);
// // }
// // }
// // Module._codecSetVideoBuffer(Module.videoBuffer);
// },
// onVideoData: function(data) {
// console.log("onVideoData"+data.toString(16));
// // var timestamp = data.timestamp;
// // Module.videoTimestamps.push(timestamp);
// // var u8s = Module.HEAPU8.subarray(
// // Module.videoBuffer,
// // Module.videoBuffer + Module.videoBufferSize
// // );
// // var output = null;
// // if (supportSharedBuffer) {
// // output = new Uint8Array(Module.videoSharedBuffer);
// // output.set(u8s);
// // } else {
// // output = new Uint8Array(u8s);
// // }
// // Module.postMessage(
// // {
// // type: "video",
// // data: {
// // buffer: output.buffer,
// // timestamp: timestamp,
// // width: data.width,
// // height: data.height,
// // stride0: data.stride0,
// // stride1: data.stride1
// // }
// // },
// // supportSharedBuffer ? undefined : [output.buffer]
// // );
// },
// onComplete: function() {
// console.log("onComplete");
// // Module.postMessage({ type: "complete" });
// }
// };
var Module = {};
self.importScripts("common.js");
self.importScripts("glue.js");
self.importScripts("prod.h265.wasm.js");
// var decoder_type = DECODER_H265;
var ptsIdx=0;
H265Frame =[];
function Decoder(){
// this.timer=null;
this.decodeTimer = null;
this.rawParserObj = null;
this.wasmLoaded = false;
this.tmpReqQue = [];
this.destroied = false;
// this.poddecoder = null;
// this.supportSharedBuffer = false;
// this.bridgeName = "__CODE_BRIDGE__" + +new Date();
// this.audioTimestamps = []
// this.videoTimestamps = []
// this.audioBufferSize = 0
// this.videoBufferSize = 0
// this.audioBuffer = null
// this.videoBuffer = null
// this.videoSharedBuffer =null;
// this.token = "base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1";
// this.version = '100.2.0';
}
Decoder.prototype.cacheReq = function (req) {
if (req) {
this.tmpReqQue.push(req);
}
};
Decoder.prototype.onWasmLoaded = function () {
console.log("Wasm loaded.");
this.wasmLoaded = true;
while (this.tmpReqQue.length > 0) {
var req = this.tmpReqQue.shift();
this.processReq(req);
}
}
Decoder.prototype.initDecoder = function () {
// var ret = Module._initDecoder(fileSize, this.coreLogLevel);
var ret=0;
console.log("initDecoder return " + ret + ".");
// try {
// this.supportSharedBuffer = !!new SharedArrayBuffer(0);
// } catch (e) {
// // nothing to do...
// }
// // this.bridgeName = "__CODE_BRIDGE__" + +new Date();
// Module._codecInit();
// var callbackStr = bridgeName.split("");
// callbackStr = callbackStr
// .map(function(v) {
// return v.charCodeAt(0);
// })
// .concat(0);
// var callbackStrData = Module._malloc(callbackStr.length - 1);
// Module.HEAPU8.set(callbackStr, callbackStrData);
// Module._codecSetBridgeName(callbackStrData);
var objData = {
t: kInitDecoderRsp,
e: ret
};
self.postMessage(objData);
};
Decoder.prototype.openDecoder = function () {
var objData = {
t: kOpenDecoderRsp,
e: 0
};
self.postMessage(objData);
}
Decoder.prototype.uninitDecoder = function () {
var ret = 0;//Module._uninitDecoder();
// Module._codecFree();
console.log("Uninit ffmpeg decoder return " + ret + ".");
};
// Decoder.prototype.onHeader = function(header) {
// // Module.postMessage({ type: "header", data: header });
// };
// Decoder.prototype.onMediaInfo = function(mediaInfo) {
// // Module.postMessage({ type: "mediaInfo", data: mediaInfo });
// };
// Decoder.prototype.onAudioDataSize = function(data) {
// this.audioBufferSize = data.size;
// this.audioBuffer = Module._malloc(this.audioBufferSize);
// Module._codecSetAudioBuffer(this.audioBuffer);
// };
// Decoder.prototype.onAudioData = function(data) {
// var timestamp = data.timestamp;
// this.audioTimestamps.push(timestamp);
// var u8s = Module.HEAPU8.subarray(
// this.audioBuffer,
// this.audioBuffer +this.audioBufferSize
// );
// var output = null;
// if (supportSharedBuffer) {
// output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
// output.set(u8s);
// } else {
// output = new Uint8Array(u8s);
// }
// Module._free(this.audioBuffer);
// this.audioBuffer = null;
// // Module.postMessage(
// // {
// // type: "audio",
// // data: {
// // buffer: output.buffer,
// // timestamp: timestamp
// // }
// // },
// // supportSharedBuffer ? undefined : [output.buffer]
// // );
// };
// Decoder.prototype.onVideoDataSize = function(data){
// if (this.videoBuffer == null) {
// this.videoBufferSize = data.size;
// this.videoBuffer = Module._malloc(this.videoBufferSize);
// if (this.supportSharedBuffer) {
// this.videoSharedBuffer = new SharedArrayBuffer(data.size);
// }
// }
// Module._codecSetVideoBuffer(this.videoBuffer);
// }
// Decoder.prototype.onVideoData = function(data) {
// var timestamp = data.timestamp;
// this.videoTimestamps.push(timestamp);
// var u8s = Module.HEAPU8.subarray(
// this.videoBuffer,
// this.videoBuffer + this.videoBufferSize
// );
// var output = null;
// if (supportSharedBuffer) {
// output = new Uint8Array(this.videoSharedBuffer);
// output.set(u8s);
// } else {
// output = new Uint8Array(u8s);
// }
// // Module.postMessage(
// // {
// // type: "video",
// // data: {
// // buffer: output.buffer,
// // timestamp: timestamp,
// // width: data.width,
// // height: data.height,
// // stride0: data.stride0,
// // stride1: data.stride1
// // }
// // },
// // supportSharedBuffer ? undefined : [output.buffer]
// // );
// var obj = {
// data: output,
// width: data.width,
// height: data.height,
// }
// var objData = {
// t: kprodVideoFrame,
// s: timestamp,
// stride0: data.stride0,
// stride1: data.stride1,
// d: obj
// };
// self.postMessage(objData, [objData.d.data.buffer]);
// };
// Decoder.prototype.onComplete=function() {
// // Module.postMessage({ type: "complete" });
// }
var decodet1=new Date().getTime();
Decoder.prototype.decodeVideo=function(){
if(H265Frame.length>0){
decodet1=new Date().getTime();
var typedArray= H265Frame.shift();//H265Frame[0];//new Uint8Array(H265Frame[0]);
h265decode(typedArray);
// if(Module){
// Module.postMessage({
// type: 'decode',
// buffer: typedArray,
// });
// }
// var size = typedArray.length
// var cacheBuffer = Module._malloc(size);
// Module.HEAPU8.set(typedArray, cacheBuffer);
// this.audioTimestamps = [];
// this.videoTimestamps = [];
// Module._codecDecode(cacheBuffer, size);
// this.decode(typedArray)
// if (cacheBuffer != null) {
// Module._free(cacheBuffer);
// cacheBuffer = null;
// }
}
}
// Decoder.prototype.decodeVideo = function(){ // 对外api,解码一段数据
// }
Decoder.prototype.decode = function(buffer){ // 对外api,解码一段数据
h265decode(buffer);
// if(Module){
// // Module.postMessage({
// // type: 'decode',
// // buffer: buffer,
// // });
// }
}
Decoder.prototype.destroy = function(){ // 对外api,销毁解码器
this.destroied = true;
if(Module){
// window.URL.revokeObjectURL(this.url);
Module.postMessage({type: 'destroy'});
}
}
Decoder.prototype.startDecoding = function (interval) {
console.log("Start decoding.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
}
this.decodeTimer = setInterval(this.decodeVideo, 0);//interval);
};
Decoder.prototype.pauseDecoding = function () {
console.log("Pause decoding.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
this.decodeTimer = null;
}
};
Decoder.prototype.sendVideoFrame = function(data,len){
var typedArray = new Uint8Array(data);
if(H265Frame.length>MAX_FRAME_SIZE){
H265Frame.shift();
}
H265Frame.push(typedArray)
}
Decoder.prototype.closeDecoder = function () {
console.log("closeDecoder.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
this.decodeTimer = null;
console.log("Decode timer stopped.");
}
// var ret = Module._closeDecoder();
console.log("Close ffmpeg decoder return " + ret + ".");
var objData = {
t: kCloseDecoderRsp,
e: 0
};
self.postMessage(objData);
};
Decoder.prototype.processReq = function (req) {
// console.log("processReq " + req.t + ".");
switch (req.t) {
case kInitDecoderReq:
this.initDecoder();
break;
case kUninitDecoderReq:
this.uninitDecoder();
break;
case kOpenDecoderReq:
this.openDecoder();
break;
case kCloseDecoderReq:
this.closeDecoder();
break;
case kStartDecodingReq:
this.startDecoding(req.i);
break;
case kPauseDecodingReq:
this.pauseDecoding();
break;
case kFeedDataReq:
this.sendVideoFrame(req.d);
break;
// case kSeekToReq:
// this.seekTo(req.ms);
// break;
default:
this.logger.logError("Unsupport messsage " + req.t);
}
};
self.decoder = new Decoder;
self.onmessage = function (evt) {
if (!self.decoder) {
console.log("[ER] Decoder not initialized!");
return;
}
var req = evt.data;
if (!self.decoder.wasmLoaded) {
self.decoder.cacheReq(req);
console.log("Temp cache req " + req.t + ".");
return;
}
self.decoder.processReq(req);
};
function onWasmLoaded() {
if (self.decoder) {
self.decoder.onWasmLoaded();
} else {
console.log("[ER] No decoder!");
}
}
// function onVideoDataSize() {
// if (self.decoder) {
// self.decoder.onVideoDataSize();
// } else {
// console.log("[ER] No decoder!");
// }
// }
// function onVideoData() {
// if (self.decoder) {
// self.decoder.onVideoData();
// } else {
// console.log("[ER] No decoder!");
// }
// }
// function onAudioDataSize() {
// if (self.decoder) {
// self.decoder.onAudioDataSize();
// } else {
// console.log("[ER] No decoder!");
// }
// }
// function onAudioData() {
// if (self.decoder) {
// self.decoder.onAudioData();
// } else {
// console.log("[ER] No decoder!");
// }
// }

3
test/start.js

@ -13,7 +13,8 @@ importScripts("./video.js")
importScripts("./audio.js") importScripts("./audio.js")
importScripts("./webgl.js") importScripts("./webgl.js")
importScripts("./datachannel.js") importScripts("./datachannel.js")
importScripts("./h265.js") importScripts("./audiodc.js")
importScripts("./h265dc.js")
importScripts("https://cdn.bootcdn.net/ajax/libs/mqtt/2.18.8/mqtt.min.js") importScripts("https://cdn.bootcdn.net/ajax/libs/mqtt/2.18.8/mqtt.min.js")
// importScripts("./adapter-latest.js") // importScripts("./adapter-latest.js")

38
test/video.js

@ -6,7 +6,17 @@ var player=null;
function handleVideo() { function handleVideo() {
player = new Worker("Player.js"); player = new Worker("Player.js");
// H265transferworker = new Worker ("") // H265transferworker = new Worker ("")
var el = document.getElementById("btnPlayVideo");
// var currentState = self.player.getState();
// if (currentState == playerStatePlaying) {
// el.src = "img/play.png";
// } else {
// el.src = "img/pause.png";
// }
// if(bAudio){
// setAudioDecoder(1) //mse 0 contex
// playAudio();
// }
startDeviceSession(player); startDeviceSession(player);
player.onmessage = function (evt){ player.onmessage = function (evt){
var objData = evt.data; var objData = evt.data;
@ -18,6 +28,9 @@ function handleVideo() {
webgldisplayVideoFrame(objData.d); webgldisplayVideoFrame(objData.d);
} }
break; break;
case kplaterNetStatus:
netstatus(objData.s)
break;
default: default:
break; break;
} }
@ -27,8 +40,14 @@ function handleVideo() {
decoder_type: DECODER_TYPE decoder_type: DECODER_TYPE
}; };
player.postMessage(req); player.postMessage(req);
el.src = "img/pause.png";
} }
function netstatus(status){
if(status==="disconnected"){
stopVideo();
}
}
function stopDecoder(){ function stopDecoder(){
var req = { var req = {
t: kendPlayerCoderReq, t: kendPlayerCoderReq,
@ -39,6 +58,23 @@ function stopVideo(){
stopDecoder(); stopDecoder();
endWebrtc(); endWebrtc();
endMqtt(); endMqtt();
var el = document.getElementById("btnPlayVideo");
// var currentState = self.player.getState();
// if (currentState == playerStatePlaying) {
el.src = "img/play.png";
// } else {
// el.src = "img/pause.png";
}
function fullscreen(){
if(!webglPlayer) {
const canvasId = "playCanvas";
canvas = document.getElementById(canvasId);
webglPlayer = new WebGLPlayer(canvas, {
preserveDrawingBuffer: false
});
}
webglPlayer.fullscreen();
} }
//用missle解码器 //用missle解码器
// var USE_MISSILE = false; // var USE_MISSILE = false;

1
test/videodec_simd_noems6_.js

File diff suppressed because one or more lines are too long

BIN
test/videodec_simd_noems6_.wasm

Binary file not shown.

5639
test/videodec_simd_noems6_h265.js

File diff suppressed because it is too large

BIN
test/videodec_simd_noems6_h265.wasm

Binary file not shown.

6214
test/videodec_wx_h265.js

File diff suppressed because it is too large

BIN
test/videodec_wx_h265.wasm

Binary file not shown.

1
web_decoder_simple

@ -0,0 +1 @@
Subproject commit 8fe88abb0c9087d05bd15f06c07b6b9f2b3a376e
Loading…
Cancel
Save