// // Emscripten/SDL2/OpenGLES2 sample that demonstrates simple geometry and shaders, mouse and touch input, and window resizing // // Setup: // Install emscripten: http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html // // Build: // emcc -std=c++11 hello_triangle.cpp events.cpp camera.cpp -s USE_SDL=2 -s FULL_ES2=1 -s WASM=0 -o hello_triangle.html // // Run: // emrun hello_triangle.html // // Result: // A colorful triangle. Left mouse pans, mouse wheel zooms in/out. Window is resizable. // #ifdef __EMSCRIPTEN__ #include #endif #include #include //#include //#include #include #include "events.h" extern "C" { #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/eval.h" #include "libavutil/mathematics.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" #include "libavutil/dict.h" #include "libavutil/fifo.h" #include "libavutil/parseutils.h" #include "libavutil/samplefmt.h" #include "libavutil/time.h" #include "libavutil/bprint.h" #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" #include "libavutil/opt.h" #include "libavcodec/avfft.h" #include "libavcodec/avcodec.h" #include "libswresample/swresample.h" } typedef void (*callback_UpdateDcmImage) (); callback_UpdateDcmImage callback_UpdateDcmImageComplete = NULL; uint8_t* g_pImageData = NULL; SwsContext *img_convert_ctx = NULL; AVFormatContext* format_ctx = NULL; AVCodecContext* codec_ctx = NULL; int video_stream_index = -1; std::string g_strFilename = ""; bool g_bLoadFile = false; bool g_bChange = false; EventHandler* g_pEventHandler = NULL; GLuint textureObj = 0; GLuint g_shaderProgramGray16 = 0; GLuint g_shaderProgramRGB = 0; // Vertex shader GLint g_shaderPanGray16, g_shaderZoomGray16, g_shaderAspectGray16, g_shaderWindowCenterGray16, g_shaderWindowWidthGray16; GLint g_shaderPanRGB, g_shaderZoomRGB, g_shaderAspectRGB, g_shaderWindowCenterRGB, g_shaderWindowWidthRGB; int g_nColorType = 1; int g_nWindowCenter = 0; int g_nWindowWidth = 0; int g_nPrevWindowCenter = 0; int g_nPrevWindowWidth = 0; Uint32 g_nCurrentFrame = 0; int g_nTotalFrames = 0; int g_nFrameWidth = 0; int g_nFrameHeight = 0; int g_nSamplesPerPixel = 0; int g_nBitsAllocated = 0; int g_nFrameSizeUncompressed = 0; const GLchar* vertexSourceGray16 = "uniform vec2 pan; \n" "uniform float zoom; \n" "uniform float aspect; \n" "attribute vec4 position; \n" "attribute vec2 a_texCoord; \n" "varying vec2 texCoord; \n" "void main() \n" "{ \n" " gl_Position = vec4(position.xyz, 1.0); \n" " gl_Position.xy += pan; \n" " gl_Position.xy *= zoom; \n" " texCoord = a_texCoord; \n" " gl_Position.y *= aspect; \n" "} \n"; // Fragment/pixel shader const GLchar* fragmentSourceGray16 = "precision mediump float; \n" "varying vec2 texCoord; \n" "uniform sampler2D texSampler; \n" "uniform float fWindowCenter; \n" "uniform float fWindowWidth; \n" "void main() \n" "{ \n" " vec4 colorOut = texture2D(texSampler, texCoord); \n" " float fMin = fWindowCenter - fWindowWidth/2.0;\n" " float fMax = fWindowCenter + fWindowWidth/2.0;\n" " float fData = ( ((colorOut.a + colorOut.r*256.0)*256.0) - fMin)/(fMax-fMin); \n" " fData = ( ((colorOut.a + colorOut.a*256.0)*256.0) - fMin)/(fMax-fMin); \n" " fData = colorOut.r;\n" " fData = (((colorOut.a * 256.0 + colorOut.r)*256.0) - fMin) / (fMax-fMin);" " float fTmpData = fMin;\n" " gl_FragColor = vec4(fData, fData, fData, 1.0); \n" "} \n"; const GLchar* vertexSourceRGB = "uniform vec2 panRGB; \n" "uniform float zoomRGB; \n" "uniform float aspectRGB; \n" "attribute vec4 position; \n" "attribute vec2 a_texCoord; \n" "varying vec2 texCoord; \n" "void main() \n" "{ \n" " gl_Position = vec4(position.xyz, 1.0); \n" " gl_Position.xy += panRGB; \n" " gl_Position.xy *= zoomRGB; \n" " texCoord = a_texCoord; \n" " gl_Position.y *= aspectRGB; \n" "} \n"; // Fragment/pixel shader const GLchar* fragmentSourceRGB = "precision mediump float; \n" "varying vec2 texCoord; \n" "uniform sampler2D texSampler; \n" "uniform float fWindowCenterRGB; \n" "uniform float fWindowWidthRGB; \n" "void main() \n" "{ \n" " vec4 colorOut = texture2D(texSampler, texCoord); \n" " float fMin = fWindowCenterRGB - fWindowWidthRGB/2.0;\n" " float fMax = fWindowCenterRGB + fWindowWidthRGB/2.0;\n" " float fTestValue = (fMax - fMin);\n" " float fR = (colorOut.r*256.0 - fMin) / (fMax-fMin);\n" " float fG = (colorOut.g*256.0 - fMin) / (fMax-fMin);\n" " float fB = (colorOut.b*256.0 - fMin) / (fMax-fMin);\n" " gl_FragColor = vec4(fR, fG, fB, 1.0); \n" //" gl_FragColor = vec4(colorOut.r/fTestValue, 1.0, 1.0, 1.0); \n" "} \n"; void updateShader(EventHandler& eventHandler) { Camera& camera = eventHandler.camera(); printf("updateShader: g_nColorType=%d\n", g_nColorType); if(g_nColorType==0) { glUseProgram(g_shaderProgramGray16); glUniform2fv(g_shaderPanGray16, 1, camera.pan()); glUniform1f(g_shaderZoomGray16, camera.zoom()); glUniform1f(g_shaderAspectGray16, camera.aspect()); } else if(g_nColorType==1) { glUseProgram(g_shaderProgramRGB); glUniform2fv(g_shaderPanRGB, 1, camera.pan()); glUniform1f(g_shaderZoomRGB, camera.zoom()); glUniform1f(g_shaderAspectRGB, camera.aspect()); } } void onErrorData(void* arg) { printf("onErrorData %d\n", (int)arg); } void updateTextureGray16(int nWidth, int nHeight, void* pData) { glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, nWidth, nHeight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pData); } void updateTextureRGB(int nWidth, int nHeight, void* pData) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pData); } void updateWindowWidthLevelGray16(int nWidth, int nLevel) { glUniform1f(g_shaderWindowCenterGray16, (float)nLevel); glUniform1f(g_shaderWindowWidthGray16, (float)nWidth); } void updateWindowWidthLevelRGB(int nWidth, int nLevel) { glUniform1f(g_shaderWindowCenterRGB, (float)nLevel); glUniform1f(g_shaderWindowWidthRGB, (float)nWidth); } void initShaderGray16() { // Create and compile vertex shader GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexSourceGray16, NULL); glCompileShader(vertexShader); // Create and compile fragment shader GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentSourceGray16, NULL); glCompileShader(fragmentShader); // Link vertex and fragment shader into shader program and use it g_shaderProgramGray16 = glCreateProgram(); glAttachShader(g_shaderProgramGray16, vertexShader); glAttachShader(g_shaderProgramGray16, fragmentShader); glLinkProgram(g_shaderProgramGray16); //glUseProgram(g_shaderProgramGray16); // Get shader variables and initialize them g_shaderPanGray16 = glGetUniformLocation(g_shaderProgramGray16, "pan"); g_shaderZoomGray16 = glGetUniformLocation(g_shaderProgramGray16, "zoom"); g_shaderAspectGray16 = glGetUniformLocation(g_shaderProgramGray16, "aspect"); g_shaderWindowCenterGray16 = glGetUniformLocation(g_shaderProgramGray16, "fWindowCenter"); g_shaderWindowWidthGray16 = glGetUniformLocation(g_shaderProgramGray16, "fWindowWidth"); glUniform1f(g_shaderWindowCenterGray16, 128.0f); glUniform1f(g_shaderWindowWidthGray16, 255.0f); //printf("pan:%d, zoom:%d, aspect:%d, g_shaderWindowCenterGray16:%d, g_shaderWindowWidthGray16:%d\n", g_shaderPanGray16, g_shaderZoomGray16, g_shaderAspectGray16, g_shaderWindowCenterGray16, g_shaderWindowWidthGray16); } void initShaderRGB() { // Create and compile vertex shader GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexSourceRGB, NULL); glCompileShader(vertexShader); // Create and compile fragment shader GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentSourceRGB, NULL); glCompileShader(fragmentShader); // Link vertex and fragment shader into shader program and use it g_shaderProgramRGB = glCreateProgram(); //printf("g_shaderProgramRGB: %d\n", g_shaderProgramRGB); glAttachShader(g_shaderProgramRGB, vertexShader); glAttachShader(g_shaderProgramRGB, fragmentShader); glLinkProgram(g_shaderProgramRGB); //glUseProgram(g_shaderProgramRGB); // Get shader variables and initialize them g_shaderPanRGB = glGetUniformLocation(g_shaderProgramRGB, "panRGB"); g_shaderZoomRGB = glGetUniformLocation(g_shaderProgramRGB, "zoomRGB"); g_shaderAspectRGB = glGetUniformLocation(g_shaderProgramRGB, "aspectRGB"); g_shaderWindowCenterRGB = glGetUniformLocation(g_shaderProgramRGB, "fWindowCenterRGB"); g_shaderWindowWidthRGB = glGetUniformLocation(g_shaderProgramRGB, "fWindowWidthRGB"); glUniform1f(g_shaderWindowCenterRGB, 128.0f); glUniform1f(g_shaderWindowWidthRGB, 255.0f); //printf("pan:%d, zoom:%d, aspect:%d, g_shaderWindowCenterRGB:%d, g_shaderWindowWidthRGB:%d\n", g_shaderPanRGB, g_shaderZoomRGB, g_shaderAspectRGB, g_shaderWindowCenterRGB, g_shaderWindowWidthRGB); } GLuint initShader(EventHandler& eventHandler) { initShaderGray16(); initShaderRGB(); updateShader(eventHandler); g_pEventHandler = &eventHandler; return g_shaderProgramGray16; } GLuint g_vbo = 0; void initGeometry(GLuint shaderProgram) { // Create vertex buffer object and copy vertex data into it //printf("g_vbo: %d\n", g_vbo); glGenBuffers(1, &g_vbo); glBindBuffer(GL_ARRAY_BUFFER, g_vbo); GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, }; glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Specify the layout of the shader vertex data (positions only, 3 floats) GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); glEnableVertexAttribArray(posAttrib); // glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); // glEnableVertexAttribArray(0); GLint texAttrib = glGetAttribLocation(shaderProgram, "a_texCoord"); glEnableVertexAttribArray(texAttrib); glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); //glEnableVertexAttribArray(2); // glBindBuffer(GL_ARRAY_BUFFER, 0); //printf("initGeometry(%d, %d)\n", posAttrib, texAttrib); } void PrintError() { int nError = 0; nError = glGetError(); printf("Error Code: %d\n", nError); } void onLoadedData(void* arg, void* buffer, int nSize) { printf("onLoadedData %d, %d\n", (int)arg, nSize); } void initTextureGray16(void* pImageData) { //const Uint16* pImageData = NULL; //g_pDcmDataset->findAndGetUint16Array(DCM_PixelData, pImageData); int w = g_nFrameWidth; int h = g_nFrameHeight; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); { glGenTextures(1, &textureObj); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureObj); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); PrintError(); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pImageData); PrintError(); GLint nTextureID = glGetUniformLocation(g_shaderProgramGray16, "texSampler"); //printf("texSampler: %d\n", nTextureID); glActiveTexture(GL_TEXTURE0); glUniform1i(nTextureID, 0); } } void initTextureRGB(void* pImageData) { printf("initTextureRGB\n"); //const Uint8* pImageData = NULL; //g_pDcmDataset->findAndGetUint8Array(DCM_PixelData, pImageData); int w = g_nFrameWidth; int h = g_nFrameHeight; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GLint format = GL_RGB; //printf("textureObj: %d\n", textureObj); if(textureObj>=0) { glBindTexture(GL_TEXTURE_2D, 0); glDeleteTextures(1, &textureObj); } glGenTextures(1, &textureObj); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureObj); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); PrintError(); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, pImageData); PrintError(); GLint nTextureID = glGetUniformLocation(g_shaderProgramRGB, "texSampler"); //printf("texSampler: %d\n", nTextureID); glActiveTexture(GL_TEXTURE0); glUniform1i(nTextureID, 0); } void redraw(EventHandler& eventHandler) { if(g_bChange==true) { if(g_nColorType==0) { initGeometry(g_shaderProgramGray16); glUseProgram(g_shaderProgramGray16); initTextureGray16(g_pImageData); updateShader(*g_pEventHandler); } else if(g_nColorType==1) { initGeometry(g_shaderProgramRGB); glUseProgram(g_shaderProgramRGB); initTextureRGB(g_pImageData); updateShader(*g_pEventHandler); } g_bChange = false; } if(g_nTotalFrames>0) { if(g_nColorType==0) { printf("updateTextureRGB: %d\n", g_nCurrentFrame); updateTextureGray16(g_nFrameWidth, g_nFrameHeight, g_pImageData); } else if(g_nColorType==1) { //printf("updateTextureRGB: %d, %d, %d, %d, %s\nerror: %s\n", g_nFrameWidth, g_nFrameHeight, g_nCurrentFrame, g_nFrameSizeUncompressed, decompressedColorModel.c_str(), ofTest.text()); updateTextureRGB(g_nFrameWidth, g_nFrameHeight, g_pImageData); } if(g_nCurrentFrame>=g_nTotalFrames) { g_nCurrentFrame = 0; } } if(g_nColorType==0) { updateWindowWidthLevelGray16(g_nPrevWindowWidth, g_nPrevWindowCenter); } else if(g_nColorType==1) { updateWindowWidthLevelRGB(g_nPrevWindowWidth, g_nPrevWindowCenter); } // Clear screen glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); // Draw the vertex buffer glDrawArrays(GL_TRIANGLES, 0, 6); // Swap front/back framebuffers eventHandler.swapWindow(); } void mainLoop(void* mainLoopArg) { EventHandler& eventHandler = *((EventHandler*)mainLoopArg); eventHandler.processEvents(); if(g_bLoadFile==false && g_strFilename.size()>0) { AVDictionary *opts = NULL; int ret = av_dict_set(&opts, "rtsp_transport", "tcp", 0); // av_dict_set(&opts, "rtsp_transport", "tcp", 0); // av_dict_set(&opts, "timeout", "5000", 0); printf("UpdateDcmImage: av_dic_set\n"); g_strFilename = "http://localhost:5173/playlist_1080p.m3u8"; printf("filename: %s\n", g_strFilename.c_str()); //open RTSP // // printf("avformat_open_input: start1212121212\n"); // format_ctx = avformat_alloc_context(); //if (avformat_open_input(&format_ctx, g_strFilename.c_str(), NULL, &opts) != 0) if (avformat_open_input(&format_ctx, g_strFilename.c_str(), NULL, NULL) != 0) { printf("Error avformat_open_input"); //return EXIT_FAILURE; } printf("avformat_open_input: finish\n"); av_dict_free(&opts); callback_UpdateDcmImageComplete(); g_bLoadFile = true; } int nType = eventHandler.GetEventType(); if(nType==1 || nType==2) { float fDeltaX = eventHandler.GetDeltaX(); float fDeltaY = eventHandler.GetDeltaY(); g_nPrevWindowCenter = g_nWindowCenter+fDeltaY; g_nPrevWindowWidth = g_nWindowWidth + fDeltaX; } else if(nType==3 || nType==4) { g_nWindowCenter = g_nPrevWindowCenter; g_nWindowWidth = g_nPrevWindowWidth; } // Update shader if camera changed if (eventHandler.camera().updated()) updateShader(eventHandler); redraw(eventHandler); } #ifdef __cplusplus #define EXTERN extern "C" #else #define EXTERN #endif EXTERN EMSCRIPTEN_KEEPALIVE int UpdateDcmImage(std::string strURL) { printf("UpdateDcmImage: %s\n", strURL.c_str()); g_strFilename = strURL; /* AVDictionary *opts = NULL; int ret = av_dict_set(&opts, "rtsp_transport", "tcp", 0); printf("UpdateDcmImage: av_dic_set\n"); //open RTSP if (avformat_open_input(&format_ctx, strURL.c_str(), NULL, &opts) != 0) { printf("Error avformat_open_input"); return EXIT_FAILURE; } av_dict_free(&opts); callback_UpdateDcmImageComplete(); */ return 0; } EXTERN EMSCRIPTEN_KEEPALIVE int SetWindowWidthLevel(int nWindowCenter, int nWindowWidth) { printf("New nWindowCenter:%d, nWindowWidth:%d\n", nWindowCenter, nWindowWidth); g_nWindowCenter = nWindowCenter; g_nWindowWidth = nWindowWidth; g_nPrevWindowCenter = g_nWindowCenter; g_nPrevWindowWidth = g_nWindowWidth; return 0; } EXTERN EMSCRIPTEN_KEEPALIVE int GetWindowWidth() { return g_nWindowWidth; } EXTERN EMSCRIPTEN_KEEPALIVE int GetWindowCenter() { return g_nWindowCenter; } EXTERN EMSCRIPTEN_KEEPALIVE bool SetCallbackUpdateDcmImageComplete(callback_UpdateDcmImage callback_) { printf("SetCallbackUpdateDcmImage: %x\n", callback_); callback_UpdateDcmImageComplete = callback_; return true; } int main(int argc, char** argv) { EventHandler eventHandler("dcm image viewer"); avdevice_register_all(); avformat_network_init(); if(g_pImageData==NULL) { g_pImageData = new uint8_t[1920*1080*3]; int i=0; int j=0; for(i=0 ; i<1080 ; i++) { for(j=0 ; j<1920 ; j++) { g_pImageData[(i*1920+j)*3+0] = 128; g_pImageData[(i*1920+j)*3+1] = 128; g_pImageData[(i*1920+j)*3+2] = 0; } } } // Initialize shader and geometry GLuint shaderProgram = initShader(eventHandler); //initTexture(); // Start the main loop void* mainLoopArg = &eventHandler; #ifdef __EMSCRIPTEN__ int fps = 0; // Use browser's requestAnimationFrame emscripten_set_main_loop_arg(mainLoop, mainLoopArg, fps, true); #else while(true) mainLoop(mainLoopArg); #endif glDeleteTextures(1, &textureObj); glBindTexture(GL_TEXTURE_2D, 0); if(g_pImageData!=NULL) { delete[] g_pImageData; g_pImageData = NULL; } printf("exit!!!!! c++ dcm_image_mod"); return 0; }