
importScripts('./jsFFMPEG.js');
let initDecoder = null;
let decoderContext = null;
let decodeByFFMPEG = null;
let getWidth = null;
let getHeight = null;
let closeContext = null;
let context = null;
let outpic = null;
let outpicptr = null;
let ID = 264;
let initialized = false;
let firstIFrame = true;

class H264Decoder {
    constructor() {



       //Module.onRuntimeInitialized = () => {
            console.log('h264 decoder init')

            initDecoder = Module.cwrap('init_jsFFmpeg', 'void', []);
            decoderContext = Module.cwrap('context_jsFFmpeg', 'number', ['number']);
            decodeByFFMPEG = Module.cwrap('decode_video_jsFFmpeg', 'number', ['number', 'array', 'number', 'number']);
            getWidth = Module.cwrap('get_width', 'number', ['number']);
            getHeight = Module.cwrap('get_height', 'number', ['number']);
            closeContext = Module.cwrap('close_jsFFmpeg', 'number', ['number']);
        initDecoder();
            this.init();
            initialized = true;
        //};
    }
    init() {
        if (context !== null) {
            closeContext(context);
            context = null;
        }
        context = decoderContext(ID);
    }

    setOutputSize(size) {
        console.log("H264 Decoder setOutputSize");
        let outpicsize = size * 1.5;
        outpicptr = Module._malloc(outpicsize);
        outpic = new Uint8Array(Module.HEAPU8.buffer, outpicptr, outpicsize);
    }

    decode(data) {
        if(!initialized) {
            console.log('未初始化完成')
            return null;
        }
        console.log(data.subarray(0, 100))
        let frameType = ((data[4] & 0x1f) === 7 || (data[4] & 0x1f) === 5) ? 'I' : 'P';
    //console.log(data[4] & 0x1f)
        if(frameType === 'I' && initialized) {
            firstIFrame = true;
        }
        if(!firstIFrame) {
            console.log('非 firstIFrame')
            return null;
        }
        let beforeDecoding = null;
        let decodingTime = null;
        let frameData = null;
        let bufferIdx = null;
        var dataHeap = null;

        beforeDecoding = Date.now();

        decodeByFFMPEG(context, data, data.length, outpic.byteOffset);
        decodingTime = Date.now() - beforeDecoding;



        let width = getWidth(context);
        let height = getHeight(context);

        console.log(width, height)
        if (width > 0 && height > 0) {
            let copyOutput = new Uint8Array(outpic);

            frameData = {
                'data': copyOutput,
                'bufferIdx': bufferIdx,
                'width': width,
                'height': height,
                'codecType': 'h264',
                'decodingTime': decodingTime,
                'frameType': frameType,
            };
            console.log(frameData)

            return frameData;
        }

        // if(decodeby) {
        //     //avcodec_decode_video2(context, outpicptr, size, data);
        //     //console.log(Module.HEAP8.subarray(outpicptr, outpicptr+20))
        //
        //     //
        //     var memoryData = Module._malloc(data.byteLength);
        //     Module.HEAPU8.set(data, memoryData);
        //     var ptr = Module._video_decode_frame(video_decoder_ctx, memoryData, data.byteLength);
        //     Module._free(memoryData);
        //     if(ptr === 0) {
        //         console.error("[ERROR] no Frame Data!");
        //         return null;
        //     }else {
        //     }
        // }else {
        //     try {
        //         //outpic = Module.HEAPU8.length - data.length - 1000;
        //         Module.HEAPU8.set(data, outpic);
        //         console.log(data.length, data.subarray(0, 30), outpic,  Module.HEAPU8.subarray(outpic))
        //         //let result = avcodec_decode_video2(context, outpic, size/8, data);
        //         console.log(h264_decode_frame(context, data, data.length, outpic));
        //         //dataHeap = new Uint8Array(Module.HEAPU8.buffer, outpic, size);
        //         //dataHeap.set(data);
        //         //outpic.set(data);
        //         //console.log(data.length, data.subarray(0, 30), outpic.byteOffset, outpic.subarray(0, 30), Module.HEAPU8.subarray(outpic.byteOffset))
        //         //let result = avcodec_decode_video2(context, outpic.byteOffset, 0, data);
        //         //console.log('result: ', result)
        //     } catch (e) {
        //         console.log(e)
        //     }
        //
        // }


        // if (!Constructor.prototype.isFirstFrame()) {
        //     Constructor.prototype.setIsFirstFrame(true);
        //     frameData = {
        //         'firstFrame': true,
        //     };
        //     return frameData;
        // }
        // draw picture in canvas.
        //console.log(outpic)

        //console.log(width, height)
        // if (width > 0 && height > 0) {
        let copyOutput;
        // if(decodeby) {
        //     var width = Module.HEAPU32[ptr / 4],
        //         height = Module.HEAPU32[ptr / 4 + 1],
        //         YimgBufferPtr = Module.HEAPU32[ptr / 4 + 2],
        //         UimgBufferPtr = Module.HEAPU32[ptr / 4 + 3],
        //         VimgBufferPtr = Module.HEAPU32[ptr / 4 + 4],
        //         YimageBuffer = Module.HEAPU8.subarray(YimgBufferPtr, YimgBufferPtr + width * height),
        //         UimageBuffer = Module.HEAPU8.subarray(UimgBufferPtr, UimgBufferPtr + width * height / 4),
        //         VimageBuffer = Module.HEAPU8.subarray(VimgBufferPtr, VimgBufferPtr + width * height / 4);
        //
        //     var ydata = new Uint8Array(YimageBuffer);
        //     var udata = new Uint8Array(UimageBuffer);
        //     var vdata = new Uint8Array(VimageBuffer);
        //
        //     frameData = {
        //         'bufferIdx': bufferIdx,
        //         'width': width,
        //         'height': height,
        //         'codecType': 'h264',
        //         'decodingTime': decodingTime,
        //         'frameType': frameType,
        //         YData:ydata.buffer,
        //         UData:udata.buffer,
        //         VData:vdata.buffer,
        //     };
        //
        //     return frameData;
        // } else {
        //     //console.log(outpic)
        //     copyOutput = new Uint8Array(Module.HEAPU8.buffer, outpic, data.size);
        //     //console.log(outpic)
        //
        // }
    }
}
