Javascript和C++之间的结构体对象传递

1.c++层接口:Decoder.cpp

// Decoder.cpp : Defines the exported functions for the DLL application.
//编译命令:
//emcc -O3 --bind -o ParseLib.bc ParseLib.cpp
//emcc -O3 --bind -o GetH264FromPS.bc GetH264FromPS.cpp
//emcc -O3 --bind -o H264Decode.bc H264Decode.cpp
//emcc --bind ParseLib.bc GetH264FromPS.bc H264Decode.bc libavcodec.bc libavutil.bc -O3
// -s WASM=1 -s EXPORTED_FUNCTIONS=" //['_Init','_PsToYUV','_InputData','_GetOneFrame','_GetBuffer','_UnInit']" -s //TOTAL_MEMORY=128*1024*1024 -s ALLOW_MEMORY_GROWTH=0 -o decode.js


#include "GetH264FromPS.h"

#include <emscripten/bind.h>
#define BUFFER_SIZE 1280*720*2 
#define FRAME_IS_NULL -1
using namespace emscripten;



struct FRAME_INFO
{
	int dWidth;
	int dHeight;
        //int Linesize_Fir;
	//int Linesize_Sec;
        //int Linesize_Thi;
};

FRAME_INFO g_stFrameInfo = {0};

unsigned char* g_Buffer = NULL;


FRAME_INFO GetFrameInfo()
{
	return g_stFrameInfo;
}



#ifdef __cplusplus
extern "C" {
#endif

GetH264FromPS* mGetH264;
int Init(int iBufferSize) {

	mGetH264 = new GetH264FromPS();
	g_Buffer = new unsigned char[BUFFER_SIZE];
	return mGetH264->Init(iBufferSize);
	
};

int PsToYUV() {
	return mGetH264->GetH246FromPs();
};

int InputData(unsigned char* pBuffe, int iLength) {

	return mGetH264->InputData(pBuffe, iLength);

};

int GetOneFrame(){
	AVFrame* frame = mGetH264->GetOneBuffer(); 
        if(frame==NULL){
	    return FRAME_IS_NULL;
        }
	memset(g_Buffer,0,BUFFER_SIZE);
	
	unsigned char **pBuf = frame->data;//指向像素保存的地址  
	int *pStride = frame->linesize;//位宽  
        unsigned char* tempBuffer = g_Buffer;
	for (int color_idx = 0; color_idx < 3; color_idx++)
	{
		int nWidth = color_idx == 0 ? frame->width : frame->width / 2;
		int nHeight = color_idx == 0 ? frame->height : frame->height / 2;
		for (int idx = 0; idx < nHeight; idx++)
		{
			memcpy(tempBuffer,pBuf[color_idx],nWidth);
			tempBuffer += nWidth;
			pBuf[color_idx] += pStride[color_idx];
			
		}
		//fflush(pFout);
	}
	
        //g_Buffer = *(frame->data);
        //g_FrameInfo.FrameType=frame->
        g_stFrameInfo.dWidth =frame->width;
        g_stFrameInfo.dHeight = frame->height;
        //g_stFrameInfo.Linesize_Fir = frame->linesize[0];
        //g_stFrameInfo.Linesize_Sec = frame->linesize[1];
        //g_stFrameInfo.Linesize_Thi = frame->linesize[2];
        return 0;
};
unsigned char* GetBuffer(){

        return g_Buffer;
};

int UnInit(){
	if(g_Buffer)
	  delete[] g_Buffer;
	g_Buffer = NULL;

        if(mGetH264)
          delete mGetH264;
        mGetH264 = NULL;
        return 0;
};

#ifdef __cplusplus
}
#endif


EMSCRIPTEN_BINDINGS(my_object)
{

	value_object<FRAME_INFO>("FRAME_INFO")
		.field("width", &FRAME_INFO::dWidth)
		.field("height", &FRAME_INFO::dHeight);
        	//.field("linesize_fir", &FRAME_INFO::Linesize_Fir)
        	//.field("linesize_sec", &FRAME_INFO::Linesize_Sec)
        	//.field("linesize_thi", &FRAME_INFO::Linesize_Thi)
        	//;


	emscripten::function("_GetFrameInfo", &GetFrameInfo);

}

2.JS层的接口:worker.js

importScripts('decode.js');//它是以阻塞方法加载js的,只有所有文件加载完成之后,接下来的脚本才能继续执行
console.log('decode.js');
Module.preRun.push(function() {
	console.log('postRun');
	var iInit_re = Module._Init(1024*1024*2);
    console.log("nihao"+iInit_re);
});	
const FRAME_IS_NULL = -1;
const DECODE_FINISHED = 4;
//var iInit_re = Module._Init(1024*1024*2);

onmessage=function(event){

	var data = event.data;
	
	if(data.type === "decode_first")
	{
		var iRe = -1;
		var iLen = data.len;
		var pBuffer = Module._malloc(iLen)//分配堆内存
		var Data = Module.HEAPU8.subarray(pBuffer, pBuffer + iLen);//绑定到视图对象
		Data.set(new Uint8Array(data.buf));//数据写入到emscripten分配的内存中去
		
		while(iRe){
			iRe = Module._InputData(pBuffer,iLen);
			console.log("input data result="+iRe);
			var res = Module._PsToYUV();
			console.log("_PsToYUV result="+res);
			var result = Module._GetOneFrame();
			console.log("getoneframe result="+result);
			if(result === FRAME_IS_NULL){
				continue;
			}
			else{
				var sFramInfo = Module._GetFrameInfo();
				var iWidth = sFramInfo.width;
				var iHeight = sFramInfo.height;
				//var iLine_Fir = sFramInfo.linesize_fir;
				//var iLine_Sec = sFramInfo.linesize_sec;
				//var iLine_Thi = sFramInfo.linesize_thi;
				
				var iyuv_size = iWidth*iHeight*3/2;
				var pYUV = Module._GetBuffer();
				var buf = new ArrayBuffer(iyuv_size);//通过二进制对象分配一块连续内存
				var ayuv_data = new Uint8Array(buf);//二进制对象绑定到视图,通过视图对内存进行读写操作
				ayuv_data.set(Module.HEAPU8.subarray(pYUV,pYUV+iyuv_size));//c中的内存拷贝到刚分配的js内存中
				postMessage({type:"video",buf:ayuv_data.buffer,len:ayuv_data.length,width:iWidth,height:iHeight},[ayuv_data.buffer]);
			}	
		}
		Module._free(pBuffer);
	}
	else if(data.type === "decode_second")
	{
		do{//解码缓存中剩余的数据
			iRe = Module._PsToYUV();
			var result = Module._GetOneFrame();
			if(result === FRAME_IS_NULL){
				continue;
			}
			else{
				var sFramInfo = Module._GetFrameInfo();
				var iWidth = sFramInfo.width;
				var iHeight = sFramInfo.height;
				//var iLine_Fir = sFramInfo.linesize_fir;
				//var iLine_Sec = sFramInfo.linesize_sec;
				//var iLine_Thi = sFramInfo.linesize_thi;
				
				var iyuv_size = iWidth*iHeight*3/2;
				var pYUV = Module._GetBuffer();
				var buf = new ArrayBuffer(iyuv_size);
				var ayuv_data = new Uint8Array(buf);
				ayuv_data.set(Module.HEAPU8.subarray(pYUV,pYUV+iyuv_size));
				postMessage({type:"video",buf:ayuv_data.buffer,len:ayuv_data.length,width:iWidth,height:iHeight},[ayuv_data.buffer]);
			}		
		}while(iRe != DECODE_FINISHED)//4 表示解码结束的标志
	}
	else if(data.type === "stop"){
		Module._UnInit();
	}
}


猜你喜欢

转载自blog.csdn.net/pkx1993/article/details/82015315