UNPKG

@osh-branches/osh-js

Version:
136 lines (117 loc) 5.19 kB
import Module from './ffmpeg-h264.js'; let instance = { ready: new Promise(resolve => { Module({ onRuntimeInitialized() { instance = Object.assign(this, { ready: Promise.resolve() }); resolve(); } }); }) }; instance.ready .then(_ => { // register all compiled codecs instance._avcodec_register_all(); init('mp3'); self.codec = null; let released = false; self.onmessage = function (e) { if(released) { return; } if(e.data.message && e.data.message === 'release') { release(); released = true; } if(e.data.codec !== self.codec) { init(e.data.codec); } const data = e.data; const decodedFrame = innerWorkerDecode(data.pktSize, new Uint8Array(data.pktData, data.byteOffset, data.pktSize), data.timeStamp, data.roll); if (typeof decodedFrame != "undefined") { decodedFrame.roll = data.roll; self.postMessage(decodedFrame, [ decodedFrame.frameYData.buffer, decodedFrame.frameUData.buffer, decodedFrame.frameVData.buffer, data.pktData, ]); } }; self.onerror = (e) => { console.log('closing worker'); } function init(codec) { self.codec = codec; // find wav decoder var codec = instance.ccall('avcodec_find_decoder_by_name', 'number', ['string'], [codec]); if (codec == 0) { console.error("Could not find "+codec+" codec"); } // init codec and conversion context self.av_ctx = instance._avcodec_alloc_context3(codec); // var defaultChannelLayoutValue = instance._av_get_default_channel_layout(2); // instance.setValue(codec + 38, defaultChannelLayoutValue, 'i32'); // open codec var ret = instance._avcodec_open2(self.av_ctx, codec, 0); if (ret < 0) { console.error("Could not initialize codec"); } // allocate packet self.av_pkt = instance._malloc(96); self.av_pktData = instance._malloc(1024 * 3000); instance._av_init_packet(self.av_pkt); instance.setValue(self.av_pkt + 24, self.av_pktData, '*'); // allocate video frame self.av_frame = instance._av_frame_alloc(); if (!self.av_frame) alert("Could not allocate video frame"); // init decode frame function self.got_frame = instance._malloc(4); } function release() { instance._avcodec_close(self.av_ctx); instance._av_free(self.av_ctx); // instance._av_frame_free(self.av_frame); } function innerWorkerDecode(pktSize, pktData, timeStamp, roll) { // prepare packet instance.setValue(self.av_pkt + 28, pktSize, 'i32'); instance.writeArrayToMemory(pktData, self.av_pktData); // decode next frame var len = instance._avcodec_decode_video2(self.av_ctx, self.av_frame, self.got_frame, self.av_pkt); if (len < 0) { console.log("Error while decoding frame"); return; } let type = instance.getValue(self.got_frame, 'i8'); if (type === 0) { // console.log("No frame"); return; } var decoded_frame = self.av_frame; var frame_width = instance.getValue(decoded_frame + 68, 'i32'); var frame_height = instance.getValue(decoded_frame + 72, 'i32'); //console.log("Decoded Frame, W=" + frame_width + ", H=" + frame_height); // copy Y channel to canvas var frameYDataPtr = instance.getValue(decoded_frame, '*'); var frameUDataPtr = instance.getValue(decoded_frame + 4, '*'); var frameVDataPtr = instance.getValue(decoded_frame + 8, '*'); return { frame_width: frame_width, frame_height: frame_height, frameYDataPtr: frameYDataPtr, frameUDataPtr: frameUDataPtr, frameVDataPtr: frameVDataPtr, frameYData: new Uint8Array(instance.HEAPU8.buffer.slice(frameYDataPtr, frameYDataPtr + frame_width * frame_height)), frameUData: new Uint8Array(instance.HEAPU8.buffer.slice(frameUDataPtr, frameUDataPtr + frame_width / 2 * frame_height / 2)), frameVData: new Uint8Array(instance.HEAPU8.buffer.slice(frameVDataPtr, frameVDataPtr + frame_width / 2 * frame_height / 2)), timeStamp:timeStamp, pktSize:pktSize }; } });