@ -37,16 +37,17 @@
# include "nvVideoEffects.h"
# include "opencv2/opencv.hpp"
# define UWS_NO_ZLIB
# include "httplib.h"
# include "mjpeg_streamer.hpp"
# include " App.h "
//#include <uWebSockets/App.h>
# include <WinSock2.h>
# include <WS2tcpip.h>
# pragma comment(lib, "Ws2_32.lib")
using MJPEGStreamer = nadjieb : : MJPEGStreamer ;
//#pragma comment(lib, "uSockets.lib")
enum StreamType {
ST_ORIGINAL ,
@ -777,7 +778,6 @@ bail:
return ( FXApp : : Err ) vfxErr ;
}
MJPEGStreamer streamer ;
std : : mutex clients_mutex ;
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 } ;
/*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_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 ) ;
if ( key > 0 ) {
appErr = processKey ( key ) ;
@ -1242,6 +1211,83 @@ void startHttpServer() {
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 nErrs = 0 ;
nErrs = ParseMyArgs ( argc , argv ) ;
@ -1250,49 +1296,11 @@ int main(int argc, char **argv) {
return nErrs ;
}
/*std::thread serverThread(startHttpServer);
streamer . start ( 8001 ) ; */
std : : thread testws ( & testWS ) ;
TcpServer server ( 8093 ) ;
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 app ;