updated video demo

pull/3471/head
kallaballa 3 years ago
parent bdc78aa255
commit a5ea310053
  1. 73
      src/common/subsystems.hpp
  2. 52
      src/video/video-demo.cpp

@ -26,7 +26,6 @@
#include <opencv2/core/ocl.hpp> #include <opencv2/core/ocl.hpp>
#include <opencv2/core/opengl.hpp> #include <opencv2/core/opengl.hpp>
using std::cout; using std::cout;
using std::cerr; using std::cerr;
using std::endl; using std::endl;
@ -294,7 +293,7 @@ std::string get_info() {
} }
void bind() { void bind() {
va::context.bind(); context.bind();
} }
} // namespace va } // namespace va
@ -375,44 +374,10 @@ void init() {
XStoreName(xdisplay, xwin, "nanovg-demo"); XStoreName(xdisplay, xwin, "nanovg-demo");
wmDeleteMessage = XInternAtom(xdisplay, "WM_DELETE_WINDOW", False); wmDeleteMessage = XInternAtom(xdisplay, "WM_DELETE_WINDOW", False);
XSetWMProtocols(xdisplay, xwin, &wmDeleteMessage, 1); XSetWMProtocols(xdisplay, xwin, &wmDeleteMessage, 1);
XSelectInput(xdisplay, xwin, ButtonPressMask | Button1MotionMask );
initialized = true; initialized = true;
} }
} // namespace x11
enum EventState {
NONE,
PRESS,
RELEASE,
MOTION
};
std::pair<EventState,cv::Point> consume_event() {
XEvent event;
EventState state;
int revert_to;
XGetInputFocus(xdisplay, &xwin, &revert_to);
int x = 0, y = 0;
if (XEventsQueued(xdisplay, QueuedAlready) > 0) {
XNextEvent(xdisplay, &event);
switch (event.type) {
case ButtonPress:
x = event.xmotion.x;
y = event.xmotion.y;
state = PRESS;
break;
case MotionNotify:
x = event.xmotion.x;
y = event.xmotion.y;
state = MOTION;
break;
}
}
return {state,{x,y}};
}
}
namespace egl { namespace egl {
//code in the kb::egl namespace deals with setting up EGL //code in the kb::egl namespace deals with setting up EGL
@ -594,7 +559,10 @@ namespace gl {
cv::ogl::Texture2D *frame_buf_tex; cv::ogl::Texture2D *frame_buf_tex;
GLuint frame_buf; GLuint frame_buf;
cv::ocl::OpenCLExecutionContext context; cv::ocl::OpenCLExecutionContext context;
bool initialized = false;
void bind() {
context.bind();
}
void init() { void init() {
glewExperimental = true; glewExperimental = true;
@ -606,6 +574,7 @@ void init() {
glCheck(glGenFramebuffers(1, &frame_buf)); glCheck(glGenFramebuffers(1, &frame_buf));
glCheck(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frame_buf)); glCheck(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frame_buf));
// Create stencil render buffer (note that I create depth buffer the exact same way, and It works.
GLuint sb; GLuint sb;
glGenRenderbuffers(1, &sb); glGenRenderbuffers(1, &sb);
glBindRenderbuffer(GL_RENDERBUFFER, sb); glBindRenderbuffer(GL_RENDERBUFFER, sb);
@ -620,16 +589,6 @@ void init() {
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
gl::context = cv::ocl::OpenCLExecutionContext::getCurrent(); gl::context = cv::ocl::OpenCLExecutionContext::getCurrent();
initialized = true;
}
void bind() {
gl::context.bind();
}
bool is_initialized() {
return initialized;
} }
void swap_buffers() { void swap_buffers() {
@ -705,11 +664,21 @@ void pop() {
glCheck(glPopAttrib()); glCheck(glPopAttrib());
} }
void begin(int w, int h, double pxRatio = 1) { void begin() {
push(); push();
float w = WIDTH;
float h = HEIGHT;
if(x11::is_initialized()) {
auto ws = x11::get_window_size();
w = ws.first;
h = ws.second;
}
glCheck(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, kb::gl::frame_buf)); glCheck(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, kb::gl::frame_buf));
nvgSave(vg); nvgSave(vg);
nvgBeginFrame(vg, w, h, pxRatio); glCheck(glViewport(0, HEIGHT - h, w, h));
nvgBeginFrame(vg, w, h, std::fmax(WIDTH/w, HEIGHT/h));
} }
void end() { void end() {
@ -736,8 +705,8 @@ void init(bool debug = false) {
} }
nvgCreateFont(vg, "icons", "fonts/entypo.ttf"); nvgCreateFont(vg, "icons", "fonts/entypo.ttf");
nvgCreateFont(vg, "sans-bold", "fonts/DejaVuSans-Bold.ttf"); nvgCreateFont(vg, "sans-bold", "fonts/TheBoldFont.ttf");
nvgCreateFont(vg, "sans", "fonts/DejaVuSans.ttf"); nvgCreateFont(vg, "sans", "fonts/TheBoldFont.ttf");
pop(); pop();
} }

@ -3,6 +3,9 @@
//WIDTH and HEIGHT have to be specified before including subsystems.hpp //WIDTH and HEIGHT have to be specified before including subsystems.hpp
constexpr long unsigned int WIDTH = 1920; constexpr long unsigned int WIDTH = 1920;
constexpr long unsigned int HEIGHT = 1080; constexpr long unsigned int HEIGHT = 1080;
constexpr const int VA_HW_DEVICE_INDEX = 0;
constexpr bool OFFSCREEN = false;
constexpr const char *OUTPUT_FILENAME = "video-demo.mkv";
#include "../common/subsystems.hpp" #include "../common/subsystems.hpp"
#include <stdlib.h> #include <stdlib.h>
@ -12,26 +15,6 @@ using std::cerr;
using std::endl; using std::endl;
using std::string; using std::string;
//Static stream info. Has to match your capture device/file
constexpr double INPUT_FPS = 30;
constexpr int INPUT_WIDTH = 320;
constexpr int INPUT_HEIGHT = 240;
const string INPUT_FORMAT = "mjpeg";
const string PIXEL_FORMAT = "yuyv422";
const string INPUT_FILENAME = "example.mp4";
const string OUTPUT_FILENAME = "camera-demo.mkv";
//The ffmpeg capture and writer options we need to capture... but don't overwrite the environment variables if they already exist.
const string CAPTURE_OPTIONS = "framerate;" + std::to_string(INPUT_FPS)
+ "|input_format;" + INPUT_FORMAT
+ "|video_size;" + std::to_string(INPUT_WIDTH) + "x" + std::to_string(INPUT_HEIGHT)
+ "|pixel_format;" + PIXEL_FORMAT;
const string WRITER_OPTIONS = "";
constexpr const int VA_HW_DEVICE_INDEX = 0;
constexpr bool OFFSCREEN = false;
void init_render() { void init_render() {
glViewport(0, 0, WIDTH, HEIGHT); glViewport(0, 0, WIDTH, HEIGHT);
glColor3f(1.0, 1.0, 1.0); glColor3f(1.0, 1.0, 1.0);
@ -52,7 +35,6 @@ void init_render() {
void render() { void render() {
//Render a tetrahedron using immediate mode because the code is more concise for a demo //Render a tetrahedron using immediate mode because the code is more concise for a demo
glBindFramebuffer(GL_FRAMEBUFFER, kb::gl::frame_buf);
glViewport(0, 0, WIDTH, HEIGHT); glViewport(0, 0, WIDTH, HEIGHT);
glRotatef(1, 0, 1, 0); glRotatef(1, 0, 1, 0);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
@ -97,29 +79,31 @@ void glow_effect(cv::UMat &src, int ksize = WIDTH / 85 % 2 == 0 ? WIDTH / 85 +
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
//The ffmpeg capture and writer options we need to capture... but don't overwrite the environment variables if they already exist.
setenv("OPENCV_FFMPEG_CAPTURE_OPTIONS", CAPTURE_OPTIONS.c_str(), 0);
setenv("OPENCV_FFMPEG_WRITER_OPTIONS", WRITER_OPTIONS.c_str(), 0);
using namespace kb; using namespace kb;
if(argc != 2) {
cerr << "Usage: video-demo <video-file>" << endl;
exit(1);
}
//Initialize OpenCL Context for VAAPI //Initialize OpenCL Context for VAAPI
va::init(); va::init();
//Initialize MJPEG HW decoding using VAAPI //Initialize MJPEG HW decoding using VAAPI
cv::VideoCapture cap(INPUT_FILENAME, cv::CAP_FFMPEG, { cv::VideoCapture capture(argv[1], cv::CAP_FFMPEG, {
cv::CAP_PROP_HW_DEVICE, VA_HW_DEVICE_INDEX, cv::CAP_PROP_HW_DEVICE, VA_HW_DEVICE_INDEX,
cv::CAP_PROP_HW_ACCELERATION, cv::VIDEO_ACCELERATION_VAAPI, cv::CAP_PROP_HW_ACCELERATION, cv::VIDEO_ACCELERATION_VAAPI,
cv::CAP_PROP_HW_ACCELERATION_USE_OPENCL, 1 cv::CAP_PROP_HW_ACCELERATION_USE_OPENCL, 1
}); });
// check if we succeeded // check if we succeeded
if (!cap.isOpened()) { if (!capture.isOpened()) {
cerr << "ERROR! Unable to open camera" << endl; cerr << "ERROR! Unable to open camera" << endl;
return -1; return -1;
} }
double fps = capture.get(cv::CAP_PROP_FPS);
//Initialize VP9 HW encoding using VAAPI. We don't need to specify the hardware device twice. only generates a warning. //Initialize VP9 HW encoding using VAAPI. We don't need to specify the hardware device twice. only generates a warning.
cv::VideoWriter video(OUTPUT_FILENAME, cv::CAP_FFMPEG, cv::VideoWriter::fourcc('V', 'P', '9', '0'), INPUT_FPS, cv::Size(WIDTH, HEIGHT), { cv::VideoWriter writer(OUTPUT_FILENAME, cv::CAP_FFMPEG, cv::VideoWriter::fourcc('V', 'P', '9', '0'), fps, cv::Size(WIDTH, HEIGHT), {
cv::VIDEOWRITER_PROP_HW_ACCELERATION, cv::VIDEO_ACCELERATION_VAAPI, cv::VIDEOWRITER_PROP_HW_ACCELERATION, cv::VIDEO_ACCELERATION_VAAPI,
cv::VIDEOWRITER_PROP_HW_ACCELERATION_USE_OPENCL, 1 cv::VIDEOWRITER_PROP_HW_ACCELERATION_USE_OPENCL, 1
}); });
@ -145,7 +129,7 @@ int main(int argc, char **argv) {
uint64_t cnt = 1; uint64_t cnt = 1;
int64 start = cv::getTickCount(); int64 start = cv::getTickCount();
double tickFreq = cv::getTickFrequency(); double tickFreq = cv::getTickFrequency();
double lastFps = INPUT_FPS; double lastFps = fps;
init_render(); init_render();
@ -158,17 +142,17 @@ int main(int argc, char **argv) {
//Activate the OpenCL context for VAAPI //Activate the OpenCL context for VAAPI
va::bind(); va::bind();
//Decode a frame on the GPU using VAAPI //Decode a frame on the GPU using VAAPI
cap >> videoFrame; capture >> videoFrame;
if (videoFrame.empty()) { if (videoFrame.empty()) {
cerr << "End of stream. Exiting" << endl; cerr << "End of stream. Exiting" << endl;
break; break;
} }
//The video is upside-down. Flip it. (OpenCL) //The frameBuffer is upside-down. Flip videoFrame. (OpenCL)
cv::flip(videoFrame, videoFrame, 0); cv::flip(videoFrame, videoFrame, 0);
//Color-conversion from BGRA to RGB. (OpenCL) //Color-conversion from RGB to BGRA. (OpenCL)
cv::cvtColor(videoFrame, videoFrameRGBA, cv::COLOR_RGB2BGRA); cv::cvtColor(videoFrame, videoFrameRGBA, cv::COLOR_RGB2BGRA);
//Resize the frame. (OpenCL) //Resize the frame if necessary. (OpenCL)
cv::resize(videoFrameRGBA, frameBuffer, cv::Size(WIDTH, HEIGHT)); cv::resize(videoFrameRGBA, frameBuffer, cv::Size(WIDTH, HEIGHT));
gl::bind(); gl::bind();
@ -191,7 +175,7 @@ int main(int argc, char **argv) {
//Activate the OpenCL context for VAAPI //Activate the OpenCL context for VAAPI
va::bind(); va::bind();
//Encode the frame using VAAPI on the GPU. //Encode the frame using VAAPI on the GPU.
video.write(videoFrame); writer.write(videoFrame);
if(x11::is_initialized()) { if(x11::is_initialized()) {
//Yet again activate the OpenCL context for OpenGL //Yet again activate the OpenCL context for OpenGL

Loading…
Cancel
Save