From d5dc9940d8d8477979edb300171cacdc4a010aa4 Mon Sep 17 00:00:00 2001 From: sz Date: Tue, 22 Mar 2022 21:59:16 -0500 Subject: [PATCH 01/10] WIP for cimbar_recv --- CMakeLists.txt | 1 + src/exe/cimbar_recv/CMakeLists.txt | 39 ++++++++ src/exe/cimbar_recv/recv.cpp | 152 +++++++++++++++++++++++++++++ src/lib/gui/gl_program.h | 1 + 4 files changed, 193 insertions(+) create mode 100644 src/exe/cimbar_recv/CMakeLists.txt create mode 100644 src/exe/cimbar_recv/recv.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b3d6038..13dcf5da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ set(PROJECTS src/exe/cimbar src/exe/cimbar_extract + src/exe/cimbar_recv src/exe/cimbar_send src/exe/build_image_assets ) diff --git a/src/exe/cimbar_recv/CMakeLists.txt b/src/exe/cimbar_recv/CMakeLists.txt new file mode 100644 index 00000000..9f2dbc89 --- /dev/null +++ b/src/exe/cimbar_recv/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.10) + +project(cimbar_recv) + +set (SOURCES + recv.cpp +) + +add_executable ( + cimbar_recv + ${SOURCES} +) + +target_link_libraries(cimbar_recv + + cimb_translator + extractor + + correct_static + wirehair + zstd + + GL + glfw + ${OPENCV_LIBS} + opencv_videoio +) + +add_custom_command( + TARGET cimbar_recv POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ cimbar_recv.dbg + COMMAND ${CMAKE_STRIP} -g $ +) + +install( + TARGETS cimbar_recv + DESTINATION bin +) + diff --git a/src/exe/cimbar_recv/recv.cpp b/src/exe/cimbar_recv/recv.cpp new file mode 100644 index 00000000..d72db204 --- /dev/null +++ b/src/exe/cimbar_recv/recv.cpp @@ -0,0 +1,152 @@ +/* This code is subject to the terms of the Mozilla Public License, v.2.0. http://mozilla.org/MPL/2.0/. */ +#include "cimb_translator/Config.h" +#include "compression/zstd_decompressor.h" +#include "encoder/Decoder.h" +#include "extractor/Extractor.h" +#include "fountain/fountain_decoder_sink.h" +#include "gui/window_glfw.h" + +#include "cxxopts/cxxopts.hpp" +#include "serialize/str.h" +#include "util/File.h" +#include +#include + +#include +#include +#include +#include +#include +using std::string; +using std::vector; + +namespace { + + template + TP wait_for_frame_time(unsigned delay, const TP& start) + { + unsigned millis = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); + if (delay > millis) + std::this_thread::sleep_for(std::chrono::milliseconds(delay-millis)); + return std::chrono::high_resolution_clock::now(); + } + + + std::pair window_size() + { + GLFWmonitor* mon = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(mon); + return {mode->width, mode->height}; + } +} + + +int main(int argc, char** argv) +{ + cxxopts::Options options("cimbar video decoder", "Use the camera to decode data!"); + + unsigned colorBits = cimbar::Config::color_bits(); + unsigned ecc = cimbar::Config::ecc_bytes(); + unsigned defaultFps = 15; + options.add_options() + ("i,in", "Video source.", cxxopts::value()) + ("o,out", "Output directory (decoding).", cxxopts::value()) + ("c,colorbits", "Color bits. [0-3]", cxxopts::value()->default_value(turbo::str::str(colorBits))) + ("e,ecc", "ECC level", cxxopts::value()->default_value(turbo::str::str(ecc))) + ("f,fps", "Target FPS", cxxopts::value()->default_value(turbo::str::str(defaultFps))) + ("h,help", "Print usage") + ; + options.show_positional_help(); + options.parse_positional({"in", "out"}); + options.positional_help(" "); + + auto result = options.parse(argc, argv); + if (result.count("help") or !result.count("in") or !result.count("out")) + { + std::cout << options.help() << std::endl; + return 0; + } + + string source = result["in"].as(); + string outpath = result["out"].as(); + + colorBits = std::min(3, result["colorbits"].as()); + ecc = result["ecc"].as(); + unsigned fps = result["fps"].as(); + if (fps == 0) + fps = defaultFps; + unsigned delay = 1000 / fps; + + cv::VideoCapture vc(source.c_str()); + if (!vc.isOpened()) + { + std::cerr << "failed to open video device :(" << std::endl; + return 70; + } + + vc.set(cv::CAP_PROP_FRAME_WIDTH, 1920); + vc.set(cv::CAP_PROP_FRAME_HEIGHT, 1080); + + //auto [width, height] = window_size(); + int width = 1280; + int height = 1080; + std::cout << "got dimensions " << width << "," << height << std::endl; + + cimbar::window_glfw window(width, height, "cimbar_recv"); + if (!window.is_good()) + { + std::cerr << "failed to create window :(" << std::endl; + return 70; + } + + Decoder dec; + + unsigned chunkSize = cimbar::Config::fountain_chunk_size(ecc); + fountain_decoder_sink> sink(outpath, chunkSize); + + cv::Mat mat; + + std::chrono::time_point start = std::chrono::high_resolution_clock::now(); + while (true) + { + // delay, then try to read frame + start = wait_for_frame_time(delay, start); + + if (!vc.read(mat)) + { + std::cerr << "failed to read from cam" << std::endl; + continue; + } + + cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); + + // draw some stats on mat? + window.show(mat, 0); + if (window.should_close()) + break; + + // extract + cv::UMat img = mat.getUMat(cv::ACCESS_RW); + + bool shouldPreprocess = false; + Extractor ext; + int res = ext.extract(img, img); + if (!res) + { + std::cerr << "no extract " << mat.cols << "," << mat.rows << std::endl; + continue; + } + else if (res == Extractor::NEEDS_SHARPEN) + shouldPreprocess = true; + + //cv::imwrite("/tmp/foo-base.png", mat); + //cv::imwrite("/tmp/foo-ex.png", img); + + // decode + int bytes = dec.decode_fountain(img, sink, shouldPreprocess); + std::cerr << "got some bytes " << bytes << std::endl; + + } + + return 0; +} diff --git a/src/lib/gui/gl_program.h b/src/lib/gui/gl_program.h index b94699ba..59521e8d 100644 --- a/src/lib/gui/gl_program.h +++ b/src/lib/gui/gl_program.h @@ -3,6 +3,7 @@ #include #include +#include #include namespace cimbar { From 8c23f60ab19e3b22e398f775af9fc2d08630278a Mon Sep 17 00:00:00 2001 From: sz Date: Thu, 24 Mar 2022 01:21:06 -0500 Subject: [PATCH 02/10] Reorder various things... still not working... --- src/exe/cimbar_recv/recv.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/exe/cimbar_recv/recv.cpp b/src/exe/cimbar_recv/recv.cpp index d72db204..1a2f4083 100644 --- a/src/exe/cimbar_recv/recv.cpp +++ b/src/exe/cimbar_recv/recv.cpp @@ -88,7 +88,7 @@ int main(int argc, char** argv) vc.set(cv::CAP_PROP_FRAME_HEIGHT, 1080); //auto [width, height] = window_size(); - int width = 1280; + int width = 1920; int height = 1080; std::cout << "got dimensions " << width << "," << height << std::endl; @@ -99,6 +99,7 @@ int main(int argc, char** argv) return 70; } + Extractor ext; Decoder dec; unsigned chunkSize = cimbar::Config::fountain_chunk_size(ecc); @@ -111,25 +112,23 @@ int main(int argc, char** argv) { // delay, then try to read frame start = wait_for_frame_time(delay, start); + if (window.should_close()) + break; if (!vc.read(mat)) { std::cerr << "failed to read from cam" << std::endl; continue; } + cv::UMat img = mat.getUMat(cv::ACCESS_RW); cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); // draw some stats on mat? window.show(mat, 0); - if (window.should_close()) - break; // extract - cv::UMat img = mat.getUMat(cv::ACCESS_RW); - - bool shouldPreprocess = false; - Extractor ext; + bool shouldPreprocess = true; int res = ext.extract(img, img); if (!res) { @@ -139,8 +138,8 @@ int main(int argc, char** argv) else if (res == Extractor::NEEDS_SHARPEN) shouldPreprocess = true; - //cv::imwrite("/tmp/foo-base.png", mat); - //cv::imwrite("/tmp/foo-ex.png", img); + cv::imwrite("/tmp/foo-base.png", mat); + cv::imwrite("/tmp/foo-ex.png", img); // decode int bytes = dec.decode_fountain(img, sink, shouldPreprocess); From e1fdcc74dc43f59ccdf133f4ca6748aac771b6ac Mon Sep 17 00:00:00 2001 From: sz Date: Thu, 24 Mar 2022 19:14:56 -0500 Subject: [PATCH 03/10] good lord --- src/lib/extractor/Scanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/extractor/Scanner.cpp b/src/lib/extractor/Scanner.cpp index 62503da2..9c976707 100644 --- a/src/lib/extractor/Scanner.cpp +++ b/src/lib/extractor/Scanner.cpp @@ -123,7 +123,7 @@ bool Scanner::sort_top_to_bottom(std::vector& anchors) incoming_edge = {-incoming_edge.y(), incoming_edge.x()}; // rotate point overlap = departing_edge - incoming_edge; - if (overlap.dot(overlap) < edges[departing_edge].dot(edges[departing_edge])) + if (overlap.dot(overlap) < departing_edge.dot(departing_edge)) top_right = fix_index<3>(top_left + 1); else top_right = fix_index<3>(top_left - 1); From 80695606bea26b6e31d47257e585c9905fee0c6a Mon Sep 17 00:00:00 2001 From: sz Date: Thu, 24 Mar 2022 20:08:43 -0500 Subject: [PATCH 04/10] The test was wrong :scream: --- src/lib/extractor/Scanner.cpp | 15 ++++++++------ src/lib/extractor/Scanner.h | 2 +- src/lib/extractor/test/ScannerTest.cpp | 28 +++++++++++++++++--------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/lib/extractor/Scanner.cpp b/src/lib/extractor/Scanner.cpp index 9c976707..3a192bd4 100644 --- a/src/lib/extractor/Scanner.cpp +++ b/src/lib/extractor/Scanner.cpp @@ -21,7 +21,7 @@ namespace { { if (i < 0) i = N-1; - else if (i > N-1) + else if (i >= N) i = 0; return i; } @@ -115,7 +115,7 @@ bool Scanner::sort_top_to_bottom(std::vector& anchors) // because of how we ordered our edges, the index of the longest edge is also the index of the anchor opposite it. int top_left = get_longest_edge(edges); - int top_right; + int top_right, bottom_left; // now, we need to find the order of the other two: const point& departing_edge = edges[fix_index<3>(top_left - 1)]; @@ -124,15 +124,18 @@ bool Scanner::sort_top_to_bottom(std::vector& anchors) point overlap = departing_edge - incoming_edge; if (overlap.dot(overlap) < departing_edge.dot(departing_edge)) + { top_right = fix_index<3>(top_left + 1); + bottom_left = fix_index<3>(top_left - 1); + } else + { top_right = fix_index<3>(top_left - 1); + bottom_left = fix_index<3>(top_left + 1); + } // apply the order. - if (&anchors[0] != &anchors[top_left]) - std::swap(anchors[0], anchors[top_left]); - if (top_left != 1 and top_right != 1) - std::swap(anchors[1], anchors[2]); + anchors = {anchors[top_left], anchors[top_right], anchors[bottom_left]}; return true; } diff --git a/src/lib/extractor/Scanner.h b/src/lib/extractor/Scanner.h index 3c77d037..10a44db3 100644 --- a/src/lib/extractor/Scanner.h +++ b/src/lib/extractor/Scanner.h @@ -41,7 +41,7 @@ class Scanner public: // other interesting methods std::vector deduplicate_candidates(const std::vector& candidates) const; unsigned filter_candidates(std::vector& candidates) const; - bool sort_top_to_bottom(std::vector& anchors); + static bool sort_top_to_bottom(std::vector& anchors); template void t1_scan_rows(std::function fun, int skip=-1, int y=-1, int yend=-1, int xstart=-1, int xend=-1) const; diff --git a/src/lib/extractor/test/ScannerTest.cpp b/src/lib/extractor/test/ScannerTest.cpp index 6463cf77..8d2402ac 100644 --- a/src/lib/extractor/test/ScannerTest.cpp +++ b/src/lib/extractor/test/ScannerTest.cpp @@ -210,34 +210,42 @@ TEST_CASE( "ScannerTest/testScanEdges", "[unit]" ) TEST_CASE( "ScannerTest/testSortTopToBottom", "[unit]" ) { - cv::Mat img = TestCimbar::loadSample("6bit/4_30_f0_627.jpg"); - Scanner sc(img); - std::vector candidates; candidates.push_back(Anchor(300, 360, 100, 160)); candidates.push_back(Anchor(300, 360, 300, 360)); candidates.push_back(Anchor(100, 160, 300, 360)); - assertTrue( sc.sort_top_to_bottom(candidates) ); // make this a static function? + assertTrue( Scanner::sort_top_to_bottom(candidates) ); assertEquals( - "330+-30,330+-30 330+-30,130+-30 130+-30,330+-30", - turbo::str::join(candidates) + "330+-30,330+-30 130+-30,330+-30 330+-30,130+-30", + turbo::str::join(candidates) ); } TEST_CASE( "ScannerTest/testSortTopToBottom.2", "[unit]" ) { - cv::Mat img = TestCimbar::loadSample("6bit/4_30_f0_627.jpg"); - Scanner sc(img); - std::vector candidates; candidates.push_back(Anchor(966, 1020, 966, 1020)); candidates.push_back(Anchor(966, 1020, 2, 56)); candidates.push_back(Anchor(2, 56, 966, 1020)); - assertTrue( sc.sort_top_to_bottom(candidates) ); + assertTrue( Scanner::sort_top_to_bottom(candidates) ); assertEquals( "993+-27,993+-27 29+-27,993+-27 993+-27,29+-27", turbo::str::join(candidates) ); } + +TEST_CASE( "ScannerTest/testSortTopToBottom.3", "[unit]" ) +{ + std::vector candidates; + candidates.push_back(Anchor(383, 437, 994, 1048)); + candidates.push_back(Anchor(395, 447, 107, 157)); + candidates.push_back(Anchor(1250, 1296, 124, 170)); + assertTrue( Scanner::sort_top_to_bottom(candidates) ); + + assertEquals( + "421+-26,132+-25 1273+-23,147+-23 410+-27,1021+-27", + turbo::str::join(candidates) + ); +} From c3f26f7db00d1b49ecf91e3ac0e43e0c8e87d9c6 Mon Sep 17 00:00:00 2001 From: sz Date: Thu, 24 Mar 2022 22:36:35 -0500 Subject: [PATCH 05/10] Cleanup, things are working* --- src/exe/cimbar_recv/recv.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/exe/cimbar_recv/recv.cpp b/src/exe/cimbar_recv/recv.cpp index 1a2f4083..3124b1b4 100644 --- a/src/exe/cimbar_recv/recv.cpp +++ b/src/exe/cimbar_recv/recv.cpp @@ -9,8 +9,9 @@ #include "cxxopts/cxxopts.hpp" #include "serialize/str.h" #include "util/File.h" -#include + #include +#include #include #include @@ -107,9 +108,12 @@ int main(int argc, char** argv) cv::Mat mat; + unsigned count = 0; std::chrono::time_point start = std::chrono::high_resolution_clock::now(); while (true) { + ++count; + // delay, then try to read frame start = wait_for_frame_time(delay, start); if (window.should_close()) @@ -120,8 +124,8 @@ int main(int argc, char** argv) std::cerr << "failed to read from cam" << std::endl; continue; } - cv::UMat img = mat.getUMat(cv::ACCESS_RW); + cv::UMat img = mat.getUMat(cv::ACCESS_RW); cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB); // draw some stats on mat? @@ -138,9 +142,6 @@ int main(int argc, char** argv) else if (res == Extractor::NEEDS_SHARPEN) shouldPreprocess = true; - cv::imwrite("/tmp/foo-base.png", mat); - cv::imwrite("/tmp/foo-ex.png", img); - // decode int bytes = dec.decode_fountain(img, sink, shouldPreprocess); std::cerr << "got some bytes " << bytes << std::endl; From 97b118ad89f67edff99ce8c3ddd5fd1c02dd5815 Mon Sep 17 00:00:00 2001 From: sz Date: Fri, 25 Mar 2022 18:49:34 -0500 Subject: [PATCH 06/10] Resize the gl viewport to match the window + ... Pick a relatively small window size by default, but match the camera ratio. The camera size settings should pick the largest size <= to the requested size, afaik --- src/exe/cimbar_recv/recv.cpp | 28 ++++++++++++---------------- src/lib/gui/window_glfw.h | 8 ++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/exe/cimbar_recv/recv.cpp b/src/exe/cimbar_recv/recv.cpp index 3124b1b4..7b2f909f 100644 --- a/src/exe/cimbar_recv/recv.cpp +++ b/src/exe/cimbar_recv/recv.cpp @@ -31,14 +31,6 @@ namespace { std::this_thread::sleep_for(std::chrono::milliseconds(delay-millis)); return std::chrono::high_resolution_clock::now(); } - - - std::pair window_size() - { - GLFWmonitor* mon = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(mon); - return {mode->width, mode->height}; - } } @@ -84,13 +76,16 @@ int main(int argc, char** argv) std::cerr << "failed to open video device :(" << std::endl; return 70; } - vc.set(cv::CAP_PROP_FRAME_WIDTH, 1920); - vc.set(cv::CAP_PROP_FRAME_HEIGHT, 1080); + vc.set(cv::CAP_PROP_FRAME_HEIGHT, 1200); + + // set max camera res, and use aspect ratio for window size... - //auto [width, height] = window_size(); - int width = 1920; - int height = 1080; + std::cout << fmt::format("width: {}, height {}", vc.get(cv::CAP_PROP_FRAME_WIDTH), vc.get(cv::CAP_PROP_FRAME_HEIGHT)) << std::endl; + + double ratio = vc.get(cv::CAP_PROP_FRAME_WIDTH) / vc.get(cv::CAP_PROP_FRAME_HEIGHT); + int height = 600; + int width = height * ratio; std::cout << "got dimensions " << width << "," << height << std::endl; cimbar::window_glfw window(width, height, "cimbar_recv"); @@ -99,6 +94,7 @@ int main(int argc, char** argv) std::cerr << "failed to create window :(" << std::endl; return 70; } + window.auto_scale_to_window(); Extractor ext; Decoder dec; @@ -136,7 +132,7 @@ int main(int argc, char** argv) int res = ext.extract(img, img); if (!res) { - std::cerr << "no extract " << mat.cols << "," << mat.rows << std::endl; + //std::cerr << "no extract " << mat.cols << "," << mat.rows << std::endl; continue; } else if (res == Extractor::NEEDS_SHARPEN) @@ -144,8 +140,8 @@ int main(int argc, char** argv) // decode int bytes = dec.decode_fountain(img, sink, shouldPreprocess); - std::cerr << "got some bytes " << bytes << std::endl; - + if (bytes > 0) + std::cerr << "got some bytes " << bytes << std::endl; } return 0; diff --git a/src/lib/gui/window_glfw.h b/src/lib/gui/window_glfw.h index a562f498..72c62386 100644 --- a/src/lib/gui/window_glfw.h +++ b/src/lib/gui/window_glfw.h @@ -56,6 +56,14 @@ class window_glfw return glfwWindowShouldClose(_w); } + void auto_scale_to_window() + { + if (!is_good()) + return; + auto fun = [](GLFWwindow*, int w, int h){ glViewport(0, 0, w, h); }; + glfwSetWindowSizeCallback(_w, fun); + } + void rotate(unsigned i=1) { if (_display) From d3dc2bd2fb3fd694ab2d549e8f90ba33ba67b58b Mon Sep 17 00:00:00 2001 From: sz Date: Fri, 25 Mar 2022 19:17:16 -0500 Subject: [PATCH 07/10] Adding a background grid cimbarjs to (maybe) help with autofocus --- web/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/index.html b/web/index.html index 9279be43..51f4b94d 100644 --- a/web/index.html +++ b/web/index.html @@ -19,7 +19,7 @@ body { background-color: white; - background-image: radial-gradient(circle at top left, rgb(7,0,0),rgb(244,244,244),rgb(255,255,255)); + background-image: radial-gradient(circle at top left, rgb(7,0,0),transparent,transparent), repeating-linear-gradient(0deg, rgb(153,197,206) 0px, rgb(153,197,206) 1px, transparent 1px, transparent 30px), repeating-linear-gradient(0deg, rgb(153,197,206) 0px, rgb(153,197,206) 2px, transparent 2px, transparent 150px), repeating-linear-gradient(90deg, rgb(153,197,206) 0px, rgb(153,197,206) 1px, transparent 1px, transparent 30px),repeating-linear-gradient(90deg, rgb(153,197,206) 0px, rgb(153,197,206) 2px, transparent 2px, transparent 150px), linear-gradient(white, white); background-size: cover; color: gray; display: grid; From 8cbd4f323a29e0ca1ffab332b1a0341e1a854c41 Mon Sep 17 00:00:00 2001 From: sz Date: Fri, 25 Mar 2022 19:21:22 -0500 Subject: [PATCH 08/10] Set FPS? --- src/exe/cimbar_recv/recv.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/exe/cimbar_recv/recv.cpp b/src/exe/cimbar_recv/recv.cpp index 7b2f909f..7fa3652e 100644 --- a/src/exe/cimbar_recv/recv.cpp +++ b/src/exe/cimbar_recv/recv.cpp @@ -78,10 +78,11 @@ int main(int argc, char** argv) } vc.set(cv::CAP_PROP_FRAME_WIDTH, 1920); vc.set(cv::CAP_PROP_FRAME_HEIGHT, 1200); + vc.set(cv::CAP_PROP_FPS, 60); // set max camera res, and use aspect ratio for window size... - std::cout << fmt::format("width: {}, height {}", vc.get(cv::CAP_PROP_FRAME_WIDTH), vc.get(cv::CAP_PROP_FRAME_HEIGHT)) << std::endl; + std::cout << fmt::format("width: {}, height {}, exposure {}", vc.get(cv::CAP_PROP_FRAME_WIDTH), vc.get(cv::CAP_PROP_FRAME_HEIGHT), vc.get(cv::CAP_PROP_EXPOSURE)) << std::endl; double ratio = vc.get(cv::CAP_PROP_FRAME_WIDTH) / vc.get(cv::CAP_PROP_FRAME_HEIGHT); int height = 600; From 7f19118a3d0710e885a4af389c69f37bb658aecc Mon Sep 17 00:00:00 2001 From: sz Date: Fri, 25 Mar 2022 19:27:53 -0500 Subject: [PATCH 09/10] Clean up headers a bit --- src/exe/cimbar_recv/recv.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/exe/cimbar_recv/recv.cpp b/src/exe/cimbar_recv/recv.cpp index 7fa3652e..82a3a773 100644 --- a/src/exe/cimbar_recv/recv.cpp +++ b/src/exe/cimbar_recv/recv.cpp @@ -8,7 +8,6 @@ #include "cxxopts/cxxopts.hpp" #include "serialize/str.h" -#include "util/File.h" #include #include @@ -17,9 +16,7 @@ #include #include #include -#include using std::string; -using std::vector; namespace { From 395d9eaeb8f1a75635bb83558286bcb192ebe9db Mon Sep 17 00:00:00 2001 From: sz Date: Fri, 25 Mar 2022 19:48:14 -0500 Subject: [PATCH 10/10] Wire up FPS --- src/exe/cimbar_recv/recv.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/exe/cimbar_recv/recv.cpp b/src/exe/cimbar_recv/recv.cpp index 82a3a773..5deeb3f5 100644 --- a/src/exe/cimbar_recv/recv.cpp +++ b/src/exe/cimbar_recv/recv.cpp @@ -37,13 +37,13 @@ int main(int argc, char** argv) unsigned colorBits = cimbar::Config::color_bits(); unsigned ecc = cimbar::Config::ecc_bytes(); - unsigned defaultFps = 15; + unsigned defaultFps = 60; options.add_options() ("i,in", "Video source.", cxxopts::value()) ("o,out", "Output directory (decoding).", cxxopts::value()) ("c,colorbits", "Color bits. [0-3]", cxxopts::value()->default_value(turbo::str::str(colorBits))) ("e,ecc", "ECC level", cxxopts::value()->default_value(turbo::str::str(ecc))) - ("f,fps", "Target FPS", cxxopts::value()->default_value(turbo::str::str(defaultFps))) + ("f,fps", "Target decode FPS", cxxopts::value()->default_value(turbo::str::str(defaultFps))) ("h,help", "Print usage") ; options.show_positional_help(); @@ -75,7 +75,7 @@ int main(int argc, char** argv) } vc.set(cv::CAP_PROP_FRAME_WIDTH, 1920); vc.set(cv::CAP_PROP_FRAME_HEIGHT, 1200); - vc.set(cv::CAP_PROP_FPS, 60); + vc.set(cv::CAP_PROP_FPS, fps); // set max camera res, and use aspect ratio for window size...