Update README, update language standard to C++20, update cmake to include uWebSockets library

master
Benjamin Ruesink 2 months ago
parent 4c93ee32df
commit c3f5f11d11

@ -4,15 +4,19 @@ cmake_minimum_required(VERSION 3.10)
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR} CACHE PATH "Path to where the samples will be installed") set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR} CACHE PATH "Path to where the samples will be installed")
option(INSTALL_SDK "Install binaries into the samples folder" OFF) option(INSTALL_SDK "Install binaries into the samples folder" OFF)
project(NvVideoEffects_SDK CXX) project(NvVideoEffects_SDK C CXX)
set(CMAKE_CONFIGURATION_TYPES "Release") set(CMAKE_CONFIGURATION_TYPES "Release")
# Require C++11 and disable non-standard extensions # Require C++20 and disable non-standard extensions
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(VCPKG_TARGET_TRIPLET "x64-windows")
set(CMAKE_TOOLCHAIN_FILE "C:/vcpkg/scripts/buildsystems/vcpkg.cmake")
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)
# Set common build path for all targets # Set common build path for all targets

@ -1,4 +1,34 @@
# README # README
## AiMaskStreamApp requirements
### Setup
- Install [vcpkg](https://github.com/microsoft/vcpkg) to e.g. C:/vcpkg
```bash
vcpkg integrate install
```
- Install required packages
```bash
vcpkg install libuv:x64-windows uwebsockets-json:x64-windows zlib:x64-windows usockets:x64-windows
```
- Configure and generate the Visual Studio solution file
- If using CMake GUI, set the source folder to the root of the repository and the build folder to `build`, and set the toolchain file (-T) to `C:/vcpkg/scripts/buildsystems/vcpkg.cmake`
```bash
mkdir build
```
- else:
```bash
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake ..
```
### Build
- Open the generated Visual Studio solution file and build the solution
- Built binaries will be in `build/Release`
- You might need to copy `opencv_world346.dll` from `samples/external/opencv/bin` to the binary directory to run the application
## NVIDIA MAXINE VideoEffects SDK: API Source Code and Sample Applications ## NVIDIA MAXINE VideoEffects SDK: API Source Code and Sample Applications
NVIDIA MAXINE Video Effects SDK enables AI-based visual effects that run with standard webcam input and can easily be integrated into video conference and content creation pipelines. The underlying deep learning models are optimized with NVIDIA AI using NVIDIA® TensorRT™ for high-performance inference, making it possible for developers to apply multiple effects in real-time applications. NVIDIA MAXINE Video Effects SDK enables AI-based visual effects that run with standard webcam input and can easily be integrated into video conference and content creation pipelines. The underlying deep learning models are optimized with NVIDIA AI using NVIDIA® TensorRT™ for high-performance inference, making it possible for developers to apply multiple effects in real-time applications.

@ -37,16 +37,17 @@
#include "nvVideoEffects.h" #include "nvVideoEffects.h"
#include "opencv2/opencv.hpp" #include "opencv2/opencv.hpp"
#define UWS_NO_ZLIB
#include "httplib.h" #include "httplib.h"
#include "mjpeg_streamer.hpp" #include "App.h"
//#include <uWebSockets/App.h> //#include <uWebSockets/App.h>
#include <WinSock2.h> #include <WinSock2.h>
#include <WS2tcpip.h> #include <WS2tcpip.h>
#pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "Ws2_32.lib")
//#pragma comment(lib, "uSockets.lib")
using MJPEGStreamer = nadjieb::MJPEGStreamer;
enum StreamType { enum StreamType {
ST_ORIGINAL, ST_ORIGINAL,
@ -777,7 +778,6 @@ bail:
return (FXApp::Err)vfxErr; return (FXApp::Err)vfxErr;
} }
MJPEGStreamer streamer;
std::mutex clients_mutex; std::mutex clients_mutex;
struct PerSocketData { struct PerSocketData {
}; };
@ -1120,40 +1120,9 @@ FXApp::Err FXApp::processMovie(const char *inFile, const char *outFile) {
static std::vector<int> params = { cv::IMWRITE_JPEG_QUALITY, 90 }; static std::vector<int> params = { cv::IMWRITE_JPEG_QUALITY, 90 };
/*std::vector<uchar> buff_bgr;
cv::imencode(".jpg", originalImg, buff_bgr, params);
streamer.publish("/original", std::string(buff_bgr.begin(), buff_bgr.end()));*/
//cv::Mat hsv;
//cv::cvtColor(result, hsv, cv::COLOR_BGR2HSV);
// http://localhost:8080/hsv
/*std::vector<uchar> buff_hsv;
cv::imencode(".jpg", result, buff_hsv, params);
streamer.publish("/masked", std::string(buff_hsv.begin(), buff_hsv.end()));*/
pushToFrameQueue(ST_ORIGINAL, originalImg); pushToFrameQueue(ST_ORIGINAL, originalImg);
pushToFrameQueue(ST_MASKED, result); pushToFrameQueue(ST_MASKED, result);
/* std::vector<uchar> buf;
cv::imencode(".jpg", originalImg, buf);
std::string encoded(buf.begin(), buf.end());
std::lock_guard<std::mutex> lock(clients_mutex);*/
/*for (auto ws : clients) {
ws->send(encoded, uWS::OpCode::BINARY);
}*/
//std::this_thread::sleep_for(std::chrono::milliseconds(33)); // ~30 fps
//pushToFrameQueue(ST_PROCESSED, outlineResult);
// Display the results
//cv::imshow("Original", originalImg);
//cv::imshow("Overlay", result);
//cv::imshow("OutlineTest", outlineResult);
int key = cv::waitKey(1); int key = cv::waitKey(1);
if (key > 0) { if (key > 0) {
appErr = processKey(key); appErr = processKey(key);
@ -1242,6 +1211,83 @@ void startHttpServer() {
svr.listen("0.0.0.0", 8090); svr.listen("0.0.0.0", 8090);
} }
void testWS() {
/* ws->getUserData returns one of these */
struct PerSocketData {
/* Fill with user data */
std::vector<std::string> topics;
int nr = 0;
};
{
/* Keep in mind that uWS::SSLApp({options}) is the same as uWS::App() when compiled without SSL support.
* You may swap to using uWS:App() if you don't need SSL */
uWS::SSLApp* app = new uWS::SSLApp({
/* There are example certificates in uWebSockets.js repo */
.key_file_name = "misc/key.pem",
.cert_file_name = "misc/cert.pem",
.passphrase = "1234"
});
app->ws<PerSocketData>("/*", {
/* Settings */
.compression = uWS::DISABLED,
.maxPayloadLength = 16 * 1024 * 1024,
.idleTimeout = 60,
.maxBackpressure = 16 * 1024 * 1024,
.closeOnBackpressureLimit = false,
.resetIdleTimeoutOnSend = true,
.sendPingsAutomatically = false,
/* Handlers */
.upgrade = nullptr,
.open = [](auto* ws) {
/* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
printf("opened\n");
PerSocketData* perSocketData = (PerSocketData*)ws->getUserData();
for (int i = 0; i < 32; i++) {
std::string topic = std::to_string((uintptr_t)ws) + "-" + std::to_string(i);
perSocketData->topics.push_back(topic);
ws->subscribe(topic);
}
},
.message = [&app](auto* ws, std::string_view message, uWS::OpCode opCode) {
PerSocketData* perSocketData = (PerSocketData*)ws->getUserData();
printf("Message: %s\n", message.data());
app->publish(perSocketData->topics[(size_t)(++perSocketData->nr % 32)], message, opCode);
ws->publish(perSocketData->topics[(size_t)(++perSocketData->nr % 32)], message, opCode);
},
.drain = [](auto*/*ws*/) {
/* Check ws->getBufferedAmount() here */
//std::cout << "drain" << std::endl;
},
.ping = [](auto*/*ws*/, std::string_view) {
/* Not implemented yet */
},
.pong = [](auto*/*ws*/, std::string_view) {
/* Not implemented yet */
},
.close = [](auto*/*ws*/, int /*code*/, std::string_view /*message*/) {
/* You may access ws->getUserData() here */
}
}).listen(9001, [](auto* listen_s) {
if (listen_s) {
std::cout << "Listening on port " << 9001 << std::endl;
//listen_socket = listen_s;
}
});
app->run();
delete app;
uWS::Loop::get()->free();
}
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
int nErrs = 0; int nErrs = 0;
nErrs = ParseMyArgs(argc, argv); nErrs = ParseMyArgs(argc, argv);
@ -1250,49 +1296,11 @@ int main(int argc, char **argv) {
return nErrs; return nErrs;
} }
/*std::thread serverThread(startHttpServer); std::thread testws(&testWS);
streamer.start(8001);*/
TcpServer server(8093); TcpServer server(8093);
std::thread serverThread2(&TcpServer::start, &server); std::thread serverThread2(&TcpServer::start, &server);
//httplib::Server svr;
//svr.Get("/video", [](const httplib::Request&, httplib::Response& res) {
// cv::VideoCapture cap(0); // Open webcam
// if (!cap.isOpened()) {
// std::cerr << "Error: Cannot open webcam\n";
// return;
// }
// // Content provider for streaming
// res.set_content_provider(
// "multipart/x-mixed-replace; boundary=frame",
// [cap](size_t offset, httplib::DataSink& sink) mutable {
// cv::Mat frame;
// cap >> frame;
// if (!frame.empty()) {
// std::vector<uchar> bytes = matToBytes(frame);
// // Write multipart content
// std::string header = "--frame\r\nContent-Type: image/jpeg\r\n\r\n";
// sink.write(header.data(), header.size());
// sink.write(reinterpret_cast<const char*>(bytes.data()), bytes.size());
// sink.write("\r\n", 2);
// }
// return true; // Continue streaming
// },
// [](bool success) {
// // Completion handler when stream ends
// }
// );
// });
//svr.listen("0.0.0.0", 8080);
FXApp::Err fxErr = FXApp::errNone; FXApp::Err fxErr = FXApp::errNone;
FXApp app; FXApp app;

@ -20,6 +20,7 @@ if(MSVC)
target_link_libraries(AiMaskStreamApp PUBLIC target_link_libraries(AiMaskStreamApp PUBLIC
opencv346 opencv346
NVVideoEffects NVVideoEffects
uWebSockets
${CMAKE_CURRENT_SOURCE_DIR}/../external/cuda/lib/x64/cudart.lib ${CMAKE_CURRENT_SOURCE_DIR}/../external/cuda/lib/x64/cudart.lib
) )

@ -1,3 +1,6 @@
add_subdirectory(uSockets)
add_subdirectory(uWebSockets)
####################### #######################
# Interface to OpenCV # # Interface to OpenCV #
####################### #######################

@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.24)
# set(CMAKE_C_STANDARD 11)
include(FetchContent)
FetchContent_Declare(
uSockets_content
GIT_REPOSITORY https://github.com/uNetworking/uSockets
GIT_TAG v0.8.5
GIT_SHALLOW ON
GIT_SUBMODULES ""
)
FetchContent_MakeAvailable(uSockets_content)
file(GLOB_RECURSE SOURCES ${usockets_content_SOURCE_DIR}/src/*.c)
add_library(uSockets ${SOURCES})
target_include_directories(uSockets PUBLIC ${usockets_content_SOURCE_DIR}/src)
target_compile_definitions(uSockets PRIVATE LIBUS_NO_SSL)
find_package(libuv CONFIG REQUIRED)
target_link_libraries(uSockets PRIVATE $<IF:$<TARGET_EXISTS:libuv::uv_a>,libuv::uv_a,libuv::uv>)

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.24)
include(FetchContent)
FetchContent_Declare(
uWebSockets_content
GIT_REPOSITORY https://github.com/uNetworking/uWebSockets
GIT_TAG v20.37.0
GIT_SHALLOW ON
GIT_SUBMODULES ""
)
FetchContent_MakeAvailable(uWebSockets_content)
find_package(ZLIB REQUIRED)
add_library(uWebSockets INTERFACE)
target_include_directories(uWebSockets INTERFACE ${uwebsockets_content_SOURCE_DIR}/src/)
target_link_libraries(uWebSockets INTERFACE uSockets ${ZLIB_LIBRARIES})
Loading…
Cancel
Save