From ccc7aff7faaf715f4cf8f7854c209386c0011c09 Mon Sep 17 00:00:00 2001 From: uvos Date: Sat, 18 Nov 2023 14:15:38 +0100 Subject: [PATCH 01/10] set mjpeg proparty on webcam --- main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 3ee0d92..dfea928 100644 --- a/main.cpp +++ b/main.cpp @@ -43,10 +43,12 @@ int main(int argc, char* argv[]) std::cout<<"UVOS webcam sender v0.1\n"; - Webcam webcam(config.device, config.Xres, config.Yres); + Webcam webcam(config.device, config.Xres, config.Yres, config.mjpeg); std::stringstream ss; ss<<"nc "< Date: Sat, 18 Nov 2023 14:17:14 +0100 Subject: [PATCH 02/10] better error messages --- main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main.cpp b/main.cpp index dfea928..53a36fa 100644 --- a/main.cpp +++ b/main.cpp @@ -56,7 +56,10 @@ int main(int argc, char* argv[]) if(!config.overlay.empty()) { if(!overlay.open(config.overlay.c_str(), config.Xres, config.Yres, 3)) + { + std::cout<<"Unable to open "< Date: Sat, 18 Nov 2023 14:18:08 +0100 Subject: [PATCH 03/10] add some missing newlines in output --- main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index 53a36fa..0d7bc1c 100644 --- a/main.cpp +++ b/main.cpp @@ -46,7 +46,7 @@ int main(int argc, char* argv[]) Webcam webcam(config.device, config.Xres, config.Yres, config.mjpeg); std::stringstream ss; - ss<<"nc "< Date: Sat, 18 Nov 2023 14:18:44 +0100 Subject: [PATCH 04/10] add missin break that was causing the yres to leak into the overlay option --- options.h | 1 + 1 file changed, 1 insertion(+) diff --git a/options.h b/options.h index 8d1ff3a..da68ec0 100644 --- a/options.h +++ b/options.h @@ -49,6 +49,7 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) break; case 'y': config->Yres = std::stoi(arg); + break; case 'o': config->overlay = arg; break; From 5651f185ff6db1768bc50927bc802187530e5bd0 Mon Sep 17 00:00:00 2001 From: uvos Date: Sat, 18 Nov 2023 14:26:31 +0100 Subject: [PATCH 05/10] use V4L2_PIX_FMT_MJPEG instead of V4L2_PIX_FMT_JPEG --- webcam.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webcam.cpp b/webcam.cpp index 85e238e..3891528 100644 --- a/webcam.cpp +++ b/webcam.cpp @@ -89,7 +89,7 @@ Webcam::Webcam(const string& device, int width, int height, bool mjpeg) : device(device), xres(width), yres(height), - format(mjpeg ? V4L2_PIX_FMT_JPEG : V4L2_PIX_FMT_YUYV) + format(mjpeg ? V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_YUYV) { open_device(); init_device(); From f6bf337540bde8b63f237ce3575bf201baf7f329 Mon Sep 17 00:00:00 2001 From: uvos Date: Sat, 18 Nov 2023 15:45:06 +0100 Subject: [PATCH 06/10] better debug prints --- webcam.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webcam.cpp b/webcam.cpp index 3891528..a5c8fd8 100644 --- a/webcam.cpp +++ b/webcam.cpp @@ -336,7 +336,8 @@ void Webcam::init_device(void) { // note that libv4l2 (look for 'v4l-utils') provides helpers // to manage conversions - throw runtime_error("Webcam does not support the requested format. Support for more formats need to be added!"); + throw runtime_error("Webcam does not support the requested format. Support for more formats need to be added! video format is " + + std::to_string(fmt.fmt.pix.pixelformat)); } /* Note VIDIOC_S_FMT may change width and height. */ From d1414556fbc43bb546a0305648bb18ffa8a3432c Mon Sep 17 00:00:00 2001 From: uvos Date: Sat, 18 Nov 2023 15:57:00 +0100 Subject: [PATCH 07/10] more debug prints --- jpeg_img.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jpeg_img.cpp b/jpeg_img.cpp index c159558..26ae2fd 100644 --- a/jpeg_img.cpp +++ b/jpeg_img.cpp @@ -13,7 +13,8 @@ Image decompressJpegImage(const unsigned char* buffer, size_t size) jpeg_create_decompress( &info ); //fills info structure jpeg_mem_src(&info, buffer, size); - jpeg_read_header( &info, true ); + if(jpeg_read_header(&info, true) != JPEG_HEADER_OK) + std::cerr<<"Could not read jpeg header"; jpeg_start_decompress( &info ); From 24487a6a510bd7f3d4917d1ae9d5f714b72f39a8 Mon Sep 17 00:00:00 2001 From: uvos Date: Sat, 18 Nov 2023 15:59:00 +0100 Subject: [PATCH 08/10] use correct format in conversion --- webcam.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/webcam.cpp b/webcam.cpp index a5c8fd8..8c0a415 100644 --- a/webcam.cpp +++ b/webcam.cpp @@ -146,10 +146,14 @@ const Image& Webcam::frame(int timeout) yres, stride); } - else if(format == V4L2_PIX_FMT_JPEG) + else if(format == V4L2_PIX_FMT_MJPEG) { rgb_frame = decompressJpegImage((unsigned char *) buffers[idx].data, buffers[idx].size); } + else + { + assert(false); + } return rgb_frame; } /* EAGAIN - continue select loop. */ From 76bd00363b3b20be20ec03a0414fb77562d76a37 Mon Sep 17 00:00:00 2001 From: uvos Date: Sat, 18 Nov 2023 16:23:52 +0100 Subject: [PATCH 09/10] add support to passthough mjpeg images --- image.h | 29 ++++++++++++++++++++++++++--- jpeg_img.cpp | 4 ++-- main.cpp | 9 +++++++-- webcam.cpp | 48 +++++++++++++++++++++++++++++++++++------------- webcam.h | 3 ++- 5 files changed, 72 insertions(+), 21 deletions(-) diff --git a/image.h b/image.h index 05a8612..df02955 100644 --- a/image.h +++ b/image.h @@ -6,16 +6,39 @@ class Image { +private: + + ssize_t bufferSize = -1; + public: + + enum { + FORMAT_RGB, + FORMAT_JPEG, + FORMAT_YUYV + } typedef format_t; + std::shared_ptr data = nullptr; uint32_t width; uint32_t height; uint8_t channels; - const uint32_t size() + format_t format = FORMAT_RGB; + + const size_t size() const { - return width*height*channels; + return bufferSize < 0 ? width*height*channels : bufferSize; } - void save(const char* filename) + void setSize(size_t size) + { + bufferSize = size; + } + void setBuffer(std::shared_ptr buffer, size_t size, format_t inFormat = FORMAT_RGB) + { + data = buffer; + bufferSize = size; + format = inFormat; + } + void save(const char* filename) const { std::ofstream outfile(filename); outfile.write((char *) data.get(), size()); diff --git a/jpeg_img.cpp b/jpeg_img.cpp index 26ae2fd..0615343 100644 --- a/jpeg_img.cpp +++ b/jpeg_img.cpp @@ -25,7 +25,7 @@ Image decompressJpegImage(const unsigned char* buffer, size_t size) image.channels = info.num_components; // 3 = RGB, 4 = RGBA // read RGB(A) scanlines one at a time into jdata[] - image.data = std::shared_ptr(new unsigned char[image.size()]); + image.data = std::shared_ptr(new unsigned char[image.size()], std::default_delete()); unsigned char* rowptr; while(info.output_scanline < image.height) { @@ -58,7 +58,7 @@ Image decompressJpegImage(FILE *file) image.channels = info.num_components; // 3 = RGB, 4 = RGBA // read RGB(A) scanlines one at a time into jdata[] - image.data = std::shared_ptr(new unsigned char[image.size()]); + image.data = std::shared_ptr(new unsigned char[image.size()], std::default_delete()); unsigned char* rowptr; while ( info.output_scanline < image.height ) { diff --git a/main.cpp b/main.cpp index 0d7bc1c..897c6c6 100644 --- a/main.cpp +++ b/main.cpp @@ -41,9 +41,11 @@ int main(int argc, char* argv[]) Config config; argp_parse(&argp, argc, argv, 0, 0, &config); + bool passthough = config.mjpeg && config.overlay.empty(); + std::cout<<"UVOS webcam sender v0.1\n"; - Webcam webcam(config.device, config.Xres, config.Yres, config.mjpeg); + Webcam webcam(config.device, config.Xres, config.Yres, config.mjpeg, passthough); std::stringstream ss; ss<<"nc "<(new unsigned char[rgb_frame.size()]); + rgb_frame.data = std::shared_ptr(new unsigned char[rgb_frame.size()], std::default_delete()); start_capturing(); } @@ -138,21 +139,42 @@ const Image& Webcam::frame(int timeout) } int idx = read_frame(); if (idx != -1) { - if (format == V4L2_PIX_FMT_YUYV) + if(!passthrough_format) { - v4lconvert_yuyv_to_rgb24((unsigned char *) buffers[idx].data, - rgb_frame.data.get(), - xres, - yres, - stride); - } - else if(format == V4L2_PIX_FMT_MJPEG) - { - rgb_frame = decompressJpegImage((unsigned char *) buffers[idx].data, buffers[idx].size); + if (format == V4L2_PIX_FMT_YUYV) + { + v4lconvert_yuyv_to_rgb24((unsigned char *) buffers[idx].data, + rgb_frame.data.get(), + xres, + yres, + stride); + } + else if(format == V4L2_PIX_FMT_MJPEG) + { + rgb_frame = decompressJpegImage((unsigned char *) buffers[idx].data, buffers[idx].size); + } + else + { + assert(false); + } } else { - assert(false); + if(format == V4L2_PIX_FMT_YUYV) + { + rgb_frame.setBuffer(std::shared_ptr(new unsigned char[buffers[idx].size], std::default_delete()), + buffers[idx].size, Image::FORMAT_YUYV); + } + else if(format == V4L2_PIX_FMT_MJPEG) + { + rgb_frame.setBuffer(std::shared_ptr(new unsigned char[buffers[idx].size], std::default_delete()), + buffers[idx].size, Image::FORMAT_RGB); + } + else + { + assert(false); + } + memcpy(rgb_frame.data.get(), buffers[idx].data, buffers[idx].size); } return rgb_frame; } diff --git a/webcam.h b/webcam.h index 09f2fdb..bc8c0ef 100644 --- a/webcam.h +++ b/webcam.h @@ -18,7 +18,7 @@ class Webcam { public: Webcam(const std::string& device = "/dev/video0", int width = 640, - int height = 480, bool mjpeg = false); + int height = 480, bool mjpeg = false, bool passthrough = false); ~Webcam(); @@ -60,6 +60,7 @@ private: size_t stride; bool force_format = true; + bool passthrough_format; uint32_t format; }; From ed44167c0e99d4aed9f2142be6a3347b4e015f4b Mon Sep 17 00:00:00 2001 From: uvos Date: Sat, 18 Nov 2023 16:26:20 +0100 Subject: [PATCH 10/10] use correct deleter for data pointer --- jpeg_img.cpp | 4 ++-- webcam.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jpeg_img.cpp b/jpeg_img.cpp index 0615343..d5656a9 100644 --- a/jpeg_img.cpp +++ b/jpeg_img.cpp @@ -25,7 +25,7 @@ Image decompressJpegImage(const unsigned char* buffer, size_t size) image.channels = info.num_components; // 3 = RGB, 4 = RGBA // read RGB(A) scanlines one at a time into jdata[] - image.data = std::shared_ptr(new unsigned char[image.size()], std::default_delete()); + image.data = std::shared_ptr(new unsigned char[image.size()], std::default_delete()); unsigned char* rowptr; while(info.output_scanline < image.height) { @@ -58,7 +58,7 @@ Image decompressJpegImage(FILE *file) image.channels = info.num_components; // 3 = RGB, 4 = RGBA // read RGB(A) scanlines one at a time into jdata[] - image.data = std::shared_ptr(new unsigned char[image.size()], std::default_delete()); + image.data = std::shared_ptr(new unsigned char[image.size()], std::default_delete()); unsigned char* rowptr; while ( info.output_scanline < image.height ) { diff --git a/webcam.cpp b/webcam.cpp index 9817d30..26576a7 100644 --- a/webcam.cpp +++ b/webcam.cpp @@ -100,7 +100,7 @@ Webcam::Webcam(const string& device, int width, int height, bool mjpeg, bool pas rgb_frame.width = xres; rgb_frame.height = yres; rgb_frame.channels = 3; - rgb_frame.data = std::shared_ptr(new unsigned char[rgb_frame.size()], std::default_delete()); + rgb_frame.data = std::shared_ptr(new unsigned char[rgb_frame.size()], std::default_delete()); start_capturing(); } @@ -162,12 +162,12 @@ const Image& Webcam::frame(int timeout) { if(format == V4L2_PIX_FMT_YUYV) { - rgb_frame.setBuffer(std::shared_ptr(new unsigned char[buffers[idx].size], std::default_delete()), + rgb_frame.setBuffer(std::shared_ptr(new unsigned char[buffers[idx].size], std::default_delete()), buffers[idx].size, Image::FORMAT_YUYV); } else if(format == V4L2_PIX_FMT_MJPEG) { - rgb_frame.setBuffer(std::shared_ptr(new unsigned char[buffers[idx].size], std::default_delete()), + rgb_frame.setBuffer(std::shared_ptr(new unsigned char[buffers[idx].size], std::default_delete()), buffers[idx].size, Image::FORMAT_RGB); } else