pull/3471/head
kallaballa 2 years ago
parent 2d55d08724
commit 14fe78b61c
  1. 34
      modules/v4d/CMakeLists.txt
  2. 4
      modules/v4d/samples/example_v4d_beauty-demo.html
  3. 35
      modules/v4d/samples/example_v4d_video-demo.html
  4. 2
      modules/v4d/src/detail/framebuffercontext.cpp
  5. 128
      modules/v4d/src/util.cpp

@ -49,7 +49,7 @@ macro(add_binary_sample sample)
endmacro()
if(EMSCRIPTEN)
set(EM_LINKER_FLAGS "-sENVIRONMENT=web,worker -sOFFSCREENCANVAS_SUPPORT -sOFFSCREENCANVASES_TO_PTHREAD=#offscreenCanvas -sEXPORTED_FUNCTIONS=_malloc,_main,_v4dSetVideoFramePointer -sEXPORTED_RUNTIME_METHODS=ccall,setValue -sPROXY_TO_PTHREAD=1 --use-preload-plugins --preload-file doc/lena.png -sINITIAL_MEMORY=128MB -sALLOW_MEMORY_GROWTH=1 -sUSE_GLFW=3 -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 --bind")
set(EM_LINKER_FLAGS "-sENVIRONMENT=web,worker -sOFFSCREENCANVAS_SUPPORT -sSTANDALONE_WASM -sOFFSCREENCANVASES_TO_PTHREAD=#offscreenCanvas -sEXPORTED_FUNCTIONS=_main,_v4dInitCapture -sEXPORTED_RUNTIME_METHODS=ccall -sPROXY_TO_PTHREAD=1 --use-preload-plugins --preload-file doc/lena.png -sINITIAL_MEMORY=128MB -sALLOW_MEMORY_GROWTH=1 -sUSE_GLFW=3 -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 --bind")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${EM_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${EM_LINKER_FLAGS}")
@ -118,23 +118,23 @@ if(BUILD_EXAMPLES)
set(NANOGUI_BUILD_GLFW OFF)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/third/nanogui/ext/glfw/include/")
add_emscripten_sample(example_v4d_display_image samples/display_image.cpp)
add_emscripten_sample(example_v4d_display_image_fb samples/display_image_fb.cpp)
add_emscripten_sample(example_v4d_vector_graphics samples/vector_graphics.cpp)
add_emscripten_sample(example_v4d_vector_graphics_and_fb samples/vector_graphics_and_fb.cpp)
add_emscripten_sample(example_v4d_render_opengl samples/render_opengl.cpp)
add_emscripten_sample(example_v4d_custom_source_and_sink samples/custom_source_and_sink.cpp)
add_emscripten_sample(example_v4d_font_rendering samples/font_rendering.cpp)
add_emscripten_sample(example_v4d_font_with_gui samples/font_with_gui.cpp)
add_emscripten_sample(example_v4d_video_editing samples/video_editing.cpp)
add_emscripten_sample(example_v4d_cube-demo samples/cube-demo.cpp)
# add_emscripten_sample(example_v4d_display_image samples/display_image.cpp)
# add_emscripten_sample(example_v4d_display_image_fb samples/display_image_fb.cpp)
# add_emscripten_sample(example_v4d_vector_graphics samples/vector_graphics.cpp)
# add_emscripten_sample(example_v4d_vector_graphics_and_fb samples/vector_graphics_and_fb.cpp)
# add_emscripten_sample(example_v4d_render_opengl samples/render_opengl.cpp)
# add_emscripten_sample(example_v4d_custom_source_and_sink samples/custom_source_and_sink.cpp)
# add_emscripten_sample(example_v4d_font_rendering samples/font_rendering.cpp)
# add_emscripten_sample(example_v4d_font_with_gui samples/font_with_gui.cpp)
# add_emscripten_sample(example_v4d_video_editing samples/video_editing.cpp)
# add_emscripten_sample(example_v4d_cube-demo samples/cube-demo.cpp)
add_emscripten_sample(example_v4d_video-demo samples/video-demo.cpp)
add_emscripten_sample(example_v4d_nanovg-demo samples/nanovg-demo.cpp)
add_emscripten_sample(example_v4d_font-demo samples/font-demo.cpp)
add_emscripten_sample(example_v4d_shader-demo samples/shader-demo.cpp)
add_emscripten_sample(example_v4d_pedestrian-demo samples/pedestrian-demo.cpp)
add_emscripten_sample(example_v4d_optflow-demo samples/optflow-demo.cpp)
add_emscripten_sample(example_v4d_beauty-demo samples/beauty-demo.cpp)
# add_emscripten_sample(example_v4d_nanovg-demo samples/nanovg-demo.cpp)
# add_emscripten_sample(example_v4d_font-demo samples/font-demo.cpp)
# add_emscripten_sample(example_v4d_shader-demo samples/shader-demo.cpp)
# add_emscripten_sample(example_v4d_pedestrian-demo samples/pedestrian-demo.cpp)
# add_emscripten_sample(example_v4d_optflow-demo samples/optflow-demo.cpp)
# add_emscripten_sample(example_v4d_beauty-demo samples/beauty-demo.cpp)
else()
add_binary_sample(example_v4d_display_image)
add_binary_sample(example_v4d_custom_source_and_sink)

@ -128,8 +128,8 @@
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var fsButton = document.querySelector("#fullscreenBtn");
var cameraBtn = document.querySelector("#captureBtn");
var videoElement = document.querySelector("#video");
var cameraBtn = document.querySelector("captureBtn");
var videoElement = document.querySelector("#v4dVideoElement");
var cameraCanvas = document.querySelector("#cameraCanvas");
function fixCanvasSize() {

@ -110,7 +110,7 @@
</span>
<canvas id="offscreenCanvas" width="1280" height="720" style="display: none;"></canvas>
<canvas id="cameraCanvas" width="1280" height="720" style="display: none;"></canvas>
<video id="video" width="1280" height="720" autoplay style="display: none;"></video>
<video id="v4dVideoElement" width="1280" height="720" autoplay style="display: none;"></video>
<div class="emscripten" id="status">Downloading...</div>
@ -128,8 +128,8 @@
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var fsButton = document.querySelector("#fullscreenBtn");
var cameraBtn = document.querySelector("#captureBtn");
var videoElement = document.querySelector("#video");
var captureBtn = document.querySelector("#captureBtn");
var videoElement = document.querySelector("#v4dVideoElement");
var cameraCanvas = document.querySelector("#cameraCanvas");
function fixCanvasSize() {
@ -142,9 +142,7 @@
var Module = {
onRuntimeInitialized: function() {
fixCanvasSize();
Module.videoBuffer = Module._malloc(1280 * 720 * 4);
Module.cameraCtx = null;
Module.ccall('v4dSetVideoFramePointer', 'void', ['number', 'number', 'number'], [Module.videoBuffer, 1280, 720]);
Module._v4dInitCapture(1280, 720);
},
preRun: [],
postRun: [],
@ -207,26 +205,16 @@
};
Module.setStatus('Downloading...');
window.onerror = function(event) {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
//spinnerElement.style.display = 'none';
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
var playing = false;
var timeupdate = false;
function checkReady() {
if (playing && timeupdate) {
Module.doCapture = true;
globalThis.doCapture = true;
}
}
cameraBtn.addEventListener('click', async function() {
let stream = await navigator.mediaDevices.getUserMedia({ video: { width: 1280, height: 720 }, audio: false});
captureBtn.addEventListener('click', async function() {
let stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
videoElement.addEventListener(
"playing",
() => {
@ -247,6 +235,15 @@
videoElement.srcObject = stream;
});
window.onerror = function(event) {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.setStatus('Exception thrown, see JavaScript console');
//spinnerElement.style.display = 'none';
Module.setStatus = function(text) {
if (text) Module.printErr('[post-exception status] ' + text);
};
};
fsButton.addEventListener('click', async function () {
Module.requestFullscreen(false, false)
});

@ -78,7 +78,7 @@ void FrameBufferContext::init() {
glfwWindowHint(GLFW_STENCIL_BITS, 8);
glfwWindowHint(GLFW_DEPTH_BITS, 24);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_VISIBLE, offscreen_ ? GLFW_FALSE : GLFW_TRUE);
glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE);
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
glfwWindow_ = glfwCreateWindow(frameBufferSize_.width, frameBufferSize_.height, title_.c_str(), nullptr,

@ -312,24 +312,39 @@ Source makeCaptureSource(const string& inputFilename) {
#else
using namespace emscripten;
uint8_t* current_frame = nullptr;
extern "C" {
EMSCRIPTEN_KEEPALIVE
void v4dSetVideoFramePointer(uint8_t* frame, int width, int height) {
assert(current_frame == nullptr);
current_frame = frame;
// memset(current_frame, 127, width * height * 4);
}
}
class HTML5Capture {
private:
cv::Ptr<V4D> window_;
int width_;
int height_;
UMat tmp_;
GLuint framebuffer = 0;
GLuint texture = 0;
public:
HTML5Capture(cv::Ptr<V4D> window, int width, int height) :
window_(window), width_(width), height_(height), tmp_(cv::Size(width, height), CV_8UC4) {
cerr << "start constr" << endl;
EM_ASM({
globalThis.playing = false;
globalThis.timeupdate = false;
globalThis.v4dVideoElement = document.querySelector("#v4dVideoElement");
globalThis.v4dCopyCanvasElement = document.createElement("canvas");
globalThis.v4dCopyCanvasElement.id = "v4dCopyCanvasElement0";
globalThis.v4dCopyCanvasElement.width = $0;
globalThis.v4dCopyCanvasElement.height = $1;
globalThis.v4dCopyCanvasElement.style.display = "none";
}, width, height);
cerr << "end constr" << endl;
}
GLuint framebuffer = 0;
GLuint texture = 0;
bool captureGPU(UMat& dst) {
cerr << "start capture" << endl;
FrameBufferContext::GLScope scope(window_->fbCtx());
cerr << "start em" << endl;
bool captureVideoFrameGPU(int width, int height) {
int ret = EM_ASM_INT(
if(typeof Module.ctx !== 'undefined' && Module.ctx !== null && Module.doCapture) {
if(typeof Module.ctx !== 'undefined' && Module.ctx != null && globalThis.doCapture) {
globalThis.gl = Module.ctx;
globalThis.v4dMainFrameBuffer = globalThis.gl.getParameter(globalThis.gl.FRAMEBUFFER_BINDING);
globalThis.v4dMainTexture = globalThis.gl.getFramebufferAttachmentParameter(globalThis.gl.FRAMEBUFFER, globalThis.gl.COLOR_ATTACHMENT0, globalThis.gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
@ -338,26 +353,21 @@ bool captureVideoFrameGPU(int width, int height) {
return 0;
}
);
cerr << "en em: " << ret << endl;
if(ret) {
EM_ASM(
if(typeof globalThis.v4dVideoElement === 'undefined' || globalThis.v4dVideoElement === null) {
globalThis.v4dVideoElement = document.querySelector("#video");
}
);
cerr << "1" << endl;
if(framebuffer == 0) {
GL_CHECK(glGenFramebuffers(1, &framebuffer));
}
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer));
cerr << "2" << endl;
if(texture == 0) {
GL_CHECK(glGenTextures(1, &texture));
}
GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture));
cerr << "3" << endl;
EM_ASM(
const level = 0;
const internalFormat = globalThis.gl.RGBA;
@ -373,7 +383,7 @@ bool captureVideoFrameGPU(int width, int height) {
globalThis.v4dVideoElement
);
);
cerr << "4" << endl;
GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0));
EM_ASM(
globalThis.gl.bindFramebuffer(globalThis.gl.DRAW_FRAMEBUFFER, globalThis.v4dMainFrameBuffer);
@ -381,51 +391,61 @@ bool captureVideoFrameGPU(int width, int height) {
globalThis.gl.pixelStorei(globalThis.gl.UNPACK_FLIP_Y_WEBGL, true);
globalThis.gl.framebufferTexture2D(globalThis.gl.DRAW_FRAMEBUFFER, globalThis.gl.COLOR_ATTACHMENT0, globalThis.gl.TEXTURE_2D, globalThis.v4dMainTexture, 0);
);
cerr << "5" << endl;
FrameBufferContext::FrameBufferScope fbScope(window_->fbCtx(), tmp_);
cvtColor(tmp_, dst, COLOR_BGRA2RGB);
cerr << "captured" << endl;
return true;
}
cerr << "not captured" << endl;
return false;
}
}
EM_JS(void,copyVideoFrameCPU,(int p), {
if(Module.doCapture) {
if(typeof Module.cameraCtx === 'undefined' || Module.cameraCtx === null)
Module.cameraCtx = document.querySelector("#cameraCanvas").getContext('2d', { willReadFrequently: true });
if(typeof Module.videoElement === 'undefined' || Module.videoElement === null)
Module.videoElement = document.querySelector("#video");
void captureCPU() {
EM_ASM(
if(globalThis.doCapture) {
if(typeof globalThis.v4dCopyCanvasContext === 'undefined' || globalThis.v4dCopyCanvasContext === null)
globalThis.v4dCopyCanvasContext = globalThis.v4dCopyCanvasElement.getContext('2d', { willReadFrequently: true });
if(typeof globalThis.v4dFrameData === 'undefined' || globalThis.v4dFrameData === null)
globalThis.v4dFrameData = Module._malloc(width_ * height_ * 4);
globalThis.v4dCopyCanvasElement.drawImage(globalThis.v4dVideoElement, 0, 0, 1280, 720);
var cameraArrayBuffer = globalThis.v4dCopyCanvasContext.getImageData(0, 0, 1280, 720);
Module.HEAPU8.set(cameraArrayBuffer.data, globalThis.v4dFrameData);
}
);
}
};
Module.cameraCtx.drawImage(Module.videoElement, 0, 0, 1280, 720);
var cameraArrayBuffer = Module.cameraCtx.getImageData(0, 0, 1280, 720);
cv::Ptr<HTML5Capture> capture = nullptr;
int capture_width = 0;
int capture_height = 0;
Module.HEAPU8.set(cameraArrayBuffer.data, p);
}
});
extern "C" {
EMSCRIPTEN_KEEPALIVE
void v4dInitCapture(int width, int height) {
capture_width = width;
capture_height = height;
}
}
Source makeCaptureSource(int width, int height, cv::Ptr<V4D> window) {
using namespace std;
return Source([=](cv::UMat& frame) {
//FIXME
static cv::UMat tmp(cv::Size(width, height), CV_8UC4);
if(capture == nullptr && capture_width > 0 && capture_height > 0)
// run_sync_on_main<16>([&](){
// capture = new HTML5Capture(window, capture_width, capture_height);
// });
try {
if(frame.empty())
frame.create(cv::Size(width, height), CV_8UC3);
if (current_frame != nullptr) {
run_sync_on_main<17>([&](){
FrameBufferContext::GLScope scope(window->fbCtx());
if(captureVideoFrameGPU(width, height)) {
FrameBufferContext::FrameBufferScope fbScope(window->fbCtx(), tmp);
cvtColor(tmp, frame, COLOR_BGRA2RGB);
}
});
// run_sync_on_main<16>([&](){
// copyVideoFrameCPU(reinterpret_cast<int>(current_frame));
// cv::Mat tmp(cv::Size(width, height), CV_8UC4, current_frame);
// cv::UMat utmp = tmp.getUMat(ACCESS_READ);
// cvtColor(utmp, frame, cv::COLOR_BGRA2RGB);
// utmp.release();
// tmp.release();
if(capture != nullptr) {
// run_sync_on_main<17>([&](){
// capture->captureGPU(frame);
// });
} else {
std::cerr << "Nothing captured" << endl;

Loading…
Cancel
Save